@vellumai/assistant 0.3.5 → 0.3.7

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 (487) hide show
  1. package/README.md +51 -0
  2. package/eslint.config.mjs +31 -0
  3. package/package.json +1 -1
  4. package/scripts/ipc/check-swift-decoder-drift.ts +4 -1
  5. package/scripts/ipc/generate-swift.ts +18 -2
  6. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +338 -1
  7. package/src/__tests__/approval-conversation-turn.test.ts +214 -0
  8. package/src/__tests__/browser-manager.test.ts +1 -0
  9. package/src/__tests__/call-conversation-messages.test.ts +130 -0
  10. package/src/__tests__/call-orchestrator.test.ts +752 -271
  11. package/src/__tests__/call-pointer-messages.test.ts +148 -0
  12. package/src/__tests__/call-recovery.test.ts +3 -0
  13. package/src/__tests__/call-routes-http.test.ts +5 -0
  14. package/src/__tests__/call-store.test.ts +3 -0
  15. package/src/__tests__/channel-approval-routes.test.ts +1260 -85
  16. package/src/__tests__/channel-approval.test.ts +37 -0
  17. package/src/__tests__/channel-approvals.test.ts +4 -65
  18. package/src/__tests__/channel-guardian.test.ts +556 -0
  19. package/src/__tests__/channel-readiness-service.test.ts +74 -7
  20. package/src/__tests__/checker.test.ts +14 -7
  21. package/src/__tests__/clarification-resolver.test.ts +44 -24
  22. package/src/__tests__/commit-message-enrichment-service.test.ts +9 -4
  23. package/src/__tests__/computer-use-session-working-dir.test.ts +8 -0
  24. package/src/__tests__/config-schema.test.ts +12 -7
  25. package/src/__tests__/context-window-manager.test.ts +30 -2
  26. package/src/__tests__/contradiction-checker.test.ts +20 -5
  27. package/src/__tests__/credential-security-invariants.test.ts +6 -2
  28. package/src/__tests__/db-migration-rollback.test.ts +752 -0
  29. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -0
  30. package/src/__tests__/fuzzy-match-property.test.ts +5 -5
  31. package/src/__tests__/guardian-action-store.test.ts +123 -0
  32. package/src/__tests__/guardian-action-sweep.test.ts +277 -0
  33. package/src/__tests__/guardian-dispatch.test.ts +389 -0
  34. package/src/__tests__/guardian-question-copy.test.ts +47 -0
  35. package/src/__tests__/handlers-telegram-config.test.ts +4 -2
  36. package/src/__tests__/handlers-twilio-config.test.ts +126 -0
  37. package/src/__tests__/intent-routing.test.ts +2 -0
  38. package/src/__tests__/ipc-snapshot.test.ts +228 -1
  39. package/src/__tests__/memory-upsert-concurrency.test.ts +828 -0
  40. package/src/__tests__/model-intents.test.ts +96 -0
  41. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +42 -0
  42. package/src/__tests__/oauth2-gateway-transport.test.ts +130 -0
  43. package/src/__tests__/onboarding-starter-tasks.test.ts +2 -0
  44. package/src/__tests__/provider-commit-message-generator.test.ts +89 -13
  45. package/src/__tests__/provider-error-scenarios.test.ts +621 -0
  46. package/src/__tests__/provider-fail-open-selection.test.ts +119 -0
  47. package/src/__tests__/qdrant-manager.test.ts +27 -20
  48. package/src/__tests__/relay-server.test.ts +779 -40
  49. package/src/__tests__/run-orchestrator-assistant-events.test.ts +2 -0
  50. package/src/__tests__/run-orchestrator.test.ts +20 -4
  51. package/src/__tests__/runtime-runs-http.test.ts +17 -1
  52. package/src/__tests__/runtime-runs.test.ts +16 -0
  53. package/src/__tests__/schedule-store.test.ts +18 -4
  54. package/src/__tests__/scheduler-recurrence.test.ts +13 -4
  55. package/src/__tests__/session-abort-tool-results.test.ts +6 -0
  56. package/src/__tests__/session-agent-loop.test.ts +857 -0
  57. package/src/__tests__/session-conflict-gate.test.ts +6 -0
  58. package/src/__tests__/session-pre-run-repair.test.ts +6 -0
  59. package/src/__tests__/session-profile-injection.test.ts +6 -0
  60. package/src/__tests__/session-provider-retry-repair.test.ts +6 -0
  61. package/src/__tests__/session-queue.test.ts +6 -0
  62. package/src/__tests__/session-runtime-assembly.test.ts +237 -13
  63. package/src/__tests__/session-slash-known.test.ts +6 -0
  64. package/src/__tests__/session-slash-queue.test.ts +6 -0
  65. package/src/__tests__/session-slash-unknown.test.ts +6 -0
  66. package/src/__tests__/session-surfaces-task-progress.test.ts +2 -0
  67. package/src/__tests__/session-tool-setup-app-refresh.test.ts +1 -0
  68. package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -0
  69. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -0
  70. package/src/__tests__/session-workspace-injection.test.ts +6 -0
  71. package/src/__tests__/session-workspace-tool-tracking.test.ts +6 -0
  72. package/src/__tests__/skills.test.ts +2 -0
  73. package/src/__tests__/sms-messaging-provider.test.ts +2 -1
  74. package/src/__tests__/starter-task-flow.test.ts +2 -0
  75. package/src/__tests__/swarm-dag-pathological.test.ts +535 -0
  76. package/src/__tests__/system-prompt.test.ts +2 -0
  77. package/src/__tests__/task-management-tools.test.ts +2 -2
  78. package/src/__tests__/task-runner.test.ts +14 -4
  79. package/src/__tests__/terminal-tools.test.ts +25 -19
  80. package/src/__tests__/tool-execution-abort-cleanup.test.ts +545 -0
  81. package/src/__tests__/tool-executor-shell-integration.test.ts +11 -11
  82. package/src/__tests__/tool-executor.test.ts +23 -24
  83. package/src/__tests__/trust-store.test.ts +3 -3
  84. package/src/__tests__/twilio-rest.test.ts +29 -0
  85. package/src/__tests__/twilio-routes-elevenlabs.test.ts +3 -0
  86. package/src/__tests__/twilio-routes-twiml.test.ts +11 -0
  87. package/src/__tests__/twilio-routes.test.ts +141 -21
  88. package/src/__tests__/user-reference.test.ts +2 -0
  89. package/src/__tests__/voice-quality.test.ts +222 -0
  90. package/src/__tests__/web-search.test.ts +45 -29
  91. package/src/agent/loop.ts +1 -1
  92. package/src/agent-heartbeat/agent-heartbeat-service.ts +2 -10
  93. package/src/amazon/client.ts +1418 -0
  94. package/src/amazon/request-extractor.ts +135 -0
  95. package/src/amazon/session.ts +109 -0
  96. package/src/autonomy/autonomy-store.ts +5 -5
  97. package/src/browser-extension-relay/client.ts +124 -0
  98. package/src/browser-extension-relay/protocol.ts +63 -0
  99. package/src/browser-extension-relay/server.ts +177 -0
  100. package/src/bundler/app-bundler.ts +3 -3
  101. package/src/bundler/bundle-signer.ts +1 -1
  102. package/src/bundler/signature-verifier.ts +1 -1
  103. package/src/calls/call-conversation-messages.ts +33 -0
  104. package/src/calls/call-domain.ts +106 -5
  105. package/src/calls/call-orchestrator.ts +252 -54
  106. package/src/calls/call-pointer-messages.ts +53 -0
  107. package/src/calls/call-recovery.ts +3 -8
  108. package/src/calls/call-store.ts +69 -87
  109. package/src/calls/elevenlabs-config.ts +3 -2
  110. package/src/calls/guardian-action-sweep.ts +105 -0
  111. package/src/calls/guardian-dispatch.ts +203 -0
  112. package/src/calls/guardian-question-copy.ts +133 -0
  113. package/src/calls/relay-server.ts +466 -8
  114. package/src/calls/speaker-identification.ts +1 -1
  115. package/src/calls/twilio-config.ts +7 -5
  116. package/src/calls/twilio-provider.ts +6 -4
  117. package/src/calls/twilio-rest.ts +40 -15
  118. package/src/calls/twilio-routes.ts +60 -45
  119. package/src/calls/types.ts +3 -1
  120. package/src/channels/types.ts +25 -0
  121. package/src/cli/amazon.ts +815 -0
  122. package/src/cli/config-commands.ts +2 -2
  123. package/src/cli/core-commands.ts +4 -3
  124. package/src/cli/influencer.ts +244 -0
  125. package/src/cli/map.ts +89 -6
  126. package/src/cli.ts +1 -1
  127. package/src/config/agent-schema.ts +171 -0
  128. package/src/config/bundled-skills/amazon/SKILL.md +127 -0
  129. package/src/config/bundled-skills/amazon/icon.svg +13 -0
  130. package/src/config/bundled-skills/api-mapping/SKILL.md +78 -0
  131. package/src/config/bundled-skills/browser/SKILL.md +1 -0
  132. package/src/config/bundled-skills/browser/TOOLS.json +17 -0
  133. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +25 -0
  134. package/src/config/bundled-skills/doordash/SKILL.md +51 -51
  135. package/src/config/bundled-skills/email-setup/SKILL.md +14 -5
  136. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +183 -0
  137. package/src/config/bundled-skills/influencer/SKILL.md +144 -0
  138. package/src/config/bundled-skills/macos-automation/icon.svg +12 -0
  139. package/src/config/bundled-skills/media-processing/SKILL.md +72 -95
  140. package/src/config/bundled-skills/media-processing/TOOLS.json +57 -147
  141. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +77 -0
  142. package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +69 -0
  143. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +303 -0
  144. package/src/config/bundled-skills/media-processing/services/concurrency-pool.ts +55 -0
  145. package/src/config/bundled-skills/media-processing/services/cost-tracker.ts +86 -0
  146. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +339 -0
  147. package/src/config/bundled-skills/media-processing/services/preprocess.ts +551 -0
  148. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +7 -9
  149. package/src/config/bundled-skills/media-processing/services/reduce.ts +197 -0
  150. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +88 -253
  151. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +22 -153
  152. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
  153. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +28 -51
  154. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +35 -270
  155. package/src/config/bundled-skills/messaging/SKILL.md +12 -2
  156. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -7
  157. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +2 -1
  158. package/src/config/bundled-skills/phone-calls/SKILL.md +86 -21
  159. package/src/config/bundled-skills/twitter/icon.svg +14 -0
  160. package/src/config/bundled-tool-registry.ts +310 -0
  161. package/src/config/calls-schema.ts +181 -0
  162. package/src/config/core-schema.ts +309 -0
  163. package/src/config/defaults.ts +27 -3
  164. package/src/config/env-registry.ts +169 -0
  165. package/src/config/env.ts +175 -0
  166. package/src/config/loader.ts +6 -6
  167. package/src/config/memory-schema.ts +528 -0
  168. package/src/config/sandbox-schema.ts +55 -0
  169. package/src/config/schema.ts +157 -1138
  170. package/src/config/skill-state.ts +1 -1
  171. package/src/config/skills-schema.ts +32 -0
  172. package/src/config/skills.ts +35 -24
  173. package/src/config/system-prompt.ts +107 -56
  174. package/src/config/templates/SOUL.md +1 -1
  175. package/src/config/types.ts +1 -0
  176. package/src/config/user-reference.ts +4 -9
  177. package/src/config/vellum-skills/catalog.json +0 -7
  178. package/src/config/vellum-skills/chatgpt-import/tools/chatgpt-import.ts +5 -1
  179. package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +1 -0
  180. package/src/config/vellum-skills/sms-setup/SKILL.md +112 -14
  181. package/src/context/window-manager.ts +27 -7
  182. package/src/daemon/approval-generators.ts +186 -0
  183. package/src/daemon/approved-devices-store.ts +140 -0
  184. package/src/daemon/assistant-attachments.ts +1 -1
  185. package/src/daemon/classifier.ts +35 -32
  186. package/src/daemon/config-watcher.ts +1 -1
  187. package/src/daemon/daemon-control.ts +254 -0
  188. package/src/daemon/handlers/apps.ts +2 -3
  189. package/src/daemon/handlers/config-channels.ts +158 -0
  190. package/src/daemon/handlers/config-inbox.ts +540 -0
  191. package/src/daemon/handlers/config-ingress.ts +231 -0
  192. package/src/daemon/handlers/config-integrations.ts +258 -0
  193. package/src/daemon/handlers/config-model.ts +143 -0
  194. package/src/daemon/handlers/config-parental.ts +163 -0
  195. package/src/daemon/handlers/config-scheduling.ts +172 -0
  196. package/src/daemon/handlers/config-slack.ts +92 -0
  197. package/src/daemon/handlers/config-telegram.ts +301 -0
  198. package/src/daemon/handlers/config-tools.ts +177 -0
  199. package/src/daemon/handlers/config-trust.ts +104 -0
  200. package/src/daemon/handlers/config-twilio.ts +1080 -0
  201. package/src/daemon/handlers/config.ts +53 -2463
  202. package/src/daemon/handlers/diagnostics.ts +1 -1
  203. package/src/daemon/handlers/dictation.ts +4 -6
  204. package/src/daemon/handlers/documents.ts +18 -32
  205. package/src/daemon/handlers/index.ts +9 -0
  206. package/src/daemon/handlers/misc.ts +3 -5
  207. package/src/daemon/handlers/pairing.ts +98 -0
  208. package/src/daemon/handlers/sessions.ts +74 -5
  209. package/src/daemon/handlers/shared.ts +3 -1
  210. package/src/daemon/handlers/skills.ts +1 -1
  211. package/src/daemon/handlers/twitter-auth.ts +2 -0
  212. package/src/daemon/handlers/work-items.ts +2 -2
  213. package/src/daemon/handlers/workspace-files.ts +4 -3
  214. package/src/daemon/install-cli-launchers.ts +113 -0
  215. package/src/daemon/ipc-contract/apps.ts +356 -0
  216. package/src/daemon/ipc-contract/browser.ts +74 -0
  217. package/src/daemon/ipc-contract/computer-use.ts +151 -0
  218. package/src/daemon/ipc-contract/diagnostics.ts +56 -0
  219. package/src/daemon/ipc-contract/documents.ts +74 -0
  220. package/src/daemon/ipc-contract/inbox.ts +209 -0
  221. package/src/daemon/ipc-contract/integrations.ts +284 -0
  222. package/src/daemon/ipc-contract/memory.ts +48 -0
  223. package/src/daemon/ipc-contract/messages.ts +211 -0
  224. package/src/daemon/ipc-contract/pairing.ts +45 -0
  225. package/src/daemon/ipc-contract/parental-control.ts +95 -0
  226. package/src/daemon/ipc-contract/schedules.ts +97 -0
  227. package/src/daemon/ipc-contract/sessions.ts +321 -0
  228. package/src/daemon/ipc-contract/shared.ts +42 -0
  229. package/src/daemon/ipc-contract/skills.ts +120 -0
  230. package/src/daemon/ipc-contract/subagents.ts +58 -0
  231. package/src/daemon/ipc-contract/surfaces.ts +250 -0
  232. package/src/daemon/ipc-contract/trust.ts +60 -0
  233. package/src/daemon/ipc-contract/work-items.ts +225 -0
  234. package/src/daemon/ipc-contract/workspace.ts +113 -0
  235. package/src/daemon/ipc-contract-inventory.json +62 -0
  236. package/src/daemon/ipc-contract-inventory.ts +55 -29
  237. package/src/daemon/ipc-contract.ts +227 -2527
  238. package/src/daemon/ipc-protocol.ts +1 -1
  239. package/src/daemon/ipc-validate.ts +7 -0
  240. package/src/daemon/lifecycle.ts +97 -379
  241. package/src/daemon/pairing-store.ts +177 -0
  242. package/src/daemon/providers-setup.ts +43 -0
  243. package/src/daemon/ride-shotgun-handler.ts +67 -2
  244. package/src/daemon/server.ts +60 -44
  245. package/src/daemon/session-agent-loop-handlers.ts +421 -0
  246. package/src/daemon/session-agent-loop.ts +113 -275
  247. package/src/daemon/session-dynamic-profile.ts +1 -1
  248. package/src/daemon/session-history.ts +1 -1
  249. package/src/daemon/session-media-retry.ts +1 -1
  250. package/src/daemon/session-messaging.ts +37 -2
  251. package/src/daemon/session-notifiers.ts +5 -25
  252. package/src/daemon/session-process.ts +99 -59
  253. package/src/daemon/session-queue-manager.ts +98 -4
  254. package/src/daemon/session-runtime-assembly.ts +149 -15
  255. package/src/daemon/session-surfaces.ts +26 -4
  256. package/src/daemon/session-tool-setup.ts +28 -30
  257. package/src/daemon/session-workspace.ts +1 -1
  258. package/src/daemon/session.ts +24 -1
  259. package/src/daemon/shutdown-handlers.ts +122 -0
  260. package/src/daemon/trace-emitter.ts +1 -1
  261. package/src/daemon/watch-handler.ts +36 -33
  262. package/src/doordash/cart-queries.ts +787 -0
  263. package/src/doordash/client.ts +144 -127
  264. package/src/doordash/order-queries.ts +85 -0
  265. package/src/doordash/queries.ts +10 -1308
  266. package/src/doordash/search-queries.ts +203 -0
  267. package/src/doordash/session.ts +3 -2
  268. package/src/doordash/store-queries.ts +246 -0
  269. package/src/doordash/types.ts +367 -0
  270. package/src/email/providers/agentmail.ts +2 -1
  271. package/src/email/providers/index.ts +3 -2
  272. package/src/email/service.ts +3 -2
  273. package/src/errors.ts +43 -0
  274. package/src/home-base/prebuilt/seed.ts +1 -1
  275. package/src/hooks/cli.ts +6 -5
  276. package/src/hooks/config.ts +6 -8
  277. package/src/hooks/discovery.ts +6 -5
  278. package/src/hooks/manager.ts +4 -3
  279. package/src/hooks/runner.ts +2 -2
  280. package/src/hooks/templates.ts +5 -5
  281. package/src/inbound/public-ingress-urls.ts +3 -1
  282. package/src/index.ts +4 -2
  283. package/src/influencer/client.ts +1104 -0
  284. package/src/instrument.ts +4 -3
  285. package/src/logfire.ts +4 -3
  286. package/src/memory/admin.ts +25 -35
  287. package/src/memory/attachments-store.ts +4 -7
  288. package/src/memory/channel-delivery-store.ts +30 -1
  289. package/src/memory/channel-guardian-store.ts +200 -1
  290. package/src/memory/clarification-resolver.ts +37 -33
  291. package/src/memory/conflict-store.ts +67 -61
  292. package/src/memory/contradiction-checker.ts +141 -117
  293. package/src/memory/conversation-store.ts +335 -51
  294. package/src/memory/db-connection.ts +27 -4
  295. package/src/memory/db-init.ts +121 -4
  296. package/src/memory/db.ts +14 -1
  297. package/src/memory/embedding-backend.ts +27 -5
  298. package/src/memory/embedding-ollama.ts +2 -1
  299. package/src/memory/entity-extractor.ts +38 -35
  300. package/src/memory/guardian-action-store.ts +430 -0
  301. package/src/memory/inbox-escalation-projection.ts +59 -0
  302. package/src/memory/inbox-thread-store.ts +218 -0
  303. package/src/memory/ingress-invite-store.ts +338 -0
  304. package/src/memory/ingress-member-store.ts +350 -0
  305. package/src/memory/items-extractor.ts +91 -97
  306. package/src/memory/job-handlers/index-maintenance.ts +3 -3
  307. package/src/memory/job-handlers/media-processing.ts +11 -42
  308. package/src/memory/job-handlers/summarization.ts +32 -26
  309. package/src/memory/job-utils.ts +3 -10
  310. package/src/memory/jobs-store.ts +6 -9
  311. package/src/memory/jobs-worker.ts +51 -36
  312. package/src/memory/migrations/001-job-deferrals.ts +45 -0
  313. package/src/memory/migrations/002-tool-invocations-fk.ts +43 -0
  314. package/src/memory/migrations/003-memory-fts-backfill.ts +24 -0
  315. package/src/memory/migrations/004-entity-relation-dedup.ts +87 -0
  316. package/src/memory/migrations/005-fingerprint-scope-unique.ts +80 -0
  317. package/src/memory/migrations/006-scope-salted-fingerprints.ts +62 -0
  318. package/src/memory/migrations/007-assistant-id-to-self.ts +254 -0
  319. package/src/memory/migrations/008-remove-assistant-id-columns.ts +208 -0
  320. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +83 -0
  321. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +56 -0
  322. package/src/memory/migrations/011-call-sessions-provider-sid-dedup.ts +63 -0
  323. package/src/memory/migrations/012-call-sessions-add-initiated-from.ts +19 -0
  324. package/src/memory/migrations/013-guardian-action-tables.ts +68 -0
  325. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +76 -0
  326. package/src/memory/migrations/015-drop-active-search-index.ts +27 -0
  327. package/src/memory/migrations/016-memory-segments-indexes.ts +11 -0
  328. package/src/memory/migrations/017-memory-items-indexes.ts +12 -0
  329. package/src/memory/migrations/018-remaining-table-indexes.ts +13 -0
  330. package/src/memory/migrations/index.ts +24 -0
  331. package/src/memory/migrations/registry.ts +79 -0
  332. package/src/memory/migrations/validate-migration-state.ts +69 -0
  333. package/src/memory/qdrant-manager.ts +49 -8
  334. package/src/memory/query-builder.ts +1 -1
  335. package/src/memory/raw-query.ts +119 -0
  336. package/src/memory/recall-cache.ts +4 -1
  337. package/src/memory/retriever.ts +163 -47
  338. package/src/memory/schema-migration.ts +25 -984
  339. package/src/memory/schema.ts +130 -7
  340. package/src/memory/search/entity.ts +10 -19
  341. package/src/memory/search/lexical.ts +81 -52
  342. package/src/memory/search/ranking.ts +21 -22
  343. package/src/memory/search/semantic.ts +157 -19
  344. package/src/memory/shared-app-links-store.ts +4 -5
  345. package/src/memory/validation.ts +19 -0
  346. package/src/messaging/draft-store.ts +5 -6
  347. package/src/messaging/providers/sms/adapter.ts +3 -6
  348. package/src/messaging/providers/telegram-bot/adapter.ts +2 -5
  349. package/src/messaging/providers/whatsapp/adapter.ts +136 -0
  350. package/src/messaging/providers/whatsapp/client.ts +67 -0
  351. package/src/messaging/style-analyzer.ts +5 -4
  352. package/src/messaging/thread-summarizer.ts +61 -69
  353. package/src/messaging/triage-engine.ts +62 -71
  354. package/src/migrations/config-merge.ts +53 -0
  355. package/src/migrations/data-layout.ts +68 -0
  356. package/src/migrations/data-merge.ts +33 -0
  357. package/src/migrations/hooks-merge.ts +90 -0
  358. package/src/migrations/index.ts +6 -0
  359. package/src/migrations/log.ts +23 -0
  360. package/src/migrations/skills-merge.ts +33 -0
  361. package/src/migrations/workspace-layout.ts +79 -0
  362. package/src/permissions/checker.ts +126 -11
  363. package/src/permissions/prompter.ts +14 -0
  364. package/src/permissions/shell-identity.ts +31 -1
  365. package/src/permissions/trust-store.ts +21 -1
  366. package/src/providers/anthropic/client.ts +4 -4
  367. package/src/providers/failover.ts +2 -2
  368. package/src/providers/model-intents.ts +70 -0
  369. package/src/providers/ollama/client.ts +2 -1
  370. package/src/providers/provider-send-message.ts +176 -0
  371. package/src/providers/registry.ts +71 -30
  372. package/src/providers/retry.ts +35 -1
  373. package/src/providers/types.ts +12 -1
  374. package/src/runtime/approval-conversation-turn.ts +97 -0
  375. package/src/runtime/approval-message-composer.ts +115 -5
  376. package/src/runtime/assistant-event-hub.ts +3 -1
  377. package/src/runtime/channel-approval-parser.ts +36 -2
  378. package/src/runtime/channel-approvals.ts +0 -21
  379. package/src/runtime/channel-guardian-service.ts +48 -7
  380. package/src/runtime/channel-readiness-service.ts +160 -34
  381. package/src/runtime/channel-readiness-types.ts +10 -4
  382. package/src/runtime/channel-retry-sweep.ts +184 -0
  383. package/src/runtime/guardian-context-resolver.ts +108 -0
  384. package/src/runtime/http-server.ts +289 -745
  385. package/src/runtime/http-types.ts +56 -3
  386. package/src/runtime/middleware/auth.ts +116 -0
  387. package/src/runtime/middleware/error-handler.ts +33 -0
  388. package/src/runtime/middleware/twilio-validation.ts +127 -0
  389. package/src/runtime/routes/app-routes.ts +1 -1
  390. package/src/runtime/routes/call-routes.ts +49 -6
  391. package/src/runtime/routes/channel-delivery-routes.ts +170 -0
  392. package/src/runtime/routes/channel-guardian-routes.ts +1191 -0
  393. package/src/runtime/routes/channel-inbound-routes.ts +1152 -0
  394. package/src/runtime/routes/channel-route-shared.ts +144 -0
  395. package/src/runtime/routes/channel-routes.ts +32 -1634
  396. package/src/runtime/routes/conversation-routes.ts +50 -7
  397. package/src/runtime/routes/events-routes.ts +2 -2
  398. package/src/runtime/routes/identity-routes.ts +126 -0
  399. package/src/runtime/routes/pairing-routes.ts +144 -0
  400. package/src/runtime/routes/run-routes.ts +15 -1
  401. package/src/runtime/run-orchestrator.ts +52 -34
  402. package/src/schedule/schedule-store.ts +36 -32
  403. package/src/schedule/scheduler.ts +3 -3
  404. package/src/security/encrypted-store.ts +5 -7
  405. package/src/security/oauth2.ts +45 -15
  406. package/src/security/parental-control-store.ts +183 -0
  407. package/src/security/secret-allowlist.ts +4 -3
  408. package/src/security/secret-scanner.ts +5 -5
  409. package/src/security/secure-keys.ts +1 -1
  410. package/src/security/token-manager.ts +3 -2
  411. package/src/services/vercel-deploy.ts +6 -2
  412. package/src/skills/tool-manifest.ts +3 -3
  413. package/src/skills/vellum-catalog-remote.ts +75 -16
  414. package/src/slack/slack-webhook.ts +2 -1
  415. package/src/swarm/orchestrator.ts +92 -1
  416. package/src/swarm/router-planner.ts +6 -9
  417. package/src/swarm/worker-prompts.ts +9 -12
  418. package/src/tasks/task-compiler.ts +19 -28
  419. package/src/tasks/task-runner.ts +1 -1
  420. package/src/tools/assets/search.ts +15 -14
  421. package/src/tools/browser/__tests__/auth-detector.test.ts +1 -0
  422. package/src/tools/browser/auto-navigate.ts +1 -0
  423. package/src/tools/browser/browser-execution.ts +13 -1
  424. package/src/tools/browser/browser-manager.ts +119 -4
  425. package/src/tools/browser/network-recorder.ts +5 -0
  426. package/src/tools/credentials/broker.ts +11 -2
  427. package/src/tools/credentials/metadata-store.ts +18 -14
  428. package/src/tools/credentials/post-connect-hooks.ts +61 -0
  429. package/src/tools/credentials/vault.ts +49 -23
  430. package/src/tools/executor.ts +80 -18
  431. package/src/tools/host-terminal/cli-discover.ts +1 -1
  432. package/src/tools/network/script-proxy/http-forwarder.ts +1 -1
  433. package/src/tools/network/script-proxy/mitm-handler.ts +1 -1
  434. package/src/tools/network/script-proxy/server.ts +1 -1
  435. package/src/tools/network/script-proxy/session-manager.ts +6 -5
  436. package/src/tools/network/web-fetch.ts +18 -2
  437. package/src/tools/network/web-search.ts +7 -3
  438. package/src/tools/reminder/reminder-store.ts +14 -15
  439. package/src/tools/schedule/create.ts +1 -0
  440. package/src/tools/schedule/list.ts +2 -1
  441. package/src/tools/shared/filesystem/file-ops-service.ts +5 -7
  442. package/src/tools/skills/skill-script-runner.ts +24 -9
  443. package/src/tools/skills/skill-tool-factory.ts +1 -0
  444. package/src/tools/tasks/work-item-enqueue.ts +2 -2
  445. package/src/tools/terminal/evaluate-typescript.ts +21 -12
  446. package/src/tools/terminal/parser.ts +50 -0
  447. package/src/tools/watcher/delete.ts +6 -0
  448. package/src/tools/weather/service.ts +1 -1
  449. package/src/twitter/client.ts +190 -24
  450. package/src/twitter/session.ts +4 -3
  451. package/src/util/clipboard.ts +1 -1
  452. package/src/util/errors.ts +65 -8
  453. package/src/util/fs.ts +40 -0
  454. package/src/util/json.ts +10 -0
  455. package/src/util/log-redact.ts +189 -0
  456. package/src/util/logger.ts +25 -18
  457. package/src/util/object.ts +3 -0
  458. package/src/util/platform.ts +72 -365
  459. package/src/util/pricing.ts +1 -1
  460. package/src/util/promise-guard.ts +1 -1
  461. package/src/util/retry.ts +19 -0
  462. package/src/util/row-mapper.ts +79 -0
  463. package/src/util/silently.ts +21 -0
  464. package/src/watcher/engine.ts +5 -1
  465. package/src/watcher/provider-types.ts +20 -0
  466. package/src/watcher/providers/github.ts +156 -0
  467. package/src/watcher/providers/gmail.ts +1 -0
  468. package/src/watcher/providers/google-calendar.ts +1 -0
  469. package/src/watcher/providers/linear.ts +460 -0
  470. package/src/watcher/providers/slack.ts +1 -0
  471. package/src/work-items/work-item-runner.ts +1 -1
  472. package/src/workspace/git-service.ts +1 -1
  473. package/src/workspace/provider-commit-message-generator.ts +51 -22
  474. package/src/__tests__/call-bridge.test.ts +0 -517
  475. package/src/__tests__/session-process-bridge.test.ts +0 -244
  476. package/src/calls/call-bridge.ts +0 -168
  477. package/src/config/bundled-skills/media-processing/services/capability-registry.ts +0 -137
  478. package/src/config/bundled-skills/media-processing/services/event-detection-service.ts +0 -280
  479. package/src/config/bundled-skills/media-processing/services/feedback-aggregation.ts +0 -144
  480. package/src/config/bundled-skills/media-processing/services/feedback-store.ts +0 -136
  481. package/src/config/bundled-skills/media-processing/services/retrieval-service.ts +0 -95
  482. package/src/config/bundled-skills/media-processing/services/timeline-service.ts +0 -267
  483. package/src/config/bundled-skills/media-processing/tools/detect-events.ts +0 -110
  484. package/src/config/bundled-skills/media-processing/tools/recalibrate.ts +0 -235
  485. package/src/config/bundled-skills/media-processing/tools/select-tracking-profile.ts +0 -142
  486. package/src/config/bundled-skills/media-processing/tools/submit-feedback.ts +0 -150
  487. package/src/config/vellum-skills/google-oauth-setup/SKILL.md +0 -199
