@vellumai/assistant 0.8.1 → 0.8.2

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 (506) hide show
  1. package/ARCHITECTURE.md +2 -7
  2. package/Dockerfile +75 -1
  3. package/bun.lock +11 -1
  4. package/docker-entrypoint.sh +5 -0
  5. package/docker-init-apt-root.sh +94 -0
  6. package/docker-kata-apt-env.sh +39 -0
  7. package/docs/plugins.md +88 -47
  8. package/docs/skills.md +9 -7
  9. package/examples/plugins/echo/README.md +27 -27
  10. package/examples/plugins/echo/package.json +3 -0
  11. package/examples/plugins/echo/register.ts +31 -31
  12. package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
  13. package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
  14. package/openapi.yaml +325 -3
  15. package/package.json +3 -1
  16. package/scripts/generate-openapi.ts +83 -10
  17. package/scripts/sync-llm-catalog.ts +2 -2
  18. package/scripts/sync-web-search-catalog.ts +47 -25
  19. package/src/__tests__/agent-image-optimize.test.ts +11 -3
  20. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  21. package/src/__tests__/anthropic-provider.test.ts +45 -0
  22. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  23. package/src/__tests__/app-executors.test.ts +220 -4
  24. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  25. package/src/__tests__/bundled-asset.test.ts +6 -6
  26. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  27. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  28. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  29. package/src/__tests__/clawhub.test.ts +75 -16
  30. package/src/__tests__/compactor-tail-resolution.test.ts +41 -0
  31. package/src/__tests__/config-schema.test.ts +21 -0
  32. package/src/__tests__/config-set-route.test.ts +80 -0
  33. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  34. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  35. package/src/__tests__/context-search-conversations-source.test.ts +117 -2
  36. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  37. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  38. package/src/__tests__/context-token-estimator.test.ts +1 -0
  39. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  40. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  41. package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
  42. package/src/__tests__/conversation-agent-loop.test.ts +2 -0
  43. package/src/__tests__/conversation-error.test.ts +42 -3
  44. package/src/__tests__/conversation-fork-crud.test.ts +82 -0
  45. package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
  46. package/src/__tests__/conversation-lifecycle.test.ts +173 -0
  47. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  48. package/src/__tests__/conversation-pairing.test.ts +54 -0
  49. package/src/__tests__/conversation-process-callsite.test.ts +4 -1
  50. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  51. package/src/__tests__/conversation-queue.test.ts +4 -1
  52. package/src/__tests__/conversation-runtime-assembly.test.ts +76 -9
  53. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  54. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  55. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  56. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  57. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  58. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  59. package/src/__tests__/credential-security-invariants.test.ts +3 -2
  60. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  61. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  62. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  63. package/src/__tests__/dm-backfill.test.ts +121 -10
  64. package/src/__tests__/document-tool-security.test.ts +258 -0
  65. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  66. package/src/__tests__/edit-propagation.test.ts +33 -0
  67. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  68. package/src/__tests__/external-plugin-loader.test.ts +60 -36
  69. package/src/__tests__/filing-service.test.ts +140 -0
  70. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  71. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
  72. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  73. package/src/__tests__/helpers/wait-for.ts +21 -0
  74. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  75. package/src/__tests__/history-repair.test.ts +73 -0
  76. package/src/__tests__/host-app-control-proxy.test.ts +266 -10
  77. package/src/__tests__/image-credentials.test.ts +1 -1
  78. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  79. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
  80. package/src/__tests__/inference-profile-reaper.test.ts +4 -2
  81. package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
  82. package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
  83. package/src/__tests__/injector-chain.test.ts +10 -8
  84. package/src/__tests__/install-skill-routing.test.ts +155 -37
  85. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +92 -3
  86. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  87. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  88. package/src/__tests__/llm-catalog-parity.test.ts +55 -13
  89. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +34 -0
  90. package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
  91. package/src/__tests__/llm-usage-store.test.ts +114 -0
  92. package/src/__tests__/managed-profile-guard.test.ts +31 -29
  93. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  94. package/src/__tests__/managed-store.test.ts +84 -192
  95. package/src/__tests__/media-generate-image.test.ts +1 -1
  96. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  97. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  98. package/src/__tests__/oauth-commands-routes.test.ts +168 -16
  99. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  100. package/src/__tests__/openai-provider.test.ts +24 -0
  101. package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
  102. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  103. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  104. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +1 -1
  105. package/src/__tests__/platform.test.ts +2 -0
  106. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  107. package/src/__tests__/plugin-bootstrap.test.ts +10 -36
  108. package/src/__tests__/plugin-external-api.test.ts +68 -0
  109. package/src/__tests__/plugin-registry.test.ts +0 -77
  110. package/src/__tests__/plugin-route-contribution.test.ts +0 -1
  111. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  112. package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
  113. package/src/__tests__/plugin-types.test.ts +3 -13
  114. package/src/__tests__/process-message-background-slack.test.ts +8 -1
  115. package/src/__tests__/process-message-display-content.test.ts +421 -0
  116. package/src/__tests__/provider-catalog-visibility.test.ts +142 -0
  117. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  118. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +8 -8
  119. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  120. package/src/__tests__/schedule-routes.test.ts +50 -3
  121. package/src/__tests__/schedule-store.test.ts +94 -0
  122. package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
  123. package/src/__tests__/schema-transforms.test.ts +20 -0
  124. package/src/__tests__/search-skills-unified.test.ts +0 -5
  125. package/src/__tests__/server-history-render.test.ts +43 -0
  126. package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
  127. package/src/__tests__/skill-load-tool.test.ts +27 -89
  128. package/src/__tests__/skill-memory.test.ts +23 -3
  129. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  130. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  131. package/src/__tests__/skills-install-extract.test.ts +49 -38
  132. package/src/__tests__/skills-install-staging.test.ts +159 -0
  133. package/src/__tests__/skills-uninstall.test.ts +9 -41
  134. package/src/__tests__/skills.test.ts +51 -58
  135. package/src/__tests__/slack-channel-config.test.ts +9 -0
  136. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  137. package/src/__tests__/system-prompt.test.ts +737 -63
  138. package/src/__tests__/terminal-tools.test.ts +28 -1
  139. package/src/__tests__/thread-backfill.test.ts +557 -27
  140. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  141. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  142. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  143. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  144. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  145. package/src/__tests__/tool-executor.test.ts +16 -4
  146. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  147. package/src/__tests__/turn-events-store.test.ts +256 -0
  148. package/src/__tests__/twilio-routes.test.ts +4 -0
  149. package/src/__tests__/user-plugin-loader.test.ts +0 -7
  150. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  151. package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
  152. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
  153. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
  154. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  155. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  156. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  157. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  158. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  159. package/src/acp/resolve-agent.ts +1 -1
  160. package/src/agent/image-optimize.ts +13 -5
  161. package/src/calls/voice-session-bridge.ts +61 -42
  162. package/src/channels/types.ts +108 -0
  163. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  164. package/src/cli/commands/__tests__/changelog.test.ts +304 -319
  165. package/src/cli/commands/__tests__/schedules.test.ts +491 -0
  166. package/src/cli/commands/changelog.ts +106 -42
  167. package/src/cli/commands/conversations.ts +102 -17
  168. package/src/cli/commands/default-action.ts +10 -53
  169. package/src/cli/commands/notifications.ts +329 -317
  170. package/src/cli/commands/plugins.ts +185 -0
  171. package/src/cli/commands/schedules.ts +391 -0
  172. package/src/cli/commands/telemetry.ts +40 -0
  173. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  174. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  175. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  176. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  177. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  178. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  179. package/src/cli/lib/cli-colors.ts +12 -0
  180. package/src/cli/lib/confirm-prompt.ts +79 -0
  181. package/src/cli/lib/install-from-github.ts +304 -0
  182. package/src/cli/lib/list-installed-plugins.ts +137 -0
  183. package/src/cli/lib/uninstall-plugin.ts +82 -0
  184. package/src/cli/lib/unknown-command.ts +111 -0
  185. package/src/cli/program.ts +38 -2
  186. package/src/config/bundled-skills/app-builder/SKILL.md +23 -21
  187. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  188. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  189. package/src/config/bundled-skills/document/SKILL.md +23 -3
  190. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  191. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  192. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  193. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  194. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  195. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  196. package/src/config/bundled-tool-registry.ts +6 -0
  197. package/src/config/feature-flag-registry.json +41 -1
  198. package/src/config/loader.ts +64 -38
  199. package/src/config/schema.ts +7 -10
  200. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  201. package/src/config/schemas/channels.ts +8 -0
  202. package/src/config/schemas/compaction.ts +28 -0
  203. package/src/config/schemas/heartbeat.ts +9 -0
  204. package/src/config/schemas/llm-request-logs.ts +31 -7
  205. package/src/config/schemas/llm.ts +3 -0
  206. package/src/config/schemas/memory-retrieval.ts +18 -0
  207. package/src/config/schemas/tools.ts +14 -0
  208. package/src/config/skills.ts +3 -96
  209. package/src/context/compactor.ts +1047 -0
  210. package/src/context/token-estimator.ts +2 -2
  211. package/src/context/window-manager.ts +197 -1520
  212. package/src/credential-execution/managed-catalog.ts +37 -0
  213. package/src/credential-health/credential-health-service.ts +280 -19
  214. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +34 -0
  215. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  216. package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
  217. package/src/daemon/approval-generators.ts +8 -6
  218. package/src/daemon/config-watcher.ts +94 -31
  219. package/src/daemon/conversation-agent-loop.ts +169 -9
  220. package/src/daemon/conversation-error.ts +171 -37
  221. package/src/daemon/conversation-lifecycle.ts +53 -40
  222. package/src/daemon/conversation-messaging.ts +25 -6
  223. package/src/daemon/conversation-process.ts +49 -12
  224. package/src/daemon/conversation-runtime-assembly.ts +16 -1
  225. package/src/daemon/conversation-slash.ts +12 -5
  226. package/src/daemon/conversation-store.ts +11 -4
  227. package/src/daemon/conversation-tool-setup.ts +39 -7
  228. package/src/daemon/conversation.ts +33 -1
  229. package/src/daemon/external-plugins-bootstrap.ts +217 -181
  230. package/src/daemon/first-greeting.ts +22 -2
  231. package/src/daemon/handlers/config-model.ts +6 -5
  232. package/src/daemon/handlers/config-slack-channel.ts +15 -3
  233. package/src/daemon/handlers/shared.ts +14 -5
  234. package/src/daemon/handlers/skills.ts +111 -108
  235. package/src/daemon/history-repair.ts +28 -1
  236. package/src/daemon/host-app-control-proxy.ts +98 -23
  237. package/src/daemon/lifecycle.ts +45 -35
  238. package/src/daemon/meet-host-supervisor.ts +5 -4
  239. package/src/daemon/memory-v2-startup.ts +49 -0
  240. package/src/daemon/message-protocol.ts +1 -0
  241. package/src/daemon/message-types/conversations.ts +25 -0
  242. package/src/daemon/message-types/messages.ts +61 -0
  243. package/src/daemon/message-types/subagents.ts +1 -0
  244. package/src/daemon/message-types/sync.ts +1 -0
  245. package/src/daemon/pkb-reminder-builder.test.ts +1 -1
  246. package/src/daemon/pkb-reminder-builder.ts +1 -1
  247. package/src/daemon/plugin-source-watcher.ts +146 -0
  248. package/src/daemon/process-message.ts +21 -3
  249. package/src/daemon/server.ts +11 -2
  250. package/src/daemon/skill-memory-refresh.ts +29 -0
  251. package/src/documents/document-store.ts +221 -3
  252. package/src/embedded/plugin-api.ts +40 -0
  253. package/src/filing/filing-service.ts +39 -0
  254. package/src/heartbeat/__tests__/heartbeat-service.test.ts +91 -6
  255. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  256. package/src/heartbeat/heartbeat-service.ts +41 -0
  257. package/src/home/__tests__/feed-types.test.ts +40 -0
  258. package/src/home/feed-types.ts +22 -0
  259. package/src/home/post-connect-feed.ts +1 -0
  260. package/src/index.ts +18 -1
  261. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  262. package/src/mcp/client.ts +20 -4
  263. package/src/media/image-credentials.ts +3 -3
  264. package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
  265. package/src/memory/__tests__/conversation-queries.test.ts +263 -0
  266. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  267. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
  268. package/src/memory/__tests__/message-content.test.ts +35 -0
  269. package/src/memory/bookmark-crud.ts +42 -10
  270. package/src/memory/context-search/sources/conversations.ts +62 -2
  271. package/src/memory/context-search/sources/workspace.ts +4 -0
  272. package/src/memory/conversation-crud.ts +63 -19
  273. package/src/memory/conversation-queries.ts +110 -10
  274. package/src/memory/db-init.ts +6 -0
  275. package/src/memory/delivery-crud.ts +152 -5
  276. package/src/memory/embedding-backend.ts +4 -4
  277. package/src/memory/external-conversation-store.ts +66 -5
  278. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +66 -9
  279. package/src/memory/graph/conversation-graph-memory.ts +31 -15
  280. package/src/memory/graph/tools.ts +3 -3
  281. package/src/memory/indexer.ts +34 -29
  282. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
  283. package/src/memory/jobs/embed-concept-page.ts +20 -11
  284. package/src/memory/jobs-worker.ts +6 -1
  285. package/src/memory/llm-request-log-source-clickhouse.ts +17 -10
  286. package/src/memory/llm-request-log-source.ts +19 -52
  287. package/src/memory/llm-usage-store.ts +125 -5
  288. package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
  289. package/src/memory/message-content.ts +1 -1
  290. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  291. package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
  292. package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
  293. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  294. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  295. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  296. package/src/memory/migrations/index.ts +6 -0
  297. package/src/memory/migrations/registry.ts +8 -0
  298. package/src/memory/onboarding-events-store.ts +106 -0
  299. package/src/memory/schema/bookmarks.ts +0 -2
  300. package/src/memory/schema/calls.ts +1 -0
  301. package/src/memory/schema/inference.ts +1 -3
  302. package/src/memory/schema/infrastructure.ts +12 -0
  303. package/src/memory/turn-events-store.ts +127 -2
  304. package/src/memory/v2/__tests__/activation.test.ts +0 -8
  305. package/src/memory/v2/__tests__/injection.test.ts +98 -8
  306. package/src/memory/v2/__tests__/migration.test.ts +87 -0
  307. package/src/memory/v2/__tests__/page-index.test.ts +83 -0
  308. package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
  309. package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
  310. package/src/memory/v2/__tests__/router.test.ts +15 -0
  311. package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
  312. package/src/memory/v2/injection.ts +32 -6
  313. package/src/memory/v2/migration.ts +49 -19
  314. package/src/memory/v2/page-index.ts +35 -5
  315. package/src/memory/v2/prompts/router.ts +11 -8
  316. package/src/memory/v2/prompts/sweep.ts +2 -2
  317. package/src/memory/v2/qdrant.ts +135 -7
  318. package/src/memory/v2/router.ts +9 -8
  319. package/src/memory/v2/skill-store.ts +120 -35
  320. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  321. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  322. package/src/messaging/providers/slack/adapter.ts +43 -5
  323. package/src/messaging/providers/slack/client.ts +27 -0
  324. package/src/messaging/providers/slack/deep-link.ts +65 -0
  325. package/src/messaging/providers/slack/download.ts +104 -0
  326. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  327. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  328. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  329. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  330. package/src/messaging/providers/slack/types.ts +20 -1
  331. package/src/notifications/conversation-pairing.ts +2 -1
  332. package/src/notifications/decision-engine.ts +2 -1
  333. package/src/notifications/emit-signal.ts +20 -1
  334. package/src/notifications/home-feed-side-effect.ts +54 -0
  335. package/src/notifications/signal.ts +3 -1
  336. package/src/oauth/connection-resolver.ts +8 -4
  337. package/src/oauth/platform-connection.ts +6 -2
  338. package/src/oauth/seed-providers.ts +10 -1
  339. package/src/permissions/checker.ts +2 -0
  340. package/src/permissions/ipc-risk-types.ts +1 -0
  341. package/src/permissions/question-prompter.test.ts +416 -0
  342. package/src/permissions/question-prompter.ts +294 -0
  343. package/src/platform/client.test.ts +1 -1
  344. package/src/platform/client.ts +1 -1
  345. package/src/plugin-api/constants.ts +26 -0
  346. package/src/plugin-api/index.ts +34 -1
  347. package/src/plugin-api/types.ts +104 -22
  348. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  349. package/src/plugins/defaults/compaction.ts +0 -4
  350. package/src/plugins/defaults/empty-response.ts +0 -2
  351. package/src/plugins/defaults/history-repair.ts +0 -2
  352. package/src/plugins/defaults/injectors.ts +36 -3
  353. package/src/plugins/defaults/llm-call.ts +0 -2
  354. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  355. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  356. package/src/plugins/defaults/persistence.ts +0 -2
  357. package/src/plugins/defaults/title-generate.ts +0 -5
  358. package/src/plugins/defaults/token-estimate.ts +0 -2
  359. package/src/plugins/defaults/tool-error.ts +0 -7
  360. package/src/plugins/defaults/tool-execute.ts +0 -2
  361. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  362. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  363. package/src/plugins/external-api.ts +104 -0
  364. package/src/plugins/external-plugin-loader.ts +105 -32
  365. package/src/plugins/feature-gate.ts +22 -0
  366. package/src/plugins/pipeline.ts +37 -0
  367. package/src/plugins/registry.ts +48 -80
  368. package/src/plugins/types.ts +31 -26
  369. package/src/plugins/user-loader.ts +21 -2
  370. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  371. package/src/proactive-artifact/job.test.ts +37 -5
  372. package/src/prompts/__tests__/system-prompt.test.ts +12 -0
  373. package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
  374. package/src/prompts/normalize-onboarding.ts +27 -0
  375. package/src/prompts/sections.ts +302 -0
  376. package/src/prompts/system-prompt.ts +63 -166
  377. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  378. package/src/prompts/templates/system-sections.ts +173 -0
  379. package/src/providers/__tests__/inference.test.ts +22 -7
  380. package/src/providers/anthropic/client.ts +28 -28
  381. package/src/providers/connection-resolution.ts +7 -0
  382. package/src/providers/inference/adapter-factory.ts +41 -4
  383. package/src/providers/inference/connections.ts +74 -29
  384. package/src/providers/inference/resolve-auth.ts +12 -4
  385. package/src/providers/model-catalog.ts +294 -12
  386. package/src/providers/openai/chat-completions-provider.ts +10 -2
  387. package/src/providers/openrouter/client.ts +7 -0
  388. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
  389. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  390. package/src/providers/provider-availability.ts +17 -2
  391. package/src/providers/provider-catalog-visibility.ts +36 -0
  392. package/src/providers/registry.ts +22 -14
  393. package/src/providers/retry.ts +47 -1
  394. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  395. package/src/runtime/agent-wake.ts +42 -14
  396. package/src/runtime/auth/route-policy.ts +8 -1
  397. package/src/runtime/btw-sidechain.ts +2 -0
  398. package/src/runtime/http-types.ts +19 -0
  399. package/src/runtime/migrations/origin-mode.ts +1 -1
  400. package/src/runtime/pending-interactions.ts +1 -0
  401. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
  402. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
  403. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +107 -20
  404. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  405. package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
  406. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  407. package/src/runtime/routes/acp-routes.ts +5 -3
  408. package/src/runtime/routes/auth-routes.ts +1 -1
  409. package/src/runtime/routes/bookmark-routes.ts +5 -3
  410. package/src/runtime/routes/btw-routes.ts +5 -1
  411. package/src/runtime/routes/channel-availability-routes.ts +121 -0
  412. package/src/runtime/routes/conversation-cli-routes.ts +44 -3
  413. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  414. package/src/runtime/routes/conversation-management-routes.ts +17 -42
  415. package/src/runtime/routes/conversation-query-routes.ts +40 -35
  416. package/src/runtime/routes/conversation-routes.ts +90 -11
  417. package/src/runtime/routes/documents-routes.ts +25 -86
  418. package/src/runtime/routes/group-routes.ts +5 -0
  419. package/src/runtime/routes/inbound-conversation.ts +28 -8
  420. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  421. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
  422. package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
  423. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  424. package/src/runtime/routes/index.ts +6 -0
  425. package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
  426. package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
  427. package/src/runtime/routes/inference-provider-connection-routes.ts +65 -21
  428. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  429. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  430. package/src/runtime/routes/integrations/twilio.ts +6 -13
  431. package/src/runtime/routes/notification-routes.ts +1 -1
  432. package/src/runtime/routes/oauth-commands-routes.ts +105 -15
  433. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  434. package/src/runtime/routes/question-routes.ts +259 -0
  435. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  436. package/src/runtime/routes/schedule-routes.ts +4 -7
  437. package/src/runtime/routes/subagents-routes.ts +57 -18
  438. package/src/runtime/routes/telemetry-routes.ts +27 -0
  439. package/src/runtime/routes/tts-routes.ts +27 -2
  440. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  441. package/src/runtime/routes/workspace-routes.ts +28 -0
  442. package/src/runtime/services/conversation-serializer.ts +39 -7
  443. package/src/runtime/sync/resource-sync-events.ts +93 -1
  444. package/src/schedule/schedule-store.ts +27 -2
  445. package/src/schedule/scheduler.ts +9 -1
  446. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  447. package/src/security/untrusted-content.ts +93 -8
  448. package/src/skills/catalog-files.ts +1 -1
  449. package/src/skills/catalog-install.ts +233 -116
  450. package/src/skills/clawhub.ts +70 -13
  451. package/src/skills/managed-store.ts +4 -119
  452. package/src/skills/skillssh-registry.ts +27 -48
  453. package/src/subagent/manager.ts +15 -7
  454. package/src/telemetry/types.ts +113 -1
  455. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  456. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  457. package/src/tools/apps/executors.ts +58 -7
  458. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  459. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  460. package/src/tools/browser/browser-execution.ts +15 -11
  461. package/src/tools/computer-use/definitions.ts +3 -3
  462. package/src/tools/credentials/vault.ts +1 -1
  463. package/src/tools/document/document-tool.ts +124 -1
  464. package/src/tools/filesystem/edit.ts +1 -1
  465. package/src/tools/filesystem/list.ts +1 -1
  466. package/src/tools/filesystem/read.ts +1 -1
  467. package/src/tools/filesystem/write.ts +5 -2
  468. package/src/tools/host-filesystem/transfer.ts +1 -1
  469. package/src/tools/host-terminal/host-shell.ts +1 -1
  470. package/src/tools/permission-checker.ts +1 -1
  471. package/src/tools/registry.ts +17 -7
  472. package/src/tools/schedule/create.ts +2 -2
  473. package/src/tools/schema-transforms.ts +7 -2
  474. package/src/tools/side-effects.ts +1 -0
  475. package/src/tools/skills/delete-managed.ts +4 -4
  476. package/src/tools/skills/execute.ts +1 -1
  477. package/src/tools/skills/scaffold-managed.ts +3 -2
  478. package/src/tools/subagent/notify-parent.ts +1 -1
  479. package/src/tools/system/request-permission.ts +2 -2
  480. package/src/tools/terminal/safe-env.ts +60 -1
  481. package/src/tools/tool-manifest.ts +2 -0
  482. package/src/tools/types.ts +72 -21
  483. package/src/tools/ui-surface/definitions.ts +6 -5
  484. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  485. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  486. package/src/types/onboarding-context.ts +2 -0
  487. package/src/util/errors.ts +17 -0
  488. package/src/util/platform.ts +10 -0
  489. package/src/watcher/__tests__/engine.test.ts +22 -0
  490. package/src/watcher/engine.ts +6 -2
  491. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
  492. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
  493. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
  494. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  495. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  496. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  497. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  498. package/src/workspace/migrations/registry.ts +8 -0
  499. package/src/workspace/migrations/runner.ts +39 -9
  500. package/src/workspace/migrations/types.ts +4 -0
  501. package/examples/plugins/echo/bun.lock +0 -25
  502. package/src/__tests__/context-window-manager.test.ts +0 -2481
  503. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  504. package/src/context/prompts/compact.md +0 -26
  505. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  506. /package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +0 -0
