@vellumai/assistant 0.6.0 → 0.6.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 (358) hide show
  1. package/AGENTS.md +4 -0
  2. package/ARCHITECTURE.md +68 -15
  3. package/Dockerfile +2 -2
  4. package/bun.lock +6 -2
  5. package/docker-entrypoint.sh +42 -1
  6. package/docs/architecture/integrations.md +1 -1
  7. package/docs/architecture/memory.md +21 -24
  8. package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
  9. package/openapi.yaml +539 -4
  10. package/package.json +5 -1
  11. package/src/__tests__/anthropic-provider.test.ts +160 -95
  12. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  13. package/src/__tests__/app-executors.test.ts +47 -1
  14. package/src/__tests__/app-source-watcher.test.ts +159 -0
  15. package/src/__tests__/assistant-event-hub.test.ts +30 -0
  16. package/src/__tests__/checker.test.ts +138 -172
  17. package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
  18. package/src/__tests__/config-schema.test.ts +5 -0
  19. package/src/__tests__/context-overflow-approval.test.ts +5 -5
  20. package/src/__tests__/conversation-agent-loop-overflow.test.ts +4 -6
  21. package/src/__tests__/conversation-agent-loop.test.ts +4 -51
  22. package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
  23. package/src/__tests__/conversation-directories-parse.test.ts +105 -0
  24. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  25. package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
  26. package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
  27. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
  28. package/src/__tests__/conversation-wipe.test.ts +2 -6
  29. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
  30. package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
  31. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  32. package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
  33. package/src/__tests__/credential-execution-approval-bridge.test.ts +0 -2
  34. package/src/__tests__/date-context.test.ts +76 -210
  35. package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
  36. package/src/__tests__/file-list-tool.test.ts +219 -0
  37. package/src/__tests__/first-greeting.test.ts +1 -1
  38. package/src/__tests__/heartbeat-service.test.ts +180 -3
  39. package/src/__tests__/identity-routes.test.ts +328 -0
  40. package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
  41. package/src/__tests__/injection-block.test.ts +24 -0
  42. package/src/__tests__/inline-command-runner.test.ts +7 -5
  43. package/src/__tests__/install-skill-routing.test.ts +7 -6
  44. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +15 -14
  45. package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
  46. package/src/__tests__/llm-context-normalization.test.ts +18 -18
  47. package/src/__tests__/llm-context-route-provider.test.ts +101 -0
  48. package/src/__tests__/llm-request-log-turn-query.test.ts +162 -0
  49. package/src/__tests__/log-export-workspace.test.ts +257 -100
  50. package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
  51. package/src/__tests__/mcp-abort-signal.test.ts +5 -0
  52. package/src/__tests__/mcp-client-auth.test.ts +5 -0
  53. package/src/__tests__/memory-recall-log-store.test.ts +132 -0
  54. package/src/__tests__/migration-export-streaming.test.ts +304 -0
  55. package/src/__tests__/migration-import-commit-http.test.ts +11 -10
  56. package/src/__tests__/mock-fetch.ts +87 -0
  57. package/src/__tests__/navigate-settings-tab.test.ts +14 -1
  58. package/src/__tests__/notification-broadcaster.test.ts +65 -0
  59. package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
  60. package/src/__tests__/onboarding-template-contract.test.ts +63 -14
  61. package/src/__tests__/parser.test.ts +32 -0
  62. package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
  63. package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
  64. package/src/__tests__/permission-mode-sse.test.ts +418 -0
  65. package/src/__tests__/permission-mode-store.test.ts +277 -0
  66. package/src/__tests__/permission-mode.test.ts +101 -0
  67. package/src/__tests__/pkb-autoinject.test.ts +96 -0
  68. package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
  69. package/src/__tests__/profiler-routes.test.ts +502 -0
  70. package/src/__tests__/profiler-run-store.test.ts +441 -0
  71. package/src/__tests__/proxy-approval-callback.test.ts +4 -75
  72. package/src/__tests__/registry.test.ts +1 -1
  73. package/src/__tests__/require-fresh-approval.test.ts +0 -2
  74. package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
  75. package/src/__tests__/sandbox-host-parity.test.ts +5 -4
  76. package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
  77. package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
  78. package/src/__tests__/search-skills-unified.test.ts +4 -3
  79. package/src/__tests__/send-endpoint-busy.test.ts +42 -3
  80. package/src/__tests__/set-permission-mode.test.ts +274 -0
  81. package/src/__tests__/skill-load-feature-flag.test.ts +12 -0
  82. package/src/__tests__/skill-memory.test.ts +2 -783
  83. package/src/__tests__/strip-memory-injections.test.ts +187 -0
  84. package/src/__tests__/subagent-detail.test.ts +84 -0
  85. package/src/__tests__/subagent-disposal.test.ts +308 -0
  86. package/src/__tests__/subagent-manager-notify.test.ts +19 -10
  87. package/src/__tests__/subagent-notify-parent.test.ts +390 -0
  88. package/src/__tests__/subagent-role-registry.test.ts +108 -0
  89. package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
  90. package/src/__tests__/subagent-tools.test.ts +464 -4
  91. package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
  92. package/src/__tests__/task-memory-cleanup.test.ts +12 -12
  93. package/src/__tests__/terminal-sandbox.test.ts +1 -1
  94. package/src/__tests__/terminal-tools.test.ts +16 -29
  95. package/src/__tests__/test-preload.ts +18 -0
  96. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
  97. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
  98. package/src/__tests__/tool-executor.test.ts +4 -27
  99. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  100. package/src/__tests__/top-level-renderer.test.ts +10 -13
  101. package/src/__tests__/transport-hints-queue.test.ts +77 -0
  102. package/src/__tests__/trust-store.test.ts +4 -4
  103. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +116 -2
  104. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
  105. package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
  106. package/src/__tests__/workspace-policy.test.ts +2 -7
  107. package/src/agent/loop.ts +6 -29
  108. package/src/approvals/guardian-request-resolvers.ts +24 -0
  109. package/src/avatar/traits-png-sync.ts +3 -3
  110. package/src/channels/types.ts +5 -0
  111. package/src/cli/__tests__/run-assistant-command.ts +56 -0
  112. package/src/cli/__tests__/unknown-command.test.ts +33 -0
  113. package/src/cli/commands/__tests__/email-download.test.ts +245 -0
  114. package/src/cli/commands/__tests__/email-list.test.ts +192 -0
  115. package/src/cli/commands/__tests__/email-register.test.ts +186 -0
  116. package/src/cli/commands/__tests__/email-send.test.ts +291 -0
  117. package/src/cli/commands/__tests__/email-status.test.ts +181 -0
  118. package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
  119. package/src/cli/commands/__tests__/routes.test.ts +562 -0
  120. package/src/cli/commands/conversations.ts +1 -8
  121. package/src/cli/commands/default-action.ts +68 -1
  122. package/src/cli/commands/email.ts +584 -835
  123. package/src/cli/commands/memory.ts +1 -34
  124. package/src/cli/commands/notifications.ts +7 -2
  125. package/src/cli/commands/oauth/__tests__/connect.test.ts +27 -0
  126. package/src/cli/commands/oauth/connect.ts +25 -5
  127. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  128. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  129. package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
  130. package/src/cli/commands/routes.ts +396 -0
  131. package/src/cli/commands/skills.ts +130 -20
  132. package/src/cli/program.ts +11 -2
  133. package/src/cli.ts +1 -120
  134. package/src/config/assistant-feature-flags.ts +59 -55
  135. package/src/config/bundled-skills/app-builder/SKILL.md +91 -5
  136. package/src/config/bundled-skills/gmail/SKILL.md +13 -8
  137. package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
  138. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
  139. package/src/config/bundled-skills/messaging/SKILL.md +7 -0
  140. package/src/config/bundled-skills/schedule/SKILL.md +22 -2
  141. package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
  142. package/src/config/bundled-skills/settings/TOOLS.json +1 -1
  143. package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
  144. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
  145. package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
  146. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
  147. package/src/config/bundled-skills/slack/SKILL.md +2 -0
  148. package/src/config/bundled-skills/subagent/SKILL.md +43 -3
  149. package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
  150. package/src/config/env-registry.ts +63 -0
  151. package/src/config/feature-flag-registry.json +17 -1
  152. package/src/config/schema.ts +8 -0
  153. package/src/config/schemas/filing.ts +51 -0
  154. package/src/config/schemas/heartbeat.ts +15 -12
  155. package/src/config/schemas/memory-lifecycle.ts +12 -0
  156. package/src/config/schemas/security.ts +14 -0
  157. package/src/config/schemas/services.ts +8 -0
  158. package/src/credential-execution/approval-bridge.ts +0 -1
  159. package/src/credential-execution/managed-catalog.ts +3 -7
  160. package/src/daemon/app-source-watcher.ts +93 -0
  161. package/src/daemon/config-watcher.ts +85 -3
  162. package/src/daemon/context-overflow-approval.ts +0 -1
  163. package/src/daemon/conversation-agent-loop-handlers.ts +20 -0
  164. package/src/daemon/conversation-agent-loop.ts +179 -65
  165. package/src/daemon/conversation-attachments.ts +0 -1
  166. package/src/daemon/conversation-history.ts +4 -19
  167. package/src/daemon/conversation-lifecycle.ts +8 -14
  168. package/src/daemon/conversation-messaging.ts +3 -0
  169. package/src/daemon/conversation-process.ts +30 -8
  170. package/src/daemon/conversation-queue-manager.ts +8 -0
  171. package/src/daemon/conversation-runtime-assembly.ts +359 -308
  172. package/src/daemon/conversation-surfaces.ts +65 -0
  173. package/src/daemon/conversation-tool-setup.ts +44 -17
  174. package/src/daemon/conversation-workspace.ts +1 -2
  175. package/src/daemon/conversation.ts +19 -3
  176. package/src/daemon/date-context.ts +26 -53
  177. package/src/daemon/first-greeting.ts +1 -1
  178. package/src/daemon/handlers/conversations.ts +5 -7
  179. package/src/daemon/handlers/shared.test.ts +143 -0
  180. package/src/daemon/handlers/shared.ts +70 -5
  181. package/src/daemon/handlers/skills.ts +11 -18
  182. package/src/daemon/lifecycle.ts +220 -158
  183. package/src/daemon/message-types/conversations.ts +29 -6
  184. package/src/daemon/message-types/messages.ts +9 -2
  185. package/src/daemon/message-types/notifications.ts +12 -0
  186. package/src/daemon/message-types/schedules.ts +1 -0
  187. package/src/daemon/message-types/settings.ts +18 -0
  188. package/src/daemon/profiler-run-store.ts +557 -0
  189. package/src/daemon/server.ts +87 -10
  190. package/src/daemon/shutdown-handlers.ts +5 -0
  191. package/src/daemon/tool-side-effects.ts +23 -3
  192. package/src/daemon/transport-hints.ts +33 -0
  193. package/src/export/transcript-formatter.ts +148 -0
  194. package/src/filing/filing-service.ts +228 -0
  195. package/src/heartbeat/heartbeat-service.ts +96 -7
  196. package/src/index.ts +1 -1
  197. package/src/mcp/client.ts +6 -0
  198. package/src/mcp/mcp-oauth-provider.ts +149 -27
  199. package/src/memory/admin.ts +33 -32
  200. package/src/memory/app-store.ts +69 -0
  201. package/src/memory/conversation-bootstrap.ts +1 -1
  202. package/src/memory/conversation-crud.ts +151 -117
  203. package/src/memory/conversation-directories.ts +39 -0
  204. package/src/memory/conversation-group-migration.ts +66 -6
  205. package/src/memory/conversation-queries.ts +58 -12
  206. package/src/memory/conversation-title-service.ts +1 -0
  207. package/src/memory/db-init.ts +182 -376
  208. package/src/memory/embedding-local.ts +1 -1
  209. package/src/memory/graph/bootstrap.ts +75 -66
  210. package/src/memory/graph/capability-seed.ts +167 -17
  211. package/src/memory/graph/consolidation.ts +38 -4
  212. package/src/memory/graph/conversation-graph-memory.ts +133 -104
  213. package/src/memory/graph/extraction-job.ts +9 -4
  214. package/src/memory/graph/extraction.ts +66 -23
  215. package/src/memory/graph/graph-memory-state-store.ts +37 -0
  216. package/src/memory/graph/graph-search.ts +29 -15
  217. package/src/memory/graph/injection.ts +38 -8
  218. package/src/memory/graph/inspect.ts +12 -3
  219. package/src/memory/graph/retriever.ts +365 -262
  220. package/src/memory/graph/store.test.ts +48 -0
  221. package/src/memory/graph/store.ts +150 -11
  222. package/src/memory/graph/tool-handlers.ts +84 -209
  223. package/src/memory/graph/tools.ts +8 -52
  224. package/src/memory/graph/types.ts +24 -0
  225. package/src/memory/group-crud.ts +25 -9
  226. package/src/memory/job-handlers/cleanup.ts +44 -1
  227. package/src/memory/jobs-store.ts +70 -60
  228. package/src/memory/jobs-worker.ts +44 -28
  229. package/src/memory/llm-request-log-store.ts +96 -12
  230. package/src/memory/memory-recall-log-store.ts +49 -5
  231. package/src/memory/migrations/203-drop-memory-items-tables.ts +33 -1
  232. package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
  233. package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
  234. package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
  235. package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
  236. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
  237. package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
  238. package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
  239. package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
  240. package/src/memory/migrations/index.ts +8 -0
  241. package/src/memory/migrations/registry.ts +8 -0
  242. package/src/memory/schema/conversations.ts +14 -0
  243. package/src/memory/schema/infrastructure.ts +8 -1
  244. package/src/memory/schema/memory-core.ts +0 -51
  245. package/src/memory/schema/memory-graph.ts +15 -0
  246. package/src/memory/task-memory-cleanup.ts +30 -11
  247. package/src/messaging/provider.ts +1 -1
  248. package/src/notifications/broadcaster.ts +6 -0
  249. package/src/notifications/conversation-pairing.ts +12 -4
  250. package/src/notifications/copy-composer.ts +86 -0
  251. package/src/notifications/decision-engine.ts +35 -0
  252. package/src/notifications/emit-signal.ts +14 -0
  253. package/src/notifications/signal.ts +11 -0
  254. package/src/oauth/platform-connection.test.ts +2 -2
  255. package/src/oauth/seed-providers.ts +1 -0
  256. package/src/permissions/checker.ts +15 -4
  257. package/src/permissions/defaults.ts +7 -8
  258. package/src/permissions/permission-mode-store.ts +180 -0
  259. package/src/permissions/permission-mode.ts +31 -0
  260. package/src/permissions/prompter.ts +0 -2
  261. package/src/permissions/workspace-policy.ts +9 -0
  262. package/src/platform/client.ts +1 -1
  263. package/src/prompts/system-prompt.ts +59 -7
  264. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
  265. package/src/prompts/templates/BOOTSTRAP.md +76 -162
  266. package/src/prompts/templates/HEARTBEAT.md +3 -1
  267. package/src/prompts/templates/SOUL.md +30 -9
  268. package/src/prompts/templates/UPDATES.md +8 -0
  269. package/src/providers/anthropic/client.ts +107 -219
  270. package/src/runtime/assistant-event-hub.ts +22 -0
  271. package/src/runtime/auth/route-policy.ts +23 -0
  272. package/src/runtime/auth/token-service.ts +8 -0
  273. package/src/runtime/http-server.ts +32 -2
  274. package/src/runtime/http-types.ts +12 -1
  275. package/src/runtime/migrations/vbundle-builder.ts +389 -3
  276. package/src/runtime/migrations/vbundle-importer.ts +8 -6
  277. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
  278. package/src/runtime/routes/app-management-routes.ts +1 -11
  279. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
  280. package/src/runtime/routes/archive-utils.ts +29 -0
  281. package/src/runtime/routes/avatar-routes.ts +2 -9
  282. package/src/runtime/routes/btw-routes.ts +14 -1
  283. package/src/runtime/routes/conversation-analysis-routes.ts +185 -0
  284. package/src/runtime/routes/conversation-management-routes.ts +1 -14
  285. package/src/runtime/routes/conversation-query-routes.ts +49 -3
  286. package/src/runtime/routes/conversation-routes.ts +270 -44
  287. package/src/runtime/routes/group-routes.ts +22 -8
  288. package/src/runtime/routes/heartbeat-routes.ts +4 -10
  289. package/src/runtime/routes/identity-routes.ts +53 -18
  290. package/src/runtime/routes/llm-context-normalization.ts +14 -10
  291. package/src/runtime/routes/log-export/AGENTS.md +104 -0
  292. package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
  293. package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
  294. package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
  295. package/src/runtime/routes/log-export-routes.ts +41 -278
  296. package/src/runtime/routes/memory-item-routes.test.ts +168 -233
  297. package/src/runtime/routes/migration-routes.ts +18 -7
  298. package/src/runtime/routes/profiler-routes.ts +350 -0
  299. package/src/runtime/routes/schedule-routes.ts +27 -12
  300. package/src/runtime/routes/settings-routes.ts +95 -8
  301. package/src/runtime/routes/subagents-routes.ts +28 -7
  302. package/src/runtime/routes/user-route-dispatcher.ts +223 -0
  303. package/src/runtime/routes/user-routes.ts +41 -0
  304. package/src/runtime/routes/workspace-routes.ts +0 -1
  305. package/src/schedule/schedule-store.ts +30 -0
  306. package/src/schedule/scheduler.ts +45 -18
  307. package/src/skills/catalog-install.ts +10 -2
  308. package/src/skills/inline-command-runner.ts +12 -14
  309. package/src/skills/managed-store.ts +2 -2
  310. package/src/skills/skill-memory.ts +1 -293
  311. package/src/subagent/index.ts +13 -3
  312. package/src/subagent/manager.ts +308 -29
  313. package/src/subagent/types.ts +68 -0
  314. package/src/tasks/task-runner.ts +4 -4
  315. package/src/tools/apps/executors.ts +29 -4
  316. package/src/tools/filesystem/list.ts +93 -0
  317. package/src/tools/permission-checker.ts +78 -18
  318. package/src/tools/registry.ts +4 -0
  319. package/src/tools/schedule/create.ts +3 -0
  320. package/src/tools/schedule/list.ts +1 -0
  321. package/src/tools/schedule/update.ts +6 -0
  322. package/src/tools/secret-detection-handler.ts +0 -1
  323. package/src/tools/shared/filesystem/errors.ts +5 -0
  324. package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
  325. package/src/tools/shared/filesystem/types.ts +17 -0
  326. package/src/tools/shared/shell-output.ts +31 -2
  327. package/src/tools/skills/sandbox-runner.ts +3 -6
  328. package/src/tools/subagent/abort.ts +12 -2
  329. package/src/tools/subagent/message.ts +9 -2
  330. package/src/tools/subagent/notify-parent.ts +79 -0
  331. package/src/tools/subagent/read.ts +29 -8
  332. package/src/tools/subagent/resolve.ts +21 -0
  333. package/src/tools/subagent/spawn.ts +2 -0
  334. package/src/tools/subagent/status.ts +11 -1
  335. package/src/tools/system/avatar-generator.ts +3 -3
  336. package/src/tools/system/register.ts +23 -0
  337. package/src/tools/system/set-permission-mode.ts +103 -0
  338. package/src/tools/terminal/parser.ts +30 -5
  339. package/src/tools/terminal/safe-env.ts +16 -1
  340. package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
  341. package/src/tools/terminal/sandbox.ts +4 -1
  342. package/src/tools/terminal/shell.ts +3 -5
  343. package/src/tools/tool-manifest.ts +6 -0
  344. package/src/tools/types.ts +2 -3
  345. package/src/util/logger.ts +1 -1
  346. package/src/util/platform.ts +50 -17
  347. package/src/watcher/provider-types.ts +1 -1
  348. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
  349. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
  350. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
  351. package/src/workspace/migrations/029-seed-pkb.ts +85 -0
  352. package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
  353. package/src/workspace/migrations/registry.ts +6 -0
  354. package/src/workspace/top-level-renderer.ts +5 -9
  355. package/src/__tests__/cli-memory.test.ts +0 -377
  356. package/src/__tests__/clipboard.test.ts +0 -88
  357. package/src/cli/cli-memory.ts +0 -179
  358. package/src/util/clipboard.ts +0 -34
