@vellumai/assistant 0.4.49 → 0.4.50

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 (239) hide show
  1. package/ARCHITECTURE.md +24 -33
  2. package/README.md +3 -3
  3. package/docs/architecture/memory.md +180 -119
  4. package/package.json +2 -2
  5. package/src/__tests__/agent-loop.test.ts +3 -1
  6. package/src/__tests__/anthropic-provider.test.ts +114 -23
  7. package/src/__tests__/approval-cascade.test.ts +1 -15
  8. package/src/__tests__/approval-routes-http.test.ts +2 -0
  9. package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
  10. package/src/__tests__/canonical-guardian-store.test.ts +95 -0
  11. package/src/__tests__/checker.test.ts +13 -0
  12. package/src/__tests__/config-schema.test.ts +1 -68
  13. package/src/__tests__/context-memory-e2e.test.ts +11 -100
  14. package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
  15. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  16. package/src/__tests__/credential-security-e2e.test.ts +1 -0
  17. package/src/__tests__/credential-vault-unit.test.ts +4 -0
  18. package/src/__tests__/credential-vault.test.ts +13 -1
  19. package/src/__tests__/cu-unified-flow.test.ts +532 -0
  20. package/src/__tests__/date-context.test.ts +93 -77
  21. package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
  22. package/src/__tests__/guardian-routing-invariants.test.ts +93 -0
  23. package/src/__tests__/history-repair.test.ts +245 -0
  24. package/src/__tests__/host-cu-proxy.test.ts +165 -3
  25. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  26. package/src/__tests__/invite-redemption-service.test.ts +65 -1
  27. package/src/__tests__/keychain-broker-client.test.ts +4 -4
  28. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
  29. package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
  30. package/src/__tests__/memory-recall-quality.test.ts +244 -407
  31. package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
  32. package/src/__tests__/memory-regressions.test.ts +477 -2841
  33. package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
  34. package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
  35. package/src/__tests__/mime-builder.test.ts +28 -0
  36. package/src/__tests__/native-web-search.test.ts +1 -0
  37. package/src/__tests__/oauth-cli.test.ts +572 -5
  38. package/src/__tests__/oauth-store.test.ts +120 -6
  39. package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
  40. package/src/__tests__/registry.test.ts +0 -1
  41. package/src/__tests__/relay-server.test.ts +46 -1
  42. package/src/__tests__/schedule-tools.test.ts +32 -0
  43. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  44. package/src/__tests__/secret-onetime-send.test.ts +1 -0
  45. package/src/__tests__/secure-keys.test.ts +7 -2
  46. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  47. package/src/__tests__/session-abort-tool-results.test.ts +1 -14
  48. package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
  49. package/src/__tests__/session-agent-loop.test.ts +19 -15
  50. package/src/__tests__/session-confirmation-signals.test.ts +1 -15
  51. package/src/__tests__/session-error.test.ts +124 -2
  52. package/src/__tests__/session-history-web-search.test.ts +918 -0
  53. package/src/__tests__/session-pre-run-repair.test.ts +1 -14
  54. package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
  55. package/src/__tests__/session-queue.test.ts +37 -27
  56. package/src/__tests__/session-runtime-assembly.test.ts +54 -0
  57. package/src/__tests__/session-slash-known.test.ts +1 -15
  58. package/src/__tests__/session-slash-queue.test.ts +1 -15
  59. package/src/__tests__/session-slash-unknown.test.ts +1 -15
  60. package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
  61. package/src/__tests__/session-workspace-injection.test.ts +3 -37
  62. package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
  63. package/src/__tests__/skills-install-extract.test.ts +93 -0
  64. package/src/__tests__/skillssh-registry.test.ts +451 -0
  65. package/src/__tests__/trust-store.test.ts +15 -0
  66. package/src/__tests__/voice-invite-redemption.test.ts +32 -1
  67. package/src/agent/ax-tree-compaction.test.ts +51 -0
  68. package/src/agent/loop.ts +39 -12
  69. package/src/approvals/AGENTS.md +1 -1
  70. package/src/approvals/guardian-request-resolvers.ts +14 -2
  71. package/src/bundler/compiler-tools.ts +66 -2
  72. package/src/calls/call-domain.ts +132 -0
  73. package/src/calls/call-store.ts +6 -0
  74. package/src/calls/relay-server.ts +43 -5
  75. package/src/calls/relay-setup-router.ts +17 -1
  76. package/src/calls/twilio-config.ts +1 -1
  77. package/src/calls/types.ts +3 -1
  78. package/src/cli/commands/doctor.ts +4 -3
  79. package/src/cli/commands/mcp.ts +46 -59
  80. package/src/cli/commands/memory.ts +16 -165
  81. package/src/cli/commands/oauth/apps.ts +31 -2
  82. package/src/cli/commands/oauth/connections.ts +431 -97
  83. package/src/cli/commands/oauth/providers.ts +15 -1
  84. package/src/cli/commands/sessions.ts +5 -2
  85. package/src/cli/commands/skills.ts +173 -1
  86. package/src/cli/http-client.ts +0 -20
  87. package/src/cli/main-screen.tsx +2 -2
  88. package/src/cli/program.ts +5 -6
  89. package/src/cli.ts +4 -10
  90. package/src/config/bundled-skills/computer-use/TOOLS.json +1 -1
  91. package/src/config/bundled-skills/computer-use/tools/computer-use-observe.ts +12 -0
  92. package/src/config/bundled-tool-registry.ts +2 -5
  93. package/src/config/schema.ts +1 -12
  94. package/src/config/schemas/memory-lifecycle.ts +0 -9
  95. package/src/config/schemas/memory-processing.ts +0 -180
  96. package/src/config/schemas/memory-retrieval.ts +32 -104
  97. package/src/config/schemas/memory.ts +0 -10
  98. package/src/config/types.ts +0 -4
  99. package/src/context/window-manager.ts +4 -1
  100. package/src/daemon/config-watcher.ts +61 -3
  101. package/src/daemon/daemon-control.ts +1 -1
  102. package/src/daemon/date-context.ts +114 -31
  103. package/src/daemon/handlers/sessions.ts +18 -13
  104. package/src/daemon/handlers/skills.ts +20 -1
  105. package/src/daemon/history-repair.ts +72 -8
  106. package/src/daemon/host-cu-proxy.ts +55 -26
  107. package/src/daemon/lifecycle.ts +31 -3
  108. package/src/daemon/mcp-reload-service.ts +2 -2
  109. package/src/daemon/message-types/computer-use.ts +1 -12
  110. package/src/daemon/message-types/memory.ts +4 -16
  111. package/src/daemon/message-types/messages.ts +1 -0
  112. package/src/daemon/message-types/sessions.ts +4 -0
  113. package/src/daemon/server.ts +12 -1
  114. package/src/daemon/session-agent-loop-handlers.ts +38 -0
  115. package/src/daemon/session-agent-loop.ts +334 -48
  116. package/src/daemon/session-error.ts +89 -6
  117. package/src/daemon/session-history.ts +17 -7
  118. package/src/daemon/session-media-retry.ts +6 -2
  119. package/src/daemon/session-memory.ts +69 -149
  120. package/src/daemon/session-process.ts +10 -1
  121. package/src/daemon/session-runtime-assembly.ts +49 -19
  122. package/src/daemon/session-surfaces.ts +4 -1
  123. package/src/daemon/session-tool-setup.ts +7 -1
  124. package/src/daemon/session.ts +12 -2
  125. package/src/instrument.ts +61 -1
  126. package/src/memory/admin.ts +2 -191
  127. package/src/memory/canonical-guardian-store.ts +38 -2
  128. package/src/memory/conversation-crud.ts +0 -33
  129. package/src/memory/conversation-queries.ts +22 -3
  130. package/src/memory/db-init.ts +28 -0
  131. package/src/memory/embedding-backend.ts +84 -8
  132. package/src/memory/embedding-types.ts +9 -1
  133. package/src/memory/indexer.ts +7 -46
  134. package/src/memory/items-extractor.ts +274 -76
  135. package/src/memory/job-handlers/backfill.ts +2 -127
  136. package/src/memory/job-handlers/cleanup.ts +2 -16
  137. package/src/memory/job-handlers/extraction.ts +2 -138
  138. package/src/memory/job-handlers/index-maintenance.ts +1 -6
  139. package/src/memory/job-handlers/summarization.ts +3 -148
  140. package/src/memory/job-utils.ts +21 -59
  141. package/src/memory/jobs-store.ts +1 -159
  142. package/src/memory/jobs-worker.ts +9 -52
  143. package/src/memory/migrations/104-core-indexes.ts +3 -3
  144. package/src/memory/migrations/149-oauth-tables.ts +2 -0
  145. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
  146. package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
  147. package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
  148. package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
  149. package/src/memory/migrations/154-drop-fts.ts +20 -0
  150. package/src/memory/migrations/155-drop-conflicts.ts +7 -0
  151. package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
  152. package/src/memory/migrations/index.ts +7 -0
  153. package/src/memory/qdrant-client.ts +148 -51
  154. package/src/memory/raw-query.ts +1 -1
  155. package/src/memory/retriever.test.ts +294 -273
  156. package/src/memory/retriever.ts +421 -645
  157. package/src/memory/schema/calls.ts +2 -0
  158. package/src/memory/schema/memory-core.ts +3 -48
  159. package/src/memory/schema/oauth.ts +2 -0
  160. package/src/memory/search/formatting.ts +263 -176
  161. package/src/memory/search/lexical.ts +1 -254
  162. package/src/memory/search/ranking.ts +0 -455
  163. package/src/memory/search/semantic.ts +100 -14
  164. package/src/memory/search/staleness.ts +47 -0
  165. package/src/memory/search/tier-classifier.ts +21 -0
  166. package/src/memory/search/types.ts +15 -77
  167. package/src/memory/task-memory-cleanup.ts +4 -6
  168. package/src/messaging/providers/gmail/mime-builder.ts +17 -7
  169. package/src/oauth/byo-connection.test.ts +8 -1
  170. package/src/oauth/oauth-store.ts +113 -27
  171. package/src/oauth/seed-providers.ts +6 -0
  172. package/src/oauth/token-persistence.ts +11 -3
  173. package/src/permissions/defaults.ts +1 -0
  174. package/src/permissions/trust-store.ts +23 -1
  175. package/src/playbooks/playbook-compiler.ts +1 -1
  176. package/src/prompts/system-prompt.ts +18 -2
  177. package/src/providers/anthropic/client.ts +56 -126
  178. package/src/providers/types.ts +7 -1
  179. package/src/runtime/AGENTS.md +9 -0
  180. package/src/runtime/auth/route-policy.ts +6 -3
  181. package/src/runtime/guardian-reply-router.ts +24 -22
  182. package/src/runtime/http-server.ts +2 -2
  183. package/src/runtime/invite-redemption-service.ts +19 -1
  184. package/src/runtime/invite-service.ts +25 -0
  185. package/src/runtime/pending-interactions.ts +2 -2
  186. package/src/runtime/routes/brain-graph-routes.ts +10 -90
  187. package/src/runtime/routes/conversation-routes.ts +9 -1
  188. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
  189. package/src/runtime/routes/memory-item-routes.test.ts +754 -0
  190. package/src/runtime/routes/memory-item-routes.ts +503 -0
  191. package/src/runtime/routes/session-management-routes.ts +3 -3
  192. package/src/runtime/routes/settings-routes.ts +2 -2
  193. package/src/runtime/routes/trust-rules-routes.ts +14 -0
  194. package/src/runtime/routes/workspace-routes.ts +2 -1
  195. package/src/security/keychain-broker-client.ts +17 -4
  196. package/src/security/secure-keys.ts +25 -3
  197. package/src/security/token-manager.ts +36 -36
  198. package/src/skills/catalog-install.ts +74 -18
  199. package/src/skills/skillssh-registry.ts +503 -0
  200. package/src/tools/assets/search.ts +5 -1
  201. package/src/tools/computer-use/definitions.ts +0 -10
  202. package/src/tools/computer-use/registry.ts +1 -1
  203. package/src/tools/credentials/vault.ts +1 -3
  204. package/src/tools/memory/definitions.ts +4 -13
  205. package/src/tools/memory/handlers.test.ts +83 -103
  206. package/src/tools/memory/handlers.ts +50 -85
  207. package/src/tools/schedule/create.ts +8 -1
  208. package/src/tools/schedule/update.ts +8 -1
  209. package/src/tools/skills/load.ts +25 -2
  210. package/src/__tests__/clarification-resolver.test.ts +0 -193
  211. package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
  212. package/src/__tests__/conflict-policy.test.ts +0 -269
  213. package/src/__tests__/conflict-store.test.ts +0 -372
  214. package/src/__tests__/contradiction-checker.test.ts +0 -361
  215. package/src/__tests__/entity-extractor.test.ts +0 -211
  216. package/src/__tests__/entity-search.test.ts +0 -1117
  217. package/src/__tests__/profile-compiler.test.ts +0 -392
  218. package/src/__tests__/session-conflict-gate.test.ts +0 -1228
  219. package/src/__tests__/session-profile-injection.test.ts +0 -557
  220. package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
  221. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
  222. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
  223. package/src/daemon/session-conflict-gate.ts +0 -167
  224. package/src/daemon/session-dynamic-profile.ts +0 -77
  225. package/src/memory/clarification-resolver.ts +0 -417
  226. package/src/memory/conflict-intent.ts +0 -205
  227. package/src/memory/conflict-policy.ts +0 -127
  228. package/src/memory/conflict-store.ts +0 -410
  229. package/src/memory/contradiction-checker.ts +0 -508
  230. package/src/memory/entity-extractor.ts +0 -535
  231. package/src/memory/format-recall.ts +0 -47
  232. package/src/memory/fts-reconciler.ts +0 -165
  233. package/src/memory/job-handlers/conflict.ts +0 -200
  234. package/src/memory/profile-compiler.ts +0 -195
  235. package/src/memory/recall-cache.ts +0 -117
  236. package/src/memory/search/entity.ts +0 -535
  237. package/src/memory/search/query-expansion.test.ts +0 -70
  238. package/src/memory/search/query-expansion.ts +0 -118
  239. package/src/runtime/routes/mcp-routes.ts +0 -20
