@vellumai/assistant 0.6.1 → 0.6.3

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 (463) hide show
  1. package/bun.lock +40 -40
  2. package/bunfig.toml +3 -0
  3. package/docker-entrypoint.sh +12 -2
  4. package/docs/architecture/memory.md +1 -1
  5. package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
  6. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
  7. package/openapi.yaml +184 -69
  8. package/package.json +41 -41
  9. package/scripts/generate-openapi.ts +1 -2
  10. package/src/__tests__/acp-session.test.ts +43 -0
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
  12. package/src/__tests__/app-executors.test.ts +1 -0
  13. package/src/__tests__/app-source-watcher.test.ts +37 -11
  14. package/src/__tests__/approval-routes-http.test.ts +178 -1
  15. package/src/__tests__/assistant-event-hub.test.ts +30 -0
  16. package/src/__tests__/browser-fill-credential.test.ts +229 -94
  17. package/src/__tests__/browser-manager.test.ts +40 -27
  18. package/src/__tests__/catalog-files.test.ts +862 -0
  19. package/src/__tests__/channel-approvals.test.ts +53 -0
  20. package/src/__tests__/checker.test.ts +104 -170
  21. package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
  22. package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
  23. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  24. package/src/__tests__/config-schema.test.ts +125 -48
  25. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
  26. package/src/__tests__/context-overflow-approval.test.ts +21 -6
  27. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
  28. package/src/__tests__/conversation-agent-loop.test.ts +1 -1
  29. package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
  30. package/src/__tests__/conversation-attachments.test.ts +80 -4
  31. package/src/__tests__/conversation-confirmation-signals.test.ts +155 -0
  32. package/src/__tests__/conversation-directories-parse.test.ts +105 -0
  33. package/src/__tests__/conversation-fork-crud.test.ts +17 -0
  34. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  35. package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
  36. package/src/__tests__/conversation-inject-context.test.ts +103 -0
  37. package/src/__tests__/conversation-queue.test.ts +45 -2
  38. package/src/__tests__/conversation-routes-disk-view.test.ts +5 -0
  39. package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
  40. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  41. package/src/__tests__/conversation-runtime-assembly.test.ts +269 -46
  42. package/src/__tests__/conversation-starter-routes.test.ts +126 -0
  43. package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
  44. package/src/__tests__/conversation-store.test.ts +195 -0
  45. package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
  46. package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -3
  47. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  48. package/src/__tests__/credential-vault-unit.test.ts +4 -4
  49. package/src/__tests__/credential-vault.test.ts +152 -13
  50. package/src/__tests__/credentials-cli.test.ts +2 -2
  51. package/src/__tests__/date-context.test.ts +4 -4
  52. package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
  53. package/src/__tests__/extension-id-sync-guard.test.ts +155 -0
  54. package/src/__tests__/fixtures/mock-chrome-extension.ts +375 -0
  55. package/src/__tests__/gateway-only-guard.test.ts +3 -0
  56. package/src/__tests__/gemini-provider.test.ts +2 -2
  57. package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
  58. package/src/__tests__/headless-browser-interactions.test.ts +707 -371
  59. package/src/__tests__/headless-browser-navigate.test.ts +389 -47
  60. package/src/__tests__/headless-browser-read-tools.test.ts +266 -103
  61. package/src/__tests__/headless-browser-snapshot.test.ts +240 -77
  62. package/src/__tests__/host-bash-proxy.test.ts +150 -1
  63. package/src/__tests__/host-browser-e2e-cloud.test.ts +462 -0
  64. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
  65. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
  66. package/src/__tests__/host-browser-event-routes.test.ts +350 -0
  67. package/src/__tests__/host-browser-proxy.test.ts +444 -0
  68. package/src/__tests__/host-browser-routes.test.ts +198 -0
  69. package/src/__tests__/host-browser-ws-events-e2e.test.ts +320 -0
  70. package/src/__tests__/host-cu-proxy.test.ts +171 -1
  71. package/src/__tests__/host-file-proxy.test.ts +185 -1
  72. package/src/__tests__/host-file-read-tool.test.ts +52 -0
  73. package/src/__tests__/host-proxy-interface.test.ts +165 -0
  74. package/src/__tests__/host-shell-tool.test.ts +1 -11
  75. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  76. package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
  77. package/src/__tests__/inline-command-runner.test.ts +7 -5
  78. package/src/__tests__/integration-status.test.ts +6 -7
  79. package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
  80. package/src/__tests__/log-export-workspace.test.ts +190 -0
  81. package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
  82. package/src/__tests__/mcp-client-auth.test.ts +40 -4
  83. package/src/__tests__/mcp-health-check.test.ts +10 -3
  84. package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
  85. package/src/__tests__/migration-export-http.test.ts +61 -2
  86. package/src/__tests__/migration-export-streaming.test.ts +66 -0
  87. package/src/__tests__/migration-import-commit-http.test.ts +101 -1
  88. package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
  89. package/src/__tests__/navigate-settings-tab.test.ts +14 -1
  90. package/src/__tests__/notification-broadcaster.test.ts +65 -0
  91. package/src/__tests__/oauth-apps-routes.test.ts +17 -12
  92. package/src/__tests__/oauth-cli.test.ts +707 -60
  93. package/src/__tests__/oauth-connect-orchestrator.test.ts +116 -24
  94. package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
  95. package/src/__tests__/oauth-provider-serializer.test.ts +146 -10
  96. package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
  97. package/src/__tests__/oauth-providers-routes.test.ts +50 -14
  98. package/src/__tests__/oauth-store.test.ts +1386 -182
  99. package/src/__tests__/oauth2-gateway-transport.test.ts +211 -20
  100. package/src/__tests__/onboarding-template-contract.test.ts +74 -55
  101. package/src/__tests__/openai-provider.test.ts +2 -2
  102. package/src/__tests__/outlook-categories.test.ts +1 -1
  103. package/src/__tests__/outlook-client-automation.test.ts +1 -1
  104. package/src/__tests__/outlook-compose-tools.test.ts +1 -1
  105. package/src/__tests__/outlook-email-watcher.test.ts +1 -1
  106. package/src/__tests__/outlook-follow-up.test.ts +1 -1
  107. package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
  108. package/src/__tests__/outlook-trash.test.ts +1 -1
  109. package/src/__tests__/outlook-unsubscribe.test.ts +1 -1
  110. package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
  111. package/src/__tests__/permission-mode.test.ts +28 -56
  112. package/src/__tests__/pkb-autoinject.test.ts +96 -0
  113. package/src/__tests__/platform-callback-registration.test.ts +19 -0
  114. package/src/__tests__/post-turn-tool-result-truncation.test.ts +296 -0
  115. package/src/__tests__/proxy-approval-callback.test.ts +18 -0
  116. package/src/__tests__/require-fresh-approval.test.ts +40 -3
  117. package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
  118. package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
  119. package/src/__tests__/schedule-routes.test.ts +162 -0
  120. package/src/__tests__/secret-detection-handler.test.ts +84 -0
  121. package/src/__tests__/secret-ingress-http.test.ts +1 -0
  122. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  123. package/src/__tests__/set-permission-mode.test.ts +13 -250
  124. package/src/__tests__/skills-file-content-endpoint.test.ts +670 -0
  125. package/src/__tests__/skills-files-catalog-fallback.test.ts +450 -0
  126. package/src/__tests__/slack-channel-config.test.ts +12 -15
  127. package/src/__tests__/subagent-detail.test.ts +44 -2
  128. package/src/__tests__/subagent-disposal.test.ts +1 -0
  129. package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
  130. package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
  131. package/src/__tests__/subagent-manager-notify.test.ts +1 -0
  132. package/src/__tests__/subagent-notify-parent.test.ts +1 -0
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
  134. package/src/__tests__/subagent-tools.test.ts +1 -0
  135. package/src/__tests__/subagent-types.test.ts +1 -0
  136. package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
  137. package/src/__tests__/system-prompt.test.ts +72 -1
  138. package/src/__tests__/task-scheduler.test.ts +32 -6
  139. package/src/__tests__/telegram-config.test.ts +10 -13
  140. package/src/__tests__/terminal-sandbox.test.ts +1 -1
  141. package/src/__tests__/terminal-tools.test.ts +11 -5
  142. package/src/__tests__/test-preload.ts +14 -0
  143. package/src/__tests__/tool-approval-handler.test.ts +73 -0
  144. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
  145. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
  146. package/src/__tests__/tool-executor.test.ts +0 -1
  147. package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
  148. package/src/__tests__/top-level-renderer.test.ts +73 -1
  149. package/src/__tests__/transport-hints-queue.test.ts +62 -0
  150. package/src/__tests__/trust-store.test.ts +4 -4
  151. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
  152. package/src/__tests__/v2-consent-policy.test.ts +103 -0
  153. package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
  154. package/src/__tests__/workspace-policy.test.ts +2 -7
  155. package/src/acp/client-handler.ts +30 -4
  156. package/src/agent/loop.ts +12 -35
  157. package/src/approvals/guardian-request-resolvers.ts +21 -15
  158. package/src/browser-session/__tests__/manager.test.ts +297 -0
  159. package/src/browser-session/backends/cdp-inspect.ts +30 -0
  160. package/src/browser-session/backends/extension.ts +26 -0
  161. package/src/browser-session/backends/local.ts +24 -0
  162. package/src/browser-session/events.ts +164 -0
  163. package/src/browser-session/index.ts +27 -0
  164. package/src/browser-session/manager.ts +159 -0
  165. package/src/browser-session/types.ts +28 -0
  166. package/src/channels/__tests__/types.test.ts +134 -0
  167. package/src/channels/types.ts +55 -0
  168. package/src/cli/__tests__/run-assistant-command.ts +34 -7
  169. package/src/cli/__tests__/unknown-command.test.ts +33 -0
  170. package/src/cli/commands/browser-relay.ts +339 -409
  171. package/src/cli/commands/credentials.ts +3 -3
  172. package/src/cli/commands/default-action.ts +68 -1
  173. package/src/cli/commands/email.ts +18 -13
  174. package/src/cli/commands/mcp.ts +16 -4
  175. package/src/cli/commands/oauth/__tests__/connect.test.ts +68 -41
  176. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
  177. package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
  178. package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
  179. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +31 -33
  180. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +329 -0
  181. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +116 -12
  182. package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
  183. package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
  184. package/src/cli/commands/oauth/apps.ts +7 -4
  185. package/src/cli/commands/oauth/connect.ts +16 -2
  186. package/src/cli/commands/oauth/disconnect.ts +1 -1
  187. package/src/cli/commands/oauth/providers.ts +200 -36
  188. package/src/cli/commands/oauth/shared.ts +5 -5
  189. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +259 -0
  190. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  191. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  192. package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
  193. package/src/cli/commands/platform/index.ts +107 -10
  194. package/src/cli/commands/usage.ts +10 -9
  195. package/src/cli/lib/daemon-credential-client.ts +4 -0
  196. package/src/cli/program.ts +10 -3
  197. package/src/config/assistant-feature-flags.ts +59 -55
  198. package/src/config/bundled-skills/app-builder/SKILL.md +33 -173
  199. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +105 -0
  200. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
  201. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
  202. package/src/config/bundled-skills/contacts/SKILL.md +3 -0
  203. package/src/config/bundled-skills/document/SKILL.md +4 -0
  204. package/src/config/bundled-skills/gmail/SKILL.md +12 -7
  205. package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
  206. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
  207. package/src/config/bundled-skills/outlook/SKILL.md +7 -0
  208. package/src/config/bundled-skills/settings/TOOLS.json +1 -1
  209. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
  210. package/src/config/bundled-skills/subagent/SKILL.md +21 -0
  211. package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
  212. package/src/config/bundled-skills/tasks/SKILL.md +5 -0
  213. package/src/config/env-registry.ts +14 -0
  214. package/src/config/env.ts +21 -0
  215. package/src/config/feature-flag-registry.json +46 -7
  216. package/src/config/loader.ts +56 -1
  217. package/src/config/sanitize-for-transfer.ts +47 -0
  218. package/src/config/schema.ts +46 -5
  219. package/src/config/schemas/host-browser.ts +66 -0
  220. package/src/config/schemas/memory-lifecycle.ts +1 -1
  221. package/src/config/schemas/memory-retrieval.ts +103 -0
  222. package/src/config/schemas/security.ts +0 -6
  223. package/src/config/schemas/services.ts +16 -0
  224. package/src/config/types.ts +0 -1
  225. package/src/context/post-turn-tool-result-truncation.ts +176 -0
  226. package/src/context/window-manager.ts +19 -1
  227. package/src/credential-execution/approval-bridge.ts +49 -16
  228. package/src/credential-execution/managed-catalog.ts +3 -7
  229. package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
  230. package/src/daemon/app-source-watcher.ts +35 -0
  231. package/src/daemon/config-watcher.ts +6 -2
  232. package/src/daemon/context-overflow-approval.ts +5 -1
  233. package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
  234. package/src/daemon/conversation-agent-loop.ts +74 -19
  235. package/src/daemon/conversation-attachments.ts +40 -1
  236. package/src/daemon/conversation-messaging.ts +3 -0
  237. package/src/daemon/conversation-process.ts +66 -3
  238. package/src/daemon/conversation-queue-manager.ts +8 -0
  239. package/src/daemon/conversation-runtime-assembly.ts +159 -20
  240. package/src/daemon/conversation-surfaces.ts +78 -12
  241. package/src/daemon/conversation-tool-setup.ts +74 -11
  242. package/src/daemon/conversation-workspace.ts +12 -0
  243. package/src/daemon/conversation.ts +227 -11
  244. package/src/daemon/date-context.ts +10 -10
  245. package/src/daemon/first-greeting.ts +3 -2
  246. package/src/daemon/handlers/conversations.ts +9 -139
  247. package/src/daemon/handlers/shared.ts +65 -0
  248. package/src/daemon/handlers/skills.ts +232 -37
  249. package/src/daemon/host-bash-proxy.ts +48 -13
  250. package/src/daemon/host-browser-proxy.ts +191 -0
  251. package/src/daemon/host-cu-proxy.ts +36 -11
  252. package/src/daemon/host-file-proxy.ts +57 -9
  253. package/src/daemon/lifecycle.ts +86 -12
  254. package/src/daemon/message-protocol.ts +7 -0
  255. package/src/daemon/message-types/conversations.ts +59 -13
  256. package/src/daemon/message-types/host-browser.ts +100 -0
  257. package/src/daemon/message-types/messages.ts +5 -6
  258. package/src/daemon/message-types/notifications.ts +12 -0
  259. package/src/daemon/message-types/settings.ts +12 -0
  260. package/src/daemon/message-types/skills.ts +10 -0
  261. package/src/daemon/message-types/subagents.ts +2 -0
  262. package/src/daemon/server.ts +112 -35
  263. package/src/daemon/tool-side-effects.ts +6 -0
  264. package/src/daemon/transport-hints.ts +14 -0
  265. package/src/inbound/platform-callback-registration.ts +18 -17
  266. package/src/index.ts +1 -1
  267. package/src/mcp/client.ts +59 -24
  268. package/src/memory/app-store.ts +31 -1
  269. package/src/memory/conversation-crud.ts +38 -10
  270. package/src/memory/conversation-directories.ts +39 -0
  271. package/src/memory/conversation-group-migration.ts +65 -5
  272. package/src/memory/conversation-starters-cadence.ts +76 -0
  273. package/src/memory/conversation-title-service.ts +5 -2
  274. package/src/memory/db-init.ts +12 -0
  275. package/src/memory/embedding-backend.test.ts +75 -0
  276. package/src/memory/embedding-backend.ts +131 -5
  277. package/src/memory/embedding-gemini.test.ts +54 -0
  278. package/src/memory/embedding-gemini.ts +20 -9
  279. package/src/memory/embedding-local.ts +177 -18
  280. package/src/memory/graph/capability-seed.ts +3 -5
  281. package/src/memory/graph/consolidation.ts +10 -23
  282. package/src/memory/graph/extraction-job.ts +15 -0
  283. package/src/memory/graph/retriever.ts +40 -22
  284. package/src/memory/graph/store.test.ts +7 -3
  285. package/src/memory/graph/store.ts +47 -12
  286. package/src/memory/group-crud.ts +25 -9
  287. package/src/memory/llm-usage-store.ts +45 -4
  288. package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
  289. package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
  290. package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
  291. package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
  292. package/src/memory/migrations/217-conversation-host-access.ts +40 -0
  293. package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
  294. package/src/memory/migrations/index.ts +6 -0
  295. package/src/memory/migrations/registry.ts +8 -0
  296. package/src/memory/schema/conversations.ts +1 -0
  297. package/src/memory/schema/oauth.ts +18 -13
  298. package/src/messaging/provider.ts +1 -1
  299. package/src/notifications/broadcaster.ts +6 -0
  300. package/src/notifications/conversation-pairing.ts +12 -4
  301. package/src/notifications/emit-signal.ts +14 -0
  302. package/src/notifications/signal.ts +11 -0
  303. package/src/oauth/AGENTS.md +76 -0
  304. package/src/oauth/__tests__/identity-verifier.test.ts +24 -19
  305. package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
  306. package/src/oauth/byo-connection.test.ts +8 -8
  307. package/src/oauth/byo-connection.ts +7 -7
  308. package/src/oauth/connect-orchestrator.ts +23 -21
  309. package/src/oauth/connect-types.ts +3 -3
  310. package/src/oauth/connection-resolver.test.ts +17 -4
  311. package/src/oauth/connection-resolver.ts +16 -16
  312. package/src/oauth/connection.ts +1 -1
  313. package/src/oauth/manual-token-connection.ts +13 -13
  314. package/src/oauth/oauth-store.ts +214 -100
  315. package/src/oauth/platform-connection.test.ts +5 -5
  316. package/src/oauth/platform-connection.ts +4 -4
  317. package/src/oauth/provider-serializer.ts +31 -5
  318. package/src/oauth/revoke.ts +76 -0
  319. package/src/oauth/seed-providers.ts +127 -87
  320. package/src/oauth/token-persistence.ts +1 -1
  321. package/src/permissions/checker.ts +3 -3
  322. package/src/permissions/defaults.ts +7 -8
  323. package/src/permissions/permission-mode.ts +4 -11
  324. package/src/permissions/prompter.ts +13 -3
  325. package/src/permissions/v2-consent-policy.ts +87 -0
  326. package/src/platform/client.ts +1 -1
  327. package/src/prompts/system-prompt.ts +18 -21
  328. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
  329. package/src/prompts/templates/BOOTSTRAP.md +59 -96
  330. package/src/prompts/templates/SOUL.md +11 -11
  331. package/src/providers/anthropic/client.ts +1 -0
  332. package/src/providers/types.ts +1 -1
  333. package/src/runtime/AGENTS.md +23 -0
  334. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
  335. package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
  336. package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
  337. package/src/runtime/assistant-event-hub.ts +24 -2
  338. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
  339. package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
  340. package/src/runtime/auth/__tests__/route-policy.test.ts +8 -0
  341. package/src/runtime/auth/middleware.ts +98 -0
  342. package/src/runtime/auth/route-policy.ts +6 -7
  343. package/src/runtime/auth/token-service.ts +8 -0
  344. package/src/runtime/capability-tokens.ts +414 -0
  345. package/src/runtime/channel-approvals.ts +18 -5
  346. package/src/runtime/chrome-extension-registry.ts +332 -0
  347. package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
  348. package/src/runtime/guardian-decision-types.ts +7 -0
  349. package/src/runtime/http-server.ts +425 -70
  350. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
  351. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
  352. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +162 -0
  353. package/src/runtime/migrations/migration-transport.ts +6 -0
  354. package/src/runtime/migrations/migration-wizard.ts +22 -2
  355. package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
  356. package/src/runtime/migrations/vbundle-builder.ts +145 -38
  357. package/src/runtime/migrations/vbundle-import-analyzer.ts +19 -0
  358. package/src/runtime/migrations/vbundle-importer.ts +55 -5
  359. package/src/runtime/pending-interactions.ts +29 -13
  360. package/src/runtime/routes/approval-routes.ts +90 -16
  361. package/src/runtime/routes/browser-cdp-routes.ts +229 -0
  362. package/src/runtime/routes/browser-extension-pair-routes.ts +497 -0
  363. package/src/runtime/routes/conversation-analysis-routes.ts +18 -5
  364. package/src/runtime/routes/conversation-management-routes.ts +108 -0
  365. package/src/runtime/routes/conversation-routes.ts +308 -28
  366. package/src/runtime/routes/conversation-starter-routes.ts +78 -16
  367. package/src/runtime/routes/group-routes.ts +22 -8
  368. package/src/runtime/routes/guardian-action-routes.ts +24 -13
  369. package/src/runtime/routes/host-browser-routes.ts +279 -0
  370. package/src/runtime/routes/host-file-routes.ts +9 -1
  371. package/src/runtime/routes/identity-routes.ts +259 -16
  372. package/src/runtime/routes/log-export/AGENTS.md +104 -0
  373. package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
  374. package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
  375. package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
  376. package/src/runtime/routes/log-export-routes.ts +60 -25
  377. package/src/runtime/routes/memory-item-routes.ts +1 -7
  378. package/src/runtime/routes/migration-routes.ts +87 -2
  379. package/src/runtime/routes/oauth-apps.ts +15 -17
  380. package/src/runtime/routes/oauth-providers.ts +4 -0
  381. package/src/runtime/routes/schedule-routes.ts +24 -11
  382. package/src/runtime/routes/settings-routes.ts +9 -97
  383. package/src/runtime/routes/skills-routes.ts +52 -2
  384. package/src/runtime/routes/subagents-routes.ts +14 -10
  385. package/src/runtime/routes/usage-routes.ts +8 -7
  386. package/src/runtime/routes/workspace-routes.test.ts +22 -0
  387. package/src/runtime/routes/workspace-routes.ts +8 -1
  388. package/src/runtime/routes/workspace-utils.ts +2 -0
  389. package/src/schedule/scheduler.ts +7 -5
  390. package/src/security/ces-credential-client.ts +20 -0
  391. package/src/security/ces-rpc-credential-backend.ts +17 -0
  392. package/src/security/credential-backend.ts +5 -0
  393. package/src/security/oauth2.ts +42 -25
  394. package/src/security/secure-keys.ts +118 -25
  395. package/src/security/token-manager.ts +23 -10
  396. package/src/skills/catalog-files.ts +492 -0
  397. package/src/skills/inline-command-runner.ts +12 -14
  398. package/src/subagent/manager.ts +131 -26
  399. package/src/subagent/types.ts +19 -0
  400. package/src/tools/apps/executors.ts +11 -2
  401. package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
  402. package/src/tools/browser/auth-detector.ts +43 -12
  403. package/src/tools/browser/browser-execution.ts +645 -340
  404. package/src/tools/browser/browser-manager.ts +36 -12
  405. package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
  406. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
  407. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +870 -0
  408. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +330 -0
  409. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +377 -0
  410. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
  411. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
  412. package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
  413. package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
  414. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
  415. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
  416. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +743 -0
  417. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
  418. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +578 -0
  419. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
  420. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +635 -0
  421. package/src/tools/browser/cdp-client/errors.ts +34 -0
  422. package/src/tools/browser/cdp-client/extension-cdp-client.ts +125 -0
  423. package/src/tools/browser/cdp-client/factory.ts +204 -0
  424. package/src/tools/browser/cdp-client/index.ts +14 -0
  425. package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
  426. package/src/tools/browser/cdp-client/types.ts +52 -0
  427. package/src/tools/filesystem/edit.ts +1 -1
  428. package/src/tools/filesystem/list.ts +1 -1
  429. package/src/tools/filesystem/read.ts +1 -1
  430. package/src/tools/filesystem/write.ts +2 -1
  431. package/src/tools/host-filesystem/edit.ts +1 -1
  432. package/src/tools/host-filesystem/read.ts +12 -15
  433. package/src/tools/host-filesystem/write.ts +1 -1
  434. package/src/tools/host-terminal/host-shell.ts +21 -16
  435. package/src/tools/permission-checker.ts +77 -100
  436. package/src/tools/registry.ts +0 -2
  437. package/src/tools/secret-detection-handler.ts +34 -1
  438. package/src/tools/shared/filesystem/image-read.ts +61 -40
  439. package/src/tools/skills/sandbox-runner.ts +3 -6
  440. package/src/tools/subagent/spawn.ts +47 -3
  441. package/src/tools/subagent/status.ts +2 -0
  442. package/src/tools/system/register.ts +2 -16
  443. package/src/tools/terminal/safe-env.ts +7 -0
  444. package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
  445. package/src/tools/terminal/sandbox.ts +4 -1
  446. package/src/tools/terminal/shell.ts +24 -21
  447. package/src/tools/tool-approval-handler.ts +48 -2
  448. package/src/tools/types.ts +2 -3
  449. package/src/util/platform.ts +14 -19
  450. package/src/watcher/provider-types.ts +1 -1
  451. package/src/workspace/migrations/029-seed-pkb.ts +1 -0
  452. package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
  453. package/src/workspace/migrations/registry.ts +2 -0
  454. package/src/workspace/top-level-renderer.ts +19 -1
  455. package/src/__tests__/chrome-cdp.test.ts +0 -419
  456. package/src/__tests__/permission-mode-sse.test.ts +0 -418
  457. package/src/__tests__/permission-mode-store.test.ts +0 -277
  458. package/src/browser-extension-relay/protocol.ts +0 -63
  459. package/src/browser-extension-relay/server.ts +0 -203
  460. package/src/config/schemas/sandbox.ts +0 -14
  461. package/src/permissions/permission-mode-store.ts +0 -180
  462. package/src/tools/browser/chrome-cdp.ts +0 -239
  463. package/src/tools/system/set-permission-mode.ts +0 -103
