@vellumai/assistant 0.12.1 → 0.12.2-dev.202609162314.7778bc8

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 (872) hide show
  1. package/.env.example +2 -0
  2. package/AGENTS.md +5 -1
  3. package/ARCHITECTURE.md +20 -21
  4. package/Dockerfile +7 -7
  5. package/docs/architecture/integrations.md +7 -0
  6. package/docs/architecture/memory.md +11 -2
  7. package/docs/architecture/turn-actor.md +15 -8
  8. package/docs/credential-execution-service.md +1 -1
  9. package/docs/desktop-browser-cli.md +35 -0
  10. package/docs/guardian-request-flow.md +16 -0
  11. package/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
  12. package/node_modules/@vellumai/environments/src/shell.ts +24 -0
  13. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -2
  14. package/node_modules/@vellumai/slack-text/src/index.ts +13 -8
  15. package/node_modules/@vellumai/slack-text/src/label-resolution-entities.test.ts +95 -0
  16. package/openapi.yaml +579 -111
  17. package/package.json +7 -4
  18. package/scripts/bundled-plugin-packages.ts +154 -0
  19. package/scripts/generate-bundled-plugin-packages.ts +29 -0
  20. package/scripts/postinstall.ts +33 -0
  21. package/scripts/smoke-desktop-browser-cli.ts +280 -0
  22. package/scripts/smoke-desktop-window-theme.ts +186 -0
  23. package/scripts/sync-llm-catalog.ts +3 -0
  24. package/scripts/test.ts +15 -13
  25. package/scripts/voice-ttft-spike.ts +2 -2
  26. package/src/__tests__/agent-loop.test.ts +259 -0
  27. package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
  28. package/src/__tests__/anthropic-provider.test.ts +55 -63
  29. package/src/__tests__/app-compiler.test.ts +6 -0
  30. package/src/__tests__/app-control-tool-schemas.test.ts +5 -2
  31. package/src/__tests__/app-dir-path-guard.test.ts +1 -3
  32. package/src/__tests__/approval-interception-trust-gates.test.ts +40 -0
  33. package/src/__tests__/assistant-event-hub-machine-name.test.ts +6 -7
  34. package/src/__tests__/assistant-event-hub.test.ts +44 -0
  35. package/src/__tests__/attachments-store.test.ts +22 -3
  36. package/src/__tests__/channel-approval.test.ts +9 -14
  37. package/src/__tests__/channel-reply-delivery.test.ts +56 -0
  38. package/src/__tests__/computer-use-screenshot-attachments.test.ts +411 -0
  39. package/src/__tests__/computer-use-screenshot-selection.test.ts +50 -0
  40. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
  41. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +5 -2
  42. package/src/__tests__/computer-use-tools.test.ts +19 -7
  43. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  44. package/src/__tests__/config-schema.test.ts +29 -30
  45. package/src/__tests__/config-sounds-sync.test.ts +23 -0
  46. package/src/__tests__/config-watcher.test.ts +23 -8
  47. package/src/__tests__/connection-model-compat.test.ts +2 -2
  48. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  49. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
  50. package/src/__tests__/conversation-agent-loop.test.ts +257 -6
  51. package/src/__tests__/conversation-attachments.test.ts +106 -0
  52. package/src/__tests__/conversation-error.test.ts +4 -1
  53. package/src/__tests__/conversation-fork-crud.test.ts +191 -0
  54. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  55. package/src/__tests__/conversation-pairing.test.ts +26 -0
  56. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -10
  57. package/src/__tests__/conversation-queue.test.ts +48 -207
  58. package/src/__tests__/conversation-retry-discard.test.ts +54 -1
  59. package/src/__tests__/conversation-runtime-assembly.test.ts +33 -3
  60. package/src/__tests__/conversation-skill-tools.test.ts +27 -0
  61. package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
  62. package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +1 -0
  63. package/src/__tests__/conversation-surfaces-point-at-capability.test.ts +1 -0
  64. package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
  65. package/src/__tests__/conversation-title-service.test.ts +14 -10
  66. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +3 -5
  67. package/src/__tests__/conversation-tool-setup-attribution.test.ts +51 -0
  68. package/src/__tests__/credential-execution-client.test.ts +70 -53
  69. package/src/__tests__/credential-record-retire.test.ts +171 -1
  70. package/src/__tests__/credential-routes.test.ts +250 -3
  71. package/src/__tests__/credential-security-invariants.test.ts +5 -3
  72. package/src/__tests__/cu-unified-flow.test.ts +14 -4
  73. package/src/__tests__/db-conversation-tool-surface.test.ts +144 -0
  74. package/src/__tests__/document-sync-tags.test.ts +25 -0
  75. package/src/__tests__/drain-kick-guard.test.ts +0 -2
  76. package/src/__tests__/drain-requeue-on-contention.test.ts +0 -6
  77. package/src/__tests__/events-tail-route.test.ts +33 -0
  78. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  79. package/src/__tests__/external-plugin-loader.test.ts +52 -0
  80. package/src/__tests__/git-porcelain.test.ts +47 -0
  81. package/src/__tests__/headless-browser-mode.test.ts +48 -0
  82. package/src/__tests__/heartbeat-service.test.ts +56 -40
  83. package/src/__tests__/helpers/set-workspace-mcp.ts +11 -0
  84. package/src/__tests__/history-repair.test.ts +53 -0
  85. package/src/__tests__/host-bash-proxy.test.ts +26 -45
  86. package/src/__tests__/host-browser-proxy.test.ts +6 -17
  87. package/src/__tests__/host-cu-proxy.test.ts +712 -18
  88. package/src/__tests__/host-file-proxy-targeted.test.ts +23 -0
  89. package/src/__tests__/host-file-proxy.test.ts +11 -23
  90. package/src/__tests__/host-transfer-proxy-targeted.test.ts +30 -9
  91. package/src/__tests__/inference-profile-session-handler.test.ts +26 -0
  92. package/src/__tests__/list-all-apps.test.ts +40 -8
  93. package/src/__tests__/list-messages-camera-frame.test.ts +121 -0
  94. package/src/__tests__/list-messages-tool-merge.test.ts +85 -1
  95. package/src/__tests__/llm-catalog-parity.test.ts +51 -3
  96. package/src/__tests__/managed-store.test.ts +121 -0
  97. package/src/__tests__/mcp-auth-routes.test.ts +104 -8
  98. package/src/__tests__/mcp-client-auth.test.ts +54 -0
  99. package/src/__tests__/mcp-config-secret-boundary.test.ts +78 -136
  100. package/src/__tests__/mcp-health-check.test.ts +40 -43
  101. package/src/__tests__/mcp-list-plugin-servers.test.ts +85 -42
  102. package/src/__tests__/mcp-tool-annotations-risk.test.ts +4 -2
  103. package/src/__tests__/message-deleted-hook-dispatch.test.ts +119 -0
  104. package/src/__tests__/messages-after-tiebreaker.test.ts +91 -0
  105. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  106. package/src/__tests__/messaging-send-tool.test.ts +355 -548
  107. package/src/__tests__/model-intents.test.ts +3 -0
  108. package/src/__tests__/notification-vellum-adapter.test.ts +85 -2
  109. package/src/__tests__/oauth-apps-routes.test.ts +1 -0
  110. package/src/__tests__/oauth-commands-routes.test.ts +282 -101
  111. package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
  112. package/src/__tests__/oauth-provider-profiles.test.ts +18 -0
  113. package/src/__tests__/oauth-provider-serializer.test.ts +23 -0
  114. package/src/__tests__/oauth-providers-routes.test.ts +3 -0
  115. package/src/__tests__/openai-provider.test.ts +1 -0
  116. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  117. package/src/__tests__/persist-media-references.test.ts +50 -0
  118. package/src/__tests__/platform-callback-registration.test.ts +8 -16
  119. package/src/__tests__/platform-client-verify-credential.test.ts +2 -0
  120. package/src/__tests__/plugin-import-boundary-guard.test.ts +13 -0
  121. package/src/__tests__/qdrant-manager.test.ts +132 -0
  122. package/src/__tests__/resolve-app.test.ts +135 -0
  123. package/src/__tests__/run-conversation-turn-persistence.test.ts +138 -1
  124. package/src/__tests__/scaffold-managed-skill-tool.test.ts +317 -6
  125. package/src/__tests__/schedule-routes.test.ts +20 -0
  126. package/src/__tests__/scheduler-result-notification.test.ts +23 -4
  127. package/src/__tests__/script-proxy-certs.test.ts +35 -0
  128. package/src/__tests__/secret-routes-acp-guard.test.ts +59 -1
  129. package/src/__tests__/secret-routes-platform-proxy.test.ts +86 -31
  130. package/src/__tests__/secret-routes-scrub.test.ts +22 -27
  131. package/src/__tests__/secure-keys-managed-failover.test.ts +8 -0
  132. package/src/__tests__/secure-keys.test.ts +7 -3
  133. package/src/__tests__/server-tool-pairing.test.ts +107 -0
  134. package/src/__tests__/service-account-token.test.ts +247 -0
  135. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  136. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  137. package/src/__tests__/skills.test.ts +20 -4
  138. package/src/__tests__/source-fingerprint.test.ts +184 -0
  139. package/src/__tests__/subagent-tool-gate-mode.test.ts +239 -3
  140. package/src/__tests__/subagent-tools.test.ts +3 -2
  141. package/src/__tests__/telephony-tts-guard.test.ts +38 -3
  142. package/src/__tests__/terminal-tools.test.ts +8 -0
  143. package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
  144. package/src/__tests__/tool-result-follow-up.test.ts +99 -0
  145. package/src/__tests__/tool-result-metadata-plumbing.test.ts +63 -0
  146. package/src/__tests__/ui-channel-variants.test.ts +1 -56
  147. package/src/__tests__/unicode.test.ts +49 -0
  148. package/src/__tests__/user-plugin-loader.test.ts +21 -0
  149. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +4 -0
  150. package/src/__tests__/watch-retro-tool-availability.test.ts +8 -17
  151. package/src/__tests__/workspace-git-service.test.ts +26 -0
  152. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +336 -0
  153. package/src/acp/__tests__/acp-claude-oauth.test.ts +257 -6
  154. package/src/acp/__tests__/acp-credentials.test.ts +13 -0
  155. package/src/acp/__tests__/agent-process.test.ts +258 -4
  156. package/src/acp/__tests__/auth-required.test.ts +96 -0
  157. package/src/acp/__tests__/claude-token-refresh.test.ts +257 -0
  158. package/src/acp/__tests__/client-handler.test.ts +90 -2
  159. package/src/acp/__tests__/helpers/acp-model-option.ts +51 -0
  160. package/src/acp/__tests__/prepare-agent-env.test.ts +60 -1
  161. package/src/acp/__tests__/session-manager-persistence.test.ts +5 -1
  162. package/src/acp/__tests__/session-manager-resume.test.ts +270 -6
  163. package/src/acp/__tests__/session-manager-usage.test.ts +4 -2
  164. package/src/acp/__tests__/session-manager.test.ts +895 -4
  165. package/src/acp/acp-claude-oauth.ts +328 -14
  166. package/src/acp/acp-credentials.ts +19 -0
  167. package/src/acp/agent-process.test.ts +4 -1
  168. package/src/acp/agent-process.ts +96 -10
  169. package/src/acp/auth-required.ts +50 -1
  170. package/src/acp/auto-install.test.ts +9 -7
  171. package/src/acp/claude-token-refresh.ts +150 -0
  172. package/src/acp/client-handler.ts +16 -3
  173. package/src/acp/model-config.test.ts +166 -0
  174. package/src/acp/model-config.ts +138 -0
  175. package/src/acp/prepare-agent-env.ts +21 -6
  176. package/src/acp/resolve-agent.test.ts +220 -6
  177. package/src/acp/resolve-agent.ts +88 -23
  178. package/src/acp/session-manager.test.ts +196 -3
  179. package/src/acp/session-manager.ts +441 -18
  180. package/src/acp/session-snapshot.ts +260 -0
  181. package/src/acp/types.ts +50 -5
  182. package/src/agent/loop.ts +38 -12
  183. package/src/agent/tool-result-follow-up.ts +70 -0
  184. package/src/api/attachment-provenance.test.ts +68 -0
  185. package/src/api/computer-use-tool.test.ts +55 -0
  186. package/src/api/computer-use-tool.ts +27 -0
  187. package/src/api/events/acp-session-model-update.test.ts +88 -0
  188. package/src/api/events/acp-session-model-update.ts +46 -0
  189. package/src/api/events/app-files-changed.ts +4 -3
  190. package/src/api/events/assistant-outbound-attachment.ts +3 -0
  191. package/src/api/events/desktop-activity-changed.ts +10 -0
  192. package/src/api/events/notification-intent.ts +2 -0
  193. package/src/api/events/question-request.ts +1 -0
  194. package/src/api/events/user-message-echo.ts +7 -1
  195. package/src/api/index.ts +17 -0
  196. package/src/api/responses/conversation-message.ts +8 -0
  197. package/src/approvals/approval-primitive.ts +5 -2
  198. package/src/approvals/scoped-approval-grants.ts +6 -2
  199. package/src/apps/app-store.ts +7 -6
  200. package/src/apps/resolve-app.ts +81 -0
  201. package/src/apps/source-fingerprint.ts +266 -0
  202. package/src/avatar/identity-avatar.ts +7 -2
  203. package/src/browser/operations.ts +2 -1
  204. package/src/browser/types.ts +7 -0
  205. package/src/browser/virtual-desktop-target.ts +34 -0
  206. package/src/bundler/app-compiler.ts +15 -0
  207. package/src/calls/__tests__/barge-in-guard.test.ts +81 -0
  208. package/src/{__tests__ → calls/__tests__}/call-controller.test.ts +503 -82
  209. package/src/{__tests__ → calls/__tests__}/media-stream-audio-transcode.test.ts +1 -1
  210. package/src/{__tests__ → calls/__tests__}/media-stream-output.test.ts +37 -8
  211. package/src/{__tests__ → calls/__tests__}/media-stream-parser.test.ts +1 -1
  212. package/src/{__tests__ → calls/__tests__}/media-stream-server-integration.test.ts +150 -57
  213. package/src/{__tests__ → calls/__tests__}/media-stream-stt-session.test.ts +5 -5
  214. package/src/{__tests__ → calls/__tests__}/media-turn-detector.test.ts +1 -1
  215. package/src/{live-voice → calls}/__tests__/progress-narration.test.ts +27 -4
  216. package/src/{live-voice → calls}/__tests__/progress-phrases.test.ts +1 -1
  217. package/src/calls/__tests__/voice-control-protocol.test.ts +151 -27
  218. package/src/calls/__tests__/voice-leg-coordinator.test.ts +229 -0
  219. package/src/calls/__tests__/voice-progress-cadence.test.ts +274 -0
  220. package/src/{__tests__/voice-session-bridge.test.ts → calls/__tests__/voice-session-bridge-turn-flow.test.ts} +20 -12
  221. package/src/calls/__tests__/voice-session-bridge.test.ts +140 -3
  222. package/src/calls/__tests__/voice-triage-escalate.test.ts +105 -0
  223. package/src/calls/barge-in-guard.ts +118 -0
  224. package/src/calls/call-constants.ts +24 -4
  225. package/src/calls/call-controller.ts +499 -199
  226. package/src/calls/call-transport.ts +16 -0
  227. package/src/calls/media-stream-output.ts +32 -0
  228. package/src/calls/media-stream-server.ts +82 -30
  229. package/src/calls/media-stream-stt-session.ts +15 -0
  230. package/src/{live-voice → calls}/progress-narration.ts +17 -4
  231. package/src/calls/resolve-call-tts-provider.ts +33 -2
  232. package/src/calls/tts-call-strategy.ts +9 -5
  233. package/src/calls/types.ts +2 -0
  234. package/src/calls/voice-control-protocol.ts +194 -21
  235. package/src/calls/voice-leg-coordinator.ts +189 -0
  236. package/src/calls/voice-progress-cadence.ts +423 -0
  237. package/src/calls/voice-session-bridge.ts +140 -76
  238. package/src/calls/voice-triage-escalate.ts +178 -59
  239. package/src/cli/commands/__tests__/apps.test.ts +245 -0
  240. package/src/cli/commands/__tests__/bash.test.ts +53 -0
  241. package/src/cli/commands/__tests__/browser.test.ts +84 -3
  242. package/src/cli/commands/__tests__/cli-test-harness.ts +21 -3
  243. package/src/cli/commands/__tests__/plugins.test.ts +85 -0
  244. package/src/cli/commands/__tests__/roadmap.help.test.ts +19 -0
  245. package/src/cli/commands/__tests__/schedules.test.ts +14 -0
  246. package/src/cli/commands/apps.help.ts +67 -13
  247. package/src/cli/commands/apps.ts +183 -0
  248. package/src/cli/commands/bash.help.ts +9 -13
  249. package/src/cli/commands/bash.ts +7 -25
  250. package/src/cli/commands/browser.help.ts +47 -0
  251. package/src/cli/commands/browser.ts +52 -8
  252. package/src/cli/commands/channels/__tests__/send.test.ts +218 -0
  253. package/src/cli/commands/channels/index.help.ts +70 -2
  254. package/src/cli/commands/channels/index.ts +16 -3
  255. package/src/cli/commands/channels/send.ts +128 -0
  256. package/src/cli/commands/credentials.help.ts +9 -5
  257. package/src/cli/commands/credentials.ts +2 -2
  258. package/src/cli/commands/mcp.help.ts +8 -8
  259. package/src/cli/commands/mcp.ts +1 -1
  260. package/src/cli/commands/oauth/index.help.ts +10 -0
  261. package/src/cli/commands/oauth/providers.ts +12 -0
  262. package/src/cli/commands/oauth/request.test.ts +179 -2
  263. package/src/cli/commands/oauth/request.ts +41 -10
  264. package/src/cli/commands/oauth/status.ts +5 -0
  265. package/src/cli/commands/plugins.ts +73 -23
  266. package/src/cli/commands/roadmap.help.ts +5 -1
  267. package/src/cli/commands/roadmap.ts +1 -1
  268. package/src/cli/commands/schedules.ts +2 -0
  269. package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
  270. package/src/cli/lib/__tests__/install-from-github.test.ts +219 -0
  271. package/src/cli/lib/__tests__/install-from-platform.test.ts +77 -2
  272. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +45 -3
  273. package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +251 -0
  274. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +65 -2
  275. package/src/cli/lib/__tests__/plugin-catalog-platform.test.ts +14 -0
  276. package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +27 -1
  277. package/src/cli/lib/__tests__/plugin-details.test.ts +35 -2
  278. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +20 -0
  279. package/src/cli/lib/__tests__/plugins-install-offline.test.ts +43 -0
  280. package/src/cli/lib/__tests__/search-plugins.test.ts +31 -0
  281. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +122 -5
  282. package/src/cli/lib/bundled-marketplace.json +962 -81
  283. package/src/cli/lib/bundled-plugin-packages.json +786 -0
  284. package/src/cli/lib/bundled-plugin-packages.ts +87 -0
  285. package/src/cli/lib/diff-plugin.ts +1 -1
  286. package/src/cli/lib/inspect-plugin.ts +87 -12
  287. package/src/cli/lib/install-from-github.ts +150 -94
  288. package/src/cli/lib/install-from-platform.ts +14 -9
  289. package/src/cli/lib/list-installed-plugins.ts +21 -35
  290. package/src/cli/lib/plugin-catalog-cache.ts +22 -3
  291. package/src/cli/lib/plugin-catalog-local.ts +13 -3
  292. package/src/cli/lib/plugin-catalog-platform.ts +6 -1
  293. package/src/cli/lib/plugin-catalog-resolve.ts +20 -0
  294. package/src/cli/lib/plugin-details.ts +33 -8
  295. package/src/cli/lib/plugin-marketplace.ts +121 -21
  296. package/src/cli/lib/plugin-pin-history.ts +5 -2
  297. package/src/cli/lib/search-plugins.ts +58 -16
  298. package/src/cli/lib/uninstall-plugin.ts +59 -1
  299. package/src/cli/lib/upgrade-plugin.ts +61 -8
  300. package/src/cli/output.ts +18 -4
  301. package/src/config/__tests__/default-profile-catalog.test.ts +22 -0
  302. package/src/config/__tests__/default-provider.test.ts +4 -0
  303. package/src/config/__tests__/memory-retrospective-schema.test.ts +15 -1
  304. package/src/config/__tests__/platform-identity.test.ts +255 -0
  305. package/src/config/__tests__/platform-rehydration.test.ts +99 -9
  306. package/src/config/__tests__/plugin-resident-skill-discovery.test.ts +21 -0
  307. package/src/config/acp-agent-write.ts +43 -0
  308. package/src/config/acp-defaults.test.ts +13 -3
  309. package/src/config/acp-defaults.ts +23 -6
  310. package/src/config/acp-schema.test.ts +81 -0
  311. package/src/config/acp-schema.ts +30 -2
  312. package/src/config/bundled-skills/acp/SKILL.md +23 -15
  313. package/src/config/bundled-skills/acp/TOOLS.json +7 -3
  314. package/src/config/bundled-skills/app-builder/SKILL.md +12 -9
  315. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  316. package/src/config/bundled-skills/computer-use/SKILL.md +59 -2
  317. package/src/config/bundled-skills/computer-use/TOOLS.json +101 -2
  318. package/src/config/bundled-skills/computer-use/tools/computer-use-sequence.ts +12 -0
  319. package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -1
  320. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -1
  321. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -1
  322. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  323. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  324. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +67 -139
  325. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  326. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -1
  327. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -1
  328. package/src/config/bundled-skills/schedule/SKILL.md +7 -8
  329. package/src/config/bundled-skills/screen-annotation/SKILL.md +10 -3
  330. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +4 -1
  331. package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
  332. package/src/config/bundled-skills/skill-management/TOOLS.json +13 -9
  333. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +5 -2
  334. package/src/config/default-profile-catalog.ts +1 -1
  335. package/src/config/env.ts +2 -2
  336. package/src/config/feature-flag-registry.json +33 -13
  337. package/src/config/loader.ts +11 -17
  338. package/src/config/memory-v3-gate.test.ts +31 -0
  339. package/src/config/memory-v3-gate.ts +20 -16
  340. package/src/config/platform-identity.ts +201 -0
  341. package/src/config/platform-rehydration.ts +11 -27
  342. package/src/config/profile-text-generation.test.ts +51 -0
  343. package/src/config/profile-text-generation.ts +51 -0
  344. package/src/config/schema.ts +2 -2
  345. package/src/config/schemas/__tests__/live-voice.test.ts +8 -158
  346. package/src/config/schemas/__tests__/voice.test.ts +148 -0
  347. package/src/config/schemas/calls.ts +1 -28
  348. package/src/config/schemas/live-voice.ts +1 -173
  349. package/src/config/schemas/llm.ts +7 -2
  350. package/src/config/schemas/mcp.ts +15 -9
  351. package/src/config/schemas/memory-retrospective.ts +10 -0
  352. package/src/config/schemas/monitoring.ts +9 -0
  353. package/src/config/schemas/services.ts +18 -0
  354. package/src/config/schemas/skills.ts +0 -14
  355. package/src/config/schemas/voice.ts +150 -0
  356. package/src/config/skills.ts +13 -21
  357. package/src/credential-execution/ces-runtime.ts +2 -2
  358. package/src/credential-execution/executable-discovery.ts +36 -134
  359. package/src/credential-execution/process-manager.test.ts +37 -42
  360. package/src/credential-execution/process-manager.ts +24 -19
  361. package/src/credential-health/credential-health-service.ts +11 -17
  362. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +47 -0
  363. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -121
  364. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +5 -1
  365. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +133 -0
  366. package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +36 -0
  367. package/src/daemon/app-change-notify.ts +45 -0
  368. package/src/daemon/assistant-attachments.ts +20 -12
  369. package/src/daemon/config-watcher.ts +13 -194
  370. package/src/daemon/conversation-agent-loop-handlers.ts +74 -3
  371. package/src/daemon/conversation-agent-loop.ts +12 -0
  372. package/src/daemon/conversation-attachments.ts +93 -12
  373. package/src/daemon/conversation-client-surface.ts +26 -0
  374. package/src/daemon/conversation-error.ts +3 -2
  375. package/src/daemon/conversation-media-retry.ts +2 -1
  376. package/src/daemon/conversation-process.ts +35 -64
  377. package/src/daemon/conversation-runtime-assembly.ts +21 -8
  378. package/src/daemon/conversation-skill-tools.ts +13 -31
  379. package/src/daemon/conversation-store.ts +1 -1
  380. package/src/daemon/conversation-surfaces.ts +21 -10
  381. package/src/daemon/conversation-tool-setup.ts +135 -109
  382. package/src/daemon/conversation-turn-finalize.ts +26 -13
  383. package/src/daemon/conversation.ts +17 -3
  384. package/src/daemon/daemon-control.ts +3 -7
  385. package/src/daemon/dictation-profile-store.ts +2 -1
  386. package/src/daemon/handlers/shared.ts +2 -1
  387. package/src/daemon/handlers/skills.ts +6 -3
  388. package/src/daemon/host-bash-proxy.ts +8 -12
  389. package/src/daemon/host-browser-proxy.ts +15 -1
  390. package/src/daemon/host-cu-proxy.ts +275 -45
  391. package/src/daemon/host-file-proxy.ts +8 -10
  392. package/src/daemon/host-proxy-preactivation.ts +4 -1
  393. package/src/daemon/host-transfer-proxy.ts +14 -18
  394. package/src/daemon/lifecycle.ts +4 -9
  395. package/src/daemon/mcp-reload-service.ts +13 -6
  396. package/src/daemon/message-types/shared.ts +1 -0
  397. package/src/daemon/message-types/sync.ts +2 -0
  398. package/src/daemon/orphan-reaper.ts +4 -3
  399. package/src/daemon/persist-media-references.ts +20 -3
  400. package/src/daemon/providers-setup.ts +5 -1
  401. package/src/daemon/reaction-history-render.ts +2 -1
  402. package/src/daemon/shutdown-handlers.ts +1 -9
  403. package/src/daemon/skill-memory-refresh.ts +64 -0
  404. package/src/daemon/tool-setup-types.ts +6 -0
  405. package/src/daemon/tool-side-effects.ts +7 -18
  406. package/src/daemon/wake-conversation-ops.ts +38 -15
  407. package/src/desktop/__tests__/fake-desktop.ts +123 -0
  408. package/src/desktop/desktop-automation-lease.test.ts +438 -0
  409. package/src/desktop/desktop-automation-lease.ts +355 -0
  410. package/src/desktop/desktop-browser-client.test.ts +413 -0
  411. package/src/desktop/desktop-browser-client.ts +430 -0
  412. package/src/desktop/desktop-browser-cursor.ts +40 -0
  413. package/src/desktop/desktop-browser-endpoint.test.ts +78 -0
  414. package/src/desktop/desktop-browser-endpoint.ts +145 -0
  415. package/src/desktop/desktop-browser-operations.ts +130 -0
  416. package/src/desktop/desktop-chrome-policy.test.ts +79 -0
  417. package/src/desktop/desktop-chrome-policy.ts +47 -0
  418. package/src/desktop/desktop-chrome-session.test.ts +48 -0
  419. package/src/desktop/desktop-chrome-session.ts +87 -0
  420. package/src/desktop/desktop-dependencies.test.ts +131 -0
  421. package/src/desktop/desktop-dependencies.ts +329 -0
  422. package/src/desktop/desktop-display.ts +9 -0
  423. package/src/desktop/desktop-help.ts +16 -0
  424. package/src/desktop/desktop-panel-config.test.ts +135 -0
  425. package/src/desktop/desktop-panel-config.ts +162 -0
  426. package/src/desktop/desktop-session-manager.test.ts +813 -0
  427. package/src/desktop/desktop-session-manager.ts +970 -0
  428. package/src/desktop/desktop-stream-bridge.test.ts +395 -0
  429. package/src/desktop/desktop-stream-bridge.ts +214 -0
  430. package/src/desktop/desktop-wallpaper.test.ts +191 -0
  431. package/src/desktop/desktop-wallpaper.ts +113 -0
  432. package/src/desktop/desktop-window-drag.ts +177 -0
  433. package/src/desktop/desktop-window-manager-config.test.ts +230 -0
  434. package/src/desktop/desktop-window-manager-config.ts +238 -0
  435. package/src/desktop/desktop-window-theme.ts +170 -0
  436. package/src/desktop/virtual-desktop-feature.ts +18 -0
  437. package/src/desktop/virtual-desktop-platform.test.ts +61 -0
  438. package/src/heartbeat/heartbeat-service.ts +21 -3
  439. package/src/home/__tests__/feed-writer.test.ts +22 -0
  440. package/src/home/feed-writer.ts +11 -2
  441. package/src/hooks/types.ts +33 -0
  442. package/src/i18n/AGENTS.md +22 -0
  443. package/src/i18n/__tests__/i18n.test.ts +112 -0
  444. package/src/i18n/index.ts +16 -0
  445. package/src/i18n/locales.ts +93 -0
  446. package/src/i18n/messages.ts +70 -0
  447. package/src/i18n/title.ts +25 -0
  448. package/src/inbound/platform-callback-registration.ts +4 -5
  449. package/src/ipc/__tests__/browser-ipc.test.ts +230 -2
  450. package/src/ipc/__tests__/cancel-on-disconnect.test.ts +54 -0
  451. package/src/ipc/assistant-server.ts +15 -1
  452. package/src/ipc/cli-client.ts +13 -5
  453. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +143 -0
  454. package/src/live-voice/__tests__/live-voice-events.test.ts +9 -7
  455. package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +374 -0
  456. package/src/live-voice/__tests__/live-voice-metrics.test.ts +0 -3
  457. package/src/live-voice/__tests__/live-voice-progress.test.ts +94 -15
  458. package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +19 -0
  459. package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +238 -0
  460. package/src/live-voice/__tests__/live-voice-vad.test.ts +660 -5
  461. package/src/live-voice/__tests__/protocol.test.ts +95 -0
  462. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
  463. package/src/live-voice/__tests__/session-controls.test.ts +156 -0
  464. package/src/live-voice/live-voice-metrics.ts +9 -0
  465. package/src/live-voice/live-voice-photo.ts +25 -6
  466. package/src/live-voice/live-voice-session.ts +1081 -760
  467. package/src/live-voice/protocol.ts +89 -2
  468. package/src/live-voice/session-controls.ts +197 -0
  469. package/src/mcp/__tests__/credential-target.test.ts +59 -0
  470. package/src/mcp/__tests__/effective-config.test.ts +13 -2
  471. package/src/mcp/__tests__/manager-state.test.ts +128 -0
  472. package/src/mcp/__tests__/manager-tool-caps.test.ts +111 -0
  473. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +20 -6
  474. package/src/mcp/__tests__/mcp-auth-state-target.test.ts +49 -0
  475. package/src/mcp/__tests__/plugin-mcp-oauth-cleanup.test.ts +107 -0
  476. package/src/mcp/__tests__/plugin-mcp-oauth-provider-isolation.test.ts +89 -0
  477. package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +63 -11
  478. package/src/mcp/__tests__/reload-signal-emission.test.ts +39 -2
  479. package/src/mcp/__tests__/startup.test.ts +30 -7
  480. package/src/mcp/__tests__/tool-caps.test.ts +107 -0
  481. package/src/mcp/__tests__/workspace-mcp-config.test.ts +135 -0
  482. package/src/mcp/client.ts +64 -16
  483. package/src/mcp/credential-target.ts +105 -0
  484. package/src/mcp/effective-config.ts +45 -18
  485. package/src/mcp/manager.ts +201 -81
  486. package/src/mcp/mcp-auth-orchestrator.ts +17 -4
  487. package/src/mcp/mcp-auth-state.ts +38 -6
  488. package/src/mcp/mcp-header-store.ts +29 -45
  489. package/src/mcp/mcp-oauth-provider.ts +101 -33
  490. package/src/mcp/spec-schema.ts +111 -0
  491. package/src/mcp/startup.ts +41 -17
  492. package/src/mcp/tool-caps.ts +176 -0
  493. package/src/mcp/workspace-mcp-config.ts +188 -0
  494. package/src/messaging/provider-message-metadata.ts +3 -3
  495. package/src/messaging/provider.ts +10 -3
  496. package/src/messaging/providers/__tests__/proactive-address.test.ts +95 -0
  497. package/src/messaging/providers/callback-routing.ts +18 -0
  498. package/src/messaging/providers/channel-transport.ts +56 -0
  499. package/src/messaging/providers/discord/transport.ts +17 -0
  500. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +6 -17
  501. package/src/messaging/providers/slack/adapter.ts +7 -44
  502. package/src/messaging/providers/slack/transport.ts +16 -0
  503. package/src/messaging/providers/telegram-bot/adapter.ts +1 -48
  504. package/src/messaging/providers/telegram-bot/client.ts +0 -26
  505. package/src/messaging/providers/telegram-bot/transport.ts +20 -0
  506. package/src/messaging/providers/whatsapp/adapter.ts +1 -48
  507. package/src/messaging/providers/whatsapp/transport.ts +18 -0
  508. package/src/monitoring/__tests__/mount-watch.test.ts +236 -0
  509. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +8 -0
  510. package/src/monitoring/mount-watch.ts +348 -0
  511. package/src/monitoring/plugin-auto-update.ts +6 -0
  512. package/src/monitoring/worker.ts +9 -0
  513. package/src/notifications/__tests__/assistant-reply-producer.test.ts +55 -0
  514. package/src/notifications/__tests__/copy-composer.test.ts +70 -0
  515. package/src/notifications/__tests__/decision-engine.test.ts +175 -0
  516. package/src/notifications/__tests__/guardian-feed-projection.test.ts +158 -2
  517. package/src/notifications/__tests__/home-feed-side-effect.test.ts +153 -3
  518. package/src/notifications/__tests__/schedule-result-producer.test.ts +99 -3
  519. package/src/notifications/adapters/macos.ts +3 -0
  520. package/src/notifications/assistant-reply-producer.ts +8 -3
  521. package/src/notifications/conversation-pairing.ts +36 -16
  522. package/src/notifications/copy-composer.ts +11 -3
  523. package/src/notifications/decision-engine.ts +43 -8
  524. package/src/notifications/delivered-post-record.ts +11 -1
  525. package/src/notifications/guardian-feed-projection.ts +125 -5
  526. package/src/notifications/home-feed-side-effect.ts +55 -7
  527. package/src/notifications/schedule-result-producer.ts +64 -22
  528. package/src/oauth/AGENTS.md +4 -0
  529. package/src/oauth/__tests__/identity-verifier.test.ts +36 -1
  530. package/src/oauth/__tests__/seed-providers-managed.test.ts +149 -0
  531. package/src/oauth/byo-connection.test.ts +105 -0
  532. package/src/oauth/byo-connection.ts +36 -6
  533. package/src/oauth/connection-resolver.test.ts +100 -0
  534. package/src/oauth/connection-resolver.ts +120 -3
  535. package/src/oauth/identity-verifier.ts +24 -0
  536. package/src/oauth/oauth-store.ts +11 -1
  537. package/src/oauth/provider-serializer.ts +10 -0
  538. package/src/oauth/scope-utils.ts +24 -0
  539. package/src/oauth/seed-providers.ts +367 -27
  540. package/src/onboarding/checkin-event.ts +2 -1
  541. package/src/outbound-proxy/certs.ts +3 -5
  542. package/src/permissions/checker.test.ts +11 -6
  543. package/src/permissions/confirmation-guardian-request.test.ts +16 -0
  544. package/src/permissions/confirmation-guardian-request.ts +2 -3
  545. package/src/permissions/question-prompter.test.ts +31 -0
  546. package/src/permissions/question-prompter.ts +2 -0
  547. package/src/persistence/attachments-store.ts +84 -44
  548. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  549. package/src/persistence/conversation-crud.ts +182 -83
  550. package/src/persistence/conversation-lineage.ts +12 -4
  551. package/src/persistence/conversation-plugin-facade.ts +13 -0
  552. package/src/persistence/conversation-queries.ts +2 -2
  553. package/src/persistence/conversation-title-placeholders.ts +23 -0
  554. package/src/persistence/conversation-title-service.ts +9 -26
  555. package/src/persistence/conversation-tool-surface.ts +86 -0
  556. package/src/persistence/conversation-types.test.ts +32 -0
  557. package/src/persistence/conversation-types.ts +26 -4
  558. package/src/persistence/embeddings/qdrant-manager.ts +163 -18
  559. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  560. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  561. package/src/persistence/message-cursor.ts +78 -0
  562. package/src/persistence/message-reads.ts +30 -0
  563. package/src/persistence/migrations/157-invite-contact-id.ts +18 -6
  564. package/src/persistence/migrations/378-create-conversation-tool-surfaces.test.ts +78 -0
  565. package/src/persistence/migrations/378-create-conversation-tool-surfaces.ts +29 -0
  566. package/src/persistence/migrations/379-oauth-providers-response-ok-field.test.ts +92 -0
  567. package/src/persistence/migrations/379-oauth-providers-response-ok-field.ts +32 -0
  568. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +149 -0
  569. package/src/persistence/schema/conversation-tool-surfaces.ts +22 -0
  570. package/src/persistence/schema/index.ts +1 -0
  571. package/src/persistence/schema/memory-core.ts +5 -0
  572. package/src/persistence/schema/oauth.ts +1 -0
  573. package/src/persistence/steps.ts +15 -3
  574. package/src/platform/client.test.ts +4 -2
  575. package/src/platform/client.ts +2 -10
  576. package/src/plugin-api/constants.ts +2 -0
  577. package/src/plugin-api/conversation-turn.ts +31 -7
  578. package/src/plugin-api/index.ts +10 -1
  579. package/src/plugin-api/plugin-channel-turn-trust.test.ts +133 -0
  580. package/src/plugin-api/plugin-channel-turn-trust.ts +71 -0
  581. package/src/plugin-api/types.ts +2 -0
  582. package/src/plugins/__tests__/installed-plugin-dirs.test.ts +14 -1
  583. package/src/plugins/__tests__/mcp-servers.test.ts +38 -8
  584. package/src/plugins/defaults/index.ts +2 -0
  585. package/src/plugins/defaults/memory/AGENTS.md +14 -2
  586. package/src/plugins/defaults/memory/__tests__/buffer-file.test.ts +365 -0
  587. package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +43 -0
  588. package/src/plugins/defaults/memory/__tests__/fixtures/buffer-appender.ts +17 -0
  589. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +46 -0
  590. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +118 -0
  591. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +83 -0
  592. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +9 -5
  593. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +66 -10
  594. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +20 -0
  595. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +219 -0
  596. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +31 -0
  597. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +63 -0
  598. package/src/plugins/defaults/memory/__tests__/memory-run-evidence.test.ts +161 -0
  599. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +4 -0
  600. package/src/plugins/defaults/memory/buffer-file.ts +354 -0
  601. package/src/plugins/defaults/memory/buffer-format.ts +40 -0
  602. package/src/plugins/defaults/memory/context-search/agent-runner.ts +3 -3
  603. package/src/plugins/defaults/memory/context-search/format.ts +4 -2
  604. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +7 -3
  605. package/src/plugins/defaults/memory/context-search/sources/workspace.ts +4 -2
  606. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -8
  607. package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -42
  608. package/src/plugins/defaults/memory/hooks/init.ts +10 -0
  609. package/src/plugins/defaults/memory/hooks/message-deleted.ts +21 -0
  610. package/src/plugins/defaults/memory/hooks/shutdown.ts +2 -0
  611. package/src/plugins/defaults/memory/injectors.ts +4 -3
  612. package/src/plugins/defaults/memory/jobs-worker.ts +13 -0
  613. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +34 -60
  614. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +126 -0
  615. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +79 -0
  616. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +28 -0
  617. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +3 -5
  618. package/src/plugins/defaults/memory/memory-retrospective-job.ts +67 -184
  619. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
  620. package/src/plugins/defaults/memory/memory-retrospective-state.ts +312 -71
  621. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +2 -1
  622. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +5 -3
  623. package/src/plugins/defaults/memory/memory-run-evidence.ts +213 -0
  624. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +9 -0
  625. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +1 -1
  626. package/src/plugins/defaults/memory/startup.ts +28 -2
  627. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +407 -99
  628. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +10 -0
  629. package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +107 -7
  630. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
  631. package/src/plugins/defaults/memory/substrate/consolidation-job.ts +307 -86
  632. package/src/plugins/defaults/memory/substrate/consolidation-tool-surface.ts +34 -0
  633. package/src/plugins/defaults/memory/substrate/page-index.ts +7 -1
  634. package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +89 -49
  635. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  636. package/src/plugins/defaults/memory/substrate/sweep-job.ts +1 -1
  637. package/src/plugins/defaults/memory/tools.ts +1 -1
  638. package/src/plugins/defaults/memory/v1/graph/consolidation.ts +4 -2
  639. package/src/plugins/defaults/memory/v1/graph/extraction.ts +4 -1
  640. package/src/plugins/defaults/memory/v1/graph/retriever.ts +4 -1
  641. package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +5 -0
  642. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +5 -2
  643. package/src/plugins/defaults/memory/v2/reranker.ts +7 -1
  644. package/src/plugins/defaults/memory/v3/__tests__/card.test.ts +24 -0
  645. package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +81 -1
  646. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +87 -0
  647. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +125 -0
  648. package/src/plugins/defaults/memory/v3/__tests__/sections.test.ts +26 -0
  649. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +51 -0
  650. package/src/plugins/defaults/memory/v3/card.ts +4 -2
  651. package/src/plugins/defaults/memory/v3/injector.ts +212 -178
  652. package/src/plugins/defaults/memory/v3/orchestrate.ts +86 -22
  653. package/src/plugins/defaults/memory/v3/pool-select.ts +13 -8
  654. package/src/plugins/defaults/memory/v3/sections.ts +10 -3
  655. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +13 -1
  656. package/src/plugins/defaults/memory/worker.ts +6 -0
  657. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +4 -1
  658. package/src/plugins/defaults/tool-result-truncate/terminal.ts +1 -46
  659. package/src/plugins/external-plugin-loader.ts +49 -86
  660. package/src/plugins/installed-plugin-dirs.ts +6 -4
  661. package/src/plugins/mcp-servers.ts +24 -90
  662. package/src/plugins/mtime-cache.ts +2 -1
  663. package/src/plugins/user-loader.ts +2 -1
  664. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  665. package/src/providers/__tests__/retry-callsite.test.ts +41 -0
  666. package/src/providers/__tests__/retry-outbound-sanitize.test.ts +176 -0
  667. package/src/providers/anthropic/client.ts +0 -47
  668. package/src/providers/gemini/client.ts +9 -23
  669. package/src/providers/gemini-thought-signature.test.ts +63 -0
  670. package/src/providers/gemini-thought-signature.ts +44 -0
  671. package/src/providers/inference/__tests__/endpoint-probe.test.ts +87 -3
  672. package/src/providers/inference/adapter-factory.ts +6 -0
  673. package/src/providers/inference/auth.ts +2 -3
  674. package/src/providers/inference/connection-availability.ts +27 -8
  675. package/src/providers/inference/endpoint-probe.ts +36 -12
  676. package/src/providers/inference/resolve-auth.ts +22 -4
  677. package/src/providers/inference/service-account-token.ts +248 -0
  678. package/src/providers/jev/client.test.ts +260 -0
  679. package/src/providers/jev/client.ts +518 -0
  680. package/src/providers/model-catalog.ts +92 -3
  681. package/src/providers/model-intents.ts +10 -5
  682. package/src/providers/openai/__tests__/chat-completions-output-token-limit.test.ts +141 -0
  683. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +146 -18
  684. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +613 -0
  685. package/src/providers/openai/__tests__/google-thought-signature.test.ts +235 -0
  686. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +83 -1
  687. package/src/providers/openai/chat-completions-provider.ts +212 -79
  688. package/src/providers/openai/codex-models.ts +0 -4
  689. package/src/providers/openai/google-thought-signature.ts +320 -0
  690. package/src/providers/openai/responses-provider.ts +9 -2
  691. package/src/providers/opencode/client.test.ts +240 -4
  692. package/src/providers/opencode/client.ts +129 -3
  693. package/src/providers/openrouter/client.ts +20 -0
  694. package/src/providers/outbound-request-sanitize.ts +96 -0
  695. package/src/providers/retry.ts +30 -19
  696. package/src/providers/server-tool-pairing.ts +16 -7
  697. package/src/providers/unparseable-tool-args.ts +5 -1
  698. package/src/runtime/AGENTS.md +9 -3
  699. package/src/runtime/__tests__/agent-wake.test.ts +86 -1
  700. package/src/runtime/__tests__/channel-send.test.ts +443 -0
  701. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +132 -0
  702. package/src/runtime/__tests__/host-observe.test.ts +40 -1
  703. package/src/runtime/__tests__/live-voice-upgrade.test.ts +58 -0
  704. package/src/runtime/__tests__/runtime-ws-test-utils.ts +72 -0
  705. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +59 -0
  706. package/src/runtime/agent-wake.ts +22 -5
  707. package/src/runtime/assistant-event-hub.ts +21 -3
  708. package/src/runtime/auth/same-actor.ts +38 -3
  709. package/src/runtime/channel-send.ts +316 -0
  710. package/src/runtime/guardian-action-service.ts +2 -17
  711. package/src/runtime/guardian-reply-router.ts +1 -8
  712. package/src/runtime/host-observe.ts +11 -1
  713. package/src/runtime/http-server.ts +160 -151
  714. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +89 -0
  715. package/src/runtime/migrations/vbundle-import-policy.ts +33 -11
  716. package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +16 -5
  717. package/src/runtime/routes/__tests__/acp-routes.test.ts +178 -4
  718. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +275 -0
  719. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +127 -0
  720. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +108 -1
  721. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
  722. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +107 -0
  723. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +24 -2
  724. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +16 -12
  725. package/src/runtime/routes/__tests__/plugins-routes.test.ts +127 -3
  726. package/src/runtime/routes/acp-claude-auth-routes.ts +11 -3
  727. package/src/runtime/routes/acp-routes.test.ts +15 -0
  728. package/src/runtime/routes/acp-routes.ts +84 -165
  729. package/src/runtime/routes/app-management-routes.ts +90 -2
  730. package/src/runtime/routes/app-routes.ts +1 -1
  731. package/src/runtime/routes/browser-context.ts +39 -0
  732. package/src/runtime/routes/browser-routes.ts +16 -47
  733. package/src/runtime/routes/browser-tabs-routes.ts +72 -29
  734. package/src/runtime/routes/channel-route-shared.ts +1 -9
  735. package/src/runtime/routes/channel-send-routes.ts +85 -0
  736. package/src/runtime/routes/conversation-list-routes.ts +14 -3
  737. package/src/runtime/routes/conversation-query-routes.ts +40 -0
  738. package/src/runtime/routes/conversation-routes.ts +45 -7
  739. package/src/runtime/routes/credential-routes.ts +20 -14
  740. package/src/runtime/routes/desktop-setup-routes.test.ts +89 -0
  741. package/src/runtime/routes/desktop-setup-routes.ts +41 -0
  742. package/src/runtime/routes/diagnostics-routes.ts +61 -4
  743. package/src/runtime/routes/events-routes.ts +4 -0
  744. package/src/runtime/routes/guardian-approval-interception.ts +24 -0
  745. package/src/runtime/routes/host-cu-routes.ts +6 -0
  746. package/src/runtime/routes/inbound-message-handler.ts +2 -3
  747. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +1 -1
  748. package/src/runtime/routes/inbound-stages/background-dispatch.ts +7 -4
  749. package/src/runtime/routes/index.ts +4 -2
  750. package/src/runtime/routes/inference-profile-session-handler.ts +11 -1
  751. package/src/runtime/routes/inference-profiles-routes.ts +9 -0
  752. package/src/runtime/routes/log-export-routes.ts +2 -0
  753. package/src/runtime/routes/mcp-auth-routes.ts +141 -137
  754. package/src/runtime/routes/migration-routes.ts +6 -20
  755. package/src/runtime/routes/oauth-commands-routes.ts +98 -45
  756. package/src/runtime/routes/oauth-providers.ts +11 -0
  757. package/src/runtime/routes/oauth-request-hints.test.ts +246 -0
  758. package/src/runtime/routes/oauth-request-hints.ts +149 -0
  759. package/src/runtime/routes/platform-routes.ts +18 -15
  760. package/src/runtime/routes/plugins-routes.ts +83 -50
  761. package/src/runtime/routes/schedule-routes.ts +2 -0
  762. package/src/runtime/routes/secret-routes.ts +99 -119
  763. package/src/runtime/routes/workspace-routes.test.ts +55 -26
  764. package/src/runtime/routes/workspace-routes.ts +46 -63
  765. package/src/runtime/routes/workspace-tree-walk.test.ts +244 -0
  766. package/src/runtime/routes/workspace-tree-walk.ts +240 -0
  767. package/src/runtime/routes/workspace-utils.ts +17 -0
  768. package/src/runtime/services/__tests__/conversation-serializer.test.ts +28 -0
  769. package/src/runtime/services/conversation-serializer.ts +16 -3
  770. package/src/runtime/sync/resource-sync-events.ts +6 -1
  771. package/src/schedule/__tests__/worker-mcp-bootstrap.test.ts +107 -0
  772. package/src/schedule/__tests__/worker-mcp-readiness.test.ts +173 -0
  773. package/src/schedule/__tests__/worker-mcp-tools.test.ts +13 -47
  774. package/src/schedule/run-script.ts +4 -3
  775. package/src/schedule/schedule-store.ts +9 -2
  776. package/src/schedule/scheduler.ts +47 -11
  777. package/src/schedule/tool-surface-readiness.ts +65 -0
  778. package/src/schedule/worker-mcp.ts +85 -0
  779. package/src/schedule/worker.ts +9 -31
  780. package/src/security/__tests__/ces-http-record-backend.test.ts +137 -0
  781. package/src/security/ces-http-record-backend.ts +120 -0
  782. package/src/security/ces-rpc-record-backend.ts +7 -0
  783. package/src/security/secure-keys.ts +60 -48
  784. package/src/security/untrusted-content.ts +3 -1
  785. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +60 -0
  786. package/src/skills/managed-store.ts +153 -31
  787. package/src/skills/workspace-skill-md-signature.ts +50 -0
  788. package/src/subagent/consult-context.ts +12 -25
  789. package/src/tools/__tests__/side-effect-abort-guard.test.ts +1 -0
  790. package/src/tools/acp/list-agents.test.ts +3 -1
  791. package/src/tools/acp/spawn.test.ts +146 -11
  792. package/src/tools/acp/spawn.ts +21 -3
  793. package/src/tools/acp/status.test.ts +349 -0
  794. package/src/tools/acp/status.ts +112 -9
  795. package/src/tools/app-control/skill-proxy-bridge.ts +2 -1
  796. package/src/tools/ask-question/ask-question-tool.test.ts +167 -5
  797. package/src/tools/ask-question/ask-question-tool.ts +119 -23
  798. package/src/tools/browser/browser-execution.ts +52 -15
  799. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +69 -0
  800. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +9 -3
  801. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +1 -0
  802. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +2 -1
  803. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +5 -0
  804. package/src/tools/browser/cdp-client/extension-cdp-client.ts +3 -2
  805. package/src/tools/browser/network-recorder.ts +2 -1
  806. package/src/tools/capability-offer.test.ts +22 -2
  807. package/src/tools/capability-offer.ts +16 -1
  808. package/src/tools/computer-use/definitions.ts +123 -5
  809. package/src/tools/computer-use/skill-proxy-bridge.ts +2 -1
  810. package/src/tools/credentials/metadata-store.ts +100 -0
  811. package/src/tools/filesystem/search.ts +2 -1
  812. package/src/tools/host-filesystem/edit.test.ts +2 -1
  813. package/src/tools/host-filesystem/edit.ts +2 -2
  814. package/src/tools/host-filesystem/read.test.ts +2 -1
  815. package/src/tools/host-filesystem/read.ts +2 -2
  816. package/src/tools/host-filesystem/transfer.test.ts +2 -1
  817. package/src/tools/host-filesystem/transfer.ts +2 -2
  818. package/src/tools/host-filesystem/write.test.ts +2 -1
  819. package/src/tools/host-filesystem/write.ts +2 -2
  820. package/src/tools/host-terminal/host-shell.test.ts +16 -0
  821. package/src/tools/host-terminal/host-shell.ts +16 -26
  822. package/src/tools/network/web-search.ts +6 -1
  823. package/src/tools/policy-context.ts +6 -7
  824. package/src/tools/shared/filesystem/file-ops-service.ts +1 -31
  825. package/src/tools/shared/shell-output.test.ts +10 -0
  826. package/src/tools/shared/shell-output.ts +14 -2
  827. package/src/tools/skills/find-similar-skills.test.ts +214 -2
  828. package/src/tools/skills/find-similar-skills.ts +62 -9
  829. package/src/tools/skills/resolve-execute-invocation.ts +24 -0
  830. package/src/tools/skills/sandbox-runner.ts +13 -2
  831. package/src/tools/skills/scaffold-managed.ts +78 -16
  832. package/src/tools/subagent/spawn.ts +5 -8
  833. package/src/tools/terminal/__tests__/safe-env.test.ts +33 -4
  834. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +43 -0
  835. package/src/tools/terminal/safe-env.ts +35 -24
  836. package/src/tools/terminal/sanitized-bash.ts +118 -0
  837. package/src/tools/terminal/shell-launch.test.ts +162 -0
  838. package/src/tools/terminal/shell.test.ts +29 -0
  839. package/src/tools/terminal/shell.ts +13 -7
  840. package/src/tools/ui-surface/channel-variants.ts +10 -59
  841. package/src/tools/watch/watch-retro-report.ts +0 -8
  842. package/src/types/host-capabilities.ts +5 -3
  843. package/src/util/__tests__/language-subtag.test.ts +23 -1
  844. package/src/util/abort-reasons.ts +12 -1
  845. package/src/util/browser-human-verification.ts +14 -0
  846. package/src/util/ca-bundle.ts +13 -0
  847. package/src/util/host-process.test.ts +17 -1
  848. package/src/util/host-process.ts +24 -0
  849. package/src/util/language-subtag.ts +16 -0
  850. package/src/util/platform.ts +8 -0
  851. package/src/util/plugin-manifest.ts +203 -0
  852. package/src/util/unicode.ts +44 -1
  853. package/src/watch/watch-retro.ts +6 -8
  854. package/src/watch/watch-timeline.ts +2 -2
  855. package/src/workflows/run-manager.ts +2 -1
  856. package/src/workspace/git-porcelain.ts +66 -0
  857. package/src/workspace/git-service.ts +6 -55
  858. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +258 -0
  859. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +78 -0
  860. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +214 -0
  861. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +102 -0
  862. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +199 -0
  863. package/src/workspace/migrations/registry.ts +6 -0
  864. package/src/__tests__/app-source-watcher.test.ts +0 -218
  865. package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -359
  866. package/src/__tests__/speaker-identification.test.ts +0 -56
  867. package/src/calls/speaker-identification.ts +0 -233
  868. package/src/daemon/app-source-watcher.ts +0 -218
  869. package/src/messaging/providers/whatsapp/client.ts +0 -29
  870. package/src/runtime/routes/debug-bash-routes.ts +0 -173
  871. package/src/util/fs-watcher-error.ts +0 -36
  872. /package/src/{live-voice → calls}/progress-phrases.ts +0 -0
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Resolve the manifest that identifies an installed plugin.
3
+ *
4
+ * `package.json` is the primary manifest for Vellum plugins. A root
5
+ * `plugin.json` is selected only when `package.json` is absent, so a legacy
6
+ * plugin can carry another ecosystem's `plugin.json` without being
7
+ * reclassified.
8
+ */
9
+
10
+ import { existsSync, readFileSync } from "node:fs";
11
+ import { join } from "node:path";
12
+
13
+ import { z } from "zod";
14
+
15
+ export const LEGACY_PLUGIN_MANIFEST = "package.json";
16
+ export const STANDARD_PLUGIN_MANIFEST = "plugin.json";
17
+ export const AGENT_PLUGINS_MANIFEST_SCHEMA_URL =
18
+ "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json";
19
+
20
+ const PluginNameSchema = z
21
+ .string()
22
+ .min(1)
23
+ .max(64)
24
+ .regex(/^[a-z0-9](?!.*(?:--|\.\.))[a-z0-9.-]*[a-z0-9]$|^[a-z0-9]$/);
25
+
26
+ const LegacyPluginManifestSchema = z
27
+ .object({
28
+ name: z.string().min(1),
29
+ version: z.string().optional(),
30
+ description: z.string().min(1).optional(),
31
+ homepage: z.string().optional(),
32
+ license: z.unknown().optional(),
33
+ peerDependencies: z.record(z.string(), z.string()).optional(),
34
+ credentialKeyPatterns: z.unknown().optional(),
35
+ displayName: z.string().min(1).optional(),
36
+ icon: z.string().min(1).optional(),
37
+ })
38
+ .passthrough();
39
+
40
+ const StandardPluginManifestSchema = z
41
+ .object({
42
+ $schema: z.literal(AGENT_PLUGINS_MANIFEST_SCHEMA_URL),
43
+ name: PluginNameSchema,
44
+ version: z.string().optional(),
45
+ description: z.string().optional(),
46
+ author: z
47
+ .object({
48
+ name: z.string().optional(),
49
+ email: z.string().optional(),
50
+ url: z.string().optional(),
51
+ })
52
+ .strict()
53
+ .optional(),
54
+ homepage: z.string().optional(),
55
+ repository: z.string().optional(),
56
+ license: z.string().optional(),
57
+ keywords: z.array(z.string()).optional(),
58
+ // The core specification says a non-object extensions value is reported
59
+ // and ignored rather than rejecting the plugin. This host does not consume
60
+ // a standard extension namespace here, so keep it opaque.
61
+ extensions: z.unknown().optional(),
62
+ })
63
+ // Unknown core fields are reported-and-ignored by the specification. The
64
+ // loader does not assign them semantics, so passthrough preserves that
65
+ // non-fatal behavior without copying them into runtime metadata.
66
+ .passthrough();
67
+
68
+ export type PluginManifestSource =
69
+ | typeof LEGACY_PLUGIN_MANIFEST
70
+ | typeof STANDARD_PLUGIN_MANIFEST;
71
+
72
+ export interface ResolvedPluginManifest {
73
+ readonly source: PluginManifestSource;
74
+ readonly name: string;
75
+ readonly version?: string;
76
+ readonly description?: string;
77
+ readonly homepage?: string;
78
+ readonly license?: unknown;
79
+ /** Parsed selected manifest, retained for Vellum-specific legacy fields. */
80
+ readonly raw: Record<string, unknown>;
81
+ }
82
+
83
+ export type PluginManifestInstallAction = "keep" | "synthesize-legacy";
84
+
85
+ export class PluginManifestError extends Error {
86
+ constructor(
87
+ readonly pluginDir: string,
88
+ readonly source: PluginManifestSource | null,
89
+ message: string,
90
+ readonly cause?: unknown,
91
+ ) {
92
+ super(message);
93
+ this.name = "PluginManifestError";
94
+ }
95
+ }
96
+
97
+ /** True when the directory carries either supported root manifest. */
98
+ export function hasPluginManifest(pluginDir: string): boolean {
99
+ return (
100
+ existsSync(join(pluginDir, LEGACY_PLUGIN_MANIFEST)) ||
101
+ existsSync(join(pluginDir, STANDARD_PLUGIN_MANIFEST))
102
+ );
103
+ }
104
+
105
+ /**
106
+ * Decide whether an installed artifact needs the compatibility `package.json`.
107
+ *
108
+ * A `package.json` file is always preserved. A root `plugin.json`
109
+ * claims the Agent Plugins format only when it names the supported schema. A
110
+ * claimed standard manifest is validated before install; other `plugin.json`
111
+ * files remain foreign metadata beside the synthesized compatibility manifest.
112
+ */
113
+ export function getPluginManifestInstallAction(
114
+ pluginDir: string,
115
+ ): PluginManifestInstallAction {
116
+ if (existsSync(join(pluginDir, LEGACY_PLUGIN_MANIFEST))) {
117
+ return "keep";
118
+ }
119
+
120
+ const standardPath = join(pluginDir, STANDARD_PLUGIN_MANIFEST);
121
+ if (!existsSync(standardPath)) {
122
+ return "synthesize-legacy";
123
+ }
124
+
125
+ let json: unknown;
126
+ try {
127
+ json = JSON.parse(readFileSync(standardPath, "utf8"));
128
+ } catch {
129
+ return "synthesize-legacy";
130
+ }
131
+
132
+ if (
133
+ typeof json !== "object" ||
134
+ json === null ||
135
+ Array.isArray(json) ||
136
+ (json as Record<string, unknown>).$schema !==
137
+ AGENT_PLUGINS_MANIFEST_SCHEMA_URL
138
+ ) {
139
+ return "synthesize-legacy";
140
+ }
141
+
142
+ readPluginManifest(pluginDir);
143
+ return "keep";
144
+ }
145
+
146
+ /**
147
+ * Read and validate the selected root manifest.
148
+ *
149
+ * Selection is deterministic: `package.json` wins when present, including
150
+ * when it is malformed. The loader never falls through
151
+ * from a selected malformed legacy manifest to `plugin.json`.
152
+ */
153
+ export function readPluginManifest(pluginDir: string): ResolvedPluginManifest {
154
+ const source = existsSync(join(pluginDir, LEGACY_PLUGIN_MANIFEST))
155
+ ? LEGACY_PLUGIN_MANIFEST
156
+ : existsSync(join(pluginDir, STANDARD_PLUGIN_MANIFEST))
157
+ ? STANDARD_PLUGIN_MANIFEST
158
+ : null;
159
+ if (source === null) {
160
+ throw new PluginManifestError(
161
+ pluginDir,
162
+ null,
163
+ `plugin at ${pluginDir} is missing package.json and plugin.json`,
164
+ );
165
+ }
166
+
167
+ const path = join(pluginDir, source);
168
+ let json: unknown;
169
+ try {
170
+ json = JSON.parse(readFileSync(path, "utf8"));
171
+ } catch (cause) {
172
+ const reason = cause instanceof Error ? cause.message : String(cause);
173
+ throw new PluginManifestError(
174
+ pluginDir,
175
+ source,
176
+ `${source} at ${pluginDir} could not be read or parsed: ${reason}`,
177
+ cause,
178
+ );
179
+ }
180
+
181
+ const parsed =
182
+ source === LEGACY_PLUGIN_MANIFEST
183
+ ? LegacyPluginManifestSchema.safeParse(json)
184
+ : StandardPluginManifestSchema.safeParse(json);
185
+ if (!parsed.success) {
186
+ throw new PluginManifestError(
187
+ pluginDir,
188
+ source,
189
+ `${source} at ${pluginDir} failed schema validation: ${parsed.error.message}`,
190
+ parsed.error,
191
+ );
192
+ }
193
+
194
+ return {
195
+ source,
196
+ name: parsed.data.name,
197
+ version: parsed.data.version,
198
+ description: parsed.data.description,
199
+ homepage: parsed.data.homepage,
200
+ license: parsed.data.license,
201
+ raw: parsed.data,
202
+ };
203
+ }
@@ -67,6 +67,35 @@ export function safeStringSlice(
67
67
  return str.slice(safeStart, safeEnd);
68
68
  }