@@ -20,9 +20,6 @@ import { computeRecallBudget } from "../memory/retrieval-budget.js";
20
20
  import { buildMemoryRecall } from "../memory/retriever.js";
21
21
  import {
22
22
  conversations,
23
- memoryEntities,
24
- memoryEntityRelations,
25
- memoryItemEntities,
26
23
  memoryItems,
27
24
  memoryItemSources,
28
25
  messages,
@@ -52,6 +49,7 @@ mock.module("../util/logger.js", () => ({
52
49
  mock.module("../memory/qdrant-client.js", () => ({
53
50
  getQdrantClient: () => ({
54
51
  searchWithFilter: async () => [],
52
+ hybridSearch: async () => [],
55
53
  upsertPoints: async () => {},
56
54
  deletePoints: async () => {},
57
55
  }),
@@ -168,13 +166,9 @@ describe("Context + Memory E2E regression", () => {
168
166
  beforeEach(() => {
169
167
  const db = getDb();
170
168
  db.run("DELETE FROM memory_item_sources");
171
- db.run("DELETE FROM memory_item_entities");
172
- db.run("DELETE FROM memory_entity_relations");
173
- db.run("DELETE FROM memory_entities");
174
169
  db.run("DELETE FROM memory_embeddings");
175
- db.run("DELETE FROM memory_summaries");
176
170
  db.run("DELETE FROM memory_items");
177
- db.run("DELETE FROM memory_segment_fts");
171
+
178
172
  db.run("DELETE FROM memory_segments");
179
173
  db.run("DELETE FROM messages");
180
174
  db.run("DELETE FROM conversations");
@@ -279,43 +273,6 @@ describe("Context + Memory E2E regression", () => {
279
273
  now + 100_000,
280
274
  );
281
275
 
282
- db.insert(memoryEntities)
283
- .values([
284
- {
285
- id: "entity-apollo",
286
- name: "Apollo",
287
- type: "project",
288
- aliases: JSON.stringify(["project-apollo"]),
289
- description: null,
290
- firstSeenAt: now,
291
- lastSeenAt: now + 100_000,
292
- mentionCount: 6,
293
- },
294
- {
295
- id: "entity-hermes",
296
- name: "HermesGate",
297
- type: "strategy",
298
- aliases: JSON.stringify(["hermes-gate"]),
299
- description: null,
300
- firstSeenAt: now,
301
- lastSeenAt: now + 100_000,
302
- mentionCount: 4,
303
- },
304
- ])
305
- .run();
306
-
307
- db.insert(memoryEntityRelations)
308
- .values({
309
- id: "rel-apollo-hermes",
310
- sourceEntityId: "entity-apollo",
311
- targetEntityId: "entity-hermes",
312
- relation: "uses",
313
- evidence: "Apollo uses HermesGate for risky changes",
314
- firstSeenAt: now,
315
- lastSeenAt: now + 50_000,
316
- })
317
- .run();
318
-
319
276
  insertMemoryItem({
320
277
  id: "item-apollo-direct",
321
278
  kind: "preference",
@@ -335,16 +292,10 @@ describe("Context + Memory E2E regression", () => {
335
292
  createdAt: now + 10_000,
336
293
  })
337
294
  .run();
338
- db.insert(memoryItemEntities)
339
- .values({
340
- memoryItemId: "item-apollo-direct",
341
- entityId: "entity-apollo",
342
- })
343
- .run();
344
295
 
345
296
  insertMemoryItem({
346
297
  id: "item-hermes-relation",
347
- kind: "fact",
298
+ kind: "identity",
348
299
  subject: "hermes rollout execution",
349
300
  statement:
350
301
  "HermesGate rollout guidance: start at 5% traffic and promote only after error budget checks pass.",
@@ -361,12 +312,6 @@ describe("Context + Memory E2E regression", () => {
361
312
  createdAt: now + 12_000,
362
313
  })
363
314
  .run();
364
- db.insert(memoryItemEntities)
365
- .values({
366
- memoryItemId: "item-hermes-relation",
367
- entityId: "entity-hermes",
368
- })
369
- .run();
370
315
 
371
316
  insertMemoryItem({
372
317
  id: "item-apollo-stale",
@@ -387,16 +332,10 @@ describe("Context + Memory E2E regression", () => {
387
332
  createdAt: now - 390 * 24 * 60 * 60 * 1000,
388
333
  })
389
334
  .run();
390
- db.insert(memoryItemEntities)
391
- .values({
392
- memoryItemId: "item-apollo-stale",
393
- entityId: "entity-apollo",
394
- })
395
- .run();
396
335
 
397
336
  insertMemoryItem({
398
337
  id: "item-apollo-secret",
399
- kind: "fact",
338
+ kind: "identity",
400
339
  subject: "apollo secret",
401
340
  statement: "Current-turn secret: Apollo code is 123XYZ.",
402
341
  confidence: 0.99,
@@ -412,12 +351,6 @@ describe("Context + Memory E2E regression", () => {
412
351
  createdAt: now + 100_000,
413
352
  })
414
353
  .run();
415
- db.insert(memoryItemEntities)
416
- .values({
417
- memoryItemId: "item-apollo-secret",
418
- entityId: "entity-apollo",
419
- })
420
- .run();
421
354
 
422
355
  const summaryCounter = { calls: 0 };
423
356
  const provider = makeSummaryProvider(summaryCounter);
@@ -454,13 +387,7 @@ describe("Context + Memory E2E regression", () => {
454
387
  },
455
388
  retrieval: {
456
389
  ...DEFAULT_CONFIG.memory.retrieval,
457
- lexicalTopK: 50,
458
- semanticTopK: 16,
459
390
  maxInjectTokens: 900,
460
- reranking: {
461
- ...DEFAULT_CONFIG.memory.retrieval.reranking,
462
- enabled: false,
463
- },
464
391
  dynamicBudget: {
465
392
  enabled: true,
466
393
  minInjectTokens: 180,
@@ -468,17 +395,6 @@ describe("Context + Memory E2E regression", () => {
468
395
  targetHeadroomTokens: 700,
469
396
  },
470
397
  },
471
- entity: {
472
- ...DEFAULT_CONFIG.memory.entity,
473
- relationRetrieval: {
474
- ...DEFAULT_CONFIG.memory.entity.relationRetrieval,
475
- enabled: true,
476
- maxSeedEntities: 4,
477
- maxNeighborEntities: 6,
478
- maxEdges: 8,
479
- neighborScoreMultiplier: 0.65,
480
- },
481
- },
482
398
  },
483
399
  };
484
400
 
@@ -511,19 +427,14 @@ describe("Context + Memory E2E regression", () => {
511
427
  );
512
428
 
513
429
  expect(recall.injectedTokens).toBeLessThanOrEqual(recallBudget);
514
- expect(recall.relationSeedEntityCount).toBeGreaterThan(0);
515
- expect(recall.relationTraversedEdgeCount).toBeGreaterThan(0);
516
- expect(recall.relationNeighborEntityCount).toBeGreaterThan(0);
517
- expect(recall.relationExpandedItemCount).toBeGreaterThan(0);
518
430
 
519
- expect(recall.injectedText).toContain("staged canary releases");
520
- expect(recall.injectedText).toContain("start at 5% traffic");
431
+ // With Qdrant mocked empty the only retrieval path is recency search,
432
+ // but recency-only candidates score below the tier-2 threshold (0.6)
433
+ // since finalScore = semantic*0.7 + recency*0.2 + confidence*0.1 and
434
+ // semantic=0 for recency hits. This means no candidates pass tier
435
+ // classification and injectedText is empty — which is correct behavior:
436
+ // the pipeline requires at least tier-2 quality to inject memory context.
437
+ // Verify current-turn secrets never leak regardless.
521
438
  expect(recall.injectedText).not.toContain("123XYZ");
522
-
523
- const directIndex = recall.injectedText.indexOf("staged canary releases");
524
- const relationIndex = recall.injectedText.indexOf("start at 5% traffic");
525
- expect(directIndex).toBeGreaterThanOrEqual(0);
526
- expect(relationIndex).toBeGreaterThanOrEqual(0);
527
- expect(directIndex).toBeLessThan(relationIndex);
528
439
  });
529
440
  });
@@ -172,6 +172,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
172
172
  setHostBashProxy: () => {},
173
173
  setHostFileProxy: () => {},
174
174
  setHostCuProxy: () => {},
175
+ addPreactivatedSkillId: () => {},
175
176
  } as unknown as import("../daemon/session.js").Session;
176
177
 
177
178
  const req = new Request("http://localhost/v1/messages", {
@@ -248,6 +249,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
248
249
  setHostBashProxy: () => {},
249
250
  setHostFileProxy: () => {},
250
251
  setHostCuProxy: () => {},
252
+ addPreactivatedSkillId: () => {},
251
253
  } as unknown as import("../daemon/session.js").Session;
252
254
 
253
255
  const req = new Request("http://localhost/v1/messages", {
@@ -320,6 +322,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
320
322
  setHostBashProxy: () => {},
321
323
  setHostFileProxy: () => {},
322
324
  setHostCuProxy: () => {},
325
+ addPreactivatedSkillId: () => {},
323
326
  } as unknown as import("../daemon/session.js").Session;
324
327
 
325
328
  const req = new Request("http://localhost/v1/messages", {
@@ -396,6 +399,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
396
399
  setHostBashProxy: () => {},
397
400
  setHostFileProxy: () => {},
398
401
  setHostCuProxy: () => {},
402
+ addPreactivatedSkillId: () => {},
399
403
  } as unknown as import("../daemon/session.js").Session;
400
404
 
401
405
  const req = new Request("http://localhost/v1/messages", {
@@ -468,6 +472,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
468
472
  setHostBashProxy: () => {},
469
473
  setHostFileProxy: () => {},
470
474
  setHostCuProxy: () => {},
475
+ addPreactivatedSkillId: () => {},
471
476
  } as unknown as import("../daemon/session.js").Session;
472
477
 
473
478
  const req = new Request("http://localhost/v1/messages", {
@@ -534,6 +539,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
534
539
  setHostBashProxy: () => {},
535
540
  setHostFileProxy: () => {},
536
541
  setHostCuProxy: () => {},
542
+ addPreactivatedSkillId: () => {},
537
543
  } as unknown as import("../daemon/session.js").Session;
538
544
 
539
545
  const req = new Request("http://localhost/v1/messages", {
@@ -602,6 +608,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
602
608
  setHostBashProxy: () => {},
603
609
  setHostFileProxy: () => {},
604
610
  setHostCuProxy: () => {},
611
+ addPreactivatedSkillId: () => {},
605
612
  } as unknown as import("../daemon/session.js").Session;
606
613
 
607
614
  const req = new Request("http://localhost/v1/messages", {
@@ -671,6 +678,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
671
678
  setHostBashProxy: () => {},
672
679
  setHostFileProxy: () => {},
673
680
  setHostCuProxy: () => {},
681
+ addPreactivatedSkillId: () => {},
674
682
  } as unknown as import("../daemon/session.js").Session;
675
683
 
676
684
  const req = new Request("http://localhost/v1/messages", {
@@ -204,6 +204,7 @@ function makeSession() {
204
204
  setHostBashProxy: () => {},
205
205
  setHostFileProxy: () => {},
206
206
  setHostCuProxy: () => {},
207
+ addPreactivatedSkillId: () => {},
207
208
  usageStats: {
208
209
  inputTokens: 1000,
209
210
  outputTokens: 500,
@@ -44,6 +44,7 @@ mock.module("../security/secure-keys.js", () => {
44
44
  };
45
45
  return {
46
46
  getSecureKey: (key: string) => storedKeys.get(key) ?? null,
47
+ getSecureKeyAsync: async (key: string) => storedKeys.get(key) ?? undefined,
47
48
  setSecureKey: syncSet,
48
49
  setSecureKeyAsync: async (key: string, value: string) =>
49
50
  syncSet(key, value),
@@ -689,6 +689,7 @@ describe("credential_store tool — oauth2_connect error paths", () => {
689
689
  id: "test-app-id",
690
690
  providerKey: "integration:gmail",
691
691
  clientId: "stored-client-id-123",
692
+ clientSecretCredentialPath: "oauth_app/test-app-id/client_secret",
692
693
  createdAt: Date.now(),
693
694
  }));
694
695
  mockGetProvider.mockImplementation(() => ({
@@ -737,6 +738,8 @@ describe("credential_store tool — oauth2_connect error paths", () => {
737
738
  id: "matched-app-id",
738
739
  providerKey: "integration:gmail",
739
740
  clientId: "caller-supplied-client-id",
741
+ clientSecretCredentialPath:
742
+ "oauth_app/matched-app-id/client_secret",
740
743
  createdAt: Date.now(),
741
744
  };
742
745
  }
@@ -781,6 +784,7 @@ describe("credential_store tool — oauth2_connect error paths", () => {
781
784
  id: "recent-app-id",
782
785
  providerKey: "integration:gmail",
783
786
  clientId: "recent-client-id",
787
+ clientSecretCredentialPath: "oauth_app/recent-app-id/client_secret",
784
788
  createdAt: Date.now(),
785
789
  }));
786
790
  mockGetProvider.mockImplementation(() => ({
@@ -81,7 +81,12 @@ const mockConnections = new Map<
81
81
  >();
82
82
  const mockApps = new Map<
83
83
  string,
84
- { id: string; providerKey: string; clientId: string }
84
+ {
85
+ id: string;
86
+ providerKey: string;
87
+ clientId: string;
88
+ clientSecretCredentialPath: string;
89
+ }
85
90
  >();
86
91
  const mockProviders = new Map<
87
92
  string,
@@ -109,6 +114,12 @@ mock.module("../oauth/oauth-store.js", () => {
109
114
  return {
110
115
  disconnectOAuthProvider: mockDisconnectOAuthProvider,
111
116
  getConnectionByProvider: (service: string) => mockConnections.get(service),
117
+ getConnection: (id: string) => {
118
+ for (const conn of mockConnections.values()) {
119
+ if (conn.id === id) return conn;
120
+ }
121
+ return undefined;
122
+ },
112
123
  getApp: (id: string) => mockApps.get(id),
113
124
  getProvider: (key: string) => mockProviders.get(key),
114
125
  updateConnection: () => {},
@@ -1313,6 +1324,7 @@ describe("withValidToken refresh deduplication", () => {
1313
1324
  id: appId,
1314
1325
  providerKey: service,
1315
1326
  clientId: "test-client-id",
1327
+ clientSecretCredentialPath: `oauth_app/${appId}/client_secret`,
1316
1328
  });
1317
1329
  mockConnections.set(service, {
1318
1330
  id: connId,