@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,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `DispatcherErrorRouter` — owns the dispatcher's failure-path
|
|
3
|
+
* machinery: the shallow retry wrapper around BackendRouter
|
|
4
|
+
* (`executeWithRetry`), the post-throw cleanup + DM/dashboard
|
|
5
|
+
* notification (`handleError`), the quota-error introspection +
|
|
6
|
+
* formatting helpers, and the §4.5 delegated-connector health
|
|
7
|
+
* warning consult/dispatch pair.
|
|
8
|
+
*
|
|
9
|
+
* Extracted from `core/dispatcher.ts` as part of phase D-2 of
|
|
10
|
+
* `docs/design/appendices/file-split-plan.md`. Pattern B (stateful
|
|
11
|
+
* coordinator): the router owns its own logic but borrows live
|
|
12
|
+
* references from the dispatcher for state that must remain
|
|
13
|
+
* observable to the parent class — the `notifiedEvents` Set used to
|
|
14
|
+
* dedup outbound notifications, the `shutdownAwaiters` Set used to
|
|
15
|
+
* shortcut the retry sleep on SIGTERM, plus accessors for the
|
|
16
|
+
* dispatcher's `shutdown` flag and lazily-injected dashboard stream.
|
|
17
|
+
*
|
|
18
|
+
* Dispatcher entry points served:
|
|
19
|
+
* - `dispatchSafe` calls `executeWithRetry` around backend invokes
|
|
20
|
+
* and `handleError` on failure;
|
|
21
|
+
* - `handleMessage` calls the `consult/run` connector-warning pair
|
|
22
|
+
* before/after recording the user message;
|
|
23
|
+
* - the §4.5 finalize callbacks (`onRetemplateFinalize` /
|
|
24
|
+
* `onManagementScanFinalize`) bridge into the ResultProcessor —
|
|
25
|
+
* the success path uses ResultProcessor directly; the error path
|
|
26
|
+
* calls through these closures to keep the failure ordering
|
|
27
|
+
* identical to the pre-split file.
|
|
28
|
+
*
|
|
29
|
+
* Shared-state references held:
|
|
30
|
+
* - `notifiedEvents: Set<string>` — live reference; `handleError`
|
|
31
|
+
* deletes the entry as defense-in-depth cleanup when execution
|
|
32
|
+
* threw before reaching `processResult`.
|
|
33
|
+
* - `shutdownAwaiters: Set<() => void>` — live reference; the retry
|
|
34
|
+
* sleep races a 5-min timer against this awaiter set so SIGTERM
|
|
35
|
+
* resolves the wait promptly.
|
|
36
|
+
* - `isShutdown: () => boolean` — getter; on shutdown wakeup the
|
|
37
|
+
* retry loop rethrows instead of looping again.
|
|
38
|
+
* - `getDashboardStream: () => IDashboardStream | null` — lazy
|
|
39
|
+
* accessor; the dashboard stream is wired after construction.
|
|
40
|
+
*/
|
|
41
|
+
import { isMessageEvent, isScheduledEvent } from "@aitne/shared";
|
|
42
|
+
import { BackendDecisiveFailure, BackendQuotaError, } from "./agent-core.js";
|
|
43
|
+
import { BackendRouterHandledError } from "./backends/backend-router.js";
|
|
44
|
+
import { consultDelegatedConnectorHealth, markSignoutWarned, renderSignoutDm, } from "./delegated-connector-health.js";
|
|
45
|
+
import { compareLocalDateParts, getLocalDateParts, localDateTimeToUtcMs, } from "./dispatcher-date-utils.js";
|
|
46
|
+
import { createLogger } from "../logging.js";
|
|
47
|
+
const logger = createLogger("dispatcher-error");
|
|
48
|
+
export class DispatcherErrorRouter {
|
|
49
|
+
db;
|
|
50
|
+
config;
|
|
51
|
+
notificationMgr;
|
|
52
|
+
messageRecorder;
|
|
53
|
+
notifiedEvents;
|
|
54
|
+
shutdownAwaiters;
|
|
55
|
+
getDashboardStream;
|
|
56
|
+
isShutdown;
|
|
57
|
+
onRetemplateFinalize;
|
|
58
|
+
onManagementScanFinalize;
|
|
59
|
+
constructor(deps) {
|
|
60
|
+
this.db = deps.db;
|
|
61
|
+
this.config = deps.config;
|
|
62
|
+
this.notificationMgr = deps.notificationMgr;
|
|
63
|
+
this.messageRecorder = deps.messageRecorder;
|
|
64
|
+
this.notifiedEvents = deps.notifiedEvents;
|
|
65
|
+
this.shutdownAwaiters = deps.shutdownAwaiters;
|
|
66
|
+
this.getDashboardStream = deps.getDashboardStream;
|
|
67
|
+
this.isShutdown = deps.isShutdown;
|
|
68
|
+
this.onRetemplateFinalize = deps.onRetemplateFinalize;
|
|
69
|
+
this.onManagementScanFinalize = deps.onManagementScanFinalize;
|
|
70
|
+
}
|
|
71
|
+
isRetryable(error) {
|
|
72
|
+
// BackendCore implementations wrap all errors into BackendQuotaError or
|
|
73
|
+
// BackendDecisiveFailure before they reach the dispatcher. Both are
|
|
74
|
+
// decisive (no retry). BackendRouterHandledError is also decisive.
|
|
75
|
+
if (error instanceof BackendQuotaError ||
|
|
76
|
+
error instanceof BackendDecisiveFailure ||
|
|
77
|
+
error instanceof BackendRouterHandledError) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
// Raw 5xx from an unclassified path — retry once.
|
|
81
|
+
const status = typeof error === "object" && error !== null && "status" in error
|
|
82
|
+
? error.status
|
|
83
|
+
: undefined;
|
|
84
|
+
return typeof status === "number" && status >= 500;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Defense-in-depth retry wrapper around BackendRouter.execute().
|
|
88
|
+
*
|
|
89
|
+
* **Primary retry responsibility lives inside each BackendCore** (§12/§13).
|
|
90
|
+
* Quota errors, timeouts, and auth failures are all normalized into
|
|
91
|
+
* BackendDecisiveFailure / BackendQuotaError before they reach this layer.
|
|
92
|
+
* The BackendRouter handles fallback on decisive failures.
|
|
93
|
+
*
|
|
94
|
+
* This outer loop exists solely as a safety net for raw 5xx errors that
|
|
95
|
+
* somehow escape the BackendCore → Router chain (e.g., an unexpected HTTP
|
|
96
|
+
* error from the SDK transport layer). In practice it almost never fires.
|
|
97
|
+
*/
|
|
98
|
+
async executeWithRetry(fn, event) {
|
|
99
|
+
const maxRetries = 1;
|
|
100
|
+
let lastError;
|
|
101
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
102
|
+
try {
|
|
103
|
+
return await fn();
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
lastError = error;
|
|
107
|
+
if (attempt < maxRetries && this.isRetryable(error)) {
|
|
108
|
+
logger.warn({
|
|
109
|
+
eventType: event.type,
|
|
110
|
+
attempt: attempt + 1,
|
|
111
|
+
error: error instanceof Error ? error.message : String(error),
|
|
112
|
+
}, "Retrying agent execution after backoff");
|
|
113
|
+
// Shutdown-aware sleep: race a single 5-minute timer against the
|
|
114
|
+
// shutdown signal so SIGTERM unwinds the retry loop promptly
|
|
115
|
+
// instead of blocking for up to 5 minutes.
|
|
116
|
+
await new Promise((resolve) => {
|
|
117
|
+
const onShutdown = () => {
|
|
118
|
+
clearTimeout(timer);
|
|
119
|
+
this.shutdownAwaiters.delete(onShutdown);
|
|
120
|
+
resolve();
|
|
121
|
+
};
|
|
122
|
+
const timer = setTimeout(() => {
|
|
123
|
+
this.shutdownAwaiters.delete(onShutdown);
|
|
124
|
+
resolve();
|
|
125
|
+
}, 5 * 60 * 1000);
|
|
126
|
+
this.shutdownAwaiters.add(onShutdown);
|
|
127
|
+
});
|
|
128
|
+
if (this.isShutdown()) {
|
|
129
|
+
throw lastError;
|
|
130
|
+
}
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
throw lastError;
|
|
137
|
+
}
|
|
138
|
+
async handleError(event, error) {
|
|
139
|
+
logger.error({ event: event.type, error: error.message }, "Event processing error");
|
|
140
|
+
// Defense-in-depth cleanup of the notify-dedup marker — processResult
|
|
141
|
+
// is the primary collection point, but if execution threw before
|
|
142
|
+
// reaching it, drop any orphan entry here so the set cannot grow
|
|
143
|
+
// unbounded across error storms.
|
|
144
|
+
this.notifiedEvents.delete(event.correlationId);
|
|
145
|
+
const routerHandledError = error instanceof BackendRouterHandledError
|
|
146
|
+
? error
|
|
147
|
+
: null;
|
|
148
|
+
// Mark scheduled task as failed whenever execution terminates
|
|
149
|
+
// without a result. Covers both scheduled.task and scheduled.dm —
|
|
150
|
+
// a scheduled.dm row that throws would otherwise stick in
|
|
151
|
+
// `running` forever.
|
|
152
|
+
if (isScheduledEvent(event) && event.scheduleId) {
|
|
153
|
+
this.db
|
|
154
|
+
.prepare("UPDATE agent_schedule SET status = 'failed' WHERE id = ? AND status = 'running'")
|
|
155
|
+
.run(event.scheduleId);
|
|
156
|
+
this.onRetemplateFinalize(event, { errored: true });
|
|
157
|
+
}
|
|
158
|
+
// Same rationale as the success-path call: management events have no
|
|
159
|
+
// `agent_schedule` row, so this hook is intentionally outside the
|
|
160
|
+
// scheduleId guard.
|
|
161
|
+
this.onManagementScanFinalize(event, { errored: true });
|
|
162
|
+
if (routerHandledError) {
|
|
163
|
+
const quotaError = this.extractQuotaError(routerHandledError.cause);
|
|
164
|
+
if (quotaError && isMessageEvent(event)) {
|
|
165
|
+
this.notifyDashboardError(event, this.formatQuotaMessage(quotaError));
|
|
166
|
+
}
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const quotaError = this.extractQuotaError(error);
|
|
170
|
+
if (quotaError && isMessageEvent(event)) {
|
|
171
|
+
const quotaMsg = this.formatQuotaMessage(quotaError);
|
|
172
|
+
this.notifyDashboardError(event, quotaMsg);
|
|
173
|
+
await this.notificationMgr.send(quotaMsg, event);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (isMessageEvent(event)) {
|
|
177
|
+
const errorMsg = "An error occurred during processing. Please try again.";
|
|
178
|
+
this.notifyDashboardError(event, errorMsg);
|
|
179
|
+
await this.notificationMgr.send(errorMsg, event);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Best-effort inline error to the dashboard tab whose POST triggered
|
|
184
|
+
* this event. `DashboardAdapter` is `notificationEligible=false`, so
|
|
185
|
+
* the normal `notificationMgr.send` path skips it — without this hook
|
|
186
|
+
* the browser sees the request accepted (200 OK), watches nothing
|
|
187
|
+
* happen, and hits the 120s waiting timeout with no explanation. We
|
|
188
|
+
* target the originating channel id; if the tab already reconnected
|
|
189
|
+
* with a new UUID the adapter silently drops, which matches the
|
|
190
|
+
* chat_error semantics.
|
|
191
|
+
*/
|
|
192
|
+
notifyDashboardError(event, message) {
|
|
193
|
+
if (!isMessageEvent(event))
|
|
194
|
+
return;
|
|
195
|
+
if (event.platform !== "dashboard")
|
|
196
|
+
return;
|
|
197
|
+
this.getDashboardStream()?.sendError?.(event.channel, message);
|
|
198
|
+
}
|
|
199
|
+
extractQuotaError(error) {
|
|
200
|
+
if (error instanceof BackendQuotaError) {
|
|
201
|
+
return error;
|
|
202
|
+
}
|
|
203
|
+
if (error instanceof BackendDecisiveFailure &&
|
|
204
|
+
error.kind === "quota" &&
|
|
205
|
+
error.cause instanceof BackendQuotaError) {
|
|
206
|
+
return error.cause;
|
|
207
|
+
}
|
|
208
|
+
// All BackendCore implementations normalize quota errors before they
|
|
209
|
+
// reach the dispatcher, so no Claude-specific fallback is needed here.
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
formatQuotaMessage(quotaError) {
|
|
213
|
+
const backendLabel = this.formatBackendLabel(quotaError.backendId);
|
|
214
|
+
const resetHint = quotaError.resetHint;
|
|
215
|
+
if (quotaError.originalCode === "max_budget_usd") {
|
|
216
|
+
return `${backendLabel} reached the per-turn budget limit. Please try a shorter request or raise max_budget_usd in backend settings.`;
|
|
217
|
+
}
|
|
218
|
+
if (resetHint) {
|
|
219
|
+
const timeZone = resetHint.timeZone || this.config.timezone || undefined;
|
|
220
|
+
const resetAtMs = this.resolveQuotaResetAtMs(resetHint);
|
|
221
|
+
if (resetAtMs !== null) {
|
|
222
|
+
const formatted = new Intl.DateTimeFormat("en-US", {
|
|
223
|
+
timeZone,
|
|
224
|
+
year: "numeric",
|
|
225
|
+
month: "2-digit",
|
|
226
|
+
day: "2-digit",
|
|
227
|
+
hour: "2-digit",
|
|
228
|
+
minute: "2-digit",
|
|
229
|
+
hourCycle: "h12",
|
|
230
|
+
}).format(new Date(resetAtMs));
|
|
231
|
+
const zoneLabel = timeZone ? ` (${timeZone})` : "";
|
|
232
|
+
return `${backendLabel} has reached its usage limit. Resets at ${formatted}${zoneLabel}. Please try again after the reset.`;
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
new Intl.DateTimeFormat("en-US", { timeZone }).format(new Date());
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// Fall through to rawLabel/generic message if the timezone label is invalid.
|
|
239
|
+
}
|
|
240
|
+
const rawLabel = resetHint.rawLabel.trim();
|
|
241
|
+
if (rawLabel) {
|
|
242
|
+
return `${backendLabel} has reached its usage limit. Resets at ${rawLabel}. Please try again after the reset.`;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return `${backendLabel} has reached its usage limit. Please wait and try again later.`;
|
|
246
|
+
}
|
|
247
|
+
formatBackendLabel(backendId) {
|
|
248
|
+
switch (backendId) {
|
|
249
|
+
case "claude":
|
|
250
|
+
return "Claude Code";
|
|
251
|
+
case "codex":
|
|
252
|
+
return "Codex";
|
|
253
|
+
case "gemini":
|
|
254
|
+
return "Gemini CLI";
|
|
255
|
+
default:
|
|
256
|
+
return backendId;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
resolveQuotaResetAtMs(resetHint) {
|
|
260
|
+
const timeZone = resetHint.timeZone || this.config.timezone || undefined;
|
|
261
|
+
const now = new Date();
|
|
262
|
+
const current = getLocalDateParts(now, timeZone);
|
|
263
|
+
let target = {
|
|
264
|
+
year: current.year,
|
|
265
|
+
month: current.month,
|
|
266
|
+
day: current.day,
|
|
267
|
+
hour: resetHint.hour,
|
|
268
|
+
minute: resetHint.minute,
|
|
269
|
+
};
|
|
270
|
+
if (compareLocalDateParts(current, target) >= 0) {
|
|
271
|
+
const nextDate = new Date(Date.UTC(current.year, current.month - 1, current.day + 1));
|
|
272
|
+
target = {
|
|
273
|
+
year: nextDate.getUTCFullYear(),
|
|
274
|
+
month: nextDate.getUTCMonth() + 1,
|
|
275
|
+
day: nextDate.getUTCDate(),
|
|
276
|
+
hour: resetHint.hour,
|
|
277
|
+
minute: resetHint.minute,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
return localDateTimeToUtcMs(target, timeZone);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* DELEGATED-MODE-V2-DESIGN.md §4.5 — at every DM dispatch, consult the
|
|
284
|
+
* cached probe for delegated integrations whose effective backend
|
|
285
|
+
* matches the session backend. Surfaces a one-shot DM (deduped via
|
|
286
|
+
* `runtime_state`) when the cached probe says required capabilities
|
|
287
|
+
* are no longer present.
|
|
288
|
+
*
|
|
289
|
+
* The consult itself is synchronous DB-only work (cheap on the hot
|
|
290
|
+
* path). The DM dispatch is fire-and-forget so the agent's response
|
|
291
|
+
* latency is not gated on Slack/Telegram round-trips. Per-warning
|
|
292
|
+
* dispatch failures are swallowed so a flaky messaging adapter never
|
|
293
|
+
* breaks the user's actual DM.
|
|
294
|
+
*
|
|
295
|
+
* Phase 1 of the §4.5 health check — synchronous cache consult only.
|
|
296
|
+
* Returns the warnings the dispatcher must surface this turn (or `[]`
|
|
297
|
+
* when nothing is broken / setup mode is active / the consult itself
|
|
298
|
+
* threw). Recovery markers are cleared inline by the consult helper, so
|
|
299
|
+
* the caller does not have to track them.
|
|
300
|
+
*
|
|
301
|
+
* Split from the dispatch step so the actual DM (and its messages-table
|
|
302
|
+
* persist) fires AFTER the dispatcher has recorded the inbound user
|
|
303
|
+
* message — otherwise the warning row's `CURRENT_TIMESTAMP` lands before
|
|
304
|
+
* the user-message row's, which makes `chat_meta` history reload reorder
|
|
305
|
+
* the bubbles (warning above user) and a one-time visual flicker leaks
|
|
306
|
+
* to the user. See `runDelegatedConnectorWarningDispatch` below.
|
|
307
|
+
*/
|
|
308
|
+
consultDelegatedConnectorWarnings(sessionBackend) {
|
|
309
|
+
try {
|
|
310
|
+
const result = consultDelegatedConnectorHealth(this.db, sessionBackend);
|
|
311
|
+
if (result.recovered.length > 0) {
|
|
312
|
+
logger.info({ recovered: result.recovered, sessionBackend }, "Delegated connector(s) recovered — sign-out warning markers cleared");
|
|
313
|
+
}
|
|
314
|
+
return result.warnings;
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
logger.warn({ err, sessionBackend }, "Delegated connector-health consult failed — skipping DM warning");
|
|
318
|
+
return [];
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Phase 2 of the §4.5 health check — asynchronous DM dispatch + post-
|
|
323
|
+
* delivery bookkeeping (throttle marker + dashboard-channel persist).
|
|
324
|
+
* Caller invokes this AFTER the user message is recorded so the DM's
|
|
325
|
+
* messages-table row carries a strictly-later `CURRENT_TIMESTAMP`
|
|
326
|
+
* (preserves pre-reconcile chat order on the dashboard).
|
|
327
|
+
*/
|
|
328
|
+
runDelegatedConnectorWarningDispatch(warnings, event, sessionBackend, sessionId) {
|
|
329
|
+
for (const warning of warnings) {
|
|
330
|
+
logger.warn({
|
|
331
|
+
integration: warning.integration,
|
|
332
|
+
backend: warning.backend,
|
|
333
|
+
missingRequired: warning.missingRequired,
|
|
334
|
+
}, "Delegated connector reports missing required capabilities — DM owner");
|
|
335
|
+
const message = renderSignoutDm(warning);
|
|
336
|
+
// Mark the throttle ONLY after a successful dispatch — if the
|
|
337
|
+
// messaging adapter is down, an absent marker keeps the next
|
|
338
|
+
// consult ready to re-issue the warning. The .send() promise
|
|
339
|
+
// resolves on adapter-acknowledged delivery; .catch() is the
|
|
340
|
+
// failure side, which deliberately leaves the marker unset.
|
|
341
|
+
//
|
|
342
|
+
// After delivery, persist the warning to `messages` so it survives
|
|
343
|
+
// dashboard chat reload + the chat_meta history-reconcile pass
|
|
344
|
+
// (`reconcileLiveMessagesAfterHistoryReload` drops live bubbles whose
|
|
345
|
+
// timestamp is before the sync started AND whose signature is not in
|
|
346
|
+
// the restored history; without this persist the DM bubble vanishes
|
|
347
|
+
// the moment the agent's reply chat_meta arrives). For non-dashboard
|
|
348
|
+
// platforms (Slack/Telegram) the message-store is the platform itself,
|
|
349
|
+
// so we deliberately persist only when `event.platform === "dashboard"`
|
|
350
|
+
// to avoid duplicating remote-platform messages locally.
|
|
351
|
+
void this.notificationMgr
|
|
352
|
+
.send(message, event, {
|
|
353
|
+
priority: "high",
|
|
354
|
+
category: "delegated_signout",
|
|
355
|
+
})
|
|
356
|
+
.then(() => {
|
|
357
|
+
try {
|
|
358
|
+
markSignoutWarned(this.db, warning);
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
logger.warn({
|
|
362
|
+
err,
|
|
363
|
+
integration: warning.integration,
|
|
364
|
+
backend: warning.backend,
|
|
365
|
+
}, "Failed to persist delegated-signout marker — next consult may re-warn");
|
|
366
|
+
}
|
|
367
|
+
if (event.platform === "dashboard") {
|
|
368
|
+
try {
|
|
369
|
+
this.messageRecorder.recordMessage({
|
|
370
|
+
sessionId,
|
|
371
|
+
role: "assistant",
|
|
372
|
+
content: message,
|
|
373
|
+
platform: event.platform,
|
|
374
|
+
backend: sessionBackend,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
catch (err) {
|
|
378
|
+
logger.warn({
|
|
379
|
+
err,
|
|
380
|
+
integration: warning.integration,
|
|
381
|
+
backend: warning.backend,
|
|
382
|
+
sessionId,
|
|
383
|
+
}, "Failed to persist delegated-signout DM into messages — bubble may vanish on chat reload");
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
})
|
|
387
|
+
.catch((err) => {
|
|
388
|
+
logger.error({ err, integration: warning.integration, backend: warning.backend }, "Failed to deliver delegated-signout DM — marker not set, will retry next dispatch");
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=dispatcher-error-handling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher-error-handling.js","sourceRoot":"","sources":["../../src/core/dispatcher-error-handling.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `HourlyCheckCoordinator` — owns the dispatcher's
|
|
3
|
+
* `triggerHourlyCheck` entry point and the cost-reduction-structural §B
|
|
4
|
+
* three-stage gate that fronts it. The coordinator decides whether a
|
|
5
|
+
* given hourly tick:
|
|
6
|
+
* - skips (autonomous gate / morning routine active / already running
|
|
7
|
+
* / below threshold);
|
|
8
|
+
* - silently consumes observations + records an Agent Log line
|
|
9
|
+
* (Stage 0 deterministic gate or Stage 2 lite-tier `log_only`);
|
|
10
|
+
* - escalates to the existing Stage 3 enqueue (Stage 2 `escalate`
|
|
11
|
+
* verdict or `failed` cautious-escalate path).
|
|
12
|
+
*
|
|
13
|
+
* Extracted from `core/dispatcher.ts` as part of phase D-2 of
|
|
14
|
+
* `docs/design/appendices/file-split-plan.md`. Pattern B (stateful
|
|
15
|
+
* coordinator): the coordinator owns the gate logic but borrows live
|
|
16
|
+
* accessors for state the dispatcher continues to own — the
|
|
17
|
+
* `hourlyCheckInProgress` flag (atomic check-and-set inside the
|
|
18
|
+
* trigger), the `morningRoutineInProgress` flag (read-only), and the
|
|
19
|
+
* lazily-injected delegated-sync refresh callback.
|
|
20
|
+
*
|
|
21
|
+
* Dispatcher entry points served:
|
|
22
|
+
* - `EventDispatcher.triggerHourlyCheck(source, options)` is now a
|
|
23
|
+
* thin one-liner that delegates to `trigger(source, options)`.
|
|
24
|
+
*
|
|
25
|
+
* Invariants preserved bit-for-bit from
|
|
26
|
+
* `docs/design/02-event-pipeline.md` §2:
|
|
27
|
+
* - skip-if-morning-routine-in-progress;
|
|
28
|
+
* - skip-if-hourly-already-running (atomic flag flip BEFORE any
|
|
29
|
+
* await boundary — the C1 race fix from before the split);
|
|
30
|
+
* - skip-if-pending-observations-below-threshold (legacy
|
|
31
|
+
* min-observations floor honoured only when the gate would have
|
|
32
|
+
* proceeded to Stage 3 anyway);
|
|
33
|
+
* - skip-if-setup-incomplete / vault-degraded / user-paused via
|
|
34
|
+
* `isAutonomousAllowed`.
|
|
35
|
+
*
|
|
36
|
+
* Shared-state references held:
|
|
37
|
+
* - `setHourlyCheckInProgress` / `isHourlyCheckInProgress` —
|
|
38
|
+
* getter/setter pair around the dispatcher's flag. The flag is
|
|
39
|
+
* left `true` when an enqueue actually happens (the EventBus
|
|
40
|
+
* consumer's `dispatchSafe` finally clears it on routine
|
|
41
|
+
* completion); it is reset inline when the coordinator owns the
|
|
42
|
+
* turn (silent gate paths) or when the trigger is skipping.
|
|
43
|
+
* - `isMorningRoutineActive` — read-only mirror of the dispatcher
|
|
44
|
+
* method so the gate stays single-sourced.
|
|
45
|
+
* - `isAutonomousAllowed` — same; returns the
|
|
46
|
+
* `TriggerHourlyCheckSkipReason` the gate should surface.
|
|
47
|
+
* - `getDelegatedSyncRefresh` — accessor; null when no delegated
|
|
48
|
+
* integration is wired, in which case the gate proceeds without
|
|
49
|
+
* a refresh, matching pre-injection behaviour.
|
|
50
|
+
*/
|
|
51
|
+
import type Database from "better-sqlite3";
|
|
52
|
+
import type { AgentConfig } from "../config.js";
|
|
53
|
+
import type { EventBus } from "./event-bus.js";
|
|
54
|
+
import type { TodayWriteLockManager } from "./today-write-lock.js";
|
|
55
|
+
import type { IAgentRouter } from "./backends/backend-router.js";
|
|
56
|
+
import type { IAuditLogger, IContextBuilder, TriggerHourlyCheckOptions, TriggerHourlyCheckResult, TriggerHourlyCheckSkipReason } from "./dispatcher-types.js";
|
|
57
|
+
import type { PromptAssembler } from "./dispatcher-prompt.js";
|
|
58
|
+
import type { RoutineFetchWindowRunner } from "./routine-fetch-window-runner.js";
|
|
59
|
+
export interface HourlyCheckCoordinatorDeps {
|
|
60
|
+
db: Database.Database;
|
|
61
|
+
config: AgentConfig;
|
|
62
|
+
eventBus: EventBus;
|
|
63
|
+
contextBuilder: IContextBuilder;
|
|
64
|
+
agentRouter: IAgentRouter;
|
|
65
|
+
audit: IAuditLogger;
|
|
66
|
+
todayWriteLock: TodayWriteLockManager | undefined;
|
|
67
|
+
prompt: PromptAssembler;
|
|
68
|
+
/**
|
|
69
|
+
* ROUTINE_DATA_ACQUISITION_DESIGN.md Phase 4 / D3 — pre-pass runner
|
|
70
|
+
* spawned between Stage 2 (lite-tier triage) and Stage 3 (medium-tier
|
|
71
|
+
* main session) on `escalate` / `failed` verdicts. The rendered
|
|
72
|
+
* `<fetch_report>` block rides on the Stage 3 RoutineEvent's
|
|
73
|
+
* `event.data.fetchReportBlock` so ContextBuilder folds it into the
|
|
74
|
+
* Stage 3 prompt.
|
|
75
|
+
*/
|
|
76
|
+
fetchWindowRunner: RoutineFetchWindowRunner;
|
|
77
|
+
/** Accessor for the lazily-injected delegated-sync refresh callback. */
|
|
78
|
+
getDelegatedSyncRefresh: () => (() => Promise<void>) | null;
|
|
79
|
+
/** Setter for the dispatcher's `hourlyCheckInProgress` flag. */
|
|
80
|
+
setHourlyCheckInProgress: (value: boolean) => void;
|
|
81
|
+
/** Getter for the dispatcher's `hourlyCheckInProgress` flag. */
|
|
82
|
+
isHourlyCheckInProgress: () => boolean;
|
|
83
|
+
/** Mirrors `EventDispatcher.isMorningRoutineActive`. */
|
|
84
|
+
isMorningRoutineActive: () => boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Mirrors `EventDispatcher.isAutonomousAllowed`. Returns the
|
|
87
|
+
* skip-reason when the gate must abort early (setup incomplete,
|
|
88
|
+
* vault degraded, user paused) or `null` when autonomous work is
|
|
89
|
+
* permitted to proceed.
|
|
90
|
+
*/
|
|
91
|
+
isAutonomousAllowed: () => TriggerHourlyCheckSkipReason | null;
|
|
92
|
+
}
|
|
93
|
+
export declare class HourlyCheckCoordinator {
|
|
94
|
+
private readonly db;
|
|
95
|
+
private readonly config;
|
|
96
|
+
private readonly eventBus;
|
|
97
|
+
private readonly contextBuilder;
|
|
98
|
+
private readonly agentRouter;
|
|
99
|
+
private readonly audit;
|
|
100
|
+
private readonly todayWriteLock;
|
|
101
|
+
private readonly prompt;
|
|
102
|
+
private readonly fetchWindowRunner;
|
|
103
|
+
private readonly getDelegatedSyncRefresh;
|
|
104
|
+
private readonly setHourlyCheckInProgress;
|
|
105
|
+
private readonly isHourlyCheckInProgress;
|
|
106
|
+
private readonly isMorningRoutineActive;
|
|
107
|
+
private readonly isAutonomousAllowed;
|
|
108
|
+
constructor(deps: HourlyCheckCoordinatorDeps);
|
|
109
|
+
trigger(source: string, options?: TriggerHourlyCheckOptions): Promise<TriggerHourlyCheckResult>;
|
|
110
|
+
/**
|
|
111
|
+
* cost-reduction-structural §B — pull a fresh signal snapshot and run
|
|
112
|
+
* the deterministic gate. Helper so the dispatcher's call site stays
|
|
113
|
+
* compact and tests can spy on the boundary.
|
|
114
|
+
*/
|
|
115
|
+
private computeHourlyCheckGateDecision;
|
|
116
|
+
private readTodayMdSafe;
|
|
117
|
+
/**
|
|
118
|
+
* cost-reduction-structural §B — daemon-direct silent path. Used by
|
|
119
|
+
* Stage 0 and Stage 2 log-only verdicts. Consumes pending user
|
|
120
|
+
* observations + appends a single Agent Log line + records the gate
|
|
121
|
+
* verdict to `agent_actions`. The flag is reset before return.
|
|
122
|
+
*/
|
|
123
|
+
private runSilentHourlyCheckPath;
|
|
124
|
+
private enqueueStage3HourlyCheck;
|
|
125
|
+
private logGateAuditRow;
|
|
126
|
+
/**
|
|
127
|
+
* cost-reduction-structural §B Stage 2 — synchronous lite-tier triage.
|
|
128
|
+
* Builds a `routine.hourly_check.triage` RoutineEvent and runs it
|
|
129
|
+
* inline through the agent router (NOT the EventBus, so the result
|
|
130
|
+
* is available before we decide whether to silence or escalate).
|
|
131
|
+
*
|
|
132
|
+
* The agent contract is JSON-only output (`{ "action": "log_only" |
|
|
133
|
+
* "escalate", "reason": "..." }`); on parse failure we return
|
|
134
|
+
* `'failed'` and the caller treats that as cautious escalate.
|
|
135
|
+
*
|
|
136
|
+
* Tool/turn clamp (defense-in-depth):
|
|
137
|
+
* - `allowedToolsOverride: []` removes every tool from the SDK's
|
|
138
|
+
* allowlist for the spawn. Stage 2 has nothing to do but emit a
|
|
139
|
+
* JSON line; the design's "no write tools" rule is enforced here
|
|
140
|
+
* instead of relying on the prompt alone.
|
|
141
|
+
* - `maxTurns: 1` caps the spawn at a single assistant turn. Even
|
|
142
|
+
* if a future prompt change accidentally invites tool use, the
|
|
143
|
+
* spawn cannot loop. Codex/Gemini have no per-spawn `allowedTools`
|
|
144
|
+
* surface today (acknowledged gap in `agent-core.ts`); the
|
|
145
|
+
* `maxTurns` cap and process_backend_config envelope are the
|
|
146
|
+
* remaining safety floor on those backends.
|
|
147
|
+
*/
|
|
148
|
+
private runStage2Triage;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=dispatcher-hourly-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher-hourly-check.d.ts","sourceRoot":"","sources":["../../src/core/dispatcher-hourly-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAe3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAgB/C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,yBAAyB,EACzB,wBAAwB,EACxB,4BAA4B,EAC7B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAKjF,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,eAAe,CAAC;IAChC,WAAW,EAAE,YAAY,CAAC;IAC1B,KAAK,EAAE,YAAY,CAAC;IACpB,cAAc,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAClD,MAAM,EAAE,eAAe,CAAC;IACxB;;;;;;;OAOG;IACH,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,wEAAwE;IACxE,uBAAuB,EAAE,MAAM,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAC5D,gEAAgE;IAChE,wBAAwB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnD,gEAAgE;IAChE,uBAAuB,EAAE,MAAM,OAAO,CAAC;IACvC,wDAAwD;IACxD,sBAAsB,EAAE,MAAM,OAAO,CAAC;IACtC;;;;;OAKG;IACH,mBAAmB,EAAE,MAAM,4BAA4B,GAAG,IAAI,CAAC;CAChE;AAED,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAkB;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;IAC3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoC;IACnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA2B;IAC7D,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAqC;IAC7E,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA2B;IACpE,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAgB;IACxD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAgB;IACvD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA4C;gBAEpE,IAAI,EAAE,0BAA0B;IAiBtC,OAAO,CACX,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,wBAAwB,CAAC;IAgUpC;;;;OAIG;IACH,OAAO,CAAC,8BAA8B;IAoBtC,OAAO,CAAC,eAAe;IAcvB;;;;;OAKG;IACH,OAAO,CAAC,wBAAwB;YA0ElB,wBAAwB;IAoEtC,OAAO,CAAC,eAAe;IA8DvB;;;;;;;;;;;;;;;;;;;;;OAqBG;YACW,eAAe;CA2F9B"}
|