@aitne/daemon 0.1.2 → 0.1.4

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.
Files changed (253) hide show
  1. package/LICENSE +21 -0
  2. package/dist/adapters/whatsapp-adapter.d.ts.map +1 -1
  3. package/dist/adapters/whatsapp-adapter.js +0 -1
  4. package/dist/adapters/whatsapp-adapter.js.map +1 -1
  5. package/dist/api/integration-route-gate.d.ts +15 -11
  6. package/dist/api/integration-route-gate.d.ts.map +1 -1
  7. package/dist/api/integration-route-gate.js +60 -23
  8. package/dist/api/integration-route-gate.js.map +1 -1
  9. package/dist/api/json-body.d.ts +22 -7
  10. package/dist/api/json-body.d.ts.map +1 -1
  11. package/dist/api/json-body.js +27 -8
  12. package/dist/api/json-body.js.map +1 -1
  13. package/dist/api/routes/agent.d.ts.map +1 -1
  14. package/dist/api/routes/agent.js +18 -0
  15. package/dist/api/routes/agent.js.map +1 -1
  16. package/dist/api/routes/backends.d.ts.map +1 -1
  17. package/dist/api/routes/backends.js +96 -1
  18. package/dist/api/routes/backends.js.map +1 -1
  19. package/dist/api/routes/books.js +1 -1
  20. package/dist/api/routes/books.js.map +1 -1
  21. package/dist/api/routes/context.d.ts.map +1 -1
  22. package/dist/api/routes/context.js +13 -1
  23. package/dist/api/routes/context.js.map +1 -1
  24. package/dist/api/routes/dashboard.d.ts.map +1 -1
  25. package/dist/api/routes/dashboard.js +75 -5
  26. package/dist/api/routes/dashboard.js.map +1 -1
  27. package/dist/api/routes/github.d.ts.map +1 -1
  28. package/dist/api/routes/github.js +38 -5
  29. package/dist/api/routes/github.js.map +1 -1
  30. package/dist/api/routes/integrations.d.ts +35 -6
  31. package/dist/api/routes/integrations.d.ts.map +1 -1
  32. package/dist/api/routes/integrations.js +191 -16
  33. package/dist/api/routes/integrations.js.map +1 -1
  34. package/dist/api/routes/mail.d.ts.map +1 -1
  35. package/dist/api/routes/mail.js +112 -46
  36. package/dist/api/routes/mail.js.map +1 -1
  37. package/dist/api/routes/observations.d.ts.map +1 -1
  38. package/dist/api/routes/observations.js +161 -8
  39. package/dist/api/routes/observations.js.map +1 -1
  40. package/dist/api/routes/setup-migrate.d.ts +9 -1
  41. package/dist/api/routes/setup-migrate.d.ts.map +1 -1
  42. package/dist/api/routes/setup-migrate.js +4 -2
  43. package/dist/api/routes/setup-migrate.js.map +1 -1
  44. package/dist/api/routes/skills.d.ts.map +1 -1
  45. package/dist/api/routes/skills.js +39 -1
  46. package/dist/api/routes/skills.js.map +1 -1
  47. package/dist/api/routes/voice.d.ts.map +1 -1
  48. package/dist/api/routes/voice.js +154 -14
  49. package/dist/api/routes/voice.js.map +1 -1
  50. package/dist/bootstrap/adapters.d.ts +109 -0
  51. package/dist/bootstrap/adapters.d.ts.map +1 -0
  52. package/dist/bootstrap/adapters.js +237 -0
  53. package/dist/bootstrap/adapters.js.map +1 -0
  54. package/dist/bootstrap/catchup.d.ts +23 -0
  55. package/dist/bootstrap/catchup.d.ts.map +1 -0
  56. package/dist/bootstrap/catchup.js +124 -0
  57. package/dist/bootstrap/catchup.js.map +1 -0
  58. package/dist/bootstrap/schedule-helpers.d.ts +18 -0
  59. package/dist/bootstrap/schedule-helpers.d.ts.map +1 -0
  60. package/dist/bootstrap/schedule-helpers.js +96 -0
  61. package/dist/bootstrap/schedule-helpers.js.map +1 -0
  62. package/dist/bootstrap/services.d.ts +60 -0
  63. package/dist/bootstrap/services.d.ts.map +1 -0
  64. package/dist/bootstrap/services.js +209 -0
  65. package/dist/bootstrap/services.js.map +1 -0
  66. package/dist/core/backends/backend-router.d.ts +23 -0
  67. package/dist/core/backends/backend-router.d.ts.map +1 -1
  68. package/dist/core/backends/backend-router.js +48 -3
  69. package/dist/core/backends/backend-router.js.map +1 -1
  70. package/dist/core/backends/claude-auth.d.ts +70 -0
  71. package/dist/core/backends/claude-auth.d.ts.map +1 -0
  72. package/dist/core/backends/claude-auth.js +198 -0
  73. package/dist/core/backends/claude-auth.js.map +1 -0
  74. package/dist/core/backends/claude-code-core.d.ts +47 -119
  75. package/dist/core/backends/claude-code-core.d.ts.map +1 -1
  76. package/dist/core/backends/claude-code-core.js +112 -1565
  77. package/dist/core/backends/claude-code-core.js.map +1 -1
  78. package/dist/core/backends/claude-delegated.d.ts +86 -0
  79. package/dist/core/backends/claude-delegated.d.ts.map +1 -0
  80. package/dist/core/backends/claude-delegated.js +801 -0
  81. package/dist/core/backends/claude-delegated.js.map +1 -0
  82. package/dist/core/backends/claude-errors.d.ts +39 -0
  83. package/dist/core/backends/claude-errors.d.ts.map +1 -0
  84. package/dist/core/backends/claude-errors.js +71 -0
  85. package/dist/core/backends/claude-errors.js.map +1 -0
  86. package/dist/core/backends/claude-probe.d.ts +103 -0
  87. package/dist/core/backends/claude-probe.d.ts.map +1 -0
  88. package/dist/core/backends/claude-probe.js +336 -0
  89. package/dist/core/backends/claude-probe.js.map +1 -0
  90. package/dist/core/backends/claude-tool-collection.d.ts +135 -0
  91. package/dist/core/backends/claude-tool-collection.d.ts.map +1 -0
  92. package/dist/core/backends/claude-tool-collection.js +831 -0
  93. package/dist/core/backends/claude-tool-collection.js.map +1 -0
  94. package/dist/core/backends/gemini-cli-core.d.ts +21 -0
  95. package/dist/core/backends/gemini-cli-core.d.ts.map +1 -1
  96. package/dist/core/backends/gemini-cli-core.js +84 -6
  97. package/dist/core/backends/gemini-cli-core.js.map +1 -1
  98. package/dist/core/backends/prompt-utils.d.ts +1 -0
  99. package/dist/core/backends/prompt-utils.d.ts.map +1 -1
  100. package/dist/core/backends/prompt-utils.js +60 -3
  101. package/dist/core/backends/prompt-utils.js.map +1 -1
  102. package/dist/core/context-builder.d.ts +36 -12
  103. package/dist/core/context-builder.d.ts.map +1 -1
  104. package/dist/core/context-builder.js +179 -89
  105. package/dist/core/context-builder.js.map +1 -1
  106. package/dist/core/dispatcher-date-utils.d.ts +49 -0
  107. package/dist/core/dispatcher-date-utils.d.ts.map +1 -0
  108. package/dist/core/dispatcher-date-utils.js +132 -0
  109. package/dist/core/dispatcher-date-utils.js.map +1 -0
  110. package/dist/core/dispatcher-error-handling.d.ts +159 -0
  111. package/dist/core/dispatcher-error-handling.d.ts.map +1 -0
  112. package/dist/core/dispatcher-error-handling.js +393 -0
  113. package/dist/core/dispatcher-error-handling.js.map +1 -0
  114. package/dist/core/dispatcher-hourly-check.d.ts +150 -0
  115. package/dist/core/dispatcher-hourly-check.d.ts.map +1 -0
  116. package/dist/core/dispatcher-hourly-check.js +665 -0
  117. package/dist/core/dispatcher-hourly-check.js.map +1 -0
  118. package/dist/core/dispatcher-message-handler.d.ts +170 -0
  119. package/dist/core/dispatcher-message-handler.d.ts.map +1 -0
  120. package/dist/core/dispatcher-message-handler.js +1054 -0
  121. package/dist/core/dispatcher-message-handler.js.map +1 -0
  122. package/dist/core/dispatcher-morning-routine.d.ts +169 -0
  123. package/dist/core/dispatcher-morning-routine.d.ts.map +1 -0
  124. package/dist/core/dispatcher-morning-routine.js +434 -0
  125. package/dist/core/dispatcher-morning-routine.js.map +1 -0
  126. package/dist/core/dispatcher-prompt.d.ts +107 -0
  127. package/dist/core/dispatcher-prompt.d.ts.map +1 -0
  128. package/dist/core/dispatcher-prompt.js +227 -0
  129. package/dist/core/dispatcher-prompt.js.map +1 -0
  130. package/dist/core/dispatcher-repository-helpers.d.ts +39 -0
  131. package/dist/core/dispatcher-repository-helpers.d.ts.map +1 -0
  132. package/dist/core/dispatcher-repository-helpers.js +86 -0
  133. package/dist/core/dispatcher-repository-helpers.js.map +1 -0
  134. package/dist/core/dispatcher-result-processor.d.ts +145 -0
  135. package/dist/core/dispatcher-result-processor.d.ts.map +1 -0
  136. package/dist/core/dispatcher-result-processor.js +414 -0
  137. package/dist/core/dispatcher-result-processor.js.map +1 -0
  138. package/dist/core/dispatcher-scheduled-tasks.d.ts +406 -0
  139. package/dist/core/dispatcher-scheduled-tasks.d.ts.map +1 -0
  140. package/dist/core/dispatcher-scheduled-tasks.js +998 -0
  141. package/dist/core/dispatcher-scheduled-tasks.js.map +1 -0
  142. package/dist/core/dispatcher-types.d.ts +296 -0
  143. package/dist/core/dispatcher-types.d.ts.map +1 -0
  144. package/dist/core/dispatcher-types.js +106 -0
  145. package/dist/core/dispatcher-types.js.map +1 -0
  146. package/dist/core/dispatcher.d.ts +86 -610
  147. package/dist/core/dispatcher.d.ts.map +1 -1
  148. package/dist/core/dispatcher.js +293 -3542
  149. package/dist/core/dispatcher.js.map +1 -1
  150. package/dist/core/integration-health.d.ts +18 -10
  151. package/dist/core/integration-health.d.ts.map +1 -1
  152. package/dist/core/integration-health.js +31 -1
  153. package/dist/core/integration-health.js.map +1 -1
  154. package/dist/core/integration-lifecycle.d.ts +65 -0
  155. package/dist/core/integration-lifecycle.d.ts.map +1 -1
  156. package/dist/core/integration-lifecycle.js +167 -16
  157. package/dist/core/integration-lifecycle.js.map +1 -1
  158. package/dist/core/integration-main-backend.d.ts +40 -0
  159. package/dist/core/integration-main-backend.d.ts.map +1 -1
  160. package/dist/core/integration-main-backend.js +89 -2
  161. package/dist/core/integration-main-backend.js.map +1 -1
  162. package/dist/core/management-md.d.ts +51 -17
  163. package/dist/core/management-md.d.ts.map +1 -1
  164. package/dist/core/management-md.js +233 -56
  165. package/dist/core/management-md.js.map +1 -1
  166. package/dist/core/output-language-policy.d.ts +74 -0
  167. package/dist/core/output-language-policy.d.ts.map +1 -0
  168. package/dist/core/output-language-policy.js +194 -0
  169. package/dist/core/output-language-policy.js.map +1 -0
  170. package/dist/core/prompts.d.ts +1 -0
  171. package/dist/core/prompts.d.ts.map +1 -1
  172. package/dist/core/prompts.js +121 -3
  173. package/dist/core/prompts.js.map +1 -1
  174. package/dist/core/repository-management-docs.d.ts +24 -0
  175. package/dist/core/repository-management-docs.d.ts.map +1 -1
  176. package/dist/core/repository-management-docs.js +210 -26
  177. package/dist/core/repository-management-docs.js.map +1 -1
  178. package/dist/core/routine-acquisition-plan.d.ts +131 -0
  179. package/dist/core/routine-acquisition-plan.d.ts.map +1 -0
  180. package/dist/core/routine-acquisition-plan.js +268 -0
  181. package/dist/core/routine-acquisition-plan.js.map +1 -0
  182. package/dist/core/routine-fetch-window-runner.d.ts +201 -0
  183. package/dist/core/routine-fetch-window-runner.d.ts.map +1 -0
  184. package/dist/core/routine-fetch-window-runner.js +661 -0
  185. package/dist/core/routine-fetch-window-runner.js.map +1 -0
  186. package/dist/core/routine-windows.d.ts +156 -0
  187. package/dist/core/routine-windows.d.ts.map +1 -0
  188. package/dist/core/routine-windows.js +330 -0
  189. package/dist/core/routine-windows.js.map +1 -0
  190. package/dist/core/skills-compiler.d.ts +11 -0
  191. package/dist/core/skills-compiler.d.ts.map +1 -1
  192. package/dist/core/skills-compiler.js +102 -13
  193. package/dist/core/skills-compiler.js.map +1 -1
  194. package/dist/core/skills-manifest.d.ts.map +1 -1
  195. package/dist/core/skills-manifest.js +26 -0
  196. package/dist/core/skills-manifest.js.map +1 -1
  197. package/dist/core/system-reset.d.ts.map +1 -1
  198. package/dist/core/system-reset.js +25 -2
  199. package/dist/core/system-reset.js.map +1 -1
  200. package/dist/db/observations.d.ts +45 -2
  201. package/dist/db/observations.d.ts.map +1 -1
  202. package/dist/db/observations.js +112 -14
  203. package/dist/db/observations.js.map +1 -1
  204. package/dist/db/schema.d.ts.map +1 -1
  205. package/dist/db/schema.js +13 -25
  206. package/dist/db/schema.js.map +1 -1
  207. package/dist/index.js +83 -610
  208. package/dist/index.js.map +1 -1
  209. package/dist/observers/delegated-sync-worker.d.ts +45 -2
  210. package/dist/observers/delegated-sync-worker.d.ts.map +1 -1
  211. package/dist/observers/delegated-sync-worker.js +71 -21
  212. package/dist/observers/delegated-sync-worker.js.map +1 -1
  213. package/dist/observers/mail-poller.d.ts +12 -5
  214. package/dist/observers/mail-poller.d.ts.map +1 -1
  215. package/dist/observers/mail-poller.js +36 -14
  216. package/dist/observers/mail-poller.js.map +1 -1
  217. package/dist/observers/manager.d.ts +37 -5
  218. package/dist/observers/manager.d.ts.map +1 -1
  219. package/dist/observers/manager.js +28 -10
  220. package/dist/observers/manager.js.map +1 -1
  221. package/dist/safety/risk-classifier.d.ts.map +1 -1
  222. package/dist/safety/risk-classifier.js +5 -0
  223. package/dist/safety/risk-classifier.js.map +1 -1
  224. package/dist/services/delegated-backend-invoker.d.ts +1 -51
  225. package/dist/services/delegated-backend-invoker.d.ts.map +1 -1
  226. package/dist/services/delegated-backend-invoker.js +41 -480
  227. package/dist/services/delegated-backend-invoker.js.map +1 -1
  228. package/dist/services/delegated-invoker-audit.d.ts +94 -0
  229. package/dist/services/delegated-invoker-audit.d.ts.map +1 -0
  230. package/dist/services/delegated-invoker-audit.js +238 -0
  231. package/dist/services/delegated-invoker-audit.js.map +1 -0
  232. package/dist/services/delegated-invoker-cache-hits.d.ts +34 -0
  233. package/dist/services/delegated-invoker-cache-hits.d.ts.map +1 -0
  234. package/dist/services/delegated-invoker-cache-hits.js +104 -0
  235. package/dist/services/delegated-invoker-cache-hits.js.map +1 -0
  236. package/dist/services/delegated-invoker-janitors.d.ts +28 -0
  237. package/dist/services/delegated-invoker-janitors.d.ts.map +1 -0
  238. package/dist/services/delegated-invoker-janitors.js +104 -0
  239. package/dist/services/delegated-invoker-janitors.js.map +1 -0
  240. package/dist/services/delegated-invoker-utils.d.ts +42 -0
  241. package/dist/services/delegated-invoker-utils.d.ts.map +1 -0
  242. package/dist/services/delegated-invoker-utils.js +100 -0
  243. package/dist/services/delegated-invoker-utils.js.map +1 -0
  244. package/dist/services/delegated-task-runtime.d.ts +1 -1
  245. package/dist/services/delegated-task-runtime.js +1 -1
  246. package/dist/services/integrations/snapshot-partitions.d.ts +5 -0
  247. package/dist/services/integrations/snapshot-partitions.d.ts.map +1 -1
  248. package/dist/services/integrations/snapshot-partitions.js +12 -0
  249. package/dist/services/integrations/snapshot-partitions.js.map +1 -1
  250. package/dist/services/voice/transcriber-impl.d.ts.map +1 -1
  251. package/dist/services/voice/transcriber-impl.js +46 -0
  252. package/dist/services/voice/transcriber-impl.js.map +1 -1
  253. package/package.json +12 -12
