@vellumai/assistant 0.11.2 → 0.11.3-staging.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 (720) hide show
  1. package/ARCHITECTURE.md +58 -3
  2. package/docs/trusted-contact-access.md +9 -5
  3. package/docs/vellum-doctor.md +195 -0
  4. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
  5. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  6. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  7. package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
  8. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +19 -2
  9. package/node_modules/@vellumai/environments/package.json +2 -1
  10. package/node_modules/@vellumai/environments/src/__tests__/cloud-assistant-hub-url.test.ts +38 -0
  11. package/node_modules/@vellumai/environments/src/__tests__/install-layout.test.ts +98 -0
  12. package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +5 -5
  13. package/node_modules/@vellumai/environments/src/index.ts +17 -6
  14. package/node_modules/@vellumai/environments/src/install-layout.ts +49 -0
  15. package/node_modules/@vellumai/environments/src/seeds.ts +29 -0
  16. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
  17. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  18. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  19. package/node_modules/@vellumai/gateway-client/src/index.ts +4 -0
  20. package/node_modules/@vellumai/gateway-client/src/verification-session-contract.ts +91 -6
  21. package/node_modules/@vellumai/ipc-server-utils/src/endpoint.test.ts +36 -0
  22. package/node_modules/@vellumai/ipc-server-utils/src/endpoint.ts +142 -0
  23. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +2 -0
  24. package/node_modules/@vellumai/ipc-server-utils/src/listen-options.ts +3 -0
  25. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +15 -1
  26. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +17 -2
  27. package/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
  28. package/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  29. package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  30. package/node_modules/@vellumai/slack-text/src/index.ts +16 -2
  31. package/openapi.yaml +589 -30
  32. package/package.json +1 -1
  33. package/src/__tests__/agent-image-optimize.test.ts +4 -4
  34. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +113 -66
  35. package/src/__tests__/agent-loop-override-profile.test.ts +38 -48
  36. package/src/__tests__/agent-loop-subagent-billing-headers.test.ts +166 -0
  37. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  38. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  39. package/src/__tests__/answered-question-persistence.test.ts +240 -0
  40. package/src/__tests__/anthropic-provider.test.ts +165 -30
  41. package/src/__tests__/app-control-flow.test.ts +9 -8
  42. package/src/__tests__/assistant-event-hub.test.ts +48 -0
  43. package/src/__tests__/attachments-store-heic-normalize.test.ts +16 -12
  44. package/src/__tests__/attachments-store.test.ts +130 -68
  45. package/src/__tests__/attachments.test.ts +36 -36
  46. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  47. package/src/__tests__/call-start-guardian-guard.test.ts +18 -4
  48. package/src/__tests__/canned-reply-release.test.ts +86 -0
  49. package/src/__tests__/channel-guardian.test.ts +59 -29
  50. package/src/__tests__/channel-readiness-telegram-remote.test.ts +154 -0
  51. package/src/__tests__/channel-setup-panel-ack.test.ts +6 -5
  52. package/src/__tests__/client-os-metadata-persistence.test.ts +103 -4
  53. package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
  54. package/src/__tests__/consult-deadline.test.ts +65 -0
  55. package/src/__tests__/conversation-agent-loop.test.ts +438 -2
  56. package/src/__tests__/conversation-disk-view-integration.test.ts +5 -1
  57. package/src/__tests__/conversation-disk-view.test.ts +4 -4
  58. package/src/__tests__/conversation-error.test.ts +22 -3
  59. package/src/__tests__/conversation-fork-crud.test.ts +5 -1
  60. package/src/__tests__/conversation-fork-referential.test.ts +352 -0
  61. package/src/__tests__/conversation-fork-retrospective.test.ts +5 -1
  62. package/src/__tests__/conversation-group-tools.test.ts +32 -2
  63. package/src/__tests__/conversation-inference-profile-route.test.ts +27 -1
  64. package/src/__tests__/conversation-initial-prompt.test.ts +51 -22
  65. package/src/__tests__/conversation-key-store-bootstrap-cleanup.test.ts +119 -0
  66. package/src/__tests__/conversation-key-store-origin.test.ts +105 -0
  67. package/src/__tests__/conversation-list-recency-ordering.test.ts +104 -0
  68. package/src/__tests__/conversation-origin-at-creation.test.ts +153 -0
  69. package/src/__tests__/conversation-origin-channel-filter.test.ts +95 -0
  70. package/src/__tests__/conversation-placement-promotion.test.ts +172 -0
  71. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +123 -0
  72. package/src/__tests__/conversation-queue.test.ts +433 -1
  73. package/src/__tests__/conversation-retry-route.test.ts +3 -1
  74. package/src/__tests__/conversation-routes-hidden-queue.test.ts +64 -1
  75. package/src/__tests__/conversation-store-ephemeral.test.ts +4 -0
  76. package/src/__tests__/conversation-store.test.ts +26 -10
  77. package/src/__tests__/conversation-summarize-route.test.ts +1 -1
  78. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +15 -6
  79. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -5
  80. package/src/__tests__/conversation-surfaces-app-control.test.ts +12 -11
  81. package/src/__tests__/conversation-surfaces-app-open.test.ts +11 -5
  82. package/src/__tests__/conversation-surfaces-data-persist.test.ts +5 -4
  83. package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +967 -0
  84. package/src/__tests__/conversation-surfaces-persisted-info.test.ts +312 -0
  85. package/src/__tests__/conversation-surfaces-queued-emit.test.ts +6 -5
  86. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -8
  87. package/src/__tests__/conversation-surfaces-standalone.test.ts +21 -11
  88. package/src/__tests__/conversation-surfaces-state-update.test.ts +7 -11
  89. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -6
  90. package/src/__tests__/conversation-surfaces-task-progress.test.ts +11 -6
  91. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +9 -6
  92. package/src/__tests__/conversation-tool-setup-attribution.test.ts +70 -7
  93. package/src/__tests__/conversation-wait-for-idle.test.ts +6 -11
  94. package/src/__tests__/credential-prompt-route.test.ts +57 -7
  95. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  96. package/src/__tests__/cu-unified-flow.test.ts +89 -28
  97. package/src/__tests__/custom-group-listing-visibility.test.ts +1 -1
  98. package/src/__tests__/db-schedule-syntax-migration.test.ts +4 -1
  99. package/src/__tests__/discord-access-request-privacy.test.ts +366 -0
  100. package/src/__tests__/discord-requester-notice-privacy.test.ts +87 -0
  101. package/src/__tests__/disk-pressure-guard.test.ts +55 -55
  102. package/src/__tests__/disk-pressure-routes.test.ts +10 -10
  103. package/src/__tests__/disk-pressure-tools.test.ts +2 -2
  104. package/src/__tests__/disk-usage.test.ts +35 -20
  105. package/src/__tests__/document-sync-tags.test.ts +379 -0
  106. package/src/__tests__/document-update-default-surface.test.ts +28 -0
  107. package/src/__tests__/dynamic-skill-background-guard.test.ts +2 -2
  108. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -4
  109. package/src/__tests__/ensure-conversation-exists.test.ts +8 -5
  110. package/src/__tests__/events-dev-bypass-actor.test.ts +183 -1
  111. package/src/__tests__/evict-conversations-for-reload.test.ts +90 -0
  112. package/src/__tests__/file-list-tool.test.ts +12 -10
  113. package/src/__tests__/file-ops-service.test.ts +151 -44
  114. package/src/__tests__/file-read-container-boundary.test.ts +137 -0
  115. package/src/__tests__/file-read-tool.test.ts +21 -9
  116. package/src/__tests__/file-url-path-guard.test.ts +83 -0
  117. package/src/__tests__/filesystem-tools.test.ts +82 -66
  118. package/src/__tests__/guardian-outbound-http.test.ts +8 -8
  119. package/src/__tests__/helpers/gateway-verification-sessions-stub.ts +14 -1
  120. package/src/__tests__/helpers/hub-clients.ts +42 -0
  121. package/src/__tests__/helpers/mock-conversation.ts +46 -0
  122. package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +61 -57
  123. package/src/__tests__/history-repair.test.ts +112 -12
  124. package/src/__tests__/host-bash-proxy.test.ts +10 -5
  125. package/src/__tests__/host-bash-routes.test.ts +67 -0
  126. package/src/__tests__/host-browser-proxy.test.ts +2 -2
  127. package/src/__tests__/host-cu-proxy.test.ts +3 -7
  128. package/src/__tests__/host-file-proxy.test.ts +3 -7
  129. package/src/__tests__/host-file-read-tool.test.ts +5 -1
  130. package/src/__tests__/host-transfer-proxy-targeted.test.ts +6 -4
  131. package/src/__tests__/http-conversation-lineage.test.ts +2 -5
  132. package/src/__tests__/http-user-message-parity.test.ts +44 -0
  133. package/src/__tests__/identity-routes.test.ts +13 -13
  134. package/src/__tests__/image-conversion.test.ts +29 -26
  135. package/src/__tests__/image-source-path-reinject.test.ts +2 -2
  136. package/src/__tests__/inference-profile-session-handler.test.ts +95 -0
  137. package/src/__tests__/inference-profile-session-ipc.test.ts +25 -0
  138. package/src/__tests__/introduction-card-resolver.test.ts +6 -1
  139. package/src/__tests__/list-messages-attachments.test.ts +56 -32
  140. package/src/__tests__/list-messages-background-tool-completion.test.ts +4 -4
  141. package/src/__tests__/list-messages-client-message-id.test.ts +2 -2
  142. package/src/__tests__/list-messages-hidden-metadata.test.ts +16 -16
  143. package/src/__tests__/list-messages-page-latest.test.ts +61 -61
  144. package/src/__tests__/list-messages-provider-error.test.ts +6 -6
  145. package/src/__tests__/list-messages-queued.test.ts +49 -6
  146. package/src/__tests__/list-messages-system-card.test.ts +4 -4
  147. package/src/__tests__/list-messages-tool-merge.test.ts +9 -9
  148. package/src/__tests__/llm-resolver-override-or-default.test.ts +141 -0
  149. package/src/__tests__/llm-usage-store.test.ts +55 -0
  150. package/src/__tests__/manual-token-reconciliation.test.ts +45 -0
  151. package/src/__tests__/mcp-tool-annotations-risk.test.ts +133 -0
  152. package/src/__tests__/media-stream-server-integration.test.ts +36 -0
  153. package/src/__tests__/migration-export-http.test.ts +1 -1
  154. package/src/__tests__/migration-import-commit-http.test.ts +1 -1
  155. package/src/__tests__/migration-import-preflight-http.test.ts +1 -1
  156. package/src/__tests__/migration-validate-http.test.ts +1 -1
  157. package/src/__tests__/mtime-cache.test.ts +65 -3
  158. package/src/__tests__/notification-platform-adapter.test.ts +104 -0
  159. package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
  160. package/src/__tests__/oauth-provider-profiles.test.ts +4 -2
  161. package/src/__tests__/oauth-provider-seed-logos.test.ts +65 -0
  162. package/src/__tests__/oauth-provider-serializer.test.ts +17 -0
  163. package/src/__tests__/oauth-providers-routes.test.ts +1 -0
  164. package/src/__tests__/openai-responses-prompt-cache.test.ts +5 -2
  165. package/src/__tests__/path-policy.test.ts +164 -1
  166. package/src/__tests__/persist-media-references.test.ts +2 -2
  167. package/src/__tests__/persist-unsendable-image-downscale.test.ts +5 -5
  168. package/src/__tests__/persist-unsendable-image.test.ts +23 -23
  169. package/src/__tests__/persona-resolver.test.ts +154 -0
  170. package/src/__tests__/plugin-api-webhook-url.test.ts +170 -0
  171. package/src/__tests__/plugin-import-boundary-guard.test.ts +6 -0
  172. package/src/__tests__/processing-flag-persist-failure.test.ts +15 -10
  173. package/src/__tests__/profile-availability-incomplete.test.ts +113 -0
  174. package/src/__tests__/profiler-routes.test.ts +13 -13
  175. package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +593 -0
  176. package/src/__tests__/proxy-approval-callback.test.ts +3 -3
  177. package/src/__tests__/queued-message-cancel-and-steer.test.ts +189 -0
  178. package/src/__tests__/queued-message-steer-actor-scoping.test.ts +164 -0
  179. package/src/__tests__/resolve-trust-class.test.ts +20 -0
  180. package/src/__tests__/run-conversation-turn-persistence.test.ts +1 -1
  181. package/src/__tests__/run-due-schedules.test.ts +174 -0
  182. package/src/__tests__/runtime-attachment-metadata.test.ts +15 -7
  183. package/src/__tests__/scaffold-managed-skill-tool.test.ts +166 -0
  184. package/src/__tests__/schedule-routes.test.ts +730 -8
  185. package/src/__tests__/schedule-store.test.ts +540 -0
  186. package/src/__tests__/schedule-tools.test.ts +103 -0
  187. package/src/__tests__/scheduler-wake.test.ts +5 -0
  188. package/src/__tests__/secret-routes-platform-proxy.test.ts +29 -1
  189. package/src/__tests__/secure-keys.test.ts +91 -0
  190. package/src/__tests__/server-history-render.test.ts +97 -7
  191. package/src/__tests__/size-guard.test.ts +8 -8
  192. package/src/__tests__/skill-docs-sync-guard.test.ts +3 -2
  193. package/src/__tests__/skill-tool-factory.test.ts +247 -0
  194. package/src/__tests__/skills-install-staging.test.ts +15 -6
  195. package/src/__tests__/slack-edit-ordering-characterization.test.ts +103 -0
  196. package/src/__tests__/slack-inbound-verification.test.ts +4 -1
  197. package/src/__tests__/slack-mention-binding-invariance.test.ts +103 -0
  198. package/src/__tests__/slack-mention-provider-leak-audit.test.ts +135 -0
  199. package/src/__tests__/starter-task-flow.test.ts +5 -4
  200. package/src/__tests__/steer-on-enqueue-question.test.ts +3 -2
  201. package/src/__tests__/stt-language-catalog-parity.test.ts +38 -0
  202. package/src/__tests__/subagent-allowlist-validation.test.ts +26 -4
  203. package/src/__tests__/subagent-cron-run-attribution.test.ts +301 -0
  204. package/src/__tests__/subagent-disposal.test.ts +10 -0
  205. package/src/__tests__/subagent-fork-notifications.test.ts +10 -0
  206. package/src/__tests__/subagent-fork-prompt-role.test.ts +85 -11
  207. package/src/__tests__/subagent-fork-spawn.test.ts +15 -7
  208. package/src/__tests__/subagent-manager-notify.test.ts +148 -0
  209. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  210. package/src/__tests__/subagent-persistence.test.ts +141 -0
  211. package/src/__tests__/subagent-role-registry.test.ts +172 -63
  212. package/src/__tests__/subagent-role-resolution.test.ts +88 -0
  213. package/src/__tests__/subagent-spawn-and-await.test.ts +48 -0
  214. package/src/__tests__/subagent-spawn-tool-fork.test.ts +111 -10
  215. package/src/__tests__/subagent-terminal-message.test.ts +88 -1
  216. package/src/__tests__/subagent-tool-gate-mode.test.ts +225 -10
  217. package/src/__tests__/subagent-tools.test.ts +1901 -108
  218. package/src/__tests__/surface-completion-compaction-boundary.test.ts +124 -0
  219. package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +298 -0
  220. package/src/__tests__/system-prompt.test.ts +82 -7
  221. package/src/__tests__/tool-grant-request-escalation.test.ts +40 -1
  222. package/src/__tests__/tool-result-spool.test.ts +74 -18
  223. package/src/__tests__/tool-side-effects-documents.test.ts +174 -0
  224. package/src/__tests__/tool-side-effects-hook-failures.test.ts +129 -0
  225. package/src/__tests__/tools-audio-read.test.ts +10 -10
  226. package/src/__tests__/tools-get-route.test.ts +85 -12
  227. package/src/__tests__/tools-list-cli.test.ts +171 -0
  228. package/src/__tests__/top-level-renderer.test.ts +54 -1
  229. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +68 -1
  230. package/src/__tests__/trusted-contact-multichannel.test.ts +4 -1
  231. package/src/__tests__/turn-tail-chain.test.ts +135 -0
  232. package/src/__tests__/ui-choice-copy-surfaces.test.ts +6 -4
  233. package/src/__tests__/ui-visual-surface.test.ts +5 -4
  234. package/src/__tests__/ui-work-result-surface.test.ts +5 -4
  235. package/src/__tests__/unified-turn-context-visible-app.test.ts +7 -8
  236. package/src/__tests__/usage-routes.test.ts +62 -0
  237. package/src/__tests__/verification-outbound-delivery.test.ts +176 -0
  238. package/src/__tests__/visible-app-context.test.ts +20 -4
  239. package/src/__tests__/web-search-history.test.ts +96 -0
  240. package/src/__tests__/workspace-migration-139-clear-renamed-cost-profile-label.test.ts +6 -6
  241. package/src/__tests__/workspace-migration-140-repair-seed-pinned-memory-v3-live.test.ts +330 -0
  242. package/src/acp/failure-error.ts +3 -5
  243. package/src/agent/attachments.ts +26 -24
  244. package/src/agent/history-repair/history-repair.ts +27 -26
  245. package/src/agent/image-optimize.ts +6 -6
  246. package/src/agent/loop.ts +40 -22
  247. package/src/agent/message-types.ts +3 -3
  248. package/src/api/constants/document-tools.ts +55 -0
  249. package/src/api/events/question-answered.ts +53 -0
  250. package/src/api/events/tool-result.ts +7 -0
  251. package/src/api/index.ts +13 -0
  252. package/src/api/responses/conversation-message.ts +11 -0
  253. package/src/api/surfaces-oauth-connect.test.ts +96 -0
  254. package/src/api/surfaces.ts +36 -8
  255. package/src/approvals/guardian-channel-delivery.ts +83 -0
  256. package/src/approvals/guardian-expiry-notifier.ts +13 -11
  257. package/src/approvals/guardian-request-resolvers.ts +222 -135
  258. package/src/calls/__tests__/voice-session-bridge.test.ts +50 -0
  259. package/src/calls/media-stream-server.ts +9 -1
  260. package/src/calls/voice-session-bridge.ts +38 -0
  261. package/src/channels/__tests__/gateway-verification-sessions.test.ts +3 -3
  262. package/src/channels/config.ts +7 -2
  263. package/src/channels/gateway-verification-sessions.ts +7 -2
  264. package/src/channels/types.ts +7 -1
  265. package/src/cli/commands/__tests__/cache.test.ts +7 -4
  266. package/src/cli/commands/__tests__/cli-test-harness.ts +82 -0
  267. package/src/cli/commands/__tests__/conversations-wake.test.ts +51 -6
  268. package/src/cli/commands/__tests__/inference-models.test.ts +14 -0
  269. package/src/cli/commands/__tests__/inference-profiles.test.ts +44 -1
  270. package/src/cli/commands/__tests__/inference-providers.test.ts +7 -0
  271. package/src/cli/commands/__tests__/plugins.test.ts +692 -0
  272. package/src/cli/commands/__tests__/schedules.test.ts +136 -37
  273. package/src/cli/commands/conversations.ts +7 -3
  274. package/src/cli/commands/credentials.help.ts +7 -0
  275. package/src/cli/commands/inference-profiles.ts +9 -3
  276. package/src/cli/commands/inference.help.ts +16 -2
  277. package/src/cli/commands/mcp.help.ts +4 -2
  278. package/src/cli/commands/memory/memory-retrospective.ts +18 -0
  279. package/src/cli/commands/notifications.ts +3 -6
  280. package/src/cli/commands/oauth/connect-surface-guidance.test.ts +16 -0
  281. package/src/cli/commands/oauth/connect-surface-guidance.ts +25 -7
  282. package/src/cli/commands/oauth/connect.test.ts +26 -1
  283. package/src/cli/commands/oauth/connect.ts +4 -1
  284. package/src/cli/commands/oauth/index.help.ts +3 -1
  285. package/src/cli/commands/oauth/providers.ts +3 -0
  286. package/src/cli/commands/plugins.help.ts +25 -2
  287. package/src/cli/commands/plugins.ts +289 -10
  288. package/src/cli/commands/schedules.help.ts +14 -12
  289. package/src/cli/commands/schedules.ts +19 -5
  290. package/src/cli/commands/tools.help.ts +4 -2
  291. package/src/cli/commands/tools.ts +38 -0
  292. package/src/cli/lib/__tests__/inspect-plugin.test.ts +1 -0
  293. package/src/cli/lib/__tests__/install-from-github.test.ts +79 -0
  294. package/src/cli/lib/__tests__/install-from-platform.test.ts +47 -1
  295. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +86 -7
  296. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +122 -0
  297. package/src/cli/lib/install-from-github.ts +61 -0
  298. package/src/cli/lib/install-from-platform.ts +13 -2
  299. package/src/cli/lib/plugin-surfaces.ts +124 -4
  300. package/src/cli/lib/upgrade-plugin.ts +18 -0
  301. package/src/cli.ts +1 -1
  302. package/src/config/__tests__/deployment-context-defaults.test.ts +73 -0
  303. package/src/config/__tests__/memory-retrospective-schema.test.ts +40 -0
  304. package/src/config/__tests__/plugin-updates-schema.test.ts +43 -0
  305. package/src/config/__tests__/profile-tool-support.test.ts +131 -0
  306. package/src/config/bundled-skills/AGENTS.md +1 -1
  307. package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
  308. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +3 -3
  309. package/src/config/bundled-skills/schedule/SKILL.md +5 -1
  310. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  311. package/src/config/bundled-skills/settings/TOOLS.json +2 -2
  312. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +1 -0
  313. package/src/config/bundled-skills/subagent/SKILL.md +53 -22
  314. package/src/config/bundled-skills/subagent/TOOLS.json +14 -13
  315. package/src/config/bundled-skills/visualize/SKILL.md +1 -1
  316. package/src/config/default-profile-catalog.ts +6 -2
  317. package/src/config/feature-flag-registry.json +25 -17
  318. package/src/config/llm-resolver.ts +45 -15
  319. package/src/config/loader.ts +70 -1
  320. package/src/config/profile-tool-support.ts +110 -0
  321. package/src/config/sanitize-for-transfer.ts +11 -0
  322. package/src/config/schema.ts +4 -0
  323. package/src/config/schemas/__tests__/stt.test.ts +20 -5
  324. package/src/config/schemas/channels.ts +13 -0
  325. package/src/config/schemas/memory-retrospective.ts +25 -0
  326. package/src/config/schemas/plugin-updates.ts +55 -0
  327. package/src/config/schemas/services.ts +8 -4
  328. package/src/config/schemas/stt.ts +17 -5
  329. package/src/config/schemas/timeouts.ts +1 -1
  330. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +16 -0
  331. package/src/contacts/guardian-delivery-reader.ts +29 -2
  332. package/src/context/compactor.ts +4 -4
  333. package/src/context/post-turn-tool-result-truncation.ts +32 -16
  334. package/src/context/strip-injections.ts +42 -0
  335. package/src/context/tool-result-spool.ts +32 -18
  336. package/src/credential-execution/ces-runtime.ts +3 -0
  337. package/src/credential-execution/client.ts +22 -1
  338. package/src/credential-execution/process-manager.test.ts +99 -0
  339. package/src/credential-execution/process-manager.ts +62 -16
  340. package/src/daemon/__tests__/abort-null-controller.test.ts +141 -5
  341. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +8 -12
  342. package/src/daemon/__tests__/install-assistant-command.test.ts +234 -0
  343. package/src/daemon/__tests__/turn-tail-assistant-reply-notify.test.ts +2 -4
  344. package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +20 -29
  345. package/src/daemon/channel-ui-capability.ts +4 -4
  346. package/src/daemon/conversation-agent-loop-handlers.ts +117 -61
  347. package/src/daemon/conversation-agent-loop.ts +318 -148
  348. package/src/daemon/conversation-attachments.ts +1 -1
  349. package/src/daemon/conversation-error.ts +8 -1
  350. package/src/daemon/conversation-initial-prompt.ts +16 -38
  351. package/src/daemon/conversation-lifecycle.ts +154 -32
  352. package/src/daemon/conversation-messaging.ts +106 -43
  353. package/src/daemon/conversation-process.ts +131 -33
  354. package/src/daemon/conversation-queue-manager.ts +10 -0
  355. package/src/daemon/conversation-runtime-assembly.ts +9 -4
  356. package/src/daemon/conversation-store.ts +52 -3
  357. package/src/daemon/conversation-surface-state.ts +9 -0
  358. package/src/daemon/conversation-surfaces.ts +403 -210
  359. package/src/daemon/conversation-tool-setup.ts +56 -7
  360. package/src/daemon/conversation-turn-finalize.ts +134 -89
  361. package/src/daemon/conversation.ts +111 -27
  362. package/src/daemon/disk-pressure-guard-lifecycle.ts +2 -2
  363. package/src/daemon/disk-pressure-guard.ts +3 -3
  364. package/src/daemon/doordash-steps.ts +5 -5
  365. package/src/daemon/external-plugins-bootstrap.ts +7 -1
  366. package/src/daemon/handlers/config-channels.ts +48 -5
  367. package/src/daemon/handlers/conversation-history.ts +1 -1
  368. package/src/daemon/handlers/conversations.ts +62 -17
  369. package/src/daemon/handlers/shared.ts +12 -0
  370. package/src/daemon/handlers/skills.ts +11 -1
  371. package/src/daemon/identity-helpers.ts +38 -10
  372. package/src/daemon/install-assistant-command.ts +322 -0
  373. package/src/daemon/lifecycle.ts +14 -3
  374. package/src/daemon/message-types/conversations.ts +6 -7
  375. package/src/daemon/message-types/sync.ts +1 -0
  376. package/src/daemon/persist-media-references.ts +23 -14
  377. package/src/daemon/process-message.ts +6 -6
  378. package/src/daemon/tool-setup-types.ts +19 -122
  379. package/src/daemon/tool-side-effects.ts +17 -94
  380. package/src/daemon/trust-context-types.ts +39 -0
  381. package/src/daemon/trust-context.ts +14 -6
  382. package/src/daemon/turn-tail-chain.ts +73 -0
  383. package/src/daemon/web-search-history.ts +47 -33
  384. package/src/heartbeat/heartbeat-service.ts +6 -6
  385. package/src/ipc/__tests__/socket-path.test.ts +21 -0
  386. package/src/ipc/assistant-server.ts +17 -10
  387. package/src/ipc/cli-client.ts +10 -1
  388. package/src/ipc/routes/__tests__/documents-sync-ipc-routes.test.ts +56 -0
  389. package/src/ipc/routes/documents-sync-ipc-routes.ts +42 -0
  390. package/src/ipc/socket-cleanup.ts +9 -7
  391. package/src/ipc/socket-path.ts +4 -96
  392. package/src/live-voice/__tests__/live-voice-archive.test.ts +16 -16
  393. package/src/live-voice/__tests__/live-voice-attach-image.test.ts +209 -0
  394. package/src/live-voice/__tests__/live-voice-connection.test.ts +20 -0
  395. package/src/live-voice/__tests__/live-voice-integration.test.ts +7 -5
  396. package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +265 -0
  397. package/src/live-voice/__tests__/live-voice-stt.test.ts +6 -1
  398. package/src/live-voice/__tests__/live-voice-vad.test.ts +35 -15
  399. package/src/live-voice/__tests__/protocol.test.ts +52 -0
  400. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +3 -0
  401. package/src/live-voice/live-voice-archive.ts +13 -13
  402. package/src/live-voice/live-voice-connection.ts +7 -1
  403. package/src/live-voice/live-voice-photo.ts +169 -0
  404. package/src/live-voice/live-voice-session.ts +108 -4
  405. package/src/live-voice/protocol.ts +89 -1
  406. package/src/mcp/client.ts +10 -0
  407. package/src/messaging/providers/__tests__/callback-routing.test.ts +5 -1
  408. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +66 -4
  409. package/src/messaging/providers/callback-routing.ts +1 -0
  410. package/src/messaging/providers/discord/api.ts +312 -0
  411. package/src/messaging/providers/discord/dm-delivery.test.ts +204 -0
  412. package/src/messaging/providers/discord/render.test.ts +204 -0
  413. package/src/messaging/providers/discord/render.ts +195 -0
  414. package/src/messaging/providers/discord/send.test.ts +179 -0
  415. package/src/messaging/providers/discord/send.ts +212 -0
  416. package/src/messaging/providers/discord/transport.ts +81 -0
  417. package/src/messaging/providers/index.ts +3 -1
  418. package/src/messaging/providers/retry-policy.test.ts +247 -0
  419. package/src/messaging/providers/retry-policy.ts +206 -0
  420. package/src/messaging/providers/slack/mention-source.test.ts +285 -0
  421. package/src/messaging/providers/slack/mention-source.ts +287 -0
  422. package/src/messaging/providers/telegram-bot/api.ts +47 -130
  423. package/src/messaging/providers/whatsapp/api.ts +47 -136
  424. package/src/monitoring/__tests__/db-integrity-sample.test.ts +4 -1
  425. package/src/monitoring/__tests__/plugin-auto-update.test.ts +332 -0
  426. package/src/monitoring/db-integrity-sample.ts +6 -1
  427. package/src/monitoring/plugin-auto-update.ts +359 -0
  428. package/src/monitoring/resource-sampler.ts +21 -5
  429. package/src/monitoring/worker.ts +13 -0
  430. package/src/notifications/__tests__/assistant-reply-producer.test.ts +375 -2
  431. package/src/notifications/__tests__/broadcaster.test.ts +37 -1
  432. package/src/notifications/__tests__/copy-composer.test.ts +165 -0
  433. package/src/notifications/__tests__/emit-signal-pipeline-failure.test.ts +205 -0
  434. package/src/notifications/__tests__/notification-utils.test.ts +249 -0
  435. package/src/notifications/adapters/platform.ts +31 -2
  436. package/src/notifications/assistant-reply-producer.ts +79 -32
  437. package/src/notifications/broadcaster.ts +30 -10
  438. package/src/notifications/copy-composer.ts +69 -0
  439. package/src/notifications/emit-signal.ts +82 -15
  440. package/src/notifications/events-store.ts +10 -2
  441. package/src/notifications/home-feed-side-effect.ts +6 -3
  442. package/src/notifications/notification-utils.ts +173 -5
  443. package/src/notifications/signal.ts +12 -0
  444. package/src/oauth/AGENTS.md +4 -2
  445. package/src/oauth/byo-connection.ts +6 -1
  446. package/src/oauth/credential-token-resolver.ts +3 -10
  447. package/src/oauth/manual-token-connection.ts +29 -64
  448. package/src/oauth/manual-token-providers.ts +62 -0
  449. package/src/oauth/provider-serializer.ts +13 -0
  450. package/src/oauth/seed-providers.ts +62 -11
  451. package/src/onboarding/onboarding-events-store.ts +91 -1
  452. package/src/permissions/question-prompter.test.ts +4 -0
  453. package/src/permissions/question-prompter.ts +21 -4
  454. package/src/persistence/__tests__/conversation-lineage.test.ts +248 -0
  455. package/src/persistence/attachments-store.ts +15 -15
  456. package/src/persistence/conversation-attention-store.ts +30 -10
  457. package/src/persistence/conversation-bootstrap.ts +17 -0
  458. package/src/persistence/conversation-crud.ts +363 -97
  459. package/src/persistence/conversation-group-migration.ts +1 -1
  460. package/src/persistence/conversation-key-store.ts +38 -10
  461. package/src/persistence/conversation-lineage.ts +226 -0
  462. package/src/persistence/conversation-plugin-facade.ts +28 -3
  463. package/src/persistence/conversation-queries.ts +207 -33
  464. package/src/persistence/conversation-types.ts +107 -1
  465. package/src/persistence/jobs-store.ts +32 -8
  466. package/src/persistence/llm-usage-store.ts +22 -0
  467. package/src/persistence/migrations/361-normalize-managed-connection-rows.test.ts +168 -0
  468. package/src/persistence/migrations/361-normalize-managed-connection-rows.ts +76 -0
  469. package/src/persistence/migrations/362-add-conversation-subagent-kind.test.ts +187 -0
  470. package/src/persistence/migrations/362-add-conversation-subagent-kind.ts +93 -0
  471. package/src/persistence/migrations/363-backfill-schedule-inference-profile.test.ts +229 -0
  472. package/src/persistence/migrations/363-backfill-schedule-inference-profile.ts +127 -0
  473. package/src/persistence/migrations/364-add-schedule-source-key.test.ts +120 -0
  474. package/src/persistence/migrations/364-add-schedule-source-key.ts +43 -0
  475. package/src/persistence/migrations/365-add-conversation-fork-strategy.ts +27 -0
  476. package/src/persistence/schema/conversations.ts +32 -0
  477. package/src/persistence/schema/infrastructure.ts +3 -0
  478. package/src/persistence/steps.ts +30 -0
  479. package/src/persistence/subagent-store.ts +148 -6
  480. package/src/platform/managed-speech.test.ts +20 -0
  481. package/src/platform/managed-speech.ts +9 -0
  482. package/src/plugin-api/index.ts +8 -0
  483. package/src/plugin-api/webhook-url.ts +151 -0
  484. package/src/plugins/__tests__/installed-plugin-dirs.test.ts +82 -0
  485. package/src/plugins/__tests__/source-fingerprint.test.ts +5 -1
  486. package/src/plugins/collect-source-versions.ts +4 -27
  487. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +5 -5
  488. package/src/plugins/defaults/exploration-drift/package.json +1 -1
  489. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +4 -2
  490. package/src/plugins/defaults/image-recovery/recover.ts +67 -57
  491. package/src/plugins/defaults/index.ts +1 -1
  492. package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +64 -18
  493. package/src/plugins/defaults/memory/__tests__/jobs-worker-outcome-contract.test.ts +242 -0
  494. package/src/plugins/defaults/memory/__tests__/jobs-worker-retrospective-sweep.test.ts +24 -1
  495. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +48 -3
  496. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +511 -19
  497. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +39 -3
  498. package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +493 -0
  499. package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +5 -4
  500. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +5 -1
  501. package/src/plugins/defaults/memory/job-handlers.ts +87 -5
  502. package/src/plugins/defaults/memory/jobs-worker.ts +60 -6
  503. package/src/plugins/defaults/memory/memory-retrospective-constants.ts +11 -0
  504. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +29 -0
  505. package/src/plugins/defaults/memory/memory-retrospective-job.ts +342 -60
  506. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +23 -3
  507. package/src/plugins/defaults/memory/substrate/consolidation-lock.ts +9 -4
  508. package/src/plugins/defaults/memory/substrate/sweep-job.ts +7 -0
  509. package/src/plugins/defaults/memory/v1/graph/injection.ts +1 -1
  510. package/src/plugins/defaults/memory/v2/router.ts +8 -0
  511. package/src/plugins/defaults/turn-context/unified-turn-context.ts +1 -2
  512. package/src/plugins/external-plugin-loader.ts +17 -8
  513. package/src/plugins/installed-plugin-dirs.ts +101 -0
  514. package/src/plugins/mtime-cache.ts +34 -22
  515. package/src/plugins/types.ts +69 -8
  516. package/src/prompts/persona-resolver.ts +6 -2
  517. package/src/prompts/system-prompt.ts +72 -17
  518. package/src/providers/__tests__/inference.test.ts +40 -0
  519. package/src/providers/__tests__/preflight-resolved-config.test.ts +58 -1
  520. package/src/providers/__tests__/retry-callsite.test.ts +67 -0
  521. package/src/providers/__tests__/vellum-connection-routing.test.ts +42 -11
  522. package/src/providers/anthropic/client.ts +112 -95
  523. package/src/providers/connection-resolution.ts +35 -1
  524. package/src/providers/gemini/client.ts +5 -5
  525. package/src/providers/inference/adapter-factory.ts +16 -10
  526. package/src/providers/inference/auth.ts +16 -0
  527. package/src/providers/inference/connection-availability.ts +164 -12
  528. package/src/providers/inference/connections.ts +25 -1
  529. package/src/providers/media-resolve.ts +21 -11
  530. package/src/providers/model-catalog.ts +15 -0
  531. package/src/providers/openai/chat-completions-provider.ts +4 -4
  532. package/src/providers/openai/responses-provider.ts +12 -25
  533. package/src/providers/registry.ts +9 -4
  534. package/src/providers/retry.ts +25 -0
  535. package/src/providers/server-tool-pairing.ts +134 -0
  536. package/src/providers/speech-to-text/__tests__/resolve.test.ts +187 -6
  537. package/src/providers/speech-to-text/deepgram.ts +1 -0
  538. package/src/providers/speech-to-text/resolve.ts +80 -10
  539. package/src/providers/speech-to-text/vellum-managed.ts +7 -1
  540. package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +3 -1
  541. package/src/providers/types.ts +26 -6
  542. package/src/providers/vellum-model-routing.ts +6 -7
  543. package/src/runtime/AGENTS.md +2 -0
  544. package/src/runtime/__tests__/agent-wake.test.ts +16 -16
  545. package/src/runtime/__tests__/background-job-runner.test.ts +0 -144
  546. package/src/runtime/__tests__/desktop-presence.test.ts +162 -0
  547. package/src/runtime/agent-wake.ts +63 -24
  548. package/src/runtime/assistant-event-hub.ts +87 -12
  549. package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -0
  550. package/src/runtime/auth/__tests__/scopes.test.ts +20 -0
  551. package/src/runtime/auth/same-actor.ts +56 -8
  552. package/src/runtime/auth/scopes.ts +12 -0
  553. package/src/runtime/auth/types.ts +2 -0
  554. package/src/runtime/background-job-runner.ts +5 -27
  555. package/src/runtime/channel-readiness-service.ts +59 -3
  556. package/src/runtime/channel-readiness-types.ts +18 -0
  557. package/src/runtime/desktop-presence.ts +69 -0
  558. package/src/runtime/http-server.ts +12 -0
  559. package/src/runtime/local-actor-identity.ts +11 -9
  560. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
  561. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  562. package/src/runtime/routes/__tests__/client-routes.test.ts +186 -14
  563. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +547 -1
  564. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +162 -7
  565. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +14 -10
  566. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +340 -3
  567. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +28 -1
  568. package/src/runtime/routes/__tests__/plugins-routes.test.ts +173 -1
  569. package/src/runtime/routes/__tests__/question-routes.test.ts +64 -0
  570. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +20 -0
  571. package/src/runtime/routes/__tests__/skill-history-route.test.ts +116 -0
  572. package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +60 -2
  573. package/src/runtime/routes/archive-utils.ts +16 -12
  574. package/src/runtime/routes/attachment-routes.ts +13 -6
  575. package/src/runtime/routes/canned-reply-release.ts +54 -0
  576. package/src/runtime/routes/channel-verification-routes.ts +2 -27
  577. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +5 -0
  578. package/src/runtime/routes/client-routes.ts +114 -2
  579. package/src/runtime/routes/conversation-cli-routes.ts +10 -12
  580. package/src/runtime/routes/conversation-list-routes.ts +59 -10
  581. package/src/runtime/routes/conversation-management-routes.ts +47 -18
  582. package/src/runtime/routes/conversation-query-routes.ts +32 -53
  583. package/src/runtime/routes/conversation-routes.ts +360 -293
  584. package/src/runtime/routes/credential-prompt-routes.ts +23 -2
  585. package/src/runtime/routes/debug-routes.ts +4 -1
  586. package/src/runtime/routes/default-provider-routes.ts +7 -11
  587. package/src/runtime/routes/documents-routes.ts +44 -1
  588. package/src/runtime/routes/events-routes.ts +28 -1
  589. package/src/runtime/routes/host-app-control-routes.ts +2 -0
  590. package/src/runtime/routes/host-bash-routes.ts +2 -0
  591. package/src/runtime/routes/host-browser-routes.ts +2 -0
  592. package/src/runtime/routes/host-cu-routes.ts +2 -0
  593. package/src/runtime/routes/host-file-routes.ts +2 -0
  594. package/src/runtime/routes/host-transfer-routes.ts +4 -0
  595. package/src/runtime/routes/identity-routes.ts +6 -6
  596. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  597. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +7 -3
  598. package/src/runtime/routes/inbound-stages/background-dispatch.ts +14 -0
  599. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -2
  600. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +14 -11
  601. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -17
  602. package/src/runtime/routes/inference-profile-availability-guard.ts +171 -0
  603. package/src/runtime/routes/inference-profile-session-handler.ts +26 -2
  604. package/src/runtime/routes/inference-profile-session-routes.ts +2 -1
  605. package/src/runtime/routes/inference-profiles-routes.ts +152 -73
  606. package/src/runtime/routes/inference-provider-connection-routes.ts +0 -16
  607. package/src/runtime/routes/llm-call-sites-routes.ts +13 -0
  608. package/src/runtime/routes/log-export-routes.ts +1 -1
  609. package/src/runtime/routes/notification-routes.ts +0 -14
  610. package/src/runtime/routes/oauth-providers.ts +1 -0
  611. package/src/runtime/routes/plugins-routes.ts +106 -1
  612. package/src/runtime/routes/profiler-routes.ts +4 -2
  613. package/src/runtime/routes/question-routes.ts +28 -10
  614. package/src/runtime/routes/retrospective-routes.ts +9 -3
  615. package/src/runtime/routes/schedule-routes.ts +210 -12
  616. package/src/runtime/routes/secret-routes.ts +40 -23
  617. package/src/runtime/routes/settings-routes.ts +41 -13
  618. package/src/runtime/routes/skills-routes.ts +79 -0
  619. package/src/runtime/routes/ui-snapshot-routes.ts +1 -0
  620. package/src/runtime/routes/wake-conversation-routes.ts +23 -0
  621. package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
  622. package/src/runtime/services/conversation-serializer.ts +24 -9
  623. package/src/runtime/sync/documents-sidecar-publish.test.ts +101 -0
  624. package/src/runtime/sync/resource-sync-events.ts +79 -1
  625. package/src/runtime/sync/worker-daemon-notify.test.ts +34 -0
  626. package/src/runtime/sync/worker-daemon-notify.ts +44 -6
  627. package/src/runtime/verification-outbound-actions.ts +250 -222
  628. package/src/runtime/verification-templates.ts +41 -30
  629. package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +614 -0
  630. package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1066 -0
  631. package/src/schedule/inference-profile.ts +64 -3
  632. package/src/schedule/plugin-schedule-declarations.ts +518 -0
  633. package/src/schedule/plugin-schedule-reconciler.ts +605 -0
  634. package/src/schedule/plugin-schedules-gate.ts +23 -0
  635. package/src/schedule/schedule-store.ts +520 -26
  636. package/src/schedule/scheduler.ts +38 -0
  637. package/src/security/credential-backend.ts +51 -4
  638. package/src/security/encrypted-store.ts +64 -42
  639. package/src/security/secure-keys.ts +55 -7
  640. package/src/skills/catalog-install.ts +20 -7
  641. package/src/skills/inline-command-runner.ts +2 -7
  642. package/src/skills/skill-history.test.ts +269 -0
  643. package/src/skills/skill-history.ts +250 -0
  644. package/src/skills/skillssh-registry.ts +1 -1
  645. package/src/stt/daemon-batch-transcriber.ts +8 -6
  646. package/src/subagent/__tests__/consult-prompt.test.ts +25 -0
  647. package/src/subagent/consult-prompt.ts +3 -1
  648. package/src/subagent/consult-transcript.ts +1 -1
  649. package/src/subagent/manager.ts +304 -44
  650. package/src/subagent/progress-events.ts +35 -0
  651. package/src/subagent/role-resolution.ts +88 -0
  652. package/src/subagent/types.ts +302 -67
  653. package/src/subagent/validate-allowlists.ts +3 -4
  654. package/src/telegram/__tests__/webhook-health.test.ts +73 -1
  655. package/src/telegram/webhook-health.ts +101 -3
  656. package/src/telemetry/__tests__/telemetry-event-fixtures.ts +2 -0
  657. package/src/telemetry/activation-funnel.ts +6 -1
  658. package/src/telemetry/live-voice-funnel.ts +75 -0
  659. package/src/telemetry/telemetry-event-sources.ts +6 -0
  660. package/src/telemetry/telemetry-wire-source.json +1 -1
  661. package/src/telemetry/telemetry-wire.generated.ts +2 -0
  662. package/src/telemetry/types.ts +23 -4
  663. package/src/telemetry/usage-telemetry-reporter.test.ts +4 -0
  664. package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +1 -1
  665. package/src/tools/ask-question/ask-question-tool.test.ts +118 -3
  666. package/src/tools/ask-question/ask-question-tool.ts +56 -2
  667. package/src/tools/browser/browser-execution.ts +1 -1
  668. package/src/tools/calls/call-start.ts +8 -5
  669. package/src/tools/conversation-groups/move_to_group.ts +10 -12
  670. package/src/tools/document/document-tool.ts +11 -4
  671. package/src/tools/execution-timeout.ts +9 -2
  672. package/src/tools/executor.ts +7 -6
  673. package/src/tools/filesystem/edit.ts +1 -1
  674. package/src/tools/filesystem/list.ts +1 -1
  675. package/src/tools/filesystem/read.ts +7 -13
  676. package/src/tools/filesystem/search.ts +23 -21
  677. package/src/tools/filesystem/write.ts +4 -1
  678. package/src/tools/host-filesystem/edit.ts +7 -2
  679. package/src/tools/host-filesystem/read.ts +21 -8
  680. package/src/tools/host-filesystem/write.ts +10 -2
  681. package/src/tools/host-terminal/host-shell.ts +2 -2
  682. package/src/tools/mcp/mcp-tool-factory.ts +25 -1
  683. package/src/tools/permission-checker.ts +8 -3
  684. package/src/tools/schedule/delete.ts +13 -1
  685. package/src/tools/schedule/list.ts +14 -3
  686. package/src/tools/schedule/update.ts +56 -33
  687. package/src/tools/shared/filesystem/audio-read.ts +6 -4
  688. package/src/tools/shared/filesystem/file-ops-service.ts +176 -116
  689. package/src/tools/shared/filesystem/image-read.ts +12 -12
  690. package/src/tools/shared/filesystem/path-policy.ts +70 -5
  691. package/src/tools/shared/filesystem/size-guard.ts +6 -6
  692. package/src/tools/shared/input-misuse.ts +72 -0
  693. package/src/tools/skills/scaffold-managed.ts +82 -0
  694. package/src/tools/skills/skill-tool-factory.ts +14 -1
  695. package/src/tools/subagent/consult-deadline.ts +12 -7
  696. package/src/tools/subagent/message.ts +3 -1
  697. package/src/tools/subagent/read.ts +66 -4
  698. package/src/tools/subagent/spawn.ts +500 -78
  699. package/src/tools/tool-approval-handler.ts +45 -4
  700. package/src/tools/types.ts +22 -3
  701. package/src/tools/ui-surface/surface-shape-docs.ts +1 -1
  702. package/src/tools/ui-surface/visual-validation.ts +2 -0
  703. package/src/usage/__tests__/subagent-attribution.test.ts +109 -0
  704. package/src/usage/subagent-attribution.ts +108 -0
  705. package/src/util/__tests__/sqlite-retry.test.ts +112 -0
  706. package/src/util/abort-reasons.ts +16 -0
  707. package/src/util/ansi.ts +44 -0
  708. package/src/util/disk-usage.ts +17 -13
  709. package/src/util/image-conversion.ts +20 -13
  710. package/src/util/schedule-source-key.ts +23 -0
  711. package/src/util/worker-process.ts +7 -1
  712. package/src/workspace/git-service.ts +33 -9
  713. package/src/workspace/migrations/140-repair-seed-pinned-memory-v3-live.ts +260 -0
  714. package/src/workspace/migrations/141-stt-english-default-to-multilingual.ts +111 -0
  715. package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +126 -0
  716. package/src/workspace/migrations/registry.ts +4 -0
  717. package/src/workspace/top-level-renderer.ts +15 -2
  718. package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -357
  719. package/src/daemon/install-symlink.ts +0 -207
  720. package/src/notifications/deferred-emit.ts +0 -147
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Tests for `skill-history.ts`, run against a REAL git repository rather than
3
+ * a mocked git.
4
+ *
5
+ * The behavior worth protecting is entirely about how git actually responds to
6
+ * a pathspec: that a commit touching 100 unrelated files still yields a diff
7
+ * scoped to one skill, that `:(exclude)` really drops the usage stamp, and
8
+ * that a commit whose only in-skill change was excluded disappears from the
9
+ * list. A stubbed git would let all three regress while the tests stayed
10
+ * green, so each test builds commits in a temp repo and reads them back.
11
+ */
12
+
13
+ import { execFileSync } from "node:child_process";
14
+ import {
15
+ existsSync,
16
+ mkdirSync,
17
+ mkdtempSync,
18
+ readdirSync,
19
+ rmSync,
20
+ writeFileSync,
21
+ } from "node:fs";
22
+ import { tmpdir } from "node:os";
23
+ import { join } from "node:path";
24
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
25
+
26
+ let repoDir = "";
27
+
28
+ // The module resolves the workspace through `getWorkspaceDir()`; point it at
29
+ // the temp repository. `getWorkspaceGitService` is left real so the git
30
+ // invocations under test are the ones that ship.
31
+ mock.module("../util/platform.js", () => ({
32
+ getWorkspaceDir: () => repoDir,
33
+ }));
34
+
35
+ import { getSkillHistory } from "./skill-history.js";
36
+
37
+ function git(...args: string[]): string {
38
+ return execFileSync("git", args, {
39
+ cwd: repoDir,
40
+ encoding: "utf-8",
41
+ env: {
42
+ ...process.env,
43
+ GIT_AUTHOR_NAME: "Test",
44
+ GIT_AUTHOR_EMAIL: "test@example.com",
45
+ GIT_COMMITTER_NAME: "Test",
46
+ GIT_COMMITTER_EMAIL: "test@example.com",
47
+ },
48
+ });
49
+ }
50
+
51
+ /** Write a file under the repo, creating parents. */
52
+ function write(relPath: string, content: string): void {
53
+ const full = join(repoDir, relPath);
54
+ mkdirSync(join(full, ".."), { recursive: true });
55
+ writeFileSync(full, content, "utf-8");
56
+ }
57
+
58
+ function commit(message: string): void {
59
+ git("add", "-A");
60
+ git("commit", "--no-verify", "-m", message);
61
+ }
62
+
63
+ beforeEach(() => {
64
+ repoDir = mkdtempSync(join(tmpdir(), "skill-history-"));
65
+ git("init", "-b", "main");
66
+ });
67
+
68
+ afterEach(() => {
69
+ rmSync(repoDir, { recursive: true, force: true });
70
+ repoDir = "";
71
+ });
72
+
73
+ describe("getSkillHistory", () => {
74
+ test("returns one entry per update, with the diff scoped to that skill", async () => {
75
+ write("skills/alpha/SKILL.md", "# Alpha\n\nStep one.\n");
76
+ write("skills/beta/SKILL.md", "# Beta\n\nUnrelated.\n");
77
+ commit("initial");
78
+
79
+ // A batched commit, the way the workspace heartbeat writes them: this
80
+ // skill, an unrelated skill, and a conversation file all at once.
81
+ write("skills/alpha/SKILL.md", "# Alpha\n\nStep one, corrected.\n");
82
+ write("skills/beta/SKILL.md", "# Beta\n\nAlso changed.\n");
83
+ write("conversations/whatever.jsonl", "{}\n");
84
+ commit("auto-commit: heartbeat safety net (3 files)");
85
+
86
+ const history = await getSkillHistory("alpha");
87
+
88
+ expect(history.skillId).toBe("alpha");
89
+ expect(history.revisions).toHaveLength(2);
90
+ // Newest first.
91
+ const [latest] = history.revisions;
92
+ expect(latest!.files).toEqual(["SKILL.md"]);
93
+ expect(latest!.diff).toContain("Step one, corrected.");
94
+ // The other skill and the conversation file are absent even though the
95
+ // same commit changed them.
96
+ expect(latest!.diff).not.toContain("Also changed.");
97
+ expect(latest!.diff).not.toContain("conversations/");
98
+ });
99
+
100
+ test("combines SKILL.md and companion changes from one update into a single entry", async () => {
101
+ write("skills/alpha/SKILL.md", "# Alpha\n");
102
+ commit("initial");
103
+
104
+ write("skills/alpha/SKILL.md", "# Alpha\n\nRun the script.\n");
105
+ write("skills/alpha/scripts/export.py", "print('v1')\n");
106
+ write("skills/alpha/references/gotchas.md", "Watch the rate limit.\n");
107
+ commit("auto-commit: heartbeat safety net (3 files)");
108
+
109
+ const history = await getSkillHistory("alpha");
110
+
111
+ // One update, not three per-file entries.
112
+ const [latest] = history.revisions;
113
+ expect(latest!.files.sort()).toEqual([
114
+ "SKILL.md",
115
+ "references/gotchas.md",
116
+ "scripts/export.py",
117
+ ]);
118
+ expect(latest!.diff).toContain("Run the script.");
119
+ expect(latest!.diff).toContain("print('v1')");
120
+ expect(latest!.diff).toContain("Watch the rate limit.");
121
+ });
122
+
123
+ test("a load-only commit does not appear as an update", async () => {
124
+ write("skills/alpha/SKILL.md", "# Alpha\n");
125
+ write(
126
+ "skills/alpha/install-meta.json",
127
+ JSON.stringify({ origin: "custom", lastUsedAt: "2026-08-04" }),
128
+ );
129
+ commit("initial");
130
+
131
+ // The skill was loaded, so only the usage stamp moved. Roughly half of a
132
+ // real skill's commits look like this.
133
+ write(
134
+ "skills/alpha/install-meta.json",
135
+ JSON.stringify({ origin: "custom", lastUsedAt: "2026-08-05" }),
136
+ );
137
+ commit("auto-commit: heartbeat safety net (1 file)");
138
+
139
+ const history = await getSkillHistory("alpha");
140
+
141
+ // Only the creating commit counts; the stamp bump is not an update.
142
+ expect(history.revisions).toHaveLength(1);
143
+ expect(history.revisions[0]!.files).toEqual(["SKILL.md"]);
144
+ });
145
+
146
+ test("a real edit alongside a stamp bump keeps the edit and drops the stamp", async () => {
147
+ write("skills/alpha/SKILL.md", "# Alpha\n");
148
+ write(
149
+ "skills/alpha/install-meta.json",
150
+ JSON.stringify({ lastUsedAt: "1" }),
151
+ );
152
+ commit("initial");
153
+
154
+ write("skills/alpha/SKILL.md", "# Alpha\n\nRefined.\n");
155
+ write(
156
+ "skills/alpha/install-meta.json",
157
+ JSON.stringify({ lastUsedAt: "2" }),
158
+ );
159
+ commit("auto-commit: heartbeat safety net (2 files)");
160
+
161
+ const history = await getSkillHistory("alpha");
162
+
163
+ const [latest] = history.revisions;
164
+ expect(latest!.files).toEqual(["SKILL.md"]);
165
+ expect(latest!.diff).toContain("Refined.");
166
+ expect(latest!.diff).not.toContain("lastUsedAt");
167
+ });
168
+
169
+ test("respects the limit after filtering, not before", async () => {
170
+ write("skills/alpha/SKILL.md", "v0\n");
171
+ commit("initial");
172
+ // Interleave real edits with load-only commits, so a naive
173
+ // `--max-count=limit` would return mostly stamps.
174
+ for (let i = 1; i <= 4; i++) {
175
+ write(
176
+ "skills/alpha/install-meta.json",
177
+ JSON.stringify({ lastUsedAt: `stamp-${i}` }),
178
+ );
179
+ commit(`stamp ${i}`);
180
+ write("skills/alpha/SKILL.md", `v${i}\n`);
181
+ commit(`edit ${i}`);
182
+ }
183
+
184
+ const history = await getSkillHistory("alpha", { limit: 3 });
185
+
186
+ expect(history.revisions).toHaveLength(3);
187
+ // Every returned entry is a real edit.
188
+ for (const revision of history.revisions) {
189
+ expect(revision.files).toEqual(["SKILL.md"]);
190
+ }
191
+ });
192
+
193
+ test("reports when older history was squashed away", async () => {
194
+ write("skills/alpha/SKILL.md", "# Alpha\n");
195
+ commit("Compacted workspace history (14667 commits squashed)");
196
+ write("skills/alpha/SKILL.md", "# Alpha\n\nMore.\n");
197
+ commit("auto-commit: heartbeat safety net (1 file)");
198
+
199
+ const history = await getSkillHistory("alpha");
200
+
201
+ // The caller needs this to avoid presenting the oldest entry as creation.
202
+ expect(history.truncatedByCompaction).toBe(true);
203
+ });
204
+
205
+ test("an untracked skill has empty history rather than an error", async () => {
206
+ write("skills/alpha/SKILL.md", "# Alpha\n");
207
+ commit("initial");
208
+
209
+ const history = await getSkillHistory("never-committed");
210
+
211
+ expect(history.revisions).toEqual([]);
212
+ expect(history.skillId).toBe("never-committed");
213
+ });
214
+
215
+ test("a repository-controlled textconv driver is never executed", async () => {
216
+ // `.gitattributes` selects a diff driver and git config names the program
217
+ // for it. Both are writable through ordinary workspace paths, so rendering
218
+ // a patch must not hand control to them (ATL-1238).
219
+ write("skills/alpha/SKILL.md", "# Alpha\n");
220
+ write(".gitattributes", "*.md diff=evil\n");
221
+ commit("initial");
222
+ write("skills/alpha/SKILL.md", "# Alpha\n\nEdited.\n");
223
+ commit("auto-commit: heartbeat safety net (1 file)");
224
+
225
+ const sentinel = join(repoDir, "textconv-executed");
226
+ git("config", "diff.evil.textconv", `sh -c "touch ${sentinel}; cat"`);
227
+
228
+ const history = await getSkillHistory("alpha");
229
+
230
+ // The driver stays unrun...
231
+ expect(existsSync(sentinel)).toBe(false);
232
+ // ...and the diff still renders, so the hardening did not cost the feature.
233
+ expect(history.revisions[0]!.diff).toContain("Edited.");
234
+ });
235
+
236
+ // `--no-ext-diff` guards the sibling vector, `diff.<driver>.command`, but has
237
+ // no test here: an external diff driver does not fire in this environment
238
+ // even without the flag, so an assertion about it would pass whether or not
239
+ // the guard were present.
240
+
241
+ test("a traversal-shaped id is rejected before it reaches a pathspec", async () => {
242
+ write("skills/alpha/SKILL.md", "# Alpha\n");
243
+ commit("initial");
244
+
245
+ await expect(getSkillHistory("../../etc")).rejects.toThrow(
246
+ /Invalid skill id/,
247
+ );
248
+ });
249
+
250
+ test("a workspace that is not a repository yields empty history, and stays not a repository", async () => {
251
+ const bare = mkdtempSync(join(tmpdir(), "skill-history-norepo-"));
252
+ const previous = repoDir;
253
+ repoDir = bare;
254
+ try {
255
+ const history = await getSkillHistory("alpha");
256
+
257
+ expect(history.revisions).toEqual([]);
258
+ // The empty result is not enough on its own: reading through
259
+ // `runReadOnlyGit` would ALSO return empty here, having quietly created
260
+ // the repository first. This route is a GET, so the absence of the
261
+ // write is the actual invariant.
262
+ expect(existsSync(join(bare, ".git"))).toBe(false);
263
+ expect(readdirSync(bare)).toEqual([]);
264
+ } finally {
265
+ repoDir = previous;
266
+ rmSync(bare, { recursive: true, force: true });
267
+ }
268
+ });
269
+ });
@@ -0,0 +1,250 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Skill revision history, read from the workspace git repository.
3
+ // ---------------------------------------------------------------------------
4
+ //
5
+ // The workspace is a git repo with an auto-committing heartbeat, and `skills/`
6
+ // is tracked, so every managed-skill write already has its prior content
7
+ // retained. This module reads that history rather than storing a second copy:
8
+ // `createManagedSkill` writes through an atomic rename and keeps no version of
9
+ // its own, but the commit underneath it does.
10
+ //
11
+ // A revision here is ONE UPDATE TO THE WHOLE SKILL, not a per-file log. A
12
+ // single commit is diffed against the skill's directory, so `SKILL.md`,
13
+ // `scripts/`, and `references/` changes made together appear as one entry with
14
+ // one combined diff, which is what "what changed the last time this skill was
15
+ // updated" means. The commit itself usually touches many unrelated files (the
16
+ // heartbeat batches by count and age), so the pathspec is what makes the diff
17
+ // legible.
18
+ //
19
+ // Two properties of that history shape the output, and both are load-bearing:
20
+ //
21
+ // - `install-meta.json` is EXCLUDED. It carries a `lastUsedAt` stamp
22
+ // refreshed every time a skill is loaded, so roughly half of a skill's
23
+ // commits touch nothing else. Including it would report a skill as
24
+ // "updated" on days nobody edited it, which is worse than showing no
25
+ // history at all. Revisions left empty by the exclusion are dropped.
26
+ // - History is BOUNDED. The workspace periodically squashes
27
+ // ("Compacted workspace history"), so the oldest revision available is not
28
+ // necessarily the skill's creation. Callers should present the list as
29
+ // "recent changes", never as a complete record.
30
+ //
31
+ // Commit subjects are deliberately not surfaced: they read
32
+ // `auto-commit: heartbeat safety net (164 files, changes older than 900s)`,
33
+ // which describes the batch rather than the skill and would actively mislead.
34
+ //
35
+ // Every git call goes through `runReadOnlyGitWithoutInit`, NOT
36
+ // `runReadOnlyGit`. The latter awaits `ensureInitialized()`, which creates the
37
+ // repository, writes `.gitignore` and the hooks directory, makes an initial
38
+ // commit, and schedules a history compaction when the workspace is not yet a
39
+ // repo. This module is reached from an HTTP GET, which `src/runtime/AGENTS.md`
40
+ // requires to be side-effect-free, so observing history must never be the
41
+ // thing that brings a repository into existence.
42
+
43
+ import { getLogger } from "../util/logger.js";
44
+ import { getWorkspaceDir } from "../util/platform.js";
45
+ import { getWorkspaceGitService } from "../workspace/git-service.js";
46
+ import { validateManagedSkillId } from "./managed-store.js";
47
+
48
+ const log = getLogger("skill-history");
49
+
50
+ /** How many revisions to return when the caller does not specify. */
51
+ export const DEFAULT_SKILL_HISTORY_LIMIT = 20;
52
+
53
+ /** Hard ceiling, so one request cannot walk an entire repository. */
54
+ export const MAX_SKILL_HISTORY_LIMIT = 100;
55
+
56
+ /** One update to a skill: a commit, diffed to that skill's directory. */
57
+ export interface SkillRevision {
58
+ /** Abbreviated commit hash. Opaque to callers; useful for support. */
59
+ id: string;
60
+ /** ISO-8601 commit timestamp. */
61
+ changedAt: string;
62
+ /** Paths changed inside the skill, relative to the skill directory. */
63
+ files: string[];
64
+ /** Unified diff of this commit, restricted to the skill's directory. */
65
+ diff: string;
66
+ }
67
+
68
+ export interface SkillHistory {
69
+ skillId: string;
70
+ revisions: SkillRevision[];
71
+ /**
72
+ * Whether history may be incomplete because the workspace squashed older
73
+ * commits. When true the oldest revision listed is a floor, not the
74
+ * skill's creation.
75
+ */
76
+ truncatedByCompaction: boolean;
77
+ }
78
+
79
+ /**
80
+ * Field separator for the `git log` format: an ASCII unit separator, written
81
+ * as an escape so the source stays copy-paste safe. It cannot occur in a
82
+ * commit hash or an ISO timestamp.
83
+ */
84
+ const FIELD = "\u001f";
85
+
86
+ /**
87
+ * Diff options that must accompany EVERY git read here.
88
+ *
89
+ * `git show` and `git diff` honour repository-controlled helpers by default:
90
+ * a `.gitattributes` entry can select a diff driver, and a `diff.<driver>.
91
+ * textconv` or `diff.<driver>.command` setting names a program git then
92
+ * EXECUTES while rendering the patch. Workspace files and git metadata are
93
+ * writable by model and tool paths, so without these flags merely viewing a
94
+ * skill's history would run whatever the workspace asked for, inside the
95
+ * daemon, on behalf of any caller holding `settings.read` (ATL-1238).
96
+ *
97
+ * Applied through `readGit` rather than at each call site, so a future reader
98
+ * cannot add a git invocation that quietly omits them.
99
+ */
100
+ const DIFF_HARDENING = ["--no-textconv", "--no-ext-diff"];
101
+
102
+ /**
103
+ * Run one hardened, non-initializing git read. The subcommand is passed
104
+ * separately because the hardening flags have to follow it.
105
+ */
106
+ async function readGit(
107
+ git: ReturnType<typeof getWorkspaceGitService>,
108
+ subcommand: "log" | "show",
109
+ args: string[],
110
+ ): Promise<{ stdout: string; stderr: string }> {
111
+ return git.runReadOnlyGitWithoutInit([
112
+ subcommand,
113
+ ...DIFF_HARDENING,
114
+ ...args,
115
+ ]);
116
+ }
117
+
118
+ /**
119
+ * Read a skill's recent revisions from workspace git.
120
+ *
121
+ * Returns an empty history rather than throwing when git is unavailable, the
122
+ * workspace is not a repository, or the skill has no tracked changes: history
123
+ * is a read-only enrichment and must never be the reason a caller fails.
124
+ * An invalid skill id DOES throw, because it means the caller passed
125
+ * unvalidated input into a pathspec.
126
+ */
127
+ export async function getSkillHistory(
128
+ skillId: string,
129
+ options: { limit?: number } = {},
130
+ ): Promise<SkillHistory> {
131
+ const invalid = validateManagedSkillId(skillId);
132
+ if (invalid) {
133
+ throw new Error(`Invalid skill id: ${invalid}`);
134
+ }
135
+ const limit = Math.min(
136
+ Math.max(1, options.limit ?? DEFAULT_SKILL_HISTORY_LIMIT),
137
+ MAX_SKILL_HISTORY_LIMIT,
138
+ );
139
+
140
+ const empty: SkillHistory = {
141
+ skillId,
142
+ revisions: [],
143
+ truncatedByCompaction: false,
144
+ };
145
+
146
+ let git: ReturnType<typeof getWorkspaceGitService>;
147
+ try {
148
+ git = getWorkspaceGitService(getWorkspaceDir());
149
+ } catch (err) {
150
+ log.warn({ err, skillId }, "workspace git unavailable; no skill history");
151
+ return empty;
152
+ }
153
+
154
+ const skillPath = `skills/${skillId}/`;
155
+ // Exclude the usage stamp so a skill that was merely LOADED does not read as
156
+ // edited. `:(exclude)` is git pathspec magic, applied to both the log and
157
+ // the per-commit diff so the two can never disagree about what counts.
158
+ const pathspec = [skillPath, `:(exclude)${skillPath}install-meta.json`];
159
+
160
+ let shas: Array<{ sha: string; changedAt: string }>;
161
+ try {
162
+ const { stdout } = await readGit(git, "log", [
163
+ // Committer date, not author date. `git log` orders by commit date, so
164
+ // reporting the author date could label the list newest-first while its
165
+ // displayed dates disagree with that order.
166
+ `--format=%h${FIELD}%cI`,
167
+ // Ask for more than `limit`: commits whose only in-skill change is
168
+ // excluded by the pathspec still appear here, so the list is filtered
169
+ // down afterwards and would otherwise come up short.
170
+ `--max-count=${limit * 4}`,
171
+ "--",
172
+ ...pathspec,
173
+ ]);
174
+ shas = stdout
175
+ .split("\n")
176
+ .map((line) => line.trim())
177
+ .filter((line) => line.length > 0)
178
+ .map((line) => {
179
+ const [sha, changedAt] = line.split(FIELD);
180
+ return { sha: sha ?? "", changedAt: changedAt ?? "" };
181
+ })
182
+ .filter((entry) => entry.sha.length > 0);
183
+ } catch (err) {
184
+ log.warn({ err, skillId }, "git log failed; no skill history");
185
+ return empty;
186
+ }
187
+
188
+ const revisions: SkillRevision[] = [];
189
+ for (const { sha, changedAt } of shas) {
190
+ if (revisions.length >= limit) {
191
+ break;
192
+ }
193
+ let diff: string;
194
+ let files: string[];
195
+ try {
196
+ const [diffResult, nameResult] = await Promise.all([
197
+ readGit(git, "show", ["--format=", sha, "--", ...pathspec]),
198
+ readGit(git, "show", [
199
+ "--format=",
200
+ "--name-only",
201
+ sha,
202
+ "--",
203
+ ...pathspec,
204
+ ]),
205
+ ]);
206
+ diff = diffResult.stdout.trim();
207
+ files = nameResult.stdout
208
+ .split("\n")
209
+ .map((line) => line.trim())
210
+ .filter((line) => line.startsWith(skillPath))
211
+ .map((line) => line.slice(skillPath.length))
212
+ .filter((line) => line.length > 0);
213
+ } catch (err) {
214
+ log.warn({ err, skillId, sha }, "git show failed; skipping revision");
215
+ continue;
216
+ }
217
+ // Nothing left once the usage stamp is excluded: the skill was loaded,
218
+ // not changed.
219
+ if (diff.length === 0 || files.length === 0) {
220
+ continue;
221
+ }
222
+ revisions.push({ id: sha, changedAt, files, diff });
223
+ }
224
+
225
+ return {
226
+ skillId,
227
+ revisions,
228
+ truncatedByCompaction: await hasCompactedHistory(git),
229
+ };
230
+ }
231
+
232
+ /**
233
+ * Whether the workspace has squashed older commits, which caps how far back
234
+ * any skill's history can reach. Best-effort: an error here only means the
235
+ * caller loses the caveat, never the history.
236
+ */
237
+ async function hasCompactedHistory(
238
+ git: ReturnType<typeof getWorkspaceGitService>,
239
+ ): Promise<boolean> {
240
+ try {
241
+ const { stdout } = await readGit(git, "log", [
242
+ "--format=%s",
243
+ "--max-count=1",
244
+ "--grep=Compacted workspace history",
245
+ ]);
246
+ return stdout.trim().length > 0;
247
+ } catch {
248
+ return false;
249
+ }
250
+ }
@@ -480,7 +480,7 @@ export async function installExternalSkill(
480
480
  contentHash: computeSkillHash(stagedDir) ?? undefined,
481
481
  });
