@kody/morning-briefing
Composable daily briefing from calendar, weather, and optional inbox or home signals.
AGENTS.md
100 lines · 3.2 KB · Markdown@kody/morning-briefing — agent notes
Human setup and intent live in README.md. This file is for
agents: imports, smoke/dryRun execute snippets, and edge cases. Never paste
OAuth client secrets. Do not disable or enable live jobs unless the operator
explicitly asks — the bundled daily-morning-briefing job stays
enabled: false until they save config and approve a dry-run.
Auth
| Source | Credential |
|---|---|
| calendar | Google OAuth via @kody/google (account, default personal) |
| weather / health | none (Open-Meteo public APIs) |
| inbox | Google OAuth with gmail.readonly (BYO client) |
| home | caller-supplied home.items only |
| email / notify output | kody.emailSend to signed-in account (no API-key secret) |
Hosts: www.googleapis.com, gmail.googleapis.com (inbox), Open-Meteo geocoding /
forecast / air-quality hosts. No /account/secrets/new for this package.
Import paths
| Export | Import |
|---|---|
| root (build + optional deliver) | kody:@kody/morning-briefing |
| run-morning-briefing | kody:@kody/morning-briefing/run-morning-briefing |
| build-report | kody:@kody/morning-briefing/build-report |
| get-report | kody:@kody/morning-briefing/get-report |
Prefer static kody:@kody/morning-briefing/... imports from execute. Do not
lead with packages.invoke.
Smoke test (read-only / no send)
Weather-only (no OAuth):
import buildReport from 'kody:@kody/morning-briefing/build-report'
export default async function main() {
const report = await buildReport({
location: 'Austin',
sources: ['weather'],
})
return {
date: report.date,
sections: report.sections.map((s) => ({ id: s.id, status: s.status })),
}
}Delivery dry-run (does not send):
import runMorningBriefing from 'kody:@kody/morning-briefing/run-morning-briefing'
export default async function main() {
return await runMorningBriefing({
dryRun: true,
location: 'Austin',
sources: ['weather'],
output: 'email',
})
}Compose preview with optional sources:
import runMorningBriefing from 'kody:@kody/morning-briefing'
export default async function main() {
return await runMorningBriefing({
dryRun: true,
location: 'Denver, CO',
timezone: 'America/Denver',
sources: ['calendar', 'weather', 'inbox', 'health', 'home'],
output: 'email',
calendar: { accounts: ['personal'] },
inbox: { account: 'personal', query: 'is:unread newer_than:1d' },
home: { items: [{ title: 'Thermostat 70°', detail: 'Heat, occupied' }] },
})
}Edge cases
- Missing Google auth becomes a warning/skipped section; do not abort the whole briefing for one bad source.
@kody/googlelistEventsAcrossCalendarsstops at its wall-clock budget. A truncated scan becomes a calendar warning so a partial day is not reported as complete.- 403 / insufficient-scope must name the missing scope and the connect URL — never fail silently.
- This official listing does not post to Discord and has no Kent-specific Kit/YouTube/GitHub/Tesla/apartment wiring.
- Do not enable
daily-morning-briefingon the official listing; after a fork, enable only when config is saved and a dry-run looks right. output: 'notify'is short callout-only body;emailis the full markdown.