@aitne/daemon 0.1.3 → 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.
- package/dist/adapters/whatsapp-adapter.d.ts.map +1 -1
- package/dist/adapters/whatsapp-adapter.js +0 -1
- package/dist/adapters/whatsapp-adapter.js.map +1 -1
- package/dist/api/integration-route-gate.d.ts +15 -11
- package/dist/api/integration-route-gate.d.ts.map +1 -1
- package/dist/api/integration-route-gate.js +60 -23
- package/dist/api/integration-route-gate.js.map +1 -1
- package/dist/api/json-body.d.ts +22 -7
- package/dist/api/json-body.d.ts.map +1 -1
- package/dist/api/json-body.js +27 -8
- package/dist/api/json-body.js.map +1 -1
- package/dist/api/routes/agent.d.ts.map +1 -1
- package/dist/api/routes/agent.js +18 -0
- package/dist/api/routes/agent.js.map +1 -1
- package/dist/api/routes/backends.d.ts.map +1 -1
- package/dist/api/routes/backends.js +96 -1
- package/dist/api/routes/backends.js.map +1 -1
- package/dist/api/routes/books.js +1 -1
- package/dist/api/routes/books.js.map +1 -1
- package/dist/api/routes/context.d.ts.map +1 -1
- package/dist/api/routes/context.js +13 -1
- package/dist/api/routes/context.js.map +1 -1
- package/dist/api/routes/dashboard.d.ts.map +1 -1
- package/dist/api/routes/dashboard.js +75 -5
- package/dist/api/routes/dashboard.js.map +1 -1
- package/dist/api/routes/github.d.ts.map +1 -1
- package/dist/api/routes/github.js +38 -5
- package/dist/api/routes/github.js.map +1 -1
- package/dist/api/routes/integrations.d.ts +35 -6
- package/dist/api/routes/integrations.d.ts.map +1 -1
- package/dist/api/routes/integrations.js +191 -16
- package/dist/api/routes/integrations.js.map +1 -1
- package/dist/api/routes/mail.d.ts.map +1 -1
- package/dist/api/routes/mail.js +112 -46
- package/dist/api/routes/mail.js.map +1 -1
- package/dist/api/routes/observations.d.ts.map +1 -1
- package/dist/api/routes/observations.js +161 -8
- package/dist/api/routes/observations.js.map +1 -1
- package/dist/api/routes/setup-migrate.d.ts +9 -1
- package/dist/api/routes/setup-migrate.d.ts.map +1 -1
- package/dist/api/routes/setup-migrate.js +4 -2
- package/dist/api/routes/setup-migrate.js.map +1 -1
- package/dist/api/routes/skills.d.ts.map +1 -1
- package/dist/api/routes/skills.js +39 -1
- package/dist/api/routes/skills.js.map +1 -1
- package/dist/api/routes/voice.d.ts.map +1 -1
- package/dist/api/routes/voice.js +62 -4
- package/dist/api/routes/voice.js.map +1 -1
- package/dist/bootstrap/adapters.d.ts +109 -0
- package/dist/bootstrap/adapters.d.ts.map +1 -0
- package/dist/bootstrap/adapters.js +237 -0
- package/dist/bootstrap/adapters.js.map +1 -0
- package/dist/bootstrap/catchup.d.ts +23 -0
- package/dist/bootstrap/catchup.d.ts.map +1 -0
- package/dist/bootstrap/catchup.js +124 -0
- package/dist/bootstrap/catchup.js.map +1 -0
- package/dist/bootstrap/schedule-helpers.d.ts +18 -0
- package/dist/bootstrap/schedule-helpers.d.ts.map +1 -0
- package/dist/bootstrap/schedule-helpers.js +96 -0
- package/dist/bootstrap/schedule-helpers.js.map +1 -0
- package/dist/bootstrap/services.d.ts +60 -0
- package/dist/bootstrap/services.d.ts.map +1 -0
- package/dist/bootstrap/services.js +209 -0
- package/dist/bootstrap/services.js.map +1 -0
- package/dist/core/backends/backend-router.d.ts +23 -0
- package/dist/core/backends/backend-router.d.ts.map +1 -1
- package/dist/core/backends/backend-router.js +48 -3
- package/dist/core/backends/backend-router.js.map +1 -1
- package/dist/core/backends/claude-auth.d.ts +70 -0
- package/dist/core/backends/claude-auth.d.ts.map +1 -0
- package/dist/core/backends/claude-auth.js +198 -0
- package/dist/core/backends/claude-auth.js.map +1 -0
- package/dist/core/backends/claude-code-core.d.ts +47 -119
- package/dist/core/backends/claude-code-core.d.ts.map +1 -1
- package/dist/core/backends/claude-code-core.js +112 -1565
- package/dist/core/backends/claude-code-core.js.map +1 -1
- package/dist/core/backends/claude-delegated.d.ts +86 -0
- package/dist/core/backends/claude-delegated.d.ts.map +1 -0
- package/dist/core/backends/claude-delegated.js +801 -0
- package/dist/core/backends/claude-delegated.js.map +1 -0
- package/dist/core/backends/claude-errors.d.ts +39 -0
- package/dist/core/backends/claude-errors.d.ts.map +1 -0
- package/dist/core/backends/claude-errors.js +71 -0
- package/dist/core/backends/claude-errors.js.map +1 -0
- package/dist/core/backends/claude-probe.d.ts +103 -0
- package/dist/core/backends/claude-probe.d.ts.map +1 -0
- package/dist/core/backends/claude-probe.js +336 -0
- package/dist/core/backends/claude-probe.js.map +1 -0
- package/dist/core/backends/claude-tool-collection.d.ts +135 -0
- package/dist/core/backends/claude-tool-collection.d.ts.map +1 -0
- package/dist/core/backends/claude-tool-collection.js +831 -0
- package/dist/core/backends/claude-tool-collection.js.map +1 -0
- package/dist/core/backends/gemini-cli-core.d.ts +21 -0
- package/dist/core/backends/gemini-cli-core.d.ts.map +1 -1
- package/dist/core/backends/gemini-cli-core.js +84 -6
- package/dist/core/backends/gemini-cli-core.js.map +1 -1
- package/dist/core/backends/prompt-utils.d.ts +1 -0
- package/dist/core/backends/prompt-utils.d.ts.map +1 -1
- package/dist/core/backends/prompt-utils.js +60 -3
- package/dist/core/backends/prompt-utils.js.map +1 -1
- package/dist/core/context-builder.d.ts +36 -12
- package/dist/core/context-builder.d.ts.map +1 -1
- package/dist/core/context-builder.js +179 -89
- package/dist/core/context-builder.js.map +1 -1
- package/dist/core/dispatcher-date-utils.d.ts +49 -0
- package/dist/core/dispatcher-date-utils.d.ts.map +1 -0
- package/dist/core/dispatcher-date-utils.js +132 -0
- package/dist/core/dispatcher-date-utils.js.map +1 -0
- package/dist/core/dispatcher-error-handling.d.ts +159 -0
- package/dist/core/dispatcher-error-handling.d.ts.map +1 -0
- package/dist/core/dispatcher-error-handling.js +393 -0
- package/dist/core/dispatcher-error-handling.js.map +1 -0
- package/dist/core/dispatcher-hourly-check.d.ts +150 -0
- package/dist/core/dispatcher-hourly-check.d.ts.map +1 -0
- package/dist/core/dispatcher-hourly-check.js +665 -0
- package/dist/core/dispatcher-hourly-check.js.map +1 -0
- package/dist/core/dispatcher-message-handler.d.ts +170 -0
- package/dist/core/dispatcher-message-handler.d.ts.map +1 -0
- package/dist/core/dispatcher-message-handler.js +1054 -0
- package/dist/core/dispatcher-message-handler.js.map +1 -0
- package/dist/core/dispatcher-morning-routine.d.ts +169 -0
- package/dist/core/dispatcher-morning-routine.d.ts.map +1 -0
- package/dist/core/dispatcher-morning-routine.js +434 -0
- package/dist/core/dispatcher-morning-routine.js.map +1 -0
- package/dist/core/dispatcher-prompt.d.ts +107 -0
- package/dist/core/dispatcher-prompt.d.ts.map +1 -0
- package/dist/core/dispatcher-prompt.js +227 -0
- package/dist/core/dispatcher-prompt.js.map +1 -0
- package/dist/core/dispatcher-repository-helpers.d.ts +39 -0
- package/dist/core/dispatcher-repository-helpers.d.ts.map +1 -0
- package/dist/core/dispatcher-repository-helpers.js +86 -0
- package/dist/core/dispatcher-repository-helpers.js.map +1 -0
- package/dist/core/dispatcher-result-processor.d.ts +145 -0
- package/dist/core/dispatcher-result-processor.d.ts.map +1 -0
- package/dist/core/dispatcher-result-processor.js +414 -0
- package/dist/core/dispatcher-result-processor.js.map +1 -0
- package/dist/core/dispatcher-scheduled-tasks.d.ts +406 -0
- package/dist/core/dispatcher-scheduled-tasks.d.ts.map +1 -0
- package/dist/core/dispatcher-scheduled-tasks.js +998 -0
- package/dist/core/dispatcher-scheduled-tasks.js.map +1 -0
- package/dist/core/dispatcher-types.d.ts +296 -0
- package/dist/core/dispatcher-types.d.ts.map +1 -0
- package/dist/core/dispatcher-types.js +106 -0
- package/dist/core/dispatcher-types.js.map +1 -0
- package/dist/core/dispatcher.d.ts +86 -610
- package/dist/core/dispatcher.d.ts.map +1 -1
- package/dist/core/dispatcher.js +293 -3542
- package/dist/core/dispatcher.js.map +1 -1
- package/dist/core/integration-health.d.ts +18 -10
- package/dist/core/integration-health.d.ts.map +1 -1
- package/dist/core/integration-health.js +31 -1
- package/dist/core/integration-health.js.map +1 -1
- package/dist/core/integration-lifecycle.d.ts +65 -0
- package/dist/core/integration-lifecycle.d.ts.map +1 -1
- package/dist/core/integration-lifecycle.js +167 -16
- package/dist/core/integration-lifecycle.js.map +1 -1
- package/dist/core/integration-main-backend.d.ts +40 -0
- package/dist/core/integration-main-backend.d.ts.map +1 -1
- package/dist/core/integration-main-backend.js +89 -2
- package/dist/core/integration-main-backend.js.map +1 -1
- package/dist/core/management-md.d.ts +51 -17
- package/dist/core/management-md.d.ts.map +1 -1
- package/dist/core/management-md.js +233 -56
- package/dist/core/management-md.js.map +1 -1
- package/dist/core/output-language-policy.d.ts +74 -0
- package/dist/core/output-language-policy.d.ts.map +1 -0
- package/dist/core/output-language-policy.js +194 -0
- package/dist/core/output-language-policy.js.map +1 -0
- package/dist/core/prompts.d.ts +1 -0
- package/dist/core/prompts.d.ts.map +1 -1
- package/dist/core/prompts.js +121 -3
- package/dist/core/prompts.js.map +1 -1
- package/dist/core/repository-management-docs.d.ts +24 -0
- package/dist/core/repository-management-docs.d.ts.map +1 -1
- package/dist/core/repository-management-docs.js +210 -26
- package/dist/core/repository-management-docs.js.map +1 -1
- package/dist/core/routine-acquisition-plan.d.ts +131 -0
- package/dist/core/routine-acquisition-plan.d.ts.map +1 -0
- package/dist/core/routine-acquisition-plan.js +268 -0
- package/dist/core/routine-acquisition-plan.js.map +1 -0
- package/dist/core/routine-fetch-window-runner.d.ts +201 -0
- package/dist/core/routine-fetch-window-runner.d.ts.map +1 -0
- package/dist/core/routine-fetch-window-runner.js +661 -0
- package/dist/core/routine-fetch-window-runner.js.map +1 -0
- package/dist/core/routine-windows.d.ts +156 -0
- package/dist/core/routine-windows.d.ts.map +1 -0
- package/dist/core/routine-windows.js +330 -0
- package/dist/core/routine-windows.js.map +1 -0
- package/dist/core/skills-compiler.d.ts +11 -0
- package/dist/core/skills-compiler.d.ts.map +1 -1
- package/dist/core/skills-compiler.js +102 -13
- package/dist/core/skills-compiler.js.map +1 -1
- package/dist/core/skills-manifest.d.ts.map +1 -1
- package/dist/core/skills-manifest.js +26 -0
- package/dist/core/skills-manifest.js.map +1 -1
- package/dist/core/system-reset.d.ts.map +1 -1
- package/dist/core/system-reset.js +25 -2
- package/dist/core/system-reset.js.map +1 -1
- package/dist/db/observations.d.ts +45 -2
- package/dist/db/observations.d.ts.map +1 -1
- package/dist/db/observations.js +112 -14
- package/dist/db/observations.js.map +1 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +13 -25
- package/dist/db/schema.js.map +1 -1
- package/dist/index.js +83 -610
- package/dist/index.js.map +1 -1
- package/dist/observers/delegated-sync-worker.d.ts +45 -2
- package/dist/observers/delegated-sync-worker.d.ts.map +1 -1
- package/dist/observers/delegated-sync-worker.js +71 -21
- package/dist/observers/delegated-sync-worker.js.map +1 -1
- package/dist/observers/mail-poller.d.ts +12 -5
- package/dist/observers/mail-poller.d.ts.map +1 -1
- package/dist/observers/mail-poller.js +36 -14
- package/dist/observers/mail-poller.js.map +1 -1
- package/dist/observers/manager.d.ts +37 -5
- package/dist/observers/manager.d.ts.map +1 -1
- package/dist/observers/manager.js +28 -10
- package/dist/observers/manager.js.map +1 -1
- package/dist/services/delegated-backend-invoker.d.ts +1 -51
- package/dist/services/delegated-backend-invoker.d.ts.map +1 -1
- package/dist/services/delegated-backend-invoker.js +41 -480
- package/dist/services/delegated-backend-invoker.js.map +1 -1
- package/dist/services/delegated-invoker-audit.d.ts +94 -0
- package/dist/services/delegated-invoker-audit.d.ts.map +1 -0
- package/dist/services/delegated-invoker-audit.js +238 -0
- package/dist/services/delegated-invoker-audit.js.map +1 -0
- package/dist/services/delegated-invoker-cache-hits.d.ts +34 -0
- package/dist/services/delegated-invoker-cache-hits.d.ts.map +1 -0
- package/dist/services/delegated-invoker-cache-hits.js +104 -0
- package/dist/services/delegated-invoker-cache-hits.js.map +1 -0
- package/dist/services/delegated-invoker-janitors.d.ts +28 -0
- package/dist/services/delegated-invoker-janitors.d.ts.map +1 -0
- package/dist/services/delegated-invoker-janitors.js +104 -0
- package/dist/services/delegated-invoker-janitors.js.map +1 -0
- package/dist/services/delegated-invoker-utils.d.ts +42 -0
- package/dist/services/delegated-invoker-utils.d.ts.map +1 -0
- package/dist/services/delegated-invoker-utils.js +100 -0
- package/dist/services/delegated-invoker-utils.js.map +1 -0
- package/dist/services/delegated-task-runtime.d.ts +1 -1
- package/dist/services/delegated-task-runtime.js +1 -1
- package/dist/services/integrations/snapshot-partitions.d.ts +5 -0
- package/dist/services/integrations/snapshot-partitions.d.ts.map +1 -1
- package/dist/services/integrations/snapshot-partitions.js +12 -0
- package/dist/services/integrations/snapshot-partitions.js.map +1 -1
- package/dist/services/voice/transcriber-impl.d.ts.map +1 -1
- package/dist/services/voice/transcriber-impl.js +7 -8
- package/dist/services/voice/transcriber-impl.js.map +1 -1
- package/package.json +2 -2
|
@@ -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&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, "&")
|
|
166
|
+
.replace(/"/g, """)
|
|
167
|
+
.replace(/</g, "<")
|
|
168
|
+
.replace(/>/g, ">");
|
|
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, "'")
|
|
193
|
+
.replace(/</g, "<")
|
|
194
|
+
.replace(/>/g, ">");
|
|
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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"}
|