482
482
 
483
- installSkillDependenciesIfPresent(stagedDir);
483
+ await installSkillDependenciesIfPresent(stagedDir);
484
484
  commitStagedSkillInstall(skillSlug, stagedDir);
485
485
  } catch (err) {
486
486
  rmSync(stagedDir, { recursive: true, force: true });
@@ -214,6 +214,8 @@ class VellumManagedBatchTranscriber implements BatchTranscriber {
214
214
  readonly providerId = "vellum" as const;
215
215
  readonly boundaryId = "daemon-batch" as const;
216
216
 
217
+ constructor(private readonly language: string | undefined) {}
218
+
217
219
  async transcribe(
218
220
  request: SttTranscribeRequest,
219
221
  ): Promise<SttTranscribeResult> {
@@ -223,6 +225,7 @@ class VellumManagedBatchTranscriber implements BatchTranscriber {
223
225
  request.audio,
224
226
  request.mimeType,
225
227
  request.signal,
228
+ this.language,
226
229
  );
227
230
  }
228
231
  }
@@ -237,12 +240,11 @@ class VellumManagedBatchTranscriber implements BatchTranscriber {
237
240
  * is unavailable.
238
241
  *
239
242
  * `language` is the spoken language, forwarded to providers whose batch API
240
- * accepts one: Deepgram (where `"multi"` also pins nova-3) and xAI (where
243
+ * accepts one: Deepgram (where `"multi"` also pins nova-3), xAI (where
241
244
  * `"multi"` is dropped because it is a Deepgram-specific value, not a
242
- * language code). Whisper and Gemini auto-detect natively and take no
243
- * language parameter, so it is silently ignored for them, as is the vellum
244
- * managed path (the platform speech proxy accepts no language parameter;
245
- * see the deferral note in `resolveBatchTranscriber`).
245
+ * language code), and the vellum managed path, whose platform proxy passes
246
+ * it to Deepgram server-side. Whisper and Gemini auto-detect natively and
247
+ * take no language parameter, so it is silently ignored for them.
246
248
  */
247
249
  export function createDaemonBatchTranscriber(
248
250
  apiKey: string | null | undefined,
@@ -251,7 +253,7 @@ export function createDaemonBatchTranscriber(
251
253
  ): BatchTranscriber | null {
252
254
  // vellum authenticates via the platform connection, not an API key.
253
255
  if (providerId === "vellum") {
254
- return new VellumManagedBatchTranscriber();
256
+ return new VellumManagedBatchTranscriber(language);
255
257
  }
256
258
  if (!apiKey) {
257
259
  return null;
@@ -20,6 +20,31 @@ describe("buildAdvisorSystem", () => {
20
20
  expect(prompt).not.toContain("<agent_system_prompt>");
21
21
  });
22
22
 
23
+ test("tells the advisor it has read-only tools for verifying decisive facts", () => {
24
+ const prompt = buildAdvisorSystem(null);
25
+ expect(prompt).toContain("read-only tools");
26
+ expect(prompt).toContain("read files");
27
+ expect(prompt).toContain("verification, not exploration");
28
+ expect(prompt).toContain("You cannot change anything");
29
+ });
30
+
31
+ test("does not offer the advisor a memory or conversation search", () => {
32
+ // The advisor's read tools stop at the workspace. Naming `recall` here
33
+ // would advertise a search the role allowlist does not grant, and would
34
+ // contradict the scope the consult framing promises the user.
35
+ const prompt = buildAdvisorSystem(null);
36
+ expect(prompt).not.toContain("recall");
37
+ expect(prompt).toContain("you cannot see other conversations");
38
+ });
39
+
40
+ test("does not claim the advisor is tool-less", () => {
41
+ // The advisor can open a file to check a fact; a prompt that says otherwise
42
+ // suppresses the read it was given tools for.
43
+ const prompt = buildAdvisorSystem(null);
44
+ expect(prompt).not.toContain("You have no tools");
45
+ expect(prompt).not.toContain("cannot search, read files, or run commands");
46
+ });
47
+
23
48
  test("keeps the situational context pack out of the system prompt", () => {
24
49
  // System Prompt Minimalism: the pack rides in the request turn instead.
25
50
  expect(buildAdvisorSystem("parent")).not.toContain("<agent_environment>");
@@ -30,11 +30,13 @@ Evaluate the work along these dimensions, and lead with whatever matters most ri
30
30
  - Verification: If the agent has no clear way to confirm its work is correct, tell it how it will know.
31
31
 
32
32
  How to advise:
33
- - Be specific and grounded. Cite what you actually see in the transcript a particular result, a line of reasoning, a command that failed. Never invent details that aren't there; if a decisive fact is missing, say what the agent should go find out.
33
+ - Be specific and grounded. Cite what you actually see in the transcript: a particular result, a line of reasoning, a command that failed. Never invent details that aren't there; if a decisive fact is missing, either check it yourself with your read tools or say what the agent should go find out.
34
34
  - Be decisive. Give a clear recommendation, not a menu of equally weighted options. When genuinely uncertain, say so and state what would resolve it.
35
35
  - Prioritize ruthlessly. Lead with the highest-leverage point. Don't restate at length what the agent already did well, and don't pad the response with minor nitpicks — a focused, well-reasoned critique beats an exhaustive one.
36
36
  - Stay in your lane. Advise the agent; do not role-play as it, write its final deliverable, or take its next action for it. If the agent is already on the right track, confirm it and sharpen the plan rather than manufacturing objections.
37
37
 
38
+ You have read-only tools: you may read files, list them, and search code to check a decisive fact before you advise. Use them with restraint. Answer from the inherited conversation whenever it already tells you what you need, and read only when a specific fact would change your advice: reading is for verification, not exploration. You cannot change anything and you cannot see other conversations, and the agent is waiting on you, so every call you make delays the guidance it gets.
39
+
38
40
  Write as much as the guidance genuinely needs, and no more.`;
39
41
  let prompt = base;
40
42
  if (originalSystemPrompt) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Sanitize an inherited parent transcript before it is injected into a
3
- * tool-less advisor consult subagent.
3
+ * advisor consult subagent.
4
4
  *
5
5
  * `Conversation.injectInheritedContext` injects the parent's messages VERBATIM
6
6
  * with no sanitization, so the advisor path must run this over the parent