@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.
Files changed (305) hide show
  1. package/dist/adapters/adapter-watchdog.d.ts +70 -0
  2. package/dist/adapters/adapter-watchdog.js +115 -0
  3. package/dist/adapters/discord.d.ts +17 -1
  4. package/dist/adapters/discord.js +33 -0
  5. package/dist/adapters/notification-manager.d.ts +27 -1
  6. package/dist/adapters/notification-manager.js +54 -39
  7. package/dist/adapters/slack-adapter.d.ts +26 -1
  8. package/dist/adapters/slack-adapter.js +41 -0
  9. package/dist/adapters/telegram-adapter.d.ts +18 -1
  10. package/dist/adapters/telegram-adapter.js +41 -2
  11. package/dist/adapters/types.d.ts +20 -0
  12. package/dist/adapters/whatsapp-adapter.d.ts +26 -7
  13. package/dist/adapters/whatsapp-adapter.js +74 -21
  14. package/dist/api/env-writer.js +8 -5
  15. package/dist/api/helpers/agent-errors-registry.d.ts +5 -5
  16. package/dist/api/helpers/agent-errors-registry.js +5 -5
  17. package/dist/api/routes/agent.js +33 -12
  18. package/dist/api/routes/agents/index.js +75 -16
  19. package/dist/api/routes/agents/views.d.ts +37 -2
  20. package/dist/api/routes/agents/views.js +64 -2
  21. package/dist/api/routes/background-task.d.ts +22 -0
  22. package/dist/api/routes/background-task.js +338 -0
  23. package/dist/api/routes/browser-history.js +9 -1
  24. package/dist/api/routes/context/permissions.js +3 -2
  25. package/dist/api/routes/context/snapshots.js +0 -3
  26. package/dist/api/routes/context/write.js +3 -17
  27. package/dist/api/routes/dashboard/config.js +48 -12
  28. package/dist/api/routes/dashboard/cost-approvals.js +66 -0
  29. package/dist/api/routes/dashboard/notifications.js +9 -9
  30. package/dist/api/routes/integrations/crud-patch.js +5 -1
  31. package/dist/api/routes/integrations-reconcile.js +2 -2
  32. package/dist/api/routes/notion.d.ts +1 -1
  33. package/dist/api/routes/observations.js +7 -7
  34. package/dist/api/routes/obsidian.d.ts +1 -1
  35. package/dist/api/routes/receipts.js +5 -1
  36. package/dist/api/routes/setup-migrate.js +1 -1
  37. package/dist/api/routes/setup.js +1 -1
  38. package/dist/api/routes/task-flows.d.ts +1 -1
  39. package/dist/api/routes/task-flows.js +1 -1
  40. package/dist/api/routes/tuning.d.ts +29 -0
  41. package/dist/api/routes/tuning.js +304 -0
  42. package/dist/api/server.d.ts +44 -16
  43. package/dist/api/server.js +9 -0
  44. package/dist/bootstrap/adapters.d.ts +19 -0
  45. package/dist/bootstrap/adapters.js +61 -0
  46. package/dist/bootstrap/api.d.ts +5 -3
  47. package/dist/bootstrap/api.js +45 -13
  48. package/dist/bootstrap/catchup.d.ts +1 -1
  49. package/dist/bootstrap/catchup.js +11 -11
  50. package/dist/bootstrap/event-pipeline.d.ts +11 -0
  51. package/dist/bootstrap/event-pipeline.js +245 -7
  52. package/dist/bootstrap/observers.js +9 -6
  53. package/dist/bootstrap/schedule-helpers.d.ts +104 -6
  54. package/dist/bootstrap/schedule-helpers.js +172 -19
  55. package/dist/config.js +26 -12
  56. package/dist/core/agent-core.d.ts +33 -1
  57. package/dist/core/agent-core.js +36 -1
  58. package/dist/core/agents/activity-scan-cadence.d.ts +103 -0
  59. package/dist/core/agents/activity-scan-cadence.js +127 -0
  60. package/dist/core/agents/agent-route-override.d.ts +53 -0
  61. package/dist/core/agents/agent-route-override.js +69 -0
  62. package/dist/core/agents/builtin-registry.d.ts +51 -14
  63. package/dist/core/agents/builtin-registry.js +92 -15
  64. package/dist/core/agents/config-gate-reconcile.d.ts +38 -0
  65. package/dist/core/agents/config-gate-reconcile.js +51 -0
  66. package/dist/core/agents/cron-substitute.d.ts +1 -1
  67. package/dist/core/agents/cron-substitute.js +1 -1
  68. package/dist/core/agents/custom-routine-migration.d.ts +60 -0
  69. package/dist/core/agents/custom-routine-migration.js +149 -0
  70. package/dist/core/agents/firing-blocked.d.ts +1 -1
  71. package/dist/core/agents/hourly-cadence.d.ts +102 -0
  72. package/dist/core/agents/hourly-cadence.js +126 -0
  73. package/dist/core/agents/loader-boot.js +23 -0
  74. package/dist/core/agents/loader.d.ts +19 -0
  75. package/dist/core/agents/loader.js +34 -2
  76. package/dist/core/agents/override-merge.d.ts +1 -1
  77. package/dist/core/agents/override-merge.js +9 -1
  78. package/dist/core/agents/recurrence-convert.d.ts +1 -1
  79. package/dist/core/agents/recurrence-convert.js +1 -1
  80. package/dist/core/agents/recurring-schedule-adapter.js +8 -0
  81. package/dist/core/alerts.js +6 -6
  82. package/dist/core/backends/auth-health-monitor.d.ts +2 -2
  83. package/dist/core/backends/auth-health-monitor.js +1 -1
  84. package/dist/core/backends/backend-router.d.ts +27 -1
  85. package/dist/core/backends/backend-router.js +165 -1
  86. package/dist/core/backends/claude-code-core.d.ts +71 -31
  87. package/dist/core/backends/claude-code-core.js +282 -54
  88. package/dist/core/backends/cli-quota-guards.d.ts +29 -1
  89. package/dist/core/backends/cli-quota-guards.js +40 -5
  90. package/dist/core/backends/codex-core.d.ts +6 -0
  91. package/dist/core/backends/codex-core.js +22 -6
  92. package/dist/core/backends/failure-spend.d.ts +58 -0
  93. package/dist/core/backends/failure-spend.js +137 -0
  94. package/dist/core/backends/gemini-cli-core.d.ts +6 -0
  95. package/dist/core/backends/gemini-cli-core.js +25 -6
  96. package/dist/core/backends/model-registry.d.ts +1 -1
  97. package/dist/core/backends/model-registry.js +4 -4
  98. package/dist/core/backends/opencode-core.d.ts +1 -1
  99. package/dist/core/backends/opencode-core.js +5 -5
  100. package/dist/core/backends/plan-presets.js +39 -15
  101. package/dist/core/bang-commands/commands-cost.js +3 -1
  102. package/dist/core/bang-commands/commands-report.js +4 -3
  103. package/dist/core/bang-commands/commands-research.js +4 -1
  104. package/dist/core/bang-commands/commands-revert-tuning.d.ts +18 -0
  105. package/dist/core/bang-commands/commands-revert-tuning.js +63 -0
  106. package/dist/core/bang-commands/commands-stop-start.js +3 -3
  107. package/dist/core/bang-commands/commands-task-control.d.ts +19 -0
  108. package/dist/core/bang-commands/commands-task-control.js +147 -0
  109. package/dist/core/bang-commands/commands-wiki.js +5 -5
  110. package/dist/core/bang-commands/index.d.ts +2 -0
  111. package/dist/core/bang-commands/index.js +12 -0
  112. package/dist/core/bang-commands/registry.d.ts +12 -0
  113. package/dist/core/browser-history/research-cluster-fanout.d.ts +28 -14
  114. package/dist/core/browser-history/research-cluster-fanout.js +39 -16
  115. package/dist/core/channel-timeline.d.ts +5 -1
  116. package/dist/core/channel-timeline.js +13 -0
  117. package/dist/core/context/index-reconciler.js +5 -2
  118. package/dist/core/context/policy-index-reconciler.d.ts +6 -4
  119. package/dist/core/context/policy-index-runner.js +25 -6
  120. package/dist/core/context-builder-calendar.js +10 -2
  121. package/dist/core/context-builder-conversation.d.ts +8 -1
  122. package/dist/core/context-builder-conversation.js +41 -7
  123. package/dist/core/context-builder-yesterday.js +4 -3
  124. package/dist/core/context-builder.d.ts +7 -2
  125. package/dist/core/context-builder.js +62 -20
  126. package/dist/core/context-file-serializer.d.ts +1 -1
  127. package/dist/core/context-file-serializer.js +1 -1
  128. package/dist/core/context-health.js +2 -2
  129. package/dist/core/context-paths.d.ts +1 -1
  130. package/dist/core/context-paths.js +1 -1
  131. package/dist/core/context-validation/prepare-write.js +1 -1
  132. package/dist/core/context-validation/routine-rulebook.d.ts +1 -1
  133. package/dist/core/context-vault-aliases.d.ts +0 -13
  134. package/dist/core/context-vault-aliases.js +37 -0
  135. package/dist/core/custom-routines.d.ts +99 -0
  136. package/dist/core/custom-routines.js +187 -0
  137. package/dist/core/daemon-api-cli.js +49 -0
  138. package/dist/core/day-boundary.d.ts +46 -0
  139. package/dist/core/day-boundary.js +40 -0
  140. package/dist/core/dispatcher-activity-scan.d.ts +221 -0
  141. package/dist/core/dispatcher-activity-scan.js +775 -0
  142. package/dist/core/dispatcher-error-handling.d.ts +6 -11
  143. package/dist/core/dispatcher-error-handling.js +38 -62
  144. package/dist/core/dispatcher-hourly-check.js +6 -1
  145. package/dist/core/dispatcher-message-handler.d.ts +10 -0
  146. package/dist/core/dispatcher-message-handler.js +17 -0
  147. package/dist/core/dispatcher-morning-routine.d.ts +6 -6
  148. package/dist/core/dispatcher-morning-routine.js +13 -13
  149. package/dist/core/dispatcher-result-processor.d.ts +33 -0
  150. package/dist/core/dispatcher-result-processor.js +167 -11
  151. package/dist/core/dispatcher-scheduled-background-task.d.ts +42 -0
  152. package/dist/core/dispatcher-scheduled-background-task.js +89 -0
  153. package/dist/core/dispatcher-scheduled-tasks.d.ts +63 -1
  154. package/dist/core/dispatcher-scheduled-tasks.js +213 -6
  155. package/dist/core/dispatcher-task-delivery.d.ts +105 -0
  156. package/dist/core/dispatcher-task-delivery.js +555 -0
  157. package/dist/core/dispatcher-types.d.ts +48 -9
  158. package/dist/core/dispatcher-types.js +3 -3
  159. package/dist/core/dispatcher.d.ts +112 -31
  160. package/dist/core/dispatcher.js +284 -59
  161. package/dist/core/dm-freshness-metrics.d.ts +1 -1
  162. package/dist/core/drift-effects.js +2 -2
  163. package/dist/core/feedback/consolidation-prep.js +17 -5
  164. package/dist/core/feedback/eviction-scorer.js +6 -2
  165. package/dist/core/feedback/lesson-format.js +9 -4
  166. package/dist/core/feedback/lesson-injection.d.ts +1 -1
  167. package/dist/core/feedback/lesson-injection.js +17 -2
  168. package/dist/core/feedback/lesson-store-overview.d.ts +8 -4
  169. package/dist/core/feedback/lesson-store-overview.js +8 -4
  170. package/dist/core/feedback/regeneralization-prep.js +29 -16
  171. package/dist/core/feedback/self-performance-prep.d.ts +186 -0
  172. package/dist/core/feedback/self-performance-prep.js +541 -0
  173. package/dist/core/feedback/tuning-actuator.d.ts +198 -0
  174. package/dist/core/feedback/tuning-actuator.js +432 -0
  175. package/dist/core/feedback/tuning-recommender.d.ts +247 -0
  176. package/dist/core/feedback/tuning-recommender.js +580 -0
  177. package/dist/core/feedback/tuning-revert-monitor.d.ts +90 -0
  178. package/dist/core/feedback/tuning-revert-monitor.js +213 -0
  179. package/dist/core/health-monitor.d.ts +6 -0
  180. package/dist/core/health-monitor.js +1 -1
  181. package/dist/core/injection-policy.d.ts +4 -4
  182. package/dist/core/injection-policy.js +4 -4
  183. package/dist/core/integration-main-backend.js +4 -0
  184. package/dist/core/management-md.d.ts +2 -2
  185. package/dist/core/management-md.js +51 -13
  186. package/dist/core/morning/orchestrator.d.ts +2 -2
  187. package/dist/core/morning/orchestrator.js +2 -2
  188. package/dist/core/notification-gate.d.ts +64 -0
  189. package/dist/core/notification-gate.js +51 -0
  190. package/dist/core/notification-rate-limit.d.ts +40 -0
  191. package/dist/core/notification-rate-limit.js +50 -0
  192. package/dist/core/policy-files.d.ts +1 -1
  193. package/dist/core/policy-files.js +2 -2
  194. package/dist/core/pre-pass-freshness.d.ts +4 -4
  195. package/dist/core/retention.d.ts +5 -0
  196. package/dist/core/retention.js +20 -4
  197. package/dist/core/review-context.d.ts +1 -1
  198. package/dist/core/review-context.js +10 -5
  199. package/dist/core/roadmap-write-lock.d.ts +2 -1
  200. package/dist/core/roadmap-write-lock.js +15 -10
  201. package/dist/core/routine-acquisition-plan.d.ts +47 -1
  202. package/dist/core/routine-acquisition-plan.js +78 -20
  203. package/dist/core/routine-fetch-window-retry.js +7 -4
  204. package/dist/core/routine-fetch-window-runner.d.ts +39 -3
  205. package/dist/core/routine-fetch-window-runner.js +264 -13
  206. package/dist/core/routine-windows.d.ts +2 -2
  207. package/dist/core/routine-windows.js +8 -5
  208. package/dist/core/scheduler.d.ts +175 -16
  209. package/dist/core/scheduler.js +559 -102
  210. package/dist/core/signal-detector.d.ts +12 -0
  211. package/dist/core/signal-detector.js +53 -9
  212. package/dist/core/skills-compiler-denied-tools.js +2 -2
  213. package/dist/core/skills-compiler-skill-index.d.ts +2 -2
  214. package/dist/core/skills-compiler-skill-index.js +2 -2
  215. package/dist/core/skills-compiler-variants.d.ts +1 -1
  216. package/dist/core/skills-compiler-variants.js +8 -0
  217. package/dist/core/skills-compiler.d.ts +29 -26
  218. package/dist/core/skills-compiler.js +117 -81
  219. package/dist/core/skills-manifest.d.ts +37 -0
  220. package/dist/core/skills-manifest.js +73 -2
  221. package/dist/core/sleep-inhibitor.d.ts +79 -0
  222. package/dist/core/sleep-inhibitor.js +132 -0
  223. package/dist/core/slim-system-prompt-loader.d.ts +77 -0
  224. package/dist/core/slim-system-prompt-loader.js +141 -0
  225. package/dist/core/spawn-gates.d.ts +126 -0
  226. package/dist/core/spawn-gates.js +180 -0
  227. package/dist/core/today-direct-writer.d.ts +2 -2
  228. package/dist/core/today-direct-writer.js +1 -1
  229. package/dist/core/today-write-lock.d.ts +4 -2
  230. package/dist/core/today-write-lock.js +30 -20
  231. package/dist/core/wake-detector.d.ts +55 -0
  232. package/dist/core/wake-detector.js +80 -0
  233. package/dist/core/wiki/compile-lock.d.ts +1 -1
  234. package/dist/core/wiki/compile-lock.js +1 -1
  235. package/dist/core/workdir.js +15 -6
  236. package/dist/db/activity-scan-signals.d.ts +77 -0
  237. package/dist/db/activity-scan-signals.js +378 -0
  238. package/dist/db/agents-store.d.ts +28 -0
  239. package/dist/db/agents-store.js +62 -0
  240. package/dist/db/background-task-clarifications-store.d.ts +81 -0
  241. package/dist/db/background-task-clarifications-store.js +152 -0
  242. package/dist/db/background-task-store.d.ts +207 -0
  243. package/dist/db/background-task-store.js +380 -0
  244. package/dist/db/browser-history-store.d.ts +39 -6
  245. package/dist/db/browser-history-store.js +51 -7
  246. package/dist/db/browser-task-clarifications-store.d.ts +12 -0
  247. package/dist/db/browser-task-clarifications-store.js +35 -5
  248. package/dist/db/browser-task-store.d.ts +3 -0
  249. package/dist/db/browser-task-store.js +29 -4
  250. package/dist/db/deferred-dm.d.ts +86 -0
  251. package/dist/db/deferred-dm.js +199 -0
  252. package/dist/db/migrations.js +330 -0
  253. package/dist/db/observations.d.ts +2 -2
  254. package/dist/db/observations.js +3 -3
  255. package/dist/db/schema.js +217 -16
  256. package/dist/db/voice-transcripts-store.d.ts +1 -1
  257. package/dist/index.js +86 -29
  258. package/dist/messaging/browser-task-mcp-notifier.d.ts +12 -70
  259. package/dist/messaging/browser-task-mcp-notifier.js +30 -151
  260. package/dist/messaging/browser-task-screenshot-attachment.d.ts +15 -0
  261. package/dist/messaging/browser-task-screenshot-attachment.js +63 -0
  262. package/dist/observers/delegated-sync-worker.d.ts +6 -6
  263. package/dist/observers/delegated-sync-worker.js +10 -10
  264. package/dist/observers/git-delegated-cron.d.ts +1 -1
  265. package/dist/observers/git-delegated-cron.js +2 -2
  266. package/dist/observers/github-poller-classifier.d.ts +3 -3
  267. package/dist/observers/github-poller-classifier.js +3 -3
  268. package/dist/observers/imminent-event-scheduler.d.ts +1 -1
  269. package/dist/observers/imminent-event-scheduler.js +1 -1
  270. package/dist/observers/mail-poller.d.ts +1 -0
  271. package/dist/observers/mail-poller.js +42 -3
  272. package/dist/observers/observation-summarizer/summarizer-client.d.ts +2 -2
  273. package/dist/observers/observation-summarizer/summarizer-client.js +2 -2
  274. package/dist/observers/observation-summarizer/worker.d.ts +2 -2
  275. package/dist/observers/observation-summarizer/worker.js +4 -4
  276. package/dist/observers/obsidian-watcher.d.ts +1 -1
  277. package/dist/observers/obsidian-watcher.js +1 -1
  278. package/dist/safety/agent-write-tracker.d.ts +4 -4
  279. package/dist/safety/agent-write-tracker.js +4 -4
  280. package/dist/safety/audit.d.ts +43 -5
  281. package/dist/safety/audit.js +86 -18
  282. package/dist/safety/risk-classifier.d.ts +6 -0
  283. package/dist/safety/risk-classifier.js +75 -11
  284. package/dist/scheduler/activity-scan-gate.d.ts +86 -0
  285. package/dist/scheduler/activity-scan-gate.js +132 -0
  286. package/dist/services/background-task/background-task-budget.d.ts +80 -0
  287. package/dist/services/background-task/background-task-budget.js +91 -0
  288. package/dist/services/background-task/background-task-driver.d.ts +105 -0
  289. package/dist/services/background-task/background-task-driver.js +416 -0
  290. package/dist/services/background-task/background-task-runner.d.ts +96 -0
  291. package/dist/services/background-task/background-task-runner.js +673 -0
  292. package/dist/services/background-task/background-task-tools.d.ts +84 -0
  293. package/dist/services/background-task/background-task-tools.js +247 -0
  294. package/dist/services/background-task/background-task-transition-events.d.ts +43 -0
  295. package/dist/services/background-task/background-task-transition-events.js +54 -0
  296. package/dist/services/browser-history/automation/egress-denylist.d.ts +1 -1
  297. package/dist/services/browser-history/automation/egress-denylist.js +16 -6
  298. package/dist/services/browser-history/managed-chromium/sandbox-launcher.js +0 -1
  299. package/dist/services/browser-task/browser-task-runner.js +53 -8
  300. package/dist/services/observations-batch.d.ts +1 -1
  301. package/dist/services/observations-batch.js +2 -2
  302. package/dist/settings/runtime-settings.d.ts +38 -11
  303. package/dist/settings/runtime-settings.js +203 -40
  304. package/dist/settings/settings-store.js +11 -3
  305. package/package.json +4 -4