@@ -0,0 +1,268 @@
1
+ /**
2
+ * `<acquisition-plan>` block assembly for the routine pre-pass fetcher.
3
+ *
4
+ * ROUTINE_DATA_ACQUISITION_DESIGN.md §6.4 / F5 — pure helper that the
5
+ * routine dispatchers (Phase 4) call to render the XML block the
6
+ * `routine.fetch_window` session reads. Stays I/O-free so it can be
7
+ * tested in isolation against synthetic integration state.
8
+ *
9
+ * The block lists one `<fetch>` element per (integration × mode × account)
10
+ * combination implied by `ROUTINE_WINDOWS[routine]` and the current
11
+ * integration state. Disabled integrations, unmapped query cells, and
12
+ * native bindings whose backend does not match the session are skipped.
13
+ *
14
+ * Output shape (§6.4 example, but with substituted timestamps and the
15
+ * resolved mode-suffix the partial filters on):
16
+ *
17
+ * ```xml
18
+ * <acquisition-plan routine="morning_routine" agent_day="2026-05-11">
19
+ * <fetch integration="gmail" mode="direct" window="inbox_today"
20
+ * account="alice@gmail.com" query="?days=1&amp;limit=20" />
21
+ * ...
22
+ * </acquisition-plan>
23
+ * ```
24
+ */
25
+ import { getAgentDayBoundsUtc, getIntegrationDescriptor, parseSqliteUtcMs, } from "@aitne/shared";
26
+ import { ROUTINE_WINDOWS, WINDOW_QUERIES, } from "./routine-windows.js";
27
+ /**
28
+ * Compute the timestamp set the assembly helper uses. Anchors to the
29
+ * agent-day boundary `dayBoundaryHour` (configurable; the daemon's
30
+ * config default is 4 = 04:00 local per CLAUDE.md), so
31
+ * `day_start_iso` matches the same UTC instant `getAgentDayBoundsUtc`
32
+ * uses everywhere else in the daemon.
33
+ *
34
+ * The parameter has no built-in default — callers MUST thread
35
+ * `config.dayBoundaryHour` through so a future config change does not
36
+ * silently desync this layer from the rest of the daemon. Tests can
37
+ * pass `0` for stable arithmetic against a UTC fixture.
38
+ */
39
+ export function buildAcquisitionTimestamps(now, timezone, dayBoundaryHour) {
40
+ const bounds = getAgentDayBoundsUtc(timezone, dayBoundaryHour, now);
41
+ const dayStartMs = parseSqliteUtcMs(bounds.start);
42
+ const dayEndMs = dayStartMs + 24 * 60 * 60 * 1000;
43
+ const day48Ms = dayStartMs + 48 * 60 * 60 * 1000;
44
+ const weekStartMs = dayStartMs - 7 * 24 * 60 * 60 * 1000;
45
+ const weekEndMs = dayStartMs + 7 * 24 * 60 * 60 * 1000;
46
+ const monthEndMs = dayStartMs + 30 * 24 * 60 * 60 * 1000;
47
+ const nowMs = now.getTime();
48
+ const hourStartMs = nowMs - (nowMs % (60 * 60 * 1000));
49
+ const plus2hMs = nowMs + 2 * 60 * 60 * 1000;
50
+ const dateOnly = (ms) => new Date(ms).toISOString().slice(0, 10);
51
+ return {
52
+ now_iso: new Date(nowMs).toISOString(),
53
+ hour_start_iso: new Date(hourStartMs).toISOString(),
54
+ day_start_iso: new Date(dayStartMs).toISOString(),
55
+ day_end_iso: new Date(dayEndMs).toISOString(),
56
+ day_plus_24h: new Date(dayEndMs).toISOString(),
57
+ day_plus_48h: new Date(day48Ms).toISOString(),
58
+ day_plus_2h: new Date(plus2hMs).toISOString(),
59
+ week_start_iso: new Date(weekStartMs).toISOString(),
60
+ week_end_iso: new Date(weekEndMs).toISOString(),
61
+ month_end_iso: new Date(monthEndMs).toISOString(),
62
+ day_start_date: dateOnly(dayStartMs),
63
+ week_start_date: dateOnly(weekStartMs),
64
+ now_date: dateOnly(nowMs),
65
+ };
66
+ }
67
+ // ── Internal helpers ───────────────────────────────────────────────────────
68
+ /**
69
+ * The integrations a window symbol applies to. Used to map a routine's
70
+ * `RoutineWindowSpec.kind` onto concrete integration keys. Walking
71
+ * `WINDOW_QUERIES[symbol]` keeps the catalog as the single source of
72
+ * truth — no hardcoded "mail → gmail+outlook_mail" mapping here.
73
+ */
74
+ function integrationsForWindow(symbol) {
75
+ return Object.keys(WINDOW_QUERIES[symbol] ?? {});
76
+ }
77
+ /**
78
+ * Resolve the integration's runtime mode to the predicate string the
79
+ * partial filters on. Returns `null` when the row should be skipped
80
+ * (disabled, missing state, native binding on a different backend).
81
+ *
82
+ * §6.8 / §3 glossary — for `userManagedConnector` integrations
83
+ * (today: `outlook_mail`, `outlook_calendar`) the daemon ships no
84
+ * `/api/integrations/<key>/exec` proxy, so `delegated-cross` is
85
+ * unreachable. The dispatcher MUST collapse cross-backend delegated to
86
+ * `delegated-same` for these descriptors — the only viable path is
87
+ * the session backend's own MCP, identical to same-backend. Without
88
+ * this collapse, the partial's `delegated-cross` defensive guard
89
+ * fires every tick instead of remaining dormant.
90
+ */
91
+ function resolveFetchMode(integration, state, sessionBackend) {
92
+ if (!state)
93
+ return null;
94
+ switch (state.mode) {
95
+ case "direct":
96
+ return "direct";
97
+ case "delegated":
98
+ if (state.delegatedBackend === sessionBackend) {
99
+ return "delegated-same";
100
+ }
101
+ // Cross-backend delegated requires a non-null `delegatedBackend`.
102
+ // Missing binding ≈ misconfiguration → skip.
103
+ if (state.delegatedBackend !== null
104
+ && state.delegatedBackend !== undefined) {
105
+ // User-managed integrations have no daemon proxy; collapse to
106
+ // same-backend so the partial body's main delegated-same prose
107
+ // runs instead of its defensive delegated-cross fallback.
108
+ if (getIntegrationDescriptor(integration).userManagedConnector === true) {
109
+ return "delegated-same";
110
+ }
111
+ return "delegated-cross";
112
+ }
113
+ return null;
114
+ case "native":
115
+ // Native binding must match the session backend. Otherwise the
116
+ // partial's `mode:native:<key>` block would be filtered out by
117
+ // `applyIntegrationModeFilter` anyway — skip the row to avoid
118
+ // emitting a `<fetch>` that no branch can handle.
119
+ if (state.nativeBackend === sessionBackend)
120
+ return "native";
121
+ return null;
122
+ case "disabled":
123
+ return null;
124
+ default:
125
+ return null;
126
+ }
127
+ }
128
+ /**
129
+ * Resolve the WINDOW_QUERIES cell for a (symbol, integration, mode)
130
+ * tuple. delegated-same / delegated-cross both look up "delegated" in
131
+ * the catalog; the predicate distinction is only meaningful at the
132
+ * partial-filtering layer.
133
+ */
134
+ function lookupQuery(symbol, integration, fetchMode) {
135
+ const catalog = WINDOW_QUERIES[symbol]?.[integration];
136
+ if (!catalog)
137
+ return undefined;
138
+ if (fetchMode === "delegated-same" || fetchMode === "delegated-cross") {
139
+ return catalog.delegated;
140
+ }
141
+ return catalog[fetchMode];
142
+ }
143
+ /**
144
+ * Substitute `{token}` placeholders in a query string with the
145
+ * pre-computed timestamps. Unknown tokens are left verbatim — they will
146
+ * surface as `{foo}` in the rendered prompt, which is visible failure
147
+ * (the partial author can grep for `{` in their query).
148
+ */
149
+ export function substituteAcquisitionTokens(query, timestamps) {
150
+ return query.replace(/\{([a-z_][a-z0-9_]*)\}/g, (match, name) => {
151
+ const value = timestamps[name];
152
+ return value ?? match;
153
+ });
154
+ }
155
+ /**
156
+ * Attribute escaping for non-query `<fetch>` attribute values
157
+ * (`integration`, `mode`, `window`, `account`, `label`, and the
158
+ * block's `routine` / `agent_day`). These are short tokens drawn
159
+ * from controlled vocabularies; the conventional XML escape set
160
+ * keeps them robust against future authors who slip a special
161
+ * character in.
162
+ */
163
+ function xmlAttr(value) {
164
+ return value
165
+ .replace(/&/g, "&amp;")
166
+ .replace(/"/g, "&quot;")
167
+ .replace(/</g, "&lt;")
168
+ .replace(/>/g, "&gt;");
169
+ }
170
+ /**
171
+ * Escaping for the `<fetch query='…'>` attribute, which uses
172
+ * single-quote delimiters so URL query strings can be rendered
173
+ * verbatim.
174
+ *
175
+ * The consumer of this block is the LLM, not an XML parser — the
176
+ * agent is told to use the `query` attribute literally as a URL
177
+ * query string (`GET .../messages<query>`) or as MCP-tool arguments
178
+ * (`q="newer_than:1d"`). Two characters in our catalog would
179
+ * otherwise need entity-decode steps the agent must remember:
180
+ * - `&` separates URL query parameters (`?a=1&b=2`),
181
+ * - `"` wraps Gmail / Calendar MCP query expressions
182
+ * (`q="newer_than:1d"`, `timeMin="…"`).
183
+ *
184
+ * Single-quote delimiters let us keep both literal. The only
185
+ * character that would now break the attribute structure is `'`,
186
+ * which no query in `WINDOW_QUERIES` uses today. We escape `'` and
187
+ * `<` / `>` defensively for any future catalog author who uses
188
+ * them.
189
+ */
190
+ function xmlQueryAttr(value) {
191
+ return value
192
+ .replace(/'/g, "&apos;")
193
+ .replace(/</g, "&lt;")
194
+ .replace(/>/g, "&gt;");
195
+ }
196
+ function renderFetchRow(row) {
197
+ const parts = [
198
+ `integration="${xmlAttr(row.integration)}"`,
199
+ `mode="${xmlAttr(row.mode)}"`,
200
+ `window="${xmlAttr(row.window)}"`,
201
+ ];
202
+ if (row.accountId !== undefined) {
203
+ parts.push(`account="${xmlAttr(row.accountId)}"`);
204
+ }
205
+ if (row.label !== undefined) {
206
+ parts.push(`label="${xmlAttr(row.label)}"`);
207
+ }
208
+ // Single-quote delimiter on `query=` — see `xmlQueryAttr` rationale.
209
+ parts.push(`query='${xmlQueryAttr(row.query)}'`);
210
+ return ` <fetch ${parts.join(" ")} />`;
211
+ }
212
+ // ── Public entry point ────────────────────────────────────────────────────
213
+ /**
214
+ * Build the `<acquisition-plan>` block string for a routine.
215
+ *
216
+ * Pure function: deterministic for a given input. Returns the rendered
217
+ * XML even when no rows survive — an empty plan still gives the
218
+ * pre-pass an explicit "nothing to do" signal rather than the absence
219
+ * of a block.
220
+ */
221
+ export function buildAcquisitionPlan(input) {
222
+ const rows = [];
223
+ const specs = ROUTINE_WINDOWS[input.routine];
224
+ for (const spec of specs) {
225
+ const integrations = integrationsForWindow(spec.window);
226
+ for (const integration of integrations) {
227
+ const state = input.integrations[integration];
228
+ const fetchMode = resolveFetchMode(integration, state, input.sessionBackend);
229
+ if (fetchMode === null)
230
+ continue;
231
+ const queryTemplate = lookupQuery(spec.window, integration, fetchMode);
232
+ if (queryTemplate === undefined)
233
+ continue;
234
+ const query = substituteAcquisitionTokens(queryTemplate, input.timestamps);
235
+ if (spec.perAccount) {
236
+ const accountRows = input.accounts.filter((a) => a.integration === integration);
237
+ for (const account of accountRows) {
238
+ rows.push({
239
+ integration,
240
+ mode: fetchMode,
241
+ window: spec.window,
242
+ accountId: account.accountId,
243
+ label: account.label,
244
+ query,
245
+ });
246
+ }
247
+ }
248
+ else {
249
+ rows.push({
250
+ integration,
251
+ mode: fetchMode,
252
+ window: spec.window,
253
+ query,
254
+ });
255
+ }
256
+ }
257
+ }
258
+ // Strip the `routine.` prefix in the attribute for compactness; the
259
+ // surrounding daemon log carries the full ProcessKey.
260
+ const routineAttr = input.routine.replace(/^routine\./, "");
261
+ const lines = [
262
+ `<acquisition-plan routine="${xmlAttr(routineAttr)}" agent_day="${xmlAttr(input.agentDay)}">`,
263
+ ...rows.map(renderFetchRow),
264
+ "</acquisition-plan>",
265
+ ];
266
+ return lines.join("\n");
267
+ }
268
+ //# sourceMappingURL=routine-acquisition-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routine-acquisition-plan.js","sourceRoot":"","sources":["../../src/core/routine-acquisition-plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * `RoutineFetchWindowRunner` — Phase 4 / D1 pre-pass orchestration.
3
+ *
4
+ * ROUTINE_DATA_ACQUISITION_DESIGN.md §6.1.1 / Phase 4 D1 — every routine
5
+ * dispatcher (morning_routine, today_refresh, hourly_check, evening /
6
+ * weekly / monthly review) calls this runner immediately before
7
+ * dispatching the parent session. The runner:
8
+ *
9
+ * 1. Reads the per-routine plan from `ROUTINE_WINDOWS` and the current
10
+ * integration state, fans out per-account where applicable, resolves
11
+ * each row's predicate (`direct` / `delegated-same` / `delegated-cross`
12
+ * / `native` / skip) via `buildAcquisitionPlan`, and renders an
13
+ * `<acquisition-plan>` block.
14
+ * 2. Synthesises a `routine.fetch_window` RoutineEvent, embeds the plan
15
+ * block in `event.data.acquisitionPlanBlock` so ContextBuilder folds
16
+ * it into the fetcher's prompt context, and routes the event
17
+ * synchronously through the standard `IAgentRouter.execute` /
18
+ * `PromptAssembler.assemble` pipeline. The session inherits the
19
+ * `routine.fetch_window` ProcessKey binding (lite tier per F1 / §6.9)
20
+ * and the dedicated `routine-fetch-window` agent profile.
21
+ * 3. Parses the agent's single-JSON-line output into a structured
22
+ * `FetchReport`, renders a `<fetch_report>` block, and logs one
23
+ * `agent_actions` row via the dispatcher's audit logger.
24
+ * 4. Returns the rendered block + parsed report so the caller can graft
25
+ * the block into the **parent** routine event's
26
+ * `event.data.fetchReportBlock`. ContextBuilder injects that block
27
+ * verbatim into the parent session's prompt (mirrors the
28
+ * `<gate_decision>` pattern used by hourly_check Stage 3).
29
+ *
30
+ * Failure-mode contract (Phase 4 D1 + design §11 R5 / OQ4):
31
+ *
32
+ * - **No applicable rows** (routine has no windows in `ROUTINE_WINDOWS`,
33
+ * every integration is disabled, every account list is empty) — the
34
+ * runner returns an empty `<fetch_report>` with `status="skipped"` and
35
+ * `fetched=posted=duplicates=0`. The parent routine still runs; the
36
+ * block is informational only.
37
+ * - **Pre-pass session errors** (binding resolve fails, agent throws,
38
+ * JSON parse fails) — the runner logs the failure and returns a
39
+ * `<fetch_report status="failed">` with one `pre-pass-failed` error.
40
+ * Pre-pass cost gains are forfeit for this tick; the parent routine
41
+ * continues with whatever observations the rest of the plan produced.
42
+ * Throwing here would otherwise propagate up and abort the parent
43
+ * routine — the opposite of P3 ("Lite for Fetch, Medium for Decide").
44
+ * - **Partial success** — the report's `errors` array carries per-row
45
+ * failures (`no-surface`, `fetch-failed`, `budget-exhausted`). The
46
+ * block surfaces them so the parent prompt can decide whether to
47
+ * treat its observations view as complete.
48
+ */
49
+ import type Database from "better-sqlite3";
50
+ import type { BackendId, Event, IntegrationKey, IntegrationState } from "@aitne/shared";
51
+ import type { AgentConfig } from "../config.js";
52
+ import type { MailAccount } from "../services/mail/provider.js";
53
+ import type { IAgentRouter } from "./backends/backend-router.js";
54
+ import type { IAuditLogger, IContextBuilder } from "./dispatcher-types.js";
55
+ import type { PromptAssembler } from "./dispatcher-prompt.js";
56
+ import { type RoutineWindowKey } from "./routine-windows.js";
57
+ /**
58
+ * Structured form of the agent's single-line JSON output. Matches the
59
+ * contract in `agent-profiles/routine-fetch-window.md`:
60
+ *
61
+ * ```json
62
+ * {"fetched": <int>, "posted": <int>, "duplicates": <int>, "errors": [...]}
63
+ * ```
64
+ *
65
+ * `status` is the runner's classification of the run — `success` /
66
+ * `partial` (any errors) / `failed` (parse / agent / dispatch failure) /
67
+ * `skipped` (no applicable rows). Persisted in the `<fetch_report>`
68
+ * block so the parent routine can branch deterministically without
69
+ * re-counting the errors array.
70
+ */
71
+ export interface FetchReport {
72
+ status: "success" | "partial" | "failed" | "skipped";
73
+ fetched: number;
74
+ posted: number;
75
+ duplicates: number;
76
+ errors: ReadonlyArray<Record<string, unknown>>;
77
+ /** True when the runner skipped dispatching a session entirely. */
78
+ skipped: boolean;
79
+ /** Set when status === "failed" — the message captured in the audit row. */
80
+ failureReason?: string;
81
+ /** Stable ID for telemetry tie-back; mirrors the fetcher event's correlationId. */
82
+ fetcherCorrelationId?: string;
83
+ }
84
+ export interface RoutineFetchWindowResult {
85
+ report: FetchReport;
86
+ /** XML block to graft into the parent routine event's `event.data.fetchReportBlock`. */
87
+ block: string;
88
+ }
89
+ export interface RoutineFetchWindowRunnerDeps {
90
+ db: Database.Database;
91
+ config: AgentConfig;
92
+ contextBuilder: IContextBuilder;
93
+ agentRouter: IAgentRouter;
94
+ audit: IAuditLogger;
95
+ prompt: PromptAssembler;
96
+ /**
97
+ * Returns the active mail account list — used to fan rows out per
98
+ * account when `RoutineWindowSpec.perAccount === true`. Threads the
99
+ * dispatcher's existing `getActiveMailAccounts` closure so the runner
100
+ * doesn't need to depend on the registry directly.
101
+ */
102
+ getActiveMailAccounts: () => readonly MailAccount[];
103
+ }
104
+ /**
105
+ * Compose the per-execute `allowedToolsOverride` for the pre-pass. The
106
+ * override REPLACES the SDK's default allowlist (no union per
107
+ * claude-code-core.ts:437) so the list must be exhaustive for every
108
+ * surface the partials use under any (integration, mode) cell. Mode
109
+ * coverage:
110
+ *
111
+ * - `direct`: daemon REST → curl prefix.
112
+ * - `delegated-same`: session backend MCP → integration tool name.
113
+ * - `delegated-cross`: daemon delegation proxy → curl prefix
114
+ * (`/api/integrations/<key>/exec`).
115
+ * - `native` (descriptor-bound): session backend MCP → integration
116
+ * tool name.
117
+ * - `native` (user-managed) / no-surface: nothing in the override —
118
+ * the partial records `no-surface` and the runner's report carries
119
+ * the gap forward to the parent routine.
120
+ *
121
+ * Exported for unit testing — the runner consumes it via
122
+ * `composePrePassAllowedTools` at dispatch time.
123
+ */
124
+ export declare function composePrePassAllowedTools(apiPort: number, integrations: Partial<Record<IntegrationKey, IntegrationState>>, sessionBackend: BackendId): readonly string[];
125
+ /**
126
+ * Derive the canonical `RoutineWindowKey` from a routine event. The
127
+ * caller's intent is conveyed by `event.type` (always `routine.<name>`),
128
+ * with `RoutineEvent.routine` carrying the same suffix without the
129
+ * `routine.` prefix. Returns null for routines outside the catalog so
130
+ * the caller can short-circuit before touching plan assembly.
131
+ */
132
+ export declare function routineWindowKeyFromEvent(event: Event): RoutineWindowKey | null;
133
+ /**
134
+ * Walk `text` and return every balanced `{...}` slice (top-level objects
135
+ * only; nested braces are honoured). Strings are tracked so brace
136
+ * characters inside `"..."` literals don't unbalance the scan. Used by
137
+ * `parseFetchWindowOutput` to pick the LAST top-level object on stdout —
138
+ * agents occasionally emit a think-aloud line carrying a JSON snippet
139
+ * before the verdict, and the fetcher's contract is "the last
140
+ * top-level JSON object wins."
141
+ *
142
+ * Exported for direct unit testing; the runner consumes it via
143
+ * `parseFetchWindowOutput`.
144
+ */
145
+ export declare function extractBalancedJsonObjects(text: string): string[];
146
+ /** Strict-JSON parse of the fetcher's single-line output. */
147
+ export declare function parseFetchWindowOutput(output: string): FetchReport | {
148
+ parseError: string;
149
+ };
150
+ /**
151
+ * Render the `<fetch_report>` XML block injected into the parent
152
+ * routine's prompt. Keep the schema narrow — every additional attribute
153
+ * costs prompt tokens on the cache-warm parent session.
154
+ *
155
+ * `meta.routine` accepts any string so the no-routine-key skip path can
156
+ * render the parent event's actual type (e.g. `routine.skill_curation`)
157
+ * instead of borrowing a catalog entry as a placeholder. The renderer
158
+ * strips the `routine.` prefix verbatim — callers may pass either the
159
+ * fully-qualified ProcessKey or a bare suffix.
160
+ */
161
+ export declare function renderFetchReportBlock(report: FetchReport, meta: {
162
+ routine: RoutineWindowKey | string;
163
+ agentDay: string;
164
+ }): string;
165
+ export declare class RoutineFetchWindowRunner {
166
+ private readonly db;
167
+ private readonly config;
168
+ private readonly contextBuilder;
169
+ private readonly agentRouter;
170
+ private readonly audit;
171
+ private readonly prompt;
172
+ private readonly getActiveMailAccounts;
173
+ constructor(deps: RoutineFetchWindowRunnerDeps);
174
+ /**
175
+ * Execute the pre-pass for `parentEvent`. Returns the fetch report
176
+ * and rendered `<fetch_report>` block; callers graft the block into
177
+ * the parent event's `event.data.fetchReportBlock` so ContextBuilder
178
+ * injects it into the parent prompt.
179
+ *
180
+ * `routineKey` overrides the auto-derived window key — used by
181
+ * morning_routine to opt into `routine.morning_routine_initial`'s
182
+ * plan when `yesterday.md` is absent (their plans currently coincide,
183
+ * but the seam exists for future divergence).
184
+ */
185
+ run(parentEvent: Event, routineKey?: RoutineWindowKey): Promise<RoutineFetchWindowResult>;
186
+ /**
187
+ * Helper for the failure paths — renders a `<fetch_report status="failed">`
188
+ * block and logs the underlying error. Never throws so the caller can
189
+ * always continue with the parent routine dispatch.
190
+ */
191
+ private fail;
192
+ /**
193
+ * Translate the mail registry's active-account list into the
194
+ * `AcquisitionAccount[]` shape `buildAcquisitionPlan` expects. Only
195
+ * accounts whose integration is currently non-disabled survive — a
196
+ * disabled gmail integration with five accounts produces zero rows,
197
+ * matching the partial's `<!-- mode:disabled:gmail -->` no-op.
198
+ */
199
+ private collectAccounts;
200
+ }
201
+ //# sourceMappingURL=routine-fetch-window-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routine-fetch-window-runner.d.ts","sourceRoot":"","sources":["../../src/core/routine-fetch-window-runner.ts"],"names":[],"mappings":"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"}