@vellumai/assistant 0.4.44 → 0.4.45

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 (681) hide show
  1. package/.prettierignore +4 -0
  2. package/ARCHITECTURE.md +34 -31
  3. package/README.md +4 -4
  4. package/bun.lock +10 -35
  5. package/docs/architecture/integrations.md +102 -197
  6. package/docs/architecture/keychain-broker.md +1 -1
  7. package/docs/architecture/memory.md +2 -2
  8. package/docs/architecture/scheduling.md +1 -1
  9. package/docs/architecture/security.md +11 -11
  10. package/docs/error-handling.md +1 -1
  11. package/docs/trusted-contact-access.md +3 -3
  12. package/drizzle/meta/0000_snapshot.json +34 -100
  13. package/drizzle/meta/_journal.json +1 -1
  14. package/drizzle.config.ts +4 -4
  15. package/package.json +3 -2
  16. package/scripts/capture-x-graphql.ts +237 -141
  17. package/scripts/generate-bundled-tool-registry.ts +223 -0
  18. package/src/__tests__/access-request-decision.test.ts +0 -1
  19. package/src/__tests__/actor-token-service.test.ts +23 -24
  20. package/src/__tests__/agent-loop.test.ts +0 -131
  21. package/src/__tests__/always-loaded-tools-guard.test.ts +71 -0
  22. package/src/__tests__/amazon-cdp-integration.test.ts +11 -9
  23. package/src/__tests__/approval-primitive.test.ts +0 -1
  24. package/src/__tests__/approval-routes-http.test.ts +11 -1
  25. package/src/__tests__/asset-materialize-tool.test.ts +0 -1
  26. package/src/__tests__/asset-search-tool.test.ts +0 -1
  27. package/src/__tests__/assistant-attachment-directive.test.ts +1 -1
  28. package/src/__tests__/assistant-events-sse-hardening.test.ts +0 -1
  29. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +70 -18
  31. package/src/__tests__/assistant-id-boundary-guard.test.ts +6 -6
  32. package/src/__tests__/attachments-store.test.ts +0 -1
  33. package/src/__tests__/avatar-e2e.test.ts +74 -115
  34. package/src/__tests__/avatar-router.test.ts +25 -62
  35. package/src/__tests__/browser-manager.test.ts +24 -0
  36. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +4 -3
  37. package/src/__tests__/browser-skill-endstate.test.ts +8 -11
  38. package/src/__tests__/btw-routes.test.ts +326 -0
  39. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +23 -9
  40. package/src/__tests__/call-controller.test.ts +0 -1
  41. package/src/__tests__/call-conversation-messages.test.ts +0 -1
  42. package/src/__tests__/call-domain.test.ts +0 -1
  43. package/src/__tests__/call-pointer-messages.test.ts +0 -1
  44. package/src/__tests__/call-recovery.test.ts +0 -1
  45. package/src/__tests__/call-routes-http.test.ts +0 -1
  46. package/src/__tests__/call-store.test.ts +0 -1
  47. package/src/__tests__/canonical-guardian-store.test.ts +0 -1
  48. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  49. package/src/__tests__/channel-approvals.test.ts +1 -1
  50. package/src/__tests__/channel-delivery-store.test.ts +0 -1
  51. package/src/__tests__/channel-guardian.test.ts +5 -7
  52. package/src/__tests__/channel-retry-sweep.test.ts +0 -1
  53. package/src/__tests__/checker.test.ts +4 -11
  54. package/src/__tests__/compaction.benchmark.test.ts +16 -14
  55. package/src/__tests__/computer-use-session-lifecycle.test.ts +10 -11
  56. package/src/__tests__/computer-use-session-working-dir.test.ts +2 -6
  57. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +2 -5
  58. package/src/__tests__/computer-use-tools.test.ts +35 -31
  59. package/src/__tests__/config-schema.test.ts +11 -15
  60. package/src/__tests__/config-watcher.test.ts +0 -1
  61. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  62. package/src/__tests__/conflict-store.test.ts +0 -1
  63. package/src/__tests__/connection-policy.test.ts +4 -7
  64. package/src/__tests__/contacts-tools.test.ts +0 -1
  65. package/src/__tests__/context-memory-e2e.test.ts +2 -4
  66. package/src/__tests__/context-overflow-reducer.test.ts +2 -4
  67. package/src/__tests__/context-window-manager.test.ts +147 -60
  68. package/src/__tests__/contradiction-checker.test.ts +0 -1
  69. package/src/__tests__/conversation-attention-store.test.ts +0 -1
  70. package/src/__tests__/conversation-attention-telegram.test.ts +1 -1
  71. package/src/__tests__/conversation-pairing.test.ts +2 -2
  72. package/src/__tests__/conversation-routes-guardian-reply.test.ts +25 -1
  73. package/src/__tests__/conversation-routes-slash-commands.test.ts +381 -0
  74. package/src/__tests__/conversation-store.test.ts +0 -1
  75. package/src/__tests__/conversation-unread-route.test.ts +1 -2
  76. package/src/__tests__/credential-security-invariants.test.ts +7 -8
  77. package/src/__tests__/cross-provider-web-search.test.ts +353 -0
  78. package/src/__tests__/daemon-assistant-events.test.ts +6 -7
  79. package/src/__tests__/db-schedule-syntax-migration.test.ts +15 -3
  80. package/src/__tests__/delete-managed-skill-tool.test.ts +5 -9
  81. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
  82. package/src/__tests__/diagnostics-export.test.ts +189 -0
  83. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  84. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
  85. package/src/__tests__/entity-extractor.test.ts +0 -1
  86. package/src/__tests__/entity-search.test.ts +0 -1
  87. package/src/__tests__/ephemeral-permissions.test.ts +2 -4
  88. package/src/__tests__/file-read-tool.test.ts +86 -0
  89. package/src/__tests__/followup-tools.test.ts +0 -1
  90. package/src/__tests__/frontmatter.test.ts +77 -34
  91. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  92. package/src/__tests__/gateway-only-guard.test.ts +1 -1
  93. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -1
  94. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
  95. package/src/__tests__/guardian-action-followup-store.test.ts +0 -1
  96. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
  97. package/src/__tests__/guardian-action-late-reply.test.ts +0 -1
  98. package/src/__tests__/guardian-action-store.test.ts +0 -1
  99. package/src/__tests__/guardian-action-sweep.test.ts +0 -1
  100. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
  101. package/src/__tests__/guardian-dispatch.test.ts +1 -2
  102. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  103. package/src/__tests__/guardian-outbound-http.test.ts +0 -1
  104. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -1
  105. package/src/__tests__/guardian-routing-invariants.test.ts +1 -1
  106. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  107. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  108. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +3 -5
  109. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +28 -426
  110. package/src/__tests__/host-bash-proxy.test.ts +335 -0
  111. package/src/__tests__/host-file-proxy.test.ts +374 -0
  112. package/src/__tests__/host-shell-tool.test.ts +147 -1
  113. package/src/__tests__/http-user-message-parity.test.ts +361 -0
  114. package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
  115. package/src/__tests__/integration-status.test.ts +3 -8
  116. package/src/__tests__/intent-routing.test.ts +7 -46
  117. package/src/__tests__/invite-redemption-service.test.ts +0 -1
  118. package/src/__tests__/invite-routes-http.test.ts +0 -1
  119. package/src/__tests__/llm-usage-store.test.ts +0 -1
  120. package/src/__tests__/managed-avatar-client.test.ts +101 -55
  121. package/src/__tests__/managed-skill-lifecycle.test.ts +9 -18
  122. package/src/__tests__/managed-store.test.ts +94 -21
  123. package/src/__tests__/media-reuse-story.e2e.test.ts +0 -1
  124. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +2 -4
  125. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -1
  126. package/src/__tests__/memory-recall-quality.test.ts +0 -1
  127. package/src/__tests__/memory-regressions.experimental.test.ts +0 -1
  128. package/src/__tests__/memory-regressions.test.ts +0 -1
  129. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -1
  130. package/src/__tests__/memory-upsert-concurrency.test.ts +0 -1
  131. package/src/__tests__/messaging-send-tool.test.ts +35 -0
  132. package/src/__tests__/messaging-skill-split.test.ts +138 -0
  133. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1
  134. package/src/__tests__/migration-export-http.test.ts +2 -3
  135. package/src/__tests__/migration-import-commit-http.test.ts +1 -2
  136. package/src/__tests__/migration-import-preflight-http.test.ts +1 -2
  137. package/src/__tests__/migration-validate-http.test.ts +1 -2
  138. package/src/__tests__/native-web-search.test.ts +475 -0
  139. package/src/__tests__/navigate-settings-tab.test.ts +84 -0
  140. package/src/__tests__/non-member-access-request.test.ts +0 -1
  141. package/src/__tests__/notification-broadcaster.test.ts +15 -15
  142. package/src/__tests__/notification-decision-strategy.test.ts +6 -6
  143. package/src/__tests__/notification-deep-link.test.ts +7 -7
  144. package/src/__tests__/notification-guardian-path.test.ts +2 -3
  145. package/src/__tests__/notification-telegram-adapter.test.ts +1 -1
  146. package/src/__tests__/notification-thread-candidates.test.ts +4 -4
  147. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
  148. package/src/__tests__/playbook-execution.test.ts +0 -1
  149. package/src/__tests__/playbook-tools.test.ts +0 -1
  150. package/src/__tests__/profile-compiler.test.ts +0 -1
  151. package/src/__tests__/provider-managed-proxy-integration.test.ts +25 -0
  152. package/src/__tests__/qdrant-collection-migration.test.ts +223 -0
  153. package/src/__tests__/recording-handler.test.ts +30 -94
  154. package/src/__tests__/registry.test.ts +28 -35
  155. package/src/__tests__/relay-server.test.ts +0 -1
  156. package/src/__tests__/ride-shotgun-handler.test.ts +4 -20
  157. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  158. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  159. package/src/__tests__/runtime-events-sse.test.ts +0 -1
  160. package/src/__tests__/sandbox-diagnostics.test.ts +0 -1
  161. package/src/__tests__/scaffold-managed-skill-tool.test.ts +30 -28
  162. package/src/__tests__/schedule-store.test.ts +441 -1
  163. package/src/__tests__/schedule-tools.test.ts +468 -7
  164. package/src/__tests__/scheduler-recurrence.test.ts +196 -23
  165. package/src/__tests__/scoped-approval-grants.test.ts +0 -1
  166. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
  167. package/src/__tests__/secret-prompt-log-hygiene.test.ts +6 -3
  168. package/src/__tests__/secret-response-routing.test.ts +4 -1
  169. package/src/__tests__/send-endpoint-busy.test.ts +14 -2
  170. package/src/__tests__/send-notification-tool.test.ts +0 -7
  171. package/src/__tests__/sequence-store.test.ts +0 -1
  172. package/src/__tests__/server-history-render.test.ts +1 -2
  173. package/src/__tests__/session-abort-tool-results.test.ts +0 -1
  174. package/src/__tests__/session-agent-loop.test.ts +46 -6
  175. package/src/__tests__/session-confirmation-signals.test.ts +0 -1
  176. package/src/__tests__/session-conflict-gate.test.ts +2 -6
  177. package/src/__tests__/session-error.test.ts +5 -14
  178. package/src/__tests__/session-init.benchmark.test.ts +3 -5
  179. package/src/__tests__/session-load-history-repair.test.ts +0 -1
  180. package/src/__tests__/session-media-retry.test.ts +12 -74
  181. package/src/__tests__/session-pre-run-repair.test.ts +0 -1
  182. package/src/__tests__/session-profile-injection.test.ts +2 -6
  183. package/src/__tests__/session-provider-retry-repair.test.ts +2 -6
  184. package/src/__tests__/session-queue.test.ts +94 -139
  185. package/src/__tests__/session-skill-tools.test.ts +115 -115
  186. package/src/__tests__/session-slash-known.test.ts +0 -1
  187. package/src/__tests__/session-slash-queue.test.ts +0 -1
  188. package/src/__tests__/session-slash-unknown.test.ts +0 -1
  189. package/src/__tests__/session-surfaces-task-progress.test.ts +34 -0
  190. package/src/__tests__/session-usage.test.ts +0 -1
  191. package/src/__tests__/session-workspace-cache-state.test.ts +2 -6
  192. package/src/__tests__/session-workspace-injection.test.ts +2 -6
  193. package/src/__tests__/session-workspace-tool-tracking.test.ts +2 -6
  194. package/src/__tests__/skill-feature-flags-integration.test.ts +180 -184
  195. package/src/__tests__/skill-feature-flags.test.ts +125 -18
  196. package/src/__tests__/skill-load-feature-flag.test.ts +1 -2
  197. package/src/__tests__/skill-load-tool.test.ts +194 -2
  198. package/src/__tests__/skill-projection-feature-flag.test.ts +27 -16
  199. package/src/__tests__/skill-projection.benchmark.test.ts +15 -14
  200. package/src/__tests__/skills.test.ts +14 -53
  201. package/src/__tests__/slack-channel-config.test.ts +0 -1
  202. package/src/__tests__/slack-inbound-verification.test.ts +0 -1
  203. package/src/__tests__/slack-skill.test.ts +1 -1
  204. package/src/__tests__/subagent-tools.test.ts +2 -2
  205. package/src/__tests__/system-prompt.test.ts +4 -3
  206. package/src/__tests__/task-compiler.test.ts +0 -1
  207. package/src/__tests__/task-management-tools.test.ts +0 -1
  208. package/src/__tests__/task-memory-cleanup.test.ts +0 -1
  209. package/src/__tests__/task-runner.test.ts +0 -1
  210. package/src/__tests__/task-scheduler.test.ts +0 -1
  211. package/src/__tests__/terminal-tools.test.ts +0 -1
  212. package/src/__tests__/test-support/computer-use-skill-harness.ts +2 -4
  213. package/src/__tests__/thread-seed-composer.test.ts +5 -5
  214. package/src/__tests__/tool-approval-handler.test.ts +0 -1
  215. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
  216. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
  217. package/src/__tests__/tool-executor.test.ts +8 -86
  218. package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
  219. package/src/__tests__/tool-notification-listener.test.ts +1 -1
  220. package/src/__tests__/tool-preview-lifecycle.test.ts +416 -0
  221. package/src/__tests__/trust-store.test.ts +80 -4
  222. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  223. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  224. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -1
  225. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  226. package/src/__tests__/trusted-contact-verification.test.ts +0 -1
  227. package/src/__tests__/twilio-provider.test.ts +0 -1
  228. package/src/__tests__/twilio-routes.test.ts +0 -1
  229. package/src/__tests__/{request-file-tool.test.ts → ui-file-upload-surface.test.ts} +11 -72
  230. package/src/__tests__/update-bulletin.test.ts +0 -1
  231. package/src/__tests__/usage-cache-backfill-migration.test.ts +0 -1
  232. package/src/__tests__/usage-routes.test.ts +0 -1
  233. package/src/__tests__/verification-control-plane-policy.test.ts +4 -4
  234. package/src/__tests__/voice-invite-redemption.test.ts +0 -1
  235. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
  236. package/src/__tests__/voice-session-bridge.test.ts +9 -1
  237. package/src/__tests__/web-fetch.test.ts +57 -0
  238. package/src/__tests__/workspace-git-service.test.ts +5 -14
  239. package/src/__tests__/workspace-policy.test.ts +0 -1
  240. package/src/agent/loop.ts +22 -34
  241. package/src/bundler/bundle-signer.ts +4 -4
  242. package/src/calls/call-controller.ts +1 -1
  243. package/src/calls/relay-server.ts +1 -1
  244. package/src/calls/twilio-rest.ts +1 -1
  245. package/src/calls/voice-session-bridge.ts +3 -1
  246. package/src/cli/__tests__/notifications.test.ts +3 -4
  247. package/src/cli/commands/map.ts +2 -6
  248. package/src/cli/commands/mcp.ts +73 -15
  249. package/src/cli/commands/notifications.ts +4 -4
  250. package/src/cli/commands/sessions.ts +9 -1
  251. package/src/cli/commands/skills.ts +6 -10
  252. package/src/cli/http-client.ts +2 -3
  253. package/src/cli/main-screen.tsx +10 -10
  254. package/src/cli/program.ts +0 -4
  255. package/src/cli/reference.ts +0 -2
  256. package/src/cli.ts +15 -9
  257. package/src/config/__tests__/bundled-tool-registry-guard.test.ts +120 -0
  258. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +11 -0
  259. package/src/config/bundled-skills/app-builder/SKILL.md +6 -1
  260. package/src/config/bundled-skills/browser/SKILL.md +6 -1
  261. package/src/config/bundled-skills/chatgpt-import/SKILL.md +5 -1
  262. package/src/config/bundled-skills/claude-code/SKILL.md +5 -1
  263. package/src/config/bundled-skills/computer-use/SKILL.md +6 -1
  264. package/src/config/bundled-skills/computer-use/TOOLS.json +6 -69
  265. package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +10 -1
  266. package/src/config/bundled-skills/contacts/SKILL.md +10 -1
  267. package/src/config/bundled-skills/contacts/TOOLS.json +35 -0
  268. package/src/config/bundled-skills/{messaging → contacts}/tools/google-contacts.ts +9 -2
  269. package/src/config/bundled-skills/document/SKILL.md +4 -1
  270. package/src/config/bundled-skills/doordash/SKILL.md +8 -1
  271. package/src/config/bundled-skills/doordash/lib/shared/platform.ts +4 -1
  272. package/src/config/bundled-skills/followups/SKILL.md +4 -1
  273. package/src/config/bundled-skills/gmail/SKILL.md +180 -0
  274. package/src/config/bundled-skills/gmail/TOOLS.json +506 -0
  275. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +149 -0
  276. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +110 -0
  277. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-draft.ts +1 -1
  278. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-filters.ts +1 -1
  279. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-follow-up.ts +1 -1
  280. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-forward.ts +1 -1
  281. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +50 -0
  282. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-outreach-scan.ts +8 -90
  283. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-send-draft.ts +1 -1
  284. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-sender-digest.ts +2 -2
  285. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-trash.ts +1 -1
  286. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-unsubscribe.ts +1 -1
  287. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-vacation.ts +1 -1
  288. package/src/config/bundled-skills/gmail/tools/shared.ts +47 -0
  289. package/src/config/bundled-skills/google-calendar/SKILL.md +5 -1
  290. package/src/config/bundled-skills/image-studio/SKILL.md +5 -1
  291. package/src/config/bundled-skills/knowledge-graph/SKILL.md +4 -1
  292. package/src/config/bundled-skills/media-processing/SKILL.md +7 -13
  293. package/src/config/bundled-skills/media-processing/TOOLS.json +0 -22
  294. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +12 -1
  295. package/src/config/bundled-skills/messaging/SKILL.md +23 -139
  296. package/src/config/bundled-skills/messaging/TOOLS.json +33 -1215
  297. package/src/config/bundled-skills/messaging/tools/gmail-mime-helpers.ts +42 -0
  298. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +165 -2
  299. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +1 -13
  300. package/src/config/bundled-skills/messaging/tools/shared.ts +81 -34
  301. package/src/config/bundled-skills/notifications/SKILL.md +5 -1
  302. package/src/config/bundled-skills/orchestration/SKILL.md +30 -0
  303. package/src/config/bundled-skills/orchestration/TOOLS.json +35 -0
  304. package/src/config/bundled-skills/{reminder/tools/reminder-create.ts → orchestration/tools/swarm-delegate.ts} +3 -3
  305. package/src/config/bundled-skills/phone-calls/SKILL.md +9 -1
  306. package/src/config/bundled-skills/playbooks/SKILL.md +4 -1
  307. package/src/config/bundled-skills/schedule/SKILL.md +70 -9
  308. package/src/config/bundled-skills/schedule/TOOLS.json +38 -6
  309. package/src/config/bundled-skills/screen-watch/SKILL.md +28 -0
  310. package/src/config/bundled-skills/screen-watch/TOOLS.json +35 -0
  311. package/src/config/bundled-skills/{reminder/tools/reminder-cancel.ts → screen-watch/tools/start-screen-watch.ts} +3 -3
  312. package/src/config/bundled-skills/sequences/SKILL.md +47 -0
  313. package/src/config/bundled-skills/sequences/TOOLS.json +340 -0
  314. package/src/config/bundled-skills/sequences/tools/sequence-update.ts +128 -0
  315. package/src/config/bundled-skills/sequences/tools/shared.ts +9 -0
  316. package/src/config/bundled-skills/settings/SKILL.md +12 -0
  317. package/src/config/bundled-skills/settings/TOOLS.json +112 -0
  318. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +43 -0
  319. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +52 -0
  320. package/src/config/bundled-skills/{computer-use/tools/computer-use-right-click.ts → settings/tools/set-avatar.ts} +2 -6
  321. package/src/{tools/system/voice-config.ts → config/bundled-skills/settings/tools/voice-config-update.ts} +59 -96
  322. package/src/config/bundled-skills/skill-management/SKILL.md +18 -0
  323. package/src/config/bundled-skills/skill-management/TOOLS.json +90 -0
  324. package/src/config/bundled-skills/{computer-use/tools/computer-use-double-click.ts → skill-management/tools/delete-managed.ts} +2 -6
  325. package/src/config/bundled-skills/skill-management/tools/scaffold-managed.ts +12 -0
  326. package/src/config/bundled-skills/slack/SKILL.md +5 -1
  327. package/src/config/bundled-skills/subagent/SKILL.md +4 -1
  328. package/src/config/bundled-skills/tasks/SKILL.md +5 -2
  329. package/src/config/bundled-skills/transcribe/SKILL.md +4 -1
  330. package/src/config/bundled-skills/watcher/SKILL.md +4 -1
  331. package/src/config/bundled-tool-registry.ts +118 -107
  332. package/src/config/env.ts +5 -2
  333. package/src/config/feature-flag-registry.json +25 -9
  334. package/src/config/loader.ts +10 -2
  335. package/src/config/schema.ts +19 -16
  336. package/src/config/schemas/inference.ts +12 -22
  337. package/src/config/schemas/memory-storage.ts +19 -1
  338. package/src/config/schemas/platform.ts +0 -16
  339. package/src/config/skill-state.ts +11 -8
  340. package/src/config/skills.ts +83 -32
  341. package/src/context/token-estimator.ts +11 -0
  342. package/src/context/window-manager.ts +180 -151
  343. package/src/daemon/computer-use-session.ts +11 -43
  344. package/src/daemon/daemon-control.ts +4 -1
  345. package/src/daemon/handlers/config-channels.ts +5 -9
  346. package/src/daemon/handlers/config-ingress.ts +0 -4
  347. package/src/daemon/handlers/config-model.ts +7 -13
  348. package/src/daemon/handlers/config-telegram.ts +4 -8
  349. package/src/daemon/handlers/config-voice.ts +2 -5
  350. package/src/daemon/handlers/dictation.ts +2 -12
  351. package/src/daemon/handlers/identity.ts +0 -105
  352. package/src/daemon/handlers/recording.ts +3 -23
  353. package/src/daemon/handlers/session-history.ts +1 -1
  354. package/src/daemon/handlers/sessions.ts +53 -72
  355. package/src/daemon/handlers/shared.ts +7 -28
  356. package/src/daemon/handlers/skills.ts +31 -27
  357. package/src/daemon/host-bash-proxy.ts +148 -0
  358. package/src/daemon/host-file-proxy.ts +135 -0
  359. package/src/daemon/lifecycle.ts +49 -24
  360. package/src/daemon/mcp-reload-service.ts +123 -0
  361. package/src/daemon/message-protocol.ts +6 -0
  362. package/src/daemon/message-types/browser.ts +1 -1
  363. package/src/daemon/message-types/computer-use.ts +1 -4
  364. package/src/daemon/message-types/guardian-actions.ts +1 -1
  365. package/src/daemon/message-types/host-bash.ts +18 -0
  366. package/src/daemon/message-types/host-file.ts +44 -0
  367. package/src/daemon/message-types/integrations.ts +1 -67
  368. package/src/daemon/message-types/messages.ts +15 -0
  369. package/src/daemon/message-types/schedules.ts +11 -27
  370. package/src/daemon/message-types/sessions.ts +2 -1
  371. package/src/daemon/message-types/settings.ts +1 -1
  372. package/src/daemon/message-types/shared.ts +1 -1
  373. package/src/daemon/ride-shotgun-handler.ts +2 -42
  374. package/src/daemon/server.ts +43 -10
  375. package/src/daemon/session-agent-loop-handlers.ts +48 -7
  376. package/src/daemon/session-agent-loop.ts +97 -66
  377. package/src/daemon/session-attachments.ts +1 -1
  378. package/src/daemon/session-error.ts +17 -16
  379. package/src/daemon/session-lifecycle.ts +20 -1
  380. package/src/daemon/session-media-retry.ts +1 -15
  381. package/src/daemon/session-messaging.ts +14 -6
  382. package/src/daemon/session-process.ts +36 -7
  383. package/src/daemon/session-queue-manager.ts +62 -103
  384. package/src/daemon/session-runtime-assembly.ts +27 -0
  385. package/src/daemon/session-skill-tools.ts +12 -11
  386. package/src/daemon/session-slash.ts +7 -0
  387. package/src/daemon/session-surfaces.ts +19 -97
  388. package/src/daemon/session-tool-setup.ts +146 -6
  389. package/src/daemon/session.ts +77 -13
  390. package/src/errors.ts +0 -2
  391. package/src/export/formatter.ts +6 -0
  392. package/src/mcp/mcp-oauth-provider.ts +1 -3
  393. package/src/media/avatar-router.ts +20 -28
  394. package/src/media/avatar-types.ts +7 -14
  395. package/src/media/managed-avatar-client.ts +70 -34
  396. package/src/memory/conversation-title-service.ts +1 -2
  397. package/src/memory/db-init.ts +16 -0
  398. package/src/memory/embedding-backend.ts +129 -27
  399. package/src/memory/embedding-gemini.test.ts +256 -0
  400. package/src/memory/embedding-gemini.ts +47 -13
  401. package/src/memory/embedding-local.ts +14 -2
  402. package/src/memory/embedding-ollama.ts +15 -2
  403. package/src/memory/embedding-openai.ts +15 -2
  404. package/src/memory/embedding-types.test.ts +116 -0
  405. package/src/memory/embedding-types.ts +61 -0
  406. package/src/memory/fingerprint.ts +1 -1
  407. package/src/memory/indexer.ts +25 -1
  408. package/src/memory/job-handlers/embedding.test.ts +258 -0
  409. package/src/memory/job-handlers/embedding.ts +81 -1
  410. package/src/memory/job-handlers/index-maintenance.ts +35 -1
  411. package/src/memory/job-handlers/media-processing.ts +11 -1
  412. package/src/memory/job-utils.ts +21 -6
  413. package/src/memory/jobs-store.ts +5 -1
  414. package/src/memory/jobs-worker.ts +8 -0
  415. package/src/memory/message-content.ts +66 -0
  416. package/src/memory/migrations/100-core-tables.ts +1 -31
  417. package/src/memory/migrations/104-core-indexes.ts +0 -11
  418. package/src/memory/migrations/145-drop-accounts-table.ts +19 -0
  419. package/src/memory/migrations/146-schedule-oneshot-routing.ts +94 -0
  420. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +129 -0
  421. package/src/memory/migrations/148-drop-reminders-table.ts +18 -0
  422. package/src/memory/migrations/index.ts +4 -0
  423. package/src/memory/migrations/registry.ts +19 -0
  424. package/src/memory/qdrant-client.ts +158 -43
  425. package/src/memory/retriever.test.ts +0 -1
  426. package/src/memory/retriever.ts +12 -2
  427. package/src/memory/schema/infrastructure.ts +5 -29
  428. package/src/memory/search/formatting.ts +34 -9
  429. package/src/memory/search/semantic.ts +57 -2
  430. package/src/memory/search/types.ts +2 -1
  431. package/src/notifications/AGENTS.md +2 -2
  432. package/src/notifications/README.md +59 -58
  433. package/src/notifications/adapters/macos.ts +1 -1
  434. package/src/notifications/broadcaster.ts +5 -5
  435. package/src/notifications/copy-composer.ts +1 -1
  436. package/src/notifications/decision-engine.ts +2 -2
  437. package/src/notifications/destination-resolver.ts +2 -2
  438. package/src/notifications/emit-signal.ts +8 -8
  439. package/src/notifications/signal.ts +1 -1
  440. package/src/notifications/thread-seed-composer.ts +1 -1
  441. package/src/oauth/connect-orchestrator.ts +1 -1
  442. package/src/oauth/token-persistence.ts +1 -1
  443. package/src/permissions/checker.ts +12 -1
  444. package/src/permissions/defaults.ts +10 -14
  445. package/src/permissions/trust-store.ts +37 -0
  446. package/src/permissions/workspace-policy.ts +0 -1
  447. package/src/prompts/__tests__/build-cli-reference-section.test.ts +11 -0
  448. package/src/prompts/computer-use-prompt.ts +1 -1
  449. package/src/prompts/system-prompt.ts +29 -30
  450. package/src/prompts/templates/SOUL.md +1 -2
  451. package/src/prompts/templates/UPDATES.md +16 -7
  452. package/src/providers/anthropic/client.ts +87 -33
  453. package/src/providers/gemini/client.ts +6 -0
  454. package/src/providers/managed-proxy/constants.ts +5 -0
  455. package/src/providers/openai/client.ts +15 -0
  456. package/src/providers/registry.ts +2 -2
  457. package/src/providers/types.ts +24 -2
  458. package/src/runtime/AGENTS.md +18 -0
  459. package/src/runtime/assistant-event-hub.ts +2 -3
  460. package/src/runtime/assistant-event.ts +4 -4
  461. package/src/runtime/auth/__tests__/context.test.ts +5 -5
  462. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  463. package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -2
  464. package/src/runtime/auth/__tests__/{ipc-auth-context.test.ts → local-auth-context.test.ts} +21 -21
  465. package/src/runtime/auth/__tests__/route-policy.test.ts +2 -2
  466. package/src/runtime/auth/__tests__/scopes.test.ts +7 -7
  467. package/src/runtime/auth/__tests__/subject.test.ts +8 -8
  468. package/src/runtime/auth/__tests__/token-service.test.ts +0 -1
  469. package/src/runtime/auth/route-policy.ts +8 -4
  470. package/src/runtime/auth/scopes.ts +1 -1
  471. package/src/runtime/auth/subject.ts +4 -4
  472. package/src/runtime/auth/token-service.ts +0 -23
  473. package/src/runtime/auth/types.ts +3 -3
  474. package/src/runtime/guardian-action-followup-executor.ts +1 -1
  475. package/src/runtime/guardian-action-grant-minter.ts +1 -1
  476. package/src/runtime/guardian-action-service.ts +3 -3
  477. package/src/runtime/http-server.ts +15 -2
  478. package/src/runtime/invite-service.ts +3 -3
  479. package/src/runtime/local-actor-identity.ts +17 -22
  480. package/src/runtime/pending-interactions.ts +21 -9
  481. package/src/runtime/routes/app-management-routes.ts +2 -3
  482. package/src/runtime/routes/approval-routes.ts +1 -3
  483. package/src/runtime/routes/btw-routes.ts +155 -0
  484. package/src/runtime/routes/computer-use-routes.ts +77 -31
  485. package/src/runtime/routes/conversation-routes.ts +230 -46
  486. package/src/runtime/routes/diagnostics-routes.ts +63 -29
  487. package/src/runtime/routes/documents-routes.ts +2 -2
  488. package/src/runtime/routes/global-search-routes.ts +1 -1
  489. package/src/runtime/routes/host-bash-routes.ts +83 -0
  490. package/src/runtime/routes/host-file-routes.ts +79 -0
  491. package/src/runtime/routes/integrations/slack/share.ts +1 -1
  492. package/src/runtime/routes/log-export-routes.ts +120 -0
  493. package/src/runtime/routes/mcp-routes.ts +20 -0
  494. package/src/runtime/routes/migration-routes.ts +3 -3
  495. package/src/runtime/routes/pairing-routes.ts +1 -1
  496. package/src/runtime/routes/recording-routes.ts +6 -4
  497. package/src/runtime/routes/schedule-routes.ts +31 -5
  498. package/src/runtime/routes/session-management-routes.ts +2 -6
  499. package/src/runtime/routes/session-query-routes.ts +18 -15
  500. package/src/runtime/routes/settings-routes.ts +7 -261
  501. package/src/runtime/routes/skills-routes.ts +7 -6
  502. package/src/runtime/routes/subagents-routes.ts +4 -10
  503. package/src/runtime/routes/surface-action-routes.ts +3 -14
  504. package/src/runtime/routes/surface-content-routes.ts +22 -5
  505. package/src/runtime/routes/work-items-routes.ts +21 -25
  506. package/src/runtime/routes/workspace-routes.test.ts +3 -3
  507. package/src/runtime/routes/workspace-utils.ts +1 -1
  508. package/src/runtime/telegram-streaming-delivery.ts +3 -0
  509. package/src/runtime/verification-outbound-actions.ts +2 -2
  510. package/src/schedule/integration-status.ts +0 -6
  511. package/src/schedule/schedule-store.ts +234 -43
  512. package/src/schedule/scheduler.ts +73 -74
  513. package/src/security/oauth2.ts +1 -1
  514. package/src/sequence/store.ts +12 -2
  515. package/src/skills/frontmatter.ts +19 -77
  516. package/src/skills/managed-store.ts +11 -2
  517. package/src/subagent/manager.ts +5 -3
  518. package/src/tasks/ephemeral-permissions.ts +3 -5
  519. package/src/tools/AGENTS.md +0 -1
  520. package/src/tools/browser/browser-manager.ts +17 -11
  521. package/src/tools/browser/jit-auth.ts +4 -1
  522. package/src/tools/claude-code/claude-code.ts +1 -1
  523. package/src/tools/computer-use/definitions.ts +48 -60
  524. package/src/tools/document/document-tool.ts +6 -6
  525. package/src/tools/filesystem/edit.ts +2 -1
  526. package/src/tools/filesystem/read.ts +20 -2
  527. package/src/tools/filesystem/write.ts +2 -1
  528. package/src/tools/host-filesystem/edit.ts +17 -1
  529. package/src/tools/host-filesystem/read.ts +16 -1
  530. package/src/tools/host-filesystem/write.ts +15 -1
  531. package/src/tools/host-terminal/host-shell.ts +24 -0
  532. package/src/tools/memory/definitions.ts +45 -81
  533. package/src/tools/memory/handlers.test.ts +0 -1
  534. package/src/tools/memory/handlers.ts +1 -1
  535. package/src/tools/memory/register.ts +26 -60
  536. package/src/tools/network/script-proxy/session-manager.ts +6 -8
  537. package/src/tools/network/web-fetch.ts +7 -1
  538. package/src/tools/network/web-search.ts +2 -1
  539. package/src/tools/registry.ts +23 -0
  540. package/src/tools/schedule/create.ts +113 -5
  541. package/src/tools/schedule/list.ts +57 -15
  542. package/src/tools/schedule/update.ts +73 -3
  543. package/src/tools/shared/filesystem/image-read.ts +192 -0
  544. package/src/tools/side-effects.ts +1 -7
  545. package/src/tools/skills/delete-managed.ts +27 -64
  546. package/src/tools/skills/execute.ts +54 -0
  547. package/src/tools/skills/load.ts +127 -5
  548. package/src/tools/skills/scaffold-managed.ts +93 -172
  549. package/src/tools/subagent/message.ts +0 -7
  550. package/src/tools/subagent/spawn.ts +1 -1
  551. package/src/tools/swarm/delegate.ts +0 -3
  552. package/src/tools/system/avatar-generator.ts +13 -19
  553. package/src/tools/system/request-permission.ts +2 -1
  554. package/src/tools/terminal/safe-env.ts +1 -0
  555. package/src/tools/tool-manifest.ts +41 -47
  556. package/src/tools/types.ts +6 -2
  557. package/src/tools/ui-surface/definitions.ts +0 -55
  558. package/src/util/errors.ts +0 -10
  559. package/src/workspace/git-service.ts +0 -2
  560. package/src/__tests__/account-registry.test.ts +0 -258
  561. package/src/__tests__/email-classifier.test.ts +0 -25
  562. package/src/__tests__/gmail-integration.test.ts +0 -97
  563. package/src/__tests__/handle-user-message-secret-resume.test.ts +0 -172
  564. package/src/__tests__/managed-twitter-guardrails.test.ts +0 -357
  565. package/src/__tests__/recording-intent-fallback.test.ts +0 -199
  566. package/src/__tests__/recording-intent.test.ts +0 -985
  567. package/src/__tests__/recording-state-machine.test.ts +0 -1574
  568. package/src/__tests__/reminder-store.test.ts +0 -350
  569. package/src/__tests__/reminder.test.ts +0 -337
  570. package/src/__tests__/scan-result-store.test.ts +0 -121
  571. package/src/__tests__/twitter-platform-proxy-client.test.ts +0 -475
  572. package/src/__tests__/view-image-tool.test.ts +0 -241
  573. package/src/cli/commands/amazon/cart.ts +0 -513
  574. package/src/cli/commands/amazon/checkout.ts +0 -394
  575. package/src/cli/commands/amazon/client.ts +0 -513
  576. package/src/cli/commands/amazon/index.ts +0 -885
  577. package/src/cli/commands/amazon/product-details.ts +0 -145
  578. package/src/cli/commands/amazon/request-extractor.ts +0 -187
  579. package/src/cli/commands/amazon/search.ts +0 -76
  580. package/src/cli/commands/amazon/session.ts +0 -108
  581. package/src/cli/commands/twitter/__tests__/cli-read-routing.test.ts +0 -345
  582. package/src/cli/commands/twitter/__tests__/cli-routing.test.ts +0 -252
  583. package/src/cli/commands/twitter/__tests__/oauth-client.test.ts +0 -151
  584. package/src/cli/commands/twitter/index.ts +0 -420
  585. package/src/cli/commands/twitter/oauth-client.ts +0 -60
  586. package/src/cli/commands/twitter/router.ts +0 -351
  587. package/src/cli/commands/twitter/types.ts +0 -30
  588. package/src/config/bundled-skills/agentmail/SKILL.md +0 -132
  589. package/src/config/bundled-skills/agentmail/icon.svg +0 -21
  590. package/src/config/bundled-skills/amazon/SKILL.md +0 -136
  591. package/src/config/bundled-skills/amazon/icon.svg +0 -13
  592. package/src/config/bundled-skills/api-mapping/SKILL.md +0 -78
  593. package/src/config/bundled-skills/api-mapping/icon.svg +0 -18
  594. package/src/config/bundled-skills/cli-discover/SKILL.md +0 -68
  595. package/src/config/bundled-skills/deploy-fullstack-vercel/SKILL.md +0 -179
  596. package/src/config/bundled-skills/document-writer/SKILL.md +0 -195
  597. package/src/config/bundled-skills/elevenlabs-voice/SKILL.md +0 -140
  598. package/src/config/bundled-skills/email-setup/SKILL.md +0 -68
  599. package/src/config/bundled-skills/frontend-design/SKILL.md +0 -44
  600. package/src/config/bundled-skills/frontend-design/icon.svg +0 -16
  601. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +0 -452
  602. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +0 -203
  603. package/src/config/bundled-skills/influencer/SKILL.md +0 -144
  604. package/src/config/bundled-skills/influencer/scripts/client.ts +0 -1269
  605. package/src/config/bundled-skills/influencer/scripts/influencer.ts +0 -267
  606. package/src/config/bundled-skills/macos-automation/SKILL.md +0 -65
  607. package/src/config/bundled-skills/macos-automation/icon.svg +0 -12
  608. package/src/config/bundled-skills/mcp-setup/SKILL.md +0 -75
  609. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +0 -184
  610. package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +0 -80
  611. package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +0 -29
  612. package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +0 -56
  613. package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +0 -34
  614. package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +0 -47
  615. package/src/config/bundled-skills/messaging/tools/gmail-label.ts +0 -31
  616. package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +0 -67
  617. package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +0 -97
  618. package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +0 -87
  619. package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +0 -135
  620. package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +0 -24
  621. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +0 -201
  622. package/src/config/bundled-skills/messaging/tools/send-notification.ts +0 -1
  623. package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +0 -27
  624. package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +0 -48
  625. package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +0 -27
  626. package/src/config/bundled-skills/messaging/tools/sequence-update.ts +0 -56
  627. package/src/config/bundled-skills/notion/SKILL.md +0 -240
  628. package/src/config/bundled-skills/notion-oauth-setup/SKILL.md +0 -126
  629. package/src/config/bundled-skills/oauth-setup/SKILL.md +0 -143
  630. package/src/config/bundled-skills/public-ingress/SKILL.md +0 -258
  631. package/src/config/bundled-skills/reminder/SKILL.md +0 -79
  632. package/src/config/bundled-skills/reminder/TOOLS.json +0 -89
  633. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +0 -12
  634. package/src/config/bundled-skills/restaurant-reservation/SKILL.md +0 -141
  635. package/src/config/bundled-skills/screen-recording/SKILL.md +0 -148
  636. package/src/config/bundled-skills/self-upgrade/SKILL.md +0 -69
  637. package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -78
  638. package/src/config/bundled-skills/slack-app-setup/SKILL.md +0 -178
  639. package/src/config/bundled-skills/slack-digest-setup/SKILL.md +0 -163
  640. package/src/config/bundled-skills/slack-oauth-setup/SKILL.md +0 -157
  641. package/src/config/bundled-skills/start-the-day/SKILL.md +0 -70
  642. package/src/config/bundled-skills/start-the-day/icon.svg +0 -13
  643. package/src/config/bundled-skills/telegram-setup/SKILL.md +0 -105
  644. package/src/config/bundled-skills/time-based-actions/SKILL.md +0 -142
  645. package/src/config/bundled-skills/twilio-setup/SKILL.md +0 -232
  646. package/src/config/bundled-skills/twitter/SKILL.md +0 -206
  647. package/src/config/bundled-skills/twitter/icon.svg +0 -14
  648. package/src/config/bundled-skills/typescript-eval/SKILL.md +0 -60
  649. package/src/config/bundled-skills/vercel-token-setup/SKILL.md +0 -214
  650. package/src/config/bundled-skills/voice-setup/SKILL.md +0 -131
  651. package/src/config/bundled-skills/voice-setup/icon.svg +0 -20
  652. package/src/daemon/handlers/pairing.ts +0 -119
  653. package/src/daemon/handlers/session-user-message.ts +0 -961
  654. package/src/daemon/recording-executor.ts +0 -180
  655. package/src/daemon/recording-intent-fallback.ts +0 -162
  656. package/src/daemon/recording-intent.ts +0 -493
  657. package/src/memory/account-store.ts +0 -117
  658. package/src/messaging/activity-analyzer.ts +0 -76
  659. package/src/messaging/email-classifier.ts +0 -208
  660. package/src/messaging/index.ts +0 -2
  661. package/src/messaging/outreach-classifier.ts +0 -185
  662. package/src/messaging/thread-summarizer.ts +0 -346
  663. package/src/messaging/types.ts +0 -17
  664. package/src/tools/browser/x-auto-navigate.ts +0 -254
  665. package/src/tools/credentials/account-registry.ts +0 -144
  666. package/src/tools/filesystem/view-image.ts +0 -244
  667. package/src/tools/reminder/reminder-store.ts +0 -194
  668. package/src/tools/reminder/reminder.ts +0 -158
  669. package/src/tools/system/navigate-settings.ts +0 -74
  670. package/src/tools/system/open-system-settings.ts +0 -85
  671. package/src/tools/system/version.ts +0 -54
  672. package/src/twitter/platform-proxy-client.ts +0 -408
  673. /package/src/config/bundled-skills/{messaging → gmail}/tools/scan-result-store.ts +0 -0
  674. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-analytics.ts +0 -0
  675. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-create.ts +0 -0
  676. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-delete.ts +0 -0
  677. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enroll.ts +0 -0
  678. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enrollment-list.ts +0 -0
  679. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-get.ts +0 -0
  680. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-import.ts +0 -0
  681. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-list.ts +0 -0
