@vellumai/assistant 0.6.3 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (667) hide show
  1. package/ARCHITECTURE.md +273 -10
  2. package/Dockerfile +2 -3
  3. package/bun.lock +5 -13
  4. package/docs/backup-troubleshooting.md +52 -0
  5. package/docs/browser-use-architecture-phase2.md +174 -0
  6. package/docs/stt-provider-onboarding.md +120 -0
  7. package/knip.json +12 -2
  8. package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
  9. package/node_modules/@vellumai/ces-contracts/package.json +3 -3
  10. package/openapi.yaml +982 -72
  11. package/package.json +4 -6
  12. package/scripts/generate-openapi.ts +0 -1
  13. package/scripts/test.sh +73 -18
  14. package/src/__tests__/agent-image-optimize.test.ts +28 -0
  15. package/src/__tests__/agent-loop.test.ts +123 -0
  16. package/src/__tests__/anthropic-provider.test.ts +263 -10
  17. package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
  18. package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
  19. package/src/__tests__/browser-fill-credential.test.ts +11 -0
  20. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  21. package/src/__tests__/browser-skill-endstate.test.ts +31 -7
  22. package/src/__tests__/btw-routes.test.ts +7 -0
  23. package/src/__tests__/call-controller.test.ts +581 -20
  24. package/src/__tests__/catalog-files.test.ts +138 -0
  25. package/src/__tests__/channel-invite-transport.test.ts +2 -2
  26. package/src/__tests__/channel-readiness-routes.test.ts +16 -20
  27. package/src/__tests__/channel-readiness-service.test.ts +12 -7
  28. package/src/__tests__/checker.test.ts +157 -10
  29. package/src/__tests__/clawhub-files.test.ts +347 -0
  30. package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
  31. package/src/__tests__/config-analysis.test.ts +100 -0
  32. package/src/__tests__/config-schema.test.ts +1013 -66
  33. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
  34. package/src/__tests__/config-watcher.test.ts +43 -8
  35. package/src/__tests__/contact-store-user-file.test.ts +512 -0
  36. package/src/__tests__/contacts-write.test.ts +197 -0
  37. package/src/__tests__/context-window-manager.test.ts +88 -0
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
  39. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  40. package/src/__tests__/conversation-agent-loop.test.ts +98 -2
  41. package/src/__tests__/conversation-confirmation-signals.test.ts +135 -0
  42. package/src/__tests__/conversation-error.test.ts +70 -0
  43. package/src/__tests__/conversation-history-web-search.test.ts +11 -4
  44. package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
  45. package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
  46. package/src/__tests__/conversation-list-source.test.ts +145 -0
  47. package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
  48. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
  49. package/src/__tests__/conversation-queue.test.ts +901 -60
  50. package/src/__tests__/conversation-routes-disk-view.test.ts +270 -0
  51. package/src/__tests__/conversation-runtime-assembly.test.ts +55 -0
  52. package/src/__tests__/conversation-skill-tools.test.ts +7 -4
  53. package/src/__tests__/conversation-slash-commands.test.ts +33 -0
  54. package/src/__tests__/conversation-slash-queue.test.ts +89 -18
  55. package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
  56. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
  57. package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
  58. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
  59. package/src/__tests__/credential-health-service.test.ts +352 -0
  60. package/src/__tests__/credential-security-invariants.test.ts +5 -3
  61. package/src/__tests__/credential-vault-unit.test.ts +379 -3
  62. package/src/__tests__/credentials-cli.test.ts +40 -16
  63. package/src/__tests__/cross-provider-web-search.test.ts +146 -35
  64. package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
  65. package/src/__tests__/device-id.test.ts +112 -0
  66. package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
  67. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
  68. package/src/__tests__/email-html-renderer.test.ts +71 -0
  69. package/src/__tests__/email-invite-adapter.test.ts +36 -32
  70. package/src/__tests__/emit-event-signal.test.ts +71 -0
  71. package/src/__tests__/extension-id-sync-guard.test.ts +75 -8
  72. package/src/__tests__/fixtures/mock-chrome-extension.ts +11 -0
  73. package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
  74. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  75. package/src/__tests__/gemini-provider.test.ts +64 -0
  76. package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
  77. package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
  78. package/src/__tests__/gmail-archive-gate.test.ts +246 -0
  79. package/src/__tests__/gmail-preferences.test.ts +117 -0
  80. package/src/__tests__/headless-browser-interactions.test.ts +43 -0
  81. package/src/__tests__/headless-browser-mode.test.ts +614 -0
  82. package/src/__tests__/headless-browser-navigate.test.ts +142 -5
  83. package/src/__tests__/headless-browser-read-tools.test.ts +11 -0
  84. package/src/__tests__/headless-browser-snapshot.test.ts +10 -0
  85. package/src/__tests__/heartbeat-service.test.ts +70 -17
  86. package/src/__tests__/home-state-routes.test.ts +162 -0
  87. package/src/__tests__/host-bash-proxy.test.ts +0 -5
  88. package/src/__tests__/host-browser-e2e-cloud.test.ts +138 -4
  89. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +4 -4
  90. package/src/__tests__/host-browser-ws-events-e2e.test.ts +103 -0
  91. package/src/__tests__/host-cu-proxy.test.ts +0 -5
  92. package/src/__tests__/identity-intro-cache.test.ts +40 -10
  93. package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
  94. package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
  95. package/src/__tests__/llm-context-normalization.test.ts +488 -0
  96. package/src/__tests__/llm-context-route-provider.test.ts +86 -5
  97. package/src/__tests__/llm-usage-store.test.ts +363 -0
  98. package/src/__tests__/media-stream-output.test.ts +555 -0
  99. package/src/__tests__/media-stream-parser.test.ts +374 -0
  100. package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
  101. package/src/__tests__/media-stream-stt-session.test.ts +588 -0
  102. package/src/__tests__/media-turn-detector.test.ts +440 -0
  103. package/src/__tests__/message-queue.test.ts +125 -0
  104. package/src/__tests__/migration-export-http.test.ts +6 -6
  105. package/src/__tests__/migration-import-commit-http.test.ts +8 -6
  106. package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
  107. package/src/__tests__/migration-validate-http.test.ts +3 -3
  108. package/src/__tests__/mock-gateway-ipc.ts +151 -0
  109. package/src/__tests__/model-intents.test.ts +2 -2
  110. package/src/__tests__/oauth-apps-routes.test.ts +1 -0
  111. package/src/__tests__/oauth-cli.test.ts +2 -0
  112. package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
  113. package/src/__tests__/oauth-provider-serializer.test.ts +1 -0
  114. package/src/__tests__/oauth-providers-routes.test.ts +2 -0
  115. package/src/__tests__/oauth-store.test.ts +85 -0
  116. package/src/__tests__/oauth2-gateway-transport.test.ts +249 -6
  117. package/src/__tests__/onboarding-template-contract.test.ts +6 -13
  118. package/src/__tests__/openai-provider.test.ts +176 -0
  119. package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
  120. package/src/__tests__/openai-responses-provider.test.ts +1105 -0
  121. package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
  122. package/src/__tests__/outlook-unsubscribe.test.ts +31 -2
  123. package/src/__tests__/persona-resolver.test.ts +251 -0
  124. package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
  125. package/src/__tests__/platform.test.ts +92 -1
  126. package/src/__tests__/post-turn-tool-result-truncation.test.ts +47 -0
  127. package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
  128. package/src/__tests__/pricing.test.ts +174 -0
  129. package/src/__tests__/qdrant-manager.test.ts +29 -8
  130. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
  131. package/src/__tests__/relationship-state-contract.test.ts +175 -0
  132. package/src/__tests__/relay-server.test.ts +423 -5
  133. package/src/__tests__/search-skills-unified.test.ts +118 -0
  134. package/src/__tests__/secret-scanner-executor.test.ts +4 -0
  135. package/src/__tests__/secure-keys.test.ts +107 -0
  136. package/src/__tests__/send-endpoint-busy.test.ts +5 -1
  137. package/src/__tests__/sequence-store.test.ts +1 -1
  138. package/src/__tests__/server-history-render.test.ts +49 -0
  139. package/src/__tests__/settings-routes.test.ts +201 -0
  140. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  141. package/src/__tests__/skills-file-content-endpoint.test.ts +276 -145
  142. package/src/__tests__/skills-files-catalog-fallback.test.ts +381 -93
  143. package/src/__tests__/skills.test.ts +5 -2
  144. package/src/__tests__/skillssh-files.test.ts +446 -0
  145. package/src/__tests__/slack-block-formatting.test.ts +110 -0
  146. package/src/__tests__/slack-channel-config.test.ts +564 -1
  147. package/src/__tests__/stt-catalog-parity.test.ts +282 -0
  148. package/src/__tests__/stt-stream-session.test.ts +535 -0
  149. package/src/__tests__/system-prompt.test.ts +112 -26
  150. package/src/__tests__/telephony-stt-routing.test.ts +329 -0
  151. package/src/__tests__/terminal-tools.test.ts +18 -7
  152. package/src/__tests__/test-preload.ts +18 -0
  153. package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
  155. package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
  156. package/src/__tests__/tool-executor.test.ts +33 -24
  157. package/src/__tests__/tool-result-truncation.test.ts +36 -0
  158. package/src/__tests__/trust-store.test.ts +7 -1
  159. package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
  160. package/src/__tests__/tts-catalog-parity.test.ts +345 -0
  161. package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
  162. package/src/__tests__/twilio-routes.test.ts +376 -0
  163. package/src/__tests__/unicode.test.ts +293 -0
  164. package/src/__tests__/update-bulletin-format.test.ts +59 -0
  165. package/src/__tests__/update-bulletin.test.ts +206 -5
  166. package/src/__tests__/usage-routes.test.ts +25 -4
  167. package/src/__tests__/user-reference.test.ts +46 -61
  168. package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
  169. package/src/__tests__/voice-config-update.test.ts +403 -0
  170. package/src/__tests__/voice-quality.test.ts +434 -19
  171. package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
  172. package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
  173. package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
  174. package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
  175. package/src/__tests__/workspace-migration-meets.test.ts +244 -0
  176. package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
  177. package/src/__tests__/workspace-policy.test.ts +2 -0
  178. package/src/agent/image-optimize.ts +24 -12
  179. package/src/agent/loop.ts +43 -3
  180. package/src/backup/__tests__/backup-key.test.ts +152 -0
  181. package/src/backup/__tests__/backup-worker.test.ts +767 -0
  182. package/src/backup/__tests__/list-snapshots.test.ts +87 -0
  183. package/src/backup/__tests__/local-writer.test.ts +218 -0
  184. package/src/backup/__tests__/offsite-writer.test.ts +641 -0
  185. package/src/backup/__tests__/paths.test.ts +300 -0
  186. package/src/backup/__tests__/restore.test.ts +498 -0
  187. package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
  188. package/src/backup/__tests__/stream-crypt.test.ts +228 -0
  189. package/src/backup/backup-key.ts +137 -0
  190. package/src/backup/backup-worker.ts +459 -0
  191. package/src/backup/list-snapshots.ts +147 -0
  192. package/src/backup/local-writer.ts +133 -0
  193. package/src/backup/offsite-writer.ts +222 -0
  194. package/src/backup/paths.ts +226 -0
  195. package/src/backup/restore.ts +322 -0
  196. package/src/backup/snapshot-lock.ts +431 -0
  197. package/src/backup/stream-crypt.ts +263 -0
  198. package/src/bundler/package-resolver.ts +4 -0
  199. package/src/calls/audio-store.ts +11 -5
  200. package/src/calls/call-controller.ts +226 -71
  201. package/src/calls/call-domain.ts +9 -0
  202. package/src/calls/call-speech-output.ts +190 -0
  203. package/src/calls/call-transport.ts +77 -0
  204. package/src/calls/media-stream-audio-transcode.ts +173 -0
  205. package/src/calls/media-stream-output.ts +660 -0
  206. package/src/calls/media-stream-parser.ts +300 -0
  207. package/src/calls/media-stream-protocol.ts +166 -0
  208. package/src/calls/media-stream-server.ts +592 -0
  209. package/src/calls/media-stream-stt-session.ts +460 -0
  210. package/src/calls/media-turn-detector.ts +230 -0
  211. package/src/calls/relay-server.ts +90 -75
  212. package/src/calls/resolve-call-tts-provider.ts +136 -0
  213. package/src/calls/telephony-stt-routing.ts +145 -0
  214. package/src/calls/tts-call-strategy.ts +161 -0
  215. package/src/calls/tts-text-sanitizer.ts +32 -16
  216. package/src/calls/twilio-routes.ts +281 -17
  217. package/src/calls/voice-quality.ts +78 -35
  218. package/src/calls/voice-session-bridge.ts +8 -1
  219. package/src/channels/types.ts +16 -0
  220. package/src/cli/__tests__/run-assistant-command.ts +11 -1
  221. package/src/cli/commands/__tests__/backup.test.ts +1165 -0
  222. package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
  223. package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
  224. package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
  225. package/src/cli/commands/__tests__/email-download.test.ts +16 -1
  226. package/src/cli/commands/__tests__/email-list.test.ts +22 -4
  227. package/src/cli/commands/__tests__/email-register.test.ts +4 -4
  228. package/src/cli/commands/__tests__/email-send.test.ts +37 -4
  229. package/src/cli/commands/__tests__/email-status.test.ts +5 -1
  230. package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
  231. package/src/cli/commands/backup.ts +993 -0
  232. package/src/cli/commands/conversations.ts +77 -0
  233. package/src/cli/commands/credentials.ts +0 -1
  234. package/src/cli/commands/domain.ts +210 -0
  235. package/src/cli/commands/email.ts +255 -3
  236. package/src/cli/commands/oauth/__tests__/connect.test.ts +12 -0
  237. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +1 -0
  238. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -0
  239. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -0
  240. package/src/cli/commands/oauth/mode.ts +12 -3
  241. package/src/cli/commands/oauth/providers.ts +15 -0
  242. package/src/cli/commands/oauth/shared.ts +2 -1
  243. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +4 -9
  244. package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
  245. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  246. package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
  247. package/src/cli/program.ts +30 -4
  248. package/src/config/__tests__/backup-schema.test.ts +134 -0
  249. package/src/config/assistant-feature-flags.ts +61 -62
  250. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +37 -1
  251. package/src/config/bundled-skills/browser/SKILL.md +30 -5
  252. package/src/config/bundled-skills/browser/TOOLS.json +123 -0
  253. package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
  254. package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
  255. package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
  256. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
  257. package/src/config/bundled-skills/contacts/SKILL.md +2 -2
  258. package/src/config/bundled-skills/gmail/SKILL.md +53 -7
  259. package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
  260. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
  261. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
  262. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
  263. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
  264. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
  265. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
  266. package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
  267. package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
  268. package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
  269. package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
  270. package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
  271. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
  272. package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
  273. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
  274. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  275. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
  276. package/src/config/bundled-skills/outlook/SKILL.md +2 -2
  277. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
  278. package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
  279. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
  280. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
  281. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  282. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
  283. package/src/config/bundled-skills/slack/SKILL.md +1 -0
  284. package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
  285. package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
  286. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
  287. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
  288. package/src/config/bundled-tool-registry.ts +8 -0
  289. package/src/config/env-registry.ts +24 -0
  290. package/src/config/env.ts +34 -10
  291. package/src/config/feature-flag-registry.json +46 -14
  292. package/src/config/loader.ts +26 -12
  293. package/src/config/schema.ts +35 -10
  294. package/src/config/schemas/__tests__/stt.test.ts +43 -0
  295. package/src/config/schemas/analysis.ts +51 -0
  296. package/src/config/schemas/backup.ts +72 -0
  297. package/src/config/schemas/calls.ts +1 -26
  298. package/src/config/schemas/elevenlabs.ts +0 -59
  299. package/src/config/schemas/filing.ts +47 -7
  300. package/src/config/schemas/heartbeat.ts +27 -5
  301. package/src/config/schemas/host-browser.ts +47 -1
  302. package/src/config/schemas/inference.ts +1 -1
  303. package/src/config/schemas/memory-lifecycle.ts +14 -2
  304. package/src/config/schemas/services.ts +44 -0
  305. package/src/config/schemas/stt.ts +59 -0
  306. package/src/config/schemas/tts.ts +230 -0
  307. package/src/config/schemas/updates.ts +14 -0
  308. package/src/config/skills.ts +4 -0
  309. package/src/config/types.ts +4 -0
  310. package/src/contacts/contact-store.ts +56 -11
  311. package/src/contacts/contacts-write.ts +38 -1
  312. package/src/context/post-turn-tool-result-truncation.ts +3 -2
  313. package/src/context/tool-result-truncation.ts +2 -1
  314. package/src/context/window-manager.ts +45 -12
  315. package/src/credential-execution/executable-discovery.ts +12 -2
  316. package/src/credential-execution/process-manager.ts +33 -2
  317. package/src/credential-health/credential-health-service.ts +366 -0
  318. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
  319. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
  320. package/src/daemon/__tests__/conversation-tool-setup.test.ts +17 -8
  321. package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
  322. package/src/daemon/config-watcher.ts +99 -5
  323. package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
  324. package/src/daemon/conversation-agent-loop.ts +101 -24
  325. package/src/daemon/conversation-error.ts +11 -0
  326. package/src/daemon/conversation-history.ts +40 -6
  327. package/src/daemon/conversation-launch.ts +220 -0
  328. package/src/daemon/conversation-lifecycle.ts +59 -9
  329. package/src/daemon/conversation-messaging.ts +37 -3
  330. package/src/daemon/conversation-notifiers.ts +5 -0
  331. package/src/daemon/conversation-process.ts +581 -19
  332. package/src/daemon/conversation-queue-manager.ts +24 -0
  333. package/src/daemon/conversation-runtime-assembly.ts +11 -1
  334. package/src/daemon/conversation-slash.ts +36 -0
  335. package/src/daemon/conversation-surfaces.ts +94 -4
  336. package/src/daemon/conversation-tool-setup.ts +25 -0
  337. package/src/daemon/conversation-usage.ts +7 -4
  338. package/src/daemon/conversation.ts +86 -28
  339. package/src/daemon/handlers/config-slack-channel.ts +269 -94
  340. package/src/daemon/handlers/conversations.ts +4 -1
  341. package/src/daemon/handlers/shared.ts +22 -0
  342. package/src/daemon/handlers/skills.ts +321 -77
  343. package/src/daemon/host-browser-proxy.ts +2 -1
  344. package/src/daemon/lifecycle.ts +122 -25
  345. package/src/daemon/message-protocol.ts +6 -0
  346. package/src/daemon/message-types/conversations.ts +34 -1
  347. package/src/daemon/message-types/home.ts +40 -0
  348. package/src/daemon/message-types/meet.ts +143 -0
  349. package/src/daemon/message-types/messages.ts +14 -0
  350. package/src/daemon/message-types/schedules.ts +34 -2
  351. package/src/daemon/message-types/skills.ts +16 -0
  352. package/src/daemon/message-types/surfaces.ts +2 -0
  353. package/src/daemon/server.ts +347 -2
  354. package/src/daemon/shutdown-handlers.ts +32 -4
  355. package/src/daemon/shutdown-registry.ts +40 -0
  356. package/src/daemon/tool-side-effects.ts +9 -0
  357. package/src/email/html-renderer.ts +76 -0
  358. package/src/heartbeat/heartbeat-service.ts +93 -7
  359. package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
  360. package/src/home/__tests__/emit-feed-event.test.ts +169 -0
  361. package/src/home/__tests__/feed-scheduler.test.ts +194 -0
  362. package/src/home/__tests__/feed-types.test.ts +275 -0
  363. package/src/home/__tests__/feed-writer.test.ts +688 -0
  364. package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
  365. package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
  366. package/src/home/__tests__/progress-formula.test.ts +213 -0
  367. package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
  368. package/src/home/__tests__/rollup-producer.test.ts +398 -0
  369. package/src/home/assistant-feed-authoring.ts +124 -0
  370. package/src/home/emit-feed-event.ts +158 -0
  371. package/src/home/feed-scheduler.ts +247 -0
  372. package/src/home/feed-types.ts +181 -0
  373. package/src/home/feed-writer.ts +469 -0
  374. package/src/home/platform-gmail-digest.ts +163 -0
  375. package/src/home/progress-formula.ts +86 -0
  376. package/src/home/relationship-state-writer.ts +824 -0
  377. package/src/home/relationship-state.ts +143 -0
  378. package/src/home/rollup-producer.ts +384 -0
  379. package/src/hooks/runner.ts +7 -0
  380. package/src/inbound/platform-callback-registration.ts +12 -3
  381. package/src/inbound/public-ingress-urls.ts +12 -0
  382. package/src/instrument.ts +1 -1
  383. package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
  384. package/src/ipc/cli-client.ts +151 -0
  385. package/src/ipc/cli-server.ts +234 -0
  386. package/src/ipc/gateway-client.ts +180 -0
  387. package/src/ipc/routes/index.ts +5 -0
  388. package/src/ipc/routes/wake-conversation.ts +19 -0
  389. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
  390. package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
  391. package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
  392. package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
  393. package/src/memory/app-store.ts +1 -1
  394. package/src/memory/attachments-store.ts +70 -0
  395. package/src/memory/auto-analysis-enqueue.ts +127 -0
  396. package/src/memory/auto-analysis-guard.ts +27 -0
  397. package/src/memory/cleanup-schedule-state.ts +37 -0
  398. package/src/memory/conversation-analyze-job.ts +73 -0
  399. package/src/memory/conversation-crud.ts +99 -0
  400. package/src/memory/conversation-disk-view.ts +7 -0
  401. package/src/memory/conversation-group-migration.ts +34 -2
  402. package/src/memory/conversation-queries.ts +6 -5
  403. package/src/memory/db-init.ts +6 -0
  404. package/src/memory/db-maintenance.ts +108 -0
  405. package/src/memory/db.ts +1 -0
  406. package/src/memory/graph/conversation-graph-memory.ts +15 -0
  407. package/src/memory/graph/extraction.test.ts +23 -0
  408. package/src/memory/graph/extraction.ts +8 -0
  409. package/src/memory/graph/retriever.ts +27 -18
  410. package/src/memory/graph/scoring.test.ts +186 -0
  411. package/src/memory/graph/scoring.ts +31 -1
  412. package/src/memory/graph/tools.ts +1 -1
  413. package/src/memory/group-crud.ts +6 -1
  414. package/src/memory/indexer.ts +95 -16
  415. package/src/memory/job-handlers/cleanup.ts +11 -8
  416. package/src/memory/job-handlers/conversation-starters.ts +16 -10
  417. package/src/memory/jobs-store.ts +64 -4
  418. package/src/memory/jobs-worker.ts +22 -9
  419. package/src/memory/llm-usage-store.ts +92 -56
  420. package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
  421. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
  422. package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
  423. package/src/memory/migrations/index.ts +6 -0
  424. package/src/memory/migrations/registry.ts +8 -0
  425. package/src/memory/qdrant-manager.ts +43 -16
  426. package/src/memory/schema/conversations.ts +2 -0
  427. package/src/memory/schema/oauth.ts +3 -0
  428. package/src/memory/usage-buckets.ts +396 -0
  429. package/src/messaging/providers/gmail/client.ts +57 -6
  430. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
  431. package/src/messaging/providers/slack/adapter.ts +143 -38
  432. package/src/messaging/providers/slack/client.ts +16 -0
  433. package/src/messaging/providers/slack/types.ts +4 -0
  434. package/src/notifications/decision-engine.ts +3 -3
  435. package/src/notifications/signal.ts +5 -0
  436. package/src/oauth/__tests__/identity-verifier.test.ts +1 -0
  437. package/src/oauth/byo-connection.test.ts +18 -1
  438. package/src/oauth/byo-connection.ts +3 -1
  439. package/src/oauth/connect-orchestrator.ts +2 -0
  440. package/src/oauth/connection-resolver.ts +6 -2
  441. package/src/oauth/connection.ts +2 -0
  442. package/src/oauth/oauth-store.ts +9 -0
  443. package/src/oauth/platform-connection.test.ts +98 -0
  444. package/src/oauth/platform-connection.ts +52 -31
  445. package/src/oauth/seed-providers.ts +7 -0
  446. package/src/permissions/checker.ts +16 -6
  447. package/src/permissions/defaults.ts +49 -1
  448. package/src/permissions/trust-store.ts +3 -3
  449. package/src/permissions/workspace-policy.ts +3 -0
  450. package/src/platform/client.test.ts +10 -0
  451. package/src/platform/sync-identity.ts +129 -0
  452. package/src/prompts/persona-resolver.ts +126 -2
  453. package/src/prompts/system-prompt.ts +59 -18
  454. package/src/prompts/templates/BOOTSTRAP.md +5 -5
  455. package/src/prompts/templates/SOUL.md +3 -1
  456. package/src/prompts/templates/UPDATES.md +12 -0
  457. package/src/prompts/templates/channels/slack.md +20 -0
  458. package/src/prompts/update-bulletin-format.ts +26 -9
  459. package/src/prompts/update-bulletin.ts +34 -23
  460. package/src/prompts/user-reference.ts +20 -17
  461. package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
  462. package/src/providers/anthropic/client.ts +157 -61
  463. package/src/providers/fireworks/client.ts +2 -2
  464. package/src/providers/gemini/client.ts +9 -1
  465. package/src/providers/model-catalog.ts +6 -0
  466. package/src/providers/model-intents.ts +4 -4
  467. package/src/providers/ollama/client.ts +2 -2
  468. package/src/providers/openai/chat-completions-provider.ts +474 -0
  469. package/src/providers/openai/client.ts +25 -440
  470. package/src/providers/openai/responses-provider.ts +502 -0
  471. package/src/providers/openrouter/client.ts +101 -4
  472. package/src/providers/provider-secret-catalog.ts +139 -0
  473. package/src/providers/registry.ts +2 -2
  474. package/src/providers/retry.ts +14 -3
  475. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
  476. package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
  477. package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
  478. package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
  479. package/src/providers/speech-to-text/deepgram.test.ts +332 -0
  480. package/src/providers/speech-to-text/deepgram.ts +115 -0
  481. package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
  482. package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
  483. package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
  484. package/src/providers/speech-to-text/google-gemini.ts +101 -0
  485. package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
  486. package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
  487. package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
  488. package/src/providers/speech-to-text/openai-whisper.ts +63 -33
  489. package/src/providers/speech-to-text/provider-catalog.ts +306 -0
  490. package/src/providers/speech-to-text/resolve.ts +386 -6
  491. package/src/providers/types.ts +9 -0
  492. package/src/runtime/AGENTS.md +43 -1
  493. package/src/runtime/__tests__/agent-wake.test.ts +831 -0
  494. package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
  495. package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
  496. package/src/runtime/agent-wake.ts +512 -0
  497. package/src/runtime/auth/__tests__/route-policy.test.ts +40 -0
  498. package/src/runtime/auth/route-policy.ts +30 -5
  499. package/src/runtime/auth/token-service.ts +56 -1
  500. package/src/runtime/btw-sidechain.ts +2 -0
  501. package/src/runtime/capability-tokens.ts +10 -10
  502. package/src/runtime/channel-invite-transport.ts +1 -1
  503. package/src/runtime/channel-invite-transports/email.ts +14 -6
  504. package/src/runtime/channel-readiness-service.ts +12 -22
  505. package/src/runtime/chrome-extension-registry.ts +38 -2
  506. package/src/runtime/http-server.ts +395 -10
  507. package/src/runtime/http-types.ts +6 -2
  508. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +36 -0
  509. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
  510. package/src/runtime/migrations/migration-transport.ts +1 -0
  511. package/src/runtime/migrations/migration-wizard.ts +1 -0
  512. package/src/runtime/migrations/vbundle-import-analyzer.ts +77 -1
  513. package/src/runtime/migrations/vbundle-importer.ts +34 -0
  514. package/src/runtime/pending-interactions.ts +0 -11
  515. package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
  516. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
  517. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
  518. package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
  519. package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
  520. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
  521. package/src/runtime/routes/app-management-routes.ts +12 -18
  522. package/src/runtime/routes/attachment-routes.test.ts +9 -3
  523. package/src/runtime/routes/attachment-routes.ts +216 -17
  524. package/src/runtime/routes/backup-routes.ts +519 -0
  525. package/src/runtime/routes/browser-extension-pair-routes.ts +82 -23
  526. package/src/runtime/routes/btw-routes.ts +8 -6
  527. package/src/runtime/routes/contact-routes.test.ts +298 -0
  528. package/src/runtime/routes/contact-routes.ts +132 -5
  529. package/src/runtime/routes/conversation-analysis-routes.ts +22 -142
  530. package/src/runtime/routes/conversation-management-routes.ts +115 -0
  531. package/src/runtime/routes/conversation-routes.ts +367 -146
  532. package/src/runtime/routes/filing-routes.ts +93 -0
  533. package/src/runtime/routes/home-feed-routes.ts +334 -0
  534. package/src/runtime/routes/home-state-routes.ts +138 -0
  535. package/src/runtime/routes/host-browser-routes.ts +3 -14
  536. package/src/runtime/routes/identity-intro-cache.ts +7 -3
  537. package/src/runtime/routes/identity-routes.ts +3 -17
  538. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
  539. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
  540. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
  541. package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
  542. package/src/runtime/routes/integrations/slack/channel.ts +11 -3
  543. package/src/runtime/routes/integrations/slack/share.ts +45 -7
  544. package/src/runtime/routes/llm-context-normalization.ts +303 -0
  545. package/src/runtime/routes/memory-item-routes.test.ts +3 -2
  546. package/src/runtime/routes/migration-routes.ts +40 -5
  547. package/src/runtime/routes/settings-routes.ts +22 -5
  548. package/src/runtime/routes/skills-routes.ts +76 -7
  549. package/src/runtime/routes/stt-routes.ts +233 -0
  550. package/src/runtime/routes/surface-action-routes.ts +41 -2
  551. package/src/runtime/routes/tts-routes.ts +108 -24
  552. package/src/runtime/routes/usage-routes.ts +30 -2
  553. package/src/runtime/routes/user-route-dispatcher.ts +50 -5
  554. package/src/runtime/routes/user-routes.ts +13 -1
  555. package/src/runtime/routes/work-items-routes.ts +8 -1
  556. package/src/runtime/runtime-mode.ts +33 -0
  557. package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
  558. package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
  559. package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
  560. package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
  561. package/src/runtime/services/analyze-conversation.ts +344 -0
  562. package/src/runtime/services/analyze-deps-singleton.ts +32 -0
  563. package/src/runtime/services/auto-analysis-prompt.ts +55 -0
  564. package/src/runtime/skill-route-registry.ts +49 -0
  565. package/src/runtime/slack-block-formatting.ts +437 -10
  566. package/src/schedule/scheduler.ts +50 -0
  567. package/src/security/oauth2.ts +26 -4
  568. package/src/security/secure-keys.ts +25 -2
  569. package/src/security/token-manager.ts +8 -0
  570. package/src/sequence/engine.ts +23 -0
  571. package/src/sequence/types.ts +1 -1
  572. package/src/skills/catalog-files.ts +64 -2
  573. package/src/skills/category-inference.ts +122 -0
  574. package/src/skills/clawhub-files.ts +213 -0
  575. package/src/skills/clawhub.ts +84 -23
  576. package/src/skills/skill-file-provider.ts +40 -0
  577. package/src/skills/skillssh-files.ts +395 -0
  578. package/src/skills/skillssh-registry.ts +4 -4
  579. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
  580. package/src/stt/__tests__/types.test.ts +89 -0
  581. package/src/stt/daemon-batch-transcriber.ts +195 -0
  582. package/src/stt/stt-stream-session.ts +499 -0
  583. package/src/stt/types.ts +330 -0
  584. package/src/stt/wav-encoder.test.ts +373 -0
  585. package/src/stt/wav-encoder.ts +175 -0
  586. package/src/subagent/manager.ts +38 -14
  587. package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
  588. package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
  589. package/src/tools/browser/browser-execution.ts +1163 -23
  590. package/src/tools/browser/browser-manager.ts +45 -0
  591. package/src/tools/browser/browser-mode-constants.ts +12 -0
  592. package/src/tools/browser/browser-mode.ts +92 -0
  593. package/src/tools/browser/browser-status-constants.ts +33 -0
  594. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +393 -0
  595. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +29 -0
  596. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1648 -32
  597. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +264 -0
  598. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +183 -17
  599. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +254 -21
  600. package/src/tools/browser/cdp-client/errors.ts +15 -0
  601. package/src/tools/browser/cdp-client/extension-cdp-client.ts +39 -16
  602. package/src/tools/browser/cdp-client/factory.ts +797 -87
  603. package/src/tools/browser/cdp-client/index.ts +16 -2
  604. package/src/tools/browser/cdp-client/types.ts +68 -0
  605. package/src/tools/credentials/vault.ts +35 -6
  606. package/src/tools/network/web-fetch.ts +5 -2
  607. package/src/tools/network/web-search.ts +5 -2
  608. package/src/tools/shared/shell-output.ts +3 -1
  609. package/src/tools/side-effects.ts +2 -0
  610. package/src/tools/skills/sandbox-runner.ts +3 -2
  611. package/src/tools/terminal/safe-env.ts +10 -2
  612. package/src/tools/terminal/shell.ts +15 -4
  613. package/src/tools/tool-manifest.ts +21 -0
  614. package/src/tools/types.ts +17 -0
  615. package/src/tools/ui-surface/definitions.ts +6 -1
  616. package/src/tts/__tests__/provider-adapters.test.ts +834 -0
  617. package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
  618. package/src/tts/__tests__/provider-catalog.test.ts +183 -0
  619. package/src/tts/__tests__/provider-registry.test.ts +90 -0
  620. package/src/tts/provider-catalog.ts +201 -0
  621. package/src/tts/provider-registry.ts +73 -0
  622. package/src/tts/providers/deepgram-provider.ts +219 -0
  623. package/src/tts/providers/elevenlabs-provider.ts +211 -0
  624. package/src/tts/providers/fish-audio-provider.ts +183 -0
  625. package/src/tts/providers/index.ts +42 -0
  626. package/src/tts/providers/register-builtins.ts +130 -0
  627. package/src/tts/synthesize-text.ts +110 -0
  628. package/src/tts/tts-config-resolver.ts +78 -0
  629. package/src/tts/types.ts +153 -0
  630. package/src/types/onboarding-context.ts +7 -0
  631. package/src/util/abort-reasons.ts +58 -0
  632. package/src/util/device-id.ts +32 -16
  633. package/src/util/errors.ts +9 -1
  634. package/src/util/platform.ts +54 -10
  635. package/src/util/pricing.ts +66 -3
  636. package/src/util/spawn.ts +1 -1
  637. package/src/util/truncate.ts +4 -2
  638. package/src/util/unicode.ts +201 -0
  639. package/src/version.ts +19 -24
  640. package/src/watcher/engine.ts +23 -0
  641. package/src/watcher/watcher-store.ts +31 -0
  642. package/src/workspace/migrations/003-seed-device-id.ts +9 -3
  643. package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
  644. package/src/workspace/migrations/029-seed-pkb.ts +1 -1
  645. package/src/workspace/migrations/031-drop-user-md.ts +317 -0
  646. package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
  647. package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
  648. package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
  649. package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
  650. package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
  651. package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
  652. package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
  653. package/src/workspace/migrations/registry.ts +16 -0
  654. package/src/workspace/top-level-renderer.ts +13 -1
  655. package/src/workspace/turn-commit.ts +31 -0
  656. package/src/__tests__/email-cli.test.ts +0 -297
  657. package/src/__tests__/email-service-config-fallback.test.ts +0 -102
  658. package/src/cli/commands/browser-relay.ts +0 -466
  659. package/src/email/guardrails.ts +0 -221
  660. package/src/email/provider.ts +0 -117
  661. package/src/email/providers/agentmail.ts +0 -361
  662. package/src/email/providers/index.ts +0 -65
  663. package/src/email/service.ts +0 -384
  664. package/src/email/types.ts +0 -126
  665. package/src/prompts/templates/USER.md +0 -13
  666. package/src/providers/speech-to-text/types.ts +0 -17
  667. package/src/runtime/routes/browser-cdp-routes.ts +0 -229
