@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
@@ -4,13 +4,14 @@ import { dirname, join } from "node:path";
4
4
  import { formatSqliteDatetime } from "@aitne/shared";
5
5
  import { createLogger } from "../../../logging.js";
6
6
  import { readJsonBody } from "../../json-body.js";
7
- import { deleteAgent, getAgent, getOverrideSnapshot, listAgents, setEnabled, setOverrideSnapshot, } from "../../../db/agents-store.js";
7
+ import { deleteAgent, getAgent, getOverrideSnapshot, getRuntimeWindow, listAgents, setEnabled, setOverrideSnapshot, setRuntimeWindow, } from "../../../db/agents-store.js";
8
8
  import { byErrorKind, getExecution, listExecutions, metricsWindow, } from "../../../db/agent-executions-store.js";
9
9
  import { deleteRecurringSchedule, getRecurringSchedule, updateRecurringSchedule, } from "../../../db/recurring-schedules.js";
10
10
  import { loadEffectiveDefinition } from "../../../core/agents/effective-definition.js";
11
11
  import { loadAgents } from "../../../core/agents/loader.js";
12
12
  import { buildAgentLoadOptions } from "../../../core/agents/loader-boot.js";
13
- import { resolveRuntimeWindowCadence } from "../../../core/agents/builtin-registry.js";
13
+ import { getBuiltinRegistryEntry, resolveRuntimeWindowCadence, } from "../../../core/agents/builtin-registry.js";
14
+ import { mergeRuntimeWindow, resolveActivityScanCadence, } from "../../../core/agents/activity-scan-cadence.js";
14
15
  import { buildDetail, buildListItem, buildRow, planCreate, planPatch, planRunNow, serializeExecution, } from "./views.js";
15
16
  /**
16
17
  * `/api/agents/*` route surface (AGENT_DEFINITIONS_DESIGN.md §9). Thin Hono
@@ -22,6 +23,19 @@ import { buildDetail, buildListItem, buildRow, planCreate, planPatch, planRunNow
22
23
  * is pinned by the behavioural `agents.test.ts`.
23
24
  */
24
25
  const logger = createLogger("agents-api");
26
+ /**
27
+ * v0.1.10 → v0.1.11: the `hourly-check` built-in became `activity-scan`.
28
+ * Old URLs (`/api/agents/hourly-check`, bookmarks, in-flight skills) keep
29
+ * working for one deprecation window — same in-process normalization
30
+ * pattern as `context-vault-aliases.ts` (never an HTTP redirect, so
31
+ * `curl -X PATCH` without `-L` keeps working). Remove after a minor release.
32
+ */
33
+ const LEGACY_AGENT_SLUG_ALIASES = {
34
+ "hourly-check": "activity-scan",
35
+ };
36
+ function normalizeSlug(raw) {
37
+ return LEGACY_AGENT_SLUG_ALIASES[raw] ?? raw;
38
+ }
25
39
  /** Per-Agent 7d-metrics cache (§9.1 — "cached in-memory for 60 seconds"). */
26
40
  const METRICS_TTL_MS = 60_000;