@@ -2,7 +2,6 @@ import { randomUUID } from "node:crypto";
2
2
  import {
3
3
  existsSync,
4
4
  mkdirSync,
5
- readFileSync,
6
5
  renameSync,
7
6
  rmSync,
8
7
  writeFileSync,
@@ -43,10 +42,6 @@ function getManagedSkillDir(id: string): string {
43
42
  return join(getManagedSkillsDir(), id);
44
43
  }
45
44
 
46
- function getSkillsIndexPath(): string {
47
- return join(getManagedSkillsDir(), "SKILLS.md");
48
- }
49
-
50
45
  // ─── SKILL.md generation ─────────────────────────────────────────────────────
51
46
 
52
47
  interface BuildSkillMarkdownInput {
@@ -106,91 +101,12 @@ function atomicWriteFile(filePath: string, content: string): void {
106
101
  renameSync(tmpPath, filePath);
107
102
  }
108
103
 
109
- // ─── SKILLS.md index management ──────────────────────────────────────────────
110
-
111
- function readIndexLines(): string[] {
112
- const indexPath = getSkillsIndexPath();
113
- if (!existsSync(indexPath)) return [];
114
- return readFileSync(indexPath, "utf-8").split("\n");
115
- }
116
-
117
- function writeIndexLines(lines: string[]): void {
118
- const content = lines.join("\n");
119
- atomicWriteFile(
120
- getSkillsIndexPath(),
121
- content.endsWith("\n") ? content : content + "\n",
122
- );
123
- }
124
-
125
- function indexEntryRegex(id: string): RegExp {
126
- const escaped = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
127
- // Match both - and * bullets, optional backticks, optional markdown link wrapping,
128
- // and optional /SKILL.md suffix (inside or outside link parens)
129
- return new RegExp(
130
- `^[-*]\\s+(?:\`)?(?:\\[.*?\\]\\()?${escaped}(?:/SKILL\\.md)?(?:\\))?(?:\`)?\\s*$`,
131
- );
132
- }
133
-
134
- export function upsertSkillsIndexEntry(id: string): void {
135
- const lines = readIndexLines();
136
- const pattern = indexEntryRegex(id);
137
- if (lines.some((line) => pattern.test(line))) {
138
- return; // already present
139
- }
140
- // Append new entry
141
- const nonEmpty = lines.filter((l) => l.trim());
142
- nonEmpty.push(`- ${id}`);
143
- writeIndexLines(nonEmpty);
144
- log.info({ id }, "Added managed skill to SKILLS.md index");
145
- }
146
-
147
- export function removeSkillsIndexEntry(id: string): void {
148
- const lines = readIndexLines();
149
- const pattern = indexEntryRegex(id);
150
- const filtered = lines.filter((line) => !pattern.test(line));
151
- if (filtered.length === lines.length) {
152
- return; // not found
153
- }
154
- writeIndexLines(filtered.filter((l) => l.trim()));
155
- log.info({ id }, "Removed managed skill from SKILLS.md index");
156
- }
157
-
158
104
  // ─── Version metadata ─────────────────────────────────────────────────────────
159
105
 
160
- interface SkillVersionMeta {
161
- version: string;
162
- installedAt: string;
163
- }
164
-
165
106
  function getVersionMetaPath(id: string): string {
166
107
  return join(getManagedSkillDir(id), "version.json");
167
108
  }
168
109
 
169
- export function readSkillVersion(id: string): string | null {
170
- // Try install-meta.json first (new format)
171
- const installMetaPath = join(getManagedSkillDir(id), "install-meta.json");
172
- if (existsSync(installMetaPath)) {
173
- try {
174
- const raw = readFileSync(installMetaPath, "utf-8");
175
- const meta = JSON.parse(raw) as { version?: string };
176
- if (meta.version) return meta.version;
177
- } catch {
178
- // Fall through to legacy path
179
- }
180
- }
181
-
182
- // Fall back to legacy version.json
183
- const metaPath = getVersionMetaPath(id);
184
- if (!existsSync(metaPath)) return null;
185
- try {
186
- const raw = readFileSync(metaPath, "utf-8");
187
- const meta: SkillVersionMeta = JSON.parse(raw);
188
- return meta.version ?? null;
189
- } catch {
190
- return null;
191
- }
192
- }
193
-
194
110
  // ─── Create / Delete ─────────────────────────────────────────────────────────
195
111
 
196
112
  interface CreateManagedSkillParams {
@@ -200,7 +116,6 @@ interface CreateManagedSkillParams {
200
116
  bodyMarkdown: string;
201
117
  emoji?: string;
202
118
  overwrite?: boolean;
203
- addToIndex?: boolean;
204
119
  includes?: string[];
205
120
  version?: string;
206
121
  contactId?: string;
@@ -209,7 +124,6 @@ interface CreateManagedSkillParams {
209
124
  interface CreateManagedSkillResult {
210
125
  created: boolean;
211
126
  path: string;
212
- indexUpdated: boolean;
213
127
  error?: string;
214
128
  }
215
129
 
@@ -221,7 +135,6 @@ export function createManagedSkill(
221
135
  return {
222
136
  created: false,
223
137
  path: "",
224
- indexUpdated: false,
225
138
  error: validationError,
226
139
  };
227
140
  }
@@ -230,7 +143,6 @@ export function createManagedSkill(
230
143
  return {
231
144
  created: false,
232
145
  path: "",
233
- indexUpdated: false,
234
146
  error: "name is required",
235
147
  };
236
148
  }
@@ -238,7 +150,6 @@ export function createManagedSkill(
238
150
  return {
239
151
  created: false,
240
152
  path: "",
241
- indexUpdated: false,
242
153
  error: "description is required",
243
154
  };
244
155
  }
@@ -250,7 +161,6 @@ export function createManagedSkill(
250
161
  return {
251
162
  created: false,
252
163
  path: skillFilePath,
253
- indexUpdated: false,
254
164
  error: `Managed skill "${params.id}" already exists. Set overwrite=true to replace it.`,
255
165
  };
256
166
  }
@@ -285,35 +195,24 @@ export function createManagedSkill(
285
195
  "Created managed skill",
286
196
  );
287
197
 
288
- let indexUpdated = false;
289
- if (params.addToIndex !== false) {
290
- upsertSkillsIndexEntry(params.id);
291
- indexUpdated = true;
292
- }
293
-
294
- return { created: true, path: skillFilePath, indexUpdated };
198
+ return { created: true, path: skillFilePath };
295
199
  }
296
200
 
297
201
  interface DeleteManagedSkillResult {
298
202
  deleted: boolean;
299
- indexUpdated: boolean;
300
203
  error?: string;
301
204
  }
302
205
 
303
- export function deleteManagedSkill(
304
- id: string,
305
- removeFromIndex = true,
306
- ): DeleteManagedSkillResult {
206
+ export function deleteManagedSkill(id: string): DeleteManagedSkillResult {
307
207
  const validationError = validateManagedSkillId(id);
308
208
  if (validationError) {
309
- return { deleted: false, indexUpdated: false, error: validationError };
209
+ return { deleted: false, error: validationError };
310
210
  }
311
211
 
312
212
  const skillDir = getManagedSkillDir(id);
313
213
  if (!existsSync(skillDir)) {
314
214
  return {
315
215
  deleted: false,
316
- indexUpdated: false,
317
216
  error: `Managed skill "${id}" not found`,
318
217
  };
319
218
  }
@@ -322,19 +221,5 @@ export function deleteManagedSkill(
322
221
  deleteSkillCapabilityNode(id);
323
222
  log.info({ id, path: skillDir }, "Deleted managed skill");
324
223
 
325
- let indexUpdated = false;
326
- if (removeFromIndex) {
327
- try {
328
- removeSkillsIndexEntry(id);
329
- indexUpdated = true;
330
- } catch (err) {
331
- // Best-effort: skill dir is already gone, don't fail the whole delete
332
- log.warn(
333
- { id, err },
334
- "Failed to update skills index after deleting managed skill",
335
- );
336
- }
337
- }
338
-
339
- return { deleted: true, indexUpdated };
224
+ return { deleted: true };
340
225
  }
@@ -1,10 +1,13 @@
1
- import { execSync } from "node:child_process";
2
- import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
3
- import { homedir } from "node:os";
4
- import { dirname, join, resolve, sep } from "node:path";
1
+ import { existsSync, rmSync } from "node:fs";
2
+ import { join } from "node:path";
5
3
 
6
4
  import { getWorkspaceSkillsDir } from "../util/platform.js";
7
- import { upsertSkillsIndex } from "./catalog-install.js";
5
+ import {
6
+ commitStagedSkillInstall,
7
+ createSkillInstallStagingDir,
8
+ installSkillDependenciesIfPresent,
9
+ writeSkillFilesToDir,
10
+ } from "./catalog-install.js";
8
11
  import { computeSkillHash, writeInstallMeta } from "./install-meta.js";
9
12
  import type {
10
13
  AuditResponse,
@@ -421,10 +424,10 @@ export function validateSkillSlug(slug: string): void {
421
424
  *
422
425
  * 1. Validates the skill slug for path safety
423
426
  * 2. Fetches all files from `skills/<skillSlug>/` in the source repo
424
- * 3. Writes them to `<workspace>/skills/<skillSlug>/` with path traversal protection
427
+ * 3. Writes them to a non-discovered staging dir with path traversal protection
425
428
  * 4. Writes `install-meta.json` with origin metadata
426
429
  * 5. Installs npm dependencies (if package.json exists)
427
- * 6. Updates SKILLS.md index
430
+ * 6. Atomically swaps the staged skill into `<workspace>/skills/<skillSlug>/`
428
431
  *
429
432
  * Auto-enable and memory seeding are handled by the caller (e.g.
430
433
  * `postInstallSkill()` in the daemon, or left to the user for CLI installs).
@@ -451,47 +454,23 @@ export async function installExternalSkill(
451
454
 
452
455
  const files = await fetchSkillFromGitHub(owner, repo, skillSlug, ref);
453
456
 
454
- // Clear existing directory on overwrite to remove stale files
455
- if (overwrite && existsSync(skillDir)) {
456
- rmSync(skillDir, { recursive: true, force: true });
457
- }
458
- mkdirSync(skillDir, { recursive: true });
459
-
460
- // Write files with path traversal protection (follows extractTarToDir pattern)
461
- for (const [filename, content] of Object.entries(files)) {
462
- const normalized = filename.replace(/\\/g, "/").replace(/^\.\/+/g, "");
463
- if (!normalized || normalized.includes("..") || normalized.startsWith("/"))
464
- continue;
465
- const destPath = resolve(skillDir, normalized);
466
- if (
467
- !destPath.startsWith(resolve(skillDir) + sep) &&
468
- destPath !== resolve(skillDir)
469
- )
470
- continue;
471
- mkdirSync(dirname(destPath), { recursive: true });
472
- writeFileSync(destPath, content, "utf-8");
473
- }
474
-
475
- // Write install metadata
476
- writeInstallMeta(skillDir, {
477
- origin: "skillssh",
478
- slug: skillSlug,
479
- sourceRepo: `${owner}/${repo}`,
480
- installedAt: new Date().toISOString(),
481
- ...(contactId ? { installedBy: contactId } : {}),
482
- contentHash: computeSkillHash(skillDir) ?? undefined,
483
- });
484
-
485
- // Post-install: install dependencies first, then index the skill.
486
- // Running bun install before upsertSkillsIndex ensures we don't index a
487
- // skill whose dependencies failed to install.
488
- if (existsSync(join(skillDir, "package.json"))) {
489
- const bunPath = `${homedir()}/.bun/bin`;
490
- execSync("bun install", {
491
- cwd: skillDir,
492
- stdio: "inherit",
493
- env: { ...process.env, PATH: `${bunPath}:${process.env.PATH}` },
457
+ const stagedDir = createSkillInstallStagingDir();
458
+ try {
459
+ writeSkillFilesToDir(files, stagedDir);
460
+
461
+ writeInstallMeta(stagedDir, {
462
+ origin: "skillssh",
463
+ slug: skillSlug,
464
+ sourceRepo: `${owner}/${repo}`,
465
+ installedAt: new Date().toISOString(),
466
+ ...(contactId ? { installedBy: contactId } : {}),
467
+ contentHash: computeSkillHash(stagedDir) ?? undefined,
494
468
  });
469
+
470
+ installSkillDependenciesIfPresent(stagedDir);
471
+ commitStagedSkillInstall(skillSlug, stagedDir);
472
+ } catch (err) {
473
+ rmSync(stagedDir, { recursive: true, force: true });
474
+ throw err;
495
475
  }
496
- upsertSkillsIndex(skillSlug);
497
476
  }
@@ -19,7 +19,9 @@ import { bootstrapConversation } from "../memory/conversation-bootstrap.js";
19
19
  import { wrapWithCallSiteRouting } from "../providers/call-site-routing.js";
20
20
  import { resolveDefaultProvider } from "../providers/connection-resolution.js";
21
21
  import { RateLimitProvider } from "../providers/ratelimit.js";
22
+ import { listProviders } from "../providers/registry.js";
22
23
  import { createAbortReason } from "../util/abort-reasons.js";
24
+ import { ProviderNotConfiguredError } from "../util/errors.js";
23
25
  import { getLogger } from "../util/logger.js";
24
26
  import { getSandboxWorkingDir } from "../util/platform.js";
25
27
  import {
@@ -112,6 +114,7 @@ export interface SubagentNotificationInfo {
112
114
  status: "running" | "completed" | "failed" | "aborted";
113
115
  error?: string;
114
116
  conversationId?: string;
117
+ objective?: string;
115
118
  }
116
119
 
117
120
  export class SubagentManager {
@@ -185,14 +188,14 @@ export class SubagentManager {
185
188
  // Connection-aware default-provider resolution. Throws
186
189
  // `ConnectionResolutionError` if `llm.default.provider_connection` is
187
190
  // unset or the connection row is missing/mismatched (config bugs).
188
- // Returns null on soft credential failures (vault miss, transient
189
- // auth) — handled below as "no provider available". Per-call
190
- // `callSite` routing is layered next.
191
+ // Returns null on soft credential failures (missing credential,
192
+ // platform auth unavailable).
191
193
  const baseProvider = await resolveDefaultProvider(appConfig);
192
194
  if (!baseProvider) {
193
- throw new Error(
194
- `Subagent: default provider '${resolveCallSiteConfig("mainAgent", appConfig.llm).provider}' is not registered`,
195
- );
195
+ const resolved = resolveCallSiteConfig("mainAgent", appConfig.llm);
196
+ throw new ProviderNotConfiguredError(resolved.provider, listProviders(), {
197
+ connectionName: resolved.provider_connection,
198
+ });
196
199
  }
197
200
  // Per-call `options.config.callSite` (e.g. `subagentSpawn`) can resolve
198
201
  // to a profile that differs from `llm.default`. The shared wrapper
@@ -230,7 +233,10 @@ export class SubagentManager {
230
233
  config.systemPromptOverride ??
231
234
  buildSubagentSystemPrompt({ ...config, id: subagentId }, role);
232
235
  }
233
- const maxTokens = resolveCallSiteConfig("subagentSpawn", appConfig.llm).maxTokens;
236
+ const maxTokens = resolveCallSiteConfig(
237
+ "subagentSpawn",
238
+ appConfig.llm,
239
+ ).maxTokens;
234
240
  const workingDir = getSandboxWorkingDir();
235
241
 
236
242
  // ── Initialise state ────────────────────────────────────────────
@@ -270,6 +276,7 @@ export class SubagentManager {
270
276
  managed.parentSendToClient({
271
277
  type: "subagent_event",
272
278
  subagentId,
279
+ conversationId: config.parentConversationId,
273
280
  event: msg,
274
281
  } as ServerMessage);
275
282
  };
@@ -946,6 +953,7 @@ export class SubagentManager {
946
953
  label: config.label,
947
954
  status: outcome,
948
955
  conversationId: managed.state.conversationId,
956
+ objective: config.objective,
949
957
  ...(outcome === "failed"
950
958
  ? { error: managed.state.error ?? "Unknown error" }
951
959
  : {}),
@@ -11,6 +11,27 @@ export interface TelemetryEventBase {
11
11
  /** LLM usage event — one per provider API call. */
12
12
  export interface LlmUsageTelemetryEvent extends TelemetryEventBase {
13
13
  type: "llm_usage";
14
+ /**
15
+ * Parent conversation id. Null for LLM calls not tied to a conversation
16
+ * (memory consolidation, background embedding work, etc.).
17
+ */
18
+ conversation_id: string | null;
19
+ /**
20
+ * Type of the parent conversation (`"standard"` / `"background"` /
21
+ * `"scheduled"`). Null when `conversation_id` is null. Daemons predating
22
+ * this field send no value; downstream consumers treat missing/null as
23
+ * `"standard"` to preserve back-compat during rollout.
24
+ */
25
+ conversation_type: string | null;
26
+ /**
27
+ * 1-indexed position of the user turn this LLM call belongs to within
28
+ * the parent conversation, counting only real user turns (tool-result
29
+ * rows persisted with role="user" are excluded — same filter as the
30
+ * `turn` event stream). Computed as the count of user messages with
31
+ * `created_at <= this_event.created_at`. Null when the LLM call isn't
32
+ * tied to a conversation, or when no user turn has occurred yet.
33
+ */
34
+ turn_index: number | null;
14
35
  provider: string;
15
36
  model: string;
16
37
  input_tokens: number;
@@ -25,9 +46,87 @@ export interface LlmUsageTelemetryEvent extends TelemetryEventBase {
25
46
  cost: number | null;
26
47
  }
27
48
 
49
+ /**
50
+ * Optional client metadata bag carried on `TurnTelemetryEvent.client`.
51
+ * Sourced from `messages.metadata.client`, which is populated by HTTP
52
+ * header middleware reading `x-vellum-browser-family`,
53
+ * `x-vellum-browser-version`, `x-vellum-client-os`,
54
+ * `x-vellum-interface-version`. Extensible without a schema change —
55
+ * lives entirely in the JSON metadata column.
56
+ */
57
+ export interface TurnTelemetryClientInfo {
58
+ /** Browser family for `web`/`chrome-extension` interfaces: `"chrome"|"safari"|"firefox"|"edge"`. */
59
+ browser_family?: string;
60
+ /** Major browser version only (`"124"`, not the full UA string). */
61
+ browser_version?: string;
62
+ /**
63
+ * User's operating system at message time. For `web`/`chrome-extension`
64
+ * this comes from `navigator.userAgentData`; for `macos`/`ios` it's
65
+ * implicit from the interface, but clients may still send it explicitly.
66
+ */
67
+ os?: string;
68
+ /**
69
+ * Version of the surface app/client (`"0.8.2"` for the macOS app,
70
+ * web client SHA, etc.) — distinct from `assistant_version` on the
71
+ * batch envelope, which identifies the daemon. A user can be on an
72
+ * older surface than the daemon (or vice versa, on web).
73
+ */
74
+ interface_version?: string;
75
+ }
76
+
28
77
  /** Turn event — one per user message. */
29
78
  export interface TurnTelemetryEvent extends TelemetryEventBase {
30
79
  type: "turn";
80
+ /**
81
+ * Parent conversation id. Lets analytics group turns by conversation
82
+ * (e.g. avg turns per conversation, time-to-first-completion).
83
+ */
84
+ conversation_id: string;
85
+ /**
86
+ * Type of the parent conversation. Lets analytics distinguish
87
+ * user-initiated turns (`"standard"`) from system-generated prompts
88
+ * in `"background"` / `"scheduled"` conversations. Daemons predating
89
+ * this field send no value; downstream consumers should treat a
90
+ * missing value as `"standard"` to preserve DAU during rollout.
91
+ */
92
+ conversation_type: string;
93
+ /**
94
+ * 1-indexed position of this user turn within the parent conversation,
95
+ * counting only real user turns (tool-result rows persisted with
96
+ * role="user" are excluded — same filter as the turn-event eligibility
97
+ * predicate). The first user turn in a conversation is `1`.
98
+ */
99
+ turn_index: number;
100
+ /**
101
+ * Canonical `InterfaceId` enum value identifying the UI surface the
102
+ * user was interacting from when this turn was created (`"macos"`,
103
+ * `"ios"`, `"cli"`, `"web"`, `"chrome-extension"`, `"slack"`,
104
+ * `"telegram"`, `"whatsapp"`, `"email"`, `"phone"`). Sourced from the
105
+ * `userMessageInterface` field already stamped on `messages.metadata`
106
+ * by every `persistUserMessage` path that flows through
107
+ * `TurnChannelContext`.
108
+ *
109
+ * Null when the metadata didn't carry the field — historical rows or
110
+ * system-initiated turns with no inbound client context. Downstream
111
+ * consumers should treat null as `"unknown"`.
112
+ */
113
+ interface_id: string | null;
114
+ /**
115
+ * Canonical `ChannelId` enum value identifying the messaging fabric the
116
+ * user message arrived on (`"vellum"` for in-app from macos/ios/web/
117
+ * cli/chrome-extension; `"slack"`/`"telegram"`/`"whatsapp"`/`"email"`/
118
+ * `"phone"` for channel-based interfaces). The 7th `ChannelId` value
119
+ * (`"platform"`) is APNs-push outbound-only and should never appear
120
+ * here.
121
+ */
122
+ channel_id: string | null;
123
+ /**
124
+ * Optional client-side metadata bag. Null when no client headers were
125
+ * attached to the request that created the user message (most
126
+ * channel-inbound paths today, and any path the new HTTP header
127
+ * middleware hasn't been wired to yet).
128
+ */
129
+ client: TurnTelemetryClientInfo | null;
31
130
  }
32
131
 
33
132
  /** Lifecycle event — app_open, hatch, etc. */
@@ -36,8 +135,21 @@ export interface LifecycleTelemetryEvent extends TelemetryEventBase {
36
135
  event_name: string;
37
136
  }
38
137
 
138
+ /** Onboarding event — pre-chat selections and Google connect status. */
139
+ export interface OnboardingTelemetryEvent extends TelemetryEventBase {
140
+ type: "onboarding";
141
+ screen: string;
142
+ tools?: string[];
143
+ tasks?: string[];
144
+ tone?: string;
145
+ google_connected?: boolean;
146
+ google_scopes?: string[];
147
+ ab_variant?: string;
148
+ }
149
+
39
150
  /** Discriminated union of all telemetry event types. */
40
151
  export type TelemetryEvent =
41
152
  | LlmUsageTelemetryEvent
42
153
  | TurnTelemetryEvent
43
- | LifecycleTelemetryEvent;
154
+ | LifecycleTelemetryEvent
155
+ | OnboardingTelemetryEvent;