@@ -0,0 +1,93 @@
1
+ /**
2
+ * HTTP route handlers for filing management.
3
+ */
4
+
5
+ import { z } from "zod";
6
+
7
+ import { getConfig } from "../../config/loader.js";
8
+ import type { FilingService } from "../../filing/filing-service.js";
9
+ import { getLogger } from "../../util/logger.js";
10
+ import { httpError } from "../http-errors.js";
11
+ import type { RouteDefinition } from "../http-router.js";
12
+
13
+ const log = getLogger("filing-routes");
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Handlers
17
+ // ---------------------------------------------------------------------------
18
+
19
+ function handleGetConfig(filingService?: FilingService): Response {
20
+ const config = getConfig().filing;
21
+ return Response.json({
22
+ enabled: config.enabled,
23
+ intervalMs: config.intervalMs,
24
+ activeHoursStart: config.activeHoursStart ?? null,
25
+ activeHoursEnd: config.activeHoursEnd ?? null,
26
+ nextRunAt: filingService?.nextRunAt ?? null,
27
+ lastRunAt: filingService?.lastRunAt ?? null,
28
+ success: true,
29
+ });
30
+ }
31
+
32
+ async function handleRunNow(
33
+ filingService?: FilingService,
34
+ ): Promise<Response> {
35
+ if (!filingService) {
36
+ return httpError(
37
+ "SERVICE_UNAVAILABLE",
38
+ "Filing service not available",
39
+ 503,
40
+ );
41
+ }
42
+
43
+ try {
44
+ const ran = await filingService.runOnce({ force: true });
45
+ return Response.json({ success: true, ran });
46
+ } catch (err) {
47
+ const message = err instanceof Error ? err.message : String(err);
48
+ log.error({ err }, "Filing run-now failed");
49
+ return Response.json({ success: false, ran: false, error: message });
50
+ }
51
+ }
52
+
53
+ // ---------------------------------------------------------------------------
54
+ // Route definitions
55
+ // ---------------------------------------------------------------------------
56
+
57
+ export function filingRouteDefinitions(deps: {
58
+ getFilingService?: () => FilingService | undefined;
59
+ }): RouteDefinition[] {
60
+ return [
61
+ {
62
+ endpoint: "filing/config",
63
+ method: "GET",
64
+ policyKey: "filing",
65
+ summary: "Get filing config",
66
+ description: "Return the current filing schedule configuration.",
67
+ tags: ["filing"],
68
+ responseBody: z.object({
69
+ enabled: z.boolean(),
70
+ intervalMs: z.number(),
71
+ activeHoursStart: z.number().nullable(),
72
+ activeHoursEnd: z.number().nullable(),
73
+ nextRunAt: z.number().nullable(),
74
+ lastRunAt: z.number().nullable(),
75
+ success: z.boolean(),
76
+ }),
77
+ handler: () => handleGetConfig(deps.getFilingService?.()),
78
+ },
79
+ {
80
+ endpoint: "filing/run-now",
81
+ method: "POST",
82
+ policyKey: "filing",
83
+ summary: "Run filing now",
84
+ description: "Trigger an immediate filing run.",
85
+ tags: ["filing"],
86
+ responseBody: z.object({
87
+ success: z.boolean(),
88
+ ran: z.boolean().describe("Whether the filing actually ran"),
89
+ }),
90
+ handler: () => handleRunNow(deps.getFilingService?.()),
91
+ },
92
+ ];
93
+ }
@@ -0,0 +1,334 @@
1
+ /**
2
+ * Home activity feed HTTP routes.
3
+ *
4
+ * Exposes the three endpoints the macOS Home page uses to render and
5
+ * interact with the activity feed:
6
+ *
7
+ * - `GET /v1/home/feed` — read + filter
8
+ * - `PATCH /v1/home/feed/:id` — mark seen / acted_on
9
+ * - `POST /v1/home/feed/:id/actions/:actionId` — trigger an action
10
+ *
11
+ * The routes are always available — the `home-feed` feature flag gates
12
+ * the client rendering path only, so the daemon surface can ship ahead
13
+ * of the rollout and client versions can adopt independently of
14
+ * feature-flag timing.
15
+ *
16
+ * All persistence goes through `readHomeFeed` / `patchFeedItemStatus`
17
+ * in `home/feed-writer.ts`; this module does not touch the on-disk
18
+ * file directly. The writer already applies the TTL filter on read
19
+ * and owns all SSE publication, so the route handlers stay pure
20
+ * shape + validation + banner computation.
21
+ */
22
+
23
+ import { z } from "zod";
24
+
25
+ import {
26
+ type FeedItem,
27
+ feedItemSchema,
28
+ type FeedItemStatus,
29
+ } from "../../home/feed-types.js";
30
+ import { patchFeedItemStatus, readHomeFeed } from "../../home/feed-writer.js";
31
+ import {
32
+ addMessage,
33
+ createConversation,
34
+ } from "../../memory/conversation-crud.js";
35
+ import { getLogger } from "../../util/logger.js";
36
+ import { httpError } from "../http-errors.js";
37
+ import type { RouteDefinition } from "../http-router.js";
38
+
39
+ const log = getLogger("home-feed-routes");
40
+
41
+ // ---------------------------------------------------------------------------
42
+ // Response / request schemas
43
+ // ---------------------------------------------------------------------------
44
+
45
+ const contextBannerSchema = z.object({
46
+ greeting: z.string(),
47
+ timeAwayLabel: z.string(),
48
+ newCount: z.number().int().min(0),
49
+ });
50
+
51
+ const getHomeFeedResponseSchema = z.object({
52
+ items: z.array(feedItemSchema),
53
+ updatedAt: z.string(),
54
+ contextBanner: contextBannerSchema,
55
+ });
56
+
57
+ const patchFeedItemRequestSchema = z.object({
58
+ status: z.enum(["new", "seen", "acted_on"]),
59
+ });
60
+
61
+ // ---------------------------------------------------------------------------
62
+ // Pure helpers (exported for direct testing — see home-feed-routes.test.ts)
63
+ // ---------------------------------------------------------------------------
64
+
65
+ /**
66
+ * Map the server's wall-clock hour to a human greeting. Pure function;
67
+ * no LLM. The buckets match the plan:
68
+ * - 05:00–11:59 → "Good morning"
69
+ * - 12:00–16:59 → "Good afternoon"
70
+ * - 17:00–21:59 → "Good evening"
71
+ * - otherwise → "Welcome back"
72
+ */
73
+ export function computeGreeting(now: Date): string {
74
+ const hour = now.getHours();
75
+ if (hour >= 5 && hour < 12) return "Good morning";
76
+ if (hour >= 12 && hour < 17) return "Good afternoon";
77
+ if (hour >= 17 && hour < 22) return "Good evening";
78
+ return "Welcome back";
79
+ }
80
+
81
+ /**
82
+ * Format a `timeAwaySeconds` value as a coarse relative-time label.
83
+ * Kept in-file since no other caller needs it yet; extract to a shared
84
+ * util module when a second caller appears.
85
+ */
86
+ export function formatRelativeTime(seconds: number): string {
87
+ if (!Number.isFinite(seconds) || seconds < 60) return "just now";
88
+ if (seconds < 3600) {
89
+ const mins = Math.floor(seconds / 60);
90
+ return `${mins} minute${mins === 1 ? "" : "s"} ago`;
91
+ }
92
+ if (seconds < 86400) {
93
+ const hours = Math.floor(seconds / 3600);
94
+ return `${hours} hour${hours === 1 ? "" : "s"} ago`;
95
+ }
96
+ if (seconds < 172800) return "yesterday";
97
+ const days = Math.floor(seconds / 86400);
98
+ return `${days} day${days === 1 ? "" : "s"} ago`;
99
+ }
100
+
101
+ /**
102
+ * Bucket `timeAwaySeconds` into coarse ranges used only for debug
103
+ * logging cardinality control. Not exposed to clients.
104
+ */
105
+ function timeAwayBucket(seconds: number): string {
106
+ if (seconds < 1800) return "<1800";
107
+ if (seconds < 14400) return "1800-14400";
108
+ if (seconds < 43200) return "14400-43200";
109
+ if (seconds < 86400) return "43200-86400";
110
+ return ">=86400";
111
+ }
112
+
113
+ // ---------------------------------------------------------------------------
114
+ // Handlers
115
+ // ---------------------------------------------------------------------------
116
+
117
+ /**
118
+ * `GET /v1/home/feed`.
119
+ *
120
+ * Required query param: `timeAwaySeconds` (non-negative integer). The
121
+ * handler reads the feed via `readHomeFeed()` (which has already
122
+ * applied TTL filtering), drops items whose `minTimeAway` exceeds the
123
+ * client-reported time away, then computes the context banner.
124
+ */
125
+ export async function handleGetHomeFeed(req: Request): Promise<Response> {
126
+ const url = new URL(req.url);
127
+ const raw = url.searchParams.get("timeAwaySeconds");
128
+ if (raw === null) {
129
+ return httpError(
130
+ "BAD_REQUEST",
131
+ "Missing required query parameter: timeAwaySeconds",
132
+ 400,
133
+ );
134
+ }
135
+ const parsed = Number(raw);
136
+ if (!Number.isInteger(parsed) || parsed < 0) {
137
+ return httpError(
138
+ "BAD_REQUEST",
139
+ "timeAwaySeconds must be a non-negative integer",
140
+ 400,
141
+ );
142
+ }
143
+ const timeAwaySeconds = parsed;
144
+
145
+ const feed = readHomeFeed();
146
+ const filtered = feed.items.filter((item) => {
147
+ if (item.minTimeAway === undefined) return true;
148
+ return item.minTimeAway <= timeAwaySeconds;
149
+ });
150
+
151
+ const now = new Date();
152
+ const contextBanner = {
153
+ greeting: computeGreeting(now),
154
+ timeAwayLabel: formatRelativeTime(timeAwaySeconds),
155
+ newCount: filtered.filter((i) => i.status === "new").length,
156
+ };
157
+
158
+ log.debug(
159
+ {
160
+ timeAwayBucket: timeAwayBucket(timeAwaySeconds),
161
+ totalItems: feed.items.length,
162
+ filteredItems: filtered.length,
163
+ newCount: contextBanner.newCount,
164
+ },
165
+ "GET /v1/home/feed",
166
+ );
167
+
168
+ return Response.json({
169
+ items: filtered,
170
+ updatedAt: feed.updatedAt,
171
+ contextBanner,
172
+ });
173
+ }
174
+
175
+ /**
176
+ * `PATCH /v1/home/feed/:id`.
177
+ *
178
+ * Body: `{ status: "new" | "seen" | "acted_on" }`. Returns the updated
179
+ * `FeedItem` on success.
180
+ *
181
+ * Disambiguates the writer's `null` return by looking up the item via
182
+ * `readHomeFeed()` first — if the lookup finds the item and the patch
183
+ * still returns null, it's a write failure (500), not a missing id
184
+ * (404).
185
+ */
186
+ export async function handlePatchFeedItem(
187
+ req: Request,
188
+ itemId: string,
189
+ ): Promise<Response> {
190
+ let body: unknown;
191
+ try {
192
+ body = await req.json();
193
+ } catch {
194
+ return httpError("BAD_REQUEST", "Invalid JSON body", 400);
195
+ }
196
+
197
+ const parsed = patchFeedItemRequestSchema.safeParse(body);
198
+ if (!parsed.success) {
199
+ return httpError("BAD_REQUEST", "Invalid request body", 400, {
200
+ issues: parsed.error.issues,
201
+ });
202
+ }
203
+ const status: FeedItemStatus = parsed.data.status;
204
+
205
+ // Pre-check for existence so we can distinguish "unknown id" (404)
206
+ // from "found, but write failed" (500). The writer applies the patch
207
+ // inside its coalescing queue against the same on-disk state we just
208
+ // read, so a race where the item disappears between the check and
209
+ // the write resolves cleanly as a 500 (write failed / no such item).
210
+ const currentFeed = readHomeFeed();
211
+ const existing = currentFeed.items.find((i) => i.id === itemId);
212
+ if (!existing) {
213
+ return httpError("NOT_FOUND", `Feed item not found: ${itemId}`, 404);
214
+ }
215
+
216
+ const updated = await patchFeedItemStatus(itemId, status);
217
+ if (!updated) {
218
+ log.warn(
219
+ { itemId, status },
220
+ "patchFeedItemStatus returned null despite pre-check — treating as write failure",
221
+ );
222
+ return httpError(
223
+ "INTERNAL_ERROR",
224
+ "Failed to persist feed item status",
225
+ 500,
226
+ );
227
+ }
228
+
229
+ return Response.json(updated);
230
+ }
231
+
232
+ /**
233
+ * `POST /v1/home/feed/:id/actions/:actionId`.
234
+ *
235
+ * Looks up the item + action, creates a new conversation pre-seeded
236
+ * with the action's `prompt` as the first user message, and returns
237
+ * `{ conversationId }`. Any lookup failure → 404; conversation create
238
+ * error → 500.
239
+ */
240
+ export async function handlePostFeedAction(
241
+ _req: Request,
242
+ itemId: string,
243
+ actionId: string,
244
+ ): Promise<Response> {
245
+ const feed = readHomeFeed();
246
+ const item: FeedItem | undefined = feed.items.find((i) => i.id === itemId);
247
+ if (!item) {
248
+ return httpError("NOT_FOUND", `Feed item not found: ${itemId}`, 404);
249
+ }
250
+
251
+ const action = item.actions?.find((a) => a.id === actionId);
252
+ if (!action) {
253
+ return httpError(
254
+ "NOT_FOUND",
255
+ `Action not found on item ${itemId}: ${actionId}`,
256
+ 404,
257
+ );
258
+ }
259
+
260
+ try {
261
+ const conversation = createConversation({
262
+ title: action.label,
263
+ source: "home-feed",
264
+ });
265
+ await addMessage(
266
+ conversation.id,
267
+ "user",
268
+ JSON.stringify([{ type: "text", text: action.prompt }]),
269
+ );
270
+ return Response.json({ conversationId: conversation.id });
271
+ } catch (err) {
272
+ log.warn(
273
+ { err, itemId, actionId },
274
+ "Failed to create conversation from feed action",
275
+ );
276
+ return httpError(
277
+ "INTERNAL_ERROR",
278
+ "Failed to create conversation for feed action",
279
+ 500,
280
+ );
281
+ }
282
+ }
283
+
284
+ // ---------------------------------------------------------------------------
285
+ // Route definitions
286
+ // ---------------------------------------------------------------------------
287
+
288
+ export function homeFeedRouteDefinitions(): RouteDefinition[] {
289
+ return [
290
+ {
291
+ endpoint: "home/feed",
292
+ method: "GET",
293
+ handler: ({ req }) => handleGetHomeFeed(req),
294
+ summary: "Get home activity feed",
295
+ description:
296
+ "Return the current Home activity feed with TTL + time-away filtering applied. Also returns a context banner (greeting, relative time-away label, new-item count).",
297
+ tags: ["home"],
298
+ queryParams: [
299
+ {
300
+ name: "timeAwaySeconds",
301
+ type: "integer",
302
+ required: true,
303
+ description:
304
+ "Seconds since the user was last active in the client. Used to filter items with a `minTimeAway` gate and to compute the context-banner relative-time label.",
305
+ },
306
+ ],
307
+ responseBody: getHomeFeedResponseSchema,
308
+ },
309
+ {
310
+ endpoint: "home/feed/:id",
311
+ method: "PATCH",
312
+ handler: ({ req, params }) => handlePatchFeedItem(req, params.id),
313
+ summary: "Patch home feed item status",
314
+ description:
315
+ "Update the `status` field of a single feed item (e.g. mark it seen or acted_on). Returns the updated item on success, 404 if the item does not exist, 500 if the underlying write fails.",
316
+ tags: ["home"],
317
+ requestBody: patchFeedItemRequestSchema,
318
+ responseBody: feedItemSchema,
319
+ },
320
+ {
321
+ endpoint: "home/feed/:id/actions/:actionId",
322
+ method: "POST",
323
+ handler: ({ req, params }) =>
324
+ handlePostFeedAction(req, params.id, params.actionId),
325
+ summary: "Trigger home feed action",
326
+ description:
327
+ "Create a new conversation pre-seeded with the action's prompt as the first user message. Returns the new `conversationId`.",
328
+ tags: ["home"],
329
+ responseBody: z.object({
330
+ conversationId: z.string(),
331
+ }),
332
+ },
333
+ ];
334
+ }
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Home state HTTP routes.
3
+ *
4
+ * Exposes `GET /v1/home/state` so macOS (and other) clients can fetch
5
+ * the current `RelationshipState` snapshot. The normal path reads
6
+ * the JSON file produced by `writeRelationshipState()`; if that file
7
+ * is missing — e.g. on a fresh install before the writer has landed
8
+ * its first snapshot — the handler falls back to computing the
9
+ * state on-demand so the client never sees a 404 and the UI can
10
+ * always render.
11
+ */
12
+
13
+ import { existsSync, readFileSync } from "node:fs";
14
+
15
+ import { z } from "zod";
16
+
17
+ import {
18
+ computeRelationshipState,
19
+ getRelationshipStatePath,
20
+ } from "../../home/relationship-state-writer.js";
21
+ import { getLogger } from "../../util/logger.js";
22
+ import { httpError } from "../http-errors.js";
23
+ import type { RouteDefinition } from "../http-router.js";
24
+
25
+ const log = getLogger("home-state-routes");
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Response schema (shared with the OpenAPI generator and runtime validation)
29
+ // ---------------------------------------------------------------------------
30
+
31
+ const factSchema = z.object({
32
+ id: z.string(),
33
+ category: z.enum(["voice", "world", "priorities"]),
34
+ text: z.string(),
35
+ confidence: z.enum(["strong", "uncertain"]),
36
+ source: z.enum(["onboarding", "inferred"]),
37
+ });
38
+
39
+ const capabilitySchema = z.object({
40
+ id: z.string(),
41
+ name: z.string(),
42
+ description: z.string(),
43
+ tier: z.enum(["unlocked", "next-up", "earned"]),
44
+ gate: z.string(),
45
+ unlockHint: z.string().optional(),
46
+ ctaLabel: z.string().optional(),
47
+ });
48
+
49
+ const relationshipStateSchema = z.object({
50
+ version: z.literal(1),
51
+ assistantId: z.string(),
52
+ tier: z.union([z.literal(1), z.literal(2), z.literal(3), z.literal(4)]),
53
+ progressPercent: z.number(),
54
+ facts: z.array(factSchema),
55
+ capabilities: z.array(capabilitySchema),
56
+ conversationCount: z.number(),
57
+ hatchedDate: z.string(),
58
+ assistantName: z.string(),
59
+ userName: z.string().optional(),
60
+ updatedAt: z.string(),
61
+ });
62
+
63
+ /**
64
+ * Handle `GET /v1/home/state`.
65
+ *
66
+ * Always computes a fresh snapshot so the response reflects the
67
+ * latest OAuth connection state, conversation count, and extracted
68
+ * facts — not just whatever the conversation-complete writer last
69
+ * persisted. This avoids serving stale capability tiers when the
70
+ * user connects an integration between turns, or when a delete/wipe
71
+ * flow mutates conversation count outside the turn-boundary writer.
72
+ *
73
+ * The persisted `relationship-state.json` remains useful as:
74
+ * - A seed for the existing-user backfill on daemon startup.
75
+ * - A fallback when live compute fails (e.g. DB not yet ready at
76
+ * cold start, or a transient filesystem error).
77
+ *
78
+ * The route does NOT write to disk or emit SSE on read — writes are
79
+ * still owned exclusively by the writer so turn-boundary SSE events
80
+ * remain tied to real state transitions rather than GET traffic.
81
+ */
82
+ export async function handleGetHomeState(): Promise<Response> {
83
+ try {
84
+ const state = await computeRelationshipState();
85
+ return Response.json(state);
86
+ } catch (computeErr) {
87
+ log.warn(
88
+ { err: computeErr },
89
+ "Live compute failed; falling back to persisted relationship-state.json",
90
+ );
91
+ }
92
+
93
+ const path = getRelationshipStatePath();
94
+ if (existsSync(path)) {
95
+ try {
96
+ const raw = readFileSync(path, "utf-8");
97
+ const parsed: unknown = JSON.parse(raw);
98
+ const validated = relationshipStateSchema.safeParse(parsed);
99
+ if (validated.success) {
100
+ return Response.json(validated.data);
101
+ }
102
+ log.warn(
103
+ { path, issues: validated.error.issues },
104
+ "Persisted relationship-state.json failed schema validation",
105
+ );
106
+ } catch (err) {
107
+ log.warn(
108
+ { err, path },
109
+ "Failed to read persisted relationship-state.json as fallback",
110
+ );
111
+ }
112
+ }
113
+
114
+ return httpError(
115
+ "INTERNAL_ERROR",
116
+ "Failed to compute relationship state",
117
+ 500,
118
+ );
119
+ }
120
+
121
+ // ---------------------------------------------------------------------------
122
+ // Route definitions
123
+ // ---------------------------------------------------------------------------
124
+
125
+ export function homeStateRouteDefinitions(): RouteDefinition[] {
126
+ return [
127
+ {
128
+ endpoint: "home/state",
129
+ method: "GET",
130
+ handler: () => handleGetHomeState(),
131
+ summary: "Get relationship state",
132
+ description:
133
+ "Return the current `RelationshipState` snapshot. Reads the persisted `relationship-state.json` when present; falls back to an on-demand compute so fresh installs never see a 404.",
134
+ tags: ["home"],
135
+ responseBody: relationshipStateSchema,
136
+ },
137
+ ];
138
+ }
@@ -21,8 +21,8 @@ import * as pendingInteractions from "../pending-interactions.js";
21
21
  * the HTTP endpoint and the WS relay path so they share the same validation
