@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (430) hide show
  1. package/bun.lock +0 -20
  2. package/docs/workspace-tools.md +33 -42
  3. package/eslint-rules/cli-no-daemon-internals.js +0 -6
  4. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
  5. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
  6. package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
  7. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
  8. package/node_modules/@vellumai/service-contracts/package.json +0 -1
  9. package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
  10. package/openapi.yaml +0 -155
  11. package/package.json +1 -4
  12. package/scripts/test.sh +15 -36
  13. package/src/__tests__/actor-token-service.test.ts +14 -36
  14. package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
  15. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
  16. package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
  17. package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
  18. package/src/__tests__/annotate-risk-options.test.ts +0 -2
  19. package/src/__tests__/approval-cascade.test.ts +0 -2
  20. package/src/__tests__/assistant-attachments.test.ts +0 -42
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  22. package/src/__tests__/btw-routes.test.ts +0 -2
  23. package/src/__tests__/build-persisted-content.test.ts +0 -2
  24. package/src/__tests__/call-controller.test.ts +0 -19
  25. package/src/__tests__/channel-guardian.test.ts +58 -94
  26. package/src/__tests__/channel-reply-delivery.test.ts +0 -2
  27. package/src/__tests__/compaction-events.test.ts +0 -2
  28. package/src/__tests__/compaction.benchmark.test.ts +0 -2
  29. package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
  30. package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
  31. package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
  32. package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
  33. package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
  34. package/src/__tests__/config-loader-backfill.test.ts +10 -123
  35. package/src/__tests__/config-schema.test.ts +0 -1
  36. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
  37. package/src/__tests__/contacts-relay-reads.test.ts +15 -13
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
  39. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
  40. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
  41. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
  42. package/src/__tests__/conversation-agent-loop.test.ts +0 -134
  43. package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
  44. package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
  45. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
  46. package/src/__tests__/conversation-history-web-search.test.ts +0 -2
  47. package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
  48. package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
  49. package/src/__tests__/conversation-pairing.test.ts +0 -2
  50. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +0 -2
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
  53. package/src/__tests__/conversation-queue.test.ts +0 -91
  54. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
  56. package/src/__tests__/conversation-slash-queue.test.ts +0 -2
  57. package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
  58. package/src/__tests__/conversation-speed-override.test.ts +0 -2
  59. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
  60. package/src/__tests__/conversation-title-service.test.ts +0 -2
  61. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
  62. package/src/__tests__/conversation-usage.test.ts +0 -2
  63. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
  64. package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
  65. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
  66. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  67. package/src/__tests__/db-migration-rollback.test.ts +171 -205
  68. package/src/__tests__/db-test-helpers.ts +4 -5
  69. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
  70. package/src/__tests__/disk-pressure-guard.test.ts +0 -41
  71. package/src/__tests__/dm-persistence.test.ts +0 -2
  72. package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
  73. package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
  74. package/src/__tests__/exploration-drift-hook.test.ts +2 -3
  75. package/src/__tests__/filing-service.test.ts +0 -2
  76. package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
  77. package/src/__tests__/guardian-dispatch.test.ts +1 -95
  78. package/src/__tests__/guardian-outbound-http.test.ts +0 -13
  79. package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
  80. package/src/__tests__/heartbeat-service.test.ts +0 -2
  81. package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
  82. package/src/__tests__/host-app-control-routes.test.ts +30 -24
  83. package/src/__tests__/host-bash-routes.test.ts +41 -31
  84. package/src/__tests__/host-browser-routes.test.ts +32 -26
  85. package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
  86. package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
  87. package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
  88. package/src/__tests__/http-user-message-parity.test.ts +8 -290
  89. package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
  90. package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
  91. package/src/__tests__/invite-redemption-service.test.ts +0 -198
  92. package/src/__tests__/llm-context-normalization.test.ts +0 -105
  93. package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
  94. package/src/__tests__/llm-usage-store.test.ts +0 -25
  95. package/src/__tests__/mcp-health-check.test.ts +1 -2
  96. package/src/__tests__/media-stream-server-integration.test.ts +0 -127
  97. package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
  98. package/src/__tests__/messaging-send-tool.test.ts +0 -2
  99. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  100. package/src/__tests__/mtime-cache.test.ts +5 -146
  101. package/src/__tests__/native-web-search.test.ts +0 -2
  102. package/src/__tests__/non-member-access-request.test.ts +17 -189
  103. package/src/__tests__/notification-broadcaster.test.ts +0 -4
  104. package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
  105. package/src/__tests__/notification-deep-link.test.ts +0 -6
  106. package/src/__tests__/notification-guardian-path.test.ts +0 -19
  107. package/src/__tests__/openai-provider.test.ts +12 -22
  108. package/src/__tests__/openai-responses-provider.test.ts +2 -12
  109. package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
  110. package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
  111. package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
  112. package/src/__tests__/plugin-bootstrap.test.ts +73 -3
  113. package/src/__tests__/plugin-route-contribution.test.ts +17 -4
  114. package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
  115. package/src/__tests__/plugin-types.test.ts +2 -0
  116. package/src/__tests__/process-message-background-slack.test.ts +0 -2
  117. package/src/__tests__/process-message-display-content.test.ts +0 -2
  118. package/src/__tests__/provider-error-scenarios.test.ts +4 -5
  119. package/src/__tests__/provider-usage-tracking.test.ts +0 -39
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
  121. package/src/__tests__/registry.test.ts +1 -4
  122. package/src/__tests__/relay-server.test.ts +25 -694
  123. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
  124. package/src/__tests__/secret-ingress-http.test.ts +0 -14
  125. package/src/__tests__/send-endpoint-busy.test.ts +8 -30
  126. package/src/__tests__/skills.test.ts +0 -44
  127. package/src/__tests__/slack-inbound-verification.test.ts +2 -47
  128. package/src/__tests__/stt-hints.test.ts +13 -44
  129. package/src/__tests__/subagent-detail.test.ts +0 -27
  130. package/src/__tests__/subagent-disposal.test.ts +0 -65
  131. package/src/__tests__/subagent-notify-parent.test.ts +0 -2
  132. package/src/__tests__/subagent-role-registry.test.ts +2 -7
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
  134. package/src/__tests__/subagent-tools.test.ts +0 -2
  135. package/src/__tests__/suggestion-routes.test.ts +0 -2
  136. package/src/__tests__/title-generate-hook.test.ts +0 -2
  137. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
  138. package/src/__tests__/tool-executor.test.ts +11 -16
  139. package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
  140. package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
  141. package/src/__tests__/tool-start-timestamp.test.ts +0 -2
  142. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
  143. package/src/__tests__/twilio-routes.test.ts +0 -96
  144. package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
  145. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  146. package/src/__tests__/voice-invite-redemption.test.ts +0 -33
  147. package/src/__tests__/web-search-backend-failure.test.ts +0 -2
  148. package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
  149. package/src/__tests__/workspace-tool-loader.test.ts +2 -195
  150. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  151. package/src/agent/loop.ts +0 -56
  152. package/src/api/index.ts +1 -19
  153. package/src/api/responses/llm-request-log-entry.ts +0 -29
  154. package/src/api/responses/subagent-detail.ts +0 -17
  155. package/src/api/surfaces.ts +3 -39
  156. package/src/approvals/guardian-request-resolvers.ts +11 -1
  157. package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
  158. package/src/calls/call-domain.ts +3 -3
  159. package/src/calls/guardian-dispatch.ts +8 -10
  160. package/src/calls/inbound-trust-reader.ts +1 -17
  161. package/src/calls/media-stream-server.ts +0 -21
  162. package/src/calls/relay-server.ts +50 -167
  163. package/src/calls/relay-setup-router.ts +7 -37
  164. package/src/calls/relay-verification.ts +4 -4
  165. package/src/calls/stt-hints.ts +12 -9
  166. package/src/calls/twilio-routes.ts +4 -14
  167. package/src/channels/types.ts +20 -10
  168. package/src/cli/commands/__tests__/cache.test.ts +1 -8
  169. package/src/cli/commands/cache.ts +181 -194
  170. package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
  171. package/src/cli/commands/db/status.ts +1 -37
  172. package/src/cli/commands/mcp.ts +218 -252
  173. package/src/cli/commands/memory/index.ts +0 -2
  174. package/src/cli/commands/plugins.ts +3 -75
  175. package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
  176. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
  177. package/src/cli/lib/list-installed-plugins.ts +1 -179
  178. package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
  179. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
  180. package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
  181. package/src/config/bundled-skills/subagent/SKILL.md +1 -1
  182. package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
  183. package/src/config/feature-flag-registry.json +13 -5
  184. package/src/config/loader.ts +5 -38
  185. package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
  186. package/src/config/schemas/memory-lifecycle.ts +0 -12
  187. package/src/config/schemas/memory-v3.ts +0 -7
  188. package/src/config/schemas/memory.ts +0 -4
  189. package/src/config/schemas/timeouts.ts +0 -8
  190. package/src/config/seed-inference-profiles.ts +11 -21
  191. package/src/config/skills.ts +5 -27
  192. package/src/config/sync-gated-profiles.ts +13 -12
  193. package/src/contacts/contacts-write.ts +0 -3
  194. package/src/daemon/assistant-attachments.ts +4 -27
  195. package/src/daemon/conversation-agent-loop.ts +0 -28
  196. package/src/daemon/conversation-process.ts +16 -35
  197. package/src/daemon/conversation-surfaces.ts +38 -111
  198. package/src/daemon/conversation-tool-setup.ts +16 -50
  199. package/src/daemon/conversation.ts +1 -13
  200. package/src/daemon/disk-pressure-guard.ts +2 -12
  201. package/src/daemon/event-loop-watchdog.ts +1 -28
  202. package/src/daemon/external-plugins-bootstrap.ts +34 -4
  203. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
  204. package/src/daemon/handlers/config-a2a.ts +14 -6
  205. package/src/daemon/handlers/config-channels.ts +22 -78
  206. package/src/daemon/handlers/conversations.ts +0 -77
  207. package/src/daemon/lifecycle.ts +0 -4
  208. package/src/daemon/mcp-reload-service.ts +0 -10
  209. package/src/daemon/memory-v2-startup.test.ts +0 -72
  210. package/src/daemon/memory-v2-startup.ts +19 -87
  211. package/src/daemon/message-types/conversations.ts +0 -2
  212. package/src/daemon/message-types/surfaces.ts +12 -12
  213. package/src/daemon/server.ts +4 -0
  214. package/src/daemon/shutdown-handlers.ts +0 -20
  215. package/src/daemon/tool-setup-types.ts +0 -9
  216. package/src/daemon/workspace-tools-watcher.ts +328 -0
  217. package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
  218. package/src/ipc/assistant-server.ts +2 -2
  219. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
  220. package/src/mcp/client.ts +1 -15
  221. package/src/mcp/mcp-auth-orchestrator.ts +1 -6
  222. package/src/mcp/mcp-oauth-provider.ts +8 -19
  223. package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
  224. package/src/memory/conversation-crud.ts +0 -38
  225. package/src/memory/db-connection.ts +3 -22
  226. package/src/memory/db-init.ts +502 -36
  227. package/src/memory/db-singleton.ts +4 -6
  228. package/src/memory/jobs-worker.ts +0 -58
  229. package/src/memory/llm-request-log-store.ts +1 -26
  230. package/src/memory/llm-usage-store.ts +20 -48
  231. package/src/memory/memory-retrospective-job.ts +8 -9
  232. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
  233. package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
  234. package/src/memory/migrations/registry.ts +573 -0
  235. package/src/memory/migrations/run-migrations.ts +6 -90
  236. package/src/memory/migrations/validate-migration-state.ts +66 -101
  237. package/src/memory/schema/conversations.ts +0 -9
  238. package/src/memory/schema/infrastructure.ts +0 -20
  239. package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
  240. package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
  241. package/src/memory/v2/cli-command-store.ts +38 -75
  242. package/src/memory/v2/prompts/consolidation.ts +82 -13
  243. package/src/memory/v2/prompts/router.ts +93 -21
  244. package/src/memory/v2/skill-store.ts +31 -68
  245. package/src/notifications/__tests__/broadcaster.test.ts +8 -16
  246. package/src/notifications/__tests__/decision-engine.test.ts +9 -78
  247. package/src/notifications/broadcaster.ts +1 -8
  248. package/src/notifications/decision-engine.ts +7 -15
  249. package/src/notifications/destination-resolver.ts +24 -68
  250. package/src/notifications/emit-signal.ts +14 -39
  251. package/src/permissions/question-prompter.test.ts +1 -1
  252. package/src/permissions/question-prompter.ts +4 -7
  253. package/src/plugin-api/index.ts +6 -6
  254. package/src/plugin-api/types.ts +5 -3
  255. package/src/plugin-api/vision-support.test.ts +4 -28
  256. package/src/plugin-api/vision-support.ts +31 -66
  257. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
  258. package/src/plugins/defaults/advisor/consult.ts +6 -110
  259. package/src/plugins/defaults/advisor/steering.ts +2 -14
  260. package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
  261. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
  262. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
  263. package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
  264. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
  265. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
  266. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
  267. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
  268. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
  269. package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
  270. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
  271. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
  272. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
  273. package/src/plugins/mtime-cache.ts +291 -76
  274. package/src/plugins/pipeline.ts +13 -111
  275. package/src/plugins/types.ts +2 -0
  276. package/src/providers/anthropic/client.ts +0 -5
  277. package/src/providers/call-site-routing.ts +0 -4
  278. package/src/providers/model-catalog.ts +0 -16
  279. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  280. package/src/providers/openai/chat-completions-provider.ts +83 -37
  281. package/src/providers/openai/responses-provider.ts +46 -50
  282. package/src/providers/openrouter/client.ts +0 -5
  283. package/src/providers/provider-send-message.ts +0 -4
  284. package/src/providers/ratelimit.ts +0 -4
  285. package/src/providers/retry.ts +0 -4
  286. package/src/providers/types.ts +0 -9
  287. package/src/providers/usage-tracking.ts +0 -4
  288. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
  289. package/src/runtime/access-request-helper.ts +39 -19
  290. package/src/runtime/actor-trust-resolver.ts +2 -2
  291. package/src/runtime/assistant-event-hub.ts +1 -1
  292. package/src/runtime/assistant-stream-state.ts +2 -9
  293. package/src/runtime/auth/require-bound-guardian.ts +11 -21
  294. package/src/runtime/channel-verification-service.ts +31 -56
  295. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
  296. package/src/runtime/guardian-vellum-migration.ts +7 -66
  297. package/src/runtime/invite-redemption-service.ts +187 -198
  298. package/src/runtime/local-actor-identity.ts +11 -76
  299. package/src/runtime/pending-interactions.ts +1 -11
  300. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
  301. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  302. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
  303. package/src/runtime/routes/browser-routes.ts +1 -1
  304. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
  305. package/src/runtime/routes/channel-verification-routes.ts +3 -3
  306. package/src/runtime/routes/contact-routes.ts +32 -8
  307. package/src/runtime/routes/conversation-cli-routes.ts +5 -4
  308. package/src/runtime/routes/conversation-list-routes.ts +7 -4
  309. package/src/runtime/routes/conversation-query-routes.ts +0 -72
  310. package/src/runtime/routes/conversation-routes.ts +85 -84
  311. package/src/runtime/routes/events-routes.ts +2 -2
  312. package/src/runtime/routes/global-search-routes.ts +1 -3
  313. package/src/runtime/routes/guardian-action-routes.ts +5 -4
  314. package/src/runtime/routes/host-app-control-routes.ts +4 -5
  315. package/src/runtime/routes/host-bash-routes.ts +4 -5
  316. package/src/runtime/routes/host-browser-routes.ts +11 -9
  317. package/src/runtime/routes/host-cu-routes.ts +4 -5
  318. package/src/runtime/routes/host-file-routes.ts +4 -5
  319. package/src/runtime/routes/host-transfer-routes.ts +6 -6
  320. package/src/runtime/routes/http-adapter.ts +1 -1
  321. package/src/runtime/routes/identity-routes.ts +2 -3
  322. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  323. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
  324. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
  325. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
  326. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
  327. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
  328. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
  329. package/src/runtime/routes/index.ts +0 -2
  330. package/src/runtime/routes/llm-context-normalization.ts +0 -83
  331. package/src/runtime/routes/mcp-auth-routes.ts +19 -171
  332. package/src/runtime/routes/migration-rollback-routes.ts +3 -4
  333. package/src/runtime/routes/migration-routes.ts +1 -4
  334. package/src/runtime/routes/subagents-routes.ts +0 -5
  335. package/src/runtime/routes/surface-action-routes.ts +56 -42
  336. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
  337. package/src/runtime/services/conversation-serializer.ts +9 -7
  338. package/src/runtime/tool-grant-request-helper.ts +3 -3
  339. package/src/runtime/trust-verdict-consumer.ts +9 -85
  340. package/src/runtime/verification-outbound-actions.ts +18 -18
  341. package/src/signals/user-message.ts +0 -16
  342. package/src/subagent/manager.ts +0 -9
  343. package/src/subagent/types.ts +3 -3
  344. package/src/telemetry/types.ts +1 -34
  345. package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
  346. package/src/telemetry/usage-telemetry-reporter.ts +3 -87
  347. package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
  348. package/src/tools/ask-question/ask-question-tool.ts +0 -13
  349. package/src/tools/executor.ts +4 -4
  350. package/src/tools/registry.ts +0 -18
  351. package/src/tools/shared/filesystem/path-policy.ts +5 -12
  352. package/src/tools/tool-approval-handler.ts +1 -1
  353. package/src/tools/tool-defaults.ts +2 -9
  354. package/src/tools/tool-manifest.ts +0 -3
  355. package/src/tools/types.ts +2 -17
  356. package/src/tools/workspace-tools/loader.ts +244 -348
  357. package/src/util/errors.ts +1 -26
  358. package/src/util/platform.ts +0 -5
  359. package/src/workflows/library.test.ts +0 -140
  360. package/src/workflows/library.ts +28 -82
  361. package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
  362. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
  363. package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
  364. package/src/workspace/migrations/registry.ts +0 -2
  365. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
  366. package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
  367. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
  368. package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
  369. package/src/__tests__/code-search-tool.test.ts +0 -585
  370. package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
  371. package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
  372. package/src/__tests__/plugin-pipeline.test.ts +0 -96
  373. package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
  374. package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
  375. package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
  376. package/src/agent/loop-exclusive-tool.test.ts +0 -150
  377. package/src/api/constants/sse-replay.ts +0 -41
  378. package/src/api/events/conversation-notice.ts +0 -26
  379. package/src/approvals/guardian-channel-delivery.ts +0 -30
  380. package/src/approvals/guardian-expiry-notifier.ts +0 -148
  381. package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
  382. package/src/cli/commands/memory/worker.ts +0 -175
  383. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
  384. package/src/config/prune-seeded-callsite-defaults.ts +0 -110
  385. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
  386. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
  387. package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
  388. package/src/contacts/guardian-delivery-reader.ts +0 -223
  389. package/src/contacts/member-write-relay.ts +0 -189
  390. package/src/daemon/conversation-notices.ts +0 -60
  391. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
  392. package/src/hooks/hook-loader.ts +0 -341
  393. package/src/mcp/mcp-header-store.ts +0 -134
  394. package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
  395. package/src/memory/__tests__/prompt-override.test.ts +0 -192
  396. package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
  397. package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
  398. package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
  399. package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
  400. package/src/memory/prompt-override.ts +0 -129
  401. package/src/memory/steps.ts +0 -573
  402. package/src/memory/watchdog-events-store.ts +0 -87
  403. package/src/memory/worker-control.ts +0 -118
  404. package/src/memory/worker-process.ts +0 -72
  405. package/src/notifications/__tests__/connected-channels.test.ts +0 -114
  406. package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
  407. package/src/onboarding/checkin-event.test.ts +0 -222
  408. package/src/onboarding/checkin-event.ts +0 -321
  409. package/src/onboarding/schedule-checkin.ts +0 -190
  410. package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
  411. package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
  412. package/src/plugins/defaults/advisor/context-pack.ts +0 -288
  413. package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
  414. package/src/plugins/surface-import.ts +0 -121
  415. package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
  416. package/src/providers/openai/api-error-normalization.ts +0 -270
  417. package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
  418. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
  419. package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
  420. package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
  421. package/src/runtime/anchored-guardian.test.ts +0 -156
  422. package/src/runtime/anchored-guardian.ts +0 -135
  423. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
  424. package/src/runtime/local-principal-trust.ts +0 -52
  425. package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
  426. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
  427. package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
  428. package/src/tools/filesystem/search.ts +0 -543
  429. package/src/util/telemetry-db-path.ts +0 -24
  430. package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