69
69
 
70
+ /**
71
+ * A `[start, end)` character window of at most `maxChars` code units that
72
+ * never splits a surrogate pair, for paging through text by offset. A split
73
+ * leaves a lone half at each edge, and each encodes to U+FFFD, so the
74
+ * character is lost from both this window and the next one paged in after
75
+ * it. `charCodeAt` reads the underlying text so a caller need not hold it as
76
+ * one string.
77
+ */
78
+ export function surrogateSafeWindow(
79
+ total: number,
80
+ charCodeAt: (index: number) => number,
81
+ requestedStart: number,
82
+ maxChars: number,
83
+ ): { start: number; end: number } {
84
+ let start = Math.max(0, Math.min(requestedStart, total));
85
+ if (start > 0 && start < total && isLowSurrogate(charCodeAt(start))) {
86
+ start -= 1;
87
+ }
88
+
89
+ let end = Math.min(total, start + maxChars);
90
+ if (end > start && end < total && isHighSurrogate(charCodeAt(end - 1))) {
91
+ // Backing off would empty a one-character window, which stalls paging on
92
+ // the same offset, so take the whole pair instead.
93
+ end = end - 1 > start ? end - 1 : Math.min(total, end + 1);
94
+ }
95
+
96
+ return { start, end };
97
+ }
98
+
70
99
  /**
71
100
  * Replace every orphaned UTF-16 surrogate in `str` with U+FFFD
72
101
  * (REPLACEMENT CHARACTER).
@@ -126,6 +155,15 @@ export interface DeepSanitizeResult<T> {
126
155
  fixedStringCount: number;
127
156
  }
128
157
 
158
+ export interface DeepSanitizeOptions {
159
+ /**
160
+ * Skip a plain-object property entirely: its value is neither scanned nor
161
+ * copied. For fields known to hold ASCII (base64 payloads), scanning is
162
+ * pure cost.
163
+ */
164
+ skipKey?: (key: string, parent: Record<string, unknown>) => boolean;
165
+ }
166
+
129
167
  /**
130
168
  * Recursively walk arrays and plain objects, replacing orphaned surrogates in
131
169
  * every string value. Non-plain objects (class instances, Date, Buffer, Map,
@@ -136,8 +174,10 @@ export interface DeepSanitizeResult<T> {
136
174
  */