22
22
  * and resolution semantics.
23
23
  *
24
- * Success → the pending interaction was consumed and the conversation (or
25
- * CLI shim callback) was notified.
24
+ * Success → the pending interaction was consumed and the conversation was
25
+ * notified.
26
26
  *
27
27
  * Error variants mirror the HTTP status codes the `/v1/host-browser-result`
28
28
  * endpoint returns, so the caller can log/translate them consistently.
@@ -40,7 +40,7 @@ export type HostBrowserResultResolution =
40
40
  * Shared resolver used by both the HTTP route handler and the WS
41
41
  * `host_browser_result` frame handler. Looks up the pending interaction
42
42
  * by requestId, validates its kind, and forwards the response to the
43
- * owning conversation (or CLI shim callback).
43
+ * owning conversation.
44
44
  *
45
45
  * This function does NOT perform auth — callers are expected to have
46
46
  * already authenticated the caller (the HTTP route uses
@@ -90,17 +90,6 @@ export function resolveHostBrowserResultByRequestId(frame: {
90
90
  const normalizedContent = typeof content === "string" ? content : "";
91
91
  const normalizedIsError = typeof isError === "boolean" ? isError : false;
92
92
 
93
- // CLI shim path: pending interactions registered by /v1/browser-cdp carry
94
- // a directBrowserResolve callback and are not bound to a Conversation.
95
- // Resolve them in place without touching the conversation object.
96
- if (interaction.directBrowserResolve) {
97
- interaction.directBrowserResolve({
98
- content: normalizedContent,
99
- isError: normalizedIsError,
100
- });
101
- return { ok: true };
102
- }
103
-
104
93
  // The host_browser kind always has a conversation attached at register time
105
94
  // (HostBrowserProxy.request wires it through), so this guard exists so a
106
95
  // future refactor of pending-interactions can change the type without
@@ -4,7 +4,8 @@
4
4
  * The intro (a short identity tagline) is generated via the
5
5
  * /v1/btw endpoint and displayed on the Identity panel. To avoid redundant LLM
6
6
  * calls, we cache the result for 4 hours with content-hash-based invalidation:
7
- * when USER.md, IDENTITY.md, or SOUL.md change, the cache is busted.
7
+ * when IDENTITY.md, SOUL.md, or the guardian's per-user persona file change,
8
+ * the cache is busted.
8
9
  *
9
10
  * Storage uses the existing `memory_checkpoints` table (simple key-value store).
10
11
  */
@@ -16,6 +17,7 @@ import {
16
17
  getMemoryCheckpoint,
17
18
  setMemoryCheckpoint,
18
19
  } from "../../memory/checkpoints.js";
20
+ import { resolveGuardianPersona } from "../../prompts/persona-resolver.js";
19
21
  import { getWorkspacePromptPath } from "../../util/platform.js";
20
22
 
21
23
  // ---------------------------------------------------------------------------
@@ -29,7 +31,7 @@ const CHECKPOINT_KEY_HASH = "identity:intro:content_hash";
29
31
  const CHECKPOINT_KEY_TIMESTAMP = "identity:intro:cached_at";
30
32
 
31
33
  /** Workspace files whose content influences the identity intro. */
32
- const IDENTITY_FILES = ["USER.md", "IDENTITY.md", "SOUL.md"] as const;
34
+ const IDENTITY_FILES = ["IDENTITY.md", "SOUL.md"] as const;
33
35
 
34
36
  // ---------------------------------------------------------------------------
35
37
  // Helpers
@@ -48,7 +50,9 @@ function readWorkspaceFile(name: string): string {
48
50
 
49
51
  /** Compute a SHA-256 hex hash of the concatenated identity file contents. */
50
52
  export function computeIdentityContentHash(): string {
51
- const combined = IDENTITY_FILES.map(readWorkspaceFile).join("\n---\n");
53
+ const staticFiles = IDENTITY_FILES.map(readWorkspaceFile).join("\n---\n");
54
+ const guardianPersona = resolveGuardianPersona() ?? "";
55
+ const combined = staticFiles + "\n---\n" + guardianPersona;
52
56
  return createHash("sha256").update(combined).digest("hex");
53
57
  }
54
58
 
@@ -4,8 +4,6 @@
4
4
 
5
5
  import { existsSync, readFileSync, statfsSync, statSync } from "node:fs";
6
6
  import { availableParallelism, cpus, totalmem } from "node:os";
7
- import { dirname, join } from "node:path";
8
- import { fileURLToPath } from "node:url";
9
7
 
10
8
  import { z } from "zod";
11
9
 
@@ -17,6 +15,7 @@ import {
17
15
  getWorkspaceDir,
18
16
  getWorkspacePromptPath,
19
17
  } from "../../util/platform.js";
18
+ import { APP_VERSION } from "../../version.js";
20
19
  import { WORKSPACE_MIGRATIONS } from "../../workspace/migrations/registry.js";
21
20
  import { getLastWorkspaceMigrationId } from "../../workspace/migrations/runner.js";
22
21
  import { httpError } from "../http-errors.js";
@@ -370,19 +369,6 @@ function getCpuInfo(): CpuInfo {
370
369
  };
371
370
  }
372
371
 
373
- function getPackageVersion(): string | undefined {
374
- try {
375
- const pkgPath = join(
376
- dirname(fileURLToPath(import.meta.url)),
377
- "../../../package.json",
378
- );
379
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
380
- return pkg.version;
381
- } catch {
382
- return undefined;
383
- }
384
- }
385
-
386
372
  export function handleHealth(): Response {
387
373
  return Response.json({ status: "ok" });
388
374
  }
@@ -398,7 +384,7 @@ export function handleDetailedHealth(): Response {
398
384
  return Response.json({
399
385
  status: "healthy",
400
386
  timestamp: new Date().toISOString(),
401
- version: getPackageVersion(),
387
+ version: APP_VERSION,
402
388
  disk: getDiskSpaceInfo(),
403
389
  memory: getMemoryInfo(),
404
390
  cpu: getCpuInfo(),
@@ -424,7 +410,7 @@ export function handleGetIdentity(): Response {
424
410
  const content = readFileSync(identityPath, "utf-8");
425
411
  const fields = parseIdentityFields(content);
426
412
 
427
- const version = getPackageVersion();
413
+ const version = APP_VERSION;
428
414
 
429
415
  // Read createdAt from IDENTITY.md file birthtime
430
416
  let createdAt: string | undefined;