@@ -1,543 +0,0 @@
1
- import { readdirSync, readFileSync, statSync } from "node:fs";
2
- import { basename, join, relative } from "node:path";
3
-
4
- import { minimatch } from "minimatch";
5
- import { RE2JS } from "re2js";
6
-
7
- import { RiskLevel } from "../../permissions/types.js";
8
- import { registerTool } from "../registry.js";
9
- import {
10
- isDeniedBasename,
11
- sandboxPolicy,
12
- } from "../shared/filesystem/path-policy.js";
13
- import type {
14
- ToolContext,
15
- ToolDefinition,
16
- ToolExecutionResult,
17
- } from "../types.js";
18
-
19
- // Directory names that are never worth searching and would otherwise dominate
20
- // the file budget (dependencies, VCS metadata).
21
- const IGNORED_DIRS = new Set(["node_modules", ".git"]);
22
-
23
- // Defensive caps so a search over a huge tree cannot read the whole disk into
24
- // memory. These bound the walk regardless of `max_results`.
25
- const MAX_FILES_SCANNED = 20_000;
26
- const MAX_TOTAL_BYTES = 256 * 1024 * 1024; // 256 MiB
27
- const MAX_FILE_BYTES = 8 * 1024 * 1024; // skip files larger than 8 MiB
28
-
29
- // Hard cap on directory entries visited during the walk, independent of
30
- // wall-clock time. `MAX_FILES_SCANNED`/`MAX_TOTAL_BYTES` only count files that
31
- // are actually READ, so a pathological tree full of oversized, unreadable,
32
- // permission-denied, or glob-filtered files (which never increment those
33
- // counters) could otherwise traverse unbounded. This bounds the readdir/stat
34
- // work even when every individual operation is fast.
35
- const MAX_ENTRIES_TRAVERSED = 200_000;
36
-
37
- // Display-only cap on emitted output lines (ripgrep-style long-line bound). The
38
- // pattern is matched against the FULL line, so a token anywhere on a long line
39
- // is found; this cap only bounds the PRINTED line text (matched and context
40
- // lines) so a single pathological line (e.g. a minified bundle on one line)
41
- // can't emit a multi-megabyte output line. Normal code/log lines are well under
42
- // the cap and print verbatim.
43
- const MAX_DISPLAY_LINE_LENGTH = 2000;
44
-
45
- // Output-byte budget: when `context_lines` is large and many nearby lines
46
- // match, the surrounding block is appended for every match, so a single large
47
- // file with many matches could allocate hundreds of MB before the post-tool
48
- // truncation hook runs. Stop accumulating once this budget is exceeded and
49
- // report the result as truncated.
50
- const MAX_OUTPUT_BYTES = 4 * 1024 * 1024; // 4 MiB
51
-
52
- // Wall-clock deadline for the whole search. The synchronous scan never yields,
53
- // so the promise-based tool timeout / abort signal can't fire mid-scan. Checking
54
- // this deadline (and the abort signal) once per line bounds how long a search
55
- // over a very large tree can block the event loop and lets an external abort
56
- // stop the walk promptly.
57
- const MAX_SEARCH_MS = 10_000; // 10 s
58
-
59
- const DEFAULT_MAX_RESULTS = 200;
60
- const DEFAULT_CONTEXT_LINES = 0;
61
- // Clamp `context_lines` so a single match cannot request unbounded surrounding
62
- // context (which would blow past the output budget on its own).
63
- const MAX_CONTEXT_LINES = 20;
64
-
65
- /** Heuristic binary-file detection: a NUL byte in the leading bytes. */
66
- function looksBinary(buf: Buffer): boolean {
67
- const len = Math.min(buf.length, 8000);
68
- for (let i = 0; i < len; i++) {
69
- if (buf[i] === 0) return true;
70
- }
71
- return false;
72
- }
73
-
74
- export const codeSearchTool = {
75
- name: "code_search",
76
- description:
77
- "Search file contents for a regular-expression pattern across a directory tree on your own machine, returning matching `path:line: text` lines. Read-only — never modifies files. Skips node_modules, .git, and binary files. Use this to grep across files without a shell.",
78
- category: "filesystem",
79
- executionTarget: "sandbox",
80
- defaultRiskLevel: RiskLevel.Low,
81
-
82
- input_schema: {
83
- type: "object",
84
- properties: {
85
- pattern: {
86
- type: "string",
87
- description:
88
- "Regular-expression pattern to search for in file contents",
89
- },
90
- path: {
91
- type: "string",
92
- description:
93
- "Directory to search under (defaults to the working directory)",
94
- },
95
- glob: {
96
- type: "string",
97
- description:
98
- "Only search files whose path (relative to the search root) matches this glob, e.g. '*.ts' or 'src/**'",
99
- },
100
- case_insensitive: {
101
- type: "boolean",
102
- description: "Match the pattern case-insensitively",
103
- },
104
- context_lines: {
105
- type: "number",
106
- description:
107
- "Number of lines of context to include before and after each match (default 0)",
108
- },
109
- max_results: {
110
- type: "number",
111
- description: "Maximum number of matches to return (default 200)",
112
- },
113
- activity: {
114
- type: "string",
115
- description:
116
- "Brief non-technical explanation of what you are doing and why, shown as a status update.",
117
- },
118
- },
119
- required: ["pattern", "activity"],
120
- },
121
-
122
- async execute(
123
- input: Record<string, unknown>,
124
- context: ToolContext,
125
- ): Promise<ToolExecutionResult> {
126
- const pattern = input.pattern;
127
- if (!pattern || typeof pattern !== "string") {
128
- return {
129
- content: "Error: pattern is required and must be a non-empty string",
130
- isError: true,
131
- };
132
- }
133
-
134
- const rawPath =
135
- typeof input.path === "string" && input.path.length > 0
136
- ? input.path
137
- : context.workingDir;
138
-
139
- const pathCheck = sandboxPolicy(rawPath, context.workingDir);
140
- if (!pathCheck.ok) {
141
- return {
142
- content: `Error: ${pathCheck.error}. To search outside the workspace, use the host_bash tool instead.`,
143
- isError: true,
144
- };
145
- }
146
- const root = pathCheck.resolved;
147
-
148
- const caseInsensitive = input.case_insensitive === true;
149
- // Match with the linear-time RE2 engine (via re2js) instead of V8's
150
- // backtracking RegExp. RE2 guarantees linear-time matching, so a
151
- // user/subagent-supplied pattern cannot trigger catastrophic backtracking
152
- // and block the synchronous scan. The trade-off is that RE2 rejects
153
- // backreferences and lookarounds; compile() throws on those, surfaced as a
154
- // clean error below.
155
- let regex: RE2JS;
156
- try {
157
- regex = RE2JS.compile(
158
- pattern,
159
- caseInsensitive ? RE2JS.CASE_INSENSITIVE : 0,
160
- );
161
- } catch (err) {
162
- return {
163
- content: `Error: invalid or unsupported pattern "${pattern}": ${
164
- err instanceof Error ? err.message : String(err)
165
- }. The RE2 engine does not support backreferences or lookarounds.`,
166
- isError: true,
167
- };
168
- }
169
-
170
- const glob =
171
- typeof input.glob === "string" && input.glob.length > 0
172
- ? input.glob
173
- : undefined;
174
-
175
- const contextLines =
176
- typeof input.context_lines === "number" && input.context_lines > 0
177
- ? Math.min(Math.floor(input.context_lines), MAX_CONTEXT_LINES)
178
- : DEFAULT_CONTEXT_LINES;
179
-
180
- const maxResults =
181
- typeof input.max_results === "number" && input.max_results > 0
182
- ? Math.floor(input.max_results)
183
- : DEFAULT_MAX_RESULTS;
184
-
185
- // Validate the search root before walking so a missing/unreadable/typo'd
186
- // path surfaces a hard error instead of being swallowed like an unreadable
187
- // child directory and returning a false "No matches found". Mirrors the
188
- // NOT_FOUND / NOT_A_DIRECTORY reporting in file_list.
189
- let rootStat: import("node:fs").Stats;
190
- try {
191
- rootStat = statSync(root);
192
- } catch {
193
- return {
194
- content: `Error: path not found: ${rawPath}`,
195
- isError: true,
196
- };
197
- }
198
-
199
- // Start the wall-clock deadline before walking so a pathological regex
200
- // (or an external abort) can stop the synchronous scan mid-flight instead
201
- // of blocking the event loop until the whole tree is exhausted.
202
- const searchStart = Date.now();
203
-
204
- const lines: string[] = [];
205
- let matchCount = 0;
206
- let truncated = false;
207
- // Set when the output-byte budget (not the max-results cap) stopped the
208
- // accumulation, so the truncation note can explain why.
209
- let outputBudgetHit = false;
210
- // Set when the wall-clock deadline (or an abort signal) stopped the scan,
211
- // so the result can report that the search timed out and is incomplete —
212
- // distinct from the scan-cap and output-budget truncation notes.
213
- let timedOut = false;
214
- // Set when the search stopped because it reached the `max_results` cap (as
215
- // opposed to a scan/traversal cap). Only this cause is helped by raising
216
- // `max_results`, so the matched-branch truncation note keys off this flag to
217
- // avoid suggesting a larger `max_results` when a scan cap stopped the walk.
218
- let maxResultsHit = false;
219
- // Set when a file was skipped mid-walk because it exceeds MAX_FILE_BYTES.
220
- // Unlike the truncation flags this does NOT halt the walk — other files may
221
- // still match — but it does mark the overall result incomplete, since the
222
- // skipped file could have contained the pattern. Kept separate from
223
- // `truncated` so the zero-match invariant ("truncated => scan cap/timeout")
224
- // stays intact.
225
- let skippedLargeFile = false;
226
- let filesScanned = 0;
227
- let totalBytes = 0;
228
- // Number of directory entries visited during the walk (files + subdirs),
229
- // bounded by MAX_ENTRIES_TRAVERSED so a pathological tree can't run the
230
- // synchronous readdir/stat work unbounded even when no file is ever read.
231
- let entriesTraversed = 0;
232
- // Set when an EXPLICIT file root (not a child discovered mid-walk) can't be
233
- // read — e.g. EACCES/EPERM. A child file's read failure is optional and
234
- // silently skipped, but an unreadable explicit root means nothing was
235
- // searched, so we surface it as an error instead of a false "No matches".
236
- let rootReadError: string | null = null;
237
- // Running size of the accumulated output (lines joined by "\n") so we can
238
- // stop before allocating an unbounded result. Each pushed line contributes
239
- // its UTF-8 byte length plus one byte for the joining newline.
240
- let outputBytes = 0;
241
-
242
- // Bound a single emitted line's length for display only. Matching always
243
- // runs against the full line; this just keeps the PRINTED text readable and
244
- // prevents one pathological line (minified bundle, huge JSON/log line) from
245
- // emitting a multi-megabyte output line. Normal lines pass through verbatim.
246
- const truncateForDisplay = (text: string): string =>
247
- text.length > MAX_DISPLAY_LINE_LENGTH
248
- ? `${text.slice(0, MAX_DISPLAY_LINE_LENGTH)} …[line truncated]`
249
- : text;
250
-
251
- // Append an output line, tracking its byte cost. Returns false once the
252
- // output-byte budget is exhausted so callers can stop accumulating.
253
- const pushLine = (line: string): boolean => {
254
- outputBytes += Buffer.byteLength(line, "utf8") + 1;
255
- lines.push(line);
256
- if (outputBytes > MAX_OUTPUT_BYTES) {
257
- truncated = true;
258
- outputBudgetHit = true;
259
- return false;
260
- }
261
- return true;
262
- };
263
-
264
- // Scan a single regular file for matches. Applies the denied-basename guard
265
- // and per-file size caps. Returns nothing; mutates the shared accumulators.
266
- const scanFile = (full: string, isExplicitRoot = false): void => {
267
- if (truncated) return;
268
-
269
- // Honor the wall-clock deadline / abort signal before doing any stat/size
270
- // work, not just inside the per-line loop. A tree full of oversized or
271
- // unreadable files (which never reach the per-line loop) could otherwise
272
- // run far past the advertised deadline.
273
- if (Date.now() - searchStart > MAX_SEARCH_MS || context.signal?.aborted) {
274
- truncated = true;
275
- timedOut = true;
276
- return;
277
- }
278
-
279
- // Never read files the assistant is forbidden from touching, even if a
280
- // broad pattern would otherwise match them. Reuses the same denylist as
281
- // file_read/file_write so the policies stay in sync.
282
- if (isDeniedBasename(full)) return;
283
-
284
- const rel = relative(root, full);
285
- // matchBase lets a slash-free pattern like "*.ts" match files at any
286
- // depth (against the basename); patterns with slashes match the full
287
- // relative path. dot so dotfiles aren't silently excluded. When the root
288
- // is a single file, `rel` is empty, so match against the basename.
289
- const globTarget = rel.length > 0 ? rel : basename(full);
290
- if (
291
- glob &&
292
- !minimatch(globTarget, glob, { matchBase: true, dot: true })
293
- ) {
294
- return;
295
- }
296
-
297
- if (filesScanned >= MAX_FILES_SCANNED) {
298
- truncated = true;
299
- return;
300
- }
301
-
302
- let size: number;
303
- try {
304
- size = statSync(full).size;
305
- } catch {
306
- return;
307
- }
308
- if (size > MAX_FILE_BYTES) {
309
- // Skip just this file (others may still match), but record that the
310
- // search is incomplete so the result doesn't read as a definitive miss.
311
- skippedLargeFile = true;
312
- return;
313
- }
314
- if (totalBytes + size > MAX_TOTAL_BYTES) {
315
- truncated = true;
316
- return;
317
- }
318
-
319
- let buf: Buffer;
320
- try {
321
- buf = readFileSync(full);
322
- } catch (err) {
323
- // A child file discovered mid-walk is optional — skip it silently. But
324
- // an explicit file root that can't be read was never searched, so record
325
- // the failure for the caller to surface as an error.
326
- if (isExplicitRoot) {
327
- const code = (err as NodeJS.ErrnoException)?.code;
328
- rootReadError = `Error: failed to read file (${code ?? "unreadable"}): ${rawPath}`;
329
- }
330
- return;
331
- }
332
- filesScanned++;
333
- totalBytes += buf.length;
334
- if (looksBinary(buf)) return;
335
-
336
- // Display path: when searching a single file at the root, `rel` is empty;
337
- // fall back to the basename so output stays readable.
338
- const display = rel.length > 0 ? rel : basename(full);
339
- const fileLines = buf.toString("utf8").split("\n");
340
- for (let i = 0; i < fileLines.length; i++) {
341
- // Bound the total event-loop block: check the wall-clock deadline and
342
- // the abort signal before every regex test (the per-line Date.now() and
343
- // .aborted reads are negligible next to a catastrophic-backtracking
344
- // test). When either trips, mark the search timed out / aborted and
345
- // stop the whole walk so partial results are still reported.
346
- if (
347
- Date.now() - searchStart > MAX_SEARCH_MS ||
348
- context.signal?.aborted
349
- ) {
350
- truncated = true;
351
- timedOut = true;
352
- return;
353
- }
354
- // Match against the FULL line so a token that appears past any display
355
- // cap (e.g. after column 2000 on a long log/JSON/minified line) is still
356
- // found. RE2's linear-time matching makes this safe — there is no
357
- // backtracking blowup to bound, so no need to slice before matching.
358
- const line = fileLines[i];
359
- // Unanchored partial match anywhere in the line — the RE2 equivalent of
360
- // RegExp.prototype.test(). The compiled pattern is stateless per call.
361
- if (!regex.test(line)) continue;
362
- if (matchCount >= maxResults) {
363
- truncated = true;
364
- maxResultsHit = true;
365
- return;
366
- }
367
- // Count the match before emitting its lines: a single match whose output
368
- // alone exceeds the output-byte budget would otherwise leave matchCount
369
- // at 0, making the zero-match branch report a false "no matches / scan
370
- // cap" instead of a truncated result that acknowledges the match.
371
- matchCount++;
372
- const lineNo = i + 1;
373
- if (contextLines > 0) {
374
- const start = Math.max(0, i - contextLines);
375
- const end = Math.min(fileLines.length - 1, i + contextLines);
376
- for (let j = start; j <= end; j++) {
377
- const sep = j === i ? ":" : "-";
378
- if (
379
- !pushLine(
380
- `${display}:${j + 1}${sep} ${truncateForDisplay(fileLines[j])}`,
381
- )
382
- )
383
- return;
384
- }
385
- if (!pushLine("--")) return;
386
- } else {
387
- if (
388
- !pushLine(
389
- `${display}:${lineNo}: ${truncateForDisplay(fileLines[i])}`,
390
- )
391
- )
392
- return;
393
- }
394
- }
395
- };
396
-
397
- const walk = (dir: string, isExplicitRoot = false): void => {
398
- if (truncated) return;
399
- // Bound the traversal itself, not just file reads: a deep/wide tree of
400
- // directories (or many entries that never get read) could otherwise run
401
- // the synchronous readdir/stat work far past the advertised deadline.
402
- if (Date.now() - searchStart > MAX_SEARCH_MS || context.signal?.aborted) {
403
- truncated = true;
404
- timedOut = true;
405
- return;
406
- }
407
- let entries: import("node:fs").Dirent[];
408
- try {
409
- entries = readdirSync(dir, { withFileTypes: true });
410
- } catch (err) {
411
- // A child directory discovered mid-walk is optional — skip it silently.
412
- // But an explicit directory root that can't be read (e.g. EACCES/EPERM)
413
- // was never searched, so record the failure for the caller to surface
414
- // as an error instead of a false "No matches found".
415
- if (isExplicitRoot) {
416
- const code = (err as NodeJS.ErrnoException)?.code;
417
- rootReadError = `Error: failed to read directory (${code ?? "unreadable"}): ${rawPath}`;
418
- }
419
- return;
420
- }
421
- for (const entry of entries) {
422
- if (truncated) return;
423
- // Per-entry deadline/abort check (the Date.now()/.aborted reads are
424
- // negligible) plus a hard entry cap independent of wall-clock time so a
425
- // pathological tree is bounded even when every operation is fast.
426
- if (
427
- Date.now() - searchStart > MAX_SEARCH_MS ||
428
- context.signal?.aborted
429
- ) {
430
- truncated = true;
431
- timedOut = true;
432
- return;
433
- }
434
- entriesTraversed++;
435
- if (entriesTraversed > MAX_ENTRIES_TRAVERSED) {
436
- truncated = true;
437
- return;
438
- }
439
- const full = join(dir, entry.name);
440
- if (entry.isDirectory()) {
441
- if (IGNORED_DIRS.has(entry.name)) continue;
442
- walk(full);
443
- continue;
444
- }
445
- if (!entry.isFile()) continue;
446
- scanFile(full);
447
- }
448
- };
449
-
450
- if (rootStat.isDirectory()) {
451
- walk(root, true);
452
- // An explicit directory root that statSync sees but readdirSync can't read
453
- // (EACCES/EPERM) was never searched — surface a hard error instead of a
454
- // false "No matches found", mirroring the unreadable explicit-file root.
455
- if (rootReadError) {
456
- return { content: rootReadError, isError: true };
457
- }
458
- } else if (rootStat.isFile()) {
459
- // A regular-file root is a valid single-file search. Unlike an oversized
460
- // file skipped mid-walk (where other files may still match), an oversized
461
- // explicit root means nothing was searched at all — surface a hard error
462
- // instead of falling through to a false "No matches found".
463
- if (rootStat.size > MAX_FILE_BYTES) {
464
- return {
465
- content: `Error: file too large to search (${rootStat.size} bytes): ${rawPath}`,
466
- isError: true,
467
- };
468
- }
469
- scanFile(root, true);
470
- if (rootReadError) {
471
- return { content: rootReadError, isError: true };
472
- }
473
- } else {
474
- return {
475
- content: `Error: path not found: ${rawPath}`,
476
- isError: true,
477
- };
478
- }
479
-
480
- if (matchCount === 0) {
481
- // With zero matches, `truncated` can only have been set by a scan cap
482
- // (MAX_FILES_SCANNED / MAX_TOTAL_BYTES / MAX_ENTRIES_TRAVERSED) or the
483
- // wall-clock deadline, never the max-results path. In either case the tree
484
- // was only partially scanned, so a definitive "No matches found" would be
485
- // a false negative.
486
- if (timedOut) {
487
- return {
488
- content: `Search timed out after ${MAX_SEARCH_MS / 1000}s before finding any match for /${pattern}/${caseInsensitive ? "i" : ""} under ${basename(root)}. Results are incomplete — narrow your pattern, glob, or path and search again.`,
489
- isError: false,
490
- status: "truncated",
491
- };
492
- }
493
- if (truncated) {
494
- return {
495
- content: `Search stopped early after hitting a scan cap before finding any match for /${pattern}/${caseInsensitive ? "i" : ""} under ${basename(root)}. Results are incomplete — narrow your glob or path and search again.`,
496
- isError: false,
497
- status: "truncated",
498
- };
499
- }
500
- if (skippedLargeFile) {
501
- return {
502
- content: `No matches found for /${pattern}/${caseInsensitive ? "i" : ""} under ${basename(root)}, but one or more files were skipped because they exceed the ${Math.round(MAX_FILE_BYTES / (1024 * 1024))} MiB per-file size limit, so results may be incomplete.`,
503
- isError: false,
504
- status: "truncated",
505
- };
506
- }
507
- return {
508
- content: `No matches found for /${pattern}/${caseInsensitive ? "i" : ""} under ${basename(root)}`,
509
- isError: false,
510
- };
511
- }
512
-
513
- let content = lines.join("\n");
514
- if (truncated) {
515
- // Distinguish the truncation cause in priority order so the note doesn't
516
- // mislead. Only `maxResultsHit` is helped by raising `max_results`; a
517
- // scan/traversal cap (MAX_FILES_SCANNED / MAX_TOTAL_BYTES /
518
- // MAX_ENTRIES_TRAVERSED) is not, so it gets its own note.
519
- if (timedOut) {
520
- content += `\n\n[Search timed out after ${MAX_SEARCH_MS / 1000}s. Results are incomplete. Narrow your pattern, glob, or path to see more.]`;
521
- } else if (outputBudgetHit) {
522
- content += `\n\n[Output capped at ${Math.round(MAX_OUTPUT_BYTES / (1024 * 1024))} MiB. Narrow your pattern, glob, or path, or reduce context_lines, to see more.]`;
523
- } else if (maxResultsHit) {
524
- content += `\n\n[Results truncated at ${maxResults} matches. Narrow your pattern, glob, or path to see more.]`;
525
- } else {
526
- content += `\n\n[Search stopped early after hitting a scan/traversal cap — some files weren't searched. Narrow your glob or path (raising max_results won't help).]`;
527
- }
528
- }
529
- if (skippedLargeFile) {
530
- // Independent of the truncation reasons above: note any files skipped for
531
- // exceeding the per-file size limit so the result isn't read as complete.
532
- content += `\n\n[One or more files were skipped because they exceed the ${Math.round(MAX_FILE_BYTES / (1024 * 1024))} MiB per-file size limit. Results may be incomplete.]`;
533
- }
534
-
535
- return {
536
- content,
537
- isError: false,
538
- ...(truncated || skippedLargeFile ? { status: "truncated" } : {}),
539
- };
540
- },
541
- } satisfies ToolDefinition;
542
-
543
- registerTool(codeSearchTool);
@@ -1,24 +0,0 @@
1
- import { join } from "node:path";
2
-
3
- import { getDataDir } from "./platform.js";
4
-
5
- /**
6
- * Path to the dedicated SQLite file that houses telemetry event tables
7
- * (starting with `watchdog_events`). It lives in the same `data/db` directory
8
- * as the main DB and is opened on its own connection (see `getTelemetryDb()`
9
- * in `memory/db-connection.ts`). Splitting telemetry tables into their own
10
- * file keeps the main DB — and its WAL — small and lets the two files
11
- * VACUUM/checkpoint independently, so a burst of watchdog events can no longer
12
- * bloat the main database.
13
- *
14
- * Kept in its own leaf module rather than alongside `getDbPath()` in
15
- * `platform.ts`: `platform.ts` is imported very early and widely, and adding an
16
- * export to it that low-level consumers (e.g. `db-connection.ts`) pull in
17
- * across the daemon's large, cyclic import graph trips a Bun link-order bug
18
- * ("Export named 'getTelemetryDbPath' not found"). Isolating it here keeps
19
- * `platform.ts`'s module shape stable — same reasoning as `logs-db-path.ts`
20
- * and `memory-db-path.ts`.
21
- */
22
- export function getTelemetryDbPath(): string {
23
- return join(getDataDir(), "db", "assistant-telemetry.db");
24
- }