@@ -0,0 +1,367 @@
1
+ /**
2
+ * Type definitions for DoorDash GraphQL API responses.
3
+ * These model the raw shapes returned by the API before extraction
4
+ * into the public-facing interfaces (SearchResult, StoreInfo, etc.).
5
+ */
6
+
7
+ // ---------------------------------------------------------------------------
8
+ // Shared / reusable fragments
9
+ // ---------------------------------------------------------------------------
10
+
11
+ export interface DDTextAttributes {
12
+ textStyle?: string;
13
+ textColor?: string;
14
+ }
15
+
16
+ export interface DDText {
17
+ title?: string;
18
+ titleTextAttributes?: DDTextAttributes;
19
+ subtitle?: string;
20
+ subtitleTextAttributes?: DDTextAttributes;
21
+ accessory?: string;
22
+ accessoryTextAttributes?: DDTextAttributes;
23
+ description?: string;
24
+ }
25
+
26
+ export interface DDImage {
27
+ uri?: string;
28
+ }
29
+
30
+ export interface DDImages {
31
+ main?: DDImage;
32
+ }
33
+
34
+ export interface DDClickEvent {
35
+ data?: string;
36
+ }
37
+
38
+ export interface DDEvents {
39
+ click?: DDClickEvent;
40
+ }
41
+
42
+ export interface DDAddress {
43
+ displayAddress?: string;
44
+ }
45
+
46
+ export interface DDRatings {
47
+ averageRating?: number;
48
+ numRatingsDisplayString?: string;
49
+ }
50
+
51
+ export interface DDFeeLayout {
52
+ title?: string;
53
+ }
54
+
55
+ export interface DDPrice {
56
+ display_string?: string;
57
+ displayString?: string;
58
+ unit_amount?: number;
59
+ unitAmount?: number;
60
+ }
61
+
62
+ // ---------------------------------------------------------------------------
63
+ // Search / Feed responses
64
+ // ---------------------------------------------------------------------------
65
+
66
+ export interface DDFacetItem {
67
+ id?: string;
68
+ childrenCount?: number;
69
+ component?: { id?: string; category?: string };
70
+ name?: string;
71
+ text?: DDText;
72
+ images?: DDImages;
73
+ events?: DDEvents;
74
+ childrenMap?: DDFacetItem[];
75
+ }
76
+
77
+ export interface DDFeedSection {
78
+ id?: string;
79
+ header?: DDFacetItem;
80
+ body?: DDFacetItem[];
81
+ layout?: { omitFooter?: boolean };
82
+ }
83
+
84
+ export interface DDFacetFeed {
85
+ body?: DDFeedSection[];
86
+ page?: DDFacetItem;
87
+ header?: DDFacetItem;
88
+ footer?: DDFacetItem;
89
+ custom?: string;
90
+ logging?: string;
91
+ }
92
+
93
+ export interface DDSearchClickData {
94
+ store_id?: string | number;
95
+ storeId?: string | number;
96
+ }
97
+
98
+ // ---------------------------------------------------------------------------
99
+ // Store page responses
100
+ // ---------------------------------------------------------------------------
101
+
102
+ export interface DDStoreHeader {
103
+ id?: string;
104
+ name?: string;
105
+ description?: string;
106
+ address?: DDAddress;
107
+ ratings?: DDRatings;
108
+ deliveryFeeLayout?: DDFeeLayout;
109
+ deliveryTimeLayout?: DDFeeLayout;
110
+ priceRangeDisplayString?: string;
111
+ }
112
+
113
+ export interface DDMenuCategory {
114
+ id?: string;
115
+ name?: string;
116
+ numItems?: number;
117
+ }
118
+
119
+ export interface DDMenuBook {
120
+ menuCategories?: DDMenuCategory[];
121
+ }
122
+
123
+ export interface DDStoreItem {
124
+ id?: string;
125
+ name?: string;
126
+ description?: string;
127
+ displayPrice?: string;
128
+ imageUrl?: string;
129
+ imgUrl?: string;
130
+ storeId?: string;
131
+ }
132
+
133
+ export interface DDItemList {
134
+ items?: DDStoreItem[];
135
+ }
136
+
137
+ export interface DDCarousel {
138
+ items?: DDStoreItem[];
139
+ }
140
+
141
+ export interface DDStorepageFeed {
142
+ storeHeader?: DDStoreHeader;
143
+ menuBook?: DDMenuBook;
144
+ itemLists?: DDItemList[];
145
+ carousels?: DDCarousel[];
146
+ }
147
+
148
+ // ---------------------------------------------------------------------------
149
+ // Retail store feed responses
150
+ // ---------------------------------------------------------------------------
151
+
152
+ export interface DDRetailStoreStatus {
153
+ delivery?: { etaDisplayString?: string };
154
+ }
155
+
156
+ export interface DDRetailStoreHeader {
157
+ name?: string;
158
+ description?: string;
159
+ address?: DDAddress;
160
+ ratings?: DDRatings;
161
+ deliveryFeeLayout?: DDFeeLayout;
162
+ priceRangeDisplayString?: string;
163
+ status?: DDRetailStoreStatus;
164
+ }
165
+
166
+ export interface DDRetailStoreDetails {
167
+ id?: string;
168
+ name?: string;
169
+ storeHeader?: DDRetailStoreHeader;
170
+ }
171
+
172
+ export interface DDRetailProduct {
173
+ id?: string;
174
+ name?: string;
175
+ description?: string;
176
+ displayPrice?: string;
177
+ imageUrl?: string;
178
+ imgUrl?: string;
179
+ storeId?: string;
180
+ price?: DDPrice;
181
+ }
182
+
183
+ export interface DDRetailCollection {
184
+ products?: DDRetailProduct[];
185
+ items?: DDRetailProduct[];
186
+ }
187
+
188
+ export interface DDRetailL1Category {
189
+ id?: string;
190
+ name?: string;
191
+ numItems?: number;
192
+ }
193
+
194
+ export interface DDRetailStorePageFeed {
195
+ storeDetails?: DDRetailStoreDetails;
196
+ l1Categories?: DDRetailL1Category[];
197
+ collections?: DDRetailCollection[];
198
+ page?: unknown;
199
+ }
200
+
201
+ // ---------------------------------------------------------------------------
202
+ // Retail search responses
203
+ // ---------------------------------------------------------------------------
204
+
205
+ export interface DDRetailItemImage {
206
+ remote?: { uri?: string };
207
+ }
208
+
209
+ export interface DDRetailItemPrice {
210
+ display_string?: string;
211
+ unit_amount?: number;
212
+ }
213
+
214
+ export interface DDRetailItemData {
215
+ item_id?: string | number;
216
+ item_name?: string;
217
+ description?: string;
218
+ store_id?: string | number;
219
+ menu_id?: string | number;
220
+ price?: DDRetailItemPrice;
221
+ }
222
+
223
+ export interface DDRetailItemCustom {
224
+ item_data?: DDRetailItemData;
225
+ image?: DDRetailItemImage;
226
+ }
227
+
228
+ export interface DDLegoRetailItem {
229
+ custom?: string;
230
+ }
231
+
232
+ export interface DDSearchSummary {
233
+ totalCount?: number;
234
+ suggestedSearchKeyword?: string;
235
+ }
236
+
237
+ export interface DDRetailSearchResult {
238
+ legoRetailItems?: DDLegoRetailItem[];
239
+ searchSummary?: DDSearchSummary;
240
+ }
241
+
242
+ // ---------------------------------------------------------------------------
243
+ // Item page responses
244
+ // ---------------------------------------------------------------------------
245
+
246
+ export interface DDItemHeader {
247
+ id?: string;
248
+ name?: string;
249
+ description?: string;
250
+ displayString?: string;
251
+ unitAmount?: number;
252
+ currency?: string;
253
+ imgUrl?: string;
254
+ menuId?: string;
255
+ }
256
+
257
+ export interface DDOptionChoice {
258
+ id?: string;
259
+ name?: string;
260
+ displayString?: string;
261
+ unitAmount?: number;
262
+ defaultQuantity?: number;
263
+ nestedExtrasList?: DDNestedExtra[];
264
+ }
265
+
266
+ export interface DDNestedExtra {
267
+ id?: string;
268
+ name?: string;
269
+ isOptional?: boolean;
270
+ options?: DDNestedExtraChoice[];
271
+ }
272
+
273
+ export interface DDNestedExtraChoice {
274
+ id?: string;
275
+ name?: string;
276
+ displayString?: string;
277
+ }
278
+
279
+ export interface DDOptionList {
280
+ id?: string;
281
+ name?: string;
282
+ isOptional?: boolean;
283
+ minNumOptions?: number;
284
+ maxNumOptions?: number;
285
+ options?: DDOptionChoice[];
286
+ }
287
+
288
+ export interface DDSpecialInstructions {
289
+ characterMaxLength?: number;
290
+ placeholderText?: string;
291
+ isEnabled?: boolean;
292
+ }
293
+
294
+ export interface DDItemPreferences {
295
+ specialInstructions?: DDSpecialInstructions;
296
+ }
297
+
298
+ export interface DDItemPage {
299
+ itemHeader?: DDItemHeader;
300
+ optionLists?: DDOptionList[];
301
+ itemPreferences?: DDItemPreferences;
302
+ }
303
+
304
+ // ---------------------------------------------------------------------------
305
+ // Cart responses
306
+ // ---------------------------------------------------------------------------
307
+
308
+ export interface DDCartItemDetail {
309
+ name?: string;
310
+ }
311
+
312
+ export interface DDOrderItem {
313
+ id?: string;
314
+ item?: DDCartItemDetail;
315
+ quantity?: number;
316
+ priceDisplayString?: string;
317
+ }
318
+
319
+ export interface DDOrder {
320
+ orderItems?: DDOrderItem[];
321
+ }
322
+
323
+ export interface DDCartRestaurant {
324
+ id?: string;
325
+ name?: string;
326
+ }
327
+
328
+ export interface DDCart {
329
+ id?: string;
330
+ restaurant?: DDCartRestaurant;
331
+ orders?: DDOrder[];
332
+ subtotal?: number;
333
+ total?: number;
334
+ }
335
+
336
+ // ---------------------------------------------------------------------------
337
+ // Dropoff options responses
338
+ // ---------------------------------------------------------------------------
339
+
340
+ export interface DDDropoffOption {
341
+ id?: string;
342
+ displayString?: string;
343
+ isDefault?: boolean;
344
+ isEnabled?: boolean;
345
+ }
346
+
347
+ // ---------------------------------------------------------------------------
348
+ // Payment method responses
349
+ // ---------------------------------------------------------------------------
350
+
351
+ export interface DDPaymentMethod {
352
+ id?: string;
353
+ type?: string;
354
+ last4?: string;
355
+ isDefault?: boolean;
356
+ paymentMethodUuid?: string;
357
+ uuid?: string;
358
+ }
359
+
360
+ // ---------------------------------------------------------------------------
361
+ // Order responses
362
+ // ---------------------------------------------------------------------------
363
+
364
+ export interface DDCreateOrderResult {
365
+ cartId?: string;
366
+ orderUuid?: string;
367
+ }
@@ -7,6 +7,7 @@
7
7
  import type { AgentMailClient } from 'agentmail';