@@ -0,0 +1,328 @@
1
+ /**
2
+ * Tests for identity/health route handlers, focusing on profiler metadata
3
+ * in /v1/health and /v1/healthz responses.
4
+ *
5
+ * Proves:
6
+ * - Backward compatibility: health endpoints return expected shape when
7
+ * profiler mode is off (no env vars).
8
+ * - Profiler payload: when profiler env vars are set, the response includes
9
+ * a `profiler` object with the expected structure and budget state.
10
+ * - Artifact detection: when run manifests and Bun summary files exist,
11
+ * the response correctly reports artifact counts and lastCompletedRun.
12
+ */
13
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
16
+
17
+ // Silence logger before any imports that use it
18
+ mock.module("../util/logger.js", () => ({
19
+ getLogger: () =>
20
+ new Proxy({} as Record<string, unknown>, {
21
+ get: () => () => {},
22
+ }),
23
+ }));
24
+
25
+ import { handleDetailedHealth } from "../runtime/routes/identity-routes.js";
26
+ import { getWorkspaceDir } from "../util/platform.js";
27
+
28
+ // ── Env helpers ─────────────────────────────────────────────────────────
29
+
30
+ let savedEnv: Record<string, string | undefined>;
31
+
32
+ const PROFILER_ENV_KEYS = [
33
+ "VELLUM_PROFILER_RUN_ID",
34
+ "VELLUM_PROFILER_MODE",
35
+ "VELLUM_PROFILER_MAX_BYTES",
36
+ "VELLUM_PROFILER_MAX_RUNS",
37
+ "VELLUM_PROFILER_MIN_FREE_MB",
38
+ ] as const;
39
+
40
+ function clearProfilerEnv(): void {
41
+ for (const key of PROFILER_ENV_KEYS) {
42
+ delete process.env[key];
43
+ }
44
+ }
45
+
46
+ function setProfilerEnv(
47
+ mode: string,
48
+ runId: string,
49
+ opts?: { maxBytes?: number; maxRuns?: number; minFreeMb?: number },
50
+ ): void {
51
+ process.env.VELLUM_PROFILER_RUN_ID = runId;
52
+ process.env.VELLUM_PROFILER_MODE = mode;
53
+ if (opts?.maxBytes !== undefined) {
54
+ process.env.VELLUM_PROFILER_MAX_BYTES = String(opts.maxBytes);
55
+ }
56
+ if (opts?.maxRuns !== undefined) {
57
+ process.env.VELLUM_PROFILER_MAX_RUNS = String(opts.maxRuns);
58
+ }
59
+ if (opts?.minFreeMb !== undefined) {
60
+ process.env.VELLUM_PROFILER_MIN_FREE_MB = String(opts.minFreeMb);
61
+ }
62
+ }
63
+
64
+ // ── Filesystem helpers ──────────────────────────────────────────────────
65
+
66
+ function ensureProfilerRunDir(runId: string): string {
67
+ const wsDir = getWorkspaceDir();
68
+ const runDir = join(wsDir, "data", "profiler", "runs", runId);
69
+ mkdirSync(runDir, { recursive: true });
70
+ return runDir;
71
+ }
72
+
73
+ function writeRunManifest(
74
+ runId: string,
75
+ manifest: {
76
+ status: "active" | "completed";
77
+ createdAt?: string;
78
+ updatedAt?: string;
79
+ completedAt?: string;
80
+ totalBytes?: number;
81
+ },
82
+ ): void {
83
+ const runDir = ensureProfilerRunDir(runId);
84
+ const m: Record<string, unknown> = {
85
+ runId,
86
+ status: manifest.status,
87
+ createdAt: manifest.createdAt ?? new Date().toISOString(),
88
+ updatedAt: manifest.updatedAt ?? new Date().toISOString(),
89
+ totalBytes: manifest.totalBytes ?? 0,
90
+ };
91
+ if (manifest.completedAt) {
92
+ m.completedAt = manifest.completedAt;
93
+ }
94
+ writeFileSync(join(runDir, "manifest.json"), JSON.stringify(m, null, 2));
95
+ }
96
+
97
+ function writeArtifactFile(
98
+ runId: string,
99
+ filename: string,
100
+ sizeBytes: number,
101
+ ): void {
102
+ const runDir = ensureProfilerRunDir(runId);
103
+ writeFileSync(join(runDir, filename), Buffer.alloc(sizeBytes));
104
+ }
105
+
106
+ // ── Setup / teardown ────────────────────────────────────────────────────
107
+
108
+ beforeEach(() => {
109
+ savedEnv = {};
110
+ for (const key of PROFILER_ENV_KEYS) {
111
+ savedEnv[key] = process.env[key];
112
+ }
113
+ clearProfilerEnv();
114
+
115
+ // Clean up any profiler run directories from previous tests so
116
+ // rescanRuns() doesn't pick up stale state in the shared workspace.
117
+ const profilerRunsDir = join(getWorkspaceDir(), "data", "profiler", "runs");
118
+ if (existsSync(profilerRunsDir)) {
119
+ rmSync(profilerRunsDir, { recursive: true, force: true });
120
+ }
121
+ });
122
+
123
+ afterEach(() => {
124
+ for (const [key, value] of Object.entries(savedEnv)) {
125
+ if (value === undefined) {
126
+ delete process.env[key];
127
+ } else {
128
+ process.env[key] = value;
129
+ }
130
+ }
131
+ });
132
+
133
+ // ── Tests ───────────────────────────────────────────────────────────────
134
+
135
+ describe("identity routes — health endpoint", () => {
136
+ describe("backward compatibility (profiler disabled)", () => {
137
+ test("/v1/health returns expected shape without profiler key when env vars are absent", async () => {
138
+ const res = handleDetailedHealth();
139
+ expect(res.status).toBe(200);
140
+
141
+ const body = (await res.json()) as Record<string, unknown>;
142
+ expect(body.status).toBe("healthy");
143
+ expect(body.timestamp).toBeDefined();
144
+ expect(body.version).toBeDefined();
145
+ expect(body.disk).toBeDefined();
146
+ expect(body.memory).toBeDefined();
147
+ expect(body.cpu).toBeDefined();
148
+ expect(body.migrations).toBeDefined();
149
+
150
+ // Profiler should either be absent or show enabled: false
151
+ if ("profiler" in body) {
152
+ const profiler = body.profiler as Record<string, unknown>;
153
+ expect(profiler.enabled).toBe(false);
154
+ expect(profiler.mode).toBeNull();
155
+ expect(profiler.runId).toBeNull();
156
+ expect(profiler.budget).toBeNull();
157
+ }
158
+ });
159
+
160
+ test("/v1/healthz returns the same shape as /v1/health", async () => {
161
+ // Both endpoints call handleDetailedHealth, so the shape must match
162
+ const res = handleDetailedHealth();
163
+ const body = (await res.json()) as Record<string, unknown>;
164
+
165
+ expect(body.status).toBe("healthy");
166
+ expect(body.timestamp).toBeDefined();
167
+ expect(body.migrations).toBeDefined();
168
+ });
169
+ });
170
+
171
+ describe("profiler payload (profiler enabled)", () => {
172
+ test("returns profiler object with enabled=true when env vars are set", async () => {
173
+ setProfilerEnv("cpu", "run-health-test-1", {
174
+ maxBytes: 10_000_000,
175
+ minFreeMb: 10,
176
+ });
177
+ ensureProfilerRunDir("run-health-test-1");
178
+
179
+ const res = handleDetailedHealth();
180
+ const body = (await res.json()) as Record<string, unknown>;
181
+
182
+ expect(body.profiler).toBeDefined();
183
+ const profiler = body.profiler as Record<string, unknown>;
184
+ expect(profiler.enabled).toBe(true);
185
+ expect(profiler.mode).toBe("cpu");
186
+ expect(profiler.runId).toBe("run-health-test-1");
187
+ expect(profiler.runDir).toContain("run-health-test-1");
188
+ expect(typeof profiler.totalBytes).toBe("number");
189
+ expect(typeof profiler.artifactCount).toBe("number");
190
+ });
191
+
192
+ test("includes budget block with expected fields", async () => {
193
+ setProfilerEnv("heap", "run-budget-test", {
194
+ maxBytes: 50_000_000,
195
+ minFreeMb: 100,
196
+ });
197
+ ensureProfilerRunDir("run-budget-test");
198
+
199
+ const res = handleDetailedHealth();
200
+ const body = (await res.json()) as Record<string, unknown>;
201
+ const profiler = body.profiler as Record<string, unknown>;
202
+ const budget = profiler.budget as Record<string, unknown>;
203
+
204
+ expect(budget).toBeDefined();
205
+ expect(budget.maxBytes).toBe(50_000_000);
206
+ expect(typeof budget.remainingBytes).toBe("number");
207
+ expect(budget.minFreeMb).toBe(100);
208
+ expect(typeof budget.freeMb).toBe("number");
209
+ expect(typeof budget.overBudget).toBe("boolean");
210
+ });
211
+
212
+ test("reports artifact count from .cpuprofile files", async () => {
213
+ setProfilerEnv("cpu", "run-artifact-count", {
214
+ maxBytes: 100_000_000,
215
+ minFreeMb: 0,
216
+ });
217
+ writeArtifactFile("run-artifact-count", "profile-1.cpuprofile", 1024);
218
+ writeArtifactFile("run-artifact-count", "profile-2.cpuprofile", 2048);
219
+ // Non-artifact file should not count
220
+ writeArtifactFile("run-artifact-count", "log.txt", 512);
221
+
222
+ const res = handleDetailedHealth();
223
+ const body = (await res.json()) as Record<string, unknown>;
224
+ const profiler = body.profiler as Record<string, unknown>;
225
+
226
+ expect(profiler.artifactCount).toBe(2);
227
+ });
228
+
229
+ test("detects over-budget state when total bytes exceed maxBytes", async () => {
230
+ setProfilerEnv("cpu+heap", "run-over-budget", {
231
+ maxBytes: 100, // Very small budget
232
+ minFreeMb: 0,
233
+ });
234
+ // Write a file larger than the budget
235
+ writeArtifactFile("run-over-budget", "big.cpuprofile", 5000);
236
+
237
+ const res = handleDetailedHealth();
238
+ const body = (await res.json()) as Record<string, unknown>;
239
+ const profiler = body.profiler as Record<string, unknown>;
240
+ const budget = profiler.budget as Record<string, unknown>;
241
+
242
+ expect(budget.overBudget).toBe(true);
243
+ expect(budget.remainingBytes).toBe(0);
244
+ });
245
+ });
246
+
247
+ describe("lastCompletedRun", () => {
248
+ test("returns null when no completed runs exist", async () => {
249
+ setProfilerEnv("cpu", "run-no-completed", {
250
+ maxBytes: 100_000_000,
251
+ minFreeMb: 0,
252
+ });
253
+ ensureProfilerRunDir("run-no-completed");
254
+
255
+ const res = handleDetailedHealth();
256
+ const body = (await res.json()) as Record<string, unknown>;
257
+ const profiler = body.profiler as Record<string, unknown>;
258
+
259
+ expect(profiler.lastCompletedRun).toBeNull();
260
+ });
261
+
262
+ test("returns completed run summary with artifact count and hasSummaries", async () => {
263
+ setProfilerEnv("cpu", "active-run-xyz", {
264
+ maxBytes: 100_000_000,
265
+ minFreeMb: 0,
266
+ });
267
+ ensureProfilerRunDir("active-run-xyz");
268
+
269
+ // Create a completed run with artifacts and a summary file
270
+ const completedId = "completed-run-abc";
271
+ const expectedCompletedAt = "2025-06-01T00:30:00Z";
272
+ writeRunManifest(completedId, {
273
+ status: "completed",
274
+ createdAt: "2025-06-01T00:00:00Z",
275
+ updatedAt: "2025-06-01T01:00:00Z",
276
+ completedAt: expectedCompletedAt,
277
+ totalBytes: 4096,
278
+ });
279
+ writeArtifactFile(completedId, "profile.cpuprofile", 3072);
280
+ writeArtifactFile(completedId, "summary.md", 256);
281
+
282
+ const res = handleDetailedHealth();
283
+ const body = (await res.json()) as Record<string, unknown>;
284
+ const profiler = body.profiler as Record<string, unknown>;
285
+ const last = profiler.lastCompletedRun as Record<string, unknown>;
286
+
287
+ expect(last).toBeDefined();
288
+ expect(last.runId).toBe(completedId);
289
+ expect(last.artifactCount).toBe(1); // Only .cpuprofile counts
290
+ expect(last.hasSummaries).toBe(true);
291
+ expect(typeof last.totalBytes).toBe("number");
292
+ // completedAt should reflect the manifest's completedAt value,
293
+ // not the current time or updatedAt.
294
+ expect(last.completedAt).toBe(expectedCompletedAt);
295
+ });
296
+
297
+ test("selects the most recent completed run when multiple exist", async () => {
298
+ setProfilerEnv("heap", "active-multi", {
299
+ maxBytes: 100_000_000,
300
+ maxRuns: 100,
301
+ minFreeMb: 0,
302
+ });
303
+ ensureProfilerRunDir("active-multi");
304
+
305
+ writeRunManifest("older-completed", {
306
+ status: "completed",
307
+ createdAt: "2025-01-01T00:00:00Z",
308
+ updatedAt: "2025-01-01T01:00:00Z",
309
+ });
310
+ writeArtifactFile("older-completed", "old.heapsnapshot", 512);
311
+
312
+ writeRunManifest("newer-completed", {
313
+ status: "completed",
314
+ createdAt: "2025-06-15T00:00:00Z",
315
+ updatedAt: "2025-06-15T01:00:00Z",
316
+ });
317
+ writeArtifactFile("newer-completed", "new.heapsnapshot", 1024);
318
+
319
+ const res = handleDetailedHealth();
320
+ const body = (await res.json()) as Record<string, unknown>;
321
+ const profiler = body.profiler as Record<string, unknown>;
322
+ const last = profiler.lastCompletedRun as Record<string, unknown>;
323
+
324
+ expect(last).toBeDefined();
325
+ expect(last.runId).toBe("newer-completed");
326
+ });
327
+ });
328
+ });
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Tests for initFeatureFlagOverrides() — the async gateway fetch that
3
+ * pre-populates the feature flag cache before CLI program construction.
4
+ */
5
+ import { afterEach, beforeEach, describe, expect, it } from "bun:test";
6
+
7
+ import {
8
+ clearFeatureFlagOverridesCache,
9
+ initFeatureFlagOverrides,
10
+ isAssistantFeatureFlagEnabled,
11
+ } from "../config/assistant-feature-flags.js";
12
+ import * as tokenService from "../runtime/auth/token-service.js";
13
+ import { getMockFetchCalls, mockFetch, resetMockFetch } from "./mock-fetch.js";
14
+
15
+ const VALID_HEX_KEY = "ab".repeat(32);
16
+
17
+ beforeEach(() => {
18
+ clearFeatureFlagOverridesCache();
19
+ tokenService._resetSigningKeyForTesting();
20
+
21
+ // Set up a signing key so mintEdgeRelayToken() works
22
+ process.env.ACTOR_TOKEN_SIGNING_KEY = VALID_HEX_KEY;
23
+ tokenService.initAuthSigningKey(tokenService.resolveSigningKey());
24
+ });
25
+
26
+ afterEach(() => {
27
+ resetMockFetch();
28
+ clearFeatureFlagOverridesCache();
29
+ tokenService._resetSigningKeyForTesting();
30
+ delete process.env.ACTOR_TOKEN_SIGNING_KEY;
31
+ });
32
+
33
+ describe("initFeatureFlagOverrides", () => {
34
+ it("populates cache from gateway fetch response", async () => {
35
+ mockFetch(
36
+ "/v1/feature-flags",
37
+ { method: "GET" },
38
+ {
39
+ body: {
40
+ flags: [
41
+ {
42
+ key: "foo-enabled",
43
+ enabled: true,
44
+ label: "Foo",
45
+ defaultEnabled: false,
46
+ description: "",
47
+ },
48
+ {
49
+ key: "bar-enabled",
50
+ enabled: true,
51
+ label: "Bar",
52
+ defaultEnabled: true,
53
+ description: "",
54
+ },
55
+ ],
56
+ },
57
+ status: 200,
58
+ },
59
+ );
60
+
61
+ await initFeatureFlagOverrides();
62
+
63
+ const config = {} as any;
64
+ expect(isAssistantFeatureFlagEnabled("foo-enabled", config)).toBe(true);
65
+ expect(isAssistantFeatureFlagEnabled("bar-enabled", config)).toBe(true);
66
+
67
+ // Verify fetch was called with correct URL and auth header
68
+ const calls = getMockFetchCalls();
69
+ expect(calls.length).toBe(1);
70
+ expect(calls[0].path).toContain("/v1/feature-flags");
71
+ const headers = calls[0].init.headers as Record<string, string> | undefined;
72
+ expect(headers).toHaveProperty("Authorization");
73
+ });
74
+
75
+ it("sends a valid Bearer JWT in the Authorization header", async () => {
76
+ mockFetch(
77
+ "/v1/feature-flags",
78
+ { method: "GET" },
79
+ { body: { flags: [] }, status: 200 },
80
+ );
81
+
82
+ await initFeatureFlagOverrides();
83
+
84
+ const calls = getMockFetchCalls();
85
+ expect(calls.length).toBe(1);
86
+ const headers = calls[0].init.headers as Record<string, string> | undefined;
87
+ const authHeader = headers?.Authorization;
88
+
89
+ expect(authHeader).toBeDefined();
90
+ expect(authHeader).toMatch(/^Bearer /);
91
+
92
+ // Verify it's a valid JWT (three dot-separated base64url segments)
93
+ const token = authHeader!.replace("Bearer ", "");
94
+ const parts = token.split(".");
95
+ expect(parts.length).toBe(3);
96
+ });
97
+
98
+ it("falls back gracefully when gateway is unreachable", async () => {
99
+ mockFetch("/v1/feature-flags", { method: "GET" }, { status: 500 });
100
+
101
+ // Should not throw
102
+ await initFeatureFlagOverrides();
103
+
104
+ // Without gateway data or file, undeclared flags default to true
105
+ const config = {} as any;
106
+ expect(isAssistantFeatureFlagEnabled("foo-enabled", config)).toBe(true);
107
+ });
108
+
109
+ it("falls back gracefully on non-OK HTTP status", async () => {
110
+ mockFetch(
111
+ "/v1/feature-flags",
112
+ { method: "GET" },
113
+ { body: "Unauthorized", status: 401 },
114
+ );
115
+
116
+ await initFeatureFlagOverrides();
117
+
118
+ // Undeclared flags default to true without overrides
119
+ const config = {} as any;
120
+ expect(isAssistantFeatureFlagEnabled("foo-enabled", config)).toBe(true);
121
+ });
122
+
123
+ it("initializes signing key lazily when not yet set", async () => {
124
+ // Reset signing key to simulate fresh CLI subprocess
125
+ tokenService._resetSigningKeyForTesting();
126
+ delete process.env.ACTOR_TOKEN_SIGNING_KEY;
127
+
128
+ expect(tokenService.isSigningKeyInitialized()).toBe(false);
129
+
130
+ mockFetch(
131
+ "/v1/feature-flags",
132
+ { method: "GET" },
133
+ {
134
+ body: {
135
+ flags: [{ key: "expected-enabled", enabled: true }],
136
+ },
137
+ status: 200,
138
+ },
139
+ );
140
+
141
+ await initFeatureFlagOverrides();
142
+
143
+ // Signing key should have been initialized during the fetch
144
+ expect(tokenService.isSigningKeyInitialized()).toBe(true);
145
+
146
+ // And the flag should be resolved correctly
147
+ const config = {} as any;
148
+ expect(isAssistantFeatureFlagEnabled("expected-enabled", config)).toBe(
149
+ true,
150
+ );
151
+ });
152
+
153
+ it("does not cache empty gateway response", async () => {
154
+ mockFetch(
155
+ "/v1/feature-flags",
156
+ { method: "GET" },
157
+ { body: { flags: [] }, status: 200 },
158
+ );
159
+
160
+ await initFeatureFlagOverrides();
161
+
162
+ // Undeclared flags without overrides default to true (not false from
163
+ // a cached empty map)
164
+ const config = {} as any;
165
+ expect(isAssistantFeatureFlagEnabled("foo-enabled", config)).toBe(true);
166
+ });
167
+ });
@@ -125,6 +125,18 @@ describe("assembleInjectionBlock", () => {
125
125
  expect(result).toContain("[skill]");
126
126
  expect(result).toContain("→ use skill_load to activate");
127
127
  });