@@ -34,7 +34,7 @@
34
34
  * is the monthly `onMissingDay` policy, which cron cannot carry — it is dropped
35
35
  * on conversion (a `daysOfMonth` cron uses node-cron's own missing-day
36
36
  * behaviour). Sub-hourly intervals (every N minutes) are NOT representable —
37
- * only the built-in hourly-check supports those, via config.
37
+ * only the built-in activity-scan supports those, via config.
38
38
  */
39
39
  /** Zero-pad a single clock field to two digits. */
40
40
  function pad2(value) {
@@ -130,6 +130,11 @@ export function createRecurringSchedulePort(db, fallbackTimezone) {
130
130
  ...(input.model !== null ? { model: input.model } : {}),
131
131
  ...(input.tier !== null ? { tier: input.tier } : {}),
132
132
  ...(input.backendId !== null ? { backendId: input.backendId } : {}),
133
+ // Quiet-hours opt-in (and any future row-local flags) — spread into
134
+ // every materialised agent_schedule row by generateNextScheduleRow.
135
+ ...(input.taskContext !== undefined
136
+ ? { taskContext: input.taskContext }
137
+ : {}),
133
138
  });
134
139
  return dto.id;
135
140
  },
@@ -148,6 +153,9 @@ export function createRecurringSchedulePort(db, fallbackTimezone) {
148
153
  ...(patch.recurrence !== undefined
149
154
  ? { recurrenceRule: specToRecurrenceRule(patch.recurrence) }
150
155
  : {}),
156
+ ...(patch.taskContext !== undefined
157
+ ? { taskContext: patch.taskContext }
158
+ : {}),
151
159
  },