8
8
  import type { EmailProvider, SetupDomainOpts, CreateInboxOpts, EnsureInboxesOpts, SetupWebhookOpts, CreateDraftOpts, ListDraftsOpts, ListMessagesOpts, ListThreadsOpts } from '../provider.js';
9
9
  import type { EmailDomain, DnsRecord, EmailInbox, EmailDraft, EmailMessage, EmailThread, EmailWebhook, ProviderHealth, SendResult } from '../types.js';
10
+ import { ConfigError } from '../../util/errors.js';
10
11
 
11
12
  const DEFAULT_INBOX_PREFIXES = ['hello', 'support', 'ops'];
12
13
 
@@ -201,7 +202,7 @@ export class AgentMailProvider implements EmailProvider {
201
202
  if (inboxes.inboxes.length > 0) {
202
203
  return inboxes.inboxes[0].inboxId;
203
204
  }
204
- throw new Error('No inboxes found. Run: vellum email setup inboxes --domain <domain>');
205
+ throw new ConfigError('No inboxes found. Run: vellum email setup inboxes --domain <domain>');
205
206
  }
206
207
  }
207
208
 
@@ -7,6 +7,7 @@
7
7
  import type { EmailProvider } from '../provider.js';
8
8
  import { getSecureKey } from '../../security/secure-keys.js';
