@vellumai/assistant 0.8.0 → 0.8.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 (991) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +2 -7
  3. package/Dockerfile +80 -5
  4. package/README.md +2 -2
  5. package/bun.lock +11 -1
  6. package/docker-entrypoint.sh +21 -0
  7. package/docker-init-apt-root.sh +94 -0
  8. package/docker-kata-apt-env.sh +39 -0
  9. package/docs/plugins.md +88 -47
  10. package/docs/skills.md +9 -7
  11. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  12. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  13. package/eslint.config.mjs +12 -0
  14. package/examples/plugins/echo/README.md +27 -27
  15. package/examples/plugins/echo/package.json +3 -0
  16. package/examples/plugins/echo/register.ts +31 -31
  17. package/knip.json +2 -1
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
  20. package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
  21. package/openapi.yaml +4462 -991
  22. package/package.json +5 -1
  23. package/scripts/generate-openapi.ts +135 -14
  24. package/scripts/sync-llm-catalog.ts +165 -0
  25. package/scripts/sync-web-search-catalog.ts +129 -0
  26. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  27. package/src/__tests__/agent-image-optimize.test.ts +11 -3
  28. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  29. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  30. package/src/__tests__/anthropic-provider.test.ts +137 -2
  31. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  32. package/src/__tests__/app-control-flow.test.ts +7 -0
  33. package/src/__tests__/app-executors.test.ts +220 -4
  34. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  35. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  36. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  37. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  38. package/src/__tests__/btw-routes.test.ts +1 -0
  39. package/src/__tests__/bundled-asset.test.ts +6 -6
  40. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  41. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  42. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  43. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  44. package/src/__tests__/channel-policy.test.ts +12 -0
  45. package/src/__tests__/checker.test.ts +89 -0
  46. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  47. package/src/__tests__/clawhub.test.ts +75 -16
  48. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
  49. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  50. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  51. package/src/__tests__/compactor-tail-resolution.test.ts +41 -0
  52. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  53. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  54. package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
  55. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  56. package/src/__tests__/config-schema.test.ts +35 -3
  57. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  58. package/src/__tests__/config-set-route.test.ts +278 -0
  59. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  60. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  61. package/src/__tests__/config-watcher.test.ts +6 -0
  62. package/src/__tests__/contacts-tools.test.ts +51 -199
  63. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  64. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  65. package/src/__tests__/context-search-conversations-source.test.ts +159 -18
  66. package/src/__tests__/context-search-fanout.test.ts +20 -157
  67. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -4
  68. package/src/__tests__/context-search-types.test.ts +7 -2
  69. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  70. package/src/__tests__/context-token-estimator.test.ts +1 -0
  71. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  72. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  73. package/src/__tests__/conversation-agent-loop-overflow.test.ts +93 -92
  74. package/src/__tests__/conversation-agent-loop.test.ts +2 -0
  75. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  76. package/src/__tests__/conversation-error.test.ts +80 -3
  77. package/src/__tests__/conversation-fork-crud.test.ts +323 -1
  78. package/src/__tests__/conversation-inference-profile-route.test.ts +54 -18
  79. package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
  80. package/src/__tests__/conversation-lifecycle.test.ts +297 -0
  81. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  82. package/src/__tests__/conversation-pairing.test.ts +54 -0
  83. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  84. package/src/__tests__/conversation-process-callsite.test.ts +25 -2
  85. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  86. package/src/__tests__/conversation-queue.test.ts +4 -1
  87. package/src/__tests__/conversation-runtime-assembly.test.ts +80 -13
  88. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  89. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  90. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  91. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  92. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  93. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  94. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  95. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  96. package/src/__tests__/credential-security-invariants.test.ts +8 -8
  97. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  98. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  99. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  100. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  101. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  102. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  103. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  104. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  105. package/src/__tests__/dm-backfill.test.ts +121 -10
  106. package/src/__tests__/document-tool-security.test.ts +258 -0
  107. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  108. package/src/__tests__/edit-propagation.test.ts +33 -0
  109. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  110. package/src/__tests__/external-plugin-loader.test.ts +482 -0
  111. package/src/__tests__/filing-service.test.ts +163 -3
  112. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  113. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  114. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  115. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  116. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +42 -69
  117. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  118. package/src/__tests__/heartbeat-service.test.ts +50 -233
  119. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  120. package/src/__tests__/helpers/wait-for.ts +21 -0
  121. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  122. package/src/__tests__/history-repair.test.ts +162 -0
  123. package/src/__tests__/host-app-control-proxy.test.ts +365 -1
  124. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  125. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  126. package/src/__tests__/host-browser-routes.test.ts +325 -33
  127. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  128. package/src/__tests__/image-credentials.test.ts +1 -1
  129. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  130. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  131. package/src/__tests__/inference-profile-reaper.test.ts +156 -0
  132. package/src/__tests__/inference-profile-session-handler.test.ts +410 -0
  133. package/src/__tests__/inference-profile-session-ipc.test.ts +248 -0
  134. package/src/__tests__/injector-chain.test.ts +10 -8
  135. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  136. package/src/__tests__/install-skill-routing.test.ts +157 -39
  137. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +107 -3
  138. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  139. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  140. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  141. package/src/__tests__/llm-catalog-parity.test.ts +190 -2
  142. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +222 -0
  143. package/src/__tests__/llm-request-log-source-factory.test.ts +100 -0
  144. package/src/__tests__/llm-resolver.test.ts +46 -0
  145. package/src/__tests__/llm-usage-store.test.ts +114 -0
  146. package/src/__tests__/managed-profile-guard.test.ts +145 -14
  147. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  148. package/src/__tests__/managed-store.test.ts +84 -192
  149. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  150. package/src/__tests__/mcp-cli.test.ts +182 -220
  151. package/src/__tests__/mcp-health-check.test.ts +56 -27
  152. package/src/__tests__/media-generate-image.test.ts +1 -1
  153. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  154. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  155. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  156. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  157. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  158. package/src/__tests__/oauth-cli.test.ts +38 -2009
  159. package/src/__tests__/oauth-commands-routes.test.ts +863 -0
  160. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  161. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  162. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  163. package/src/__tests__/openai-provider.test.ts +24 -0
  164. package/src/__tests__/openai-responses-cutover-guard.test.ts +48 -19
  165. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  166. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  167. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  168. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +1 -1
  169. package/src/__tests__/platform.test.ts +2 -0
  170. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  171. package/src/__tests__/plugin-bootstrap.test.ts +41 -38
  172. package/src/__tests__/plugin-external-api.test.ts +68 -0
  173. package/src/__tests__/plugin-registry.test.ts +0 -77
  174. package/src/__tests__/plugin-route-contribution.test.ts +31 -4
  175. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  176. package/src/__tests__/plugin-tool-contribution.test.ts +47 -18
  177. package/src/__tests__/plugin-types.test.ts +15 -23
  178. package/src/__tests__/process-message-background-slack.test.ts +53 -0
  179. package/src/__tests__/process-message-display-content.test.ts +421 -0
  180. package/src/__tests__/profile-entry-status.test.ts +43 -0
  181. package/src/__tests__/provider-catalog-visibility.test.ts +142 -0
  182. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  183. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +20 -12
  184. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  185. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  186. package/src/__tests__/relay-server.test.ts +118 -0
  187. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  188. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  189. package/src/__tests__/schedule-retry.test.ts +56 -4
  190. package/src/__tests__/schedule-routes.test.ts +151 -0
  191. package/src/__tests__/schedule-store.test.ts +94 -0
  192. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  193. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  194. package/src/__tests__/scheduler-reuse-conversation.test.ts +208 -5
  195. package/src/__tests__/scheduler-wake.test.ts +0 -63
  196. package/src/__tests__/schema-transforms.test.ts +20 -0
  197. package/src/__tests__/search-skills-unified.test.ts +0 -5
  198. package/src/__tests__/secret-allowlist.test.ts +1 -0
  199. package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +12 -4
  200. package/src/__tests__/server-history-render.test.ts +43 -0
  201. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  202. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  203. package/src/__tests__/skill-load-feature-flag.test.ts +1 -12
  204. package/src/__tests__/skill-load-tool.test.ts +29 -93
  205. package/src/__tests__/skill-memory.test.ts +23 -3
  206. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  207. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  208. package/src/__tests__/skills-install-extract.test.ts +49 -38
  209. package/src/__tests__/skills-install-staging.test.ts +159 -0
  210. package/src/__tests__/skills-uninstall.test.ts +9 -41
  211. package/src/__tests__/skills.test.ts +51 -58
  212. package/src/__tests__/slack-channel-config.test.ts +9 -0
  213. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  214. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  215. package/src/__tests__/suggestion-routes.test.ts +3 -3
  216. package/src/__tests__/sync-message-contract.test.ts +63 -0
  217. package/src/__tests__/system-prompt.test.ts +737 -63
  218. package/src/__tests__/task-scheduler.test.ts +88 -23
  219. package/src/__tests__/terminal-tools.test.ts +28 -1
  220. package/src/__tests__/thread-backfill.test.ts +557 -27
  221. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  222. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  223. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  224. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  225. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  226. package/src/__tests__/tool-executor.test.ts +16 -4
  227. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  228. package/src/__tests__/turn-events-store.test.ts +256 -0
  229. package/src/__tests__/twilio-routes.test.ts +4 -0
  230. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  231. package/src/__tests__/usage-cli.test.ts +11 -73
  232. package/src/__tests__/user-plugin-loader.test.ts +143 -5
  233. package/src/__tests__/vercel-config.test.ts +168 -0
  234. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  235. package/src/__tests__/web-search-catalog-parity.test.ts +108 -0
  236. package/src/__tests__/web-search.test.ts +303 -2
  237. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  238. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +170 -0
  239. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
  240. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +241 -0
  241. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  242. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  243. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  244. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  245. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  246. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  247. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  248. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  249. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  250. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  251. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  252. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  253. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  254. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  255. package/src/acp/resolve-agent.test.ts +25 -0
  256. package/src/acp/resolve-agent.ts +13 -2
  257. package/src/acp/session-manager.ts +14 -0
  258. package/src/agent/image-optimize.ts +13 -5
  259. package/src/approvals/guardian-request-resolvers.ts +32 -87
  260. package/src/calls/relay-server.ts +35 -0
  261. package/src/calls/relay-setup-router.ts +36 -0
  262. package/src/calls/types.ts +1 -0
  263. package/src/calls/voice-session-bridge.ts +74 -36
  264. package/src/channels/config.ts +14 -1
  265. package/src/channels/types.ts +109 -0
  266. package/src/cli/AGENTS.md +164 -4
  267. package/src/cli/__tests__/notifications.test.ts +54 -0
  268. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  269. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  270. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  271. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  272. package/src/cli/commands/__tests__/changelog.test.ts +578 -0
  273. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  274. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  275. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  276. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  277. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  278. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  279. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  280. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  281. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  282. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  283. package/src/cli/commands/__tests__/schedules.test.ts +491 -0
  284. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  285. package/src/cli/commands/__tests__/status.test.ts +249 -0
  286. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  287. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  288. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  289. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  290. package/src/cli/commands/attachment.ts +8 -3
  291. package/src/cli/commands/audit.ts +95 -64
  292. package/src/cli/commands/auth.ts +61 -58
  293. package/src/cli/commands/avatar.ts +276 -390
  294. package/src/cli/commands/backup.ts +409 -505
  295. package/src/cli/commands/bash.ts +9 -5
  296. package/src/cli/commands/browser.ts +28 -9
  297. package/src/cli/commands/cache.ts +9 -4
  298. package/src/cli/commands/changelog.ts +478 -0
  299. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  300. package/src/cli/commands/clients.ts +8 -3
  301. package/src/cli/commands/completions.ts +9 -9
  302. package/src/cli/commands/config.ts +102 -72
  303. package/src/cli/commands/contacts.ts +575 -696
  304. package/src/cli/commands/conversations-defer.ts +17 -69
  305. package/src/cli/commands/conversations-import.ts +90 -253
  306. package/src/cli/commands/conversations.ts +429 -434
  307. package/src/cli/commands/credential-execution.ts +9 -6
  308. package/src/cli/commands/credentials.ts +456 -736
  309. package/src/cli/commands/default-action.ts +10 -53
  310. package/src/cli/commands/domain.ts +128 -206
  311. package/src/cli/commands/email.ts +606 -794
  312. package/src/cli/commands/gateway.ts +8 -1
  313. package/src/cli/commands/image-generation.ts +157 -205
  314. package/src/cli/commands/inference-providers.ts +352 -0
  315. package/src/cli/commands/inference-session.ts +415 -0
  316. package/src/cli/commands/inference.ts +87 -65
  317. package/src/cli/commands/keys.ts +8 -3
  318. package/src/cli/commands/mcp.ts +103 -287
  319. package/src/cli/commands/memory-v2.ts +162 -516
  320. package/src/cli/commands/notifications.ts +342 -304
  321. package/src/cli/commands/oauth/apps.ts +292 -261
  322. package/src/cli/commands/oauth/connect.ts +176 -297
  323. package/src/cli/commands/oauth/disconnect.ts +16 -215
  324. package/src/cli/commands/oauth/index.ts +49 -45
  325. package/src/cli/commands/oauth/mode.ts +43 -199
  326. package/src/cli/commands/oauth/ping.ts +17 -125
  327. package/src/cli/commands/oauth/providers.ts +732 -921
  328. package/src/cli/commands/oauth/request.ts +60 -350
  329. package/src/cli/commands/oauth/shared.ts +11 -121
  330. package/src/cli/commands/oauth/status.ts +31 -121
  331. package/src/cli/commands/oauth/token.ts +13 -55
  332. package/src/cli/commands/pending.ts +19 -10
  333. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  334. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  335. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  336. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  337. package/src/cli/commands/platform/connect.ts +16 -80
  338. package/src/cli/commands/platform/disconnect.ts +14 -112
  339. package/src/cli/commands/platform/index.ts +177 -246
  340. package/src/cli/commands/plugins.ts +185 -0
  341. package/src/cli/commands/routes.ts +153 -336
  342. package/src/cli/commands/schedules.ts +391 -0
  343. package/src/cli/commands/sequence.ts +316 -360
  344. package/src/cli/commands/skills.ts +449 -671
  345. package/src/cli/commands/status.ts +58 -37
  346. package/src/cli/commands/stt.ts +94 -262
  347. package/src/cli/commands/task.ts +14 -40
  348. package/src/cli/commands/telemetry.ts +40 -0
  349. package/src/cli/commands/trust.ts +8 -3
  350. package/src/cli/commands/tts.ts +162 -167
  351. package/src/cli/commands/ui.ts +35 -42
  352. package/src/cli/commands/usage.ts +188 -126
  353. package/src/cli/commands/watchers.ts +8 -3
  354. package/src/cli/commands/webhooks.ts +99 -193
  355. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  356. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  357. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  358. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  359. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  360. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  361. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  362. package/src/cli/lib/cli-colors.ts +12 -0
  363. package/src/cli/lib/confirm-prompt.ts +79 -0
  364. package/src/cli/lib/daemon-credential-client.ts +4 -5
  365. package/src/cli/lib/install-from-github.ts +304 -0
  366. package/src/cli/lib/list-installed-plugins.ts +137 -0
  367. package/src/cli/lib/nested-value.ts +44 -0
  368. package/src/cli/lib/open-browser.ts +36 -0
  369. package/src/cli/lib/register-command.ts +19 -0
  370. package/src/cli/lib/time-ago.ts +34 -0
  371. package/src/cli/lib/uninstall-plugin.ts +82 -0
  372. package/src/cli/lib/unknown-command.ts +111 -0
  373. package/src/cli/program.ts +40 -6
  374. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  375. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  376. package/src/cli/utils/conversation-id.ts +30 -0
  377. package/src/cli/utils/parse-duration.ts +41 -0
  378. package/src/config/acp-defaults.test.ts +5 -1
  379. package/src/config/acp-defaults.ts +11 -4
  380. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  381. package/src/config/bundled-skills/app-builder/SKILL.md +23 -21
  382. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  383. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  384. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  385. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  386. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  387. package/src/config/bundled-skills/document/SKILL.md +23 -3
  388. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  389. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  390. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  391. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  392. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  393. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  394. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  395. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  396. package/src/config/bundled-tool-registry.ts +6 -2
  397. package/src/config/feature-flag-registry.json +57 -1
  398. package/src/config/llm-resolver.ts +16 -1
  399. package/src/config/loader.ts +140 -52
  400. package/src/config/raw-config-utils.ts +2 -30
  401. package/src/config/schema.ts +8 -7
  402. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  403. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  404. package/src/config/schemas/call-site-catalog.ts +29 -7
  405. package/src/config/schemas/channels.ts +8 -0
  406. package/src/config/schemas/compaction.ts +28 -0
  407. package/src/config/schemas/heartbeat.ts +9 -0
  408. package/src/config/schemas/llm-request-logs.ts +81 -0
  409. package/src/config/schemas/llm.ts +55 -2
  410. package/src/config/schemas/memory-retrieval.ts +18 -0
  411. package/src/config/schemas/memory-retrospective.ts +48 -0
  412. package/src/config/schemas/memory-v2.ts +32 -1
  413. package/src/config/schemas/memory.ts +4 -0
  414. package/src/config/schemas/services.ts +15 -12
  415. package/src/config/schemas/tools.ts +14 -0
  416. package/src/config/seed-inference-profiles.ts +195 -134
  417. package/src/config/skills.ts +3 -96
  418. package/src/contacts/contact-store.ts +0 -61
  419. package/src/context/compactor.ts +1047 -0
  420. package/src/context/token-estimator.ts +2 -2
  421. package/src/context/window-manager.ts +197 -1334
  422. package/src/credential-execution/managed-catalog.ts +37 -0
  423. package/src/credential-health/credential-health-service.ts +280 -19
  424. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +113 -0
  425. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  426. package/src/daemon/__tests__/conversation-tool-setup.test.ts +183 -4
  427. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  428. package/src/daemon/approval-generators.ts +26 -30
  429. package/src/daemon/config-watcher.ts +94 -29
  430. package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
  431. package/src/daemon/conversation-agent-loop.ts +293 -103
  432. package/src/daemon/conversation-error.ts +188 -33
  433. package/src/daemon/conversation-lifecycle.ts +80 -26
  434. package/src/daemon/conversation-messaging.ts +25 -6
  435. package/src/daemon/conversation-process.ts +85 -31
  436. package/src/daemon/conversation-runtime-assembly.ts +30 -6
  437. package/src/daemon/conversation-slash.ts +184 -25
  438. package/src/daemon/conversation-store.ts +24 -10
  439. package/src/daemon/conversation-surfaces.ts +76 -12
  440. package/src/daemon/conversation-tool-setup.ts +63 -21
  441. package/src/daemon/conversation.ts +81 -10
  442. package/src/daemon/external-plugins-bootstrap.ts +231 -185
  443. package/src/daemon/first-greeting.ts +22 -2
  444. package/src/daemon/guardian-action-generators.ts +7 -22
  445. package/src/daemon/handlers/config-model.ts +13 -130
  446. package/src/daemon/handlers/config-slack-channel.ts +25 -10
  447. package/src/daemon/handlers/config-vercel.ts +3 -1
  448. package/src/daemon/handlers/shared.ts +14 -5
  449. package/src/daemon/handlers/skills.ts +166 -84
  450. package/src/daemon/history-repair.ts +61 -7
  451. package/src/daemon/host-app-control-proxy.ts +129 -29
  452. package/src/daemon/host-bash-proxy.ts +85 -158
  453. package/src/daemon/host-browser-proxy.ts +96 -35
  454. package/src/daemon/host-proxy-base.ts +13 -1
  455. package/src/daemon/host-proxy-preactivation.ts +25 -1
  456. package/src/daemon/identity-helpers.ts +19 -0
  457. package/src/daemon/lifecycle.ts +79 -70
  458. package/src/daemon/meet-host-supervisor.ts +20 -19
  459. package/src/daemon/memory-v2-startup.ts +58 -2
  460. package/src/daemon/message-protocol.ts +7 -0
  461. package/src/daemon/message-types/bookmarks.ts +18 -0
  462. package/src/daemon/message-types/conversations.ts +37 -9
  463. package/src/daemon/message-types/messages.ts +70 -1
  464. package/src/daemon/message-types/subagents.ts +1 -0
  465. package/src/daemon/message-types/sync.ts +61 -0
  466. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  467. package/src/daemon/pkb-reminder-builder.ts +21 -7
  468. package/src/daemon/plugin-source-watcher.ts +146 -0
  469. package/src/daemon/process-message.ts +77 -26
  470. package/src/daemon/server.ts +34 -20
  471. package/src/daemon/shutdown-handlers.ts +0 -2
  472. package/src/daemon/skill-memory-refresh.ts +29 -0
  473. package/src/daemon/tool-setup-types.ts +9 -0
  474. package/src/daemon/tool-side-effects.ts +6 -4
  475. package/src/daemon/wake-target-adapter.ts +11 -0
  476. package/src/documents/document-store.ts +221 -3
  477. package/src/embedded/plugin-api.ts +40 -0
  478. package/src/export/transcript-formatter.ts +61 -2
  479. package/src/filing/filing-service.ts +79 -53
  480. package/src/heartbeat/__tests__/heartbeat-service.test.ts +444 -0
  481. package/src/heartbeat/heartbeat-run-store.ts +3 -1
  482. package/src/heartbeat/heartbeat-service.ts +189 -127
  483. package/src/home/__tests__/feed-types.test.ts +99 -127
  484. package/src/home/__tests__/feed-writer.test.ts +77 -278
  485. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  486. package/src/home/feed-types.ts +41 -73
  487. package/src/home/feed-writer.ts +25 -156
  488. package/src/home/post-connect-feed.ts +2 -3
  489. package/src/index.ts +18 -1
  490. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  491. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  492. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  493. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  494. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  495. package/src/ipc/assistant-server.ts +55 -6
  496. package/src/ipc/cli-client.ts +370 -50
  497. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  498. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  499. package/src/ipc/skill-routes/events.ts +30 -3
  500. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  501. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  502. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  503. package/src/live-voice/live-voice-session-manager.ts +11 -4
  504. package/src/live-voice/live-voice-session.ts +14 -6
  505. package/src/mcp/client.ts +20 -4
  506. package/src/media/image-credentials.ts +3 -3
  507. package/src/memory/__tests__/bookmark-crud.test.ts +264 -0
  508. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  509. package/src/memory/__tests__/conversation-queries.test.ts +263 -0
  510. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  511. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  512. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  513. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  514. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  515. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +318 -0
  516. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  517. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  518. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  519. package/src/memory/__tests__/message-content.test.ts +35 -0
  520. package/src/memory/bookmark-crud.ts +211 -0
  521. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  522. package/src/memory/context-search/agent-protocol.ts +5 -1
  523. package/src/memory/context-search/agent-runner.ts +60 -85
  524. package/src/memory/context-search/limits.ts +1 -4
  525. package/src/memory/context-search/search.ts +23 -113
  526. package/src/memory/context-search/sources/conversations.ts +80 -8
  527. package/src/memory/context-search/sources/memory-v2.ts +39 -14
  528. package/src/memory/context-search/sources/memory.ts +7 -0
  529. package/src/memory/context-search/sources/workspace.ts +17 -10
  530. package/src/memory/context-search/types.ts +1 -1
  531. package/src/memory/conversation-bootstrap.ts +11 -0
  532. package/src/memory/conversation-crud.ts +368 -22
  533. package/src/memory/conversation-queries.ts +116 -12
  534. package/src/memory/conversation-title-service.ts +1 -0
  535. package/src/memory/conversation-types.ts +16 -0
  536. package/src/memory/db-init.ts +20 -0
  537. package/src/memory/delivery-crud.ts +152 -5
  538. package/src/memory/embedding-backend.ts +6 -5
  539. package/src/memory/embedding-runtime-manager.ts +1 -2
  540. package/src/memory/external-conversation-store.ts +66 -5
  541. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +66 -9
  542. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  543. package/src/memory/graph/conversation-graph-memory.ts +92 -5
  544. package/src/memory/graph/extraction.ts +4 -0
  545. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  546. package/src/memory/graph/tool-handlers.ts +17 -7
  547. package/src/memory/graph/tools.ts +45 -6
  548. package/src/memory/indexer.ts +51 -29
  549. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +86 -15
  550. package/src/memory/jobs/embed-concept-page.ts +65 -20
  551. package/src/memory/jobs-store.ts +51 -1
  552. package/src/memory/jobs-worker.ts +57 -3
  553. package/src/memory/llm-request-log-source-clickhouse.ts +324 -0
  554. package/src/memory/llm-request-log-source-local.ts +26 -0
  555. package/src/memory/llm-request-log-source.ts +64 -0
  556. package/src/memory/llm-request-log-store.ts +1 -1
  557. package/src/memory/llm-usage-store.ts +125 -5
  558. package/src/memory/memory-retrospective-constants.ts +13 -0
  559. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  560. package/src/memory/memory-retrospective-job.ts +351 -0
  561. package/src/memory/memory-retrospective-startup-cleanup.ts +175 -0
  562. package/src/memory/memory-retrospective-state.ts +162 -0
  563. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  564. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  565. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  566. package/src/memory/message-content.ts +38 -1
  567. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  568. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  569. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  570. package/src/memory/migrations/229-delete-private-conversations.test.ts +107 -1
  571. package/src/memory/migrations/229-delete-private-conversations.ts +19 -0
  572. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  573. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  574. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  575. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  576. package/src/memory/migrations/243-provider-connections.ts +68 -0
  577. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  578. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  579. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  580. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  581. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  582. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  583. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  584. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  585. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  586. package/src/memory/migrations/index.ts +13 -0
  587. package/src/memory/migrations/registry.ts +8 -0
  588. package/src/memory/onboarding-events-store.ts +106 -0
  589. package/src/memory/published-pages-store.ts +16 -0
  590. package/src/memory/schema/bookmarks.ts +36 -0
  591. package/src/memory/schema/calls.ts +1 -0
  592. package/src/memory/schema/conversations.ts +2 -0
  593. package/src/memory/schema/index.ts +2 -0
  594. package/src/memory/schema/inference.ts +27 -0
  595. package/src/memory/schema/infrastructure.ts +12 -0
  596. package/src/memory/schema/memory-core.ts +9 -0
  597. package/src/memory/search/semantic.ts +1 -4
  598. package/src/memory/turn-events-store.ts +127 -2
  599. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  600. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  601. package/src/memory/v2/__tests__/activation.test.ts +11 -12
  602. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  603. package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
  604. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  605. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  606. package/src/memory/v2/__tests__/injection.test.ts +726 -18
  607. package/src/memory/v2/__tests__/migration.test.ts +94 -3
  608. package/src/memory/v2/__tests__/page-index.test.ts +360 -0
  609. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  610. package/src/memory/v2/__tests__/prompts-router.test.ts +309 -0
  611. package/src/memory/v2/__tests__/qdrant.test.ts +138 -3
  612. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  613. package/src/memory/v2/__tests__/router.test.ts +531 -0
  614. package/src/memory/v2/__tests__/sim.test.ts +45 -1
  615. package/src/memory/v2/__tests__/skill-store.test.ts +445 -11
  616. package/src/memory/v2/__tests__/static-context.test.ts +7 -22
  617. package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
  618. package/src/memory/v2/activation-store.ts +34 -5
  619. package/src/memory/v2/activation.ts +40 -27
  620. package/src/memory/v2/backfill-jobs.ts +17 -84
  621. package/src/memory/v2/consolidation-job.ts +85 -78
  622. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  623. package/src/memory/v2/injection.ts +466 -109
  624. package/src/memory/v2/migration.ts +147 -20
  625. package/src/memory/v2/page-index.ts +221 -0
  626. package/src/memory/v2/page-store.ts +3 -0
  627. package/src/memory/v2/prompts/consolidation.ts +9 -7
  628. package/src/memory/v2/prompts/router.ts +195 -0
  629. package/src/memory/v2/prompts/sweep.ts +2 -2
  630. package/src/memory/v2/qdrant.ts +234 -93
  631. package/src/memory/v2/reranker.ts +14 -7
  632. package/src/memory/v2/router.ts +323 -0
  633. package/src/memory/v2/sim.ts +25 -12
  634. package/src/memory/v2/skill-store.ts +204 -30
  635. package/src/memory/v2/static-context.ts +16 -9
  636. package/src/memory/v2/sweep-job.ts +122 -96
  637. package/src/memory/v2/types.ts +10 -6
  638. package/src/memory/validation.ts +13 -0
  639. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  640. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  641. package/src/messaging/providers/slack/adapter.ts +43 -5
  642. package/src/messaging/providers/slack/client.ts +27 -0
  643. package/src/messaging/providers/slack/deep-link.ts +65 -0
  644. package/src/messaging/providers/slack/download.ts +104 -0
  645. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  646. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  647. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  648. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  649. package/src/messaging/providers/slack/types.ts +20 -1
  650. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  651. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  652. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  653. package/src/notifications/adapters/platform.ts +171 -0
  654. package/src/notifications/conversation-pairing.ts +4 -3
  655. package/src/notifications/copy-composer.ts +15 -0
  656. package/src/notifications/decision-engine.ts +2 -1
  657. package/src/notifications/destination-resolver.ts +21 -0
  658. package/src/notifications/emit-signal.ts +48 -2
  659. package/src/notifications/home-feed-side-effect.ts +165 -0
  660. package/src/notifications/signal.ts +8 -1
  661. package/src/oauth/connection-resolver.ts +8 -4
  662. package/src/oauth/platform-connection.ts +6 -2
  663. package/src/oauth/seed-providers.ts +10 -1
  664. package/src/permissions/checker.ts +14 -0
  665. package/src/permissions/ipc-risk-types.ts +3 -0
  666. package/src/permissions/question-prompter.test.ts +416 -0
  667. package/src/permissions/question-prompter.ts +294 -0
  668. package/src/platform/client.test.ts +1 -1
  669. package/src/platform/client.ts +1 -1
  670. package/src/plugin-api/constants.ts +26 -0
  671. package/src/plugin-api/index.ts +46 -0
  672. package/src/plugin-api/package.json +12 -0
  673. package/src/plugin-api/types.ts +144 -0
  674. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  675. package/src/plugins/defaults/compaction.ts +0 -4
  676. package/src/plugins/defaults/empty-response.ts +0 -2
  677. package/src/plugins/defaults/history-repair.ts +0 -2
  678. package/src/plugins/defaults/injectors.ts +55 -6
  679. package/src/plugins/defaults/llm-call.ts +0 -2
  680. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  681. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  682. package/src/plugins/defaults/persistence.ts +0 -2
  683. package/src/plugins/defaults/title-generate.ts +0 -5
  684. package/src/plugins/defaults/token-estimate.ts +0 -2
  685. package/src/plugins/defaults/tool-error.ts +0 -7
  686. package/src/plugins/defaults/tool-execute.ts +0 -2
  687. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  688. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  689. package/src/plugins/external-api.ts +104 -0
  690. package/src/plugins/external-plugin-loader.ts +367 -0
  691. package/src/plugins/feature-gate.ts +22 -0
  692. package/src/plugins/pipeline.ts +37 -0
  693. package/src/plugins/registry.ts +48 -80
  694. package/src/plugins/types.ts +74 -53
  695. package/src/plugins/user-loader.ts +85 -43
  696. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  697. package/src/proactive-artifact/job.test.ts +49 -9
  698. package/src/proactive-artifact/job.ts +4 -0
  699. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  700. package/src/proactive-artifact/trigger-state.ts +4 -0
  701. package/src/prompts/__tests__/system-prompt.test.ts +117 -0
  702. package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
  703. package/src/prompts/normalize-onboarding.ts +27 -0
  704. package/src/prompts/sections.ts +302 -0
  705. package/src/prompts/system-prompt.ts +72 -154
  706. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  707. package/src/prompts/templates/system-sections.ts +173 -0
  708. package/src/prompts/update-bulletin-job.ts +61 -73
  709. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  710. package/src/providers/__tests__/inference.test.ts +303 -0
  711. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  712. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  713. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  714. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  715. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  716. package/src/providers/anthropic/client.ts +123 -54
  717. package/src/providers/call-site-routing.ts +94 -16
  718. package/src/providers/connection-resolution.ts +170 -0
  719. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  720. package/src/providers/inference/adapter-factory.ts +210 -0
  721. package/src/providers/inference/auth.ts +112 -0
  722. package/src/providers/inference/backfill.ts +196 -0
  723. package/src/providers/inference/connections.ts +401 -0
  724. package/src/providers/inference/resolve-auth.ts +73 -0
  725. package/src/providers/model-catalog.ts +386 -6
  726. package/src/providers/openai/chat-completions-provider.ts +10 -2
  727. package/src/providers/openai/responses-provider.ts +4 -2
  728. package/src/providers/openrouter/client.ts +7 -0
  729. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
  730. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  731. package/src/providers/provider-availability.ts +17 -2
  732. package/src/providers/provider-catalog-visibility.ts +36 -0
  733. package/src/providers/provider-env-vars.ts +17 -7
  734. package/src/providers/provider-secret-catalog.ts +49 -30
  735. package/src/providers/provider-send-message.ts +41 -20
  736. package/src/providers/registry.ts +151 -159
  737. package/src/providers/retry.ts +65 -11
  738. package/src/providers/search-provider-catalog.ts +121 -0
  739. package/src/runtime/AGENTS.md +18 -5
  740. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  741. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  742. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  743. package/src/runtime/actor-trust-resolver.ts +32 -10
  744. package/src/runtime/agent-wake.ts +64 -7
  745. package/src/runtime/assistant-event-hub.ts +3 -85
  746. package/src/runtime/auth/route-policy.ts +311 -9
  747. package/src/runtime/auth/same-actor.ts +2 -0
  748. package/src/runtime/background-job-runner.ts +339 -0
  749. package/src/runtime/btw-sidechain.ts +3 -0
  750. package/src/runtime/http-router.ts +36 -1
  751. package/src/runtime/http-server.ts +31 -5
  752. package/src/runtime/http-types.ts +21 -0
  753. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  754. package/src/runtime/middleware/request-logger.ts +62 -1
  755. package/src/runtime/migrations/origin-mode.ts +1 -1
  756. package/src/runtime/pending-interactions.ts +1 -0
  757. package/src/runtime/pre-first-message-gate.ts +83 -0
  758. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  759. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +268 -0
  760. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  761. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +319 -0
  762. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +280 -4
  763. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  764. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  765. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
  766. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  767. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  768. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  769. package/src/runtime/routes/__tests__/tts-routes.test.ts +70 -3
  770. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  771. package/src/runtime/routes/acp-routes.ts +12 -8
  772. package/src/runtime/routes/app-management-routes.ts +228 -3
  773. package/src/runtime/routes/approval-routes.ts +0 -18
  774. package/src/runtime/routes/audit-routes.ts +43 -0
  775. package/src/runtime/routes/auth-routes.ts +72 -0
  776. package/src/runtime/routes/avatar-routes.ts +273 -20
  777. package/src/runtime/routes/backup-routes.ts +406 -2
  778. package/src/runtime/routes/bookmark-routes.ts +156 -0
  779. package/src/runtime/routes/btw-routes.ts +5 -1
  780. package/src/runtime/routes/channel-availability-routes.ts +121 -0
  781. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  782. package/src/runtime/routes/contact-routes.ts +0 -160
  783. package/src/runtime/routes/conversation-cli-routes.ts +233 -0
  784. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  785. package/src/runtime/routes/conversation-management-routes.ts +47 -85
  786. package/src/runtime/routes/conversation-query-routes.ts +350 -97
  787. package/src/runtime/routes/conversation-routes.ts +121 -21
  788. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  789. package/src/runtime/routes/credential-routes.ts +540 -0
  790. package/src/runtime/routes/debug-routes.ts +2 -2
  791. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  792. package/src/runtime/routes/documents-routes.ts +25 -86
  793. package/src/runtime/routes/domain-routes.ts +167 -0
  794. package/src/runtime/routes/email-routes.ts +603 -0
  795. package/src/runtime/routes/errors.ts +2 -2
  796. package/src/runtime/routes/events-routes.ts +192 -0
  797. package/src/runtime/routes/group-routes.ts +5 -0
  798. package/src/runtime/routes/home-feed-routes.ts +6 -78
  799. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  800. package/src/runtime/routes/host-browser-routes.ts +103 -22
  801. package/src/runtime/routes/http-adapter.ts +2 -0
  802. package/src/runtime/routes/identity-routes.ts +5 -0
  803. package/src/runtime/routes/image-generation-routes.ts +99 -0
  804. package/src/runtime/routes/inbound-conversation.ts +28 -8
  805. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  806. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +248 -1
  807. package/src/runtime/routes/inbound-stages/background-dispatch.ts +118 -7
  808. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  809. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  810. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
  811. package/src/runtime/routes/index.ts +42 -0
  812. package/src/runtime/routes/inference-profile-session-handler.ts +285 -0
  813. package/src/runtime/routes/inference-profile-session-reaper.ts +84 -0
  814. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  815. package/src/runtime/routes/inference-provider-connection-routes.ts +361 -0
  816. package/src/runtime/routes/inference-send-routes.ts +115 -0
  817. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  818. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  819. package/src/runtime/routes/integrations/twilio.ts +7 -13
  820. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  821. package/src/runtime/routes/memory-v2-routes.ts +13 -398
  822. package/src/runtime/routes/notification-routes.ts +3 -1
  823. package/src/runtime/routes/oauth-apps.ts +112 -7
  824. package/src/runtime/routes/oauth-commands-routes.ts +1097 -0
  825. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  826. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  827. package/src/runtime/routes/oauth-providers.ts +298 -8
  828. package/src/runtime/routes/platform-routes.ts +336 -0
  829. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  830. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  831. package/src/runtime/routes/playground/state.ts +2 -1
  832. package/src/runtime/routes/publish-routes.ts +221 -0
  833. package/src/runtime/routes/question-routes.ts +259 -0
  834. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  835. package/src/runtime/routes/schedule-routes.ts +79 -0
  836. package/src/runtime/routes/sequence-routes.ts +291 -0
  837. package/src/runtime/routes/settings-routes.ts +2 -10
  838. package/src/runtime/routes/skills-routes.ts +31 -1
  839. package/src/runtime/routes/stt-routes.ts +240 -3
  840. package/src/runtime/routes/subagents-routes.ts +57 -18
  841. package/src/runtime/routes/surface-action-routes.ts +43 -7
  842. package/src/runtime/routes/telemetry-routes.ts +27 -0
  843. package/src/runtime/routes/tts-routes.ts +93 -1
  844. package/src/runtime/routes/types.ts +32 -0
  845. package/src/runtime/routes/user-routes-cli.ts +243 -0
  846. package/src/runtime/routes/webhook-routes.ts +165 -0
  847. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  848. package/src/runtime/routes/workspace-routes.ts +28 -0
  849. package/src/runtime/services/conversation-serializer.ts +39 -7
  850. package/src/runtime/sync/resource-sync-events.ts +117 -0
  851. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  852. package/src/runtime/sync/sync-publisher.ts +21 -0
  853. package/src/schedule/schedule-store.ts +27 -2
  854. package/src/schedule/scheduler.ts +208 -123
  855. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  856. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  857. package/src/security/secret-patterns.ts +3 -0
  858. package/src/security/untrusted-content.ts +93 -8
  859. package/src/sequence/engine.ts +38 -40
  860. package/src/skills/catalog-files.ts +1 -1
  861. package/src/skills/catalog-install.ts +233 -116
  862. package/src/skills/clawhub.ts +70 -13
  863. package/src/skills/managed-store.ts +4 -119
  864. package/src/skills/skillssh-registry.ts +27 -48
  865. package/src/subagent/manager.ts +28 -15
  866. package/src/telemetry/types.ts +113 -1
  867. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  868. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  869. package/src/tools/apps/executors.ts +58 -7
  870. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  871. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  872. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  873. package/src/tools/browser/browser-execution.ts +29 -14
  874. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  875. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  876. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  877. package/src/tools/browser/cdp-client/factory.ts +66 -5
  878. package/src/tools/browser/runtime-check.ts +77 -0
  879. package/src/tools/computer-use/definitions.ts +3 -3
  880. package/src/tools/credentials/vault.ts +1 -1
  881. package/src/tools/document/document-tool.ts +124 -1
  882. package/src/tools/filesystem/edit.ts +1 -1
  883. package/src/tools/filesystem/list.ts +1 -1
  884. package/src/tools/filesystem/read.ts +1 -1
  885. package/src/tools/filesystem/write.ts +5 -2
  886. package/src/tools/host-filesystem/transfer.ts +1 -1
  887. package/src/tools/host-terminal/host-shell.ts +1 -1
  888. package/src/tools/memory/register.test.ts +3 -3
  889. package/src/tools/memory/register.ts +9 -1
  890. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  891. package/src/tools/network/web-search.ts +280 -37
  892. package/src/tools/permission-checker.ts +14 -6
  893. package/src/tools/registry.ts +17 -7
  894. package/src/tools/schedule/create.ts +2 -2
  895. package/src/tools/schema-transforms.ts +7 -2
  896. package/src/tools/side-effects.ts +1 -0
  897. package/src/tools/skills/delete-managed.ts +4 -4
  898. package/src/tools/skills/execute.ts +1 -1
  899. package/src/tools/skills/scaffold-managed.ts +3 -2
  900. package/src/tools/subagent/notify-parent.ts +1 -1
  901. package/src/tools/subagent/spawn.ts +3 -3
  902. package/src/tools/system/request-permission.ts +2 -2
  903. package/src/tools/terminal/safe-env.ts +60 -1
  904. package/src/tools/terminal/shell.ts +44 -0
  905. package/src/tools/tool-manifest.ts +2 -0
  906. package/src/tools/types.ts +72 -21
  907. package/src/tools/ui-surface/definitions.ts +6 -5
  908. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  909. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  910. package/src/types/onboarding-context.ts +2 -0
  911. package/src/usage/attribution.ts +3 -2
  912. package/src/util/errors.ts +17 -0
  913. package/src/util/platform.ts +10 -0
  914. package/src/util/pricing.ts +86 -160
  915. package/src/watcher/__tests__/engine.test.ts +323 -0
  916. package/src/watcher/constants.ts +7 -0
  917. package/src/watcher/engine.ts +94 -90
  918. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  919. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  920. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +94 -5
  921. package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
  922. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +117 -0
  923. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +95 -0
  924. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  925. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  926. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  927. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  928. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  929. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  930. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  931. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  932. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  933. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  934. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  935. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  936. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  937. package/src/workspace/migrations/registry.ts +30 -0
  938. package/src/workspace/migrations/runner.ts +46 -5
  939. package/src/workspace/migrations/types.ts +17 -3
  940. package/src/workspace/provider-commit-message-generator.ts +3 -2
  941. package/examples/plugins/echo/bun.lock +0 -25
  942. package/src/__tests__/context-search-pkb-source.test.ts +0 -498
  943. package/src/__tests__/context-window-manager.test.ts +0 -2093
  944. package/src/__tests__/credentials-cli.test.ts +0 -1225
  945. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  946. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  947. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  948. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  949. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  950. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  951. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  952. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  953. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  954. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  955. package/src/cli/commands/autonomy.ts +0 -365
  956. package/src/cli/commands/memory.ts +0 -424
  957. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
  958. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  959. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  960. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  961. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  962. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  963. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  964. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  965. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  966. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  967. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  968. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  969. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  970. package/src/context/prompts/compact.md +0 -26
  971. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  972. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  973. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  974. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  975. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  976. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  977. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  978. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  979. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  980. package/src/home/assistant-feed-authoring.ts +0 -135
  981. package/src/home/emit-feed-event.ts +0 -169
  982. package/src/home/feed-scheduler.ts +0 -281
  983. package/src/home/platform-gmail-digest.ts +0 -163
  984. package/src/home/rewrite-command-preview.ts +0 -66
  985. package/src/home/rewrite-feed-title.ts +0 -58
  986. package/src/home/rollup-producer.ts +0 -426
  987. package/src/memory/admin.ts +0 -326
  988. package/src/memory/context-search/sources/pkb.ts +0 -476
  989. package/src/memory/graph/compaction.ts +0 -299
  990. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  991. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -19,6 +19,7 @@ mock.module("../util/logger.js", () => ({
19
19
  const mockAutoInstall = mock((_skillId: string) => Promise.resolve(false));
20
20
  mock.module("../skills/catalog-install.js", () => ({
21
21
  autoInstallFromCatalog: (skillId: string) => mockAutoInstall(skillId),
22
+ getRepoSkillsDir: () => undefined,
22
23
  resolveCatalog: (_skillId?: string) => Promise.resolve([]),
23
24
  }));
24
25
 
@@ -115,10 +116,6 @@ describe("skill_load tool", () => {
115
116
  "Runs release checks",
116
117
  "1. Run tests",
117
118
  );
118
- writeFileSync(
119
- join(TEST_DIR, "skills", "SKILLS.md"),
120
- "- release-checklist\n",
121
- );
122
119
 
123
120
  const result = await executeSkillLoad({ skill: "release-checklist" });
124
121
  expect(result.isError).toBe(false);
@@ -140,7 +137,6 @@ describe("skill_load tool", () => {
140
137
  "Handles incidents",
141
138
  "Page primary responder",
142
139
  );
143
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- oncall\n");
144
140
 
145
141
  const result = await executeSkillLoad({ skill: "oncall runbook" });
146
142
  expect(result.isError).toBe(false);
@@ -165,10 +161,6 @@ describe("skill_load tool", () => {
165
161
  "Release flow",
166
162
  "Run release checklist",
167
163
  );
168
- writeFileSync(
169
- join(TEST_DIR, "skills", "SKILLS.md"),
170
- "- incident-response\n- release-checklist\n",
171
- );
172
164
 
173
165
  const result = await executeSkillLoad({ skill: "incident" });
174
166
  expect(result.isError).toBe(false);
@@ -182,10 +174,6 @@ describe("skill_load tool", () => {
182
174
  test("returns an error when name resolution is ambiguous", async () => {
183
175
  writeSkill("skill-a", "Shared Name", "First", "Body A");
184
176
  writeSkill("skill-b", "Shared Name", "Second", "Body B");
185
- writeFileSync(
186
- join(TEST_DIR, "skills", "SKILLS.md"),
187
- "- skill-a\n- skill-b\n",
188
- );
189
177
 
190
178
  const result = await executeSkillLoad({ skill: "Shared Name" });
191
179
  expect(result.isError).toBe(true);
@@ -200,7 +188,6 @@ describe("skill_load tool", () => {
200
188
  "Test versioning",
201
189
  "Original body",
202
190
  );
203
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- versioned\n");
204
191
 
205
192
  const result1 = await executeSkillLoad({ skill: "versioned" });
206
193
  const match1 = result1.content.match(
@@ -229,7 +216,6 @@ describe("skill_load tool", () => {
229
216
 
230
217
  test("returns an error when skill is missing", async () => {
231
218
  writeSkill("existing", "Existing Skill", "Exists", "Body");
232
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- existing\n");
233
219
 
234
220
  const result = await executeSkillLoad({ skill: "does-not-exist" });
235
221
  expect(result.isError).toBe(true);
@@ -237,6 +223,32 @@ describe("skill_load tool", () => {
237
223
  expect(result.content).not.toContain("<loaded_skill");
238
224
  });
239
225
 
226
+ test("loads a valid disk-discovered skill omitted from stale SKILLS.md", async () => {
227
+ writeSkill("existing", "Existing Skill", "Exists", "Existing body");
228
+ writeSkill(
229
+ "geo-article-writer",
230
+ "Geo Article Writer",
231
+ "Writes local geo articles",
232
+ "Draft the article.",
233
+ );
234
+ writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- existing\n");
235
+
236
+ const result = await executeSkillLoad({ skill: "geo-article-writer" });
237
+
238
+ expect(result.isError).toBe(false);
239
+ expect(result.content).toContain("ID: geo-article-writer");
240
+ const markers = result.content.match(/<loaded_skill/g) || [];
241
+ expect(markers.length).toBe(1);
242
+ expect(result.content).toMatch(
243
+ /<loaded_skill id="geo-article-writer" version="v1:[a-f0-9]{64}" \/>/,
244
+ );
245
+
246
+ const missing = await executeSkillLoad({ skill: "does-not-exist" });
247
+ expect(missing.isError).toBe(true);
248
+ expect(missing.content).toContain("No skill matched");
249
+ expect(missing.content).not.toContain("<loaded_skill");
250
+ });
251
+
240
252
  test('successful skill_load output shows "none" for skills without includes', async () => {
241
253
  writeSkill(
242
254
  "standalone",
@@ -244,7 +256,6 @@ describe("skill_load tool", () => {
244
256
  "A skill with no children",
245
257
  "Do the thing",
246
258
  );
247
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- standalone\n");
248
259
 
249
260
  const result = await executeSkillLoad({ skill: "standalone" });
250
261
  expect(result.isError).toBe(false);
@@ -258,7 +269,6 @@ describe("skill_load tool", () => {
258
269
  "Should have one marker",
259
270
  "Step 1",
260
271
  );
261
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- single-marker\n");
262
272
 
263
273
  const result = await executeSkillLoad({ skill: "single-marker" });
264
274
  expect(result.isError).toBe(false);
@@ -270,7 +280,6 @@ describe("skill_load tool", () => {
270
280
  writeSkillWithIncludes("parent", "Parent", "Has missing child", "Body", [
271
281
  "missing-child",
272
282
  ]);
273
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- parent\n");
274
283
 
275
284
  const result = await executeSkillLoad({ skill: "parent" });
276
285
  expect(result.isError).toBe(false);
@@ -288,10 +297,6 @@ describe("skill_load tool", () => {
288
297
  writeSkillWithIncludes("skill-b", "Skill B", "Cycles", "Body B", [
289
298
  "skill-a",
290
299
  ]);
291
- writeFileSync(
292
- join(TEST_DIR, "skills", "SKILLS.md"),
293
- "- skill-a\n- skill-b\n",
294
- );
295
300
 
296
301
  const result = await executeSkillLoad({ skill: "skill-a" });
297
302
  expect(result.isError).toBe(true);
@@ -308,10 +313,6 @@ describe("skill_load tool", () => {
308
313
  ["valid-child"],
309
314
  );
310
315
  writeSkill("valid-child", "Valid Child", "A child", "Child body");
311
- writeFileSync(
312
- join(TEST_DIR, "skills", "SKILLS.md"),
313
- "- valid-parent\n- valid-child\n",
314
- );
315
316
 
316
317
  const result = await executeSkillLoad({ skill: "valid-parent" });
317
318
  expect(result.isError).toBe(false);
@@ -326,7 +327,6 @@ describe("skill_load tool", () => {
326
327
  join(skillDir, "SKILL.md"),
327
328
  '---\nname: "Marker Missing"\ndescription: "test"\nmetadata: {"vellum":{"includes":["nonexistent"]}}\n---\n\nBody.\n',
328
329
  );
329
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- marker-missing\n");
330
330
 
331
331
  const result = await executeSkillLoad({ skill: "marker-missing" });
332
332
  expect(result.isError).toBe(false);
@@ -351,10 +351,6 @@ describe("skill_load tool", () => {
351
351
  join(dirB, "SKILL.md"),
352
352
  '---\nname: "Cycle B"\ndescription: "test"\nmetadata: {"vellum":{"includes":["cycle-a"]}}\n---\n\nBody B.\n',
353
353
  );
354
- writeFileSync(
355
- join(TEST_DIR, "skills", "SKILLS.md"),
356
- "- cycle-a\n- cycle-b\n",
357
- );
358
354
 
359
355
  const result = await executeSkillLoad({ skill: "cycle-a" });
360
356
  expect(result.isError).toBe(true);
@@ -364,22 +360,19 @@ describe("skill_load tool", () => {
364
360
 
365
361
  test("succeeds when skill has no includes", async () => {
366
362
  writeSkill("no-includes", "No Includes", "Plain skill", "Body");
367
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- no-includes\n");
368
363
 
369
364
  const result = await executeSkillLoad({ skill: "no-includes" });
370
365
  expect(result.isError).toBe(false);
371
366
  expect(result.content).toContain("Skill: No Includes");
372
367
  });
373
368
 
374
- test("bundled app-builder loads when frontend-design is unavailable", async () => {
369
+ test("bundled app-builder loads without includes", async () => {
375
370
  const result = await executeSkillLoad({ skill: "app-builder" });
376
371
 
377
372
  expect(result.isError).toBe(false);
378
373
  expect(result.content).toContain("Skill: App Builder");
379
- expect(result.content).toContain("Suggested Included Skills (not loaded):");
380
- expect(result.content).toContain("frontend-design");
374
+ expect(result.content).toContain("Included Skills (immediate): none");
381
375
  expect(result.content).toContain('<loaded_skill id="app-builder"');
382
- expect(result.content).not.toContain('<loaded_skill id="frontend-design"');
383
376
  });
384
377
 
385
378
  test("bundled phone-calls loads when setup includes are unavailable", async () => {
@@ -401,10 +394,6 @@ describe("skill_load tool", () => {
401
394
  join(parentDir, "SKILL.md"),
402
395
  '---\nname: "Parent"\ndescription: "Has children"\nmetadata: {"vellum":{"includes":["child-skill"]}}\n---\n\nParent body.\n',
403
396
  );
404
- writeFileSync(
405
- join(TEST_DIR, "skills", "SKILLS.md"),
406
- "- parent-with-children\n- child-skill\n",
407
- );
408
397
 
409
398
  const result = await executeSkillLoad({ skill: "parent-with-children" });
410
399
  expect(result.isError).toBe(false);
@@ -415,7 +404,6 @@ describe("skill_load tool", () => {
415
404
 
416
405
  test('skill_load output shows "none" when no includes', async () => {
417
406
  writeSkill("solo-skill", "Solo", "No children", "Body");
418
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- solo-skill\n");
419
407
 
420
408
  const result = await executeSkillLoad({ skill: "solo-skill" });
421
409
  expect(result.isError).toBe(false);
@@ -437,10 +425,6 @@ describe("skill_load tool", () => {
437
425
  "Parent instructions.",
438
426
  ["e2e-child"],
439
427
  );
440
- writeFileSync(
441
- join(TEST_DIR, "skills", "SKILLS.md"),
442
- "- e2e-parent\n- e2e-child\n",
443
- );
444
428
 
445
429
  // Load the parent
446
430
  const result = await executeSkillLoad({ skill: "e2e-parent" });
@@ -481,10 +465,6 @@ describe("skill_load tool", () => {
481
465
  "Grandparent body",
482
466
  ["child"],
483
467
  );
484
- writeFileSync(
485
- join(TEST_DIR, "skills", "SKILLS.md"),
486
- "- grandparent\n- child\n- grandchild\n",
487
- );
488
468
 
489
469
  const result = await executeSkillLoad({ skill: "grandparent" });
490
470
  expect(result.isError).toBe(false);
@@ -536,10 +516,6 @@ describe("skill_load tool", () => {
536
516
  "Root body",
537
517
  ["branch-a", "branch-b"],
538
518
  );
539
- writeFileSync(
540
- join(TEST_DIR, "skills", "SKILLS.md"),
541
- "- diamond-root\n- branch-a\n- branch-b\n- shared-leaf\n",
542
- );
543
519
 
544
520
  const result = await executeSkillLoad({ skill: "diamond-root" });
545
521
  expect(result.isError).toBe(false);
@@ -578,7 +554,6 @@ describe("skill_load tool", () => {
578
554
  "Body",
579
555
  ["self-ref"],
580
556
  );
581
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- self-ref\n");
582
557
 
583
558
  const result = await executeSkillLoad({ skill: "self-ref" });
584
559
  expect(result.isError).toBe(true);
@@ -603,7 +578,6 @@ describe("skill_load tool", () => {
603
578
  join(skillDir, "references", "TROUBLESHOOTING.md"),
604
579
  "# Troubleshooting\n\nFix things here.",
605
580
  );
606
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- with-refs\n");
607
581
 
608
582
  const result = await executeSkillLoad({ skill: "with-refs" });
609
583
  expect(result.isError).toBe(false);
@@ -626,7 +600,6 @@ describe("skill_load tool", () => {
626
600
 
627
601
  test("skill without references/ directory loads normally", async () => {
628
602
  writeSkill("no-refs", "No Refs", "No references dir", "Just body.");
629
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- no-refs\n");
630
603
 
631
604
  const result = await executeSkillLoad({ skill: "no-refs" });
632
605
  expect(result.isError).toBe(false);
@@ -652,8 +625,6 @@ describe("skill_load tool", () => {
652
625
  writeFileSync(outsideSecretPath, "TOP_SECRET_DO_NOT_LOAD");
653
626
  symlinkSync(outsideSecretPath, join(skillDir, "references", "secret.md"));
654
627
 
655
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- refs-symlink\n");
656
-
657
628
  const result = await executeSkillLoad({ skill: "refs-symlink" });
658
629
  expect(result.isError).toBe(false);
659
630
  expect(result.content).toContain("Body.");
@@ -677,7 +648,6 @@ describe("skill_load tool", () => {
677
648
  join(skillDir, "references", "data.json"),
678
649
  '{"key": "value"}',
679
650
  );
680
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- refs-filter\n");
681
651
 
682
652
  const result = await executeSkillLoad({ skill: "refs-filter" });
683
653
  expect(result.isError).toBe(false);
@@ -697,7 +667,6 @@ describe("skill_load tool", () => {
697
667
  join(skillDir, "SKILL.md"),
698
668
  '---\nname: "Empty Includes"\ndescription: "Has empty array"\nmetadata: {"vellum":{"includes":[]}}\n---\n\nBody.\n',
699
669
  );
700
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- empty-includes\n");
701
670
 
702
671
  const result = await executeSkillLoad({ skill: "empty-includes" });
703
672
  expect(result.isError).toBe(false);
@@ -748,11 +717,6 @@ describe("skill_load tool", () => {
748
717
  },
749
718
  },
750
719
  ]);
751
- writeFileSync(
752
- join(TEST_DIR, "skills", "SKILLS.md"),
753
- "- skill-with-tools\n",
754
- );
755
-
756
720
  const result = await executeSkillLoad({ skill: "skill-with-tools" });
757
721
  expect(result.isError).toBe(false);
758
722
 
@@ -786,7 +750,6 @@ describe("skill_load tool", () => {
786
750
 
787
751
  test("skill without TOOLS.json does not include tool schemas section", async () => {
788
752
  writeSkill("no-tools", "No Tools", "No tools manifest", "Body.");
789
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- no-tools\n");
790
753
 
791
754
  const result = await executeSkillLoad({ skill: "no-tools" });
792
755
  expect(result.isError).toBe(false);
@@ -819,10 +782,6 @@ describe("skill_load tool", () => {
819
782
  },
820
783
  },
821
784
  ]);
822
- writeFileSync(
823
- join(TEST_DIR, "skills", "SKILLS.md"),
824
- "- parent-tools\n- child-tools\n",
825
- );
826
785
 
827
786
  const result = await executeSkillLoad({ skill: "parent-tools" });
828
787
  expect(result.isError).toBe(false);
@@ -847,17 +806,11 @@ describe("skill_load tool", () => {
847
806
  "Parent body",
848
807
  ["dep-a"],
849
808
  );
850
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- auto-parent\n");
851
809
 
852
810
  // Mock autoInstallFromCatalog to succeed and write the skill to disk
853
811
  mockAutoInstall.mockImplementation((skillId: string) => {
854
812
  if (skillId === "dep-a") {
855
813
  writeSkill("dep-a", "Dep A", "A dependency", "Dep A body");
856
- // Add to SKILLS.md so catalog reload finds it
857
- writeFileSync(
858
- join(TEST_DIR, "skills", "SKILLS.md"),
859
- "- auto-parent\n- dep-a\n",
860
- );
861
814
  return Promise.resolve(true);
862
815
  }
863
816
  return Promise.resolve(false);
@@ -875,7 +828,6 @@ describe("skill_load tool", () => {
875
828
  writeSkillWithIncludes("trans-a", "Trans A", "Top level", "Body A", [
876
829
  "trans-b",
877
830
  ]);
878
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- trans-a\n");
879
831
 
880
832
  let round = 0;
881
833
  mockAutoInstall.mockImplementation((skillId: string) => {
@@ -884,20 +836,12 @@ describe("skill_load tool", () => {
884
836
  writeSkillWithIncludes("trans-b", "Trans B", "Mid level", "Body B", [
885
837
  "trans-c",
886
838
  ]);
887
- writeFileSync(
888
- join(TEST_DIR, "skills", "SKILLS.md"),
889
- "- trans-a\n- trans-b\n",
890
- );
891
839
  round++;
892
840
  return Promise.resolve(true);
893
841
  }
894
842
  if (skillId === "trans-c") {
895
843
  // Second round: install C
896
844
  writeSkill("trans-c", "Trans C", "Leaf", "Body C");
897
- writeFileSync(
898
- join(TEST_DIR, "skills", "SKILLS.md"),
899
- "- trans-a\n- trans-b\n- trans-c\n",
900
- );
901
845
  return Promise.resolve(true);
902
846
  }
903
847
  return Promise.resolve(false);
@@ -919,7 +863,6 @@ describe("skill_load tool", () => {
919
863
  "Body",
920
864
  ["dep-x"],
921
865
  );
922
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- fail-parent\n");
923
866
 
924
867
  // autoInstallFromCatalog throws an error
925
868
  mockAutoInstall.mockImplementation((skillId: string) => {
@@ -943,7 +886,6 @@ describe("skill_load tool", () => {
943
886
  writeSkillWithIncludes("loop-root", "Loop Root", "Infinite deps", "Body", [
944
887
  "loop-dep-0",
945
888
  ]);
946
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- loop-root\n");
947
889
 
948
890
  let installCount = 0;
949
891
  mockAutoInstall.mockImplementation((skillId: string) => {
@@ -959,12 +901,6 @@ describe("skill_load tool", () => {
959
901
  "Body",
960
902
  [nextDepId],
961
903
  );
962
- // Update SKILLS.md to include all installed deps so far
963
- const entries = ["- loop-root\n"];
964
- for (let i = 0; i < installCount; i++) {
965
- entries.push(`- loop-dep-${i}\n`);
966
- }
967
- writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), entries.join(""));
968
904
  return Promise.resolve(true);
969
905
  }
970
906
  return Promise.resolve(false);
@@ -3,9 +3,7 @@ import { describe, expect, test } from "bun:test";
3
3
  import type { SkillSummary } from "../config/skills.js";
4
4
  import { fromSkillSummary } from "../skills/skill-memory.js";
5
5
 
6
- function makeSkillSummary(
7
- overrides: Partial<SkillSummary> = {},
8
- ): SkillSummary {
6
+ function makeSkillSummary(overrides: Partial<SkillSummary> = {}): SkillSummary {
9
7
  return {
10
8
  id: "test-skill",
11
9
  name: "test-skill",
@@ -62,4 +60,26 @@ describe("fromSkillSummary", () => {
62
60
  expect(input.id).toBe("my-id");
63
61
  expect(input.description).toBe("Does amazing things");
64
62
  });
63
+
64
+ test("maps custom managed skill metadata required by Memory V2 rendering", () => {
65
+ const entry = makeSkillSummary({
66
+ id: "geo-article-writer",
67
+ name: "geo-article-writer",
68
+ displayName: "Geo Article Writer",
69
+ description: "Writes local geo articles",
70
+ source: "managed",
71
+ activationHints: ["user asks for local article drafts"],
72
+ avoidWhen: ["user only wants citation extraction"],
73
+ });
74
+
75
+ const input = fromSkillSummary(entry);
76
+
77
+ expect(input).toEqual({
78
+ id: "geo-article-writer",
79
+ displayName: "Geo Article Writer",
80
+ description: "Writes local geo articles",
81
+ activationHints: ["user asks for local article drafts"],
82
+ avoidWhen: ["user only wants citation extraction"],
83
+ });
84
+ });
65
85
  });
@@ -199,7 +199,6 @@ mock.module("../skills/skill-file-provider.js", () => ({}));
199
199
 
200
200
  mock.module("../skills/catalog-install.js", () => ({
201
201
  installSkillLocally: async () => {},
202
- upsertSkillsIndex: () => {},
203
202
  getRepoSkillsDir: () => undefined,
204
203
  }));
205
204
 
@@ -230,7 +229,6 @@ mock.module("../skills/install-meta.js", () => ({
230
229
  mock.module("../skills/managed-store.js", () => ({
231
230
  createManagedSkill: () => ({ created: true }),
232
231
  deleteManagedSkill: () => ({ deleted: true }),
233
- removeSkillsIndexEntry: () => {},
234
232
  validateManagedSkillId: () => null,
235
233
  }));
236
234
 
@@ -412,10 +410,7 @@ describe("getSkillFileContent — installed skill", () => {
412
410
  mockResolvedSkills = [installedSkill("my-skill", skillDir)];
413
411
  installFetchForbidden();
414
412
 
415
- const result = await getSkillFileContent(
416
- "my-skill",
417
- "SKILL.md\0.png",
418
- );
413
+ const result = await getSkillFileContent("my-skill", "SKILL.md\0.png");
419
414
  expect("error" in result).toBe(true);
420
415
  if (!("error" in result)) return;
421
416
  expect(result.status).toBe(400);
@@ -458,10 +453,7 @@ describe("getSkillFileContent — uninstalled skill (provider chain)", () => {
458
453
  toSlimSkill: async () => null,
459
454
  };
460
455
 
461
- const result = await getSkillFileContent(
462
- "remote-skill",
463
- "SKILL.md",
464
- );
456
+ const result = await getSkillFileContent("remote-skill", "SKILL.md");
465
457
  expect("error" in result).toBe(false);
466
458
  if ("error" in result) return;
467
459
  expect(result.path).toBe("SKILL.md");
@@ -478,10 +470,7 @@ describe("getSkillFileContent — uninstalled skill (provider chain)", () => {
478
470
 
479
471
  // All providers return canHandle=false (default noop)
480
472
 
481
- const result = await getSkillFileContent(
482
- "ghost-skill",
483
- "SKILL.md",
484
- );
473
+ const result = await getSkillFileContent("ghost-skill", "SKILL.md");
485
474
  expect("error" in result).toBe(true);
486
475
  if (!("error" in result)) return;
487
476
  expect(result.status).toBe(404);
@@ -510,10 +499,7 @@ describe("getSkillFileContent — uninstalled skill (provider chain)", () => {
510
499
  toSlimSkill: async () => null,
511
500
  };
512
501
 
513
- const result = await getSkillFileContent(
514
- "owner/repo/my-skill",
515
- "SKILL.md",
516
- );
502
+ const result = await getSkillFileContent("owner/repo/my-skill", "SKILL.md");
517
503
  expect("error" in result).toBe(false);
518
504
  if ("error" in result) return;
519
505
  expect(result.content).toBe("# skillssh content\n");
@@ -562,10 +548,7 @@ describe("getSkillFileContent — uninstalled skill (provider chain)", () => {
562
548
  toSlimSkill: async () => null,
563
549
  };
564
550
 
565
- const result = await getSkillFileContent(
566
- "known-skill",
567
- "nonexistent.txt",
568
- );
551
+ const result = await getSkillFileContent("known-skill", "nonexistent.txt");
569
552
  expect("error" in result).toBe(true);
570
553
  if (!("error" in result)) return;
571
554
  expect(result.status).toBe(404);
@@ -604,10 +587,7 @@ describe("getSkillFileContent — uninstalled skill (provider chain)", () => {
604
587
  toSlimSkill: async () => null,
605
588
  };
606
589
 
607
- const result = await getSkillFileContent(
608
- "simple-slug",
609
- "SKILL.md",
610
- );
590
+ const result = await getSkillFileContent("simple-slug", "SKILL.md");
611
591
  // Should be "File not found" (vellum handled but returned null)
612
592
  expect("error" in result).toBe(true);
613
593
  if (!("error" in result)) return;
@@ -626,10 +606,7 @@ describe("getSkillFileContent — skill not found", () => {
626
606
  mockResolvedSkills = [];
627
607
  installFetchForbidden();
628
608
 
629
- const result = await getSkillFileContent(
630
- "ghost-skill",
631
- "SKILL.md",
632
- );
609
+ const result = await getSkillFileContent("ghost-skill", "SKILL.md");
633
610
  expect("error" in result).toBe(true);
634
611
  if (!("error" in result)) return;
635
612
  expect(result.status).toBe(404);
@@ -666,10 +643,7 @@ describe("getSkillFileContent — installed skill with missing directory", () =>
666
643
  };
667
644
  installFetchForbidden();
668
645
 
669
- const result = await getSkillFileContent(
670
- "ghost-installed",
671
- "SKILL.md",
672
- );
646
+ const result = await getSkillFileContent("ghost-installed", "SKILL.md");
673
647
 
674
648
  expect("error" in result).toBe(true);
675
649
  if (!("error" in result)) return;
@@ -766,10 +740,7 @@ describe("getSkillFileContent — hidden / SKIP_DIRS rejection", () => {
766
740
  mockResolvedSkills = [installedSkill("healthy-skill", skillDir)];
767
741
  installFetchForbidden();
768
742
 
769
- const result = await getSkillFileContent(
770
- "healthy-skill",
771
- "SKILL.md",
772
- );
743
+ const result = await getSkillFileContent("healthy-skill", "SKILL.md");
773
744
  expect("error" in result).toBe(false);
774
745
  if ("error" in result) return;
775
746
  expect(result.content).toBe("# hello\n");
@@ -164,7 +164,6 @@ mock.module("../skills/skill-file-provider.js", () => ({}));
164
164
 
165
165
  mock.module("../skills/catalog-install.js", () => ({
166
166
  installSkillLocally: async () => {},
167
- upsertSkillsIndex: () => {},
168
167
  }));
169
168
 
170
169
  mock.module("../skills/catalog-search.js", () => ({
@@ -188,7 +187,6 @@ mock.module("../skills/skillssh-registry.js", () => ({
188
187
  mock.module("../skills/managed-store.js", () => ({
189
188
  createManagedSkill: () => ({ created: true }),
190
189
  deleteManagedSkill: () => ({ deleted: true }),
191
- removeSkillsIndexEntry: () => {},
192
190
  validateManagedSkillId: () => null,
193
191
  }));
194
192
 
@@ -238,7 +236,6 @@ import {
238
236
  // Helpers
239
237
  // ---------------------------------------------------------------------------
240
238
 
241
-
242
239
  function makeSummary(overrides: Partial<SkillSummary>): SkillSummary {
243
240
  return {
244
241
  id: overrides.id ?? "summary-id",
@@ -3,47 +3,14 @@ import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
5
5
 
6
- import { extractTarToDir } from "../skills/catalog-install.js";
6
+ import {
7
+ extractTarToDir,
8
+ writeSkillFilesToDir,
9
+ } from "../skills/catalog-install.js";
10
+ import { makeTar } from "./helpers/tar-fixtures.js";
7
11
 
8
12
  let tempDir: string;
9
13
 
10
- function makeTarEntry(name: string, content: string): Buffer {
11
- const header = Buffer.alloc(512, 0);
12
- const nameBuffer = Buffer.from(name, "utf-8");
13
- nameBuffer.copy(header, 0, 0, Math.min(nameBuffer.length, 100));
14
-
15
- const mode = Buffer.from("0000644\0", "ascii");
16
- mode.copy(header, 100);
17
- Buffer.from("0000000\0", "ascii").copy(header, 108); // uid
18
- Buffer.from("0000000\0", "ascii").copy(header, 116); // gid
19
-
20
- const sizeOct = content.length.toString(8).padStart(11, "0") + "\0";
21
- Buffer.from(sizeOct, "ascii").copy(header, 124);
22
-
23
- Buffer.from("00000000000\0", "ascii").copy(header, 136); // mtime
24
- Buffer.from(" ", "ascii").copy(header, 148); // checksum placeholder
25
- header[156] = "0".charCodeAt(0);
26
- Buffer.from("ustar\0", "ascii").copy(header, 257);
27
- Buffer.from("00", "ascii").copy(header, 263);
28
-
29
- let sum = 0;
30
- for (let i = 0; i < 512; i += 1) sum += header[i] ?? 0;
31
- const checksum = sum.toString(8).padStart(6, "0");
32
- Buffer.from(`${checksum}\0 `, "ascii").copy(header, 148);
33
-
34
- const data = Buffer.from(content, "utf-8");
35
- const paddedSize = Math.ceil(data.length / 512) * 512;
36
- const padded = Buffer.alloc(paddedSize, 0);
37
- data.copy(padded);
38
-
39
- return Buffer.concat([header, padded]);
40
- }
41
-
42
- function makeTar(entries: Array<{ name: string; content: string }>): Buffer {
43
- const body = entries.map((entry) => makeTarEntry(entry.name, entry.content));
44
- return Buffer.concat([...body, Buffer.alloc(1024, 0)]);
45
- }
46
-
47
14
  beforeEach(() => {
48
15
  tempDir = join(
49
16
  tmpdir(),
@@ -90,4 +57,48 @@ describe("extractTarToDir", () => {
90
57
  expect(existsSync(join(tempDir, "windows.txt"))).toBe(false);
91
58
  expect(readFileSync(join(tempDir, "SKILL.md"), "utf-8")).toBe("# demo\n");
92
59
  });
60
+
61
+ test("does not count nested SKILL.md as a valid skill root", () => {
62
+ const tar = makeTar([
63
+ { name: "nested/SKILL.md", content: "# nested\n" },
64
+ { name: "README.md", content: "# wrapper\n" },
65
+ ]);
66
+
67
+ const foundSkillMd = extractTarToDir(tar, tempDir);
68
+
69
+ expect(foundSkillMd).toBe(false);
70
+ expect(existsSync(join(tempDir, "SKILL.md"))).toBe(false);
71
+ expect(readFileSync(join(tempDir, "nested", "SKILL.md"), "utf-8")).toBe(
72
+ "# nested\n",
73
+ );
74
+ });
75
+
76
+ test("normalizes safe relative segments before top-level SKILL.md detection", () => {
77
+ const tar = makeTar([{ name: "wrapper/../SKILL.md", content: "# demo\n" }]);
78
+
79
+ const foundSkillMd = extractTarToDir(tar, tempDir);
80
+
81
+ expect(foundSkillMd).toBe(true);
82
+ expect(readFileSync(join(tempDir, "SKILL.md"), "utf-8")).toBe("# demo\n");
83
+ });
84
+ });
85
+
86
+ describe("writeSkillFilesToDir", () => {
87
+ test("uses the same traversal rules as tar extraction", () => {
88
+ const foundSkillMd = writeSkillFilesToDir(
89
+ {
90
+ "./SKILL.md": "# demo\n",
91
+ "scripts/../notes.md": "ok\n",
92
+ "../../escape.txt": "nope\n",
93
+ "/absolute.txt": "nope\n",
94
+ },
95
+ tempDir,
96
+ );
97
+
98
+ expect(foundSkillMd).toBe(true);
99
+ expect(readFileSync(join(tempDir, "SKILL.md"), "utf-8")).toBe("# demo\n");
100
+ expect(readFileSync(join(tempDir, "notes.md"), "utf-8")).toBe("ok\n");
101
+ expect(existsSync(join(tempDir, "escape.txt"))).toBe(false);
102
+ expect(existsSync(join(tempDir, "absolute.txt"))).toBe(false);
103
+ });
93
104
  });