@@ -34,6 +34,7 @@ export async function executeSubagentStatus(
34
34
  subagentId: state.config.id,
35
35
  label: state.config.label,
36
36
  status: state.status,
37
+ isFork: state.isFork,
37
38
  error: state.error,
38
39
  createdAt: state.createdAt,
39
40
  startedAt: state.startedAt,
@@ -57,6 +58,7 @@ export async function executeSubagentStatus(
57
58
  subagentId: s.config.id,
58
59
  label: s.config.label,
59
60
  status: s.status,
61
+ isFork: s.isFork,
60
62
  error: s.error,
61
63
  }));
62
64
 
@@ -1,23 +1,9 @@
1
1
  /**
2
2
  * Registers feature-flag-gated system tools with the daemon's tool registry.
3
3
  *
4
- * Called once at daemon startup via initializeTools(). Tools that are always
5
- * registered (e.g. request_system_permission) are handled via the tool
6
- * manifest's explicit tools list; this module handles conditional registration.
4
+ * No conditional tools are currently registered.
7
5
  */
8
6
 
9
- import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
10
- import { getConfig } from "../../config/loader.js";
11
- import { registerTool } from "../registry.js";
12
- import { setPermissionModeTool } from "./set-permission-mode.js";
13
-
14
7
  export function registerSystemTools(): void {
15
- try {
16
- const config = getConfig();
17
- if (isAssistantFeatureFlagEnabled("permission-controls-v2", config)) {
18
- registerTool(setPermissionModeTool);
19
- }
20
- } catch {
21
- // Config not yet loaded (e.g. during test setup) — permission mode tool stays off.
22
- }
8
+ // No-op.
23
9
  }