9
9
  import { loadRawConfig, getNestedValue } from '../../config/loader.js';
10
+ import { ConfigError } from '../../util/errors.js';
10
11
 
11
12
  export const SUPPORTED_PROVIDERS = ['agentmail'] as const;
12
13
  export type SupportedProvider = (typeof SUPPORTED_PROVIDERS)[number];
@@ -44,7 +45,7 @@ export async function createProvider(name?: SupportedProvider): Promise<EmailPro
44
45
  if (apiKey) break;
45
46
  }
46
47
  if (!apiKey) {
47
- throw new Error(
48
+ throw new ConfigError(
48
49
  'No AgentMail API key configured. Run: vellum keys set agentmail <key>',
49
50
  );
50
51
  }
@@ -53,6 +54,6 @@ export async function createProvider(name?: SupportedProvider): Promise<EmailPro
53
54
  return new AgentMailProvider(new AgentMailClient({ apiKey }));
54
55
  }
55
56
  default:
56
- throw new Error(`Unknown email provider: ${providerName}`);
57
+ throw new ConfigError(`Unknown email provider: ${providerName}`);
57
58
  }
58
59
  }
@@ -31,6 +31,7 @@ import {
31
31
  } from '../cli/email-guardrails.js';
32
32
  import { createProvider, getActiveProviderName, type SupportedProvider } from './providers/index.js';
