@aitne/daemon 0.1.10 → 0.1.11
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/adapter-watchdog.d.ts +70 -0
- package/dist/adapters/adapter-watchdog.js +115 -0
- package/dist/adapters/discord.d.ts +17 -1
- package/dist/adapters/discord.js +33 -0
- package/dist/adapters/notification-manager.d.ts +27 -1
- package/dist/adapters/notification-manager.js +54 -39
- package/dist/adapters/slack-adapter.d.ts +26 -1
- package/dist/adapters/slack-adapter.js +41 -0
- package/dist/adapters/telegram-adapter.d.ts +18 -1
- package/dist/adapters/telegram-adapter.js +41 -2
- package/dist/adapters/types.d.ts +20 -0
- package/dist/adapters/whatsapp-adapter.d.ts +26 -7
- package/dist/adapters/whatsapp-adapter.js +74 -21
- package/dist/api/env-writer.js +8 -5
- package/dist/api/helpers/agent-errors-registry.d.ts +5 -5
- package/dist/api/helpers/agent-errors-registry.js +5 -5
- package/dist/api/routes/agent.js +33 -12
- package/dist/api/routes/agents/index.js +75 -16
- package/dist/api/routes/agents/views.d.ts +37 -2
- package/dist/api/routes/agents/views.js +64 -2
- package/dist/api/routes/background-task.d.ts +22 -0
- package/dist/api/routes/background-task.js +338 -0
- package/dist/api/routes/browser-history.js +9 -1
- package/dist/api/routes/context/permissions.js +3 -2
- package/dist/api/routes/context/snapshots.js +0 -3
- package/dist/api/routes/context/write.js +3 -17
- package/dist/api/routes/dashboard/config.js +48 -12
- package/dist/api/routes/dashboard/cost-approvals.js +66 -0
- package/dist/api/routes/dashboard/notifications.js +9 -9
- package/dist/api/routes/integrations/crud-patch.js +5 -1
- package/dist/api/routes/integrations-reconcile.js +2 -2
- package/dist/api/routes/notion.d.ts +1 -1
- package/dist/api/routes/observations.js +7 -7
- package/dist/api/routes/obsidian.d.ts +1 -1
- package/dist/api/routes/receipts.js +5 -1
- package/dist/api/routes/setup-migrate.js +1 -1
- package/dist/api/routes/setup.js +1 -1
- package/dist/api/routes/task-flows.d.ts +1 -1
- package/dist/api/routes/task-flows.js +1 -1
- package/dist/api/routes/tuning.d.ts +29 -0
- package/dist/api/routes/tuning.js +304 -0
- package/dist/api/server.d.ts +44 -16
- package/dist/api/server.js +9 -0
- package/dist/bootstrap/adapters.d.ts +19 -0
- package/dist/bootstrap/adapters.js +61 -0
- package/dist/bootstrap/api.d.ts +5 -3
- package/dist/bootstrap/api.js +45 -13
- package/dist/bootstrap/catchup.d.ts +1 -1
- package/dist/bootstrap/catchup.js +11 -11
- package/dist/bootstrap/event-pipeline.d.ts +11 -0
- package/dist/bootstrap/event-pipeline.js +245 -7
- package/dist/bootstrap/observers.js +9 -6
- package/dist/bootstrap/schedule-helpers.d.ts +104 -6
- package/dist/bootstrap/schedule-helpers.js +172 -19
- package/dist/config.js +26 -12
- package/dist/core/agent-core.d.ts +33 -1
- package/dist/core/agent-core.js +36 -1
- package/dist/core/agents/activity-scan-cadence.d.ts +103 -0
- package/dist/core/agents/activity-scan-cadence.js +127 -0
- package/dist/core/agents/agent-route-override.d.ts +53 -0
- package/dist/core/agents/agent-route-override.js +69 -0
- package/dist/core/agents/builtin-registry.d.ts +51 -14
- package/dist/core/agents/builtin-registry.js +92 -15
- package/dist/core/agents/config-gate-reconcile.d.ts +38 -0
- package/dist/core/agents/config-gate-reconcile.js +51 -0
- package/dist/core/agents/cron-substitute.d.ts +1 -1
- package/dist/core/agents/cron-substitute.js +1 -1
- package/dist/core/agents/custom-routine-migration.d.ts +60 -0
- package/dist/core/agents/custom-routine-migration.js +149 -0
- package/dist/core/agents/firing-blocked.d.ts +1 -1
- package/dist/core/agents/hourly-cadence.d.ts +102 -0
- package/dist/core/agents/hourly-cadence.js +126 -0
- package/dist/core/agents/loader-boot.js +23 -0
- package/dist/core/agents/loader.d.ts +19 -0
- package/dist/core/agents/loader.js +34 -2
- package/dist/core/agents/override-merge.d.ts +1 -1
- package/dist/core/agents/override-merge.js +9 -1
- package/dist/core/agents/recurrence-convert.d.ts +1 -1
- package/dist/core/agents/recurrence-convert.js +1 -1
- package/dist/core/agents/recurring-schedule-adapter.js +8 -0
- package/dist/core/alerts.js +6 -6
- package/dist/core/backends/auth-health-monitor.d.ts +2 -2
- package/dist/core/backends/auth-health-monitor.js +1 -1
- package/dist/core/backends/backend-router.d.ts +27 -1
- package/dist/core/backends/backend-router.js +165 -1
- package/dist/core/backends/claude-code-core.d.ts +71 -31
- package/dist/core/backends/claude-code-core.js +282 -54
- package/dist/core/backends/cli-quota-guards.d.ts +29 -1
- package/dist/core/backends/cli-quota-guards.js +40 -5
- package/dist/core/backends/codex-core.d.ts +6 -0
- package/dist/core/backends/codex-core.js +22 -6
- package/dist/core/backends/failure-spend.d.ts +58 -0
- package/dist/core/backends/failure-spend.js +137 -0
- package/dist/core/backends/gemini-cli-core.d.ts +6 -0
- package/dist/core/backends/gemini-cli-core.js +25 -6
- package/dist/core/backends/model-registry.d.ts +1 -1
- package/dist/core/backends/model-registry.js +4 -4
- package/dist/core/backends/opencode-core.d.ts +1 -1
- package/dist/core/backends/opencode-core.js +5 -5
- package/dist/core/backends/plan-presets.js +39 -15
- package/dist/core/bang-commands/commands-cost.js +3 -1
- package/dist/core/bang-commands/commands-report.js +4 -3
- package/dist/core/bang-commands/commands-research.js +4 -1
- package/dist/core/bang-commands/commands-revert-tuning.d.ts +18 -0
- package/dist/core/bang-commands/commands-revert-tuning.js +63 -0
- package/dist/core/bang-commands/commands-stop-start.js +3 -3
- package/dist/core/bang-commands/commands-task-control.d.ts +19 -0
- package/dist/core/bang-commands/commands-task-control.js +147 -0
- package/dist/core/bang-commands/commands-wiki.js +5 -5
- package/dist/core/bang-commands/index.d.ts +2 -0
- package/dist/core/bang-commands/index.js +12 -0
- package/dist/core/bang-commands/registry.d.ts +12 -0
- package/dist/core/browser-history/research-cluster-fanout.d.ts +28 -14
- package/dist/core/browser-history/research-cluster-fanout.js +39 -16
- package/dist/core/channel-timeline.d.ts +5 -1
- package/dist/core/channel-timeline.js +13 -0
- package/dist/core/context/index-reconciler.js +5 -2
- package/dist/core/context/policy-index-reconciler.d.ts +6 -4
- package/dist/core/context/policy-index-runner.js +25 -6
- package/dist/core/context-builder-calendar.js +10 -2
- package/dist/core/context-builder-conversation.d.ts +8 -1
- package/dist/core/context-builder-conversation.js +41 -7
- package/dist/core/context-builder-yesterday.js +4 -3
- package/dist/core/context-builder.d.ts +7 -2
- package/dist/core/context-builder.js +62 -20
- package/dist/core/context-file-serializer.d.ts +1 -1
- package/dist/core/context-file-serializer.js +1 -1
- package/dist/core/context-health.js +2 -2
- package/dist/core/context-paths.d.ts +1 -1
- package/dist/core/context-paths.js +1 -1
- package/dist/core/context-validation/prepare-write.js +1 -1
- package/dist/core/context-validation/routine-rulebook.d.ts +1 -1
- package/dist/core/context-vault-aliases.d.ts +0 -13
- package/dist/core/context-vault-aliases.js +37 -0
- package/dist/core/custom-routines.d.ts +99 -0
- package/dist/core/custom-routines.js +187 -0
- package/dist/core/daemon-api-cli.js +49 -0
- package/dist/core/day-boundary.d.ts +46 -0
- package/dist/core/day-boundary.js +40 -0
- package/dist/core/dispatcher-activity-scan.d.ts +221 -0
- package/dist/core/dispatcher-activity-scan.js +775 -0
- package/dist/core/dispatcher-error-handling.d.ts +6 -11
- package/dist/core/dispatcher-error-handling.js +38 -62
- package/dist/core/dispatcher-hourly-check.js +6 -1
- package/dist/core/dispatcher-message-handler.d.ts +10 -0
- package/dist/core/dispatcher-message-handler.js +17 -0
- package/dist/core/dispatcher-morning-routine.d.ts +6 -6
- package/dist/core/dispatcher-morning-routine.js +13 -13
- package/dist/core/dispatcher-result-processor.d.ts +33 -0
- package/dist/core/dispatcher-result-processor.js +167 -11
- package/dist/core/dispatcher-scheduled-background-task.d.ts +42 -0
- package/dist/core/dispatcher-scheduled-background-task.js +89 -0
- package/dist/core/dispatcher-scheduled-tasks.d.ts +63 -1
- package/dist/core/dispatcher-scheduled-tasks.js +213 -6
- package/dist/core/dispatcher-task-delivery.d.ts +105 -0
- package/dist/core/dispatcher-task-delivery.js +555 -0
- package/dist/core/dispatcher-types.d.ts +48 -9
- package/dist/core/dispatcher-types.js +3 -3
- package/dist/core/dispatcher.d.ts +112 -31
- package/dist/core/dispatcher.js +284 -59
- package/dist/core/dm-freshness-metrics.d.ts +1 -1
- package/dist/core/drift-effects.js +2 -2
- package/dist/core/feedback/consolidation-prep.js +17 -5
- package/dist/core/feedback/eviction-scorer.js +6 -2
- package/dist/core/feedback/lesson-format.js +9 -4
- package/dist/core/feedback/lesson-injection.d.ts +1 -1
- package/dist/core/feedback/lesson-injection.js +17 -2
- package/dist/core/feedback/lesson-store-overview.d.ts +8 -4
- package/dist/core/feedback/lesson-store-overview.js +8 -4
- package/dist/core/feedback/regeneralization-prep.js +29 -16
- package/dist/core/feedback/self-performance-prep.d.ts +186 -0
- package/dist/core/feedback/self-performance-prep.js +541 -0
- package/dist/core/feedback/tuning-actuator.d.ts +198 -0
- package/dist/core/feedback/tuning-actuator.js +432 -0
- package/dist/core/feedback/tuning-recommender.d.ts +247 -0
- package/dist/core/feedback/tuning-recommender.js +580 -0
- package/dist/core/feedback/tuning-revert-monitor.d.ts +90 -0
- package/dist/core/feedback/tuning-revert-monitor.js +213 -0
- package/dist/core/health-monitor.d.ts +6 -0
- package/dist/core/health-monitor.js +1 -1
- package/dist/core/injection-policy.d.ts +4 -4
- package/dist/core/injection-policy.js +4 -4
- package/dist/core/integration-main-backend.js +4 -0
- package/dist/core/management-md.d.ts +2 -2
- package/dist/core/management-md.js +51 -13
- package/dist/core/morning/orchestrator.d.ts +2 -2
- package/dist/core/morning/orchestrator.js +2 -2
- package/dist/core/notification-gate.d.ts +64 -0
- package/dist/core/notification-gate.js +51 -0
- package/dist/core/notification-rate-limit.d.ts +40 -0
- package/dist/core/notification-rate-limit.js +50 -0
- package/dist/core/policy-files.d.ts +1 -1
- package/dist/core/policy-files.js +2 -2
- package/dist/core/pre-pass-freshness.d.ts +4 -4
- package/dist/core/retention.d.ts +5 -0
- package/dist/core/retention.js +20 -4
- package/dist/core/review-context.d.ts +1 -1
- package/dist/core/review-context.js +10 -5
- package/dist/core/roadmap-write-lock.d.ts +2 -1
- package/dist/core/roadmap-write-lock.js +15 -10
- package/dist/core/routine-acquisition-plan.d.ts +47 -1
- package/dist/core/routine-acquisition-plan.js +78 -20
- package/dist/core/routine-fetch-window-retry.js +7 -4
- package/dist/core/routine-fetch-window-runner.d.ts +39 -3
- package/dist/core/routine-fetch-window-runner.js +264 -13
- package/dist/core/routine-windows.d.ts +2 -2
- package/dist/core/routine-windows.js +8 -5
- package/dist/core/scheduler.d.ts +175 -16
- package/dist/core/scheduler.js +559 -102
- package/dist/core/signal-detector.d.ts +12 -0
- package/dist/core/signal-detector.js +53 -9
- package/dist/core/skills-compiler-denied-tools.js +2 -2
- package/dist/core/skills-compiler-skill-index.d.ts +2 -2
- package/dist/core/skills-compiler-skill-index.js +2 -2
- package/dist/core/skills-compiler-variants.d.ts +1 -1
- package/dist/core/skills-compiler-variants.js +8 -0
- package/dist/core/skills-compiler.d.ts +29 -26
- package/dist/core/skills-compiler.js +117 -81
- package/dist/core/skills-manifest.d.ts +37 -0
- package/dist/core/skills-manifest.js +73 -2
- package/dist/core/sleep-inhibitor.d.ts +79 -0
- package/dist/core/sleep-inhibitor.js +132 -0
- package/dist/core/slim-system-prompt-loader.d.ts +77 -0
- package/dist/core/slim-system-prompt-loader.js +141 -0
- package/dist/core/spawn-gates.d.ts +126 -0
- package/dist/core/spawn-gates.js +180 -0
- package/dist/core/today-direct-writer.d.ts +2 -2
- package/dist/core/today-direct-writer.js +1 -1
- package/dist/core/today-write-lock.d.ts +4 -2
- package/dist/core/today-write-lock.js +30 -20
- package/dist/core/wake-detector.d.ts +55 -0
- package/dist/core/wake-detector.js +80 -0
- package/dist/core/wiki/compile-lock.d.ts +1 -1
- package/dist/core/wiki/compile-lock.js +1 -1
- package/dist/core/workdir.js +15 -6
- package/dist/db/activity-scan-signals.d.ts +77 -0
- package/dist/db/activity-scan-signals.js +378 -0
- package/dist/db/agents-store.d.ts +28 -0
- package/dist/db/agents-store.js +62 -0
- package/dist/db/background-task-clarifications-store.d.ts +81 -0
- package/dist/db/background-task-clarifications-store.js +152 -0
- package/dist/db/background-task-store.d.ts +207 -0
- package/dist/db/background-task-store.js +380 -0
- package/dist/db/browser-history-store.d.ts +39 -6
- package/dist/db/browser-history-store.js +51 -7
- package/dist/db/browser-task-clarifications-store.d.ts +12 -0
- package/dist/db/browser-task-clarifications-store.js +35 -5
- package/dist/db/browser-task-store.d.ts +3 -0
- package/dist/db/browser-task-store.js +29 -4
- package/dist/db/deferred-dm.d.ts +86 -0
- package/dist/db/deferred-dm.js +199 -0
- package/dist/db/migrations.js +330 -0
- package/dist/db/observations.d.ts +2 -2
- package/dist/db/observations.js +3 -3
- package/dist/db/schema.js +217 -16
- package/dist/db/voice-transcripts-store.d.ts +1 -1
- package/dist/index.js +86 -29
- package/dist/messaging/browser-task-mcp-notifier.d.ts +12 -70
- package/dist/messaging/browser-task-mcp-notifier.js +30 -151
- package/dist/messaging/browser-task-screenshot-attachment.d.ts +15 -0
- package/dist/messaging/browser-task-screenshot-attachment.js +63 -0
- package/dist/observers/delegated-sync-worker.d.ts +6 -6
- package/dist/observers/delegated-sync-worker.js +10 -10
- package/dist/observers/git-delegated-cron.d.ts +1 -1
- package/dist/observers/git-delegated-cron.js +2 -2
- package/dist/observers/github-poller-classifier.d.ts +3 -3
- package/dist/observers/github-poller-classifier.js +3 -3
- package/dist/observers/imminent-event-scheduler.d.ts +1 -1
- package/dist/observers/imminent-event-scheduler.js +1 -1
- package/dist/observers/mail-poller.d.ts +1 -0
- package/dist/observers/mail-poller.js +42 -3
- package/dist/observers/observation-summarizer/summarizer-client.d.ts +2 -2
- package/dist/observers/observation-summarizer/summarizer-client.js +2 -2
- package/dist/observers/observation-summarizer/worker.d.ts +2 -2
- package/dist/observers/observation-summarizer/worker.js +4 -4
- package/dist/observers/obsidian-watcher.d.ts +1 -1
- package/dist/observers/obsidian-watcher.js +1 -1
- package/dist/safety/agent-write-tracker.d.ts +4 -4
- package/dist/safety/agent-write-tracker.js +4 -4
- package/dist/safety/audit.d.ts +43 -5
- package/dist/safety/audit.js +86 -18
- package/dist/safety/risk-classifier.d.ts +6 -0
- package/dist/safety/risk-classifier.js +75 -11
- package/dist/scheduler/activity-scan-gate.d.ts +86 -0
- package/dist/scheduler/activity-scan-gate.js +132 -0
- package/dist/services/background-task/background-task-budget.d.ts +80 -0
- package/dist/services/background-task/background-task-budget.js +91 -0
- package/dist/services/background-task/background-task-driver.d.ts +105 -0
- package/dist/services/background-task/background-task-driver.js +416 -0
- package/dist/services/background-task/background-task-runner.d.ts +96 -0
- package/dist/services/background-task/background-task-runner.js +673 -0
- package/dist/services/background-task/background-task-tools.d.ts +84 -0
- package/dist/services/background-task/background-task-tools.js +247 -0
- package/dist/services/background-task/background-task-transition-events.d.ts +43 -0
- package/dist/services/background-task/background-task-transition-events.js +54 -0
- package/dist/services/browser-history/automation/egress-denylist.d.ts +1 -1
- package/dist/services/browser-history/automation/egress-denylist.js +16 -6
- package/dist/services/browser-history/managed-chromium/sandbox-launcher.js +0 -1
- package/dist/services/browser-task/browser-task-runner.js +53 -8
- package/dist/services/observations-batch.d.ts +1 -1
- package/dist/services/observations-batch.js +2 -2
- package/dist/settings/runtime-settings.d.ts +38 -11
- package/dist/settings/runtime-settings.js +203 -40
- package/dist/settings/settings-store.js +11 -3
- package/package.json +4 -4
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage-1 deterministic gate for the three-stage activity_scan funnel
|
|
3
|
+
* (cost-reduction-structural §B). Pure function over a `ActivityScanSignals`
|
|
4
|
+
* snapshot — no DB handle, no clock, no I/O. The dispatcher computes the
|
|
5
|
+
* snapshot via `computeActivityScanSignals`, then asks this module which
|
|
6
|
+
* stage to enter.
|
|
7
|
+
*
|
|
8
|
+
* The four possible decisions:
|
|
9
|
+
* - `stage0_silent`: consume observations, append a single Agent Log
|
|
10
|
+
* line via the daemon-direct writer, return. No LLM call.
|
|
11
|
+
* - `stage2`: lite-tier triage (only when `stage2Enabled`). Strict
|
|
12
|
+
* JSON-only output decides log_only vs escalate.
|
|
13
|
+
* - `stage3`: existing full activity_scan session.
|
|
14
|
+
*
|
|
15
|
+
* HOURLY_CHECK_GATE_REDESIGN_PLAN.md Phase 4 collapsed the gateMode
|
|
16
|
+
* enum (`off`/`shadow`/`live`) into a single execution path. The gate's
|
|
17
|
+
* verdict is always honoured.
|
|
18
|
+
*/
|
|
19
|
+
import type { ActivityScanSignals } from "../db/activity-scan-signals.js";
|
|
20
|
+
export type ActivityScanGateStage = "stage0_silent" | "stage2" | "stage3";
|
|
21
|
+
export interface ActivityScanGateConfig {
|
|
22
|
+
/**
|
|
23
|
+
* Hours since the last Stage 3 run after which the gate force-runs at
|
|
24
|
+
* least Stage 2 (or Stage 3 if novelty is high). Bounds the worst case
|
|
25
|
+
* where Stage 0/1 keeps short-circuiting on a quiet day.
|
|
26
|
+
*/
|
|
27
|
+
heartbeatHours: number;
|
|
28
|
+
/**
|
|
29
|
+
* When `false`, low-signal cases bypass Stage 2 entirely and route to
|
|
30
|
+
* Stage 3. The cautious default — Stage 2 only takes effect after
|
|
31
|
+
* shadow telemetry validates the decision boundary.
|
|
32
|
+
*/
|
|
33
|
+
stage2Enabled: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Below this threshold, `pendingObsCount` alone does not imply
|
|
36
|
+
* Stage 3. Default 0 — any pending observation hits the low-signal
|
|
37
|
+
* branch which routes to Stage 2 or Stage 3 depending on the flag.
|
|
38
|
+
*/
|
|
39
|
+
pendingObsLowSignalCeiling?: number;
|
|
40
|
+
}
|
|
41
|
+
export interface ActivityScanGateDecision {
|
|
42
|
+
stage: ActivityScanGateStage;
|
|
43
|
+
/** Short, telemetry-friendly explanation. */
|
|
44
|
+
reason: string;
|
|
45
|
+
/** Snapshot at decision time (echoed for the audit row). */
|
|
46
|
+
signals: ActivityScanSignals;
|
|
47
|
+
}
|
|
48
|
+
export declare function decideStage(signals: ActivityScanSignals, config: ActivityScanGateConfig): ActivityScanGateDecision;
|
|
49
|
+
/**
|
|
50
|
+
* The dispatcher logs every cron tick to `agent_actions` regardless of
|
|
51
|
+
* which stage runs. Helper that builds the JSON payload from a decision
|
|
52
|
+
* so the schema stays consistent across stages and call-sites.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildGateAuditDetail(decision: ActivityScanGateDecision, extra: {
|
|
55
|
+
appliedDecision: ActivityScanGateStage;
|
|
56
|
+
/** Stage-2 LLM verdict, when Stage 2 ran. */
|
|
57
|
+
stage2Verdict?: "log_only" | "escalate" | "failed";
|
|
58
|
+
/** Forced-run flag from `/api/agent/run-now` etc. */
|
|
59
|
+
forced?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* HOURLY_CHECK_GATE_REDESIGN_PLAN.md §3.5 — true when pre-pass for
|
|
62
|
+
* any non-direct integration failed in `harvestForGate` and the
|
|
63
|
+
* gate force-escalated to `stage3` regardless of the signal
|
|
64
|
+
* verdict. Surfaced in the audit row so dashboards can flag the
|
|
65
|
+
* cautious-escalate path.
|
|
66
|
+
*/
|
|
67
|
+
cautiousEscalate?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Original gate verdict captured BEFORE cautious-escalate
|
|
70
|
+
* overwrote it. Persisted as `pre_escalate_gate_*` so dashboards
|
|
71
|
+
* can answer "what would the gate have said if pre-pass had
|
|
72
|
+
* succeeded?" — distinguishes a tick that was structurally
|
|
73
|
+
* stage3 anyway from one that was forced up from stage0_silent
|
|
74
|
+
* by a transient fetch outage.
|
|
75
|
+
*/
|
|
76
|
+
preEscalateGateStage?: ActivityScanGateStage;
|
|
77
|
+
preEscalateGateReason?: string;
|
|
78
|
+
}): Record<string, unknown>;
|
|
79
|
+
/**
|
|
80
|
+
* Build the `<gate_decision>` block injected into Stage 3's prompt so
|
|
81
|
+
* the routine knows *why* it was escalated and can prioritize.
|
|
82
|
+
*/
|
|
83
|
+
export declare function renderGateDecisionBlock(decision: ActivityScanGateDecision, extra: {
|
|
84
|
+
forced?: boolean;
|
|
85
|
+
cautiousEscalate?: boolean;
|
|
86
|
+
}): string;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage-1 deterministic gate for the three-stage activity_scan funnel
|
|
3
|
+
* (cost-reduction-structural §B). Pure function over a `ActivityScanSignals`
|
|
4
|
+
* snapshot — no DB handle, no clock, no I/O. The dispatcher computes the
|
|
5
|
+
* snapshot via `computeActivityScanSignals`, then asks this module which
|
|
6
|
+
* stage to enter.
|
|
7
|
+
*
|
|
8
|
+
* The four possible decisions:
|
|
9
|
+
* - `stage0_silent`: consume observations, append a single Agent Log
|
|
10
|
+
* line via the daemon-direct writer, return. No LLM call.
|
|
11
|
+
* - `stage2`: lite-tier triage (only when `stage2Enabled`). Strict
|
|
12
|
+
* JSON-only output decides log_only vs escalate.
|
|
13
|
+
* - `stage3`: existing full activity_scan session.
|
|
14
|
+
*
|
|
15
|
+
* HOURLY_CHECK_GATE_REDESIGN_PLAN.md Phase 4 collapsed the gateMode
|
|
16
|
+
* enum (`off`/`shadow`/`live`) into a single execution path. The gate's
|
|
17
|
+
* verdict is always honoured.
|
|
18
|
+
*/
|
|
19
|
+
const HIGH_NOVELTY_FLOOR = 3;
|
|
20
|
+
const ESCALATE_NOVELTY_FLOOR = 2;
|
|
21
|
+
export function decideStage(signals, config) {
|
|
22
|
+
// Heartbeat: even on quiet days, exercise Stage 2/3 every N hours so
|
|
23
|
+
// the gate's signal compute is exercised end-to-end. We pick Stage 3
|
|
24
|
+
// when there is *some* novelty pending, Stage 2 otherwise — Stage 2
|
|
25
|
+
// is the cheaper lite-tier shape and Stage 3 wastes context if there
|
|
26
|
+
// is nothing to act on. If Stage 2 is disabled, the cautious fallback
|
|
27
|
+
// is Stage 3.
|
|
28
|
+
if (signals.hoursSinceLastStage3Run >= config.heartbeatHours) {
|
|
29
|
+
if (numericNovelty(signals.maxNoveltyScore) >= ESCALATE_NOVELTY_FLOOR) {
|
|
30
|
+
return decision("stage3", "heartbeat_due_with_novelty", signals);
|
|
31
|
+
}
|
|
32
|
+
return decision(config.stage2Enabled ? "stage2" : "stage3", "heartbeat_due", signals);
|
|
33
|
+
}
|
|
34
|
+
// Hard escalate: any high-priority signal goes straight to Stage 3.
|
|
35
|
+
if (numericNovelty(signals.maxNoveltyScore) >= HIGH_NOVELTY_FLOOR) {
|
|
36
|
+
return decision("stage3", "high_novelty", signals);
|
|
37
|
+
}
|
|
38
|
+
if (signals.calendarHasConflict) {
|
|
39
|
+
return decision("stage3", "calendar_conflict", signals);
|
|
40
|
+
}
|
|
41
|
+
if (signals.vipMailUnreadCount > 0) {
|
|
42
|
+
return decision("stage3", "vip_mail_unread", signals);
|
|
43
|
+
}
|
|
44
|
+
if (signals.agentPlanOverdueCount > 0) {
|
|
45
|
+
return decision("stage3", "agent_plan_overdue", signals);
|
|
46
|
+
}
|
|
47
|
+
if (signals.scheduleApproachingCount > 0) {
|
|
48
|
+
return decision("stage3", "schedule_approaching", signals);
|
|
49
|
+
}
|
|
50
|
+
// No signals at all → Stage 0 silent.
|
|
51
|
+
if (signals.pendingObsCount === 0 && !signals.calendarHas24hChange) {
|
|
52
|
+
return decision("stage0_silent", "no_signals", signals);
|
|
53
|
+
}
|
|
54
|
+
// Low signals only → Stage 2 if enabled, else Stage 3 (cautious default).
|
|
55
|
+
// The pendingObsLowSignalCeiling lets an operator widen the silent-skip
|
|
56
|
+
// band ("at most N noise observations is still nothing to act on"); the
|
|
57
|
+
// default 0 leaves the design's conservative posture intact.
|
|
58
|
+
const ceiling = Math.max(0, config.pendingObsLowSignalCeiling ?? 0);
|
|
59
|
+
if (signals.pendingObsCount <= ceiling
|
|
60
|
+
&& !signals.calendarHas24hChange) {
|
|
61
|
+
return decision("stage0_silent", "low_signal_under_ceiling", signals);
|
|
62
|
+
}
|
|
63
|
+
return decision(config.stage2Enabled ? "stage2" : "stage3", "low_signal_default", signals);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The dispatcher logs every cron tick to `agent_actions` regardless of
|
|
67
|
+
* which stage runs. Helper that builds the JSON payload from a decision
|
|
68
|
+
* so the schema stays consistent across stages and call-sites.
|
|
69
|
+
*/
|
|
70
|
+
export function buildGateAuditDetail(decision, extra) {
|
|
71
|
+
return {
|
|
72
|
+
stage_reached: extra.appliedDecision,
|
|
73
|
+
gate_stage: decision.stage,
|
|
74
|
+
gate_reason: decision.reason,
|
|
75
|
+
forced: extra.forced ?? false,
|
|
76
|
+
...(extra.stage2Verdict ? { stage2_verdict: extra.stage2Verdict } : {}),
|
|
77
|
+
...(extra.cautiousEscalate ? { cautious_escalate: true } : {}),
|
|
78
|
+
...(extra.preEscalateGateStage
|
|
79
|
+
? { pre_escalate_gate_stage: extra.preEscalateGateStage }
|
|
80
|
+
: {}),
|
|
81
|
+
...(extra.preEscalateGateReason
|
|
82
|
+
? { pre_escalate_gate_reason: extra.preEscalateGateReason }
|
|
83
|
+
: {}),
|
|
84
|
+
signal_snapshot: {
|
|
85
|
+
pendingObsCount: decision.signals.pendingObsCount,
|
|
86
|
+
maxNoveltyScore: decision.signals.maxNoveltyScore,
|
|
87
|
+
noveltyDistribution: decision.signals.noveltyDistribution,
|
|
88
|
+
vipMailUnreadCount: decision.signals.vipMailUnreadCount,
|
|
89
|
+
calendarHas24hChange: decision.signals.calendarHas24hChange,
|
|
90
|
+
calendarHasConflict: decision.signals.calendarHasConflict,
|
|
91
|
+
agentPlanOverdueCount: decision.signals.agentPlanOverdueCount,
|
|
92
|
+
scheduleApproachingCount: decision.signals.scheduleApproachingCount,
|
|
93
|
+
hoursSinceLastStage3Run: serializeHours(decision.signals.hoursSinceLastStage3Run),
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Build the `<gate_decision>` block injected into Stage 3's prompt so
|
|
99
|
+
* the routine knows *why* it was escalated and can prioritize.
|
|
100
|
+
*/
|
|
101
|
+
export function renderGateDecisionBlock(decision, extra) {
|
|
102
|
+
return [
|
|
103
|
+
"<gate_decision>",
|
|
104
|
+
` triggered_by: ${decision.stage === "stage3" ? "stage1" : "stage2_escalation"}`,
|
|
105
|
+
` reason: ${decision.reason}`,
|
|
106
|
+
` forced: ${extra.forced ? "true" : "false"}`,
|
|
107
|
+
...(extra.cautiousEscalate ? [" cautious_escalate: true"] : []),
|
|
108
|
+
` signals_snapshot: ${JSON.stringify({
|
|
109
|
+
maxNovelty: decision.signals.maxNoveltyScore,
|
|
110
|
+
pendingObs: decision.signals.pendingObsCount,
|
|
111
|
+
vipMail: decision.signals.vipMailUnreadCount,
|
|
112
|
+
calConflict: decision.signals.calendarHasConflict,
|
|
113
|
+
agentPlanOverdue: decision.signals.agentPlanOverdueCount,
|
|
114
|
+
scheduleApproaching: decision.signals.scheduleApproachingCount,
|
|
115
|
+
})}`,
|
|
116
|
+
"</gate_decision>",
|
|
117
|
+
].join("\n");
|
|
118
|
+
}
|
|
119
|
+
function numericNovelty(score) {
|
|
120
|
+
// Cautious default — null (no summary done yet) is treated as 2 so a
|
|
121
|
+
// backlog of unsummarized observations does NOT silently skip the
|
|
122
|
+
// routine. The design doc calls this out explicitly under "edge cases".
|
|
123
|
+
return score ?? ESCALATE_NOVELTY_FLOOR;
|
|
124
|
+
}
|
|
125
|
+
function decision(stage, reason, signals) {
|
|
126
|
+
return { stage, reason, signals };
|
|
127
|
+
}
|
|
128
|
+
function serializeHours(value) {
|
|
129
|
+
if (!Number.isFinite(value))
|
|
130
|
+
return null;
|
|
131
|
+
return Number(value.toFixed(2));
|
|
132
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background-task budget envelope — BACKGROUND_TASK_RUNNER_DESIGN.md §6 / §10.1.
|
|
3
|
+
*
|
|
4
|
+
* Pure resolution of the `(modelId, maxTurns, maxBudgetUsd,
|
|
5
|
+
* executeTimeoutMinutes)` envelope for a background-task worker from
|
|
6
|
+
* three inputs:
|
|
7
|
+
*
|
|
8
|
+
* 1. The per-task `tier` (`lite` | `medium` | `high`) — selects the
|
|
9
|
+
* base turn/budget/timeout envelope.
|
|
10
|
+
* 2. The optional per-task `maxBudgetUsd` override (POST body).
|
|
11
|
+
* 3. The operator-editable `process_backend_config` row for
|
|
12
|
+
* `process_key='background_task'` (model + caps) — same chokepoint
|
|
13
|
+
* as browser-task's `loadBrowserTaskBackendBinding`.
|
|
14
|
+
*
|
|
15
|
+
* The worker is Claude-only (it drives the Claude Agent SDK `query()`
|
|
16
|
+
* loop directly, like browser_task). A `process_backend_config` row that
|
|
17
|
+
* pins a non-Claude backend is refused with `backend_misconfigured` so a
|
|
18
|
+
* mis-set `/settings/models` row fails fast rather than silently doing
|
|
19
|
+
* nothing.
|
|
20
|
+
*
|
|
21
|
+
* 100% coverage gate — the I/O (DB read) lives in
|
|
22
|
+
* `loadBackgroundTaskBinding`; this module is the pure arithmetic.
|
|
23
|
+
*/
|
|
24
|
+
import type { BackgroundTaskTier } from "../../db/background-task-store.js";
|
|
25
|
+
/** Fallback model when the `process_backend_config` row is missing or
|
|
26
|
+
* carries an empty `main_model`. Mirrors the seed default. */
|
|
27
|
+
export declare const BACKGROUND_TASK_FALLBACK_CLAUDE_MODEL = "claude-sonnet-4-6";
|
|
28
|
+
export declare const BACKGROUND_TASK_DEFAULT_TIER: BackgroundTaskTier;
|
|
29
|
+
/** Hard upper bounds. The seed sits well below; the caps give the
|
|
30
|
+
* operator room to relax via `/settings/models` while pinning a ceiling
|
|
31
|
+
* no per-task override can blow past. Background tasks are the
|
|
32
|
+
* long-running surface, so the turn / timeout ceilings are far higher
|
|
33
|
+
* than browser-task's (60 turns / 5 min) — a deep research or
|
|
34
|
+
* multi-repo audit legitimately runs for many turns over many minutes. */
|
|
35
|
+
export declare const BACKGROUND_TASK_MAX_TURNS_CAP = 120;
|
|
36
|
+
export declare const BACKGROUND_TASK_MAX_BUDGET_USD_CAP = 15;
|
|
37
|
+
export declare const BACKGROUND_TASK_MAX_EXECUTE_TIMEOUT_MINUTES = 120;
|
|
38
|
+
export interface BackgroundTaskEnvelope {
|
|
39
|
+
modelId: string;
|
|
40
|
+
maxTurns: number;
|
|
41
|
+
maxBudgetUsd: number;
|
|
42
|
+
executeTimeoutMinutes: number;
|
|
43
|
+
}
|
|
44
|
+
interface TierEnvelope {
|
|
45
|
+
maxTurns: number;
|
|
46
|
+
maxBudgetUsd: number;
|
|
47
|
+
executeTimeoutMinutes: number;
|
|
48
|
+
}
|
|
49
|
+
export declare function tierEnvelope(tier: BackgroundTaskTier): TierEnvelope;
|
|
50
|
+
/** Shape of the operator-editable `process_backend_config` row, already
|
|
51
|
+
* read from the DB (or null when absent). */
|
|
52
|
+
export interface BackgroundTaskProcessConfig {
|
|
53
|
+
mainBackend: string;
|
|
54
|
+
mainModel: string | null;
|
|
55
|
+
maxTurns: number | null;
|
|
56
|
+
maxBudgetUsd: number | null;
|
|
57
|
+
}
|
|
58
|
+
export interface ResolveEnvelopeInput {
|
|
59
|
+
tier: BackgroundTaskTier | null;
|
|
60
|
+
/** Per-task budget override (POST body). Clamped to the hard cap. */
|
|
61
|
+
maxBudgetUsd: number | null;
|
|
62
|
+
processConfig: BackgroundTaskProcessConfig | null;
|
|
63
|
+
}
|
|
64
|
+
export type ResolveEnvelopeResult = {
|
|
65
|
+
ok: true;
|
|
66
|
+
envelope: BackgroundTaskEnvelope;
|
|
67
|
+
} | {
|
|
68
|
+
ok: false;
|
|
69
|
+
reason: "backend_misconfigured";
|
|
70
|
+
detail: string;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Pure envelope resolution. Branches:
|
|
74
|
+
* - processConfig present + `mainBackend !== 'claude'` → REFUSE.
|
|
75
|
+
* - otherwise: model from the config (or fallback); turns from the
|
|
76
|
+
* config (or tier base), clamped; budget = per-task override ?? config
|
|
77
|
+
* budget ?? tier base, clamped; timeout from the tier base, clamped.
|
|
78
|
+
*/
|
|
79
|
+
export declare function resolveBackgroundTaskEnvelope(input: ResolveEnvelopeInput): ResolveEnvelopeResult;
|
|
80
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background-task budget envelope — BACKGROUND_TASK_RUNNER_DESIGN.md §6 / §10.1.
|
|
3
|
+
*
|
|
4
|
+
* Pure resolution of the `(modelId, maxTurns, maxBudgetUsd,
|
|
5
|
+
* executeTimeoutMinutes)` envelope for a background-task worker from
|
|
6
|
+
* three inputs:
|
|
7
|
+
*
|
|
8
|
+
* 1. The per-task `tier` (`lite` | `medium` | `high`) — selects the
|
|
9
|
+
* base turn/budget/timeout envelope.
|
|
10
|
+
* 2. The optional per-task `maxBudgetUsd` override (POST body).
|
|
11
|
+
* 3. The operator-editable `process_backend_config` row for
|
|
12
|
+
* `process_key='background_task'` (model + caps) — same chokepoint
|
|
13
|
+
* as browser-task's `loadBrowserTaskBackendBinding`.
|
|
14
|
+
*
|
|
15
|
+
* The worker is Claude-only (it drives the Claude Agent SDK `query()`
|
|
16
|
+
* loop directly, like browser_task). A `process_backend_config` row that
|
|
17
|
+
* pins a non-Claude backend is refused with `backend_misconfigured` so a
|
|
18
|
+
* mis-set `/settings/models` row fails fast rather than silently doing
|
|
19
|
+
* nothing.
|
|
20
|
+
*
|
|
21
|
+
* 100% coverage gate — the I/O (DB read) lives in
|
|
22
|
+
* `loadBackgroundTaskBinding`; this module is the pure arithmetic.
|
|
23
|
+
*/
|
|
24
|
+
/** Fallback model when the `process_backend_config` row is missing or
|
|
25
|
+
* carries an empty `main_model`. Mirrors the seed default. */
|
|
26
|
+
export const BACKGROUND_TASK_FALLBACK_CLAUDE_MODEL = "claude-sonnet-4-6";
|
|
27
|
+
export const BACKGROUND_TASK_DEFAULT_TIER = "medium";
|
|
28
|
+
/** Hard upper bounds. The seed sits well below; the caps give the
|
|
29
|
+
* operator room to relax via `/settings/models` while pinning a ceiling
|
|
30
|
+
* no per-task override can blow past. Background tasks are the
|
|
31
|
+
* long-running surface, so the turn / timeout ceilings are far higher
|
|
32
|
+
* than browser-task's (60 turns / 5 min) — a deep research or
|
|
33
|
+
* multi-repo audit legitimately runs for many turns over many minutes. */
|
|
34
|
+
export const BACKGROUND_TASK_MAX_TURNS_CAP = 120;
|
|
35
|
+
export const BACKGROUND_TASK_MAX_BUDGET_USD_CAP = 15.0;
|
|
36
|
+
export const BACKGROUND_TASK_MAX_EXECUTE_TIMEOUT_MINUTES = 120;
|
|
37
|
+
/** Per-tier base envelope. `process_backend_config` overrides
|
|
38
|
+
* model/turns/budget; the tier is the source of the execute-timeout
|
|
39
|
+
* (which has no `process_backend_config` column) and the fallback when
|
|
40
|
+
* the config row is absent. */
|
|
41
|
+
const TIER_ENVELOPES = {
|
|
42
|
+
lite: { maxTurns: 15, maxBudgetUsd: 0.5, executeTimeoutMinutes: 10 },
|
|
43
|
+
medium: { maxTurns: 40, maxBudgetUsd: 2.0, executeTimeoutMinutes: 30 },
|
|
44
|
+
high: { maxTurns: 80, maxBudgetUsd: 8.0, executeTimeoutMinutes: 60 },
|
|
45
|
+
};
|
|
46
|
+
export function tierEnvelope(tier) {
|
|
47
|
+
return TIER_ENVELOPES[tier];
|
|
48
|
+
}
|
|
49
|
+
function clampPositive(value, cap, fallback) {
|
|
50
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
51
|
+
return fallback;
|
|
52
|
+
return Math.min(value, cap);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Pure envelope resolution. Branches:
|
|
56
|
+
* - processConfig present + `mainBackend !== 'claude'` → REFUSE.
|
|
57
|
+
* - otherwise: model from the config (or fallback); turns from the
|
|
58
|
+
* config (or tier base), clamped; budget = per-task override ?? config
|
|
59
|
+
* budget ?? tier base, clamped; timeout from the tier base, clamped.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveBackgroundTaskEnvelope(input) {
|
|
62
|
+
const tier = input.tier ?? BACKGROUND_TASK_DEFAULT_TIER;
|
|
63
|
+
const base = TIER_ENVELOPES[tier];
|
|
64
|
+
const cfg = input.processConfig;
|
|
65
|
+
if (cfg && cfg.mainBackend !== "claude") {
|
|
66
|
+
return {
|
|
67
|
+
ok: false,
|
|
68
|
+
reason: "backend_misconfigured",
|
|
69
|
+
detail: `process_backend_config.main_backend='${cfg.mainBackend}' — background_task drives the Claude Agent SDK directly; refusing to dispatch. Set background_task back to claude in /settings/models.`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const modelId = cfg && typeof cfg.mainModel === "string" && cfg.mainModel.length > 0
|
|
73
|
+
? cfg.mainModel
|
|
74
|
+
: BACKGROUND_TASK_FALLBACK_CLAUDE_MODEL;
|
|
75
|
+
const rawTurns = cfg && typeof cfg.maxTurns === "number" && Number.isFinite(cfg.maxTurns)
|
|
76
|
+
? Math.max(1, Math.floor(cfg.maxTurns))
|
|
77
|
+
: base.maxTurns;
|
|
78
|
+
const maxTurns = Math.min(rawTurns, BACKGROUND_TASK_MAX_TURNS_CAP);
|
|
79
|
+
// Per-task override wins, then the operator config, then the tier base.
|
|
80
|
+
const budgetSource = input.maxBudgetUsd != null
|
|
81
|
+
? input.maxBudgetUsd
|
|
82
|
+
: cfg && cfg.maxBudgetUsd != null
|
|
83
|
+
? cfg.maxBudgetUsd
|
|
84
|
+
: base.maxBudgetUsd;
|
|
85
|
+
const maxBudgetUsd = clampPositive(budgetSource, BACKGROUND_TASK_MAX_BUDGET_USD_CAP, base.maxBudgetUsd);
|
|
86
|
+
const executeTimeoutMinutes = Math.min(base.executeTimeoutMinutes, BACKGROUND_TASK_MAX_EXECUTE_TIMEOUT_MINUTES);
|
|
87
|
+
return {
|
|
88
|
+
ok: true,
|
|
89
|
+
envelope: { modelId, maxTurns, maxBudgetUsd, executeTimeoutMinutes },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background-task driver — generic Claude Agent SDK glue for the
|
|
3
|
+
* per-task worker loop. BACKGROUND_TASK_RUNNER_DESIGN.md §4.1.
|
|
4
|
+
*
|
|
5
|
+
* The browser-task driver's analogue, with the entire Playwright /
|
|
6
|
+
* managed-Chromium / allowlist / final-confirm plane removed. A worker
|
|
7
|
+
* is a plain `query()` session seeded with a SELF-CONTAINED brief and a
|
|
8
|
+
* three-tool MCP envelope (`read_memory`, `ask_user`, `finish`) plus the
|
|
9
|
+
* SDK's `WebSearch` / `WebFetch` for research-type work. It opts out of
|
|
10
|
+
* the `<user>` / `<management_rules>` injection (`settingSources:
|
|
11
|
+
* ["project"]`, as browser-task does) — the brief carries the context,
|
|
12
|
+
* the output-language directive, persona hints for the `draft`, and the
|
|
13
|
+
* notification policy / criteria.
|
|
14
|
+
*
|
|
15
|
+
* Responsibilities:
|
|
16
|
+
* 1. Resolve the `(model, maxTurns, maxBudgetUsd, executeTimeout)`
|
|
17
|
+
* envelope from `process_backend_config` + the row's tier/budget
|
|
18
|
+
* (`background-task-budget.ts`), pinned for the task's lifetime.
|
|
19
|
+
* 2. Render a per-task workdir (empty dir + CLAUDE.md agent profile).
|
|
20
|
+
* 3. Drive `query()` until terminal, honouring the AbortController
|
|
21
|
+
* (cancel + timeout) — no Playwright resources to release.
|
|
22
|
+
* 4. Hand back a `DriverRunResult` the runner maps to terminal state /
|
|
23
|
+
* park. On the death paths the artifact is NULL — the runner
|
|
24
|
+
* synthesizes the fail-loud artifact (§4.3).
|
|
25
|
+
*
|
|
26
|
+
* Excluded from the 100% coverage gate — SDK stream consumer. The pure
|
|
27
|
+
* sub-pieces (budget envelope) live in the covered set.
|
|
28
|
+
*/
|
|
29
|
+
import type Database from "better-sqlite3";
|
|
30
|
+
import { type BackgroundTaskRow } from "../../db/background-task-store.js";
|
|
31
|
+
import { type BackgroundTaskEnvelope, type BackgroundTaskProcessConfig } from "./background-task-budget.js";
|
|
32
|
+
import { type BackgroundTaskRuntime } from "./background-task-tools.js";
|
|
33
|
+
import { type BackgroundTaskTransitionEmitter } from "./background-task-transition-events.js";
|
|
34
|
+
/** Read the operator-editable envelope row for `background_task`. */
|
|
35
|
+
export declare function loadBackgroundTaskProcessConfig(db: Database.Database): BackgroundTaskProcessConfig | null;
|
|
36
|
+
export interface DriverDeps {
|
|
37
|
+
db: Database.Database;
|
|
38
|
+
paDataDir: string;
|
|
39
|
+
/** Workspace dir root — resolves the agent-profile MD. */
|
|
40
|
+
workspaceDir: string;
|
|
41
|
+
transitionEmitter?: BackgroundTaskTransitionEmitter;
|
|
42
|
+
/** Vault root for the worker's `read_memory` tool. */
|
|
43
|
+
contextDir: string;
|
|
44
|
+
/** Clarification TTL in ms (`backgroundTaskClarificationTtlMinutes`). */
|
|
45
|
+
clarificationTtlMs: number;
|
|
46
|
+
/** Override for tests; production wires `() => Date.now()`. */
|
|
47
|
+
nowFn?: () => number;
|
|
48
|
+
}
|
|
49
|
+
export interface DriverHandle {
|
|
50
|
+
abortController: AbortController;
|
|
51
|
+
cwd: string;
|
|
52
|
+
runtime: BackgroundTaskRuntime;
|
|
53
|
+
sdkSessionId: string | null;
|
|
54
|
+
binding: BackgroundTaskEnvelope;
|
|
55
|
+
}
|
|
56
|
+
export interface DriverRunResult {
|
|
57
|
+
outcome: "completed" | "yielded_for_clarification" | "no_finish" | "max_turns_exceeded" | "budget_exceeded" | "timeout" | "cancelled" | "sdk_error" | "resume_unavailable" | "backend_misconfigured";
|
|
58
|
+
sdkSessionId: string | null;
|
|
59
|
+
detail?: string | null;
|
|
60
|
+
costUsd: number;
|
|
61
|
+
numTurns: number;
|
|
62
|
+
durationMs: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Acquire a fresh workdir + runtime + binding for `row`. The runner
|
|
66
|
+
* calls this BEFORE `runDriver` so it can stash the handle in its parked
|
|
67
|
+
* map before any turn fires (an ask_user on the first turn must find the
|
|
68
|
+
* handle already there).
|
|
69
|
+
*/
|
|
70
|
+
export declare function prepareDriverHandle(input: {
|
|
71
|
+
deps: DriverDeps;
|
|
72
|
+
row: BackgroundTaskRow;
|
|
73
|
+
}): Promise<{
|
|
74
|
+
ok: true;
|
|
75
|
+
handle: DriverHandle;
|
|
76
|
+
} | {
|
|
77
|
+
ok: false;
|
|
78
|
+
reason: DriverRunResult["outcome"];
|
|
79
|
+
detail?: string;
|
|
80
|
+
}>;
|
|
81
|
+
/** Drive the initial turn — the worker reads the brief and works. */
|
|
82
|
+
export declare function runDriver(deps: DriverDeps, row: BackgroundTaskRow, handle: DriverHandle): Promise<DriverRunResult>;
|
|
83
|
+
/** Resume a parked task after `/clarify` lands the owner's answer. Uses
|
|
84
|
+
* the persisted SDK session id so the prompt cache stays warm. Works both
|
|
85
|
+
* in-process (warm parked handle) and across a daemon restart (the runner
|
|
86
|
+
* reconstructs the handle from the persisted `backend_session_id`); in the
|
|
87
|
+
* cross-restart case a session the SDK can no longer load surfaces as
|
|
88
|
+
* `resume_unavailable`. */
|
|
89
|
+
export declare function resumeDriver(deps: DriverDeps, row: BackgroundTaskRow, handle: DriverHandle, userAnswer: string): Promise<DriverRunResult>;
|
|
90
|
+
/**
|
|
91
|
+
* BACKGROUND_TASK_RUNNER_DESIGN.md §10.2 / Phase 4 — resume a task that was
|
|
92
|
+
* mid-execution when the daemon restarted, using the persisted SDK session
|
|
93
|
+
* id (`backend_session_id`) so the warm transcript + prompt cache survive
|
|
94
|
+
* the restart instead of re-running the brief from scratch. The runner
|
|
95
|
+
* reconstructs the handle (`prepareDriverHandle` recreates the per-task
|
|
96
|
+
* workdir + sets `sdkSessionId` from the row). When the SDK can no longer
|
|
97
|
+
* load the session, this returns `resume_unavailable` and the runner falls
|
|
98
|
+
* back to re-dispatch-from-brief — so resume is a pure optimization with no
|
|
99
|
+
* regression.
|
|
100
|
+
*/
|
|
101
|
+
export declare function resumeFromBootDriver(deps: DriverDeps, row: BackgroundTaskRow, handle: DriverHandle): Promise<DriverRunResult>;
|
|
102
|
+
/** Remove the per-task workdir. Idempotent. Parked tasks (awaiting_user)
|
|
103
|
+
* do NOT call this — the runner keeps the handle in its parked map so
|
|
104
|
+
* /clarify can resume the warm SDK session. */
|
|
105
|
+
export declare function releaseDriverHandle(deps: DriverDeps, handle: DriverHandle): Promise<void>;
|