@@ -32,6 +32,7 @@ export const SAFE_ENV_VARS = [
32
32
  "CES_BOOTSTRAP_SOCKET_DIR",
33
33
  "GATEWAY_INTERNAL_URL",
34
34
  "VELLUM_PLATFORM_URL",
35
+ "VELLUM_DOCS_BASE_URL",
35
36
  "CES_CREDENTIAL_URL",
36
37
  "CES_MANAGED_MODE",
37
38
  "IS_CONTAINERIZED",
@@ -42,6 +43,8 @@ export const SAFE_ENV_VARS = [
42
43
  "VELLUM_PROFILER_MAX_BYTES",
43
44
  "VELLUM_PROFILER_MAX_RUNS",
44
45
  "VELLUM_PROFILER_MIN_FREE_MB",
46
+ "VELLUM_MEMORY_LIMIT",
47
+ "VELLUM_CPU_LIMIT",
45
48
  ] as const;
46
49
 
47
50
  /**
@@ -71,5 +74,9 @@ export function buildSanitizedEnv(): Record<string, string> {
71
74
  // Expose the workspace directory so skills and child processes can read/write
72
75
  // workspace-scoped files (e.g. avatar traits, user data).
73
76
  env.VELLUM_WORKSPACE_DIR = getWorkspaceDir();
77
+ // Ensure UTF-8 locale so multi-byte characters (em dashes, curly quotes,
78
+ // arrows, etc.) survive piping through tools like pbcopy without corruption.
79
+ if (!env.LANG) env.LANG = "C.UTF-8";
80
+ if (!env.LC_ALL) env.LC_ALL = "C.UTF-8";
74
81
  return env;
75
82
  }
@@ -1,8 +1,7 @@
1
1
  import { execSync } from "node:child_process";
2
2
 
3
- import { getConfig } from "../../config/loader.js";
4
- import type { SandboxConfig } from "../../config/schema.js";
5
3
  import { isLinux, isMacOS } from "../../util/platform.js";
4
+ import type { SandboxConfig } from "./sandbox.js";
6
5
 
7
6
  export interface SandboxCheckResult {
8
7
  label: string;
@@ -69,8 +68,9 @@ function getActiveBackendReason(sandboxConfig: SandboxConfig): string {
69
68
  * and reports current configuration.
70
69
  */
71
70
  export function runSandboxDiagnostics(): SandboxDiagnostics {
72
- const config = getConfig();
73
- const sandboxConfig = config.sandbox;
71
+ // Sandbox is disabled — the assistant runs exclusively in Docker or
72
+ // platform-managed environments.
73
+ const sandboxConfig: SandboxConfig = { enabled: false };
74
74
 
75
75
  const checks: SandboxCheckResult[] = [];
76
76
 
@@ -1,7 +1,10 @@
1
- import type { SandboxConfig } from "../../config/schema.js";
2
1
  import { NativeBackend } from "./backends/native.js";
3
2
  import type { SandboxResult, WrapOptions } from "./backends/types.js";
4
3
 
4
+ export interface SandboxConfig {
5
+ enabled: boolean;
6
+ }
7
+
5
8
  export type {
6
9
  SandboxBackend,
7
10
  SandboxResult,
@@ -261,11 +261,9 @@ class ShellTool implements Tool {
261
261
  "Executing shell command",
262
262
  );
263
263
 
264
- // Resolve sandbox config early - needed both for proxy env and command wrapping.
265
- const sandboxConfig =
266
- context.sandboxOverride != null
267
- ? { ...config.sandbox, enabled: context.sandboxOverride }
268
- : config.sandbox;
264
+ // The assistant runs exclusively in Docker or platform-managed
265
+ // environments where the container provides isolation.
266
+ const sandboxConfig = { enabled: false } as const;
269
267
 
270
268
  // Acquire proxy session if proxied mode is requested.
271
269
  // `getOrStartSession` serializes per-conversation so concurrent proxied
@@ -329,30 +327,35 @@ class ShellTool implements Tool {
329
327
  detached: true,
330
328
  });
331
329
 
332
- const timer = setTimeout(() => {
333
- timedOut = true;
330
+ // Kill the entire process tree. Tries the process group first
331
+ // (negative PID), then falls back to killing the direct child if the
332
+ // PID is unavailable or the group kill fails.
333
+ const killTree = () => {
334
+ if (child.pid != null) {
335
+ try {
336
+ process.kill(-child.pid, "SIGKILL");
337
+ return;
338
+ } catch {
339
+ // Process group may have already exited — fall through.
340
+ }
341
+ }
334
342
  try {
335
- process.kill(-child.pid!, "SIGKILL");
343
+ child.kill("SIGKILL");
336
344
  } catch {
337
- // Process group may have already exited.
345
+ // Child may have already exited.
338
346
  }
347
+ };
348
+
349
+ const timer = setTimeout(() => {
350
+ timedOut = true;
351
+ killTree();
339
352
  }, timeoutMs);
340
353
 
341
354
  // Cooperative cancellation via AbortSignal
342
- const onAbort = () => {
343
- try {
344
- process.kill(-child.pid!, "SIGKILL");
345
- } catch {
346
- // Process group may have already exited.
347
- }
348
- };
355
+ const onAbort = () => killTree();
349
356
  if (context.signal) {
350
357
  if (context.signal.aborted) {
351
- try {
352
- process.kill(-child.pid!, "SIGKILL");
353
- } catch {
354
- // Process group may have already exited.
355
- }
358
+ killTree();
356
359
  } else {
357
360
  context.signal.addEventListener("abort", onAbort, { once: true });
358
361
  }
@@ -4,6 +4,10 @@ import {
4
4
  getCanonicalGuardianRequest,
5
5
  updateCanonicalGuardianRequest,
6
6
  } from "../memory/canonical-guardian-store.js";
7
+ import {
8
+ isConversationHostAccessEnabled,
9
+ isPermissionControlsV2Enabled,
10
+ } from "../permissions/v2-consent-policy.js";
7
11
  import { isUntrustedTrustClass } from "../runtime/actor-trust-resolver.js";
8
12
  import { createOrReuseToolGrantRequest } from "../runtime/tool-grant-request-helper.js";
9
13
  import { redactSecrets } from "../security/secret-scanner.js";
@@ -178,6 +182,10 @@ function guardianApprovalDeniedMessage(
178
182
  return `Permission denied for "${toolName}": this action requires guardian approval and the current actor is not the guardian.`;
179
183
  }
180
184
 
185
+ function trustedContactHostAccessDeniedMessage(toolName: string): string {
186
+ return `Permission denied for "${toolName}": computer access is not enabled for this conversation. Confirm the guardian's intent conversationally and ask them to enable computer access for this conversation before retrying.`;
187
+ }
188
+
181
189
  export type PreExecutionGateResult =
182
190
  | { allowed: true; tool: Tool; grantConsumed?: boolean }
183
191
  | { allowed: false; result: ToolExecutionResult };
@@ -216,6 +224,8 @@ export class ToolApprovalHandler {
216
224
  startTime: number,
217
225
  emitLifecycleEvent: (event: ToolLifecycleEvent) => void,
218
226
  ): Promise<PreExecutionGateResult> {
227
+ const v2Enabled = isPermissionControlsV2Enabled();
228
+
219
229
  // Bail out immediately if the session was aborted before this tool started.
220
230
  if (context.signal?.aborted) {
221
231
  const durationMs = Date.now() - startTime;
@@ -286,9 +296,44 @@ export class ToolApprovalHandler {
286
296
  | Parameters<typeof consumeGrantForInvocation>[0]
287
297
  | null = null;
288
298
 
299
+ const guardianApprovalRequired = requiresGuardianApprovalForActor(
300
+ name,
301
+ input,
302
+ executionTarget,
303
+ );
304
+
305
+ if (
306
+ v2Enabled &&
307
+ context.trustClass === "trusted_contact" &&
308
+ guardianApprovalRequired &&
309
+ executionTarget === "host" &&
310
+ !isConversationHostAccessEnabled(context.conversationId)
311
+ ) {
312
+ const durationMs = Date.now() - startTime;
313
+ const reason = trustedContactHostAccessDeniedMessage(name);
314
+ emitLifecycleEvent({
315
+ type: "permission_denied",
316
+ toolName: name,
317
+ executionTarget,
318
+ input,
319
+ workingDir: context.workingDir,
320
+ conversationId: context.conversationId,
321
+ requestId: context.requestId,
322
+ riskLevel,
323
+ decision: "deny",
324
+ reason,
325
+ durationMs,
326
+ });
327
+ return {
328
+ allowed: false,
329
+ result: { content: reason, isError: true },
330
+ };
331
+ }
332
+
289
333
  if (
290
334
  isUntrustedTrustClass(context.trustClass) &&
291
- requiresGuardianApprovalForActor(name, input, executionTarget)
335
+ guardianApprovalRequired &&
336
+ !(v2Enabled && context.trustClass === "trusted_contact")
292
337
  ) {
293
338
  const inputDigest = computeToolApprovalDigest(name, input);
294
339
  needsGrantConsumption = true;
@@ -513,7 +558,8 @@ export class ToolApprovalHandler {
513
558
  toolName: name,
514
559
  inputDigest,
515
560
  questionText: buildToolGrantQuestionText(name, input, context),
516
- requesterIdentifier: context.requesterDisplayName || context.requesterIdentifier,
561
+ requesterIdentifier:
562
+ context.requesterDisplayName || context.requesterIdentifier,
517
563
  });
518
564
 
519
565
  // Only wait inline if the escalation succeeded (created or deduped).
@@ -34,7 +34,6 @@ export interface ToolPermissionPromptEvent extends ToolLifecycleEventBase {
34
34
  allowlistOptions: AllowlistOption[];
35
35
  scopeOptions: ScopeOption[];
36
36
  diff?: DiffInfo;
37
- sandboxed?: boolean;
38
37
  persistentDecisionsAllowed?: boolean;
39
38
  }
40
39
 
@@ -110,8 +109,6 @@ export interface ToolContext {
110
109
  onOutput?: (chunk: string) => void;
111
110
  /** Abort signal for cooperative cancellation. Tools should check this periodically. */
112
111
  signal?: AbortSignal;
113
- /** Per-conversation sandbox override. When set, takes precedence over the global config. */
114
- sandboxOverride?: boolean;
115
112
  /** Optional callback for tool lifecycle events (start/prompt/deny/execute/error/secret_detected). */
116
113
  onToolLifecycleEvent?: ToolLifecycleEventHandler;
117
114
  /** Optional resolver for proxy tools - delegates execution to an external client. */
@@ -179,6 +176,8 @@ export interface ToolContext {
179
176
  toolUseId?: string;
180
177
  /** Optional proxy for delegating host_bash execution to a connected client (managed/cloud-hosted mode). */
181
178
  hostBashProxy?: import("../daemon/host-bash-proxy.js").HostBashProxy;
179
+ /** Optional proxy for delegating CDP commands to a connected client (managed/cloud-hosted mode). */
180
+ hostBrowserProxy?: import("../daemon/host-browser-proxy.js").HostBrowserProxy;
182
181
  /** Optional proxy for delegating host_file_read/write/edit execution to a connected client (managed/cloud-hosted mode). */
183
182
  hostFileProxy?: import("../daemon/host-file-proxy.js").HostFileProxy;
184
183
  /** True when the assistant is running as a platform-managed remote instance. Used to auto-approve sandboxed bash tools. */
@@ -136,30 +136,13 @@ export function isTCPEnabled(): boolean {
136
136
 
137
137
  /**
138
138
  * Returns the hostname/address for the TCP listener.
139
- * If iOS pairing is enabled (flag file): '0.0.0.0' (LAN-accessible).
140
- * Default: '127.0.0.1' (localhost only).
139
+ * Always binds to localhost only. iOS pairing uses the gateway
140
+ * relay.
141
141
  */
142
142
  export function getTCPHost(): string {
143
- if (isIOSPairingEnabled()) return "0.0.0.0";
144
143
  return "127.0.0.1";
145
144
  }
146
145
 
147
- /**
148
- * Returns whether iOS pairing mode is enabled.
149
- * When enabled, the TCP listener binds to 0.0.0.0 (all interfaces)
150
- * instead of 127.0.0.1 (localhost only), making the daemon reachable
151
- * from iOS devices on the same local network.
152
- *
153
- * Checks for the presence of the flag file ~/.vellum/ios-pairing-enabled.
154
- * Default: false.
155
- *
156
- * This is separate from isTCPEnabled() — TCP can be enabled for localhost-only
157
- * access without exposing the daemon to the LAN.
158
- */
159
- export function isIOSPairingEnabled(): boolean {
160
- return existsSync(join(vellumRoot(), "ios-pairing-enabled"));
161
- }
162
-
163
146
  /**
164
147
  * Returns the XDG-compliant path for the platform API token
165
148
  * (~/.config/vellum/platform-token). This is the canonical location
@@ -202,6 +185,18 @@ export function getPidPath(): string {
202
185
  return join(vellumRoot(), "vellum.pid");
203
186
  }
204
187
 
188
+ /**
189
+ * Returns the path to the runtime HTTP port file (~/.vellum/runtime-port).
190
+ * The daemon writes its active HTTP port here on startup so thin helpers
191
+ * that need to reach the runtime (e.g. the chrome-extension native messaging
192
+ * helper) can locate a non-default `RUNTIME_HTTP_PORT` without a manifest
193
+ * change. Root-level path by design — the file is read by helpers that may
194
+ * not know the workspace override path.
195
+ */
196
+ export function getRuntimePortFilePath(): string {
197
+ return join(vellumRoot(), "runtime-port");
198
+ }
199
+
205
200
  export function getDbPath(): string {
206
201
  return join(getDataDir(), "db", "assistant.db");
207
202
  }
@@ -28,7 +28,7 @@ export interface WatcherProvider {
28
28
  id: string;
29
29
  /** Human-readable name. */
30
30
  displayName: string;
31
- /** Credential service required (e.g. 'integration:google'). */
31
+ /** Credential service required (e.g. 'google'). */
32
32
  requiredCredentialService: string;
33
33
 
34
34
  /**
@@ -14,6 +14,7 @@ const INDEX_TEMPLATE = `_ Lines starting with _ are comments - they won't appear
14
14
  - threads.md — Active commitments, follow-ups, and projects in progress
15
15
  - buffer.md — Inbox of recently learned facts (filed periodically)
16
16
 
17
+
17
18
  ## Topics
18
19
  `;
19
20
 
@@ -0,0 +1,73 @@
1
+ import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ const AUTOINJECT_TEMPLATE = `_ Lines starting with _ are comments - they won't appear in the injected context
7
+ _ List one PKB filename per line. These files are loaded into every conversation.
8
+ _ Remove a line to stop autoinjecting that file. Add new filenames to inject more.
9
+
10
+ INDEX.md
11
+ essentials.md
12
+ threads.md
13
+ buffer.md
14
+ `;
15
+
16
+ const INDEX_ENTRY = "- _autoinject.md — Controls which files are loaded into every conversation";
17
+
18
+ export const seedPkbAutoinjectMigration: WorkspaceMigration = {
19
+ id: "030-seed-pkb-autoinject",
20
+ description: "Seed pkb/_autoinject.md for configurable PKB autoinjection",
21
+
22
+ run(workspaceDir: string): void {
23
+ const pkbDir = join(workspaceDir, "pkb");
24
+ if (!existsSync(pkbDir)) return;
25
+
26
+ // Seed _autoinject.md if it doesn't already exist
27
+ const autoinjectPath = join(pkbDir, "_autoinject.md");
28
+ if (!existsSync(autoinjectPath)) {
29
+ writeFileSync(autoinjectPath, AUTOINJECT_TEMPLATE, "utf-8");
30
+ }
31
+
32
+ // Append _autoinject.md entry to INDEX.md if not already present
33
+ const indexPath = join(pkbDir, "INDEX.md");
34
+ if (existsSync(indexPath)) {
35
+ try {
36
+ const indexContent = readFileSync(indexPath, "utf-8");
37
+ if (!indexContent.includes("_autoinject.md")) {
38
+ // Insert after the last "Always Loaded" entry (buffer.md line)
39
+ const bufferLine = "- buffer.md";
40
+ const bufferIdx = indexContent.indexOf(bufferLine);
41
+ if (bufferIdx !== -1) {
42
+ const endOfBufferLine = indexContent.indexOf("\n", bufferIdx);
43
+ const insertAt =
44
+ endOfBufferLine === -1 ? indexContent.length : endOfBufferLine;
45
+ const updated =
46
+ indexContent.slice(0, insertAt) +
47
+ "\n" +
48
+ INDEX_ENTRY +
49
+ indexContent.slice(insertAt);
50
+ writeFileSync(indexPath, updated, "utf-8");
51
+ }
52
+ }
53
+ } catch {
54
+ // INDEX.md unreadable — skip
55
+ }
56
+ }
57
+ },
58
+
59
+ down(workspaceDir: string): void {
60
+ const autoinjectPath = join(workspaceDir, "pkb", "_autoinject.md");
61
+ if (!existsSync(autoinjectPath)) return;
62
+
63
+ try {
64
+ const content = readFileSync(autoinjectPath, "utf-8");
65
+ // Only delete if content matches the template (preserve user edits)
66
+ if (content === AUTOINJECT_TEMPLATE) {
67
+ unlinkSync(autoinjectPath);
68
+ }
69
+ } catch {
70
+ // Unreadable — leave it alone
71
+ }
72
+ },
73
+ };
@@ -26,6 +26,7 @@ import { backfillInstallMetaMigration } from "./026-backfill-install-meta.js";
26
26
  import { removeOrphanedOptimizedImagesCacheMigration } from "./027-remove-orphaned-optimized-images-cache.js";
27
27
  import { recoverConversationsFromDiskViewMigration } from "./028-recover-conversations-from-disk-view.js";
28
28
  import { seedPkbMigration } from "./029-seed-pkb.js";
29
+ import { seedPkbAutoinjectMigration } from "./030-seed-pkb-autoinject.js";
29
30
  import { migrateToWorkspaceVolumeMigration } from "./migrate-to-workspace-volume.js";
30
31
  import type { WorkspaceMigration } from "./types.js";
31
32
 
@@ -63,4 +64,5 @@ export const WORKSPACE_MIGRATIONS: WorkspaceMigration[] = [
63
64
  removeOrphanedOptimizedImagesCacheMigration,
64
65
  recoverConversationsFromDiskViewMigration,
65
66
  seedPkbMigration,
67
+ seedPkbAutoinjectMigration,
66
68
  ];
@@ -1,7 +1,21 @@
1
+ import { homedir, userInfo } from "node:os";
2
+
1
3
  import type { TopLevelSnapshot } from "./top-level-scanner.js";
2
4
 
3
5
  export interface WorkspaceTopLevelRenderOptions {
4
6
  conversationAttachmentsPath?: string | null;
7
+ /**
8
+ * Host home directory on the client machine. When provided, takes
9
+ * precedence over the daemon's own `os.homedir()`. This matters for
10
+ * platform-managed (containerized) daemons where `os.homedir()` returns
11
+ * the container's home, not the user's actual Mac.
12
+ */
13
+ hostHomeDir?: string;
14
+ /**
15
+ * Host username on the client machine. When provided, takes precedence
16
+ * over the daemon's own `os.userInfo().username`. See `hostHomeDir`.
17
+ */
18
+ hostUsername?: string;
5
19
  }
6
20
 
7
21
  /**
@@ -19,11 +33,15 @@ export function renderWorkspaceTopLevelContext(
19
33
  lines.push(`Directories: ${snapshot.directories.join(", ")}`);
20
34
  lines.push(`Files: ${snapshot.files.join(", ")}`);
21
35
  if (options.conversationAttachmentsPath) {
22
- lines.push(`Current conversation attachments: ${options.conversationAttachmentsPath}`);
36
+ lines.push(
37
+ `Current conversation attachments: ${options.conversationAttachmentsPath}`,
38
+ );
23
39
  }
24
40
  if (snapshot.truncated) {
25
41
  lines.push("(list truncated — more entries exist)");
26
42
  }
43
+ lines.push(`Host home directory: ${options.hostHomeDir ?? homedir()}`);
44
+ lines.push(`Host username: ${options.hostUsername ?? userInfo().username}`);
27
45
  lines.push("</workspace>");
28
46
  return lines.join("\n");
29
47
  }