128
+
129
+ test("assembleInjectionBlock omits skill_load suffix for CLI commands", () => {
130
+ const node = makeScoredNode({
131
+ type: "procedural",
132
+ content:
133
+ 'cli:bash\nThe "assistant bash" CLI command is available. Execute a shell command.',
134
+ });
135
+ const result = assembleInjectionBlock([node]);
136
+ expect(result).not.toContain("[skill]");
137
+ expect(result).not.toContain("skill_load to activate");
138
+ expect(result).toContain("CLI command is available");
139
+ });
128
140
  });
129
141
 
130
142
  describe("assembleContextBlock — procedural nodes", () => {
@@ -139,6 +151,18 @@ describe("assembleContextBlock — procedural nodes", () => {
139
151
  expect(result).toContain("use skill_load to activate");
140
152
  });
141
153
 
154
+ test("omits skill_load suffix for CLI commands", () => {
155
+ const node = makeScoredNode({
156
+ type: "procedural",
157
+ content:
158
+ 'cli:bash\nThe "assistant bash" CLI command is available. Execute a shell command.',
159
+ });
160
+ const result = assembleContextBlock([node]);
161
+ expect(result).toContain("### Skills You Can Use");
162
+ expect(result).not.toContain("skill_load to activate");
163
+ expect(result).toContain("CLI command is available");
164
+ });
165
+
142
166
  test("strips skill: prefix from old-format content", () => {
143
167
  const node = makeScoredNode({
144
168
  type: "procedural",
@@ -11,7 +11,6 @@ const mockConfig = {
11
11
  model: "test",
12
12
  maxTokens: 4096,
13
13
  dataDir: "/tmp",
14
- sandbox: { enabled: true },
15
14
  timeouts: {
16
15
  shellDefaultTimeoutSec: 120,
17
16
  shellMaxTimeoutSec: 600,
@@ -104,20 +103,23 @@ describe("runInlineCommand", () => {
104
103
  // ── Sandbox enforcement ──────────────────────────────────────────────────
105
104
 
106
105
  describe("sandbox enforcement", () => {
107
- test("always passes sandbox config with enabled=true", async () => {
106
+ test("always passes sandbox config with enabled=false", async () => {
108
107
  lastWrapCall = null;
109
108
  await runInlineCommand("echo sandbox-check", CWD);
110
109
 
111
110
  expect(lastWrapCall).not.toBeNull();
112
- expect(lastWrapCall!.config.enabled).toBe(true);
111
+ expect(lastWrapCall!.config.enabled).toBe(false);
113
112
  });
114
113
 
115
- test("always passes networkMode=off", async () => {
114
+ test("does not pass networkMode when sandbox is disabled", async () => {
116
115
  lastWrapCall = null;
117
116
  await runInlineCommand("echo network-check", CWD);
118
117
 
119
118
  expect(lastWrapCall).not.toBeNull();
120
- expect(lastWrapCall!.options?.networkMode).toBe("off");
119
+ // networkMode is a no-op when sandbox is disabled (wrapCommand returns
120
+ // a plain bash invocation), so it is not passed. Network isolation is
121
+ // provided by the Docker/platform-managed container.
122
+ expect(lastWrapCall!.options).toBeUndefined();
121
123
  });
122
124
 
123
125
  test("uses the provided workingDir as cwd", async () => {
@@ -32,7 +32,7 @@ const mockInstallExternalSkill = mock(
32
32
  );
33
33
  const mockGetCatalog = mock(async () => []);
34
34
  const mockInstallSkillLocally = mock(async () => {});
35
- const mockSeedCatalogSkillMemories = mock(() => {});
35
+ const mockSeedSkillGraphNodes = mock(() => {});
36
36
  const mockEnsureSkillEntry = mock(
37
37
  (_raw: Record<string, unknown>, _id: string) => ({
38
38
  enabled: false,
@@ -115,9 +115,10 @@ mock.module("../skills/managed-store.js", () => ({
115
115
  removeSkillsIndexEntry: () => {},
116
116
  validateManagedSkillId: () => null,
117
117
  }));
118
- mock.module("../skills/skill-memory.js", () => ({
119
- deleteSkillCapabilityMemory: () => {},
120
- seedCatalogSkillMemories: mockSeedCatalogSkillMemories,
118
+ mock.module("../memory/graph/capability-seed.js", () => ({
119
+ deleteSkillCapabilityNode: () => {},
120
+ seedSkillGraphNodes: mockSeedSkillGraphNodes,
121
+ seedUninstalledCatalogSkillMemories: async () => {},
121
122
  }));
122
123
  mock.module("../util/platform.js", () => ({
123
124
  getWorkspaceSkillsDir: () => "/tmp/test-skills",
@@ -158,7 +159,7 @@ describe("installSkill routing", () => {
158
159
  mockInstallExternalSkill.mockReset();
159
160
  mockGetCatalog.mockReset();
160
161
  mockInstallSkillLocally.mockReset();
161
- mockSeedCatalogSkillMemories.mockReset();
162
+ mockSeedSkillGraphNodes.mockReset();
162
163
  mockEnsureSkillEntry.mockReset();
163
164
 
164
165
  // Defaults
@@ -167,7 +168,7 @@ describe("installSkill routing", () => {
167
168
  mockInstallExternalSkill.mockResolvedValue(undefined);
168
169
  mockGetCatalog.mockResolvedValue([]);
169
170
  mockInstallSkillLocally.mockResolvedValue(undefined);
170
- mockSeedCatalogSkillMemories.mockReturnValue(undefined);
171
+ mockSeedSkillGraphNodes.mockReturnValue(undefined);
171
172
  mockEnsureSkillEntry.mockReturnValue({ enabled: false });
172
173
  });
173
174