@vellumai/assistant 0.4.35 → 0.4.37

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/AGENTS.md +1 -1
  2. package/ARCHITECTURE.md +44 -49
  3. package/README.md +32 -20
  4. package/docs/architecture/keychain-broker.md +186 -0
  5. package/docs/architecture/security.md +110 -116
  6. package/docs/runbook-trusted-contacts.md +2 -2
  7. package/docs/skills.md +25 -25
  8. package/package.json +5 -2
  9. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +11 -2
  10. package/src/__tests__/actor-token-service.test.ts +1 -0
  11. package/src/__tests__/amazon-cdp-integration.test.ts +74 -0
  12. package/src/__tests__/assistant-feature-flags-integration.test.ts +38 -9
  13. package/src/__tests__/assistant-id-boundary-guard.test.ts +29 -0
  14. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  15. package/src/__tests__/bundle-scanner.test.ts +1 -1
  16. package/src/__tests__/channel-guardian.test.ts +102 -102
  17. package/src/__tests__/channel-invite-transport.test.ts +155 -256
  18. package/src/__tests__/channel-readiness-routes.test.ts +336 -0
  19. package/src/__tests__/checker.test.ts +6 -6
  20. package/src/__tests__/chrome-cdp.test.ts +350 -0
  21. package/src/__tests__/computer-use-session-lifecycle.test.ts +3 -3
  22. package/src/__tests__/computer-use-session-working-dir.test.ts +86 -52
  23. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +1 -1
  24. package/src/__tests__/config-loader-migration.test.ts +85 -0
  25. package/src/__tests__/conversation-pairing.test.ts +370 -5
  26. package/src/__tests__/credential-broker-browser-fill.test.ts +1 -10
  27. package/src/__tests__/credential-broker-server-use.test.ts +1 -10
  28. package/src/__tests__/credential-security-e2e.test.ts +7 -1
  29. package/src/__tests__/credential-security-invariants.test.ts +14 -20
  30. package/src/__tests__/credential-vault-unit.test.ts +1 -11
  31. package/src/__tests__/credential-vault.test.ts +5 -19
  32. package/src/__tests__/credentials-cli.test.ts +814 -0
  33. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +23 -4
  34. package/src/__tests__/email-invite-adapter.test.ts +78 -0
  35. package/src/__tests__/email-service-config-fallback.test.ts +102 -0
  36. package/src/__tests__/encrypted-store.test.ts +6 -6
  37. package/src/__tests__/ephemeral-permissions.test.ts +3 -3
  38. package/src/__tests__/gateway-only-enforcement.test.ts +5 -1
  39. package/src/__tests__/guardian-actions-endpoint.test.ts +70 -12
  40. package/src/__tests__/guardian-outbound-http.test.ts +53 -47
  41. package/src/__tests__/handle-user-message-secret-resume.test.ts +23 -0
  42. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +32 -23
  43. package/src/__tests__/handlers-telegram-config.test.ts +8 -2
  44. package/src/__tests__/handlers-twitter-config.test.ts +2 -2
  45. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +108 -7
  46. package/src/__tests__/ingress-reconcile.test.ts +6 -0
  47. package/src/__tests__/intent-routing.test.ts +23 -4
  48. package/src/__tests__/invite-routes-http.test.ts +12 -0
  49. package/src/__tests__/ipc-snapshot.test.ts +8 -2
  50. package/src/__tests__/keychain-broker-client.test.ts +543 -0
  51. package/src/__tests__/llm-usage-store.test.ts +344 -0
  52. package/src/__tests__/mcp-client-auth.test.ts +2 -2
  53. package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
  54. package/src/__tests__/migration-transport.test.ts +49 -0
  55. package/src/__tests__/notification-broadcaster.test.ts +205 -5
  56. package/src/__tests__/notification-deep-link.test.ts +365 -1
  57. package/src/__tests__/oauth-connect-handler.test.ts +2 -2
  58. package/src/__tests__/onboarding-starter-tasks.test.ts +17 -4
  59. package/src/__tests__/proxy-approval-callback.test.ts +1 -1
  60. package/src/__tests__/recording-handler.test.ts +1 -1
  61. package/src/__tests__/recording-intent-handler.test.ts +6 -1
  62. package/src/__tests__/recording-state-machine.test.ts +1 -1
  63. package/src/__tests__/relay-server.test.ts +9 -1
  64. package/src/__tests__/ride-shotgun-handler.test.ts +499 -0
  65. package/src/__tests__/runtime-attachment-metadata.test.ts +160 -1
  66. package/src/__tests__/script-proxy-injection-runtime.test.ts +299 -2
  67. package/src/__tests__/script-proxy-profile-template-fallback.test.ts +1 -1
  68. package/src/__tests__/secret-onetime-send.test.ts +8 -2
  69. package/src/__tests__/secure-keys.test.ts +175 -216
  70. package/src/__tests__/session-confirmation-signals.test.ts +1 -1
  71. package/src/__tests__/session-messaging-secret-redirect.test.ts +1 -1
  72. package/src/__tests__/session-queue.test.ts +2 -1
  73. package/src/__tests__/session-tool-setup-app-refresh.test.ts +2 -2
  74. package/src/__tests__/skill-feature-flags-integration.test.ts +29 -4
  75. package/src/__tests__/skill-feature-flags.test.ts +12 -9
  76. package/src/__tests__/skill-load-feature-flag.test.ts +26 -5
  77. package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
  78. package/src/__tests__/skills.test.ts +34 -4
  79. package/src/__tests__/slack-channel-config.test.ts +2 -2
  80. package/src/__tests__/system-prompt.test.ts +26 -4
  81. package/src/__tests__/telegram-bot-username-resolution.test.ts +212 -0
  82. package/src/__tests__/telegram-invite-adapter.test.ts +164 -0
  83. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  84. package/src/__tests__/tool-permission-simulate-handler.test.ts +8 -2
  85. package/src/__tests__/trusted-contact-approval-notifier.test.ts +9 -1
  86. package/src/__tests__/twitter-auth-handler.test.ts +2 -2
  87. package/src/__tests__/twitter-oauth-client.test.ts +1 -1
  88. package/src/__tests__/usage-routes.test.ts +339 -0
  89. package/src/__tests__/whatsapp-invite-adapter.test.ts +94 -0
  90. package/src/agent/loop.ts +3 -0
  91. package/src/amazon/checkout.ts +0 -1
  92. package/src/approvals/guardian-request-resolvers.ts +9 -1
  93. package/src/bundler/app-bundler.ts +28 -12
  94. package/src/bundler/bundle-scanner.ts +1 -1
  95. package/src/bundler/bundle-signer.ts +3 -3
  96. package/src/bundler/manifest.ts +1 -1
  97. package/src/bundler/signature-verifier.ts +3 -3
  98. package/src/channels/config.ts +1 -1
  99. package/src/cli/AGENTS.md +63 -0
  100. package/src/cli/__tests__/notifications.test.ts +470 -0
  101. package/src/cli/amazon.ts +344 -167
  102. package/src/cli/audit.ts +85 -0
  103. package/src/cli/autonomy.ts +369 -0
  104. package/src/cli/channels.ts +51 -0
  105. package/src/cli/completions.ts +208 -0
  106. package/src/cli/config.ts +220 -0
  107. package/src/cli/contacts.ts +471 -0
  108. package/src/cli/credentials.ts +564 -0
  109. package/src/cli/default-action.ts +14 -0
  110. package/src/cli/dev.ts +131 -0
  111. package/src/cli/doctor.ts +398 -0
  112. package/src/cli/email.ts +494 -0
  113. package/src/cli/influencer.ts +72 -0
  114. package/src/cli/integrations.ts +248 -57
  115. package/src/cli/keys.ts +114 -0
  116. package/src/cli/map.ts +46 -54
  117. package/src/cli/mcp.ts +111 -3
  118. package/src/cli/{config-commands.ts → memory.ts} +134 -245
  119. package/src/cli/notifications.ts +407 -0
  120. package/src/cli/program.ts +65 -0
  121. package/src/cli/reference.ts +48 -0
  122. package/src/cli/sequence.ts +154 -0
  123. package/src/cli/sessions.ts +262 -0
  124. package/src/cli/trust.ts +175 -0
  125. package/src/cli/twitter.ts +323 -106
  126. package/src/config/__tests__/build-cli-reference-section.test.ts +49 -0
  127. package/src/config/bundled-skills/amazon/SKILL.md +2 -2
  128. package/src/config/bundled-skills/app-builder/TOOLS.json +26 -0
  129. package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +13 -0
  130. package/src/config/bundled-skills/contacts/SKILL.md +178 -10
  131. package/src/config/bundled-skills/doordash/doordash-cli.ts +23 -168
  132. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +135 -34
  133. package/src/config/bundled-skills/messaging/tools/shared.ts +4 -1
  134. package/src/config/bundled-skills/twilio-setup/SKILL.md +70 -17
  135. package/src/config/bundled-tool-registry.ts +2 -0
  136. package/src/config/core-schema.ts +7 -0
  137. package/src/config/feature-flag-registry.json +16 -0
  138. package/src/config/loader.ts +26 -0
  139. package/src/config/schema.ts +4 -0
  140. package/src/config/skill-state.ts +0 -13
  141. package/src/config/system-prompt.ts +27 -0
  142. package/src/contacts/contact-store.ts +25 -0
  143. package/src/daemon/computer-use-session.ts +1 -1
  144. package/src/daemon/handlers/apps.ts +1 -0
  145. package/src/daemon/handlers/config-channels.ts +3 -3
  146. package/src/daemon/handlers/config-dispatch.ts +29 -0
  147. package/src/daemon/handlers/config-inbox.ts +4 -3
  148. package/src/daemon/handlers/config.ts +3 -43
  149. package/src/daemon/handlers/contacts.ts +34 -0
  150. package/src/daemon/handlers/index.ts +17 -3
  151. package/src/daemon/handlers/session-user-message.ts +7 -0
  152. package/src/daemon/handlers/sessions.ts +21 -2
  153. package/src/daemon/handlers/shared.ts +17 -0
  154. package/src/daemon/ipc-contract/apps.ts +2 -0
  155. package/src/daemon/ipc-contract/computer-use.ts +9 -0
  156. package/src/daemon/ipc-contract/contacts.ts +3 -3
  157. package/src/daemon/ipc-contract/inbox.ts +2 -0
  158. package/src/daemon/ipc-contract/messages.ts +4 -0
  159. package/src/daemon/ipc-contract/sessions.ts +8 -0
  160. package/src/daemon/ipc-contract-inventory.json +1 -0
  161. package/src/daemon/lifecycle.ts +0 -5
  162. package/src/daemon/ride-shotgun-handler.ts +139 -25
  163. package/src/daemon/session-agent-loop-handlers.ts +100 -0
  164. package/src/daemon/session-agent-loop.ts +72 -0
  165. package/src/daemon/session-tool-setup.ts +7 -0
  166. package/src/daemon/session.ts +23 -1
  167. package/src/daemon/tool-side-effects.ts +39 -1
  168. package/src/email/service.ts +59 -2
  169. package/src/index.ts +2 -60
  170. package/src/mcp/mcp-oauth-provider.ts +90 -8
  171. package/src/media/app-icon-generator.ts +86 -0
  172. package/src/memory/db-init.ts +11 -0
  173. package/src/memory/llm-usage-store.ts +186 -0
  174. package/src/memory/migrations/137-usage-dashboard-indexes.ts +26 -0
  175. package/src/memory/migrations/139-drop-usage-composite-indexes.ts +30 -0
  176. package/src/memory/migrations/index.ts +2 -0
  177. package/src/memory/schema-migration.ts +1 -0
  178. package/src/memory/shared-app-links-store.ts +1 -1
  179. package/src/messaging/registry.ts +27 -0
  180. package/src/notifications/README.md +79 -70
  181. package/src/notifications/broadcaster.ts +2 -1
  182. package/src/notifications/conversation-pairing.ts +147 -13
  183. package/src/notifications/copy-composer.ts +7 -3
  184. package/src/notifications/destination-resolver.ts +14 -1
  185. package/src/notifications/emit-signal.ts +3 -2
  186. package/src/notifications/signal.ts +105 -1
  187. package/src/notifications/types.ts +16 -0
  188. package/src/permissions/checker.ts +29 -3
  189. package/src/permissions/prompter.ts +11 -3
  190. package/src/runtime/access-request-helper.ts +2 -1
  191. package/src/runtime/auth/route-policy.ts +7 -1
  192. package/src/runtime/channel-invite-transport.ts +40 -63
  193. package/src/runtime/channel-invite-transports/email.ts +13 -39
  194. package/src/runtime/channel-invite-transports/slack.ts +5 -34
  195. package/src/runtime/channel-invite-transports/sms.ts +8 -29
  196. package/src/runtime/channel-invite-transports/telegram.ts +69 -28
  197. package/src/runtime/channel-invite-transports/voice.ts +0 -7
  198. package/src/runtime/channel-invite-transports/whatsapp.ts +43 -0
  199. package/src/runtime/channel-readiness-service.ts +202 -45
  200. package/src/runtime/confirmation-request-guardian-bridge.ts +2 -1
  201. package/src/runtime/guardian-outbound-actions.ts +8 -5
  202. package/src/runtime/http-server.ts +2 -0
  203. package/src/runtime/invite-instruction-generator.ts +178 -0
  204. package/src/runtime/invite-service.ts +22 -25
  205. package/src/runtime/migrations/migration-transport.ts +13 -0
  206. package/src/runtime/routes/app-routes.ts +1 -1
  207. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +8 -7
  208. package/src/runtime/routes/channel-readiness-routes.ts +30 -11
  209. package/src/runtime/routes/contact-routes.ts +54 -26
  210. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +1 -1
  211. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +2 -1
  212. package/src/runtime/routes/inbound-stages/verification-intercept.ts +2 -1
  213. package/src/runtime/routes/integration-routes.ts +1 -1
  214. package/src/runtime/routes/invite-routes.ts +1 -1
  215. package/src/runtime/routes/secret-routes.ts +31 -7
  216. package/src/runtime/routes/twilio-routes.ts +32 -1
  217. package/src/runtime/routes/usage-routes.ts +114 -0
  218. package/src/runtime/tool-grant-request-helper.ts +2 -1
  219. package/src/security/encrypted-store.ts +9 -5
  220. package/src/security/keychain-broker-client.ts +393 -0
  221. package/src/security/secure-keys.ts +106 -321
  222. package/src/tools/apps/executors.ts +73 -0
  223. package/src/tools/browser/auto-navigate.ts +15 -6
  224. package/src/tools/browser/chrome-cdp.ts +211 -0
  225. package/src/tools/browser/network-recorder.test.ts +83 -0
  226. package/src/tools/browser/network-recorder.ts +8 -7
  227. package/src/tools/browser/x-auto-navigate.ts +12 -6
  228. package/src/tools/credentials/policy-types.ts +24 -0
  229. package/src/tools/credentials/vault.ts +22 -27
  230. package/src/tools/network/script-proxy/session-manager.ts +47 -3
  231. package/src/tools/permission-checker.ts +1 -0
  232. package/src/tools/types.ts +2 -0
  233. package/src/tools/ui-surface/definitions.ts +1 -2
  234. package/src/tools/watch/watch-state.ts +2 -0
  235. package/src/__tests__/key-migration.test.ts +0 -240
  236. package/src/__tests__/keychain.test.ts +0 -286
  237. package/src/cli/core-commands.ts +0 -899
  238. package/src/security/keychain-to-encrypted-migration.ts +0 -66
  239. package/src/security/keychain.ts +0 -490