27
41
  const EXECUTION_RESULTS = new Set([
@@ -34,15 +48,37 @@ export function createAgentDefinitionRoutes(deps) {
34
48
  const app = new Hono();
35
49
  const { db, config } = deps;
36
50
  const dayBoundaryHour = config.dayBoundaryHour;
37
- // Live interval cadence for a runtime-window built-in (hourly-check), or null
38
- // for every other Agent. Reads `config` at call time — `applyConfigUpdates`
39
- // mutates it in place (Object.assign), so a runtime interval/active-hours
40
- // change via PATCH /api/config is reflected here without a daemon restart.
41
- const cadenceFor = (slug) => resolveRuntimeWindowCadence(slug, {
42
- hourlyCheckIntervalMinutes: config.hourlyCheckIntervalMinutes,
43
- hourlyCheckActiveStartHour: config.hourlyCheckActiveStartHour,
44
- hourlyCheckActiveEndHour: config.hourlyCheckActiveEndHour,
45
- });
51
+ // Live interval cadence for a runtime-window built-in (activity-scan), or null
52
+ // for every other Agent. The agent row's `runtime_window` overrides win;
53
+ // the legacy `activityScan*` config keys are the per-field fallback
54
+ // (AGENTS_HUB_REDESIGN_PLAN §2). Read at call time so a PATCH is reflected
55
+ // immediately.
56
+ const cadenceFor = (slug) => {
57
+ const resolved = resolveActivityScanCadence(getRuntimeWindow(db, "activity-scan"), config);
58
+ return resolveRuntimeWindowCadence(slug, {
59
+ activityScanIntervalMinutes: resolved.intervalMinutes,
60
+ activityScanActiveStartHour: resolved.activeStartHour,
61
+ activityScanActiveEndHour: resolved.activeEndHour,
62
+ });
63
+ };
64
+ // Runtime-window block for the detail envelope — only for the
65
+ // runtime-window built-in (registry cron resolver === null).
66
+ const scheduleWindowFor = (slug) => {
67
+ const entry = getBuiltinRegistryEntry(slug);
68
+ if (!entry || entry.cronExpression !== null)
69
+ return null;
70
+ const overrides = getRuntimeWindow(db, slug);
71
+ const resolved = resolveActivityScanCadence(overrides, config);
72
+ return {
73
+ overrides: overrides,
74
+ resolved: {
75
+ interval_minutes: resolved.intervalMinutes,
76
+ active_start_hour: resolved.activeStartHour,
77
+ active_end_hour: resolved.activeEndHour,
78
+ min_observations: resolved.minObservations,
79
+ },
80
+ };
81
+ };
46
82
  const readDefinitionFile = (path) => {
47
83
  try {
48
84
  return existsSync(path) ? readFileSync(path, "utf-8") : null;
@@ -168,7 +204,7 @@ export function createAgentDefinitionRoutes(deps) {
168
204
  });
169
205
  // ── GET /agents/:slug (§9.2) ────────────────────────────────────────────
170
206
  app.get("/agents/:slug", (c) => {
171
- const slug = c.req.param("slug");
207
+ const slug = normalizeSlug(c.req.param("slug"));
172
208
  const dto = getAgent(db, slug);
173
209
  if (!dto)
174
210
  return c.json({ error: "agent_not_found", slug }, 404);
@@ -185,12 +221,13 @@ export function createAgentDefinitionRoutes(deps) {
185
221
  metrics30d: metricsWindow(db, slug, 30),
186
222
  byErrorKind7d: byErrorKind(db, slug, 7),
187
223
  intervalCadence: cadenceFor(slug),
224
+ scheduleWindow: scheduleWindowFor(slug),
188
225
  });
189
226
  return c.json(detail);
190
227
  });
191
228
  // ── GET /agents/:slug/executions (§9.3) ─────────────────────────────────
192
229
  app.get("/agents/:slug/executions", (c) => {
193
- const slug = c.req.param("slug");
230
+ const slug = normalizeSlug(c.req.param("slug"));
194
231
  if (!getAgent(db, slug))
195
232
  return c.json({ error: "agent_not_found", slug }, 404);
196
233
  const limitRaw = Number.parseInt(c.req.query("limit") ?? "25", 10);
@@ -211,7 +248,7 @@ export function createAgentDefinitionRoutes(deps) {
211
248
  });
212
249
  // ── POST /agents/:slug/run-now (§9.4) ───────────────────────────────────
213
250
  app.post("/agents/:slug/run-now", async (c) => {
214
- const slug = c.req.param("slug");
251
+ const slug = normalizeSlug(c.req.param("slug"));
215
252
  const dto = getAgent(db, slug);
216
253
  if (!dto)
217
254
  return c.json({ error: "agent_not_found", slug }, 404);
@@ -288,7 +325,7 @@ export function createAgentDefinitionRoutes(deps) {
288
325
  });
289
326
  // ── PATCH /agents/:slug (§9.5) ──────────────────────────────────────────
290
327
  app.patch("/agents/:slug", async (c) => {
291
- const slug = c.req.param("slug");
328
+ const slug = normalizeSlug(c.req.param("slug"));
292
329
  const dto = getAgent(db, slug);
293
330
  if (!dto)
294
331
  return c.json({ error: "agent_not_found", slug }, 404);
@@ -307,6 +344,15 @@ export function createAgentDefinitionRoutes(deps) {
307
344
  return c.json({ error: plan.error, ...(plan.hint ? { hint: plan.hint } : {}), ...(plan.field ? { field: plan.field } : {}) }, 400);
308
345
  }
309
346
  const now = Date.now();
347
+ // Validate the schedule_window merge BEFORE applying anything so a bad
348
+ // window can't leave a half-applied PATCH (enabled flipped, window 400d).
349
+ let mergedWindow;
350
+ if (plan.scheduleWindow !== undefined) {
351
+ mergedWindow = mergeRuntimeWindow(getRuntimeWindow(db, slug), plan.scheduleWindow, config);
352
+ if (!mergedWindow.ok) {
353
+ return c.json({ error: mergedWindow.error, field: mergedWindow.field }, 400);
354
+ }
355
+ }
310
356
  if (plan.setEnabled !== undefined) {
311
357
  setEnabled(db, slug, plan.setEnabled, now, now);
312
358
  deps.agentEnabledCache?.invalidate();
@@ -337,6 +383,19 @@ export function createAgentDefinitionRoutes(deps) {
337
383
  reset: plan.overrideReset,
338
384
  });
339
385
  }
386
+ if (mergedWindow?.ok) {
387
+ setRuntimeWindow(db, slug, mergedWindow.value, now);
388
+ recordAudit("agent.schedule_window_changed", slug, {
389
+ window: mergedWindow.value,
390
+ cadence_changed: mergedWindow.cadenceChanged,
391
+ });
392
+ // Interval / active-hours edits change the registered cron expression;
393
+ // rebuild live (same mechanism the dashboard config PATCH used for the
394
+ // legacy keys). min_observations is fire-time-only — no rebuild.
395
+ if (mergedWindow.cadenceChanged) {
396
+ deps.onScheduleConfigChanged?.();
397
+ }
398
+ }
340
399
  if (plan.stripped.length > 0) {
341
400
  logger.info({ slug, stripped: plan.stripped }, "PATCH /agents stripped read-only fields");
342
401
  }
@@ -346,7 +405,7 @@ export function createAgentDefinitionRoutes(deps) {
346
405
  });
347
406
  // ── DELETE /agents/:slug (§9.6) ─────────────────────────────────────────
348
407
  app.delete("/agents/:slug", async (c) => {
349
- const slug = c.req.param("slug");
408
+ const slug = normalizeSlug(c.req.param("slug"));
350
409
  const dto = getAgent(db, slug);
351
410
  if (!dto)
352
411
  return c.json({ error: "agent_not_found", slug }, 404);
@@ -1,6 +1,6 @@
1
1
  import type { AgentDefinition, StopWarning } from "@aitne/shared";
2
2
  import { OVERRIDE_EDIT_PATHS } from "@aitne/shared";
3
- import type { IntervalCadence } from "../../../core/agents/builtin-registry.js";
3
+ import type { AgentPolicyFile, IntervalCadence } from "../../../core/agents/builtin-registry.js";
4
4
  import type { AgentDTO } from "../../../db/agents-store.js";
5
5
  import type { AgentExecutionDTO, AgentMetricsWindow } from "../../../db/agent-executions-store.js";
6
6
  /**
@@ -24,13 +24,26 @@ export interface ListItemInputs {
24
24
  metrics7d: AgentMetricsWindow;
25
25
  lastExecution: AgentExecutionDTO | null;
26
26
  /**
27
- * Live interval cadence for a runtime-window built-in (hourly-check), or
27
+ * Live interval cadence for a runtime-window built-in (activity-scan), or
28
28
  * `null` for fixed-cron / one-shot / event Agents. Resolved by the route from
29
29
  * live config via `resolveRuntimeWindowCadence` so the schedule block carries
30
30
  * the REAL cadence rather than the stored placeholder cron (§5.5.1).
31
31
  */
32
32
  intervalCadence?: IntervalCadence | null;
33
33
  }
34
+ /**
35
+ * Hub category for the `/agents` dashboard grouping
36
+ * (AGENTS_HUB_REDESIGN_PLAN.md §4.1): built-ins carry their registry
37
+ * category; every user Agent is `"user"`. An unknown builtin slug (should
38
+ * not happen — the loader synthesises rows from the registry) degrades to
39
+ * `"maintenance"` rather than failing the response.
40
+ */
41
+ export declare function agentCategory(dto: AgentDTO): string;
42
+ /**
43
+ * The declared Rulebook surface (registry `policyFiles`) for a built-in, or
44
+ * `[]` for user Agents / undeclared built-ins (AGENTS_HUB_REDESIGN_PLAN §4.2).
45
+ */
46
+ export declare function agentPolicyFiles(dto: AgentDTO): readonly AgentPolicyFile[];
34
47
  /** One row of `GET /api/agents` (§9.1). `kind` mirrors the stored `source`. */
35
48
  export declare function buildListItem(dto: AgentDTO, inputs: ListItemInputs): Record<string, unknown>;
36
49
  /**
@@ -50,6 +63,21 @@ export interface DetailInputs {
50
63
  byErrorKind7d: Record<string, number>;
51
64
  /** Live runtime-window cadence for the detail `row.schedule_interval` (§5.5.1). */
52
65
  intervalCadence?: IntervalCadence | null;
66
+ /**
67
+ * Runtime-window editing block for a runtime-window built-in (activity-scan):
68
+ * the stored per-field overrides + the fully-resolved effective values the
69
+ * cadence form prefills with. Null/absent for every other Agent
70
+ * (AGENTS_HUB_REDESIGN_PLAN §2).
71
+ */
72
+ scheduleWindow?: {
73
+ overrides: Record<string, number>;
74
+ resolved: {
75
+ interval_minutes: number;
76
+ active_start_hour: number;
77
+ active_end_hour: number;
78
+ min_observations: number;
79
+ };
80
+ } | null;
53
81
  }
54
82
  /** Full `GET /api/agents/:slug` envelope (§9.2). */
55
83
  export declare function buildDetail(inputs: DetailInputs): Record<string, unknown>;
@@ -166,6 +194,13 @@ export type PatchPlan = {
166
194
  overrideSet: Record<string, unknown>;
167
195
  /** Built-in override-snapshot keys to delete. */
168
196
  overrideReset: string[];
197
+ /**
198
+ * Raw `schedule_window` patch for a runtime-window built-in
199
+ * (AGENTS_HUB_REDESIGN_PLAN §2). Field-level validation + the
200
+ * cross-field window check happen in `mergeRuntimeWindow` at the route
201
+ * (it needs the stored override + live config). Undefined when absent.
202
+ */
203
+ scheduleWindow?: Record<string, unknown>;
169
204
  /** For a user Agent enabled toggle: mirror onto its recurring row. */
170
205
  mirrorRecurringEnabled?: boolean;
171
206
  /** Read-only / unknown body keys ignored (logged in the response). */
@@ -1,4 +1,5 @@
1
- import { AGENT_TIERS, OVERRIDE_EDIT_PATHS, agentDefinitionSchema, recurrenceRuleSchema } from "@aitne/shared";
1
+ import { AGENT_TIERS, BACKEND_IDS, OVERRIDE_EDIT_PATHS, agentDefinitionSchema, recurrenceRuleSchema } from "@aitne/shared";
2
+ import { getBuiltinRegistryEntry } from "../../../core/agents/builtin-registry.js";
2
3
  import { recurrenceRuleToCron } from "../../../core/agents/recurrence-convert.js";
3
4
  import { renderAgentMarkdown } from "../../../core/agents/agent-frontmatter.js";
4
5
  /**
@@ -67,6 +68,27 @@ export function serializeListMetrics(w) {
67
68
  criteria_hit_rate: w.criteriaHitRate,
68
69
  };
69
70
  }
71
+ /**
72
+ * Hub category for the `/agents` dashboard grouping
73
+ * (AGENTS_HUB_REDESIGN_PLAN.md §4.1): built-ins carry their registry
74
+ * category; every user Agent is `"user"`. An unknown builtin slug (should
75
+ * not happen — the loader synthesises rows from the registry) degrades to
76
+ * `"maintenance"` rather than failing the response.
77
+ */
78
+ export function agentCategory(dto) {
79
+ if (dto.source === "user")
80
+ return "user";
81
+ return getBuiltinRegistryEntry(dto.slug)?.category ?? "maintenance";
82
+ }
83
+ /**
84
+ * The declared Rulebook surface (registry `policyFiles`) for a built-in, or
85
+ * `[]` for user Agents / undeclared built-ins (AGENTS_HUB_REDESIGN_PLAN §4.2).
86
+ */
87
+ export function agentPolicyFiles(dto) {
88
+ if (dto.source !== "builtin")
89
+ return [];
90
+ return getBuiltinRegistryEntry(dto.slug)?.policyFiles ?? [];
91
+ }
70
92
  /** One row of `GET /api/agents` (§9.1). `kind` mirrors the stored `source`. */
71
93
  export function buildListItem(dto, inputs) {
72
94
  // Read the parse-error into a camelCase local + emit it via the object-literal
@@ -87,6 +109,7 @@ export function buildListItem(dto, inputs) {
87
109
  // string here loses no information (a valid/fallback row always has one).
88
110
  description: dto.description ?? "",
89
111
  kind: dto.source,
112
+ category: agentCategory(dto),
90
113
  enabled: dto.enabled,
91
114
  tags: dto.tags,
92
115
  schedule: {
@@ -119,6 +142,7 @@ export function buildRow(dto, intervalCadence = null) {
119
142
  // failure via the envelope's separate error field, not this column.
120
143
  description: dto.description ?? "",
121
144
  source: dto.source,
145
+ category: agentCategory(dto),
122
146
  definition_path: dto.definitionPath,
123
147
  definition_hash: dto.definitionHash,
124
148
  enabled: dto.enabled,
@@ -154,6 +178,14 @@ export function buildDetail(inputs) {
154
178
  },
155
179
  definition_yaml: inputs.definitionYaml,
156
180
  definition_path: inputs.dto.definitionPath,
181
+ // Rulebook tab inputs (AGENTS_HUB_REDESIGN_PLAN §4.2): the vault policy
182
+ // files this Agent reads at prompt-assembly time. The dashboard edits
183
+ // them through `/api/context/<path>`; this only declares the list.
184
+ policy_files: agentPolicyFiles(inputs.dto),
185
+ // Runtime-window editing inputs (§2): stored overrides + resolved
186
+ // effective values for the activity-scan cadence form. `null` for every
187
+ // non-runtime-window Agent.
188
+ schedule_window: inputs.scheduleWindow ?? null,
157
189
  };
158
190
  }
159
191
  /**
@@ -296,6 +328,13 @@ export function planCreate(body, existingSlugs) {
296
328
  kind: "cron",
297
329
  expression: recurrenceRuleToCron(parsedRule.data),
298
330
  ...(timezone !== undefined ? { timezone } : {}),
331
+ // Quiet-hours opt-in (QUIET_HOURS_HARDENING_PLAN.md §6) — carried
332
+ // verbatim so the schema validates it (a non-boolean is rejected as
333
+ // invalid_definition on schedule.defer_in_quiet_hours, same as the raw
334
+ // cron form, where the whole schedule block passes through).
335
+ ...(schedule.defer_in_quiet_hours !== undefined
336
+ ? { defer_in_quiet_hours: schedule.defer_in_quiet_hours }
337
+ : {}),
299
338
  };
300
339
  }
301
340
  else if (scheduleKind === "cron") {
@@ -382,7 +421,7 @@ export const EDITABLE_NESTED = (() => {
382
421
  }
383
422
  return acc;
384
423
  })();
385
- const CONTROL_KEYS = new Set(["enabled", "ack_warning", "reset"]);
424
+ const CONTROL_KEYS = new Set(["enabled", "ack_warning", "reset", "schedule_window"]);
386
425
  function isAgentTier(v) {
387
426
  return typeof v === "string" && AGENT_TIERS.includes(v);
388
427
  }
@@ -399,6 +438,8 @@ function isValidOverrideValue(path, value) {
399
438
  return value === null || isAgentTier(value);
400
439
  case "backend.model":
401
440
  return value === null || (typeof value === "string" && value.length > 0);
441
+ case "backend.backend_id":
442
+ return value === null || (typeof value === "string" && BACKEND_IDS.includes(value));
402
443
  case "limits.max_turns":
403
444
  case "limits.timeout_minutes":
404
445
  return isPositiveInt(value);
@@ -483,6 +524,26 @@ export function planPatch(dto, body) {
483
524
  }
484
525
  }
485
526
  }
527
+ // ── schedule_window (runtime-window built-ins only) ──
528
+ let scheduleWindow;
529
+ if ("schedule_window" in body) {
530
+ if (!isPlainObject(body.schedule_window)) {
531
+ return { ok: false, status: 400, error: "invalid_schedule_window", field: "schedule_window" };
532
+ }
533
+ const entry = dto.source === "builtin" ? getBuiltinRegistryEntry(dto.slug) : undefined;
534
+ // Runtime-window marker: a builtin whose registry cron resolver is null
535
+ // (today: activity-scan) owns an interval cadence on its agent row.
536
+ if (!entry || entry.cronExpression !== null) {
537
+ return {
538
+ ok: false,
539
+ status: 400,
540
+ error: "schedule_window_not_supported",
541
+ field: "schedule_window",
542
+ hint: "Only the interval-based activity-scan Agent accepts schedule_window edits.",
543
+ };
544
+ }
545
+ scheduleWindow = body.schedule_window;
546
+ }
486
547
  // ── user Agents: only enabled is editable via this endpoint ──
487
548
  if (dto.source === "user" && (edits.length > 0 || reset.length > 0)) {
488
549
  return {
@@ -506,6 +567,7 @@ export function planPatch(dto, body) {
506
567
  overrideReset: reset,
507
568
  stripped,
508
569
  ...(setEnabled !== undefined ? { setEnabled } : {}),
570
+ ...(scheduleWindow !== undefined ? { scheduleWindow } : {}),
509
571
  };
510
572
  if (dto.source === "user" && setEnabled !== undefined && dto.recurringScheduleId !== null) {
511
573
  plan.mirrorRecurringEnabled = setEnabled;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * /api/background-task/* — BACKGROUND_TASK_RUNNER_DESIGN.md §7.
3
+ *
4
+ * The generic detached-task surface. The DM agent POSTs a self-contained
5
+ * brief, acks, and ends its turn; the runner runs the worker detached and
6
+ * writes an artifact; the delivery boundary surfaces it. GET /:id returns
7
+ * the artifact (the DM agent's "read the result" affordance for precise
8
+ * follow-ups). /clarify relays the owner's answer; /cancel aborts.
9
+ *
10
+ * Routes (§7):
11
+ * POST /api/background-task spawn (or schedule via scheduleAt)
12
+ * GET /api/background-task list
13
+ * GET /api/background-task/:id the artifact (full detail)
14
+ * POST /api/background-task/:id/clarify answer a pending clarification
15
+ * POST /api/background-task/:id/cancel abort in-flight task
16
+ *
17
+ * Excluded from the 100% coverage gate — route glue. The pure pieces
18
+ * (budget envelope, slot manager) are 100%-covered peers.
19
+ */
20
+ import { Hono } from "hono";
21
+ import type { ApiDependencies } from "../server.js";
22
+ export declare function createBackgroundTaskRoutes(deps: ApiDependencies): Hono;