152
160
  // Agent-driven edits tag a superseded pending row so the dispatcher /
153
161
  // dashboard can attribute the skip to a definition change (§11.3.2).
@@ -31,9 +31,9 @@ function detectContextFilesMissing(inputs) {
31
31
  severity: "error",
32
32
  title: `${sorted.length} context file${sorted.length === 1 ? "" : "s"} missing`,
33
33
  description: `Missing: ${sorted.slice(0, 3).join(", ")}${sorted.length > 3 ? `, and ${sorted.length - 3} more` : ""}. The agent cannot read or write these until they are recreated.`,
34
- // Recovery: "Reinstall context" on /settings/advanced (tarball
34
+ // Recovery: "Reinstall context" on /settings/danger-zone (tarball
35
35
  // backup + re-seed from templates on next restart).
36
- href: "/settings/advanced",
36
+ href: "/settings/danger-zone",
37
37
  source: "system",
38
38
  dismissable: false,
39
39
  detectedAt: iso(inputs.now),
@@ -89,8 +89,8 @@ function detectTemplateUpgrades(inputs) {
89
89
  severity: "warning",
90
90
  title: `${count} template upgrade${count === 1 ? "" : "s"} pending`,
91
91
  description: "Newer template versions ship with this release. Review and merge to pick up format changes.",
92
- // Acceptance path: "Reinstall context" on /settings/advanced.
93
- href: "/settings/advanced",
92
+ // Acceptance path: "Reinstall context" on /settings/danger-zone.
93
+ href: "/settings/danger-zone",
94
94
  source: "config",
95
95
  dismissable: true,
96
96
  detectedAt: iso(inputs.now),
@@ -172,7 +172,7 @@ function detectAuthHealth(inputs) {
172
172
  severity: "error",
173
173
  title: `${b.id} CLI not found on PATH`,
174
174
  description: "Install the CLI or disable this backend so it doesn't get scheduled.",
175
- href: "/settings/backends",
175
+ href: "/settings/models",
176
176
  source: "auth",
177
177
  dismissable: false,
178
178
  detectedAt: iso(inputs.now),
@@ -192,7 +192,7 @@ function detectAuthHealth(inputs) {
192
192
  description: b.lastError
193
193
  ? `Last error: ${b.lastError}.`
194
194
  : "Re-authenticate to resume sessions on this backend.",
195
- href: "/settings/backends",
195
+ href: "/settings/models",
196
196
  source: "auth",
197
197
  dismissable: false,
198
198
  detectedAt: iso(inputs.now),
@@ -88,7 +88,7 @@ export interface AuthHealthMonitorOptions {
88
88
  now?: () => Date;
89
89
  /**
90
90
  * Injected morning-routine gate — returning `true` causes `checkAll()`
91
- * to short-circuit without probing. Mirrors the existing hourly-check
91
+ * to short-circuit without probing. Mirrors the existing activity-scan
92
92
  * gate (§3.2 of the design doc) so probe DMs never collide with the
93
93
  * morning routine. In production, index.ts wires this to
94
94
  * `dispatcher.isMorningRoutineActive()`. Tests may pass a fake.
@@ -219,7 +219,7 @@ export declare class AuthHealthMonitor {
219
219
  * overlapping cron ticks (e.g. a slow probe still running when the
220
220
  * next hour fires) serialize without queueing stacks of probes. The
221
221
  * field is set atomically before any `await` to avoid the
222
- * microtask-scheduling race that bit `Dispatcher.hourlyCheckInProgress`
222
+ * microtask-scheduling race that bit `Dispatcher.activityScanInProgress`
223
223
  * pre-C1 fix (see `dispatcher.ts`).
224
224
  */
225
225
  private checkAllInFlight;
@@ -332,7 +332,7 @@ export class AuthHealthMonitor {
332
332
  * overlapping cron ticks (e.g. a slow probe still running when the
333
333
  * next hour fires) serialize without queueing stacks of probes. The
334
334
  * field is set atomically before any `await` to avoid the
335
- * microtask-scheduling race that bit `Dispatcher.hourlyCheckInProgress`
335
+ * microtask-scheduling race that bit `Dispatcher.activityScanInProgress`
336
336
  * pre-C1 fix (see `dispatcher.ts`).
337
337
  */
338
338
  checkAllInFlight = null;
@@ -43,7 +43,7 @@ export interface RouterExecuteParams {
43
43
  * Concretely: if `requestedTier` is passed and the pinned model's registry
44
44
  * tier does NOT match, `resolveBinding` will swap in a canonical model for
45
45
  * the requested tier on the same backend (e.g. Pro preset pins
46
- * `routine.hourly_check` to Sonnet; `requestedTier: "heavy"` swaps to
46
+ * `routine.activity_scan` to Sonnet; `requestedTier: "heavy"` swaps to
47
47
  * `claude-opus-4-8`). This is the ONLY path through which the three
48
48
  * explicit-Opus escape hatches (dashboard chat picker, agent_schedule.model,
49
49
  * `/api/agent/run-now {requestedModel}`) can reach Opus on Pro plan.
@@ -171,6 +171,7 @@ export declare class BackendRouter implements IAgentRouter {
171
171
  private readonly cores;
172
172
  private readonly hasProcessConfigTable;
173
173
  private readonly hasBackendDefaultsTable;
174
+ private readonly hasAgentsTable;
174
175
  private readonly notificationDedup;
175
176
  constructor(db: Database.Database, config: AgentConfig, cores: IAgentCore[], notifier?: BackendRouterNotifier | undefined, authTelemetry?: AuthTelemetry | undefined, prepareSessionDir?: PrepareSessionDirFn | undefined);
176
177
  execute(params: RouterExecuteParams, streamCallbacks?: StreamCallbacks): Promise<AgentResult>;
@@ -197,12 +198,37 @@ export declare class BackendRouter implements IAgentRouter {
197
198
  * added once instead of in two diverging code paths.
198
199
  */
199
200
  private executeFallbackCore;
201
+ /**
202
+ * Best-effort `agent_actions` record of the main attempt's billed
203
+ * spend on paths where the dispatcher's `BackendRouterHandledError`
204
+ * unwrap will never see `mainFailure` (fallback success, raw fallback
205
+ * rethrow). No-op when the failure carries no spend.
206
+ * PREPASS_COST_REDUCTION_PLAN.md N1.
207
+ */
208
+ private recordMainFailureSpend;
200
209
  resolveBinding(event: Event, options?: {
201
210
  processKey?: ProcessKey;
202
211
  requestedTier?: ProcessModelTier;
203
212
  requestedBackendId?: BackendId;
204
213
  requestedModelId?: string;
205
214
  }): ResolvedBackendRoute;
215
+ /**
216
+ * Read the firing Agent's routing override. `event.data.agentId` is
217
+ * stamped by `Dispatcher.beginAgentExecution` for every firing that
218
+ * resolves to an Agent (and propagates to morning Stage A/B via the
219
+ * parent-data spread); reactive DMs and pre-pass fan-out sub-events carry
220
+ * no stamp and resolve to `null` here. User Agents are excluded — their
221
+ * tier / backend / model already arrive as explicit event hints from the
222
+ * materialised schedule row.
223
+ */
224
+ private loadAgentRouteOverride;
225
+ /** True only when an explicit `backends` row says `enabled = 0`. A missing
226
+ * row or table stays permissive — matches the resolver's existing trust
227
+ * posture for `process_backend_config` backends. */
228
+ private isBackendDisabled;
229
+ /** Apply the Agent's per-execution limit overrides onto a resolved route. */
230
+ private applyAgentLimitOverrides;
231
+ private resolveBindingCore;
206
232
  private resolveConfiguredBinding;
207
233
  /**
208
234
  * Returns a modified binding whose `modelId` has been swapped to a canonical
@@ -4,6 +4,8 @@ import { createLogger } from "../../logging.js";
4
4
  import { BackendDecisiveFailure, BackendQuotaError, } from "../agent-core.js";
5
5
  import { DEFAULT_CLAUDE_HIGH_MODEL, DEFAULT_CLAUDE_LITE_MODEL, DEFAULT_CLAUDE_MEDIUM_MODEL, findRegisteredModel, getModelsForBackend, } from "./model-registry.js";
6
6
  import { readCachedAuthStatus, recordReactiveAuthFailure, recordReactiveAuthSuccess, } from "./auth-health-monitor.js";
7
+ import { extractFailureSpendInfo, recordFailureSpendRow, } from "./failure-spend.js";
8
+ import { extractAgentRouteOverride, } from "../agents/agent-route-override.js";
7
9
  const logger = createLogger("backend-router");
8
10
  /**
9
11
  * Per-process maxTurns caps, applied when no DB-level process_backend_config
@@ -12,7 +14,7 @@ const logger = createLogger("backend-router");
12
14
  */
13
15
  const PROCESS_MAX_TURNS = {
14
16
  "routine.morning_routine": 50, // avg 17.7, max observed 35 — 300 was 8.5x max
15
- "routine.hourly_check": 30, // P90=25, pad for complex observation sets
17
+ "routine.activity_scan": 30, // P90=25, pad for complex observation sets
16
18
  "routine.roadmap_refresh": 25, // single observed run was 13 turns
17
19
  "message.dm": 35, // most <15, allow long conversations
18
20
  // Setup is high-tier (Opus / gpt-5.4 / Pro — Codex collapses high to
@@ -63,6 +65,7 @@ export class BackendRouter {
63
65
  cores;
64
66
  hasProcessConfigTable;
65
67
  hasBackendDefaultsTable;
68
+ hasAgentsTable;
66
69
  notificationDedup = new Map();
67
70
  constructor(db, config, cores, notifier, authTelemetry, prepareSessionDir) {
68
71
  this.db = db;
@@ -73,6 +76,7 @@ export class BackendRouter {
73
76
  this.cores = Object.fromEntries(cores.map((core) => [core.backendId, core]));
74
77
  this.hasProcessConfigTable = this.hasTable("process_backend_config");
75
78
  this.hasBackendDefaultsTable = this.hasTable("backend_global_defaults");
79
+ this.hasAgentsTable = this.hasTable("agents");
76
80
  }
77
81
  async execute(params, streamCallbacks) {
78
82
  const binding = params.preResolvedBinding ?? this.resolveBinding(params.event, {
@@ -332,6 +336,14 @@ export class BackendRouter {
332
336
  ...(params.skillsReplace ? { skillsReplace: true } : {}),
333
337
  }, streamCallbacks);
334
338
  recordReactiveAuthSuccess(this.db, fallback.backendId, this.authTelemetry);
339
+ // PREPASS_COST_REDUCTION_PLAN.md N1 — the main attempt may have
340
+ // billed before failing over (e.g. a Claude max_budget_usd abort
341
+ // with a partial-usage snapshot). On fallback SUCCESS the
342
+ // dispatcher's error path never runs, so this is the only place
343
+ // the main attempt's spend can land in agent_actions; without it
344
+ // the run shows only the fallback's success row and the main
345
+ // attempt's cost is invisible.
346
+ this.recordMainFailureSpend(params.event, mainFailure);
335
347
  await this.notifyFallbackSuccess(params.event, binding.processKey, binding.main, mainFailure, fallback);
336
348
  return result;
337
349
  }
@@ -344,6 +356,11 @@ export class BackendRouter {
344
356
  }
345
357
  if (!(fallbackError instanceof BackendDecisiveFailure
346
358
  || fallbackError instanceof BackendQuotaError)) {
359
+ // Raw (unclassified) fallback errors are rethrown without the
360
+ // router wrap, so the dispatcher's spend unwrap never sees
361
+ // `mainFailure` — record its spend here before rethrowing.
362
+ // PREPASS_COST_REDUCTION_PLAN.md N1.
363
+ this.recordMainFailureSpend(params.event, mainFailure);
347
364
  throw fallbackError;
348
365
  }
349
366
  await this.handleFallbackFailure(params.event, binding.processKey, binding.main, mainFailure, fallback, fallbackError);
@@ -352,7 +369,154 @@ export class BackendRouter {
352
369
  + `fallback: ${describeBackendFailure(fallbackError)}`, fallbackError, mainFailure, fallbackError);
353
370
  }
354
371
  }
372
+ /**
373
+ * Best-effort `agent_actions` record of the main attempt's billed
374
+ * spend on paths where the dispatcher's `BackendRouterHandledError`
375
+ * unwrap will never see `mainFailure` (fallback success, raw fallback
376
+ * rethrow). No-op when the failure carries no spend.
377
+ * PREPASS_COST_REDUCTION_PLAN.md N1.
378
+ */
379
+ recordMainFailureSpend(event, mainFailure) {
380
+ const spendInfo = extractFailureSpendInfo(mainFailure);
381
+ if (spendInfo) {
382
+ recordFailureSpendRow(this.db, event, spendInfo, describeBackendFailure(mainFailure));
383
+ }
384
+ }
355
385
  resolveBinding(event, options) {
386
+ // Built-in Agent override layer (AGENT_DEFINITIONS_DESIGN.md §6.4.1
387
+ // runtime wiring). When the firing resolved to a built-in Agent whose
388
+ // operator saved tier / model / limit overrides on the Definition tab,
389
+ // fold them in UNDER caller-explicit options:
390
+ //
391
+ // caller-explicit (chat picker, run-now hint, fetch-window backend pin)
392
+ // > agent override snapshot
393
+ // > process_backend_config / process-key defaults
394
+ //
395
+ // A caller that passes ANY routing option (tier, backend, or model)
396
+ // keeps full control and the agent override is skipped WHOLESALE —
397
+ // routing AND limits. The explicit-caller cases are all envelopes the
398
+ // caller owns deliberately: run-now / !checks model hints, the
399
+ // dashboard pickers, the morning-retry medium clamp (a cost cap that
400
+ // must not be re-widened by an agent override), and the fetch-window
401
+ // pre-pass — whose budget sizing + attempt-1 binding resolve against
402
+ // the PARENT routine event (stamped with `agentId`) plus a
403
+ // `requestedBackendId` pin, so a limits-always rule would leak the
404
+ // Agent's envelope into its pre-pass sub-sessions while retries
405
+ // (resolved against unstamped fetcher events) stayed clean.
406
+ //
407
+ // With no caller routing intent, the agent's model pin wins over its
408
+ // own tier (a concrete model is the more specific standing
409
+ // instruction) and the limit overrides are applied onto the resolved
410
+ // main + fallback bindings.
411
+ const agentOverride = this.loadAgentRouteOverride(event);
412
+ if (agentOverride) {
413
+ const callerRouted = options?.requestedTier !== undefined
414
+ || options?.requestedBackendId !== undefined
415
+ || options?.requestedModelId !== undefined;
416
+ if (!callerRouted) {
417
+ const merged = {
418
+ ...options,
419
+ ...(agentOverride.tier ? { requestedTier: agentOverride.tier } : {}),
420
+ ...(agentOverride.modelId && agentOverride.backendId
421
+ ? {
422
+ requestedBackendId: agentOverride.backendId,
423
+ requestedModelId: agentOverride.modelId,
424
+ }
425
+ : {}),
426
+ };
427
+ return this.applyAgentLimitOverrides(this.resolveBindingCore(event, merged), agentOverride);
428
+ }
429
+ }
430
+ return this.resolveBindingCore(event, options);
431
+ }
432
+ /**
433
+ * Read the firing Agent's routing override. `event.data.agentId` is
434
+ * stamped by `Dispatcher.beginAgentExecution` for every firing that
435
+ * resolves to an Agent (and propagates to morning Stage A/B via the
436
+ * parent-data spread); reactive DMs and pre-pass fan-out sub-events carry
437
+ * no stamp and resolve to `null` here. User Agents are excluded — their
438
+ * tier / backend / model already arrive as explicit event hints from the
439
+ * materialised schedule row.
440
+ */
441
+ loadAgentRouteOverride(event) {
442
+ if (!this.hasAgentsTable)
443
+ return null;
444
+ const agentId = event.data?.agentId;
445
+ if (typeof agentId !== "string" || agentId.length === 0)
446
+ return null;
447
+ let row;
448
+ try {
449
+ row = this.db
450
+ .prepare("SELECT source, metadata_json FROM agents WHERE id = ? LIMIT 1")
451
+ .get(agentId);
452
+ }
453
+ catch (err) {
454
+ logger.warn({ err, agentId }, "agent override lookup failed; ignoring");
455
+ return null;
456
+ }
457
+ if (!row || row.source !== "builtin" || !row.metadata_json)
458
+ return null;
459
+ let override;
460
+ try {
461
+ const metadata = JSON.parse(row.metadata_json);
462
+ override = extractAgentRouteOverride(metadata.override_snapshot);
463
+ }
464
+ catch {
465
+ // Corrupt metadata_json must never take routing down with it.
466
+ return null;
467
+ }
468
+ // Standing-pin drift guard: the dashboard dropdown only offers enabled
469
+ // backends at SAVE time, but an agent override persists across later
470
+ // backend disables. A pin to a now-disabled backend would fail the
471
+ // firing on every cron tick (hard override drops the fallback), so
472
+ // drop the pin — tier/limit overrides survive. The chat picker has no
473
+ // such guard because its pin lives for a single user-initiated turn.
474
+ if (override?.backendId && this.isBackendDisabled(override.backendId)) {
475
+ logger.warn({ agentId, backendId: override.backendId, modelId: override.modelId }, "agent model pin targets a disabled backend; ignoring the pin");
476
+ const stripped = {
477
+ ...override,
478
+ modelId: null,
479
+ backendId: null,
480
+ };
481
+ return stripped.tier === null
482
+ && stripped.maxTurns === null
483
+ && stripped.maxBudgetUsd === null
484
+ ? null
485
+ : stripped;
486
+ }
487
+ return override;
488
+ }
489
+ /** True only when an explicit `backends` row says `enabled = 0`. A missing
490
+ * row or table stays permissive — matches the resolver's existing trust
491
+ * posture for `process_backend_config` backends. */
492
+ isBackendDisabled(backendId) {
493
+ try {
494
+ const row = this.db
495
+ .prepare("SELECT enabled FROM backends WHERE id = ? LIMIT 1")
496
+ .get(backendId);
497
+ return row !== undefined && row.enabled === 0;
498
+ }
499
+ catch {
500
+ return false;
501
+ }
502
+ }
503
+ /** Apply the Agent's per-execution limit overrides onto a resolved route. */
504
+ applyAgentLimitOverrides(route, override) {
505
+ if (override.maxTurns === null && override.maxBudgetUsd === null) {
506
+ return route;
507
+ }
508
+ const applyTo = (binding) => ({
509
+ ...binding,
510
+ maxTurns: override.maxTurns ?? binding.maxTurns,
511
+ maxBudgetUsd: override.maxBudgetUsd ?? binding.maxBudgetUsd,
512
+ });
513
+ return {
514
+ ...route,
515
+ main: applyTo(route.main),
516
+ fallback: route.fallback ? applyTo(route.fallback) : null,
517
+ };
518
+ }
519
+ resolveBindingCore(event, options) {
356
520
  const processKey = options?.processKey ?? resolveProcessKey(event);
357
521
  // TIER_LOCKED hard clamp (DOCS_QA_B7_DESIGN.md S2). When set, this
358
522
  // process is pinned to a tier regardless of requestedTier hints,
@@ -1,55 +1,47 @@
1
1
  import { type AgentResult, type BackendModel } from "@aitne/shared";
2
2
  import type { AgentConfig } from "../../config.js";
3
3
  import type { AgentExecuteParams, AgentResumeParams, AuthCheckResult, DelegatedTaskInvokeParams, DelegatedTaskResultRaw, DelegatedToolInvokeParams, DelegatedToolResult, IAgentCore, McpSessionContext, ReadSensitiveTokenManager, StreamCallbacks } from "../agent-core.js";
4
- import { BackendQuotaError, BackendDecisiveFailure } from "../agent-core.js";
4
+ import { BackendQuotaError, BackendDecisiveFailure, type BackendQuotaSpend } from "../agent-core.js";
5
+ import { PriceFetcher } from "./price-fetcher.js";
5
6
  import type { AgentWriteTracker } from "../../safety/agent-write-tracker.js";
6
- import { loadFetchWindowSystemPrompt, resetFetchWindowSystemPromptForTest } from "../fetch-window-prompt-loader.js";
7
+ import { loadFetchWindowSystemPrompt, resetFetchWindowSystemPromptForTest } from "../slim-system-prompt-loader.js";
7
8
  import { CLAUDE_PROBE_TOOLS_PROMPT, computeDelegatedClaudeTools, computeNativeClaudeTools } from "./claude-probe.js";
8
9
  import { AgentTimeoutError, extractClaudeCodeQuotaResetHint, isClaudeCodeQuotaError } from "./claude-errors.js";
9
10
  import { checkAuth as checkAuthFn } from "./claude-auth.js";
10
11
  export { AgentTimeoutError, CLAUDE_PROBE_TOOLS_PROMPT, computeDelegatedClaudeTools, computeNativeClaudeTools, extractClaudeCodeQuotaResetHint, isClaudeCodeQuotaError, };
11
12
  /**
12
- * Test-only surface: lets `claude-code-core.test.ts` exercise the
13
- * fetch_window prompt loader without reaching into module internals via
14
- * `as any` casts. Re-exports the shared loader (now hoisted to
15
- * `core/fetch-window-prompt-loader.ts`) so the existing test import path
16
- * keeps working after Phase 1.5's hoist.
13
+ * Test-only surface: lets `claude-code-core.test.ts` exercise the slim
14
+ * prompt loader without reaching into module internals via `as any` casts.
15
+ * Re-exports the shared loaders (hoisted to `core/slim-system-prompt-loader.ts`)
16
+ * so the existing fetch_window test import path keeps working.
17
17
  */
18
18
  export declare const _testInternals: {
19
19
  loadFetchWindowSystemPrompt: typeof loadFetchWindowSystemPrompt;
20
20
  resetFetchWindowSystemPromptForTest: typeof resetFetchWindowSystemPromptForTest;
21
21
  };
22
- /**
23
- * ClaudeCodeCore intentionally does NOT run a pre-flight `checkAuth()`
24
- * gate inside `execute()` / `runTurn()`. Codex and Gemini each call
25
- * `await this.checkAuth()` at the top of `runTurn()` as a cheap way
26
- * to surface an early `BackendDecisiveFailure("auth")` before paying
27
- * the latency of spawning the CLI subprocess; Claude uses the
28
- * `@anthropic-ai/claude-agent-sdk` stream consumer instead, and the
29
- * SDK's first HTTP round-trip already returns a decisive 401 on its
30
- * own. A pre-flight here would duplicate work (two credential reads
31
- * per execute) and isn't needed to prevent accidental token use —
32
- * the reactive path in `BackendRouter` catches the SDK's 401, maps
33
- * it to `BackendDecisiveFailure("auth")`, and calls
34
- * `recordReactiveAuthFailure` exactly as if a pre-flight had run.
35
- *
36
- * This asymmetry is deliberate and matched by the corresponding
37
- * explanatory comments at `codex-core.ts` / `gemini-cli-core.ts`'s
38
- * `runTurn` pre-flight and at `IAgentCore.checkAuth` in
39
- * `agent-core.ts`. If you add a new backend, decide the pre-flight
40
- * question based on the CLI / SDK's own startup cost, not on
41
- * pattern-matching against one of the existing three.
42
- */
22
+ /** Visible for testing. */
23
+ export declare function getAttachedPartialSpend(error: unknown): BackendQuotaSpend | null;
43
24
  export declare class ClaudeCodeCore implements IAgentCore {
44
25
  private readonly config;
45
26
  /**
46
27
  * Shared AgentWriteTracker. When present, the Write/Edit PreToolUse hook
47
28
  * pre-marks vault-scoped writes so the ObsidianWatcher attributes the
48
29
  * resulting chokidar event to `actor='agent'` instead of `'user'`. Without
49
- * this wiring, the hourly_check dispatcher would re-discover the agent's
30
+ * this wiring, the activity_scan dispatcher would re-discover the agent's
50
31
  * own vault writes every cycle and loop.
51
32
  */
52
33
  private readonly writeTracker?;
34
+ /**
35
+ * PREPASS_COST_REDUCTION_PLAN.md N1 — used only to estimate the
36
+ * dollar figure of a partial spend snapshot when the SDK stream
37
+ * terminates abnormally (budget abort, timeout, transport failure).
38
+ * Success-path cost still comes from the SDK's own metering.
39
+ * Defaulted like the CLI cores' fetchers so bootstrap stays
40
+ * unchanged; guarded on `dataDir` because several unit tests
41
+ * construct the core with a partial config — those fall back to
42
+ * cap-floor-only estimation in `stampPartialSpend`.
43
+ */
44
+ private readonly priceFetcher;
53
45
  readonly backendId: "claude";
54
46
  private static readonly RETRY_DELAY_MS;
55
47
  private static readonly MAX_RETRIES;
@@ -78,10 +70,21 @@ export declare class ClaudeCodeCore implements IAgentCore {
78
70
  * Shared AgentWriteTracker. When present, the Write/Edit PreToolUse hook
79
71
  * pre-marks vault-scoped writes so the ObsidianWatcher attributes the
80
72
  * resulting chokidar event to `actor='agent'` instead of `'user'`. Without
81
- * this wiring, the hourly_check dispatcher would re-discover the agent's
73
+ * this wiring, the activity_scan dispatcher would re-discover the agent's
82
74
  * own vault writes every cycle and loop.
83
75
  */
84
- writeTracker?: AgentWriteTracker | undefined);
76
+ writeTracker?: AgentWriteTracker | undefined,
77
+ /**
78
+ * PREPASS_COST_REDUCTION_PLAN.md N1 — used only to estimate the
79
+ * dollar figure of a partial spend snapshot when the SDK stream
80
+ * terminates abnormally (budget abort, timeout, transport failure).
81
+ * Success-path cost still comes from the SDK's own metering.
82
+ * Defaulted like the CLI cores' fetchers so bootstrap stays
83
+ * unchanged; guarded on `dataDir` because several unit tests
84
+ * construct the core with a partial config — those fall back to
85
+ * cap-floor-only estimation in `stampPartialSpend`.
86
+ */
87
+ priceFetcher?: PriceFetcher | undefined);
85
88
  /** Set the per-daemon-boot read token for subprocess-local daemon API auth. */
86
89
  setReadToken(token: string): void;
87
90
  setReadTokenManager(manager: ReadSensitiveTokenManager): void;
@@ -150,6 +153,26 @@ export declare class ClaudeCodeCore implements IAgentCore {
150
153
  */
151
154
  private buildAdvisorSettings;
152
155
  private buildSystemPrompt;
156
+ /**
157
+ * Resolve the SDK `settingSources` for a session. Returns `["project"]`
158
+ * for `USER_SCOPE_SHED_PROCESS_KEYS` (dropping the daemon user's `~/.claude`
159
+ * scope — plugin SKILL.md tree + claude.ai connector schemas — from the
160
+ * prompt-cache prefix) and the default `["user", "project"]` otherwise. A
161
+ * fresh array per call: the SDK option type is mutable `SettingSource[]`.
162
+ *
163
+ * Applied at both `query()` sites (`executeOnce`, `executeResumeOnce`).
164
+ * Resume carries no `processKey` (it is always a reactive DM continuation,
165
+ * never a slim routine), so it always resolves to the full default.
166
+ */
167
+ private resolveSettingSources;
168
+ /**
169
+ * Whether to force `strictMcpConfig` for a session — true exactly for the
170
+ * `USER_SCOPE_SHED_PROCESS_KEYS`, as defense-in-depth on top of the
171
+ * `settingSources` drop (shuts out settings-file-sourced MCP servers; the
172
+ * daemon's own servers are passed programmatically and unaffected). Resume
173
+ * carries no `processKey`, so it never qualifies.
174
+ */
175
+ private resolveStrictMcpConfig;
153
176
  /**
154
177
  * Expand CLI-style aliases ("opus", "sonnet") to their current canonical
155
178
  * API IDs. Unrecognised strings pass through unchanged so custom or
@@ -166,6 +189,23 @@ export declare class ClaudeCodeCore implements IAgentCore {
166
189
  private executeResumeOnce;
167
190
  private runWithRetry;
168
191
  private isRetryableExecutionError;
192
+ /**
193
+ * PREPASS_COST_REDUCTION_PLAN.md N1 — build a spend snapshot from the
194
+ * stream's partial-usage accumulator and stamp it onto the propagating
195
+ * error so `classifyExecutionError` / `toBackendQuotaError` (which only
196
+ * see the error object) can lift it onto the classified failure.
197
+ *
198
+ * Dollar figure: estimated from the accumulated tokens via the shared
199
+ * price fetcher. For the SDK's `max_budget_usd` abort the figure is
200
+ * additionally floored at the cap — the SDK's own metering crossed it,
201
+ * so any lower estimate (e.g. usage observed only for the first few
202
+ * messages) would under-report what was actually billed. `costSource`
203
+ * is `"sdk_partial"` to mark the figure as a partial reconstruction.
204
+ *
205
+ * No-op when nothing recordable exists: no usage observed AND the
206
+ * error is not a budget abort with a known cap.
207
+ */
208
+ private stampPartialSpend;
169
209
  /** Visible for testing. */
170
210
  classifyExecutionError(error: unknown): BackendQuotaError | BackendDecisiveFailure;
171
211
  private toBackendQuotaError;