33
33
  import { loadRawConfig, setNestedValue, saveRawConfig } from '../config/loader.js';
34
+ import { ConfigError } from '../util/errors.js';
34
35
 
35
36
  // ---------------------------------------------------------------------------
36
37
  // Guardrail error
@@ -156,12 +157,12 @@ export class EmailService {
156
157
  // Resolve inbox from the "from" address — fail fast if not found
157
158
  const health = await p.health();
158
159
  if (health.inboxes.length === 0) {
159
- throw new Error('No inboxes found. Run: vellum email setup inboxes --domain <domain>');
160
+ throw new ConfigError('No inboxes found. Run: vellum email setup inboxes --domain <domain>');
160
161
  }
161
162
  const inbox = health.inboxes.find(i => i.address === input.from || i.id === input.from);
162
163
  if (!inbox) {
163
164
  const available = health.inboxes.map(i => i.address || i.id).join(', ');
164
- throw new Error(`No inbox matches --from "${input.from}". Available: ${available}`);
165
+ throw new ConfigError(`No inbox matches --from "${input.from}". Available: ${available}`);
165
166
  }
166
167
  const inboxId = inbox.id;
167
168
  return p.createDraft({
package/src/errors.ts ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Central export point for the Vellum error hierarchy.
3
+ *
4
+ * Import from this module to access any named error class:
5
+ *
6
+ * import { VellumError, BackendUnavailableError, RateLimitError, ... } from '../errors.js';
7
+ *
8
+ * Full hierarchy (defined in util/errors.ts):
9
+ *
10
+ * VellumError — root base
11
+ * ├─ BackendError — infrastructure / external-service failures
12
+ * │ ├─ BackendUnavailableError — service not reachable or not configured
13
+ * │ └─ RateLimitError — request or token quota exceeded
14
+ * ├─ UserError — user input / policy violations
15
+ * └─ AssistantError — assistant-logic errors (carries ErrorCode)
16
+ * ├─ ProviderError
17
+ * ├─ ToolError
18
+ * ├─ PermissionDeniedError
19
+ * ├─ ConfigError
20
+ * ├─ DaemonError
21
+ * ├─ IpcError
22
+ * ├─ PlatformError
23
+ * ├─ IntegrityError
24
+ * └─ IngressBlockedError
25
+ */
26
+ export {
27
+ ErrorCode,
28
+ VellumError,
29
+ BackendError,
30
+ BackendUnavailableError,
31
+ RateLimitError,
32
+ UserError,
33
+ AssistantError,
34
+ ProviderError,
35
+ ToolError,
36
+ PermissionDeniedError,
37
+ ConfigError,
38
+ DaemonError,
39
+ IpcError,
40
+ PlatformError,
41
+ IntegrityError,
42
+ IngressBlockedError,
43
+ } from './util/errors.js';
@@ -94,7 +94,7 @@ export function ensurePrebuiltHomeBaseSeeded(): { appId: string; created: boolea
94
94
 
95
95
  const metadata = loadSeedMetadata();
96
96
  const html = loadPrebuiltHtml();
97
- if (html === null) {
97
+ if (html == null) {
98
98
  log.warn('Skipping Home Base seed — prebuilt HTML not available');
99
99
  return null;
100
100
  }
package/src/hooks/cli.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Command } from 'commander';
2
- import { existsSync, cpSync, readFileSync, chmodSync, rmSync } from 'node:fs';
2
+ import { cpSync, readFileSync, chmodSync, rmSync } from 'node:fs';
3
+ import { pathExists } from '../util/fs.js';
3
4
  import { join, resolve, sep } from 'node:path';
4
5
  import { discoverHooks, isValidInstallManifest } from './discovery.js';
5
6
  import { setHookEnabled, ensureHookInConfig, removeHook } from './config.js';
@@ -79,13 +80,13 @@ export function registerHooksCommand(program: Command): void {
79
80
  .description('Install a hook from a directory')
80
81
  .action((hookPath: string) => {
81
82
  const srcDir = resolve(hookPath);
82
- if (!existsSync(srcDir)) {
83
+ if (!pathExists(srcDir)) {
83
84
  log.error(`Directory not found: ${srcDir}`);
84
85
  process.exit(1);
85
86
  }
86
87
 
87
88
  const manifestPath = join(srcDir, 'hook.json');
88
- if (!existsSync(manifestPath)) {
89
+ if (!pathExists(manifestPath)) {
89
90
  log.error(`No hook.json found in ${srcDir}`);
90
91
  process.exit(1);
91
92
  }
@@ -117,7 +118,7 @@ export function registerHooksCommand(program: Command): void {
117
118
  process.exit(1);
118
119
  }
119
120
 
120
- if (existsSync(targetDir)) {
121
+ if (pathExists(targetDir)) {
121
122
  log.error(`Hook already installed: ${manifest.name}`);
122
123
  process.exit(1);
123
124
  }
@@ -125,7 +126,7 @@ export function registerHooksCommand(program: Command): void {
125
126
  cpSync(srcDir, targetDir, { recursive: true });
126
127
 
127
128
  // Make script executable
128
- if (existsSync(scriptPath)) {
129
+ if (pathExists(scriptPath)) {
129
130
  chmodSync(scriptPath, 0o755);
130
131
  }
131
132
 
@@ -1,5 +1,6 @@
1
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
1
+ import { writeFileSync } from 'node:fs';
2
2
  import { join, dirname } from 'node:path';
3
+ import { ensureDir, readTextFileSync } from '../util/fs.js';
3
4
  import { getHooksDir } from '../util/platform.js';
4
5
  import { getLogger } from '../util/logger.js';
5
6
  import type { HookConfig, HookConfigEntry, HookManifest } from './types.js';
@@ -14,14 +15,14 @@ function getConfigPath(): string {
14
15
 
15
16
  export function loadHooksConfig(): HookConfig {
16
17
  const configPath = getConfigPath();
17
- if (!existsSync(configPath)) {
18
+ const raw = readTextFileSync(configPath);
19
+ if (raw == null) {
18
20
  return { version: HOOKS_CONFIG_VERSION, hooks: {} };
19
21
  }
20
22
 
21
23
  try {
22
- const raw = readFileSync(configPath, 'utf-8');
23
24
  const parsed = JSON.parse(raw) as HookConfig;
24
- if (typeof parsed.version !== 'number' || typeof parsed.hooks !== 'object' || parsed.hooks === null) {
25
+ if (typeof parsed.version !== 'number' || typeof parsed.hooks !== 'object' || parsed.hooks == null) {
25
26
  log.warn({ configPath }, 'Invalid hooks config, using defaults');
26
27
  return { version: HOOKS_CONFIG_VERSION, hooks: {} };
27
28
  }
@@ -34,10 +35,7 @@ export function loadHooksConfig(): HookConfig {
34
35
 
35
36
  export function saveHooksConfig(config: HookConfig): void {
36
37
  const configPath = getConfigPath();
37
- const dir = dirname(configPath);
38
- if (!existsSync(dir)) {
39
- mkdirSync(dir, { recursive: true });
40
- }
38
+ ensureDir(dirname(configPath));
41
39
  writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
42
40
  }
43
41
 
@@ -1,5 +1,6 @@
1
- import { readdirSync, readFileSync, existsSync, type Dirent } from 'node:fs';
1
+ import { readdirSync, readFileSync, type Dirent } from 'node:fs';
2
2
  import { join, resolve, relative } from 'node:path';
3
+ import { pathExists } from '../util/fs.js';
3
4
  import { getHooksDir } from '../util/platform.js';
4
5
  import { loadHooksConfig } from './config.js';
5
6
  import { getLogger } from '../util/logger.js';
@@ -23,7 +24,7 @@ const VALID_EVENTS = new Set<string>([
23
24
  * (created before those fields were added) continue to be discovered.
24
25
  */
25
26
  export function isValidManifest(manifest: unknown): manifest is HookManifest {
26
- if (typeof manifest !== 'object' || manifest === null) return false;
27
+ if (typeof manifest !== 'object' || manifest == null) return false;
27
28
  const m = manifest as Record<string, unknown>;
28
29
  if (typeof m.name !== 'string' || !m.name) return false;
29
30
  if (typeof m.script !== 'string' || !m.script) return false;
@@ -50,7 +51,7 @@ export function isValidInstallManifest(manifest: unknown): manifest is HookManif
50
51
 
51
52
  export function discoverHooks(hooksDir?: string): DiscoveredHook[] {
52
53
  const dir = hooksDir ?? getHooksDir();
53
- if (!existsSync(dir)) return [];
54
+ if (!pathExists(dir)) return [];
54
55
 
55
56
  const config = loadHooksConfig();
56
57
  const hooks: DiscoveredHook[] = [];
@@ -68,7 +69,7 @@ export function discoverHooks(hooksDir?: string): DiscoveredHook[] {
68
69
 
69
70
  const hookDir = join(dir, entry.name);
70
71
  const manifestPath = join(hookDir, 'hook.json');
71
- if (!existsSync(manifestPath)) continue;
72
+ if (!pathExists(manifestPath)) continue;
72
73
 
73
74
  let manifest: unknown;
74
75
  try {
@@ -92,7 +93,7 @@ export function discoverHooks(hooksDir?: string): DiscoveredHook[] {
92
93
  log.warn({ hookDir, script: manifest.script }, 'Hook script path traversal detected, skipping');
93
94
  continue;
94
95
  }
95
- if (!existsSync(scriptPath)) {
96
+ if (!pathExists(scriptPath)) {
96
97
  log.warn({ hookDir, script: manifest.script }, 'Hook script not found, skipping');
97
98
  continue;
98
99
  }
@@ -1,4 +1,5 @@
1
- import { watch, existsSync, type FSWatcher } from 'node:fs';
1
+ import { watch, type FSWatcher } from 'node:fs';
2
+ import { pathExists } from '../util/fs.js';
2
3
  import { discoverHooks } from './discovery.js';
3
4
  import { runHookScript } from './runner.js';
4
5
  import { getLogger, isDebug } from '../util/logger.js';
@@ -49,7 +50,7 @@ export class HookManager {
49
50
  for (const hook of hooks) {
50
51
  try {
51
52
  const result = await runHookScript(hook, eventData);
52
- if (result.exitCode !== null && result.exitCode !== 0) {
53
+ if (result.exitCode != null && result.exitCode !== 0) {
53
54
  // Blocking hooks on pre-* events cancel the action
54
55
  if (isPreEvent && hook.manifest.blocking) {
55
56
  log.info({ hook: hook.name, event, exitCode: result.exitCode }, 'Blocking hook rejected action');
@@ -77,7 +78,7 @@ export class HookManager {
77
78
 
78
79
  watch(): void {
79
80
  const hooksDir = getHooksDir();
80
- if (!existsSync(hooksDir)) return;
81
+ if (!pathExists(hooksDir)) return;
81
82
 
82
83
  this.stopWatching();
83
84
 
@@ -1,6 +1,6 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { existsSync } from 'node:fs';
3
2
  import { basename, extname, join } from 'node:path';
3
+ import { pathExists } from '../util/fs.js';
4
4
  import { homedir } from 'node:os';
5
5
  import { getRootDir, getWorkspaceDir } from '../util/platform.js';
6
6
  import { getHookSettings } from './config.js';
@@ -24,7 +24,7 @@ function resolveBunPath(): string {
24
24
  if (found) return found;
25
25
 
26
26
  const fallback = join(homedir(), '.bun', 'bin', 'bun');
27
- if (existsSync(fallback)) return fallback;
27
+ if (pathExists(fallback)) return fallback;
28
28
 
29
29
  throw new Error(
30
30
  'Cannot find a bun runtime to execute .ts hooks. ' +
@@ -1,6 +1,6 @@
1
- import { existsSync, readdirSync, readFileSync, cpSync, chmodSync, rmSync } from 'node:fs';
1
+ import { readdirSync, readFileSync, cpSync, chmodSync, rmSync, type Dirent } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- import type { Dirent } from 'node:fs';
3
+ import { pathExists } from '../util/fs.js';
4
4
  import { getHooksDir } from '../util/platform.js';
5
5
  import { ensureHookInConfig } from './config.js';
6
6
  import { getLogger } from '../util/logger.js';
@@ -15,7 +15,7 @@ const log = getLogger('hooks-templates');
15
15
  */
16
16
  export function installTemplates(): void {
17
17
  const templatesDir = join(import.meta.dirname ?? __dirname, '../../hook-templates');
18
- if (!existsSync(templatesDir)) return;
18
+ if (!pathExists(templatesDir)) return;
19
19
 
20
20
  const hooksDir = getHooksDir();
21
21
  const entries = readdirSync(templatesDir, { withFileTypes: true }) as Dirent[];
@@ -24,7 +24,7 @@ export function installTemplates(): void {
24
24
  if (!entry.isDirectory()) continue;
25
25
 
26
26
  const targetDir = join(hooksDir, entry.name);
27
- if (existsSync(targetDir)) continue; // Never overwrite user hooks
27
+ if (pathExists(targetDir)) continue; // Never overwrite user hooks
28
28
 
29
29
  try {
30
30
  // Copy template directory
@@ -32,7 +32,7 @@ export function installTemplates(): void {
32
32
 
33
33
  // Make script executable
34
34
  const manifestPath = join(targetDir, 'hook.json');
35
- if (existsSync(manifestPath)) {
35
+ if (pathExists(manifestPath)) {
36
36
  const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
37
37
  if (manifest.script) {
38
38
  chmodSync(join(targetDir, manifest.script), 0o755);