@@ -1,13 +1,6 @@
1
1
  import { bootstrapConversation } from "../memory/conversation-bootstrap.js";
2
2
  import { invalidateAssistantInferredItemsForConversation } from "../memory/task-memory-cleanup.js";
3
3
  import { runSequencesOnce } from "../sequence/engine.js";
4
- import {
5
- claimDueReminders,
6
- completeReminder,
7
- failReminder,
8
- type RoutingIntent,
9
- setReminderConversationId,
10
- } from "../tools/reminder/reminder-store.js";
11
4
  import { getLogger } from "../util/logger.js";
12
5
  import {
13
6
  runWatchersOnce,
@@ -17,8 +10,11 @@ import {
17
10
  import { hasSetConstructs } from "./recurrence-engine.js";
18
11
  import {
19
12
  claimDueSchedules,
13
+ completeOneShot,
20
14
  completeScheduleRun,
21
15
  createScheduleRun,
16
+ failOneShot,
17
+ type RoutingIntent,
22
18
  } from "./schedule-store.js";
23
19
 
24
20
  const log = getLogger("scheduler");
@@ -33,13 +29,13 @@ export type ScheduleMessageProcessor = (
33
29
  options?: ScheduleMessageOptions,
34
30
  ) => Promise<unknown>;
35
31
 
36
- export type ReminderNotifier = (reminder: {
32
+ export type ScheduleNotifyModeNotifier = (payload: {
37
33
  id: string;
38
34
  label: string;
39
35
  message: string;
40
36
  routingIntent: RoutingIntent;
41
37
  routingHints: Record<string, unknown>;
42
- }) => void;
38
+ }) => void | Promise<void>;
43
39
 
44
40
  export type ScheduleNotifier = (schedule: { id: string; name: string }) => void;
45
41
 
@@ -58,7 +54,7 @@ const TICK_INTERVAL_MS = 15_000;
58
54
 
59
55
  export function startScheduler(
60
56
  processMessage: ScheduleMessageProcessor,
61
- notifyReminder: ReminderNotifier,
57
+ notifyScheduleOneShot: ScheduleNotifyModeNotifier,
62
58
  notifySchedule: ScheduleNotifier,
63
59
  watcherNotifier?: WatcherNotifier,
64
60
  watcherEscalator?: WatcherEscalator,
@@ -73,7 +69,7 @@ export function startScheduler(
73
69
  try {
74
70
  await runScheduleOnce(
75
71
  processMessage,
76
- notifyReminder,
72
+ notifyScheduleOneShot,
77
73
  notifySchedule,
78
74
  watcherNotifier,
79
75
  watcherEscalator,
@@ -96,7 +92,7 @@ export function startScheduler(
96
92
  async runOnce(): Promise<number> {
97
93
  return runScheduleOnce(
98
94
  processMessage,
99
- notifyReminder,
95
+ notifyScheduleOneShot,
100
96
  notifySchedule,
101
97
  watcherNotifier,
102
98
  watcherEscalator,
@@ -112,7 +108,7 @@ export function startScheduler(
112
108
 
113
109
  async function runScheduleOnce(
114
110
  processMessage: ScheduleMessageProcessor,
115
- notifyReminder: ReminderNotifier,
111
+ notifyScheduleOneShot: ScheduleNotifyModeNotifier,
116
112
  notifySchedule: ScheduleNotifier,
117
113
  watcherNotifier?: WatcherNotifier,
118
114
  watcherEscalator?: WatcherEscalator,
@@ -121,15 +117,60 @@ async function runScheduleOnce(
121
117
  const now = Date.now();
122
118
  let processed = 0;
123
119
 
124
- // ── Recurrence schedules (cron + RRULE) ─────────────────────────────
120
+ // ── Schedules (recurring cron/RRULE + one-shot) ─────────────────────
125
121
  const jobs = claimDueSchedules(now);
126
122
  for (const job of jobs) {
123
+ const isOneShot = job.expression == null;
124
+
125
+ // ── Notify mode (one-shot or recurring) ─────────────────────────
126
+ if (job.mode === "notify") {
127
+ try {
128
+ log.info(
129
+ { jobId: job.id, name: job.name, isOneShot },
130
+ "Firing schedule notification",
131
+ );
132
+ await notifyScheduleOneShot({
133
+ id: job.id,
134
+ label: job.name,
135
+ message: job.message,
136
+ routingIntent: job.routingIntent,
137
+ routingHints: job.routingHints,
138
+ });
139
+ if (isOneShot) {
140
+ completeOneShot(job.id);
141
+ } else {
142
+ // Track recurring notify-mode success so lastStatus resets to ok
143
+ // and retryCount clears after a transient failure.
144
+ const runId = createScheduleRun(job.id, `notify-ok:${job.id}`);
145
+ completeScheduleRun(runId, { status: "ok" });
146
+ }
147
+ } catch (err) {
148
+ log.warn(
149
+ { err, jobId: job.id, name: job.name, isOneShot },
150
+ "Schedule notification failed",
151
+ );
152
+ if (isOneShot) {
153
+ failOneShot(job.id);
154
+ } else {
155
+ // Track recurring notify-mode failures via a schedule run so the
156
+ // occurrence isn't silently lost and lastStatus/retryCount update.
157
+ const errorMsg = err instanceof Error ? err.message : String(err);
158
+ const runId = createScheduleRun(job.id, `notify-error:${job.id}`);
159
+ completeScheduleRun(runId, { status: "error", error: errorMsg });
160
+ }
161
+ }
162
+ processed += 1;
163
+ continue;
164
+ }
165
+
166
+ // ── Execute mode ────────────────────────────────────────────────
167
+
127
168
  // Check if message is a task invocation (run_task:<task_id>)
128
169
  const taskMatch = job.message.match(/^run_task:(\S+)$/);
129
170
  if (taskMatch) {
130
171
  const taskId = taskMatch[1];
131
172
  const isRruleSet =
132
- job.syntax === "rrule" && hasSetConstructs(job.expression);
173
+ job.syntax === "rrule" && job.expression != null && hasSetConstructs(job.expression);
133
174
  try {
134
175
  log.info(
135
176
  {
@@ -139,6 +180,7 @@ async function runScheduleOnce(
139
180
  syntax: job.syntax,
140
181
  expression: job.expression,
141
182
  isRruleSet,
183
+ isOneShot,
142
184
  },
143
185
  "Executing scheduled task",
144
186
  );
@@ -159,9 +201,11 @@ async function runScheduleOnce(
159
201
  status: "error",
160
202
  error: result.error ?? "Task run failed",
161
203
  });
204
+ if (isOneShot) failOneShot(job.id);
162
205
  } else {
163
206
  completeScheduleRun(runId, { status: "ok" });
164
207
  notifySchedule({ id: job.id, name: job.name });
208
+ if (isOneShot) completeOneShot(job.id);
165
209
  }
166
210
  processed += 1;
167
211
  } catch (err) {
@@ -175,6 +219,7 @@ async function runScheduleOnce(
175
219
  syntax: job.syntax,
176
220
  expression: job.expression,
177
221
  isRruleSet,
222
+ isOneShot,
178
223
  },
179
224
  "Scheduled task execution failed",
180
225
  );
@@ -192,6 +237,7 @@ async function runScheduleOnce(
192
237
  });
193
238
  const runId = createScheduleRun(job.id, fallbackConversation.id);
194
239
  completeScheduleRun(runId, { status: "error", error: message });
240
+ if (isOneShot) failOneShot(job.id);
195
241
  }
196
242
  continue;
197
243
  }
@@ -200,7 +246,9 @@ async function runScheduleOnce(
200
246
  source: "schedule",
201
247
  scheduleJobId: job.id,
202
248
  origin: "schedule",
203
- systemHint: `Schedule: ${job.name}`,
249
+ systemHint: isOneShot
250
+ ? `Reminder: ${job.name}`
251
+ : `Schedule: ${job.name}`,
204
252
  });
205
253
  onScheduleThreadCreated?.({
206
254
  conversationId: conversation.id,
@@ -209,7 +257,7 @@ async function runScheduleOnce(
209
257
  });
210
258
  const runId = createScheduleRun(job.id, conversation.id);
211
259
  const isRruleSetMsg =
212
- job.syntax === "rrule" && hasSetConstructs(job.expression);
260
+ job.syntax === "rrule" && job.expression != null && hasSetConstructs(job.expression);
213
261
 
214
262
  try {
215
263
  log.info(
@@ -219,15 +267,17 @@ async function runScheduleOnce(
219
267
  syntax: job.syntax,
220
268
  expression: job.expression,
221
269
  isRruleSet: isRruleSetMsg,
270
+ isOneShot,
222
271
  conversationId: conversation.id,
223
272
  },
224
- "Executing schedule",
273
+ isOneShot ? "Executing one-shot schedule" : "Executing schedule",
225
274
  );
226
275
  await processMessage(conversation.id, job.message, {
227
276
  trustClass: "guardian",
228
277
  });
229
278
  completeScheduleRun(runId, { status: "ok" });
230
279
  notifySchedule({ id: job.id, name: job.name });
280
+ if (isOneShot) completeOneShot(job.id);
231
281
  processed += 1;
232
282
  } catch (err) {
233
283
  const message = err instanceof Error ? err.message : String(err);
@@ -239,10 +289,14 @@ async function runScheduleOnce(
239
289
  syntax: job.syntax,
240
290
  expression: job.expression,
241
291
  isRruleSet: isRruleSetMsg,
292
+ isOneShot,
242
293
  },
243
- "Schedule execution failed",
294
+ isOneShot
295
+ ? "One-shot schedule execution failed"
296
+ : "Schedule execution failed",
244
297
  );
245
298
  completeScheduleRun(runId, { status: "error", error: message });
299
+ if (isOneShot) failOneShot(job.id);
246
300
 
247
301
  try {
248
302
  invalidateAssistantInferredItemsForConversation(conversation.id);
@@ -255,61 +309,6 @@ async function runScheduleOnce(
255
309
  }
256
310
  }
257
311
 
258
- // ── One-shot reminders ──────────────────────────────────────────────
259
- const dueReminders = claimDueReminders(now);
260
- for (const reminder of dueReminders) {
261
- if (reminder.mode === "execute") {
262
- const conversation = bootstrapConversation({
263
- source: "reminder",
264
- origin: "reminder",
265
- systemHint: `Reminder: ${reminder.label}`,
266
- });
267
- setReminderConversationId(reminder.id, conversation.id);
268
- try {
269
- log.info(
270
- {
271
- reminderId: reminder.id,
272
- label: reminder.label,
273
- conversationId: conversation.id,
274
- },
275
- "Executing reminder",
276
- );
277
- await processMessage(conversation.id, reminder.message, {
278
- trustClass: "guardian",
279
- });
280
- completeReminder(reminder.id);
281
- } catch (err) {
282
- log.warn(
283
- { err, reminderId: reminder.id },
284
- "Reminder execution failed, reverting to pending",
285
- );
286
- failReminder(reminder.id);
287
- }
288
- } else {
289
- try {
290
- log.info(
291
- { reminderId: reminder.id, label: reminder.label },
292
- "Firing reminder notification",
293
- );
294
- notifyReminder({
295
- id: reminder.id,
296
- label: reminder.label,
297
- message: reminder.message,
298
- routingIntent: reminder.routingIntent,
299
- routingHints: reminder.routingHints,
300
- });
301
- completeReminder(reminder.id);
302
- } catch (err) {
303
- log.warn(
304
- { err, reminderId: reminder.id },
305
- "Reminder notification failed, reverting to pending",
306
- );
307
- failReminder(reminder.id);
308
- }
309
- }
310
- processed += 1;
311
- }
312
-
313
312
  // ── Watchers (event-driven polling) ────────────────────────────────
314
313
  if (watcherNotifier && watcherEscalator) {
315
314
  try {
@@ -59,7 +59,7 @@ export interface OAuth2TokenResult {
59
59
  }
60
60
 
61
61
  export interface OAuth2FlowCallbacks {
62
- /** Open a URL in the user's browser (e.g. via IPC `open_url`). */
62
+ /** Open a URL in the user's browser (e.g. via `open_url` message). */
63
63
  openUrl: (url: string) => void;
64
64
  }
65
65
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * SQLite-backed implementation of the SequenceStore interface.
3
3
  *
4
- * Follows the same patterns as schedule-store.ts and reminder-store.ts:
4
+ * Follows the same patterns as schedule-store.ts:
5
5
  * - Flat exported functions (no class)
6
6
  * - getDb() called inside each function
7
7
  * - Optimistic locking for claimDueEnrollments
@@ -215,7 +215,7 @@ export function listEnrollments(
215
215
  /**
216
216
  * Atomically claim enrollments that are due for processing.
217
217
  *
218
- * Uses the same optimistic locking pattern as claimDueReminders:
218
+ * Uses the same optimistic locking pattern as claimDueSchedules:
219
219
  * 1. Query candidates (status=active, nextStepAt <= now)
220
220
  * 2. For each, UPDATE with WHERE status='active' — only succeeds if not already claimed
221
221
  * 3. Check rawChanges() to confirm the lock was acquired
@@ -315,6 +315,16 @@ export function pauseEnrollment(id: string): void {
315
315
  .run();
316
316
  }
317
317
 
318
+ /** Resume a paused enrollment — re-activates it so the scheduler picks it up. */
319
+ export function resumeEnrollment(id: string): void {
320
+ const db = getDb();
321
+ const now = Date.now();
322
+ db.update(sequenceEnrollments)
323
+ .set({ status: "active", nextStepAt: now, updatedAt: now })
324
+ .where(eq(sequenceEnrollments.id, id))
325
+ .run();
326
+ }
327
+
318
328
  // ── Query Helpers ───────────────────────────────────────────────────
319
329
 
320
330
  export function findActiveEnrollmentsByEmail(
@@ -1,17 +1,23 @@
1
1
  /**
2
2
  * Shared frontmatter parsing for SKILL.md files.
3
3
  *
4
- * Frontmatter is a YAML-like block delimited by `---` at the top of a file.
4
+ * Frontmatter is a YAML block delimited by `---` at the top of a file.
5
5
  * This module provides a single implementation used by the skill catalog loader
6
6
  * and the CC command registry.
7
7
  */
8
8
 
9
+ import { parse as parseYaml } from "yaml";
10
+
11
+ import { getLogger } from "../util/logger.js";
12
+
13
+ const log = getLogger("frontmatter");
14
+
9
15
  /** Matches a `---` delimited frontmatter block at the start of a file. */
10
16
  export const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/;
11
17
 
12
18
  export interface FrontmatterParseResult {
13
19
  /** Key-value pairs extracted from the frontmatter block. */
14
- fields: Record<string, string>;
20
+ fields: Record<string, unknown>;
15
21
  /** The remaining file content after the frontmatter block. */
16
22
  body: string;
17
23
  }
@@ -20,8 +26,8 @@ export interface FrontmatterParseResult {
20
26
  * Parse frontmatter fields from file content.
21
27
  *
22
28
  * Extracts key-value pairs from the `---` delimited block at the top of the
23
- * file. Handles single- and double-quoted values, and unescapes common escape
24
- * sequences (`\n`, `\r`, `\\`, `\"`) in double-quoted values.
29
+ * file using a proper YAML parser. Handles nested objects, arrays, quoted
30
+ * strings, escape sequences, and all YAML features natively.
25
31
  *
26
32
  * Returns `null` if no frontmatter block is found.
27
33
  */
@@ -32,80 +38,16 @@ export function parseFrontmatterFields(
32
38
  if (!match) return null;
33
39
 
34
40
  const frontmatter = match[1];
35
- const fields: Record<string, string> = {};
41
+ const body = content.slice(match[0].length);
36
42
 
37
- const lines = frontmatter.split(/\r?\n/);
38
- let currentKey: string | undefined;
39
- let continuationLines: string[] = [];
40
-
41
- function flushContinuation() {
42
- if (currentKey !== undefined) {
43
- if (continuationLines.length > 0) {
44
- const joined = continuationLines.map((l) => l.trim()).join(" ");
45
- // Try parsing as-is first to avoid corrupting commas inside quoted strings.
46
- // Only apply trailing-comma cleanup if the raw text isn't valid JSON.
47
- try {
48
- JSON.parse(joined);
49
- fields[currentKey] = joined;
50
- } catch {
51
- fields[currentKey] = joined.replace(/,\s*([}\]])/g, "$1");
52
- }
53
- } else {
54
- fields[currentKey] = "";
55
- }
43
+ try {
44
+ const parsed = parseYaml(frontmatter);
45
+ if (parsed == null || typeof parsed !== "object") {
46
+ return { fields: {}, body };
56
47
  }
57
- currentKey = undefined;
58
- continuationLines = [];
48
+ return { fields: parsed as Record<string, unknown>, body };
49
+ } catch (err) {
50
+ log.warn({ err }, "Failed to parse YAML frontmatter");
51
+ return null;
59
52
  }
60
-
61
- for (const line of lines) {
62
- const trimmed = line.trim();
63
- if (!trimmed || trimmed.startsWith("#")) continue;
64
-
65
- // Continuation line: indented and no top-level key: pattern
66
- // (i.e. starts with whitespace and either has no colon or the colon
67
- // is inside braces/quotes — heuristic: line starts with space/tab)
68
- if (currentKey !== undefined && /^\s/.test(line)) {
69
- continuationLines.push(trimmed);
70
- continue;
71
- }
72
-
73
- // Flush any pending multiline value
74
- flushContinuation();
75
-
76
- const separatorIndex = trimmed.indexOf(":");
77
- if (separatorIndex === -1) continue;
78
-
79
- const key = trimmed.slice(0, separatorIndex).trim();
80
- let value = trimmed.slice(separatorIndex + 1).trim();
81
-
82
- if (!value) {
83
- // Value may continue on subsequent indented lines
84
- currentKey = key;
85
- continuationLines = [];
86
- continue;
87
- }
88
-
89
- const isDoubleQuoted = value.startsWith('"') && value.endsWith('"');
90
- const isSingleQuoted = value.startsWith("'") && value.endsWith("'");
91
- if (isDoubleQuoted || isSingleQuoted) {
92
- value = value.slice(1, -1);
93
- if (isDoubleQuoted) {
94
- // Unescape sequences produced by buildSkillMarkdown's esc().
95
- // Only for double-quoted values — single-quoted YAML treats backslashes literally.
96
- // Single-pass to avoid misinterpreting \\n (escaped backslash + n) as a newline.
97
- value = value.replace(/\\(["\\nr])/g, (_, ch) => {
98
- if (ch === "n") return "\n";
99
- if (ch === "r") return "\r";
100
- return ch; // handles \\ → \ and \" → "
101
- });
102
- }
103
- }
104
- fields[key] = value;
105
- }
106
-
107
- // Flush any trailing multiline value
108
- flushContinuation();
109
-
110
- return { fields, body: content.slice(match[0].length) };
111
53
  }
@@ -9,6 +9,8 @@ import {
9
9
  } from "node:fs";
10
10
  import { dirname, join } from "node:path";
11
11
 
12
+ import { stringify as stringifyYaml } from "yaml";
13
+
12
14
  import { getLogger } from "../util/logger.js";
13
15
  import { getWorkspaceSkillsDir } from "../util/platform.js";
14
16
 
@@ -67,7 +69,10 @@ export function buildSkillMarkdown(input: BuildSkillMarkdownInput): string {
67
69
  lines.push(`description: "${esc(input.description)}"`);
68
70
 
69
71
  // Build metadata object matching the format parseFrontmatter expects:
70
- // metadata: {"vellum":{"emoji":"...","user-invocable":false,...}}
72
+ // metadata:
73
+ // vellum:
74
+ // emoji: "..."
75
+ // user-invocable: false
71
76
  const vellum: Record<string, unknown> = {};
72
77
  if (input.emoji) {
73
78
  vellum.emoji = input.emoji;
@@ -84,7 +89,11 @@ export function buildSkillMarkdown(input: BuildSkillMarkdownInput): string {
84
89
 
85
90
  if (Object.keys(vellum).length > 0) {
86
91
  const metadata = { vellum };
87
- lines.push(`metadata: ${JSON.stringify(metadata)}`);
92
+ const yamlBlock = stringifyYaml(metadata, { indent: 2 });
93
+ lines.push("metadata:");
94
+ for (const yamlLine of yamlBlock.trimEnd().split("\n")) {
95
+ lines.push(` ${yamlLine}`);
96
+ }
88
97
  }
89
98
 
90
99
  lines.push("---");
@@ -188,7 +188,7 @@ export class SubagentManager {
188
188
  memoryPolicy,
189
189
  );
190
190
 
191
- // Mark session as having no direct IPC client — it routes through parent.
191
+ // Mark session as having no direct client — it routes through parent.
192
192
  // This ensures interactive prompts (host attachment reads) fail fast.
193
193
  session.updateClient(wrappedSendToClient, true);
194
194
 
@@ -380,7 +380,7 @@ export class SubagentManager {
380
380
  async sendMessage(
381
381
  subagentId: string,
382
382
  content: string,
383
- ): Promise<"sent" | "empty" | "not_found" | "terminal" | "queue_full"> {
383
+ ): Promise<"sent" | "empty" | "not_found" | "terminal"> {
384
384
  const trimmed = content?.trim();
385
385
  if (!trimmed) return "empty";
386
386
 
@@ -398,7 +398,9 @@ export class SubagentManager {
398
398
  onEvent,
399
399
  requestId,
400
400
  );
401
- if (result.rejected) return "queue_full";
401
+ if (result.rejected) {
402
+ return "sent"; // error event already delivered via onEvent
403
+ }
402
404
  if (!result.queued) {
403
405
  // Session is idle — send directly. Fire-and-forget so we don't block.
404
406
  const messageId = await managed.session.persistUserMessage(trimmed, []);
@@ -29,10 +29,9 @@ export function clearTaskRunRules(taskRunId: string): void {
29
29
  * default rules (50) so pre-approved tools aren't shadowed by default
30
30
  * `ask` rules (which would trigger prompting and auto-deny in
31
31
  * non-interactive task runs), but below user rules (100) so user deny
32
- * rules still take precedence. `allowHighRisk` is set because task runs
33
- * execute asynchronously without interactive confirmation the client
34
- * pre-approves tools via the preflight flow before execution begins,
35
- * so there is no interactive prompt during the run itself.
32
+ * rules still take precedence. `allowHighRisk` is intentionally omitted:
33
+ * high-risk tool invocations still flow through the normal risk-classification
34
+ * path rather than being blanket-approved.
36
35
  */
37
36
  export function buildTaskRules(
38
37
  taskRunId: string,
@@ -45,7 +44,6 @@ export function buildTaskRules(
45
44
  pattern: "**",
46
45
  scope: "everywhere",
47
46
  decision: "allow" as const,
48
- allowHighRisk: true,
49
47
  priority: 75,
50
48
  createdAt: Date.now(),
51
49
  }));
@@ -32,7 +32,6 @@ If Team Jarvis has approved your new tool:
32
32
  2. Use `git commit --no-verify` to bypass the hook
33
33
  3. Include the approval context in your PR description
34
34
 
35
-
36
35
  ## Questions?
37
36
 
38
37
  Contact Team Jarvis before shipping a new tool.
@@ -1,5 +1,5 @@
1
1
  import { existsSync, mkdirSync } from "node:fs";
2
- import { join } from "node:path";
2
+ import { isAbsolute, join, relative, resolve } from "node:path";
3
3
 
4
4
  import { getLogger } from "../../util/logger.js";
5
5
  import { getDataDir } from "../../util/platform.js";
@@ -30,10 +30,7 @@ function findSystemChrome(): string | null {
30
30
  );
31
31
  } else {
32
32
  // Linux
33
- candidates.push(
34
- "/usr/bin/google-chrome",
35
- "/usr/bin/google-chrome-stable",
36
- );
33
+ candidates.push("/usr/bin/google-chrome", "/usr/bin/google-chrome-stable");
37
34
  }
38
35
 
39
36
  for (const candidate of candidates) {
@@ -60,6 +57,13 @@ function getDownloadsDir(): string {
60
57
  return dir;
61
58
  }
62
59
 
60
+ export function sanitizeDownloadFilename(filename: string): string {
61
+ const leaf = filename.replaceAll("\\", "/").split("/").pop() ?? "";
62
+ const stripped = leaf.replaceAll("\0", "").trim();
63
+ const safe = stripped.length > 0 ? stripped : "download";
64
+ return safe === "." || safe === ".." ? "download" : safe;
65
+ }
66
+
63
67
  /** Wraps a promise with a timeout to prevent indefinite hangs. */
64
68
  export function withTimeout<T>(
65
69
  promise: Promise<T>,
@@ -284,10 +288,7 @@ class BrowserManager {
284
288
  const systemChrome = findSystemChrome();
285
289
 
286
290
  if (systemChrome) {
287
- log.info(
288
- { path: systemChrome },
289
- "Using system Chrome installation",
290
- );
291
+ log.info({ path: systemChrome }, "Using system Chrome installation");
291
292
  launch = (userDataDir, options) =>
292
293
  pw.chromium.launchPersistentContext(userDataDir, {
293
294
  ...options,
@@ -778,8 +779,13 @@ class BrowserManager {
778
779
  failure(): Promise<string | null>;
779
780
  };
780
781
  try {
781
- const filename = dl.suggestedFilename();
782
- const destPath = join(getDownloadsDir(), `${Date.now()}-${filename}`);
782
+ const filename = sanitizeDownloadFilename(dl.suggestedFilename());
783
+ const downloadsDir = getDownloadsDir();
784
+ const destPath = resolve(downloadsDir, `${Date.now()}-${filename}`);
785
+ const relPath = relative(resolve(downloadsDir), destPath);
786
+ if (relPath.startsWith("..") || isAbsolute(relPath)) {
787
+ throw new Error("Resolved download path escaped downloads directory");
788
+ }
783
789
  await withTimeout(dl.saveAs(destPath), 120_000, "Download save");
784
790
  const info: DownloadInfo = { path: destPath, filename };
785
791
 
@@ -1,4 +1,7 @@
1
- import type { FormField, FormSurfaceData } from "../../daemon/message-protocol.js";
1
+ import type {
2
+ FormField,
3
+ FormSurfaceData,
4
+ } from "../../daemon/message-protocol.js";
2
5
  import type { AuthChallenge, AuthField } from "./auth-detector.js";
3
6
 
4
7
  /**
@@ -26,7 +26,7 @@ const AUTO_APPROVE_TOOLS = new Set([
26
26
  "Bash(find *)",
27
27
  ]);
28
28
 
29
- // Tools that always require user approval via confirmation IPC
29
+ // Tools that always require user approval via confirmation prompt
30
30
  const APPROVAL_REQUIRED_TOOLS = new Set([
31
31
  "Bash",
32
32
  "Edit",