@aitne/daemon 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/adapters/composite-dashboard-stream.d.ts +42 -0
- package/dist/adapters/composite-dashboard-stream.d.ts.map +1 -0
- package/dist/adapters/composite-dashboard-stream.js +49 -0
- package/dist/adapters/composite-dashboard-stream.js.map +1 -0
- package/dist/adapters/dashboard-adapter.d.ts +104 -0
- package/dist/adapters/dashboard-adapter.d.ts.map +1 -0
- package/dist/adapters/dashboard-adapter.js +216 -0
- package/dist/adapters/dashboard-adapter.js.map +1 -0
- package/dist/adapters/discord.d.ts +77 -0
- package/dist/adapters/discord.d.ts.map +1 -0
- package/dist/adapters/discord.js +339 -0
- package/dist/adapters/discord.js.map +1 -0
- package/dist/adapters/docs-qa-adapter.d.ts +123 -0
- package/dist/adapters/docs-qa-adapter.d.ts.map +1 -0
- package/dist/adapters/docs-qa-adapter.js +218 -0
- package/dist/adapters/docs-qa-adapter.js.map +1 -0
- package/dist/adapters/message-hub.d.ts +70 -0
- package/dist/adapters/message-hub.d.ts.map +1 -0
- package/dist/adapters/message-hub.js +359 -0
- package/dist/adapters/message-hub.js.map +1 -0
- package/dist/adapters/notification-manager.d.ts +99 -0
- package/dist/adapters/notification-manager.d.ts.map +1 -0
- package/dist/adapters/notification-manager.js +498 -0
- package/dist/adapters/notification-manager.js.map +1 -0
- package/dist/adapters/outbound-text.d.ts +28 -0
- package/dist/adapters/outbound-text.d.ts.map +1 -0
- package/dist/adapters/outbound-text.js +58 -0
- package/dist/adapters/outbound-text.js.map +1 -0
- package/dist/adapters/slack-adapter.d.ts +82 -0
- package/dist/adapters/slack-adapter.d.ts.map +1 -0
- package/dist/adapters/slack-adapter.js +359 -0
- package/dist/adapters/slack-adapter.js.map +1 -0
- package/dist/adapters/telegram-adapter.d.ts +107 -0
- package/dist/adapters/telegram-adapter.d.ts.map +1 -0
- package/dist/adapters/telegram-adapter.js +477 -0
- package/dist/adapters/telegram-adapter.js.map +1 -0
- package/dist/adapters/types.d.ts +92 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/adapters/whatsapp-adapter.d.ts +213 -0
- package/dist/adapters/whatsapp-adapter.d.ts.map +1 -0
- package/dist/adapters/whatsapp-adapter.js +1216 -0
- package/dist/adapters/whatsapp-adapter.js.map +1 -0
- package/dist/api/chat-binding-query.d.ts +36 -0
- package/dist/api/chat-binding-query.d.ts.map +1 -0
- package/dist/api/chat-binding-query.js +63 -0
- package/dist/api/chat-binding-query.js.map +1 -0
- package/dist/api/chat-session-resume.d.ts +12 -0
- package/dist/api/chat-session-resume.d.ts.map +1 -0
- package/dist/api/chat-session-resume.js +21 -0
- package/dist/api/chat-session-resume.js.map +1 -0
- package/dist/api/delegated-proxy-helper.d.ts +33 -0
- package/dist/api/delegated-proxy-helper.d.ts.map +1 -0
- package/dist/api/delegated-proxy-helper.js +54 -0
- package/dist/api/delegated-proxy-helper.js.map +1 -0
- package/dist/api/directory-picker.d.ts +38 -0
- package/dist/api/directory-picker.d.ts.map +1 -0
- package/dist/api/directory-picker.js +278 -0
- package/dist/api/directory-picker.js.map +1 -0
- package/dist/api/env-writer.d.ts +25 -0
- package/dist/api/env-writer.d.ts.map +1 -0
- package/dist/api/env-writer.js +421 -0
- package/dist/api/env-writer.js.map +1 -0
- package/dist/api/integration-route-gate.d.ts +60 -0
- package/dist/api/integration-route-gate.d.ts.map +1 -0
- package/dist/api/integration-route-gate.js +83 -0
- package/dist/api/integration-route-gate.js.map +1 -0
- package/dist/api/json-body.d.ts +29 -0
- package/dist/api/json-body.d.ts.map +1 -0
- package/dist/api/json-body.js +87 -0
- package/dist/api/json-body.js.map +1 -0
- package/dist/api/routes/activity-sources.d.ts +20 -0
- package/dist/api/routes/activity-sources.d.ts.map +1 -0
- package/dist/api/routes/activity-sources.js +18 -0
- package/dist/api/routes/activity-sources.js.map +1 -0
- package/dist/api/routes/agent.d.ts +4 -0
- package/dist/api/routes/agent.d.ts.map +1 -0
- package/dist/api/routes/agent.js +619 -0
- package/dist/api/routes/agent.js.map +1 -0
- package/dist/api/routes/apple-calendar.d.ts +31 -0
- package/dist/api/routes/apple-calendar.d.ts.map +1 -0
- package/dist/api/routes/apple-calendar.js +310 -0
- package/dist/api/routes/apple-calendar.js.map +1 -0
- package/dist/api/routes/attachments.d.ts +36 -0
- package/dist/api/routes/attachments.d.ts.map +1 -0
- package/dist/api/routes/attachments.js +305 -0
- package/dist/api/routes/attachments.js.map +1 -0
- package/dist/api/routes/backends.d.ts +4 -0
- package/dist/api/routes/backends.d.ts.map +1 -0
- package/dist/api/routes/backends.js +1132 -0
- package/dist/api/routes/backends.js.map +1 -0
- package/dist/api/routes/books.d.ts +63 -0
- package/dist/api/routes/books.d.ts.map +1 -0
- package/dist/api/routes/books.js +467 -0
- package/dist/api/routes/books.js.map +1 -0
- package/dist/api/routes/calendar.d.ts +36 -0
- package/dist/api/routes/calendar.d.ts.map +1 -0
- package/dist/api/routes/calendar.js +351 -0
- package/dist/api/routes/calendar.js.map +1 -0
- package/dist/api/routes/commands.d.ts +4 -0
- package/dist/api/routes/commands.d.ts.map +1 -0
- package/dist/api/routes/commands.js +251 -0
- package/dist/api/routes/commands.js.map +1 -0
- package/dist/api/routes/context.d.ts +57 -0
- package/dist/api/routes/context.d.ts.map +1 -0
- package/dist/api/routes/context.js +1765 -0
- package/dist/api/routes/context.js.map +1 -0
- package/dist/api/routes/dashboard.d.ts +29 -0
- package/dist/api/routes/dashboard.d.ts.map +1 -0
- package/dist/api/routes/dashboard.js +2062 -0
- package/dist/api/routes/dashboard.js.map +1 -0
- package/dist/api/routes/delegated-sync.d.ts +4 -0
- package/dist/api/routes/delegated-sync.d.ts.map +1 -0
- package/dist/api/routes/delegated-sync.js +192 -0
- package/dist/api/routes/delegated-sync.js.map +1 -0
- package/dist/api/routes/delegated.d.ts +42 -0
- package/dist/api/routes/delegated.d.ts.map +1 -0
- package/dist/api/routes/delegated.js +250 -0
- package/dist/api/routes/delegated.js.map +1 -0
- package/dist/api/routes/docs.d.ts +34 -0
- package/dist/api/routes/docs.d.ts.map +1 -0
- package/dist/api/routes/docs.js +580 -0
- package/dist/api/routes/docs.js.map +1 -0
- package/dist/api/routes/entities.d.ts +9 -0
- package/dist/api/routes/entities.d.ts.map +1 -0
- package/dist/api/routes/entities.js +176 -0
- package/dist/api/routes/entities.js.map +1 -0
- package/dist/api/routes/git-accounts.d.ts +23 -0
- package/dist/api/routes/git-accounts.d.ts.map +1 -0
- package/dist/api/routes/git-accounts.js +227 -0
- package/dist/api/routes/git-accounts.js.map +1 -0
- package/dist/api/routes/git-templates.d.ts +50 -0
- package/dist/api/routes/git-templates.d.ts.map +1 -0
- package/dist/api/routes/git-templates.js +276 -0
- package/dist/api/routes/git-templates.js.map +1 -0
- package/dist/api/routes/git.d.ts +34 -0
- package/dist/api/routes/git.d.ts.map +1 -0
- package/dist/api/routes/git.js +126 -0
- package/dist/api/routes/git.js.map +1 -0
- package/dist/api/routes/github.d.ts +34 -0
- package/dist/api/routes/github.d.ts.map +1 -0
- package/dist/api/routes/github.js +465 -0
- package/dist/api/routes/github.js.map +1 -0
- package/dist/api/routes/health.d.ts +4 -0
- package/dist/api/routes/health.d.ts.map +1 -0
- package/dist/api/routes/health.js +257 -0
- package/dist/api/routes/health.js.map +1 -0
- package/dist/api/routes/integrations-reconcile.d.ts +33 -0
- package/dist/api/routes/integrations-reconcile.d.ts.map +1 -0
- package/dist/api/routes/integrations-reconcile.js +463 -0
- package/dist/api/routes/integrations-reconcile.js.map +1 -0
- package/dist/api/routes/integrations.d.ts +19 -0
- package/dist/api/routes/integrations.d.ts.map +1 -0
- package/dist/api/routes/integrations.js +1384 -0
- package/dist/api/routes/integrations.js.map +1 -0
- package/dist/api/routes/knowledge.d.ts +4 -0
- package/dist/api/routes/knowledge.d.ts.map +1 -0
- package/dist/api/routes/knowledge.js +224 -0
- package/dist/api/routes/knowledge.js.map +1 -0
- package/dist/api/routes/mail.d.ts +39 -0
- package/dist/api/routes/mail.d.ts.map +1 -0
- package/dist/api/routes/mail.js +1406 -0
- package/dist/api/routes/mail.js.map +1 -0
- package/dist/api/routes/managed-tasks.d.ts +48 -0
- package/dist/api/routes/managed-tasks.d.ts.map +1 -0
- package/dist/api/routes/managed-tasks.js +844 -0
- package/dist/api/routes/managed-tasks.js.map +1 -0
- package/dist/api/routes/mcp.d.ts +50 -0
- package/dist/api/routes/mcp.d.ts.map +1 -0
- package/dist/api/routes/mcp.js +470 -0
- package/dist/api/routes/mcp.js.map +1 -0
- package/dist/api/routes/metrics.d.ts +13 -0
- package/dist/api/routes/metrics.d.ts.map +1 -0
- package/dist/api/routes/metrics.js +117 -0
- package/dist/api/routes/metrics.js.map +1 -0
- package/dist/api/routes/notion.d.ts +35 -0
- package/dist/api/routes/notion.d.ts.map +1 -0
- package/dist/api/routes/notion.js +442 -0
- package/dist/api/routes/notion.js.map +1 -0
- package/dist/api/routes/observations.d.ts +4 -0
- package/dist/api/routes/observations.d.ts.map +1 -0
- package/dist/api/routes/observations.js +177 -0
- package/dist/api/routes/observations.js.map +1 -0
- package/dist/api/routes/obsidian.d.ts +16 -0
- package/dist/api/routes/obsidian.d.ts.map +1 -0
- package/dist/api/routes/obsidian.js +321 -0
- package/dist/api/routes/obsidian.js.map +1 -0
- package/dist/api/routes/profile-questions.d.ts +17 -0
- package/dist/api/routes/profile-questions.d.ts.map +1 -0
- package/dist/api/routes/profile-questions.js +115 -0
- package/dist/api/routes/profile-questions.js.map +1 -0
- package/dist/api/routes/receipts.d.ts +4 -0
- package/dist/api/routes/receipts.d.ts.map +1 -0
- package/dist/api/routes/receipts.js +155 -0
- package/dist/api/routes/receipts.js.map +1 -0
- package/dist/api/routes/recurring-schedules.d.ts +4 -0
- package/dist/api/routes/recurring-schedules.d.ts.map +1 -0
- package/dist/api/routes/recurring-schedules.js +137 -0
- package/dist/api/routes/recurring-schedules.js.map +1 -0
- package/dist/api/routes/repositories.d.ts +40 -0
- package/dist/api/routes/repositories.d.ts.map +1 -0
- package/dist/api/routes/repositories.js +857 -0
- package/dist/api/routes/repositories.js.map +1 -0
- package/dist/api/routes/setup-migrate.d.ts +74 -0
- package/dist/api/routes/setup-migrate.d.ts.map +1 -0
- package/dist/api/routes/setup-migrate.js +944 -0
- package/dist/api/routes/setup-migrate.js.map +1 -0
- package/dist/api/routes/setup.d.ts +4 -0
- package/dist/api/routes/setup.d.ts.map +1 -0
- package/dist/api/routes/setup.js +443 -0
- package/dist/api/routes/setup.js.map +1 -0
- package/dist/api/routes/skill-curation.d.ts +5 -0
- package/dist/api/routes/skill-curation.d.ts.map +1 -0
- package/dist/api/routes/skill-curation.js +728 -0
- package/dist/api/routes/skill-curation.js.map +1 -0
- package/dist/api/routes/skills.d.ts +52 -0
- package/dist/api/routes/skills.d.ts.map +1 -0
- package/dist/api/routes/skills.js +429 -0
- package/dist/api/routes/skills.js.map +1 -0
- package/dist/api/routes/sot-bindings.d.ts +20 -0
- package/dist/api/routes/sot-bindings.d.ts.map +1 -0
- package/dist/api/routes/sot-bindings.js +163 -0
- package/dist/api/routes/sot-bindings.js.map +1 -0
- package/dist/api/routes/sse.d.ts +86 -0
- package/dist/api/routes/sse.d.ts.map +1 -0
- package/dist/api/routes/sse.js +378 -0
- package/dist/api/routes/sse.js.map +1 -0
- package/dist/api/routes/system.d.ts +4 -0
- package/dist/api/routes/system.d.ts.map +1 -0
- package/dist/api/routes/system.js +207 -0
- package/dist/api/routes/system.js.map +1 -0
- package/dist/api/routes/task-flows.d.ts +30 -0
- package/dist/api/routes/task-flows.d.ts.map +1 -0
- package/dist/api/routes/task-flows.js +155 -0
- package/dist/api/routes/task-flows.js.map +1 -0
- package/dist/api/routes/travel-bookings.d.ts +4 -0
- package/dist/api/routes/travel-bookings.d.ts.map +1 -0
- package/dist/api/routes/travel-bookings.js +142 -0
- package/dist/api/routes/travel-bookings.js.map +1 -0
- package/dist/api/routes/travel-time.d.ts +8 -0
- package/dist/api/routes/travel-time.d.ts.map +1 -0
- package/dist/api/routes/travel-time.js +87 -0
- package/dist/api/routes/travel-time.js.map +1 -0
- package/dist/api/routes/triggers.d.ts +4 -0
- package/dist/api/routes/triggers.d.ts.map +1 -0
- package/dist/api/routes/triggers.js +101 -0
- package/dist/api/routes/triggers.js.map +1 -0
- package/dist/api/routes/voice.d.ts +48 -0
- package/dist/api/routes/voice.d.ts.map +1 -0
- package/dist/api/routes/voice.js +232 -0
- package/dist/api/routes/voice.js.map +1 -0
- package/dist/api/server.d.ts +428 -0
- package/dist/api/server.d.ts.map +1 -0
- package/dist/api/server.js +558 -0
- package/dist/api/server.js.map +1 -0
- package/dist/config.d.ts +136 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +699 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-core.d.ts +517 -0
- package/dist/core/agent-core.d.ts.map +1 -0
- package/dist/core/agent-core.js +102 -0
- package/dist/core/agent-core.js.map +1 -0
- package/dist/core/alerts.d.ts +86 -0
- package/dist/core/alerts.d.ts.map +1 -0
- package/dist/core/alerts.js +304 -0
- package/dist/core/alerts.js.map +1 -0
- package/dist/core/atomic-write.d.ts +51 -0
- package/dist/core/atomic-write.d.ts.map +1 -0
- package/dist/core/atomic-write.js +135 -0
- package/dist/core/atomic-write.js.map +1 -0
- package/dist/core/backends/api-key-probe.d.ts +40 -0
- package/dist/core/backends/api-key-probe.d.ts.map +1 -0
- package/dist/core/backends/api-key-probe.js +116 -0
- package/dist/core/backends/api-key-probe.js.map +1 -0
- package/dist/core/backends/auth-health-monitor.d.ts +373 -0
- package/dist/core/backends/auth-health-monitor.d.ts.map +1 -0
- package/dist/core/backends/auth-health-monitor.js +950 -0
- package/dist/core/backends/auth-health-monitor.js.map +1 -0
- package/dist/core/backends/auth-recovery.d.ts +263 -0
- package/dist/core/backends/auth-recovery.d.ts.map +1 -0
- package/dist/core/backends/auth-recovery.js +1086 -0
- package/dist/core/backends/auth-recovery.js.map +1 -0
- package/dist/core/backends/auth-telemetry.d.ts +81 -0
- package/dist/core/backends/auth-telemetry.d.ts.map +1 -0
- package/dist/core/backends/auth-telemetry.js +108 -0
- package/dist/core/backends/auth-telemetry.js.map +1 -0
- package/dist/core/backends/backend-router.d.ts +272 -0
- package/dist/core/backends/backend-router.d.ts.map +1 -0
- package/dist/core/backends/backend-router.js +759 -0
- package/dist/core/backends/backend-router.js.map +1 -0
- package/dist/core/backends/claude-code-core.d.ts +299 -0
- package/dist/core/backends/claude-code-core.d.ts.map +1 -0
- package/dist/core/backends/claude-code-core.js +2541 -0
- package/dist/core/backends/claude-code-core.js.map +1 -0
- package/dist/core/backends/claude-credentials-store.d.ts +83 -0
- package/dist/core/backends/claude-credentials-store.d.ts.map +1 -0
- package/dist/core/backends/claude-credentials-store.js +243 -0
- package/dist/core/backends/claude-credentials-store.js.map +1 -0
- package/dist/core/backends/cli-utils.d.ts +95 -0
- package/dist/core/backends/cli-utils.d.ts.map +1 -0
- package/dist/core/backends/cli-utils.js +464 -0
- package/dist/core/backends/cli-utils.js.map +1 -0
- package/dist/core/backends/codex-core.d.ts +127 -0
- package/dist/core/backends/codex-core.d.ts.map +1 -0
- package/dist/core/backends/codex-core.js +1693 -0
- package/dist/core/backends/codex-core.js.map +1 -0
- package/dist/core/backends/gemini-cli-core.d.ts +367 -0
- package/dist/core/backends/gemini-cli-core.d.ts.map +1 -0
- package/dist/core/backends/gemini-cli-core.js +2331 -0
- package/dist/core/backends/gemini-cli-core.js.map +1 -0
- package/dist/core/backends/idle-watchdog.d.ts +77 -0
- package/dist/core/backends/idle-watchdog.d.ts.map +1 -0
- package/dist/core/backends/idle-watchdog.js +94 -0
- package/dist/core/backends/idle-watchdog.js.map +1 -0
- package/dist/core/backends/install-methods.d.ts +93 -0
- package/dist/core/backends/install-methods.d.ts.map +1 -0
- package/dist/core/backends/install-methods.js +267 -0
- package/dist/core/backends/install-methods.js.map +1 -0
- package/dist/core/backends/model-registry.d.ts +58 -0
- package/dist/core/backends/model-registry.d.ts.map +1 -0
- package/dist/core/backends/model-registry.js +539 -0
- package/dist/core/backends/model-registry.js.map +1 -0
- package/dist/core/backends/plan-presets.d.ts +123 -0
- package/dist/core/backends/plan-presets.d.ts.map +1 -0
- package/dist/core/backends/plan-presets.js +235 -0
- package/dist/core/backends/plan-presets.js.map +1 -0
- package/dist/core/backends/price-fetcher.d.ts +48 -0
- package/dist/core/backends/price-fetcher.d.ts.map +1 -0
- package/dist/core/backends/price-fetcher.js +248 -0
- package/dist/core/backends/price-fetcher.js.map +1 -0
- package/dist/core/backends/process-config-cascade.d.ts +68 -0
- package/dist/core/backends/process-config-cascade.d.ts.map +1 -0
- package/dist/core/backends/process-config-cascade.js +173 -0
- package/dist/core/backends/process-config-cascade.js.map +1 -0
- package/dist/core/backends/prompt-utils.d.ts +6 -0
- package/dist/core/backends/prompt-utils.d.ts.map +1 -0
- package/dist/core/backends/prompt-utils.js +80 -0
- package/dist/core/backends/prompt-utils.js.map +1 -0
- package/dist/core/backends/proxy-model-registry.d.ts +110 -0
- package/dist/core/backends/proxy-model-registry.d.ts.map +1 -0
- package/dist/core/backends/proxy-model-registry.js +195 -0
- package/dist/core/backends/proxy-model-registry.js.map +1 -0
- package/dist/core/backends/silent-api-error-detector.d.ts +31 -0
- package/dist/core/backends/silent-api-error-detector.d.ts.map +1 -0
- package/dist/core/backends/silent-api-error-detector.js +44 -0
- package/dist/core/backends/silent-api-error-detector.js.map +1 -0
- package/dist/core/bang-commands/commands-cost.d.ts +13 -0
- package/dist/core/bang-commands/commands-cost.d.ts.map +1 -0
- package/dist/core/bang-commands/commands-cost.js +91 -0
- package/dist/core/bang-commands/commands-cost.js.map +1 -0
- package/dist/core/bang-commands/commands-report.d.ts +18 -0
- package/dist/core/bang-commands/commands-report.d.ts.map +1 -0
- package/dist/core/bang-commands/commands-report.js +105 -0
- package/dist/core/bang-commands/commands-report.js.map +1 -0
- package/dist/core/bang-commands/commands-stop-start.d.ts +4 -0
- package/dist/core/bang-commands/commands-stop-start.d.ts.map +1 -0
- package/dist/core/bang-commands/commands-stop-start.js +88 -0
- package/dist/core/bang-commands/commands-stop-start.js.map +1 -0
- package/dist/core/bang-commands/format-utils.d.ts +34 -0
- package/dist/core/bang-commands/format-utils.d.ts.map +1 -0
- package/dist/core/bang-commands/format-utils.js +118 -0
- package/dist/core/bang-commands/format-utils.js.map +1 -0
- package/dist/core/bang-commands/index.d.ts +20 -0
- package/dist/core/bang-commands/index.d.ts.map +1 -0
- package/dist/core/bang-commands/index.js +31 -0
- package/dist/core/bang-commands/index.js.map +1 -0
- package/dist/core/bang-commands/registry.d.ts +72 -0
- package/dist/core/bang-commands/registry.d.ts.map +1 -0
- package/dist/core/bang-commands/registry.js +174 -0
- package/dist/core/bang-commands/registry.js.map +1 -0
- package/dist/core/bang-commands/user-commands.d.ts +86 -0
- package/dist/core/bang-commands/user-commands.d.ts.map +1 -0
- package/dist/core/bang-commands/user-commands.js +212 -0
- package/dist/core/bang-commands/user-commands.js.map +1 -0
- package/dist/core/channel-timeline.d.ts +28 -0
- package/dist/core/channel-timeline.d.ts.map +1 -0
- package/dist/core/channel-timeline.js +117 -0
- package/dist/core/channel-timeline.js.map +1 -0
- package/dist/core/character-block.d.ts +37 -0
- package/dist/core/character-block.d.ts.map +1 -0
- package/dist/core/character-block.js +162 -0
- package/dist/core/character-block.js.map +1 -0
- package/dist/core/context/activity-sources.d.ts +37 -0
- package/dist/core/context/activity-sources.d.ts.map +1 -0
- package/dist/core/context/activity-sources.js +69 -0
- package/dist/core/context/activity-sources.js.map +1 -0
- package/dist/core/context/activity-view-reconciler.d.ts +110 -0
- package/dist/core/context/activity-view-reconciler.d.ts.map +1 -0
- package/dist/core/context/activity-view-reconciler.js +252 -0
- package/dist/core/context/activity-view-reconciler.js.map +1 -0
- package/dist/core/context/activity-view-runner.d.ts +38 -0
- package/dist/core/context/activity-view-runner.d.ts.map +1 -0
- package/dist/core/context/activity-view-runner.js +402 -0
- package/dist/core/context/activity-view-runner.js.map +1 -0
- package/dist/core/context/default-schedules-reconciler.d.ts +85 -0
- package/dist/core/context/default-schedules-reconciler.d.ts.map +1 -0
- package/dist/core/context/default-schedules-reconciler.js +153 -0
- package/dist/core/context/default-schedules-reconciler.js.map +1 -0
- package/dist/core/context/default-schedules-runner.d.ts +40 -0
- package/dist/core/context/default-schedules-runner.d.ts.map +1 -0
- package/dist/core/context/default-schedules-runner.js +233 -0
- package/dist/core/context/default-schedules-runner.js.map +1 -0
- package/dist/core/context/domain-index-reconciler.d.ts +81 -0
- package/dist/core/context/domain-index-reconciler.d.ts.map +1 -0
- package/dist/core/context/domain-index-reconciler.js +199 -0
- package/dist/core/context/domain-index-reconciler.js.map +1 -0
- package/dist/core/context/domain-index-runner.d.ts +35 -0
- package/dist/core/context/domain-index-runner.d.ts.map +1 -0
- package/dist/core/context/domain-index-runner.js +223 -0
- package/dist/core/context/domain-index-runner.js.map +1 -0
- package/dist/core/context/entity-mirror.d.ts +227 -0
- package/dist/core/context/entity-mirror.d.ts.map +1 -0
- package/dist/core/context/entity-mirror.js +629 -0
- package/dist/core/context/entity-mirror.js.map +1 -0
- package/dist/core/context/entity-source-rename.d.ts +61 -0
- package/dist/core/context/entity-source-rename.d.ts.map +1 -0
- package/dist/core/context/entity-source-rename.js +237 -0
- package/dist/core/context/entity-source-rename.js.map +1 -0
- package/dist/core/context/index-reconciler.d.ts +61 -0
- package/dist/core/context/index-reconciler.d.ts.map +1 -0
- package/dist/core/context/index-reconciler.js +329 -0
- package/dist/core/context/index-reconciler.js.map +1 -0
- package/dist/core/context/policy-index-reconciler.d.ts +102 -0
- package/dist/core/context/policy-index-reconciler.d.ts.map +1 -0
- package/dist/core/context/policy-index-reconciler.js +202 -0
- package/dist/core/context/policy-index-reconciler.js.map +1 -0
- package/dist/core/context/policy-index-runner.d.ts +66 -0
- package/dist/core/context/policy-index-runner.d.ts.map +1 -0
- package/dist/core/context/policy-index-runner.js +406 -0
- package/dist/core/context/policy-index-runner.js.map +1 -0
- package/dist/core/context/reconciler-runner.d.ts +44 -0
- package/dist/core/context/reconciler-runner.d.ts.map +1 -0
- package/dist/core/context/reconciler-runner.js +273 -0
- package/dist/core/context/reconciler-runner.js.map +1 -0
- package/dist/core/context-builder.d.ts +115 -0
- package/dist/core/context-builder.d.ts.map +1 -0
- package/dist/core/context-builder.js +1148 -0
- package/dist/core/context-builder.js.map +1 -0
- package/dist/core/context-frontmatter-backfill.d.ts +33 -0
- package/dist/core/context-frontmatter-backfill.d.ts.map +1 -0
- package/dist/core/context-frontmatter-backfill.js +111 -0
- package/dist/core/context-frontmatter-backfill.js.map +1 -0
- package/dist/core/context-frontmatter.d.ts +13 -0
- package/dist/core/context-frontmatter.d.ts.map +1 -0
- package/dist/core/context-frontmatter.js +325 -0
- package/dist/core/context-frontmatter.js.map +1 -0
- package/dist/core/context-health.d.ts +51 -0
- package/dist/core/context-health.d.ts.map +1 -0
- package/dist/core/context-health.js +304 -0
- package/dist/core/context-health.js.map +1 -0
- package/dist/core/context-paths.d.ts +183 -0
- package/dist/core/context-paths.d.ts.map +1 -0
- package/dist/core/context-paths.js +241 -0
- package/dist/core/context-paths.js.map +1 -0
- package/dist/core/context-staleness.d.ts +45 -0
- package/dist/core/context-staleness.d.ts.map +1 -0
- package/dist/core/context-staleness.js +88 -0
- package/dist/core/context-staleness.js.map +1 -0
- package/dist/core/custom-routine-scheduler.d.ts +151 -0
- package/dist/core/custom-routine-scheduler.d.ts.map +1 -0
- package/dist/core/custom-routine-scheduler.js +335 -0
- package/dist/core/custom-routine-scheduler.js.map +1 -0
- package/dist/core/daemon-api-cli.d.ts +33 -0
- package/dist/core/daemon-api-cli.d.ts.map +1 -0
- package/dist/core/daemon-api-cli.js +614 -0
- package/dist/core/daemon-api-cli.js.map +1 -0
- package/dist/core/dashboard-session-cleanup.d.ts +39 -0
- package/dist/core/dashboard-session-cleanup.d.ts.map +1 -0
- package/dist/core/dashboard-session-cleanup.js +108 -0
- package/dist/core/dashboard-session-cleanup.js.map +1 -0
- package/dist/core/dashboard-session-controls.d.ts +41 -0
- package/dist/core/dashboard-session-controls.d.ts.map +1 -0
- package/dist/core/dashboard-session-controls.js +154 -0
- package/dist/core/dashboard-session-controls.js.map +1 -0
- package/dist/core/delegated-connector-health.d.ts +63 -0
- package/dist/core/delegated-connector-health.d.ts.map +1 -0
- package/dist/core/delegated-connector-health.js +157 -0
- package/dist/core/delegated-connector-health.js.map +1 -0
- package/dist/core/dispatcher.d.ts +999 -0
- package/dist/core/dispatcher.d.ts.map +1 -0
- package/dist/core/dispatcher.js +4378 -0
- package/dist/core/dispatcher.js.map +1 -0
- package/dist/core/dm-freshness-metrics.d.ts +73 -0
- package/dist/core/dm-freshness-metrics.d.ts.map +1 -0
- package/dist/core/dm-freshness-metrics.js +138 -0
- package/dist/core/dm-freshness-metrics.js.map +1 -0
- package/dist/core/docs/citation-validator.d.ts +73 -0
- package/dist/core/docs/citation-validator.d.ts.map +1 -0
- package/dist/core/docs/citation-validator.js +195 -0
- package/dist/core/docs/citation-validator.js.map +1 -0
- package/dist/core/docs/extract-terms.d.ts +78 -0
- package/dist/core/docs/extract-terms.d.ts.map +1 -0
- package/dist/core/docs/extract-terms.js +147 -0
- package/dist/core/docs/extract-terms.js.map +1 -0
- package/dist/core/docs/indexer.d.ts +104 -0
- package/dist/core/docs/indexer.d.ts.map +1 -0
- package/dist/core/docs/indexer.js +340 -0
- package/dist/core/docs/indexer.js.map +1 -0
- package/dist/core/drift-effects.d.ts +30 -0
- package/dist/core/drift-effects.d.ts.map +1 -0
- package/dist/core/drift-effects.js +384 -0
- package/dist/core/drift-effects.js.map +1 -0
- package/dist/core/event-bus.d.ts +56 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +135 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/git-project-docs.d.ts +77 -0
- package/dist/core/git-project-docs.d.ts.map +1 -0
- package/dist/core/git-project-docs.js +439 -0
- package/dist/core/git-project-docs.js.map +1 -0
- package/dist/core/health-monitor.d.ts +57 -0
- package/dist/core/health-monitor.d.ts.map +1 -0
- package/dist/core/health-monitor.js +137 -0
- package/dist/core/health-monitor.js.map +1 -0
- package/dist/core/heartbeat.d.ts +26 -0
- package/dist/core/heartbeat.d.ts.map +1 -0
- package/dist/core/heartbeat.js +48 -0
- package/dist/core/heartbeat.js.map +1 -0
- package/dist/core/integration-health.d.ts +49 -0
- package/dist/core/integration-health.d.ts.map +1 -0
- package/dist/core/integration-health.js +89 -0
- package/dist/core/integration-health.js.map +1 -0
- package/dist/core/integration-lifecycle.d.ts +79 -0
- package/dist/core/integration-lifecycle.d.ts.map +1 -0
- package/dist/core/integration-lifecycle.js +153 -0
- package/dist/core/integration-lifecycle.js.map +1 -0
- package/dist/core/integration-main-backend.d.ts +36 -0
- package/dist/core/integration-main-backend.d.ts.map +1 -0
- package/dist/core/integration-main-backend.js +59 -0
- package/dist/core/integration-main-backend.js.map +1 -0
- package/dist/core/integration-probe.d.ts +98 -0
- package/dist/core/integration-probe.d.ts.map +1 -0
- package/dist/core/integration-probe.js +152 -0
- package/dist/core/integration-probe.js.map +1 -0
- package/dist/core/management-md-write-lock.d.ts +68 -0
- package/dist/core/management-md-write-lock.d.ts.map +1 -0
- package/dist/core/management-md-write-lock.js +93 -0
- package/dist/core/management-md-write-lock.js.map +1 -0
- package/dist/core/management-md.d.ts +186 -0
- package/dist/core/management-md.d.ts.map +1 -0
- package/dist/core/management-md.js +652 -0
- package/dist/core/management-md.js.map +1 -0
- package/dist/core/management-registry.d.ts +245 -0
- package/dist/core/management-registry.d.ts.map +1 -0
- package/dist/core/management-registry.js +906 -0
- package/dist/core/management-registry.js.map +1 -0
- package/dist/core/management-telemetry.d.ts +100 -0
- package/dist/core/management-telemetry.d.ts.map +1 -0
- package/dist/core/management-telemetry.js +156 -0
- package/dist/core/management-telemetry.js.map +1 -0
- package/dist/core/message-recorder.d.ts +38 -0
- package/dist/core/message-recorder.d.ts.map +1 -0
- package/dist/core/message-recorder.js +88 -0
- package/dist/core/message-recorder.js.map +1 -0
- package/dist/core/metrics.d.ts +338 -0
- package/dist/core/metrics.d.ts.map +1 -0
- package/dist/core/metrics.js +747 -0
- package/dist/core/metrics.js.map +1 -0
- package/dist/core/migration-backup.d.ts +218 -0
- package/dist/core/migration-backup.d.ts.map +1 -0
- package/dist/core/migration-backup.js +934 -0
- package/dist/core/migration-backup.js.map +1 -0
- package/dist/core/overview-write-lock.d.ts +48 -0
- package/dist/core/overview-write-lock.d.ts.map +1 -0
- package/dist/core/overview-write-lock.js +56 -0
- package/dist/core/overview-write-lock.js.map +1 -0
- package/dist/core/path-compat.d.ts +22 -0
- package/dist/core/path-compat.d.ts.map +1 -0
- package/dist/core/path-compat.js +67 -0
- package/dist/core/path-compat.js.map +1 -0
- package/dist/core/path-rewrite.d.ts +58 -0
- package/dist/core/path-rewrite.d.ts.map +1 -0
- package/dist/core/path-rewrite.js +141 -0
- package/dist/core/path-rewrite.js.map +1 -0
- package/dist/core/policy-files.d.ts +108 -0
- package/dist/core/policy-files.d.ts.map +1 -0
- package/dist/core/policy-files.js +198 -0
- package/dist/core/policy-files.js.map +1 -0
- package/dist/core/profile-questions/seed.d.ts +44 -0
- package/dist/core/profile-questions/seed.d.ts.map +1 -0
- package/dist/core/profile-questions/seed.js +173 -0
- package/dist/core/profile-questions/seed.js.map +1 -0
- package/dist/core/profile-questions/slot-filled.d.ts +51 -0
- package/dist/core/profile-questions/slot-filled.d.ts.map +1 -0
- package/dist/core/profile-questions/slot-filled.js +118 -0
- package/dist/core/profile-questions/slot-filled.js.map +1 -0
- package/dist/core/prompts.d.ts +111 -0
- package/dist/core/prompts.d.ts.map +1 -0
- package/dist/core/prompts.js +267 -0
- package/dist/core/prompts.js.map +1 -0
- package/dist/core/quiet-hours-sync.d.ts +15 -0
- package/dist/core/quiet-hours-sync.d.ts.map +1 -0
- package/dist/core/quiet-hours-sync.js +51 -0
- package/dist/core/quiet-hours-sync.js.map +1 -0
- package/dist/core/read-sensitive-token-manager.d.ts +19 -0
- package/dist/core/read-sensitive-token-manager.d.ts.map +1 -0
- package/dist/core/read-sensitive-token-manager.js +29 -0
- package/dist/core/read-sensitive-token-manager.js.map +1 -0
- package/dist/core/recurrence.d.ts +24 -0
- package/dist/core/recurrence.d.ts.map +1 -0
- package/dist/core/recurrence.js +162 -0
- package/dist/core/recurrence.js.map +1 -0
- package/dist/core/reinstall.d.ts +107 -0
- package/dist/core/reinstall.d.ts.map +1 -0
- package/dist/core/reinstall.js +163 -0
- package/dist/core/reinstall.js.map +1 -0
- package/dist/core/release-assets.d.ts +106 -0
- package/dist/core/release-assets.d.ts.map +1 -0
- package/dist/core/release-assets.js +434 -0
- package/dist/core/release-assets.js.map +1 -0
- package/dist/core/repository-management-docs.d.ts +216 -0
- package/dist/core/repository-management-docs.d.ts.map +1 -0
- package/dist/core/repository-management-docs.js +855 -0
- package/dist/core/repository-management-docs.js.map +1 -0
- package/dist/core/retention.d.ts +164 -0
- package/dist/core/retention.d.ts.map +1 -0
- package/dist/core/retention.js +1008 -0
- package/dist/core/retention.js.map +1 -0
- package/dist/core/review-context.d.ts +48 -0
- package/dist/core/review-context.d.ts.map +1 -0
- package/dist/core/review-context.js +282 -0
- package/dist/core/review-context.js.map +1 -0
- package/dist/core/roadmap-horizon.d.ts +48 -0
- package/dist/core/roadmap-horizon.d.ts.map +1 -0
- package/dist/core/roadmap-horizon.js +213 -0
- package/dist/core/roadmap-horizon.js.map +1 -0
- package/dist/core/roadmap-ids.d.ts +57 -0
- package/dist/core/roadmap-ids.d.ts.map +1 -0
- package/dist/core/roadmap-ids.js +118 -0
- package/dist/core/roadmap-ids.js.map +1 -0
- package/dist/core/roadmap-merge.d.ts +7 -0
- package/dist/core/roadmap-merge.d.ts.map +1 -0
- package/dist/core/roadmap-merge.js +187 -0
- package/dist/core/roadmap-merge.js.map +1 -0
- package/dist/core/roadmap-refresh-triggers.d.ts +32 -0
- package/dist/core/roadmap-refresh-triggers.d.ts.map +1 -0
- package/dist/core/roadmap-refresh-triggers.js +51 -0
- package/dist/core/roadmap-refresh-triggers.js.map +1 -0
- package/dist/core/roadmap-truncate.d.ts +49 -0
- package/dist/core/roadmap-truncate.d.ts.map +1 -0
- package/dist/core/roadmap-truncate.js +152 -0
- package/dist/core/roadmap-truncate.js.map +1 -0
- package/dist/core/roadmap-validate.d.ts +31 -0
- package/dist/core/roadmap-validate.d.ts.map +1 -0
- package/dist/core/roadmap-validate.js +403 -0
- package/dist/core/roadmap-validate.js.map +1 -0
- package/dist/core/roadmap-write-lock.d.ts +53 -0
- package/dist/core/roadmap-write-lock.d.ts.map +1 -0
- package/dist/core/roadmap-write-lock.js +59 -0
- package/dist/core/roadmap-write-lock.js.map +1 -0
- package/dist/core/schedule-insert-helper.d.ts +46 -0
- package/dist/core/schedule-insert-helper.d.ts.map +1 -0
- package/dist/core/schedule-insert-helper.js +52 -0
- package/dist/core/schedule-insert-helper.js.map +1 -0
- package/dist/core/schedule-maintenance.d.ts +22 -0
- package/dist/core/schedule-maintenance.d.ts.map +1 -0
- package/dist/core/schedule-maintenance.js +57 -0
- package/dist/core/schedule-maintenance.js.map +1 -0
- package/dist/core/scheduler.d.ts +208 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +896 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/semaphore.d.ts +13 -0
- package/dist/core/semaphore.d.ts.map +1 -0
- package/dist/core/semaphore.js +31 -0
- package/dist/core/semaphore.js.map +1 -0
- package/dist/core/session-gate.d.ts +37 -0
- package/dist/core/session-gate.d.ts.map +1 -0
- package/dist/core/session-gate.js +69 -0
- package/dist/core/session-gate.js.map +1 -0
- package/dist/core/session-manager.d.ts +252 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +716 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/core/signal-detector.d.ts +97 -0
- package/dist/core/signal-detector.d.ts.map +1 -0
- package/dist/core/signal-detector.js +215 -0
- package/dist/core/signal-detector.js.map +1 -0
- package/dist/core/skeleton.d.ts +83 -0
- package/dist/core/skeleton.d.ts.map +1 -0
- package/dist/core/skeleton.js +255 -0
- package/dist/core/skeleton.js.map +1 -0
- package/dist/core/skill-curation/apply-proposal.d.ts +71 -0
- package/dist/core/skill-curation/apply-proposal.d.ts.map +1 -0
- package/dist/core/skill-curation/apply-proposal.js +175 -0
- package/dist/core/skill-curation/apply-proposal.js.map +1 -0
- package/dist/core/skill-curation/auto-revert.d.ts +43 -0
- package/dist/core/skill-curation/auto-revert.d.ts.map +1 -0
- package/dist/core/skill-curation/auto-revert.js +155 -0
- package/dist/core/skill-curation/auto-revert.js.map +1 -0
- package/dist/core/skill-curation/classify-diff.d.ts +27 -0
- package/dist/core/skill-curation/classify-diff.d.ts.map +1 -0
- package/dist/core/skill-curation/classify-diff.js +0 -0
- package/dist/core/skill-curation/classify-diff.js.map +1 -0
- package/dist/core/skill-curation/declarations.d.ts +32 -0
- package/dist/core/skill-curation/declarations.d.ts.map +1 -0
- package/dist/core/skill-curation/declarations.js +171 -0
- package/dist/core/skill-curation/declarations.js.map +1 -0
- package/dist/core/skill-curation/knowledge-map.d.ts +26 -0
- package/dist/core/skill-curation/knowledge-map.d.ts.map +1 -0
- package/dist/core/skill-curation/knowledge-map.js +154 -0
- package/dist/core/skill-curation/knowledge-map.js.map +1 -0
- package/dist/core/skill-curation/orphan-overlay.d.ts +35 -0
- package/dist/core/skill-curation/orphan-overlay.d.ts.map +1 -0
- package/dist/core/skill-curation/orphan-overlay.js +167 -0
- package/dist/core/skill-curation/orphan-overlay.js.map +1 -0
- package/dist/core/skill-curation/overlay-store.d.ts +41 -0
- package/dist/core/skill-curation/overlay-store.d.ts.map +1 -0
- package/dist/core/skill-curation/overlay-store.js +143 -0
- package/dist/core/skill-curation/overlay-store.js.map +1 -0
- package/dist/core/skill-curation/render/convention-notes.d.ts +4 -0
- package/dist/core/skill-curation/render/convention-notes.d.ts.map +1 -0
- package/dist/core/skill-curation/render/convention-notes.js +13 -0
- package/dist/core/skill-curation/render/convention-notes.js.map +1 -0
- package/dist/core/skill-curation/render/cross-references.d.ts +4 -0
- package/dist/core/skill-curation/render/cross-references.d.ts.map +1 -0
- package/dist/core/skill-curation/render/cross-references.js +10 -0
- package/dist/core/skill-curation/render/cross-references.js.map +1 -0
- package/dist/core/skill-curation/render/frontmatter-schema.d.ts +4 -0
- package/dist/core/skill-curation/render/frontmatter-schema.d.ts.map +1 -0
- package/dist/core/skill-curation/render/frontmatter-schema.js +25 -0
- package/dist/core/skill-curation/render/frontmatter-schema.js.map +1 -0
- package/dist/core/skill-curation/render/index.d.ts +5 -0
- package/dist/core/skill-curation/render/index.d.ts.map +1 -0
- package/dist/core/skill-curation/render/index.js +42 -0
- package/dist/core/skill-curation/render/index.js.map +1 -0
- package/dist/core/skill-curation/render/knowledge-layout.d.ts +4 -0
- package/dist/core/skill-curation/render/knowledge-layout.d.ts.map +1 -0
- package/dist/core/skill-curation/render/knowledge-layout.js +36 -0
- package/dist/core/skill-curation/render/knowledge-layout.js.map +1 -0
- package/dist/core/skill-curation/render/routing-table.d.ts +4 -0
- package/dist/core/skill-curation/render/routing-table.d.ts.map +1 -0
- package/dist/core/skill-curation/render/routing-table.js +37 -0
- package/dist/core/skill-curation/render/routing-table.js.map +1 -0
- package/dist/core/skill-curation/render/search-recipes.d.ts +4 -0
- package/dist/core/skill-curation/render/search-recipes.d.ts.map +1 -0
- package/dist/core/skill-curation/render/search-recipes.js +39 -0
- package/dist/core/skill-curation/render/search-recipes.js.map +1 -0
- package/dist/core/skill-curation/run-token.d.ts +27 -0
- package/dist/core/skill-curation/run-token.d.ts.map +1 -0
- package/dist/core/skill-curation/run-token.js +81 -0
- package/dist/core/skill-curation/run-token.js.map +1 -0
- package/dist/core/skill-curation/signals.d.ts +49 -0
- package/dist/core/skill-curation/signals.d.ts.map +1 -0
- package/dist/core/skill-curation/signals.js +149 -0
- package/dist/core/skill-curation/signals.js.map +1 -0
- package/dist/core/skill-curation/smoke-test.d.ts +39 -0
- package/dist/core/skill-curation/smoke-test.d.ts.map +1 -0
- package/dist/core/skill-curation/smoke-test.js +313 -0
- package/dist/core/skill-curation/smoke-test.js.map +1 -0
- package/dist/core/skill-curation/splicer.d.ts +16 -0
- package/dist/core/skill-curation/splicer.d.ts.map +1 -0
- package/dist/core/skill-curation/splicer.js +78 -0
- package/dist/core/skill-curation/splicer.js.map +1 -0
- package/dist/core/skill-curation/workdir.d.ts +40 -0
- package/dist/core/skill-curation/workdir.d.ts.map +1 -0
- package/dist/core/skill-curation/workdir.js +242 -0
- package/dist/core/skill-curation/workdir.js.map +1 -0
- package/dist/core/skills-compiler.d.ts +391 -0
- package/dist/core/skills-compiler.d.ts.map +1 -0
- package/dist/core/skills-compiler.js +1271 -0
- package/dist/core/skills-compiler.js.map +1 -0
- package/dist/core/skills-manifest.d.ts +8 -0
- package/dist/core/skills-manifest.d.ts.map +1 -0
- package/dist/core/skills-manifest.js +408 -0
- package/dist/core/skills-manifest.js.map +1 -0
- package/dist/core/system-reset.d.ts +268 -0
- package/dist/core/system-reset.d.ts.map +1 -0
- package/dist/core/system-reset.js +816 -0
- package/dist/core/system-reset.js.map +1 -0
- package/dist/core/template-store.d.ts +170 -0
- package/dist/core/template-store.d.ts.map +1 -0
- package/dist/core/template-store.js +388 -0
- package/dist/core/template-store.js.map +1 -0
- package/dist/core/template-versions.d.ts +95 -0
- package/dist/core/template-versions.d.ts.map +1 -0
- package/dist/core/template-versions.js +175 -0
- package/dist/core/template-versions.js.map +1 -0
- package/dist/core/today-agent-plan.d.ts +33 -0
- package/dist/core/today-agent-plan.d.ts.map +1 -0
- package/dist/core/today-agent-plan.js +120 -0
- package/dist/core/today-agent-plan.js.map +1 -0
- package/dist/core/today-direct-writer.d.ts +62 -0
- package/dist/core/today-direct-writer.d.ts.map +1 -0
- package/dist/core/today-direct-writer.js +132 -0
- package/dist/core/today-direct-writer.js.map +1 -0
- package/dist/core/today-write-lock.d.ts +89 -0
- package/dist/core/today-write-lock.d.ts.map +1 -0
- package/dist/core/today-write-lock.js +154 -0
- package/dist/core/today-write-lock.js.map +1 -0
- package/dist/core/trigger-dispatch.d.ts +31 -0
- package/dist/core/trigger-dispatch.d.ts.map +1 -0
- package/dist/core/trigger-dispatch.js +100 -0
- package/dist/core/trigger-dispatch.js.map +1 -0
- package/dist/core/trigger-evaluator.d.ts +59 -0
- package/dist/core/trigger-evaluator.d.ts.map +1 -0
- package/dist/core/trigger-evaluator.js +243 -0
- package/dist/core/trigger-evaluator.js.map +1 -0
- package/dist/core/workdir.d.ts +241 -0
- package/dist/core/workdir.d.ts.map +1 -0
- package/dist/core/workdir.js +565 -0
- package/dist/core/workdir.js.map +1 -0
- package/dist/db/automation-triggers.d.ts +90 -0
- package/dist/db/automation-triggers.d.ts.map +1 -0
- package/dist/db/automation-triggers.js +199 -0
- package/dist/db/automation-triggers.js.map +1 -0
- package/dist/db/client.d.ts +6 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +47 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/entities-store.d.ts +92 -0
- package/dist/db/entities-store.d.ts.map +1 -0
- package/dist/db/entities-store.js +180 -0
- package/dist/db/entities-store.js.map +1 -0
- package/dist/db/hourly-check-signals.d.ts +78 -0
- package/dist/db/hourly-check-signals.d.ts.map +1 -0
- package/dist/db/hourly-check-signals.js +289 -0
- package/dist/db/hourly-check-signals.js.map +1 -0
- package/dist/db/integration-probe-store.d.ts +27 -0
- package/dist/db/integration-probe-store.d.ts.map +1 -0
- package/dist/db/integration-probe-store.js +75 -0
- package/dist/db/integration-probe-store.js.map +1 -0
- package/dist/db/integrations-store.d.ts +19 -0
- package/dist/db/integrations-store.d.ts.map +1 -0
- package/dist/db/integrations-store.js +85 -0
- package/dist/db/integrations-store.js.map +1 -0
- package/dist/db/managed-tasks-store.d.ts +130 -0
- package/dist/db/managed-tasks-store.d.ts.map +1 -0
- package/dist/db/managed-tasks-store.js +238 -0
- package/dist/db/managed-tasks-store.js.map +1 -0
- package/dist/db/management-parse-failures-store.d.ts +45 -0
- package/dist/db/management-parse-failures-store.d.ts.map +1 -0
- package/dist/db/management-parse-failures-store.js +36 -0
- package/dist/db/management-parse-failures-store.js.map +1 -0
- package/dist/db/observations.d.ts +145 -0
- package/dist/db/observations.d.ts.map +1 -0
- package/dist/db/observations.js +287 -0
- package/dist/db/observations.js.map +1 -0
- package/dist/db/recurring-schedules.d.ts +70 -0
- package/dist/db/recurring-schedules.d.ts.map +1 -0
- package/dist/db/recurring-schedules.js +213 -0
- package/dist/db/recurring-schedules.js.map +1 -0
- package/dist/db/repositories-store.d.ts +296 -0
- package/dist/db/repositories-store.d.ts.map +1 -0
- package/dist/db/repositories-store.js +754 -0
- package/dist/db/repositories-store.js.map +1 -0
- package/dist/db/runtime-state.d.ts +61 -0
- package/dist/db/runtime-state.d.ts.map +1 -0
- package/dist/db/runtime-state.js +104 -0
- package/dist/db/runtime-state.js.map +1 -0
- package/dist/db/schema.d.ts +4 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +1338 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/sot-bindings-store.d.ts +41 -0
- package/dist/db/sot-bindings-store.d.ts.map +1 -0
- package/dist/db/sot-bindings-store.js +64 -0
- package/dist/db/sot-bindings-store.js.map +1 -0
- package/dist/db/test-schemas.d.ts +23 -0
- package/dist/db/test-schemas.d.ts.map +1 -0
- package/dist/db/test-schemas.js +111 -0
- package/dist/db/test-schemas.js.map +1 -0
- package/dist/db/voice-transcripts-store.d.ts +28 -0
- package/dist/db/voice-transcripts-store.d.ts.map +1 -0
- package/dist/db/voice-transcripts-store.js +43 -0
- package/dist/db/voice-transcripts-store.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2913 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +7 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +32 -0
- package/dist/init.js.map +1 -0
- package/dist/log-buffer.d.ts +71 -0
- package/dist/log-buffer.d.ts.map +1 -0
- package/dist/log-buffer.js +201 -0
- package/dist/log-buffer.js.map +1 -0
- package/dist/logging.d.ts +5 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +130 -0
- package/dist/logging.js.map +1 -0
- package/dist/management-rules.d.ts +2 -0
- package/dist/management-rules.d.ts.map +1 -0
- package/dist/management-rules.js +62 -0
- package/dist/management-rules.js.map +1 -0
- package/dist/messaging/constants.d.ts +33 -0
- package/dist/messaging/constants.d.ts.map +1 -0
- package/dist/messaging/constants.js +52 -0
- package/dist/messaging/constants.js.map +1 -0
- package/dist/messaging/magic-phrase.d.ts +16 -0
- package/dist/messaging/magic-phrase.d.ts.map +1 -0
- package/dist/messaging/magic-phrase.js +103 -0
- package/dist/messaging/magic-phrase.js.map +1 -0
- package/dist/messaging/owner-channels.d.ts +20 -0
- package/dist/messaging/owner-channels.d.ts.map +1 -0
- package/dist/messaging/owner-channels.js +41 -0
- package/dist/messaging/owner-channels.js.map +1 -0
- package/dist/observers/calendar-poller.d.ts +51 -0
- package/dist/observers/calendar-poller.d.ts.map +1 -0
- package/dist/observers/calendar-poller.js +128 -0
- package/dist/observers/calendar-poller.js.map +1 -0
- package/dist/observers/context-index-reconciler-observer.d.ts +72 -0
- package/dist/observers/context-index-reconciler-observer.d.ts.map +1 -0
- package/dist/observers/context-index-reconciler-observer.js +253 -0
- package/dist/observers/context-index-reconciler-observer.js.map +1 -0
- package/dist/observers/delegated-probe-observer.d.ts +83 -0
- package/dist/observers/delegated-probe-observer.d.ts.map +1 -0
- package/dist/observers/delegated-probe-observer.js +237 -0
- package/dist/observers/delegated-probe-observer.js.map +1 -0
- package/dist/observers/delegated-sync-worker.d.ts +375 -0
- package/dist/observers/delegated-sync-worker.d.ts.map +1 -0
- package/dist/observers/delegated-sync-worker.js +1087 -0
- package/dist/observers/delegated-sync-worker.js.map +1 -0
- package/dist/observers/entity-mirror-observer.d.ts +55 -0
- package/dist/observers/entity-mirror-observer.d.ts.map +1 -0
- package/dist/observers/entity-mirror-observer.js +73 -0
- package/dist/observers/entity-mirror-observer.js.map +1 -0
- package/dist/observers/git-delegated-cron.d.ts +41 -0
- package/dist/observers/git-delegated-cron.d.ts.map +1 -0
- package/dist/observers/git-delegated-cron.js +159 -0
- package/dist/observers/git-delegated-cron.js.map +1 -0
- package/dist/observers/git-event-classifier.d.ts +52 -0
- package/dist/observers/git-event-classifier.d.ts.map +1 -0
- package/dist/observers/git-event-classifier.js +70 -0
- package/dist/observers/git-event-classifier.js.map +1 -0
- package/dist/observers/git-watcher.d.ts +162 -0
- package/dist/observers/git-watcher.d.ts.map +1 -0
- package/dist/observers/git-watcher.js +768 -0
- package/dist/observers/git-watcher.js.map +1 -0
- package/dist/observers/github-poller-classifier.d.ts +101 -0
- package/dist/observers/github-poller-classifier.d.ts.map +1 -0
- package/dist/observers/github-poller-classifier.js +199 -0
- package/dist/observers/github-poller-classifier.js.map +1 -0
- package/dist/observers/github-poller.d.ts +291 -0
- package/dist/observers/github-poller.d.ts.map +1 -0
- package/dist/observers/github-poller.js +609 -0
- package/dist/observers/github-poller.js.map +1 -0
- package/dist/observers/imminent-event-scheduler.d.ts +34 -0
- package/dist/observers/imminent-event-scheduler.d.ts.map +1 -0
- package/dist/observers/imminent-event-scheduler.js +125 -0
- package/dist/observers/imminent-event-scheduler.js.map +1 -0
- package/dist/observers/mail-poller.d.ts +133 -0
- package/dist/observers/mail-poller.d.ts.map +1 -0
- package/dist/observers/mail-poller.js +563 -0
- package/dist/observers/mail-poller.js.map +1 -0
- package/dist/observers/mail-reconciliation.d.ts +87 -0
- package/dist/observers/mail-reconciliation.d.ts.map +1 -0
- package/dist/observers/mail-reconciliation.js +241 -0
- package/dist/observers/mail-reconciliation.js.map +1 -0
- package/dist/observers/manager.d.ts +67 -0
- package/dist/observers/manager.d.ts.map +1 -0
- package/dist/observers/manager.js +136 -0
- package/dist/observers/manager.js.map +1 -0
- package/dist/observers/notion-poller.d.ts +43 -0
- package/dist/observers/notion-poller.d.ts.map +1 -0
- package/dist/observers/notion-poller.js +184 -0
- package/dist/observers/notion-poller.js.map +1 -0
- package/dist/observers/observation-summarizer/index.d.ts +13 -0
- package/dist/observers/observation-summarizer/index.d.ts.map +1 -0
- package/dist/observers/observation-summarizer/index.js +13 -0
- package/dist/observers/observation-summarizer/index.js.map +1 -0
- package/dist/observers/observation-summarizer/pre-filter.d.ts +62 -0
- package/dist/observers/observation-summarizer/pre-filter.d.ts.map +1 -0
- package/dist/observers/observation-summarizer/pre-filter.js +189 -0
- package/dist/observers/observation-summarizer/pre-filter.js.map +1 -0
- package/dist/observers/observation-summarizer/response-parser.d.ts +30 -0
- package/dist/observers/observation-summarizer/response-parser.d.ts.map +1 -0
- package/dist/observers/observation-summarizer/response-parser.js +106 -0
- package/dist/observers/observation-summarizer/response-parser.js.map +1 -0
- package/dist/observers/observation-summarizer/summarizer-client.d.ts +83 -0
- package/dist/observers/observation-summarizer/summarizer-client.d.ts.map +1 -0
- package/dist/observers/observation-summarizer/summarizer-client.js +185 -0
- package/dist/observers/observation-summarizer/summarizer-client.js.map +1 -0
- package/dist/observers/observation-summarizer/summarizer-prompts.d.ts +51 -0
- package/dist/observers/observation-summarizer/summarizer-prompts.d.ts.map +1 -0
- package/dist/observers/observation-summarizer/summarizer-prompts.js +286 -0
- package/dist/observers/observation-summarizer/summarizer-prompts.js.map +1 -0
- package/dist/observers/observation-summarizer/worker.d.ts +106 -0
- package/dist/observers/observation-summarizer/worker.d.ts.map +1 -0
- package/dist/observers/observation-summarizer/worker.js +311 -0
- package/dist/observers/observation-summarizer/worker.js.map +1 -0
- package/dist/observers/obsidian-watcher.d.ts +90 -0
- package/dist/observers/obsidian-watcher.d.ts.map +1 -0
- package/dist/observers/obsidian-watcher.js +166 -0
- package/dist/observers/obsidian-watcher.js.map +1 -0
- package/dist/observers/primary-vault-watcher.d.ts +73 -0
- package/dist/observers/primary-vault-watcher.d.ts.map +1 -0
- package/dist/observers/primary-vault-watcher.js +115 -0
- package/dist/observers/primary-vault-watcher.js.map +1 -0
- package/dist/observers/repository-management-cron.d.ts +70 -0
- package/dist/observers/repository-management-cron.d.ts.map +1 -0
- package/dist/observers/repository-management-cron.js +166 -0
- package/dist/observers/repository-management-cron.js.map +1 -0
- package/dist/observers/skill-curation-walker.d.ts +33 -0
- package/dist/observers/skill-curation-walker.d.ts.map +1 -0
- package/dist/observers/skill-curation-walker.js +216 -0
- package/dist/observers/skill-curation-walker.js.map +1 -0
- package/dist/safety/absolute-block-audit.d.ts +22 -0
- package/dist/safety/absolute-block-audit.d.ts.map +1 -0
- package/dist/safety/absolute-block-audit.js +32 -0
- package/dist/safety/absolute-block-audit.js.map +1 -0
- package/dist/safety/agent-write-tracker.d.ts +42 -0
- package/dist/safety/agent-write-tracker.d.ts.map +1 -0
- package/dist/safety/agent-write-tracker.js +82 -0
- package/dist/safety/agent-write-tracker.js.map +1 -0
- package/dist/safety/always-disallowed.d.ts +66 -0
- package/dist/safety/always-disallowed.d.ts.map +1 -0
- package/dist/safety/always-disallowed.js +347 -0
- package/dist/safety/always-disallowed.js.map +1 -0
- package/dist/safety/audit.d.ts +118 -0
- package/dist/safety/audit.d.ts.map +1 -0
- package/dist/safety/audit.js +324 -0
- package/dist/safety/audit.js.map +1 -0
- package/dist/safety/integration-write-tracker.d.ts +58 -0
- package/dist/safety/integration-write-tracker.d.ts.map +1 -0
- package/dist/safety/integration-write-tracker.js +41 -0
- package/dist/safety/integration-write-tracker.js.map +1 -0
- package/dist/safety/risk-classifier.d.ts +65 -0
- package/dist/safety/risk-classifier.d.ts.map +1 -0
- package/dist/safety/risk-classifier.js +763 -0
- package/dist/safety/risk-classifier.js.map +1 -0
- package/dist/scheduler/hourly-check-gate.d.ts +73 -0
- package/dist/scheduler/hourly-check-gate.d.ts.map +1 -0
- package/dist/scheduler/hourly-check-gate.js +128 -0
- package/dist/scheduler/hourly-check-gate.js.map +1 -0
- package/dist/secrets/backend-api-key-env.d.ts +104 -0
- package/dist/secrets/backend-api-key-env.d.ts.map +1 -0
- package/dist/secrets/backend-api-key-env.js +197 -0
- package/dist/secrets/backend-api-key-env.js.map +1 -0
- package/dist/secrets/codex-home-materializer.d.ts +35 -0
- package/dist/secrets/codex-home-materializer.d.ts.map +1 -0
- package/dist/secrets/codex-home-materializer.js +76 -0
- package/dist/secrets/codex-home-materializer.js.map +1 -0
- package/dist/secrets/encrypted-blob-store.d.ts +20 -0
- package/dist/secrets/encrypted-blob-store.d.ts.map +1 -0
- package/dist/secrets/encrypted-blob-store.js +80 -0
- package/dist/secrets/encrypted-blob-store.js.map +1 -0
- package/dist/secrets/platform-secret-store.d.ts +17 -0
- package/dist/secrets/platform-secret-store.d.ts.map +1 -0
- package/dist/secrets/platform-secret-store.js +37 -0
- package/dist/secrets/platform-secret-store.js.map +1 -0
- package/dist/secrets/redaction.d.ts +2 -0
- package/dist/secrets/redaction.d.ts.map +1 -0
- package/dist/secrets/redaction.js +2 -0
- package/dist/secrets/redaction.js.map +1 -0
- package/dist/secrets/secret-broker.d.ts +61 -0
- package/dist/secrets/secret-broker.d.ts.map +1 -0
- package/dist/secrets/secret-broker.js +160 -0
- package/dist/secrets/secret-broker.js.map +1 -0
- package/dist/secrets/secret-names.d.ts +34 -0
- package/dist/secrets/secret-names.d.ts.map +1 -0
- package/dist/secrets/secret-names.js +39 -0
- package/dist/secrets/secret-names.js.map +1 -0
- package/dist/secrets/secret-store.d.ts +8 -0
- package/dist/secrets/secret-store.d.ts.map +1 -0
- package/dist/secrets/secret-store.js +2 -0
- package/dist/secrets/secret-store.js.map +1 -0
- package/dist/secrets/types.d.ts +7 -0
- package/dist/secrets/types.d.ts.map +1 -0
- package/dist/secrets/types.js +2 -0
- package/dist/secrets/types.js.map +1 -0
- package/dist/services/apple-calendar/caldav-client.d.ts +48 -0
- package/dist/services/apple-calendar/caldav-client.d.ts.map +1 -0
- package/dist/services/apple-calendar/caldav-client.js +86 -0
- package/dist/services/apple-calendar/caldav-client.js.map +1 -0
- package/dist/services/apple-calendar/caldav-codec.d.ts +67 -0
- package/dist/services/apple-calendar/caldav-codec.d.ts.map +1 -0
- package/dist/services/apple-calendar/caldav-codec.js +341 -0
- package/dist/services/apple-calendar/caldav-codec.js.map +1 -0
- package/dist/services/apple-calendar/index.d.ts +3 -0
- package/dist/services/apple-calendar/index.d.ts.map +1 -0
- package/dist/services/apple-calendar/index.js +2 -0
- package/dist/services/apple-calendar/index.js.map +1 -0
- package/dist/services/apple-calendar/service.d.ts +75 -0
- package/dist/services/apple-calendar/service.d.ts.map +1 -0
- package/dist/services/apple-calendar/service.js +374 -0
- package/dist/services/apple-calendar/service.js.map +1 -0
- package/dist/services/apple-calendar/types.d.ts +78 -0
- package/dist/services/apple-calendar/types.d.ts.map +1 -0
- package/dist/services/apple-calendar/types.js +17 -0
- package/dist/services/apple-calendar/types.js.map +1 -0
- package/dist/services/attachments/hardlink.d.ts +11 -0
- package/dist/services/attachments/hardlink.d.ts.map +1 -0
- package/dist/services/attachments/hardlink.js +56 -0
- package/dist/services/attachments/hardlink.js.map +1 -0
- package/dist/services/attachments/sanitize.d.ts +21 -0
- package/dist/services/attachments/sanitize.d.ts.map +1 -0
- package/dist/services/attachments/sanitize.js +128 -0
- package/dist/services/attachments/sanitize.js.map +1 -0
- package/dist/services/attachments/store.d.ts +146 -0
- package/dist/services/attachments/store.d.ts.map +1 -0
- package/dist/services/attachments/store.js +477 -0
- package/dist/services/attachments/store.js.map +1 -0
- package/dist/services/calendar/outlook/graph-calendar-client.d.ts +114 -0
- package/dist/services/calendar/outlook/graph-calendar-client.d.ts.map +1 -0
- package/dist/services/calendar/outlook/graph-calendar-client.js +146 -0
- package/dist/services/calendar/outlook/graph-calendar-client.js.map +1 -0
- package/dist/services/calendar.d.ts +115 -0
- package/dist/services/calendar.d.ts.map +1 -0
- package/dist/services/calendar.js +281 -0
- package/dist/services/calendar.js.map +1 -0
- package/dist/services/delegated-backend-invoker.d.ts +414 -0
- package/dist/services/delegated-backend-invoker.d.ts.map +1 -0
- package/dist/services/delegated-backend-invoker.js +2372 -0
- package/dist/services/delegated-backend-invoker.js.map +1 -0
- package/dist/services/delegated-proxy-config.d.ts +93 -0
- package/dist/services/delegated-proxy-config.d.ts.map +1 -0
- package/dist/services/delegated-proxy-config.js +98 -0
- package/dist/services/delegated-proxy-config.js.map +1 -0
- package/dist/services/delegated-task-result-cache.d.ts +176 -0
- package/dist/services/delegated-task-result-cache.d.ts.map +1 -0
- package/dist/services/delegated-task-result-cache.js +0 -0
- package/dist/services/delegated-task-result-cache.js.map +1 -0
- package/dist/services/delegated-task-runtime.d.ts +346 -0
- package/dist/services/delegated-task-runtime.d.ts.map +1 -0
- package/dist/services/delegated-task-runtime.js +589 -0
- package/dist/services/delegated-task-runtime.js.map +1 -0
- package/dist/services/delegated-task-session-pool.d.ts +182 -0
- package/dist/services/delegated-task-session-pool.d.ts.map +1 -0
- package/dist/services/delegated-task-session-pool.js +292 -0
- package/dist/services/delegated-task-session-pool.js.map +1 -0
- package/dist/services/delegated-tool-runtime.d.ts +50 -0
- package/dist/services/delegated-tool-runtime.d.ts.map +1 -0
- package/dist/services/delegated-tool-runtime.js +120 -0
- package/dist/services/delegated-tool-runtime.js.map +1 -0
- package/dist/services/fts5.d.ts +40 -0
- package/dist/services/fts5.d.ts.map +1 -0
- package/dist/services/fts5.js +54 -0
- package/dist/services/fts5.js.map +1 -0
- package/dist/services/git-account-registry.d.ts +164 -0
- package/dist/services/git-account-registry.d.ts.map +1 -0
- package/dist/services/git-account-registry.js +297 -0
- package/dist/services/git-account-registry.js.map +1 -0
- package/dist/services/github.d.ts +49 -0
- package/dist/services/github.d.ts.map +1 -0
- package/dist/services/github.js +123 -0
- package/dist/services/github.js.map +1 -0
- package/dist/services/gmail-classifier.d.ts +62 -0
- package/dist/services/gmail-classifier.d.ts.map +1 -0
- package/dist/services/gmail-classifier.js +221 -0
- package/dist/services/gmail-classifier.js.map +1 -0
- package/dist/services/gmail.d.ts +192 -0
- package/dist/services/gmail.d.ts.map +1 -0
- package/dist/services/gmail.js +678 -0
- package/dist/services/gmail.js.map +1 -0
- package/dist/services/google-auth.d.ts +16 -0
- package/dist/services/google-auth.d.ts.map +1 -0
- package/dist/services/google-auth.js +37 -0
- package/dist/services/google-auth.js.map +1 -0
- package/dist/services/google-maps.d.ts +35 -0
- package/dist/services/google-maps.d.ts.map +1 -0
- package/dist/services/google-maps.js +82 -0
- package/dist/services/google-maps.js.map +1 -0
- package/dist/services/integrations/extract-write-item-id.d.ts +64 -0
- package/dist/services/integrations/extract-write-item-id.d.ts.map +1 -0
- package/dist/services/integrations/extract-write-item-id.js +188 -0
- package/dist/services/integrations/extract-write-item-id.js.map +1 -0
- package/dist/services/integrations/reconcile.d.ts +136 -0
- package/dist/services/integrations/reconcile.d.ts.map +1 -0
- package/dist/services/integrations/reconcile.js +218 -0
- package/dist/services/integrations/reconcile.js.map +1 -0
- package/dist/services/integrations/snapshot-partitions.d.ts +40 -0
- package/dist/services/integrations/snapshot-partitions.d.ts.map +1 -0
- package/dist/services/integrations/snapshot-partitions.js +113 -0
- package/dist/services/integrations/snapshot-partitions.js.map +1 -0
- package/dist/services/journal/render.d.ts +15 -0
- package/dist/services/journal/render.d.ts.map +1 -0
- package/dist/services/journal/render.js +17 -0
- package/dist/services/journal/render.js.map +1 -0
- package/dist/services/journal/writer.d.ts +26 -0
- package/dist/services/journal/writer.d.ts.map +1 -0
- package/dist/services/journal/writer.js +50 -0
- package/dist/services/journal/writer.js.map +1 -0
- package/dist/services/mail/account-registry.d.ts +208 -0
- package/dist/services/mail/account-registry.d.ts.map +1 -0
- package/dist/services/mail/account-registry.js +554 -0
- package/dist/services/mail/account-registry.js.map +1 -0
- package/dist/services/mail/gmail/auth-failure-classifier.d.ts +24 -0
- package/dist/services/mail/gmail/auth-failure-classifier.d.ts.map +1 -0
- package/dist/services/mail/gmail/auth-failure-classifier.js +67 -0
- package/dist/services/mail/gmail/auth-failure-classifier.js.map +1 -0
- package/dist/services/mail/gmail/gmail-provider.d.ts +58 -0
- package/dist/services/mail/gmail/gmail-provider.d.ts.map +1 -0
- package/dist/services/mail/gmail/gmail-provider.js +434 -0
- package/dist/services/mail/gmail/gmail-provider.js.map +1 -0
- package/dist/services/mail/gmail/legacy-row.d.ts +24 -0
- package/dist/services/mail/gmail/legacy-row.d.ts.map +1 -0
- package/dist/services/mail/gmail/legacy-row.js +71 -0
- package/dist/services/mail/gmail/legacy-row.js.map +1 -0
- package/dist/services/mail/gmail/poll-cursor.d.ts +12 -0
- package/dist/services/mail/gmail/poll-cursor.d.ts.map +1 -0
- package/dist/services/mail/gmail/poll-cursor.js +32 -0
- package/dist/services/mail/gmail/poll-cursor.js.map +1 -0
- package/dist/services/mail/html-to-plaintext.d.ts +27 -0
- package/dist/services/mail/html-to-plaintext.d.ts.map +1 -0
- package/dist/services/mail/html-to-plaintext.js +163 -0
- package/dist/services/mail/html-to-plaintext.js.map +1 -0
- package/dist/services/mail/imap/app-password.d.ts +27 -0
- package/dist/services/mail/imap/app-password.d.ts.map +1 -0
- package/dist/services/mail/imap/app-password.js +86 -0
- package/dist/services/mail/imap/app-password.js.map +1 -0
- package/dist/services/mail/imap/auth-failure-classifier.d.ts +21 -0
- package/dist/services/mail/imap/auth-failure-classifier.d.ts.map +1 -0
- package/dist/services/mail/imap/auth-failure-classifier.js +54 -0
- package/dist/services/mail/imap/auth-failure-classifier.js.map +1 -0
- package/dist/services/mail/imap/capabilities.d.ts +30 -0
- package/dist/services/mail/imap/capabilities.d.ts.map +1 -0
- package/dist/services/mail/imap/capabilities.js +70 -0
- package/dist/services/mail/imap/capabilities.js.map +1 -0
- package/dist/services/mail/imap/client.d.ts +15 -0
- package/dist/services/mail/imap/client.d.ts.map +1 -0
- package/dist/services/mail/imap/client.js +60 -0
- package/dist/services/mail/imap/client.js.map +1 -0
- package/dist/services/mail/imap/cursor.d.ts +19 -0
- package/dist/services/mail/imap/cursor.d.ts.map +1 -0
- package/dist/services/mail/imap/cursor.js +47 -0
- package/dist/services/mail/imap/cursor.js.map +1 -0
- package/dist/services/mail/imap/folder-resolver.d.ts +24 -0
- package/dist/services/mail/imap/folder-resolver.d.ts.map +1 -0
- package/dist/services/mail/imap/folder-resolver.js +58 -0
- package/dist/services/mail/imap/folder-resolver.js.map +1 -0
- package/dist/services/mail/imap/icloud-provider.d.ts +5 -0
- package/dist/services/mail/imap/icloud-provider.d.ts.map +1 -0
- package/dist/services/mail/imap/icloud-provider.js +5 -0
- package/dist/services/mail/imap/icloud-provider.js.map +1 -0
- package/dist/services/mail/imap/imap-provider-base.d.ts +173 -0
- package/dist/services/mail/imap/imap-provider-base.d.ts.map +1 -0
- package/dist/services/mail/imap/imap-provider-base.js +1004 -0
- package/dist/services/mail/imap/imap-provider-base.js.map +1 -0
- package/dist/services/mail/imap/query-translator.d.ts +13 -0
- package/dist/services/mail/imap/query-translator.d.ts.map +1 -0
- package/dist/services/mail/imap/query-translator.js +114 -0
- package/dist/services/mail/imap/query-translator.js.map +1 -0
- package/dist/services/mail/imap/reconcile-planner.d.ts +56 -0
- package/dist/services/mail/imap/reconcile-planner.d.ts.map +1 -0
- package/dist/services/mail/imap/reconcile-planner.js +52 -0
- package/dist/services/mail/imap/reconcile-planner.js.map +1 -0
- package/dist/services/mail/imap/reply-mime.d.ts +24 -0
- package/dist/services/mail/imap/reply-mime.d.ts.map +1 -0
- package/dist/services/mail/imap/reply-mime.js +77 -0
- package/dist/services/mail/imap/reply-mime.js.map +1 -0
- package/dist/services/mail/imap/yahoo-provider.d.ts +5 -0
- package/dist/services/mail/imap/yahoo-provider.d.ts.map +1 -0
- package/dist/services/mail/imap/yahoo-provider.js +5 -0
- package/dist/services/mail/imap/yahoo-provider.js.map +1 -0
- package/dist/services/mail/mail-search.d.ts +35 -0
- package/dist/services/mail/mail-search.d.ts.map +1 -0
- package/dist/services/mail/mail-search.js +59 -0
- package/dist/services/mail/mail-search.js.map +1 -0
- package/dist/services/mail/outlook/auth-failure-classifier.d.ts +38 -0
- package/dist/services/mail/outlook/auth-failure-classifier.d.ts.map +1 -0
- package/dist/services/mail/outlook/auth-failure-classifier.js +91 -0
- package/dist/services/mail/outlook/auth-failure-classifier.js.map +1 -0
- package/dist/services/mail/outlook/client-config.d.ts +34 -0
- package/dist/services/mail/outlook/client-config.d.ts.map +1 -0
- package/dist/services/mail/outlook/client-config.js +58 -0
- package/dist/services/mail/outlook/client-config.js.map +1 -0
- package/dist/services/mail/outlook/delta-cursor.d.ts +66 -0
- package/dist/services/mail/outlook/delta-cursor.d.ts.map +1 -0
- package/dist/services/mail/outlook/delta-cursor.js +85 -0
- package/dist/services/mail/outlook/delta-cursor.js.map +1 -0
- package/dist/services/mail/outlook/graph-client.d.ts +98 -0
- package/dist/services/mail/outlook/graph-client.d.ts.map +1 -0
- package/dist/services/mail/outlook/graph-client.js +198 -0
- package/dist/services/mail/outlook/graph-client.js.map +1 -0
- package/dist/services/mail/outlook/msal-app-factory.d.ts +20 -0
- package/dist/services/mail/outlook/msal-app-factory.d.ts.map +1 -0
- package/dist/services/mail/outlook/msal-app-factory.js +62 -0
- package/dist/services/mail/outlook/msal-app-factory.js.map +1 -0
- package/dist/services/mail/outlook/msal-cache-plugin.d.ts +19 -0
- package/dist/services/mail/outlook/msal-cache-plugin.d.ts.map +1 -0
- package/dist/services/mail/outlook/msal-cache-plugin.js +30 -0
- package/dist/services/mail/outlook/msal-cache-plugin.js.map +1 -0
- package/dist/services/mail/outlook/oauth-device-code.d.ts +26 -0
- package/dist/services/mail/outlook/oauth-device-code.d.ts.map +1 -0
- package/dist/services/mail/outlook/oauth-device-code.js +32 -0
- package/dist/services/mail/outlook/oauth-device-code.js.map +1 -0
- package/dist/services/mail/outlook/oauth-loopback.d.ts +41 -0
- package/dist/services/mail/outlook/oauth-loopback.d.ts.map +1 -0
- package/dist/services/mail/outlook/oauth-loopback.js +223 -0
- package/dist/services/mail/outlook/oauth-loopback.js.map +1 -0
- package/dist/services/mail/outlook/outlook-provider.d.ts +100 -0
- package/dist/services/mail/outlook/outlook-provider.d.ts.map +1 -0
- package/dist/services/mail/outlook/outlook-provider.js +619 -0
- package/dist/services/mail/outlook/outlook-provider.js.map +1 -0
- package/dist/services/mail/outlook/query-translator.d.ts +10 -0
- package/dist/services/mail/outlook/query-translator.d.ts.map +1 -0
- package/dist/services/mail/outlook/query-translator.js +103 -0
- package/dist/services/mail/outlook/query-translator.js.map +1 -0
- package/dist/services/mail/provider.d.ts +267 -0
- package/dist/services/mail/provider.d.ts.map +1 -0
- package/dist/services/mail/provider.js +34 -0
- package/dist/services/mail/provider.js.map +1 -0
- package/dist/services/mail/query-utils.d.ts +13 -0
- package/dist/services/mail/query-utils.d.ts.map +1 -0
- package/dist/services/mail/query-utils.js +18 -0
- package/dist/services/mail/query-utils.js.map +1 -0
- package/dist/services/mail-classifier.d.ts +25 -0
- package/dist/services/mail-classifier.d.ts.map +1 -0
- package/dist/services/mail-classifier.js +52 -0
- package/dist/services/mail-classifier.js.map +1 -0
- package/dist/services/mail-ingestion.d.ts +139 -0
- package/dist/services/mail-ingestion.d.ts.map +1 -0
- package/dist/services/mail-ingestion.js +223 -0
- package/dist/services/mail-ingestion.js.map +1 -0
- package/dist/services/mcp/auto-probe.d.ts +76 -0
- package/dist/services/mcp/auto-probe.d.ts.map +1 -0
- package/dist/services/mcp/auto-probe.js +147 -0
- package/dist/services/mcp/auto-probe.js.map +1 -0
- package/dist/services/mcp/generators/claude.d.ts +18 -0
- package/dist/services/mcp/generators/claude.d.ts.map +1 -0
- package/dist/services/mcp/generators/claude.js +90 -0
- package/dist/services/mcp/generators/claude.js.map +1 -0
- package/dist/services/mcp/generators/codex.d.ts +22 -0
- package/dist/services/mcp/generators/codex.d.ts.map +1 -0
- package/dist/services/mcp/generators/codex.js +102 -0
- package/dist/services/mcp/generators/codex.js.map +1 -0
- package/dist/services/mcp/generators/gemini.d.ts +20 -0
- package/dist/services/mcp/generators/gemini.d.ts.map +1 -0
- package/dist/services/mcp/generators/gemini.js +97 -0
- package/dist/services/mcp/generators/gemini.js.map +1 -0
- package/dist/services/mcp/generators/index.d.ts +20 -0
- package/dist/services/mcp/generators/index.d.ts.map +1 -0
- package/dist/services/mcp/generators/index.js +29 -0
- package/dist/services/mcp/generators/index.js.map +1 -0
- package/dist/services/mcp/generators/types.d.ts +47 -0
- package/dist/services/mcp/generators/types.d.ts.map +1 -0
- package/dist/services/mcp/generators/types.js +40 -0
- package/dist/services/mcp/generators/types.js.map +1 -0
- package/dist/services/mcp/probe.d.ts +31 -0
- package/dist/services/mcp/probe.d.ts.map +1 -0
- package/dist/services/mcp/probe.js +437 -0
- package/dist/services/mcp/probe.js.map +1 -0
- package/dist/services/mcp/registry.d.ts +84 -0
- package/dist/services/mcp/registry.d.ts.map +1 -0
- package/dist/services/mcp/registry.js +387 -0
- package/dist/services/mcp/registry.js.map +1 -0
- package/dist/services/mcp/risk.d.ts +82 -0
- package/dist/services/mcp/risk.d.ts.map +1 -0
- package/dist/services/mcp/risk.js +126 -0
- package/dist/services/mcp/risk.js.map +1 -0
- package/dist/services/mcp/session-materializer.d.ts +123 -0
- package/dist/services/mcp/session-materializer.d.ts.map +1 -0
- package/dist/services/mcp/session-materializer.js +361 -0
- package/dist/services/mcp/session-materializer.js.map +1 -0
- package/dist/services/mcp/tool-audit.d.ts +53 -0
- package/dist/services/mcp/tool-audit.d.ts.map +1 -0
- package/dist/services/mcp/tool-audit.js +74 -0
- package/dist/services/mcp/tool-audit.js.map +1 -0
- package/dist/services/mcp/types.d.ts +88 -0
- package/dist/services/mcp/types.d.ts.map +1 -0
- package/dist/services/mcp/types.js +94 -0
- package/dist/services/mcp/types.js.map +1 -0
- package/dist/services/notion.d.ts +134 -0
- package/dist/services/notion.d.ts.map +1 -0
- package/dist/services/notion.js +350 -0
- package/dist/services/notion.js.map +1 -0
- package/dist/services/obsidian.d.ts +116 -0
- package/dist/services/obsidian.d.ts.map +1 -0
- package/dist/services/obsidian.js +305 -0
- package/dist/services/obsidian.js.map +1 -0
- package/dist/services/service-registry.d.ts +31 -0
- package/dist/services/service-registry.d.ts.map +1 -0
- package/dist/services/service-registry.js +15 -0
- package/dist/services/service-registry.js.map +1 -0
- package/dist/services/voice/transcriber-impl.d.ts +15 -0
- package/dist/services/voice/transcriber-impl.d.ts.map +1 -0
- package/dist/services/voice/transcriber-impl.js +129 -0
- package/dist/services/voice/transcriber-impl.js.map +1 -0
- package/dist/services/voice/transcriber.d.ts +117 -0
- package/dist/services/voice/transcriber.d.ts.map +1 -0
- package/dist/services/voice/transcriber.js +201 -0
- package/dist/services/voice/transcriber.js.map +1 -0
- package/dist/settings/runtime-settings.d.ts +232 -0
- package/dist/settings/runtime-settings.d.ts.map +1 -0
- package/dist/settings/runtime-settings.js +769 -0
- package/dist/settings/runtime-settings.js.map +1 -0
- package/dist/settings/settings-store.d.ts +13 -0
- package/dist/settings/settings-store.d.ts.map +1 -0
- package/dist/settings/settings-store.js +87 -0
- package/dist/settings/settings-store.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,1406 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { streamSSE } from "hono/streaming";
|
|
3
|
+
import { createSettingsStore } from "../../settings/settings-store.js";
|
|
4
|
+
import { applyConfigUpdates } from "../env-writer.js";
|
|
5
|
+
import { markIntegrationWrite } from "../../safety/integration-write-tracker.js";
|
|
6
|
+
import { loadOutlookClientConfig, saveOutlookClientConfig, OUTLOOK_CLIENT_CONFIG_BLOB, } from "../../services/mail/outlook/client-config.js";
|
|
7
|
+
import { runLoopbackOAuth, OAuthLoopbackError, OAuthLoopbackTimeoutError, } from "../../services/mail/outlook/oauth-loopback.js";
|
|
8
|
+
import { runDeviceCodeOAuth } from "../../services/mail/outlook/oauth-device-code.js";
|
|
9
|
+
import { DuplicateAccountError, ProviderNotImplementedError, } from "../../services/mail/account-registry.js";
|
|
10
|
+
import { createLogger } from "../../logging.js";
|
|
11
|
+
import { readJsonBody } from "../json-body.js";
|
|
12
|
+
import { buildImapAccountSecret, isImapAppPasswordKind, serializeImapAccountSecret, } from "../../services/mail/imap/app-password.js";
|
|
13
|
+
import { classifyImapAuthFailure } from "../../services/mail/imap/auth-failure-classifier.js";
|
|
14
|
+
import { verifyImapAccountSecret } from "../../services/mail/imap/client.js";
|
|
15
|
+
import { searchMail } from "../../services/mail/mail-search.js";
|
|
16
|
+
import { extractMailHtmlBody, renderExtractedMailHtmlBody, } from "../../services/mail/html-to-plaintext.js";
|
|
17
|
+
import { isIntegrationDelegated } from "../../core/integration-lifecycle.js";
|
|
18
|
+
import { INTEGRATION_DESCRIPTORS, } from "@aitne/shared";
|
|
19
|
+
import { readIntegrations } from "../../db/integrations-store.js";
|
|
20
|
+
const logger = createLogger("mail-api");
|
|
21
|
+
const ALL_KINDS = [
|
|
22
|
+
"gmail",
|
|
23
|
+
"outlook",
|
|
24
|
+
"yahoo",
|
|
25
|
+
"icloud",
|
|
26
|
+
];
|
|
27
|
+
const PROVIDER_LABELS = {
|
|
28
|
+
gmail: "Gmail",
|
|
29
|
+
outlook: "Outlook",
|
|
30
|
+
yahoo: "Yahoo Mail",
|
|
31
|
+
icloud: "iCloud Mail",
|
|
32
|
+
};
|
|
33
|
+
/** Lower bound on the §C6 agent-write-attribution TTL. Covers the common
|
|
34
|
+
* case where the poll interval is short (default 180s) — we still want
|
|
35
|
+
* enough slack for a user action that triggered the send to settle before
|
|
36
|
+
* the next poll picks it up. Real TTL scales with the configured poll
|
|
37
|
+
* interval (see {@link computeAgentWriteTtlMs}). */
|
|
38
|
+
const MAIL_AGENT_WRITE_TTL_FLOOR_MS = 5 * 60 * 1000;
|
|
39
|
+
/** The poll-interval multiplier. Two ticks of slack means: a send at T=0
|
|
40
|
+
* survives the T=poll and T=2*poll ticks before the mark expires —
|
|
41
|
+
* enough to absorb one missed/delayed tick without losing attribution. */
|
|
42
|
+
const MAIL_AGENT_WRITE_TTL_POLL_MULTIPLIER = 2;
|
|
43
|
+
const MAIL_BODY_CHUNK_DEFAULT_CHARS = 12_000;
|
|
44
|
+
const MAIL_BODY_CHUNK_MAX_CHARS = 50_000;
|
|
45
|
+
const MAIL_BODY_METADATA_DEFAULT_LIMIT = 100;
|
|
46
|
+
const MAIL_BODY_METADATA_MAX_LIMIT = 500;
|
|
47
|
+
export function computeAgentWriteTtlMs(pollIntervalSeconds) {
|
|
48
|
+
const derived = (pollIntervalSeconds ?? 0) * 1000 * MAIL_AGENT_WRITE_TTL_POLL_MULTIPLIER;
|
|
49
|
+
return Math.max(MAIL_AGENT_WRITE_TTL_FLOOR_MS, derived);
|
|
50
|
+
}
|
|
51
|
+
function gatedIntegrationForKind(kind) {
|
|
52
|
+
if (kind === "gmail")
|
|
53
|
+
return "gmail";
|
|
54
|
+
if (kind === "outlook")
|
|
55
|
+
return "outlook_mail";
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function delegatedMailIntegrationMessage(key, delegatedBackend) {
|
|
59
|
+
const descriptor = INTEGRATION_DESCRIPTORS[key];
|
|
60
|
+
const displayName = descriptor.displayName;
|
|
61
|
+
const owner = delegatedBackend
|
|
62
|
+
? `delegated to ${delegatedBackend}`
|
|
63
|
+
: "delegated";
|
|
64
|
+
// User-managed connector integrations (Outlook today) ship no
|
|
65
|
+
// daemon-side proxy. The agent must use whatever Outlook MCP /
|
|
66
|
+
// connector the user wired up on the chosen backend; pointing at
|
|
67
|
+
// `/api/integrations/.../invoke` would be a lie.
|
|
68
|
+
if (descriptor.userManagedConnector) {
|
|
69
|
+
return [
|
|
70
|
+
`${displayName} is in delegated mode (${owner}).`,
|
|
71
|
+
`The agent backend is expected to use the user-installed ${displayName} MCP / connector tools — the daemon does not proxy this integration.`,
|
|
72
|
+
"Other mail accounts remain available through /api/mail/*.",
|
|
73
|
+
].join(" ");
|
|
74
|
+
}
|
|
75
|
+
return [
|
|
76
|
+
`${displayName} is in delegated mode (${owner}).`,
|
|
77
|
+
`Same-backend sessions: use the connector's native ${displayName} MCP tools.`,
|
|
78
|
+
`Cross-backend sessions: call POST /api/integrations/${key}/invoke.`,
|
|
79
|
+
`Non-${displayName} mail accounts remain available through /api/mail/*.`,
|
|
80
|
+
].join(" ");
|
|
81
|
+
}
|
|
82
|
+
export function createMailRoutes(deps) {
|
|
83
|
+
const app = new Hono();
|
|
84
|
+
const getSettingsStore = () => deps.settingsStore ?? createSettingsStore(deps.db);
|
|
85
|
+
const verifyImapCredentials = deps.verifyImapAccountSecret ?? verifyImapAccountSecret;
|
|
86
|
+
app.get("/mail/providers", (c) => {
|
|
87
|
+
const registry = deps.services.mail;
|
|
88
|
+
const accounts = registry?.listAccounts() ?? [];
|
|
89
|
+
const available = ALL_KINDS.map((kind) => {
|
|
90
|
+
const ofKind = accounts.filter((a) => a.kind === kind);
|
|
91
|
+
return {
|
|
92
|
+
kind,
|
|
93
|
+
label: PROVIDER_LABELS[kind],
|
|
94
|
+
accountsConfigured: ofKind.length,
|
|
95
|
+
accountsHealthy: ofKind.filter((a) => a.authStatus === "healthy").length,
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
return c.json({
|
|
99
|
+
enabledKinds: [...deps.config.enabledMailProviders],
|
|
100
|
+
available,
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
app.patch("/mail/providers", async (c) => {
|
|
104
|
+
const parsedBody = await readJsonBody(c);
|
|
105
|
+
if (!parsedBody.ok)
|
|
106
|
+
return parsedBody.response;
|
|
107
|
+
const candidate = parsedBody.body?.enabledKinds;
|
|
108
|
+
if (!Array.isArray(candidate)) {
|
|
109
|
+
return c.json({ error: "invalid_body", message: "enabledKinds must be an array" }, 400);
|
|
110
|
+
}
|
|
111
|
+
const settingsStore = getSettingsStore();
|
|
112
|
+
const result = await applyConfigUpdates(deps.config, settingsStore, {
|
|
113
|
+
enabledMailProviders: candidate,
|
|
114
|
+
});
|
|
115
|
+
if (Object.keys(result.errors).length > 0) {
|
|
116
|
+
return c.json({ error: "validation_failed", errors: result.errors }, 400);
|
|
117
|
+
}
|
|
118
|
+
const newKinds = deps.config.enabledMailProviders;
|
|
119
|
+
const registry = deps.services.mail;
|
|
120
|
+
const before = new Set();
|
|
121
|
+
const after = new Set(newKinds);
|
|
122
|
+
const accounts = registry?.listAccounts() ?? [];
|
|
123
|
+
for (const acct of accounts) {
|
|
124
|
+
before.add(acct.kind);
|
|
125
|
+
}
|
|
126
|
+
const dormantAccounts = accounts
|
|
127
|
+
.filter((a) => before.has(a.kind) && !after.has(a.kind))
|
|
128
|
+
.map((a) => a.id);
|
|
129
|
+
const resumedAccounts = accounts
|
|
130
|
+
.filter((a) => after.has(a.kind))
|
|
131
|
+
.map((a) => a.id);
|
|
132
|
+
registry?.onProviderSelectionChanged(newKinds);
|
|
133
|
+
logger.info({ enabledKinds: [...newKinds], dormantAccounts, resumedAccounts }, "mail provider selection updated");
|
|
134
|
+
return c.json({ status: "updated", dormantAccounts, resumedAccounts });
|
|
135
|
+
});
|
|
136
|
+
// GET /mail/accounts — all configured accounts (dashboard, setup).
|
|
137
|
+
// GET /mail/accounts?active=1 — scope-gated subset that matches what
|
|
138
|
+
// `accounts.md` materializes and what the unified poller observes:
|
|
139
|
+
// kind ∈ enabledMailProviders ∧ account.active ∧ authStatus === "healthy".
|
|
140
|
+
// Skills that need to refresh a stale `accounts.md` MUST pass `?active=1`
|
|
141
|
+
// — raw listAccounts() includes dormant / unhealthy rows and will mislead
|
|
142
|
+
// the agent into picking an id that every operation will 4xx on.
|
|
143
|
+
app.get("/mail/accounts", (c) => {
|
|
144
|
+
const registry = deps.services.mail;
|
|
145
|
+
if (!registry) {
|
|
146
|
+
return c.json({ accounts: [] });
|
|
147
|
+
}
|
|
148
|
+
const activeOnly = c.req.query("active") === "1";
|
|
149
|
+
const accounts = activeOnly
|
|
150
|
+
? registry.listActiveAccounts()
|
|
151
|
+
: registry.listAccounts();
|
|
152
|
+
return c.json({ accounts });
|
|
153
|
+
});
|
|
154
|
+
// POST /mail/accounts blocks for the duration of the loopback PKCE flow —
|
|
155
|
+
// up to OAuthLoopbackTimeoutError's 5-minute cap (see oauth-loopback.ts).
|
|
156
|
+
// Dashboard clients MUST configure a long fetch timeout for this route.
|
|
157
|
+
// Headless environments (SSH, WSL) should use /mail/accounts/device-code.
|
|
158
|
+
app.post("/mail/accounts", async (c) => {
|
|
159
|
+
const registry = deps.services.mail;
|
|
160
|
+
if (!registry)
|
|
161
|
+
return c.json({ error: "mail_not_configured" }, 503);
|
|
162
|
+
if (!deps.blobStore)
|
|
163
|
+
return c.json({ error: "blob_store_unavailable" }, 503);
|
|
164
|
+
const parsedBody = await readJsonBody(c);
|
|
165
|
+
if (!parsedBody.ok)
|
|
166
|
+
return parsedBody.response;
|
|
167
|
+
const body = parsedBody.body;
|
|
168
|
+
if (body?.kind === "gmail") {
|
|
169
|
+
// The primary Gmail mailbox now participates in the unified mail
|
|
170
|
+
// surface via the shared Google OAuth credentials from
|
|
171
|
+
// /config/google-auth. Additional Gmail accounts still need a
|
|
172
|
+
// per-account Google OAuth credential store and are intentionally
|
|
173
|
+
// not wired up yet.
|
|
174
|
+
return c.json({
|
|
175
|
+
error: "not_implemented",
|
|
176
|
+
message: "Additional Gmail accounts are not implemented yet. The primary Gmail identity is configured through /config/google-auth and is exposed on the unified /mail/* surface automatically.",
|
|
177
|
+
}, 501);
|
|
178
|
+
}
|
|
179
|
+
if (body?.kind !== "outlook") {
|
|
180
|
+
return c.json({
|
|
181
|
+
error: "unsupported_kind",
|
|
182
|
+
message: "Only outlook is supported on this endpoint. Yahoo/iCloud use POST /config/mail/app-password. The primary Gmail account uses /config/google-auth; extra Gmail accounts are not implemented.",
|
|
183
|
+
}, 400);
|
|
184
|
+
}
|
|
185
|
+
// §UI v2 auth-then-enable: registration is allowed regardless of
|
|
186
|
+
// enabledMailProviders. The provider becomes live only when the user
|
|
187
|
+
// toggles "Enable" on the dashboard mail card.
|
|
188
|
+
const clientConfig = await loadOutlookClientConfig(deps.blobStore);
|
|
189
|
+
if (!clientConfig) {
|
|
190
|
+
return c.json({
|
|
191
|
+
error: "outlook_client_config_missing",
|
|
192
|
+
message: "PUT /api/config/mail/outlook/client-config first.",
|
|
193
|
+
}, 412);
|
|
194
|
+
}
|
|
195
|
+
let oauthResult;
|
|
196
|
+
try {
|
|
197
|
+
oauthResult = await runLoopbackOAuth({ clientConfig });
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
if (err instanceof OAuthLoopbackTimeoutError) {
|
|
201
|
+
return c.json({ error: "oauth_timeout", message: err.message }, 408);
|
|
202
|
+
}
|
|
203
|
+
if (err instanceof OAuthLoopbackError) {
|
|
204
|
+
return c.json({ error: err.code, message: err.message }, 400);
|
|
205
|
+
}
|
|
206
|
+
logger.error({ err }, "outlook oauth bootstrap failed");
|
|
207
|
+
return c.json({ error: "oauth_failed", message: err instanceof Error ? err.message : String(err) }, 500);
|
|
208
|
+
}
|
|
209
|
+
try {
|
|
210
|
+
const account = await registry.addAccount({
|
|
211
|
+
kind: "outlook",
|
|
212
|
+
email: oauthResult.email,
|
|
213
|
+
label: typeof body?.label === "string" ? body.label : undefined,
|
|
214
|
+
authType: "oauth",
|
|
215
|
+
secretPayload: oauthResult.serializedCache,
|
|
216
|
+
});
|
|
217
|
+
return c.json({ status: "completed", account });
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
if (err instanceof DuplicateAccountError) {
|
|
221
|
+
return c.json({ error: err.code, message: err.message }, 409);
|
|
222
|
+
}
|
|
223
|
+
logger.error({ err, email: oauthResult.email }, "outlook addAccount failed after OAuth");
|
|
224
|
+
return c.json({ error: "add_account_failed", message: err instanceof Error ? err.message : String(err) }, 500);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
// Device-code fallback (§B2). Used by headless/SSH environments where the
|
|
228
|
+
// loopback flow's browser-open would fail. Streams SSE events:
|
|
229
|
+
// `prompt` { userCode, verificationUri, expiresIn, message }
|
|
230
|
+
// `completed` { account }
|
|
231
|
+
// `failed` { error, message }
|
|
232
|
+
//
|
|
233
|
+
// MSAL's acquireTokenByDeviceCode blocks until the user completes verification
|
|
234
|
+
// in their browser, so this endpoint may remain open for several minutes.
|
|
235
|
+
app.post("/mail/accounts/device-code", async (c) => {
|
|
236
|
+
const registry = deps.services.mail;
|
|
237
|
+
if (!registry)
|
|
238
|
+
return c.json({ error: "mail_not_configured" }, 503);
|
|
239
|
+
if (!deps.blobStore)
|
|
240
|
+
return c.json({ error: "blob_store_unavailable" }, 503);
|
|
241
|
+
const parsedBody = await readJsonBody(c);
|
|
242
|
+
if (!parsedBody.ok)
|
|
243
|
+
return parsedBody.response;
|
|
244
|
+
const body = parsedBody.body;
|
|
245
|
+
if (body?.kind !== "outlook") {
|
|
246
|
+
return c.json({ error: "unsupported_kind" }, 400);
|
|
247
|
+
}
|
|
248
|
+
// §UI v2 auth-then-enable: registration allowed regardless of
|
|
249
|
+
// enabledMailProviders. The Enable toggle on the dashboard mail card
|
|
250
|
+
// governs whether the agent observes this account.
|
|
251
|
+
const clientConfig = await loadOutlookClientConfig(deps.blobStore);
|
|
252
|
+
if (!clientConfig) {
|
|
253
|
+
return c.json({ error: "outlook_client_config_missing" }, 412);
|
|
254
|
+
}
|
|
255
|
+
const label = typeof body?.label === "string" ? body.label : undefined;
|
|
256
|
+
return streamSSE(c, async (stream) => {
|
|
257
|
+
try {
|
|
258
|
+
const result = await runDeviceCodeOAuth({
|
|
259
|
+
clientConfig,
|
|
260
|
+
onPrompt: async (info) => {
|
|
261
|
+
await stream.writeSSE({
|
|
262
|
+
event: "prompt",
|
|
263
|
+
data: JSON.stringify(info),
|
|
264
|
+
});
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
try {
|
|
268
|
+
const account = await registry.addAccount({
|
|
269
|
+
kind: "outlook",
|
|
270
|
+
email: result.email,
|
|
271
|
+
label,
|
|
272
|
+
authType: "oauth",
|
|
273
|
+
secretPayload: result.serializedCache,
|
|
274
|
+
});
|
|
275
|
+
await stream.writeSSE({
|
|
276
|
+
event: "completed",
|
|
277
|
+
data: JSON.stringify({ account }),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
if (err instanceof DuplicateAccountError) {
|
|
282
|
+
await stream.writeSSE({
|
|
283
|
+
event: "failed",
|
|
284
|
+
data: JSON.stringify({ error: err.code, message: err.message }),
|
|
285
|
+
});
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
throw err;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch (err) {
|
|
292
|
+
logger.error({ err }, "device-code oauth failed");
|
|
293
|
+
await stream.writeSSE({
|
|
294
|
+
event: "failed",
|
|
295
|
+
data: JSON.stringify({
|
|
296
|
+
error: "device_code_failed",
|
|
297
|
+
message: err instanceof Error ? err.message : String(err),
|
|
298
|
+
}),
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
// Active-toggle for a single account. Distinct from provider-level enable
|
|
304
|
+
// (§6.0): users can disable one Outlook account while keeping the "Outlook"
|
|
305
|
+
// provider enabled.
|
|
306
|
+
app.patch("/mail/accounts/:accountId", async (c) => {
|
|
307
|
+
const registry = deps.services.mail;
|
|
308
|
+
if (!registry)
|
|
309
|
+
return c.json({ error: "mail_not_configured" }, 503);
|
|
310
|
+
const accountId = c.req.param("accountId");
|
|
311
|
+
const parsedBody = await readJsonBody(c);
|
|
312
|
+
if (!parsedBody.ok)
|
|
313
|
+
return parsedBody.response;
|
|
314
|
+
const active = parsedBody.body?.active;
|
|
315
|
+
if (typeof active !== "boolean") {
|
|
316
|
+
return c.json({ error: "invalid_body", message: "active: boolean required" }, 400);
|
|
317
|
+
}
|
|
318
|
+
const updated = await registry.setActive(accountId, active);
|
|
319
|
+
if (!updated)
|
|
320
|
+
return c.json({ error: "not_found" }, 404);
|
|
321
|
+
return c.json({ status: "updated", account: updated });
|
|
322
|
+
});
|
|
323
|
+
app.delete("/mail/accounts/:accountId", async (c) => {
|
|
324
|
+
const registry = deps.services.mail;
|
|
325
|
+
if (!registry) {
|
|
326
|
+
return c.json({ error: "mail_not_configured" }, 503);
|
|
327
|
+
}
|
|
328
|
+
const accountId = c.req.param("accountId");
|
|
329
|
+
const removed = await registry.removeAccount(accountId);
|
|
330
|
+
if (!removed) {
|
|
331
|
+
return c.json({ error: "not_found" }, 404);
|
|
332
|
+
}
|
|
333
|
+
return c.json({ status: "removed", accountId });
|
|
334
|
+
});
|
|
335
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
336
|
+
// Outlook BYOA client config (§6.1).
|
|
337
|
+
// Stored separately from per-account token cache.
|
|
338
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
339
|
+
app.get("/config/mail/outlook/client-config", async (c) => {
|
|
340
|
+
if (!deps.blobStore)
|
|
341
|
+
return c.json({ error: "blob_store_unavailable" }, 503);
|
|
342
|
+
const config = await loadOutlookClientConfig(deps.blobStore);
|
|
343
|
+
if (!config)
|
|
344
|
+
return c.json({ configured: false }, 200);
|
|
345
|
+
// clientId is technically public per the OAuth "public client" model;
|
|
346
|
+
// returning it lets the dashboard show a confirmation. Tenant ditto.
|
|
347
|
+
return c.json({ configured: true, clientId: config.clientId, tenant: config.tenant });
|
|
348
|
+
});
|
|
349
|
+
app.put("/config/mail/outlook/client-config", async (c) => {
|
|
350
|
+
if (!deps.blobStore)
|
|
351
|
+
return c.json({ error: "blob_store_unavailable" }, 503);
|
|
352
|
+
const parsedBody = await readJsonBody(c);
|
|
353
|
+
if (!parsedBody.ok)
|
|
354
|
+
return parsedBody.response;
|
|
355
|
+
const candidate = parsedBody.body;
|
|
356
|
+
const clientId = candidate?.clientId;
|
|
357
|
+
const tenant = candidate?.tenant;
|
|
358
|
+
if (typeof clientId !== "string" || clientId.length === 0) {
|
|
359
|
+
return c.json({ error: "invalid_body", message: "clientId required" }, 400);
|
|
360
|
+
}
|
|
361
|
+
const resolved = {
|
|
362
|
+
clientId,
|
|
363
|
+
tenant: typeof tenant === "string" && tenant.length > 0 ? tenant : "common",
|
|
364
|
+
};
|
|
365
|
+
await saveOutlookClientConfig(deps.blobStore, resolved);
|
|
366
|
+
return c.json({ status: "saved", clientId: resolved.clientId, tenant: resolved.tenant });
|
|
367
|
+
});
|
|
368
|
+
app.delete("/config/mail/outlook/client-config", async (c) => {
|
|
369
|
+
if (!deps.blobStore)
|
|
370
|
+
return c.json({ error: "blob_store_unavailable" }, 503);
|
|
371
|
+
await deps.blobStore.remove(OUTLOOK_CLIENT_CONFIG_BLOB);
|
|
372
|
+
return c.json({ status: "removed" });
|
|
373
|
+
});
|
|
374
|
+
// The Outlook OAuth bootstrap lives on POST /mail/accounts (loopback) or
|
|
375
|
+
// POST /mail/accounts/device-code (headless). No daemon-side callback
|
|
376
|
+
// endpoint is needed — the Microsoft redirect targets the ephemeral loopback
|
|
377
|
+
// http.Server inside runLoopbackOAuth.
|
|
378
|
+
app.post("/config/mail/app-password", async (c) => {
|
|
379
|
+
const registry = deps.services.mail;
|
|
380
|
+
if (!registry)
|
|
381
|
+
return c.json({ error: "mail_not_configured" }, 503);
|
|
382
|
+
const parsedBody = await readJsonBody(c);
|
|
383
|
+
if (!parsedBody.ok)
|
|
384
|
+
return parsedBody.response;
|
|
385
|
+
const body = parsedBody.body;
|
|
386
|
+
const kindCandidate = typeof body?.kind === "string" ? body.kind : null;
|
|
387
|
+
const email = typeof body?.email === "string" ? body.email : null;
|
|
388
|
+
const appPassword = typeof body?.appPassword === "string" ? body.appPassword : null;
|
|
389
|
+
if (!kindCandidate ||
|
|
390
|
+
!isImapAppPasswordKind(kindCandidate) ||
|
|
391
|
+
!email ||
|
|
392
|
+
email.length === 0 ||
|
|
393
|
+
!appPassword ||
|
|
394
|
+
appPassword.length === 0) {
|
|
395
|
+
return c.json({
|
|
396
|
+
error: "invalid_body",
|
|
397
|
+
message: "kind(yahoo|icloud), email, and appPassword are required.",
|
|
398
|
+
}, 400);
|
|
399
|
+
}
|
|
400
|
+
const kind = kindCandidate;
|
|
401
|
+
// §UI v2 auth-then-enable: registration allowed regardless of
|
|
402
|
+
// enabledMailProviders. The Enable toggle on the dashboard mail card
|
|
403
|
+
// governs whether the agent observes this account.
|
|
404
|
+
const secret = buildImapAccountSecret(kind, email, appPassword);
|
|
405
|
+
let capabilities;
|
|
406
|
+
try {
|
|
407
|
+
capabilities = await verifyImapCredentials(secret);
|
|
408
|
+
}
|
|
409
|
+
catch (err) {
|
|
410
|
+
const classified = classifyImapAuthFailure({
|
|
411
|
+
errorName: err instanceof Error ? err.name : null,
|
|
412
|
+
message: getImapErrorMessage(err),
|
|
413
|
+
responseCode: getErrorResponseCode(err),
|
|
414
|
+
});
|
|
415
|
+
if (classified.status === "requires_consent") {
|
|
416
|
+
return c.json({
|
|
417
|
+
error: "imap_auth_failed",
|
|
418
|
+
message: "IMAP login failed. Verify the email address and app password, then try again.",
|
|
419
|
+
}, 400);
|
|
420
|
+
}
|
|
421
|
+
if (classified.status === "degraded" || classified.status === "transient") {
|
|
422
|
+
return c.json({
|
|
423
|
+
error: "imap_connect_failed",
|
|
424
|
+
message: "The IMAP server could not be reached or rejected the login attempt. Try again shortly.",
|
|
425
|
+
}, 502);
|
|
426
|
+
}
|
|
427
|
+
logger.error({ err, kind, email }, "app-password IMAP verification failed");
|
|
428
|
+
return c.json({ error: "add_account_failed", message: err instanceof Error ? err.message : String(err) }, 500);
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
const account = await registry.addAccount({
|
|
432
|
+
kind,
|
|
433
|
+
email,
|
|
434
|
+
label: typeof body?.label === "string" ? body.label : undefined,
|
|
435
|
+
authType: "app_password",
|
|
436
|
+
secretPayload: serializeImapAccountSecret(secret),
|
|
437
|
+
idleEnabled: true,
|
|
438
|
+
capabilities: capabilities ?? undefined,
|
|
439
|
+
});
|
|
440
|
+
return c.json({ status: "completed", account });
|
|
441
|
+
}
|
|
442
|
+
catch (err) {
|
|
443
|
+
if (err instanceof DuplicateAccountError) {
|
|
444
|
+
return c.json({ error: err.code, message: err.message }, 409);
|
|
445
|
+
}
|
|
446
|
+
if (err instanceof ProviderNotImplementedError) {
|
|
447
|
+
return c.json({ error: err.code, message: err.message }, 400);
|
|
448
|
+
}
|
|
449
|
+
logger.error({ err, kind, email }, "app-password account add failed");
|
|
450
|
+
return c.json({ error: "add_account_failed", message: err instanceof Error ? err.message : String(err) }, 500);
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
// Refresh an existing IMAP (Yahoo / iCloud) account's app password without
|
|
454
|
+
// deleting and re-creating the row. Used when the user rotates the password
|
|
455
|
+
// at the provider and the account flips to `requires_consent`. The route
|
|
456
|
+
// verifies the new credentials against the IMAP server before persisting,
|
|
457
|
+
// then resets `auth_status` to `healthy`.
|
|
458
|
+
app.post("/config/mail/app-password/:accountId/refresh", async (c) => {
|
|
459
|
+
const registry = deps.services.mail;
|
|
460
|
+
if (!registry)
|
|
461
|
+
return c.json({ error: "mail_not_configured" }, 503);
|
|
462
|
+
const accountId = c.req.param("accountId");
|
|
463
|
+
const account = registry.getAccount(accountId);
|
|
464
|
+
if (!account)
|
|
465
|
+
return c.json({ error: "not_found" }, 404);
|
|
466
|
+
if (account.kind !== "yahoo" && account.kind !== "icloud") {
|
|
467
|
+
return c.json({
|
|
468
|
+
error: "unsupported_kind",
|
|
469
|
+
message: "App-password refresh only supports yahoo / icloud. Outlook re-authenticates via the OAuth loopback flow.",
|
|
470
|
+
}, 400);
|
|
471
|
+
}
|
|
472
|
+
const parsedBody = await readJsonBody(c);
|
|
473
|
+
if (!parsedBody.ok)
|
|
474
|
+
return parsedBody.response;
|
|
475
|
+
const body = parsedBody.body;
|
|
476
|
+
const appPassword = typeof body?.appPassword === "string" ? body.appPassword : null;
|
|
477
|
+
if (!appPassword || appPassword.length === 0) {
|
|
478
|
+
return c.json({ error: "invalid_body", message: "appPassword is required." }, 400);
|
|
479
|
+
}
|
|
480
|
+
const secret = buildImapAccountSecret(account.kind, account.email, appPassword);
|
|
481
|
+
let capabilities;
|
|
482
|
+
try {
|
|
483
|
+
capabilities = await verifyImapCredentials(secret);
|
|
484
|
+
}
|
|
485
|
+
catch (err) {
|
|
486
|
+
const classified = classifyImapAuthFailure({
|
|
487
|
+
errorName: err instanceof Error ? err.name : null,
|
|
488
|
+
message: getImapErrorMessage(err),
|
|
489
|
+
responseCode: getErrorResponseCode(err),
|
|
490
|
+
});
|
|
491
|
+
if (classified.status === "requires_consent") {
|
|
492
|
+
return c.json({
|
|
493
|
+
error: "imap_auth_failed",
|
|
494
|
+
message: "IMAP login failed with the new password. Generate a fresh app password and try again.",
|
|
495
|
+
}, 400);
|
|
496
|
+
}
|
|
497
|
+
if (classified.status === "degraded" || classified.status === "transient") {
|
|
498
|
+
return c.json({
|
|
499
|
+
error: "imap_connect_failed",
|
|
500
|
+
message: "The IMAP server could not be reached. Try again shortly.",
|
|
501
|
+
}, 502);
|
|
502
|
+
}
|
|
503
|
+
logger.error({ err, accountId }, "app-password refresh verification failed");
|
|
504
|
+
return c.json({ error: "refresh_failed", message: err instanceof Error ? err.message : String(err) }, 500);
|
|
505
|
+
}
|
|
506
|
+
try {
|
|
507
|
+
const updated = await registry.refreshImapSecret(accountId, serializeImapAccountSecret(secret), capabilities ?? undefined);
|
|
508
|
+
if (!updated)
|
|
509
|
+
return c.json({ error: "not_found" }, 404);
|
|
510
|
+
return c.json({ status: "refreshed", account: updated });
|
|
511
|
+
}
|
|
512
|
+
catch (err) {
|
|
513
|
+
logger.error({ err, accountId }, "app-password refresh failed");
|
|
514
|
+
return c.json({ error: "refresh_failed", message: err instanceof Error ? err.message : String(err) }, 500);
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
518
|
+
// Cross-account local search backed by the fts_mail_messages virtual
|
|
519
|
+
// table. Returns a flat list of lightweight summaries sourced
|
|
520
|
+
// from the index — no provider round-trip. Use this as the first stop for
|
|
521
|
+
// "find emails about X" queries; fall back to `/mail/:acct/messages?q=`
|
|
522
|
+
// only when the user wants provider-fresh results or matches bodies older
|
|
523
|
+
// than the local index.
|
|
524
|
+
//
|
|
525
|
+
// Shape matches MailMessageSummary (subset): { accountId, providerMsgId,
|
|
526
|
+
// subject, snippet, receivedAtUtc, from, isRead }. Results span all
|
|
527
|
+
// accounts by default; scope with `?accountId=`.
|
|
528
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
529
|
+
app.get("/mail/search", (c) => {
|
|
530
|
+
const q = c.req.query("q")?.trim() ?? "";
|
|
531
|
+
if (q.length === 0) {
|
|
532
|
+
return c.json({ error: "invalid_query", message: "q is required and must be non-empty" }, 400);
|
|
533
|
+
}
|
|
534
|
+
const limit = parseIntParam(c.req.query("limit"), 50, { min: 1, max: 500 });
|
|
535
|
+
const accountId = c.req.query("accountId") ?? undefined;
|
|
536
|
+
// §4.8 per-account delegated gate for search — if the caller pins the
|
|
537
|
+
// query to a Gmail account while gmail is delegated, 410. The
|
|
538
|
+
// unscoped cross-account search path stays open; results for a
|
|
539
|
+
// delegated Gmail account will just be stale FTS hits (live polling
|
|
540
|
+
// is off), which is acceptable for Phase 2 and documented in §4.4.
|
|
541
|
+
if (accountId) {
|
|
542
|
+
const account = deps.services.mail?.getAccount(accountId);
|
|
543
|
+
if (account) {
|
|
544
|
+
const gatedIntegrationKey = gatedIntegrationForKind(account.kind);
|
|
545
|
+
if (gatedIntegrationKey
|
|
546
|
+
&& isIntegrationDelegated(deps.db, gatedIntegrationKey)) {
|
|
547
|
+
const state = readIntegrations(deps.db)[gatedIntegrationKey];
|
|
548
|
+
return c.json({
|
|
549
|
+
error: "integration_delegated",
|
|
550
|
+
message: delegatedMailIntegrationMessage(gatedIntegrationKey, state.delegatedBackend ?? null),
|
|
551
|
+
integration: gatedIntegrationKey,
|
|
552
|
+
backend: state.delegatedBackend ?? null,
|
|
553
|
+
mode: "delegated",
|
|
554
|
+
}, 410);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
const hits = searchMail(deps.db, q, { accountId, limit });
|
|
559
|
+
const results = hits.map((h) => ({
|
|
560
|
+
accountId: h.accountId,
|
|
561
|
+
providerMsgId: h.providerMsgId,
|
|
562
|
+
subject: h.subject,
|
|
563
|
+
snippet: h.snippet,
|
|
564
|
+
receivedAtUtc: h.receivedAtUtc,
|
|
565
|
+
from: h.fromEmail ? { email: h.fromEmail } : null,
|
|
566
|
+
isRead: h.isRead,
|
|
567
|
+
}));
|
|
568
|
+
return c.json({ results, count: results.length, query: q });
|
|
569
|
+
});
|
|
570
|
+
// Read the mail-side parse_failures diagnostics table. The poller +
|
|
571
|
+
// ingestion pipeline write a row whenever a Kindle-export / travel /
|
|
572
|
+
// classification path bails out; this endpoint surfaces the latest
|
|
573
|
+
// failures so the dashboard (or a curl one-liner) can answer "why
|
|
574
|
+
// didn't my booking get picked up?". Read-only — no mutation surface.
|
|
575
|
+
app.get("/mail/parse-failures", (c) => {
|
|
576
|
+
const limit = parseIntParam(c.req.query("limit"), 50, { min: 1, max: 500 });
|
|
577
|
+
const accountId = c.req.query("accountId") ?? null;
|
|
578
|
+
const params = [];
|
|
579
|
+
let sql = `
|
|
580
|
+
SELECT id,
|
|
581
|
+
account_id AS accountId,
|
|
582
|
+
provider_msg_id AS providerMsgId,
|
|
583
|
+
sender,
|
|
584
|
+
subject,
|
|
585
|
+
snippet,
|
|
586
|
+
error_reason AS errorReason,
|
|
587
|
+
created_at AS createdAt
|
|
588
|
+
FROM parse_failures`;
|
|
589
|
+
if (accountId) {
|
|
590
|
+
sql += ` WHERE account_id = ?`;
|
|
591
|
+
params.push(accountId);
|
|
592
|
+
}
|
|
593
|
+
sql += ` ORDER BY id DESC LIMIT ?`;
|
|
594
|
+
params.push(limit);
|
|
595
|
+
const rows = deps.db.prepare(sql).all(...params);
|
|
596
|
+
return c.json({ failures: rows, count: rows.length });
|
|
597
|
+
});
|
|
598
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
599
|
+
// Per-account operations (§3.3, §3.11 parity table).
|
|
600
|
+
// Each route resolves a live MailProvider via the registry; error mapping
|
|
601
|
+
// distinguishes 404 (account not found) / 400 (provider not enabled for
|
|
602
|
+
// selection) / 501 (provider interface method not implemented yet for this
|
|
603
|
+
// kind). Write routes call writeTracker.markWriting so the unified poller
|
|
604
|
+
// suppresses the agent's own operations (§3.2).
|
|
605
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
606
|
+
const resolveProvider = async (accountId) => {
|
|
607
|
+
const registry = deps.services.mail;
|
|
608
|
+
if (!registry) {
|
|
609
|
+
return { ok: false, status: 503, code: "mail_not_configured", message: "Mail registry unavailable." };
|
|
610
|
+
}
|
|
611
|
+
const account = registry.getAccount(accountId);
|
|
612
|
+
if (!account) {
|
|
613
|
+
return { ok: false, status: 404, code: "not_found", message: `No mail account ${accountId}` };
|
|
614
|
+
}
|
|
615
|
+
// §4.8 per-account delegated gate. The route-gate middleware cannot
|
|
616
|
+
// blanket 410 `/api/mail/*` because it would also stop direct-only
|
|
617
|
+
// providers (iCloud, Yahoo, IMAP). Instead, accounts whose kind maps
|
|
618
|
+
// to a delegated integration (Gmail → gmail; Outlook → outlook_mail)
|
|
619
|
+
// return 410, and the agent backend's MCP / connector is expected to
|
|
620
|
+
// be the access path. Other kinds fall through unchanged.
|
|
621
|
+
const gatedIntegrationKey = gatedIntegrationForKind(account.kind);
|
|
622
|
+
if (gatedIntegrationKey && isIntegrationDelegated(deps.db, gatedIntegrationKey)) {
|
|
623
|
+
const state = readIntegrations(deps.db)[gatedIntegrationKey];
|
|
624
|
+
return {
|
|
625
|
+
ok: false,
|
|
626
|
+
status: 410,
|
|
627
|
+
code: "integration_delegated",
|
|
628
|
+
message: delegatedMailIntegrationMessage(gatedIntegrationKey, state.delegatedBackend ?? null),
|
|
629
|
+
integration: gatedIntegrationKey,
|
|
630
|
+
backend: state.delegatedBackend ?? null,
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
// Single scope-gate check mirroring `passesScopeGate` used by the
|
|
634
|
+
// unified poller and `accounts.md` materialization. Clients get one
|
|
635
|
+
// error shape (`provider_not_enabled`) with a machine-readable `detail`
|
|
636
|
+
// field so dashboards can render a specific prompt without having to
|
|
637
|
+
// branch on three near-synonymous codes.
|
|
638
|
+
//
|
|
639
|
+
// Recovery endpoints (`POST /config/mail/app-password/:id/refresh`)
|
|
640
|
+
// intentionally bypass this gate by reading the account directly — users
|
|
641
|
+
// MUST be able to fix a degraded account. If you add new recovery flows,
|
|
642
|
+
// keep that property: never route recovery through `resolveProvider`.
|
|
643
|
+
const detail = !deps.config.enabledMailProviders.includes(account.kind)
|
|
644
|
+
? "kind_not_enabled"
|
|
645
|
+
: !account.active
|
|
646
|
+
? "account_inactive"
|
|
647
|
+
: account.authStatus !== "healthy"
|
|
648
|
+
? "account_unhealthy"
|
|
649
|
+
: null;
|
|
650
|
+
if (detail !== null) {
|
|
651
|
+
const detailMessages = {
|
|
652
|
+
kind_not_enabled: `${account.kind} is not in enabledMailProviders.`,
|
|
653
|
+
account_inactive: `Mail account ${accountId} is disabled.`,
|
|
654
|
+
account_unhealthy: `Mail account ${accountId} requires re-auth (status: ${account.authStatus}).`,
|
|
655
|
+
};
|
|
656
|
+
return {
|
|
657
|
+
ok: false,
|
|
658
|
+
status: 400,
|
|
659
|
+
code: "provider_not_enabled",
|
|
660
|
+
message: detailMessages[detail],
|
|
661
|
+
detail,
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
try {
|
|
665
|
+
const provider = await registry.getProvider(accountId);
|
|
666
|
+
if (!provider) {
|
|
667
|
+
return {
|
|
668
|
+
ok: false,
|
|
669
|
+
status: 501,
|
|
670
|
+
code: "provider_not_implemented",
|
|
671
|
+
message: `Provider ${account.kind} is not wired up.`,
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
return { ok: true, provider };
|
|
675
|
+
}
|
|
676
|
+
catch (err) {
|
|
677
|
+
if (err instanceof ProviderNotImplementedError) {
|
|
678
|
+
return { ok: false, status: 501, code: err.code, message: err.message };
|
|
679
|
+
}
|
|
680
|
+
throw err;
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
// TTL is derived from the current poll interval so the tracker mark
|
|
684
|
+
// outlives at least one poll tick (see computeAgentWriteTtlMs). Read at
|
|
685
|
+
// mark-time — reflects a runtime PATCH /api/config without a restart.
|
|
686
|
+
const writeTtlMs = () => computeAgentWriteTtlMs(deps.config.mailPollIntervalSeconds);
|
|
687
|
+
const markAgentWrite = (accountId, providerMsgId) => {
|
|
688
|
+
deps.writeTracker?.markWriting(`mail:${accountId}:${providerMsgId}`, undefined, {
|
|
689
|
+
ttlMs: writeTtlMs(),
|
|
690
|
+
});
|
|
691
|
+
};
|
|
692
|
+
// INTEGRATION-DRIFT-DETECTION-PLAN.md §11 Phase 4 — actor attribution
|
|
693
|
+
// for the persistent `integration_writes` table. Only Gmail accounts
|
|
694
|
+
// map to an `IntegrationKey` (per `gatedIntegrationForKind`); iCloud /
|
|
695
|
+
// Outlook / Yahoo / IMAP have no integration descriptor and skip.
|
|
696
|
+
// Each id passed here is marked under `(gmail, id)` for the Gmail
|
|
697
|
+
// default TTL (30 min — see INTEGRATION_WRITE_TTL_MS). Non-Gmail
|
|
698
|
+
// accounts return a no-op; the in-memory `markAgentWrite` above is the
|
|
699
|
+
// only attribution surface for them.
|
|
700
|
+
const markGmailIntegrationWrite = (accountId, ...providerIds) => {
|
|
701
|
+
const registry = deps.services.mail;
|
|
702
|
+
if (!registry)
|
|
703
|
+
return;
|
|
704
|
+
const account = registry.getAccount(accountId);
|
|
705
|
+
if (!account)
|
|
706
|
+
return;
|
|
707
|
+
if (gatedIntegrationForKind(account.kind) !== "gmail")
|
|
708
|
+
return;
|
|
709
|
+
for (const id of providerIds) {
|
|
710
|
+
if (typeof id === "string" && id.length > 0) {
|
|
711
|
+
markIntegrationWrite(deps.db, "gmail", id);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
/**
|
|
716
|
+
* Second-key attribution via RFC-2822 Message-Id. On IMAP, the Sent folder
|
|
717
|
+
* UID the poller later observes has no relationship to the draft UID the
|
|
718
|
+
* route marked. The rfc822 key is stable across the transport path so the
|
|
719
|
+
* poller can still match. Providers that don't surface the id leave this
|
|
720
|
+
* a no-op (route treats undefined as "skip"). The poller is taught to
|
|
721
|
+
* check both keys (§MailPoller.pollAccount).
|
|
722
|
+
*/
|
|
723
|
+
const markAgentWriteRfc822 = (accountId, rfc822MsgId) => {
|
|
724
|
+
if (!rfc822MsgId)
|
|
725
|
+
return;
|
|
726
|
+
deps.writeTracker?.markWriting(`mail:${accountId}:rfc822:${rfc822MsgId}`, undefined, { ttlMs: writeTtlMs() });
|
|
727
|
+
};
|
|
728
|
+
const ensureMethod = (provider, method) => typeof provider[method] === "function";
|
|
729
|
+
/**
|
|
730
|
+
* Render a `resolveProvider` failure as an HTTP response. The 410
|
|
731
|
+
* branch carries the §4.5.2 `integration_delegated` body shape (integration,
|
|
732
|
+
* backend) so the dashboard and agent tooling can uniformly detect the
|
|
733
|
+
* delegated-mode surface regardless of whether the path was caught by the
|
|
734
|
+
* global route-gate middleware (§4.5.2) or the per-account gate here (§4.8).
|
|
735
|
+
*/
|
|
736
|
+
const renderResolveError = (c, resolved) => {
|
|
737
|
+
if (resolved.status === 410) {
|
|
738
|
+
return c.json({
|
|
739
|
+
error: resolved.code,
|
|
740
|
+
message: resolved.message,
|
|
741
|
+
integration: resolved.integration ?? null,
|
|
742
|
+
backend: resolved.backend ?? null,
|
|
743
|
+
mode: "delegated",
|
|
744
|
+
}, 410);
|
|
745
|
+
}
|
|
746
|
+
return c.json({
|
|
747
|
+
error: resolved.code,
|
|
748
|
+
message: resolved.message,
|
|
749
|
+
detail: resolved.detail,
|
|
750
|
+
}, resolved.status);
|
|
751
|
+
};
|
|
752
|
+
app.get("/mail/:accountId/health", (c) => {
|
|
753
|
+
const registry = deps.services.mail;
|
|
754
|
+
if (!registry)
|
|
755
|
+
return c.json({ error: "mail_not_configured" }, 503);
|
|
756
|
+
const accountId = c.req.param("accountId");
|
|
757
|
+
// §4.8 per-account delegated gate — also applies to /health so the
|
|
758
|
+
// dashboard does not surface a stale poll cursor for a Gmail account
|
|
759
|
+
// the daemon has stopped touching. Recovery endpoints (`POST
|
|
760
|
+
// /config/mail/app-password/:id/refresh`) stay outside this gate.
|
|
761
|
+
const account = registry.getAccount(accountId);
|
|
762
|
+
if (account) {
|
|
763
|
+
const gatedIntegrationKey = gatedIntegrationForKind(account.kind);
|
|
764
|
+
if (gatedIntegrationKey && isIntegrationDelegated(deps.db, gatedIntegrationKey)) {
|
|
765
|
+
const state = readIntegrations(deps.db)[gatedIntegrationKey];
|
|
766
|
+
return c.json({
|
|
767
|
+
error: "integration_delegated",
|
|
768
|
+
message: delegatedMailIntegrationMessage(gatedIntegrationKey, state.delegatedBackend ?? null),
|
|
769
|
+
integration: gatedIntegrationKey,
|
|
770
|
+
backend: state.delegatedBackend ?? null,
|
|
771
|
+
mode: "delegated",
|
|
772
|
+
}, 410);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
const health = registry.getHealth(accountId);
|
|
776
|
+
if (!health)
|
|
777
|
+
return c.json({ error: "not_found" }, 404);
|
|
778
|
+
return c.json(health);
|
|
779
|
+
});
|
|
780
|
+
app.get("/mail/:accountId/messages", async (c) => {
|
|
781
|
+
const accountId = c.req.param("accountId");
|
|
782
|
+
const resolved = await resolveProvider(accountId);
|
|
783
|
+
if (!resolved.ok)
|
|
784
|
+
return renderResolveError(c, resolved);
|
|
785
|
+
const limit = parseIntParam(c.req.query("limit"), 20, { min: 1, max: 100 });
|
|
786
|
+
try {
|
|
787
|
+
const messages = await resolved.provider.list({
|
|
788
|
+
folder: c.req.query("folder") ?? undefined,
|
|
789
|
+
q: c.req.query("q") ?? undefined,
|
|
790
|
+
limit,
|
|
791
|
+
since: c.req.query("since") ?? undefined,
|
|
792
|
+
unreadOnly: c.req.query("unreadOnly") === "true",
|
|
793
|
+
});
|
|
794
|
+
return c.json({ messages });
|
|
795
|
+
}
|
|
796
|
+
catch (err) {
|
|
797
|
+
return providerError(c, err, "list_failed");
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
app.get("/mail/:accountId/messages/:messageId", async (c) => {
|
|
801
|
+
const accountId = c.req.param("accountId");
|
|
802
|
+
const resolved = await resolveProvider(accountId);
|
|
803
|
+
if (!resolved.ok)
|
|
804
|
+
return renderResolveError(c, resolved);
|
|
805
|
+
const bodyMode = parseBodyMode(c.req.query("body"));
|
|
806
|
+
if (!bodyMode.ok)
|
|
807
|
+
return c.json(bodyMode.body, 400);
|
|
808
|
+
try {
|
|
809
|
+
const message = await resolved.provider.get(c.req.param("messageId"));
|
|
810
|
+
return c.json({ message: applyMailMessageBodyMode(message, bodyMode.value) });
|
|
811
|
+
}
|
|
812
|
+
catch (err) {
|
|
813
|
+
return providerError(c, err, "get_failed");
|
|
814
|
+
}
|
|
815
|
+
});
|
|
816
|
+
app.get("/mail/:accountId/messages/:messageId/body", async (c) => {
|
|
817
|
+
const resolved = await resolveProvider(c.req.param("accountId"));
|
|
818
|
+
if (!resolved.ok)
|
|
819
|
+
return renderResolveError(c, resolved);
|
|
820
|
+
const format = c.req.query("format") ?? "extracted";
|
|
821
|
+
if (format !== "extracted" && format !== "raw") {
|
|
822
|
+
return c.json({ error: "invalid_query", message: "format must be extracted or raw" }, 400);
|
|
823
|
+
}
|
|
824
|
+
const chunk = parseIntParam(c.req.query("chunk"), 0, { min: 0, max: 100_000 });
|
|
825
|
+
const maxChars = parseIntParam(c.req.query("maxChars"), MAIL_BODY_CHUNK_DEFAULT_CHARS, {
|
|
826
|
+
min: 1_000,
|
|
827
|
+
max: MAIL_BODY_CHUNK_MAX_CHARS,
|
|
828
|
+
});
|
|
829
|
+
const metadataOffset = parseIntParam(c.req.query("metadataOffset"), 0, {
|
|
830
|
+
min: 0,
|
|
831
|
+
max: 100_000,
|
|
832
|
+
});
|
|
833
|
+
const metadataLimit = parseIntParam(c.req.query("metadataLimit"), MAIL_BODY_METADATA_DEFAULT_LIMIT, { min: 1, max: MAIL_BODY_METADATA_MAX_LIMIT });
|
|
834
|
+
try {
|
|
835
|
+
const message = await resolved.provider.get(c.req.param("messageId"));
|
|
836
|
+
return c.json(buildMailBodyResponse({
|
|
837
|
+
accountId: c.req.param("accountId"),
|
|
838
|
+
message,
|
|
839
|
+
format,
|
|
840
|
+
chunk,
|
|
841
|
+
maxChars,
|
|
842
|
+
metadataOffset,
|
|
843
|
+
metadataLimit,
|
|
844
|
+
}));
|
|
845
|
+
}
|
|
846
|
+
catch (err) {
|
|
847
|
+
return providerError(c, err, "get_body_failed");
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
// /messages/send always *sends*. Draft creation has a dedicated endpoint
|
|
851
|
+
// (POST /mail/:id/drafts) so the path — not a body flag — determines the
|
|
852
|
+
// risk tier (§8). This avoids the "every draft DMs the owner" trap that
|
|
853
|
+
// body-aware classification would require.
|
|
854
|
+
app.post("/mail/:accountId/messages/send", async (c) => {
|
|
855
|
+
const accountId = c.req.param("accountId");
|
|
856
|
+
const parsedBody = await readJsonBody(c);
|
|
857
|
+
if (!parsedBody.ok)
|
|
858
|
+
return parsedBody.response;
|
|
859
|
+
const resolved = await resolveProvider(accountId);
|
|
860
|
+
if (!resolved.ok)
|
|
861
|
+
return renderResolveError(c, resolved);
|
|
862
|
+
const input = validateSendInput(parsedBody.body);
|
|
863
|
+
if (!input.ok)
|
|
864
|
+
return c.json({ error: input.code, message: input.message }, 400);
|
|
865
|
+
try {
|
|
866
|
+
const result = await resolved.provider.send({ ...input.value, draftOnly: false });
|
|
867
|
+
markAgentWrite(accountId, result.id);
|
|
868
|
+
markAgentWriteRfc822(accountId, result.rfc822MsgId);
|
|
869
|
+
// Phase 5 Gmail reconcile (`inbox:7d`) keys snapshots by threadId,
|
|
870
|
+
// so threadId is the load-bearing mark for actor attribution;
|
|
871
|
+
// messageId is kept as a forward-compat second key. GmailProvider
|
|
872
|
+
// surfaces threadId from `users.messages.send`'s response; IMAP /
|
|
873
|
+
// Outlook leave it undefined and only the messageId mark lands
|
|
874
|
+
// (those providers don't drive a reconcile path today, so a missed
|
|
875
|
+
// mark there is a no-op).
|
|
876
|
+
markGmailIntegrationWrite(accountId, result.id, result.threadId);
|
|
877
|
+
return c.json({ result });
|
|
878
|
+
}
|
|
879
|
+
catch (err) {
|
|
880
|
+
return providerError(c, err, "send_failed");
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
app.post("/mail/:accountId/messages/:messageId/read", async (c) => {
|
|
884
|
+
const accountId = c.req.param("accountId");
|
|
885
|
+
const messageId = c.req.param("messageId");
|
|
886
|
+
const resolved = await resolveProvider(accountId);
|
|
887
|
+
if (!resolved.ok)
|
|
888
|
+
return renderResolveError(c, resolved);
|
|
889
|
+
const parsedBody = await readJsonBody(c);
|
|
890
|
+
if (!parsedBody.ok)
|
|
891
|
+
return parsedBody.response;
|
|
892
|
+
const body = parsedBody.body;
|
|
893
|
+
const read = body?.read;
|
|
894
|
+
if (typeof read !== "boolean") {
|
|
895
|
+
return c.json({ error: "invalid_body", message: "read: boolean required" }, 400);
|
|
896
|
+
}
|
|
897
|
+
try {
|
|
898
|
+
await resolved.provider.markRead(messageId, read);
|
|
899
|
+
markAgentWrite(accountId, messageId);
|
|
900
|
+
return c.json({ status: "updated", read });
|
|
901
|
+
}
|
|
902
|
+
catch (err) {
|
|
903
|
+
return providerError(c, err, "mark_read_failed");
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
app.post("/mail/:accountId/messages/:messageId/trash", async (c) => {
|
|
907
|
+
const accountId = c.req.param("accountId");
|
|
908
|
+
const messageId = c.req.param("messageId");
|
|
909
|
+
const resolved = await resolveProvider(accountId);
|
|
910
|
+
if (!resolved.ok)
|
|
911
|
+
return renderResolveError(c, resolved);
|
|
912
|
+
try {
|
|
913
|
+
await resolved.provider.trash(messageId);
|
|
914
|
+
markAgentWrite(accountId, messageId);
|
|
915
|
+
return c.json({ status: "trashed" });
|
|
916
|
+
}
|
|
917
|
+
catch (err) {
|
|
918
|
+
return providerError(c, err, "trash_failed");
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
app.post("/mail/:accountId/messages/:messageId/untrash", async (c) => {
|
|
922
|
+
const accountId = c.req.param("accountId");
|
|
923
|
+
const messageId = c.req.param("messageId");
|
|
924
|
+
const resolved = await resolveProvider(accountId);
|
|
925
|
+
if (!resolved.ok)
|
|
926
|
+
return renderResolveError(c, resolved);
|
|
927
|
+
if (!ensureMethod(resolved.provider, "untrash")) {
|
|
928
|
+
return c.json({ error: "not_implemented", message: `untrash not supported on ${resolved.provider.kind}` }, 501);
|
|
929
|
+
}
|
|
930
|
+
try {
|
|
931
|
+
await resolved.provider.untrash(messageId);
|
|
932
|
+
markAgentWrite(accountId, messageId);
|
|
933
|
+
return c.json({ status: "untrashed" });
|
|
934
|
+
}
|
|
935
|
+
catch (err) {
|
|
936
|
+
return providerError(c, err, "untrash_failed");
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
app.post("/mail/:accountId/messages/:messageId/archive", async (c) => {
|
|
940
|
+
const accountId = c.req.param("accountId");
|
|
941
|
+
const messageId = c.req.param("messageId");
|
|
942
|
+
const resolved = await resolveProvider(accountId);
|
|
943
|
+
if (!resolved.ok)
|
|
944
|
+
return renderResolveError(c, resolved);
|
|
945
|
+
if (!ensureMethod(resolved.provider, "archive")) {
|
|
946
|
+
return c.json({ error: "not_implemented", message: `archive not supported on ${resolved.provider.kind}` }, 501);
|
|
947
|
+
}
|
|
948
|
+
try {
|
|
949
|
+
await resolved.provider.archive(messageId);
|
|
950
|
+
markAgentWrite(accountId, messageId);
|
|
951
|
+
return c.json({ status: "archived" });
|
|
952
|
+
}
|
|
953
|
+
catch (err) {
|
|
954
|
+
return providerError(c, err, "archive_failed");
|
|
955
|
+
}
|
|
956
|
+
});
|
|
957
|
+
app.post("/mail/:accountId/messages/:messageId/tags", async (c) => {
|
|
958
|
+
const accountId = c.req.param("accountId");
|
|
959
|
+
const messageId = c.req.param("messageId");
|
|
960
|
+
const parsedBody = await readJsonBody(c);
|
|
961
|
+
if (!parsedBody.ok)
|
|
962
|
+
return parsedBody.response;
|
|
963
|
+
const resolved = await resolveProvider(accountId);
|
|
964
|
+
if (!resolved.ok)
|
|
965
|
+
return renderResolveError(c, resolved);
|
|
966
|
+
const body = parsedBody.body;
|
|
967
|
+
const add = toStringArray(body?.add);
|
|
968
|
+
const remove = toStringArray(body?.remove);
|
|
969
|
+
if (!add || !remove) {
|
|
970
|
+
return c.json({ error: "invalid_body", message: "add: string[], remove: string[] required" }, 400);
|
|
971
|
+
}
|
|
972
|
+
try {
|
|
973
|
+
await resolved.provider.modifyTags(messageId, add, remove);
|
|
974
|
+
markAgentWrite(accountId, messageId);
|
|
975
|
+
return c.json({ status: "tags_updated", add, remove });
|
|
976
|
+
}
|
|
977
|
+
catch (err) {
|
|
978
|
+
return providerError(c, err, "modify_tags_failed");
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
app.get("/mail/:accountId/tags", async (c) => {
|
|
982
|
+
const accountId = c.req.param("accountId");
|
|
983
|
+
const resolved = await resolveProvider(accountId);
|
|
984
|
+
if (!resolved.ok)
|
|
985
|
+
return renderResolveError(c, resolved);
|
|
986
|
+
if (!ensureMethod(resolved.provider, "listTags")) {
|
|
987
|
+
// Minimal fallback: return empty catalog for providers that don't yet
|
|
988
|
+
// surface a tag list. Keeps callers from needing per-kind branching.
|
|
989
|
+
return c.json({ system: [], userDefined: [] });
|
|
990
|
+
}
|
|
991
|
+
try {
|
|
992
|
+
const catalog = await resolved.provider.listTags();
|
|
993
|
+
return c.json(catalog);
|
|
994
|
+
}
|
|
995
|
+
catch (err) {
|
|
996
|
+
return providerError(c, err, "list_tags_failed");
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
app.get("/mail/:accountId/folders", async (c) => {
|
|
1000
|
+
const resolved = await resolveProvider(c.req.param("accountId"));
|
|
1001
|
+
if (!resolved.ok)
|
|
1002
|
+
return renderResolveError(c, resolved);
|
|
1003
|
+
try {
|
|
1004
|
+
const folders = await resolved.provider.listFolders();
|
|
1005
|
+
return c.json({ folders });
|
|
1006
|
+
}
|
|
1007
|
+
catch (err) {
|
|
1008
|
+
return providerError(c, err, "list_folders_failed");
|
|
1009
|
+
}
|
|
1010
|
+
});
|
|
1011
|
+
app.get("/mail/:accountId/threads/:threadId", async (c) => {
|
|
1012
|
+
const accountId = c.req.param("accountId");
|
|
1013
|
+
const resolved = await resolveProvider(accountId);
|
|
1014
|
+
if (!resolved.ok)
|
|
1015
|
+
return renderResolveError(c, resolved);
|
|
1016
|
+
if (!ensureMethod(resolved.provider, "getThread")) {
|
|
1017
|
+
return c.json({ error: "not_implemented", message: `getThread not supported on ${resolved.provider.kind}` }, 501);
|
|
1018
|
+
}
|
|
1019
|
+
const bodyMode = parseBodyMode(c.req.query("body"));
|
|
1020
|
+
if (!bodyMode.ok)
|
|
1021
|
+
return c.json(bodyMode.body, 400);
|
|
1022
|
+
const limit = parseIntParam(c.req.query("limit"), 25, { min: 1, max: 100 });
|
|
1023
|
+
try {
|
|
1024
|
+
const thread = await resolved.provider.getThread(c.req.param("threadId"), limit);
|
|
1025
|
+
return c.json({ thread: applyThreadBodyMode(thread, bodyMode.value) });
|
|
1026
|
+
}
|
|
1027
|
+
catch (err) {
|
|
1028
|
+
return providerError(c, err, "get_thread_failed");
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
1031
|
+
app.get("/mail/:accountId/drafts", async (c) => {
|
|
1032
|
+
const accountId = c.req.param("accountId");
|
|
1033
|
+
const resolved = await resolveProvider(accountId);
|
|
1034
|
+
if (!resolved.ok)
|
|
1035
|
+
return renderResolveError(c, resolved);
|
|
1036
|
+
if (!ensureMethod(resolved.provider, "listDrafts")) {
|
|
1037
|
+
return c.json({ error: "not_implemented", message: `listDrafts not supported on ${resolved.provider.kind}` }, 501);
|
|
1038
|
+
}
|
|
1039
|
+
const limit = parseIntParam(c.req.query("limit"), 20, { min: 1, max: 100 });
|
|
1040
|
+
try {
|
|
1041
|
+
const drafts = await resolved.provider.listDrafts(limit);
|
|
1042
|
+
return c.json({ drafts });
|
|
1043
|
+
}
|
|
1044
|
+
catch (err) {
|
|
1045
|
+
return providerError(c, err, "list_drafts_failed");
|
|
1046
|
+
}
|
|
1047
|
+
});
|
|
1048
|
+
app.get("/mail/:accountId/drafts/:draftId", async (c) => {
|
|
1049
|
+
const resolved = await resolveProvider(c.req.param("accountId"));
|
|
1050
|
+
if (!resolved.ok)
|
|
1051
|
+
return renderResolveError(c, resolved);
|
|
1052
|
+
if (!ensureMethod(resolved.provider, "getDraft")) {
|
|
1053
|
+
return c.json({ error: "not_implemented", message: `getDraft not supported on ${resolved.provider.kind}` }, 501);
|
|
1054
|
+
}
|
|
1055
|
+
try {
|
|
1056
|
+
const draft = await resolved.provider.getDraft(c.req.param("draftId"));
|
|
1057
|
+
if (!draft)
|
|
1058
|
+
return c.json({ error: "not_found" }, 404);
|
|
1059
|
+
return c.json({ draft });
|
|
1060
|
+
}
|
|
1061
|
+
catch (err) {
|
|
1062
|
+
return providerError(c, err, "get_draft_failed");
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
app.post("/mail/:accountId/drafts", async (c) => {
|
|
1066
|
+
const accountId = c.req.param("accountId");
|
|
1067
|
+
const parsedBody = await readJsonBody(c);
|
|
1068
|
+
if (!parsedBody.ok)
|
|
1069
|
+
return parsedBody.response;
|
|
1070
|
+
const resolved = await resolveProvider(accountId);
|
|
1071
|
+
if (!resolved.ok)
|
|
1072
|
+
return renderResolveError(c, resolved);
|
|
1073
|
+
if (!ensureMethod(resolved.provider, "createDraft")) {
|
|
1074
|
+
return c.json({ error: "not_implemented", message: `createDraft not supported on ${resolved.provider.kind}` }, 501);
|
|
1075
|
+
}
|
|
1076
|
+
const input = validateSendInput(parsedBody.body);
|
|
1077
|
+
if (!input.ok)
|
|
1078
|
+
return c.json({ error: input.code, message: input.message }, 400);
|
|
1079
|
+
try {
|
|
1080
|
+
const result = await resolved.provider.createDraft(input.value);
|
|
1081
|
+
markAgentWrite(accountId, result.id);
|
|
1082
|
+
return c.json({ draftId: result.id });
|
|
1083
|
+
}
|
|
1084
|
+
catch (err) {
|
|
1085
|
+
return providerError(c, err, "create_draft_failed");
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
app.patch("/mail/:accountId/drafts/:draftId", async (c) => {
|
|
1089
|
+
const accountId = c.req.param("accountId");
|
|
1090
|
+
const draftId = c.req.param("draftId");
|
|
1091
|
+
const resolved = await resolveProvider(accountId);
|
|
1092
|
+
if (!resolved.ok)
|
|
1093
|
+
return renderResolveError(c, resolved);
|
|
1094
|
+
if (!ensureMethod(resolved.provider, "updateDraft")) {
|
|
1095
|
+
return c.json({ error: "not_implemented", message: `updateDraft not supported on ${resolved.provider.kind}` }, 501);
|
|
1096
|
+
}
|
|
1097
|
+
const parsedBody = await readJsonBody(c);
|
|
1098
|
+
if (!parsedBody.ok)
|
|
1099
|
+
return parsedBody.response;
|
|
1100
|
+
const input = validateUpdateDraftInput(parsedBody.body);
|
|
1101
|
+
if (!input.ok)
|
|
1102
|
+
return c.json({ error: input.code, message: input.message }, 400);
|
|
1103
|
+
try {
|
|
1104
|
+
const result = await resolved.provider.updateDraft(draftId, input.value);
|
|
1105
|
+
markAgentWrite(accountId, result.id);
|
|
1106
|
+
if (result.previousId)
|
|
1107
|
+
markAgentWrite(accountId, result.previousId);
|
|
1108
|
+
// `warnings` surface provider-specific caveats (e.g. Outlook's
|
|
1109
|
+
// reply-threading immutability). Agents need to see them — dropping
|
|
1110
|
+
// them would make the UpdateDraftResult.warnings field a no-op.
|
|
1111
|
+
return c.json({
|
|
1112
|
+
status: "updated",
|
|
1113
|
+
id: result.id,
|
|
1114
|
+
previousId: result.previousId,
|
|
1115
|
+
warnings: result.warnings,
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
catch (err) {
|
|
1119
|
+
return providerError(c, err, "update_draft_failed");
|
|
1120
|
+
}
|
|
1121
|
+
});
|
|
1122
|
+
app.delete("/mail/:accountId/drafts/:draftId", async (c) => {
|
|
1123
|
+
const accountId = c.req.param("accountId");
|
|
1124
|
+
const draftId = c.req.param("draftId");
|
|
1125
|
+
const resolved = await resolveProvider(accountId);
|
|
1126
|
+
if (!resolved.ok)
|
|
1127
|
+
return renderResolveError(c, resolved);
|
|
1128
|
+
if (!ensureMethod(resolved.provider, "deleteDraft")) {
|
|
1129
|
+
return c.json({ error: "not_implemented", message: `deleteDraft not supported on ${resolved.provider.kind}` }, 501);
|
|
1130
|
+
}
|
|
1131
|
+
try {
|
|
1132
|
+
await resolved.provider.deleteDraft(draftId);
|
|
1133
|
+
markAgentWrite(accountId, draftId);
|
|
1134
|
+
return c.json({ status: "deleted" });
|
|
1135
|
+
}
|
|
1136
|
+
catch (err) {
|
|
1137
|
+
return providerError(c, err, "delete_draft_failed");
|
|
1138
|
+
}
|
|
1139
|
+
});
|
|
1140
|
+
app.post("/mail/:accountId/drafts/:draftId/send", async (c) => {
|
|
1141
|
+
const accountId = c.req.param("accountId");
|
|
1142
|
+
const draftId = c.req.param("draftId");
|
|
1143
|
+
const resolved = await resolveProvider(accountId);
|
|
1144
|
+
if (!resolved.ok)
|
|
1145
|
+
return renderResolveError(c, resolved);
|
|
1146
|
+
if (!ensureMethod(resolved.provider, "sendDraft")) {
|
|
1147
|
+
return c.json({ error: "not_implemented", message: `sendDraft not supported on ${resolved.provider.kind}` }, 501);
|
|
1148
|
+
}
|
|
1149
|
+
try {
|
|
1150
|
+
const result = await resolved.provider.sendDraft(draftId);
|
|
1151
|
+
markAgentWrite(accountId, result.id);
|
|
1152
|
+
// sendDraft is a surface-area subset of send(); if the provider
|
|
1153
|
+
// surfaces the rfc822 Message-Id, it flows through the same field.
|
|
1154
|
+
const rfc = result.rfc822MsgId;
|
|
1155
|
+
markAgentWriteRfc822(accountId, rfc);
|
|
1156
|
+
markGmailIntegrationWrite(accountId, result.id, result.threadId);
|
|
1157
|
+
return c.json({ status: "sent", id: result.id, threadId: result.threadId });
|
|
1158
|
+
}
|
|
1159
|
+
catch (err) {
|
|
1160
|
+
return providerError(c, err, "send_draft_failed");
|
|
1161
|
+
}
|
|
1162
|
+
});
|
|
1163
|
+
return app;
|
|
1164
|
+
}
|
|
1165
|
+
function getErrorResponseCode(err) {
|
|
1166
|
+
const candidate = err?.responseCode;
|
|
1167
|
+
return typeof candidate === "number" ? candidate : null;
|
|
1168
|
+
}
|
|
1169
|
+
// ImapFlow sets err.message to the generic "Command failed" and puts the
|
|
1170
|
+
// actual IMAP server response code in serverResponseCode (e.g. "AUTHENTICATIONFAILED")
|
|
1171
|
+
// and the human text in responseText. Concatenate all three so that the
|
|
1172
|
+
// classifyImapAuthFailure patterns can match the real server response.
|
|
1173
|
+
function getImapErrorMessage(err) {
|
|
1174
|
+
if (!(err instanceof Error))
|
|
1175
|
+
return String(err);
|
|
1176
|
+
const e = err;
|
|
1177
|
+
return [err.message, e.serverResponseCode, e.responseText].filter(Boolean).join(" ");
|
|
1178
|
+
}
|
|
1179
|
+
function parseIntParam(raw, fallback, bounds) {
|
|
1180
|
+
if (!raw)
|
|
1181
|
+
return fallback;
|
|
1182
|
+
const n = Number.parseInt(raw, 10);
|
|
1183
|
+
if (!Number.isFinite(n))
|
|
1184
|
+
return fallback;
|
|
1185
|
+
return Math.max(bounds.min, Math.min(bounds.max, n));
|
|
1186
|
+
}
|
|
1187
|
+
function toStringArray(value) {
|
|
1188
|
+
if (value === undefined)
|
|
1189
|
+
return [];
|
|
1190
|
+
if (!Array.isArray(value))
|
|
1191
|
+
return null;
|
|
1192
|
+
if (value.every((v) => typeof v === "string"))
|
|
1193
|
+
return value;
|
|
1194
|
+
return null;
|
|
1195
|
+
}
|
|
1196
|
+
function buildMailBodyResponse(input) {
|
|
1197
|
+
const { message, format, chunk, maxChars, metadataOffset, metadataLimit } = input;
|
|
1198
|
+
const resolved = resolveMailBody(message, format);
|
|
1199
|
+
const totalChars = resolved.content.length;
|
|
1200
|
+
const start = chunk * maxChars;
|
|
1201
|
+
const end = start + maxChars;
|
|
1202
|
+
const content = start < totalChars ? resolved.content.slice(start, end) : "";
|
|
1203
|
+
const hasMore = end < totalChars;
|
|
1204
|
+
const links = resolved.links.slice(metadataOffset, metadataOffset + metadataLimit);
|
|
1205
|
+
const images = resolved.images.slice(metadataOffset, metadataOffset + metadataLimit);
|
|
1206
|
+
const linksHasMore = metadataOffset + metadataLimit < resolved.links.length;
|
|
1207
|
+
const imagesHasMore = metadataOffset + metadataLimit < resolved.images.length;
|
|
1208
|
+
return {
|
|
1209
|
+
accountId: input.accountId,
|
|
1210
|
+
providerMsgId: message.providerMsgId,
|
|
1211
|
+
rfc822MsgId: message.rfc822MsgId,
|
|
1212
|
+
threadId: message.threadId,
|
|
1213
|
+
subject: message.subject,
|
|
1214
|
+
format,
|
|
1215
|
+
source: resolved.source,
|
|
1216
|
+
content,
|
|
1217
|
+
chunk,
|
|
1218
|
+
maxChars,
|
|
1219
|
+
totalChars,
|
|
1220
|
+
hasMore,
|
|
1221
|
+
nextChunk: hasMore ? chunk + 1 : null,
|
|
1222
|
+
rawHtmlAvailable: typeof message.body.html === "string" && message.body.html.length > 0,
|
|
1223
|
+
rawTextAvailable: typeof message.body.text === "string" && message.body.text.length > 0,
|
|
1224
|
+
metadataOffset,
|
|
1225
|
+
metadataLimit,
|
|
1226
|
+
links,
|
|
1227
|
+
images,
|
|
1228
|
+
linkCount: resolved.links.length,
|
|
1229
|
+
imageCount: resolved.images.length,
|
|
1230
|
+
linksHasMore,
|
|
1231
|
+
imagesHasMore,
|
|
1232
|
+
nextMetadataOffset: linksHasMore || imagesHasMore
|
|
1233
|
+
? metadataOffset + metadataLimit
|
|
1234
|
+
: null,
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
function resolveMailBody(message, format) {
|
|
1238
|
+
const html = message.body.html;
|
|
1239
|
+
const text = message.body.text;
|
|
1240
|
+
if (format === "raw") {
|
|
1241
|
+
if (html)
|
|
1242
|
+
return { content: html, source: "html", links: [], images: [] };
|
|
1243
|
+
if (text)
|
|
1244
|
+
return { content: text, source: "text", links: [], images: [] };
|
|
1245
|
+
return { content: "", source: "empty", links: [], images: [] };
|
|
1246
|
+
}
|
|
1247
|
+
if (html) {
|
|
1248
|
+
const extracted = extractMailHtmlBody(html);
|
|
1249
|
+
return {
|
|
1250
|
+
content: renderExtractedMailHtmlBody(extracted),
|
|
1251
|
+
source: "html",
|
|
1252
|
+
links: extracted.links,
|
|
1253
|
+
images: extracted.images,
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
if (text)
|
|
1257
|
+
return { content: text, source: "text", links: [], images: [] };
|
|
1258
|
+
return { content: "", source: "empty", links: [], images: [] };
|
|
1259
|
+
}
|
|
1260
|
+
function parseBodyMode(raw) {
|
|
1261
|
+
if (raw === undefined || raw === "full")
|
|
1262
|
+
return { ok: true, value: "full" };
|
|
1263
|
+
if (raw === "none")
|
|
1264
|
+
return { ok: true, value: "none" };
|
|
1265
|
+
return {
|
|
1266
|
+
ok: false,
|
|
1267
|
+
body: { error: "invalid_query", message: "body must be full or none" },
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
function applyMailMessageBodyMode(message, mode) {
|
|
1271
|
+
if (mode === "full")
|
|
1272
|
+
return message;
|
|
1273
|
+
return { ...message, body: {} };
|
|
1274
|
+
}
|
|
1275
|
+
function applyThreadBodyMode(thread, mode) {
|
|
1276
|
+
if (mode === "full")
|
|
1277
|
+
return thread;
|
|
1278
|
+
return {
|
|
1279
|
+
...thread,
|
|
1280
|
+
messages: thread.messages.map((message) => applyMailMessageBodyMode(message, mode)),
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
function providerError(c, err, tag) {
|
|
1284
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1285
|
+
// Classify common provider errors where a 404 from the backend should not
|
|
1286
|
+
// become a 500 for the caller. The Graph client throws GraphError with a
|
|
1287
|
+
// httpStatus field; the IMAP layer throws Error with a responseCode.
|
|
1288
|
+
const candidate = err;
|
|
1289
|
+
const status = pickNumber(candidate.httpStatus) ??
|
|
1290
|
+
pickNumber(candidate.statusCode) ??
|
|
1291
|
+
pickNumber(candidate.response?.status);
|
|
1292
|
+
if (status === 404) {
|
|
1293
|
+
return c.json({ error: "not_found", message }, 404);
|
|
1294
|
+
}
|
|
1295
|
+
if (status === 501) {
|
|
1296
|
+
// Providers throw MailOperationNotSupportedError (httpStatus=501) when a
|
|
1297
|
+
// sub-case of an implemented method is out of scope — e.g. IMAP draft
|
|
1298
|
+
// writes. Map to the same shape as the missing-method-on-interface path
|
|
1299
|
+
// so callers can't distinguish the two (both mean "don't retry here").
|
|
1300
|
+
return c.json({ error: "not_implemented", message }, 501);
|
|
1301
|
+
}
|
|
1302
|
+
if (status === 401 || status === 403) {
|
|
1303
|
+
return c.json({ error: "provider_auth_error", message }, 502);
|
|
1304
|
+
}
|
|
1305
|
+
logger.error({ err, tag }, `mail route failure: ${tag}`);
|
|
1306
|
+
return c.json({ error: tag, message }, 500);
|
|
1307
|
+
}
|
|
1308
|
+
function pickNumber(value) {
|
|
1309
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1310
|
+
}
|
|
1311
|
+
function validateSendInput(body) {
|
|
1312
|
+
const raw = body;
|
|
1313
|
+
const to = toStringArray(raw?.to);
|
|
1314
|
+
if (!to || to.length === 0) {
|
|
1315
|
+
return { ok: false, code: "invalid_body", message: "to: non-empty string[] required" };
|
|
1316
|
+
}
|
|
1317
|
+
if (typeof raw.subject !== "string") {
|
|
1318
|
+
return { ok: false, code: "invalid_body", message: "subject: string required" };
|
|
1319
|
+
}
|
|
1320
|
+
const cc = raw.cc === undefined ? undefined : toStringArray(raw.cc);
|
|
1321
|
+
const bcc = raw.bcc === undefined ? undefined : toStringArray(raw.bcc);
|
|
1322
|
+
if (cc === null || bcc === null) {
|
|
1323
|
+
return { ok: false, code: "invalid_body", message: "cc/bcc must be string[] when present" };
|
|
1324
|
+
}
|
|
1325
|
+
const reply = parseReplyContext(raw.reply);
|
|
1326
|
+
if (reply === "invalid") {
|
|
1327
|
+
return {
|
|
1328
|
+
ok: false,
|
|
1329
|
+
code: "invalid_body",
|
|
1330
|
+
message: "reply requires inReplyToRfc822Id (string) and references (string[])",
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
return {
|
|
1334
|
+
ok: true,
|
|
1335
|
+
value: {
|
|
1336
|
+
to,
|
|
1337
|
+
cc,
|
|
1338
|
+
bcc,
|
|
1339
|
+
subject: raw.subject,
|
|
1340
|
+
textBody: typeof raw.textBody === "string" ? raw.textBody : undefined,
|
|
1341
|
+
htmlBody: typeof raw.htmlBody === "string" ? raw.htmlBody : undefined,
|
|
1342
|
+
reply,
|
|
1343
|
+
// `draftOnly` is intentionally NOT surfaced at the route boundary.
|
|
1344
|
+
// Drafts go through POST /mail/:id/drafts (Autonomous tier); sends
|
|
1345
|
+
// go through POST /mail/:id/messages/send (Notify tier). Body flags
|
|
1346
|
+
// cannot be classified by the path-prefix risk classifier.
|
|
1347
|
+
},
|
|
1348
|
+
};
|
|
1349
|
+
}
|
|
1350
|
+
function parseReplyContext(raw) {
|
|
1351
|
+
if (raw === undefined || raw === null)
|
|
1352
|
+
return undefined;
|
|
1353
|
+
if (typeof raw !== "object")
|
|
1354
|
+
return "invalid";
|
|
1355
|
+
const r = raw;
|
|
1356
|
+
if (typeof r.inReplyToRfc822Id !== "string")
|
|
1357
|
+
return "invalid";
|
|
1358
|
+
const refs = toStringArray(r.references);
|
|
1359
|
+
if (!refs)
|
|
1360
|
+
return "invalid";
|
|
1361
|
+
return {
|
|
1362
|
+
inReplyToRfc822Id: r.inReplyToRfc822Id,
|
|
1363
|
+
references: refs,
|
|
1364
|
+
providerThreadId: typeof r.providerThreadId === "string" ? r.providerThreadId : undefined,
|
|
1365
|
+
parentProviderMsgId: typeof r.parentProviderMsgId === "string" ? r.parentProviderMsgId : undefined,
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
function validateUpdateDraftInput(body) {
|
|
1369
|
+
const raw = body;
|
|
1370
|
+
const to = raw.to === undefined ? undefined : toStringArray(raw.to);
|
|
1371
|
+
const cc = raw.cc === undefined ? undefined : toStringArray(raw.cc);
|
|
1372
|
+
const bcc = raw.bcc === undefined ? undefined : toStringArray(raw.bcc);
|
|
1373
|
+
if (to === null || cc === null || bcc === null) {
|
|
1374
|
+
return { ok: false, code: "invalid_body", message: "to/cc/bcc must be string[] when present" };
|
|
1375
|
+
}
|
|
1376
|
+
// `reply` tri-state: undefined = leave existing threading; null = clear;
|
|
1377
|
+
// object = reshape (must include inReplyToRfc822Id + references).
|
|
1378
|
+
let reply;
|
|
1379
|
+
if (raw.reply === null) {
|
|
1380
|
+
reply = null;
|
|
1381
|
+
}
|
|
1382
|
+
else if (raw.reply !== undefined) {
|
|
1383
|
+
const parsed = parseReplyContext(raw.reply);
|
|
1384
|
+
if (parsed === "invalid") {
|
|
1385
|
+
return {
|
|
1386
|
+
ok: false,
|
|
1387
|
+
code: "invalid_body",
|
|
1388
|
+
message: "reply requires inReplyToRfc822Id (string) and references (string[]); pass null to clear",
|
|
1389
|
+
};
|
|
1390
|
+
}
|
|
1391
|
+
reply = parsed;
|
|
1392
|
+
}
|
|
1393
|
+
return {
|
|
1394
|
+
ok: true,
|
|
1395
|
+
value: {
|
|
1396
|
+
to,
|
|
1397
|
+
cc,
|
|
1398
|
+
bcc,
|
|
1399
|
+
subject: typeof raw.subject === "string" ? raw.subject : undefined,
|
|
1400
|
+
textBody: typeof raw.textBody === "string" ? raw.textBody : undefined,
|
|
1401
|
+
htmlBody: typeof raw.htmlBody === "string" ? raw.htmlBody : undefined,
|
|
1402
|
+
reply,
|
|
1403
|
+
},
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
//# sourceMappingURL=mail.js.map
|