137
175
  export function stripOrphanedSurrogatesDeep<T>(
138
176
  input: T,
177
+ options: DeepSanitizeOptions = {},
139
178
  ): DeepSanitizeResult<T> {
140
179
  let fixedStringCount = 0;
180
+ const { skipKey } = options;
141
181
 
142
182
  const walk = (value: unknown): { value: unknown; changed: boolean } => {
143
183
  if (typeof value === "string") {
@@ -178,7 +218,10 @@ export function stripOrphanedSurrogatesDeep<T>(
178
218
  let next: Record<string, unknown> | null = null;
179
219
  for (let i = 0; i < keys.length; i++) {
180
220
  const key = keys[i]!;
181
- const result = walk(source[key]);
221
+ const result =
222
+ skipKey?.(key, source) === true
223
+ ? { value: source[key], changed: false }
224
+ : walk(source[key]);
182
225
  if (result.changed && next === null) {
183
226
  next = {};
184
227
  for (let j = 0; j < i; j++) {
@@ -61,14 +61,12 @@ const WATCH_RETRO_WAKE_SOURCE = "watch-retro";
61
61
  * under the `watch_retro` template, which the client draws as a paged card: the
62
62
  * record on the first page, one question per page after it.
63
63
  *
64
- * **The daemon appends the card; the model never reaches `ui_show`.** This wake
65
- * is `clientless`, and `conversation-tool-setup` gates the whole `ui_surface`
66
- * family on a client being present, so `ui_show` is absent from this turn's
67
- * tool set rather than merely denied. A retrospective told to call it can only
68
- * report that it cannot. `watch_retro_report` is an ordinary tool and passes
69
- * that gate, and the surface is appended here, the way the memory
70
- * retrospective's `skill_card` is appended by the daemon rather than requested
71
- * by the model.
64
+ * **The daemon appends the card; the model calls `watch_retro_report`.** This
65
+ * wake is `clientless`. `ui_show` stays on the wire so background surfaces can
66
+ * persist, but this flow still reports through `watch_retro_report` so the
67
+ * daemon can append the card after the turn ends. The memory retrospective's
68
+ * `skill_card` is appended the same way: the daemon writes the surface, the
69
+ * model does not request it.
72
70
  *
73
71
  * **The append waits for the turn to end.** A `ui_surface` row written mid-turn
74
72
  * can land between a persisted `tool_use` and its `tool_result`, an ordering
@@ -366,8 +366,8 @@ export function appendNarration(
366
366
  * timeline of a session where observation stalled is simply a sparser one.
367
367
  *
368
368
  * The screenshot is stored only when `attachScreenshot` asks for it, and
369
- * carrying one is not asking. The host captures a screenshot on every observe
370
- * with no opt-out, so an observation always has pixels available and a policy
369
+ * carrying one is not asking. Watch requests a screenshot on every observe, so
370
+ * an observation normally has pixels available and a policy
371
371
  * of "store what arrives" is a policy of storing every frame. Which frames are
372
372
  * worth an image is a cadence decision, and it belongs to the caller driving
373
373
  * the session rather than to the row writer.
@@ -33,6 +33,7 @@ import type { TrustContext } from "../daemon/trust-context-types.js";
33
33
  import { wakeAgentForOpportunity } from "../runtime/agent-wake.js";
34
34
  import { broadcastMessage } from "../runtime/assistant-event-hub.js";
35
35
  import { getLogger } from "../util/logger.js";
36
+ import { safeStringSlice } from "../util/unicode.js";
36
37
  import type { CapabilityManifest } from "./capabilities.js";
37
38
  import {
38
39
  normalizeCapabilityManifest,
@@ -611,7 +612,7 @@ function truncateForSummary(s: string, runId: string): string {
611
612
  }
612
613
  const omitted = s.length - MAX_SUMMARY_RESULT_CHARS;
613
614
  return (
614
- `${s.slice(0, MAX_SUMMARY_RESULT_CHARS)}… ` +
615
+ `${safeStringSlice(s, 0, MAX_SUMMARY_RESULT_CHARS)}… ` +
615
616
  `[truncated ${omitted} chars — fetch the full result with manage_workflows ` +
616
617
  `{ action: "get_result", run_id: "${runId}" }]`
617
618
  );
@@ -0,0 +1,66 @@
1
+ /**
2
+ * NUL-terminated `git status --porcelain -z` parsing.
3
+ *
4
+ * Status reporting and batched staging share this parser so rename/copy
5
+ * origin paths cannot drift between the two readers.
6
+ */
7
+
8
+ export interface PorcelainEntry {
9
+ /** Two-character XY status from porcelain v1. */
10
+ status: string;
11
+ /** Path git reports for this record (the destination for rename/copy). */
12
+ path: string;
13
+ /** Pre-rename/copy path. Present when the record is a rename or copy. */
14
+ origin?: string;
15
+ }
16
+
17
+ /**
18
+ * Parse NUL-terminated `git status --porcelain -z` output into status/path
19
+ * records. NUL termination is required so paths with special characters
20
+ * (non-ASCII, quotes, newlines) arrive verbatim instead of C-style quoted.
21
+ *
22
+ * A rename/copy record is followed by a bare origin-path entry, captured on
23
+ * {@link PorcelainEntry.origin}.
24
+ */
25
+ export function parsePorcelainZ(stdout: string): PorcelainEntry[] {
26
+ const entries = stdout.split("\0");
27
+ const parsed: PorcelainEntry[] = [];
28
+ for (let i = 0; i < entries.length; i++) {
29
+ const entry = entries[i] ?? "";
30
+ if (entry.length < 4) {
31
+ continue;
32
+ }
33
+ const status = entry.substring(0, 2);
34
+ const path = entry.substring(3);
35
+ if (status[0] === "R" || status[0] === "C") {
36
+ i++;
37
+ const origin = entries[i];
38
+ if (origin && origin.length > 0) {
39
+ parsed.push({ status, path, origin });
40
+ continue;
41
+ }
42
+ }
43
+ parsed.push({ status, path });
44
+ }
45
+ return parsed;
46
+ }
47
+
48
+ /**
49
+ * Every path git status knows about, including rename/copy origins.
50
+ * Origins still need to be staged so a deletion is not left behind when a
51
+ * rename is split across add batches.
52
+ */
53
+ export function collectDirtyPathsFromPorcelain(stdout: string): string[] {
54
+ const paths: string[] = [];
55
+ const seen = new Set<string>();
56
+ for (const entry of parsePorcelainZ(stdout)) {
57
+ for (const path of [entry.path, entry.origin]) {
58
+ if (!path || seen.has(path)) {
59
+ continue;
60
+ }
61
+ seen.add(path);
62
+ paths.push(path);
63
+ }
64
+ }
65
+ return paths;
66
+ }
@@ -17,6 +17,10 @@ import { getLogger } from "../util/logger.js";
17
17
  import { Mutex } from "../util/mutex.js";
18
18
  import { addToPathEnv, getExtraToolPathDirs } from "../util/platform.js";
19
19
  import { PromiseGuard } from "../util/promise-guard.js";
20
+ import {
21
+ collectDirtyPathsFromPorcelain,
22
+ parsePorcelainZ,
23
+ } from "./git-porcelain.js";
20
24
 
21
25
  const execFileAsync = promisify(execFile);
22
26
  const log = getLogger("workspace-git");
@@ -51,7 +55,7 @@ function cleanGitEnv(workspaceDir: string): Record<string, string> {
51
55
  * Patterns excluded from workspace git tracking.
52
56
  * These are written to .gitignore on init and appended to existing .gitignore files.
53
57
  */
54
- const WORKSPACE_GITIGNORE_RULES = [
58
+ export const WORKSPACE_GITIGNORE_RULES = [
55
59
  // Runtime state directories
56
60
  "data/db/",
57
61
  "data/qdrant/",
@@ -226,59 +230,6 @@ done
226
230
  exit 0
227
231
  `;
228
232
 
229
- /**
230
- * Parse NUL-terminated `git status --porcelain -z` output into status/path
231
- * pairs. NUL termination is required so paths with special characters
232
- * (non-ASCII, quotes, newlines) arrive verbatim instead of C-style quoted.
233
- * A rename/copy record is followed by a bare origin-path entry, which is
234
- * skipped.
235
- */
236
- function parsePorcelainZ(
237
- stdout: string,
238
- ): Array<{ status: string; path: string }> {
239
- const entries = stdout.split("\0");
240
- const parsed: Array<{ status: string; path: string }> = [];
241
- for (let i = 0; i < entries.length; i++) {
242
- const entry = entries[i] ?? "";
243
- if (entry.length < 4) {
244
- continue;
245
- }
246
- const status = entry.substring(0, 2);
247
- parsed.push({ status, path: entry.substring(3) });
248
- if (status[0] === "R" || status[0] === "C") {
249
- i++;
250
- }
251
- }
252
- return parsed;
253
- }
254
-
255
- /**
256
- * Every path git status knows about, including rename/copy origins.
257
- * Origins are skipped by {@link parsePorcelainZ} (they have no status
258
- * prefix) but still need to be staged so a deletion is not left behind
259
- * when a rename is split across add batches.
260
- */
261
- function collectDirtyPathsFromPorcelain(stdout: string): string[] {
262
- const entries = stdout.split("\0");
263
- const paths: string[] = [];
264
- for (let i = 0; i < entries.length; i++) {
265
- const entry = entries[i] ?? "";
266
- if (entry.length < 4) {
267
- continue;
268
- }
269
- const status = entry.substring(0, 2);
270
- paths.push(entry.substring(3));
271
- if (status[0] === "R" || status[0] === "C") {
272
- i++;
273
- const origin = entries[i];
274
- if (origin && origin.length > 0) {
275
- paths.push(origin);
276
- }
277
- }
278
- }
279
- return paths;
280
- }
281
-
282
233
  /** Properties added by Node's child_process errors. */
283
234
  interface ExecError extends Error {
284
235
  killed?: boolean;
@@ -433,7 +384,7 @@ export class WorkspaceGitService {
433
384
  *
434
385
  * This method is always called inside the mutex, so no git operation from
435
386
  * our code can be concurrently holding the lock. However, an external git
436
- * process (user running `git add`, IDE tooling, etc.) could legitimately
387
+ * git process (user running `git add`, IDE tooling, etc.) could legitimately
437
388
  * hold the lock. We use `lsof` to check — if any process has the file
438
389
  * open, we leave it alone. If no process holds it, it's stale (crashed
439
390
  * process) and safe to remove.