@@ -35,7 +35,10 @@ let currentConfig: Record<string, unknown> = {
35
35
  const DECLARED_FLAG_KEY = "feature_flags.hatch-new-assistant.enabled";
36
36
  const DECLARED_SKILL_ID = "hatch-new-assistant";
37
37
 
38
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
39
+ const realPlatform = require("../util/platform.js");
38
40
  mock.module("../util/platform.js", () => ({
41
+ ...realPlatform,
39
42
  getRootDir: () => TEST_DIR,
40
43
  getDataDir: () => TEST_DIR,
41
44
  getWorkspaceDir: () => TEST_DIR,
@@ -59,38 +62,60 @@ mock.module("../util/platform.js", () => ({
59
62
  isWindows: () => false,
60
63
  getPlatformName: () => "linux",
61
64
  getClipboardCommand: () => null,
65
+ readSessionToken: () => null,
62
66
  removeSocketFile: () => {},
63
67
  migratePath: () => {},
64
68
  migrateToWorkspaceLayout: () => {},
65
69
  migrateToDataLayout: () => {},
66
70
  }));
67
71
 
72
+ const noopLogger = new Proxy({} as Record<string, unknown>, {
73
+ get: (_target, prop) => (prop === "child" ? () => noopLogger : () => {}),
74
+ });
75
+
76
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
77
+ const realLogger = require("../util/logger.js");
68
78
  mock.module("../util/logger.js", () => ({
69
- getLogger: () =>
70
- new Proxy({} as Record<string, unknown>, {
71
- get: () => () => {},
72
- }),
79
+ ...realLogger,
80
+ getLogger: () => noopLogger,
81
+ getCliLogger: () => noopLogger,
73
82
  isDebug: () => false,
74
83
  truncateForLog: (v: string) => v,
84
+ initLogger: () => {},
85
+ pruneOldLogFiles: () => 0,
75
86
  }));
76
87
 
77
88
  mock.module("../config/loader.js", () => ({
78
89
  getConfig: () => currentConfig,
90
+ loadConfig: () => currentConfig,
91
+ loadRawConfig: () => ({}),
92
+ saveConfig: () => {},
93
+ saveRawConfig: () => {},
94
+ invalidateConfigCache: () => {},
95
+ getNestedValue: () => undefined,
96
+ setNestedValue: () => {},
97
+ syncConfigToLockfile: () => {},
79
98
  }));
80
99
 
100
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
101
+ const realUserReference = require("../config/user-reference.js");
81
102
  mock.module("../config/user-reference.js", () => ({
103
+ ...realUserReference,
82
104
  resolveUserReference: () => "TestUser",
83
105
  resolveUserPronouns: () => null,
84
106
  }));
85
107
 
108
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
109
+ const realCredentialMetadataStore = require("../tools/credentials/metadata-store.js");
86
110
  mock.module("../tools/credentials/metadata-store.js", () => ({
111
+ ...realCredentialMetadataStore,
87
112
  listCredentialMetadata: () => [],
88
113
  }));
89
114
 
90
115
  const { buildSystemPrompt } = await import("../config/system-prompt.js");
91
116
  const { isAssistantFeatureFlagEnabled } =
92
117
  await import("../config/assistant-feature-flags.js");
93
- const { isSkillFeatureEnabled } = await import("../config/skill-state.js");
118
+ const { skillFlagKey } = await import("../config/skill-state.js");
94
119
 
95
120
  // ---------------------------------------------------------------------------
96
121
  // Setup / Teardown
@@ -301,18 +326,22 @@ describe("isAssistantFeatureFlagEnabled", () => {
301
326
  });
302
327
  });
303
328
 
304
- describe("legacy isSkillFeatureEnabled backward compat", () => {
305
- test("delegates to the canonical resolver", () => {
329
+ describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
330
+ test("resolves skill flag via canonical path", () => {
306
331
  const config = {
307
332
  assistantFeatureFlagValues: { [DECLARED_FLAG_KEY]: false },
308
333
  } as any;
309
334
 
310
- expect(isSkillFeatureEnabled(DECLARED_SKILL_ID, config)).toBe(false);
335
+ expect(
336
+ isAssistantFeatureFlagEnabled(skillFlagKey(DECLARED_SKILL_ID), config),
337
+ ).toBe(false);
311
338
  });
312
339
 
313
340
  test("disabled when no override set (registry default is false)", () => {
314
341
  const config = {} as any;
315
342
 
316
- expect(isSkillFeatureEnabled(DECLARED_SKILL_ID, config)).toBe(false);
343
+ expect(
344
+ isAssistantFeatureFlagEnabled(skillFlagKey(DECLARED_SKILL_ID), config),
345
+ ).toBe(false);
317
346
  });
318
347
  });
@@ -594,6 +594,35 @@ describe("assistant ID boundary", () => {
594
594
  match;
595
595
  match = exportFnStartRegex.exec(content)
596
596
  ) {
597
+ // Skip matches that fall inside comments. Find the beginning of
598
+ // the line containing the match and check for comment prefixes.
599
+ const lineStart = content.lastIndexOf("\n", match.index) + 1;
600
+ const linePrefix = content.slice(lineStart, match.index).trim();
601
+ if (linePrefix.startsWith("//")) {
602
+ continue;
603
+ }
604
+ // For block comments: check if the match is inside an unclosed
605
+ // block comment. A prefix starting with `*` (continuation line)
606
+ // or `/*` only counts if there is no closing `*/` between the
607
+ // last `/*` opener and the match position — otherwise the
608
+ // comment was already closed (e.g. `/** docs */ export …`).
609
+ if (linePrefix.startsWith("*") || linePrefix.startsWith("/*")) {
610
+ const textBeforeMatch = content.slice(lineStart, match.index);
611
+ const lastOpen = textBeforeMatch.lastIndexOf("/*");
612
+ if (lastOpen === -1) {
613
+ // No block-comment opener on this line but starts with `*`,
614
+ // so it's a continuation line inside a multi-line comment.
615
+ continue;
616
+ }
617
+ const closeBetween = textBeforeMatch.indexOf("*/", lastOpen + 2);
618
+ if (closeBetween === -1) {
619
+ // The block comment is still open at the match position.
620
+ continue;
621
+ }
622
+ // The block comment was closed before the match — fall through
623
+ // and evaluate the match normally.
624
+ }
625
+
597
626
  // Find the matching closing paren to extract the full parameter list,
598
627
  // which may span multiple lines.
599
628
  const parenStart = match.index + match[0].length - 1; // index of '('
@@ -60,7 +60,7 @@ let mockGetCredentialMetadata: ReturnType<typeof mock>;
60
60
  mock.module("../security/secure-keys.js", () => ({
61
61
  getSecureKey: (...args: unknown[]) => mockGetSecureKey(...args),
62
62
  setSecureKey: () => true,
63
- deleteSecureKey: () => true,
63
+ deleteSecureKey: () => "deleted",
64
64
  listSecureKeys: () => [],
65
65
  getBackendType: () => "encrypted",
66
66
  _resetBackend: () => {},
@@ -49,7 +49,7 @@ async function createBundle(
49
49
  const data = await zip.generateAsync({ type: "uint8array" });
50
50
  const path = join(
51
51
  tempDir,
52
- `test-${Date.now()}-${Math.random().toString(36).slice(2)}.vellumapp`,
52
+ `test-${Date.now()}-${Math.random().toString(36).slice(2)}.vellum`,
53
53
  );
54
54
  await Bun.write(path, data);
55
55
  return path;