@vellumai/assistant 0.4.2 → 0.4.4

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 (221) hide show
  1. package/.env.example +3 -0
  2. package/ARCHITECTURE.md +124 -10
  3. package/README.md +43 -35
  4. package/docs/trusted-contact-access.md +20 -0
  5. package/package.json +1 -1
  6. package/scripts/ipc/generate-swift.ts +1 -0
  7. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +58 -120
  8. package/src/__tests__/access-request-decision.test.ts +0 -1
  9. package/src/__tests__/actor-token-service.test.ts +1099 -0
  10. package/src/__tests__/agent-loop.test.ts +51 -0
  11. package/src/__tests__/approval-routes-http.test.ts +2 -0
  12. package/src/__tests__/assistant-events-sse-hardening.test.ts +7 -5
  13. package/src/__tests__/assistant-id-boundary-guard.test.ts +415 -0
  14. package/src/__tests__/call-controller.test.ts +49 -0
  15. package/src/__tests__/call-pointer-message-composer.test.ts +171 -0
  16. package/src/__tests__/call-pointer-messages.test.ts +93 -3
  17. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +42 -0
  18. package/src/__tests__/call-routes-http.test.ts +0 -25
  19. package/src/__tests__/callback-handoff-copy.test.ts +186 -0
  20. package/src/__tests__/channel-approval-routes.test.ts +133 -12
  21. package/src/__tests__/channel-guardian.test.ts +0 -86
  22. package/src/__tests__/channel-readiness-service.test.ts +10 -16
  23. package/src/__tests__/checker.test.ts +33 -12
  24. package/src/__tests__/config-schema.test.ts +6 -0
  25. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +410 -0
  26. package/src/__tests__/conversation-routes-guardian-reply.test.ts +256 -0
  27. package/src/__tests__/conversation-routes.test.ts +12 -3
  28. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  29. package/src/__tests__/daemon-server-session-init.test.ts +4 -0
  30. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
  31. package/src/__tests__/guardian-actions-endpoint.test.ts +39 -13
  32. package/src/__tests__/guardian-dispatch.test.ts +8 -0
  33. package/src/__tests__/guardian-outbound-http.test.ts +4 -5
  34. package/src/__tests__/guardian-question-mode.test.ts +200 -0
  35. package/src/__tests__/guardian-routing-invariants.test.ts +178 -0
  36. package/src/__tests__/guardian-routing-state.test.ts +525 -0
  37. package/src/__tests__/handle-user-message-secret-resume.test.ts +2 -0
  38. package/src/__tests__/handlers-telegram-config.test.ts +0 -83
  39. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +55 -0
  40. package/src/__tests__/headless-browser-navigate.test.ts +2 -0
  41. package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
  42. package/src/__tests__/ingress-routes-http.test.ts +55 -0
  43. package/src/__tests__/ipc-snapshot.test.ts +18 -51
  44. package/src/__tests__/non-member-access-request.test.ts +159 -9
  45. package/src/__tests__/notification-decision-fallback.test.ts +129 -4
  46. package/src/__tests__/notification-decision-strategy.test.ts +106 -2
  47. package/src/__tests__/notification-guardian-path.test.ts +3 -0
  48. package/src/__tests__/recording-intent-handler.test.ts +1 -0
  49. package/src/__tests__/relay-server.test.ts +1475 -33
  50. package/src/__tests__/send-endpoint-busy.test.ts +5 -0
  51. package/src/__tests__/session-agent-loop.test.ts +1 -0
  52. package/src/__tests__/session-confirmation-signals.test.ts +523 -0
  53. package/src/__tests__/session-init.benchmark.test.ts +0 -2
  54. package/src/__tests__/session-runtime-assembly.test.ts +4 -1
  55. package/src/__tests__/session-surfaces-task-progress.test.ts +44 -1
  56. package/src/__tests__/session-tool-setup-app-refresh.test.ts +81 -2
  57. package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -1
  58. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -1
  59. package/src/__tests__/tool-executor.test.ts +21 -2
  60. package/src/__tests__/tool-grant-request-escalation.test.ts +333 -27
  61. package/src/__tests__/trusted-contact-approval-notifier.test.ts +678 -0
  62. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1064 -0
  63. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +11 -1
  64. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  65. package/src/__tests__/trusted-contact-verification.test.ts +0 -1
  66. package/src/__tests__/twilio-config.test.ts +2 -13
  67. package/src/__tests__/twilio-routes.test.ts +4 -3
  68. package/src/__tests__/update-bulletin.test.ts +0 -1
  69. package/src/agent/loop.ts +1 -1
  70. package/src/approvals/guardian-decision-primitive.ts +12 -3
  71. package/src/approvals/guardian-request-resolvers.ts +169 -11
  72. package/src/calls/call-constants.ts +29 -0
  73. package/src/calls/call-controller.ts +11 -3
  74. package/src/calls/call-domain.ts +33 -11
  75. package/src/calls/call-pointer-message-composer.ts +154 -0
  76. package/src/calls/call-pointer-messages.ts +106 -27
  77. package/src/calls/guardian-dispatch.ts +4 -2
  78. package/src/calls/relay-server.ts +921 -112
  79. package/src/calls/twilio-config.ts +4 -11
  80. package/src/calls/twilio-routes.ts +4 -6
  81. package/src/calls/types.ts +3 -1
  82. package/src/calls/voice-session-bridge.ts +4 -3
  83. package/src/cli/core-commands.ts +7 -4
  84. package/src/cli.ts +5 -4
  85. package/src/config/bundled-skills/agentmail/SKILL.md +4 -0
  86. package/src/config/bundled-skills/app-builder/SKILL.md +309 -10
  87. package/src/config/bundled-skills/app-builder/TOOLS.json +1 -1
  88. package/src/config/bundled-skills/email-setup/SKILL.md +1 -1
  89. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +105 -81
  90. package/src/config/bundled-skills/messaging/SKILL.md +61 -12
  91. package/src/config/bundled-skills/messaging/TOOLS.json +58 -0
  92. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +6 -1
  93. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +35 -0
  94. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +52 -0
  95. package/src/config/bundled-skills/phone-calls/SKILL.md +30 -39
  96. package/src/config/bundled-skills/twitter/SKILL.md +3 -3
  97. package/src/config/bundled-skills/vercel-token-setup/SKILL.md +215 -0
  98. package/src/config/calls-schema.ts +36 -0
  99. package/src/config/env.ts +22 -0
  100. package/src/config/feature-flag-registry.json +8 -8
  101. package/src/config/schema.ts +2 -2
  102. package/src/config/skills.ts +11 -0
  103. package/src/config/system-prompt.ts +11 -1
  104. package/src/config/templates/SOUL.md +2 -0
  105. package/src/config/vellum-skills/sms-setup/SKILL.md +71 -82
  106. package/src/config/vellum-skills/trusted-contacts/SKILL.md +8 -1
  107. package/src/config/vellum-skills/twilio-setup/SKILL.md +88 -73
  108. package/src/daemon/call-pointer-generators.ts +59 -0
  109. package/src/daemon/computer-use-session.ts +2 -5
  110. package/src/daemon/handlers/apps.ts +76 -20
  111. package/src/daemon/handlers/config-channels.ts +9 -61
  112. package/src/daemon/handlers/config-inbox.ts +11 -3
  113. package/src/daemon/handlers/config-ingress.ts +28 -3
  114. package/src/daemon/handlers/config-telegram.ts +12 -0
  115. package/src/daemon/handlers/config.ts +2 -6
  116. package/src/daemon/handlers/index.ts +2 -1
  117. package/src/daemon/handlers/pairing.ts +2 -0
  118. package/src/daemon/handlers/publish.ts +11 -46
  119. package/src/daemon/handlers/sessions.ts +59 -5
  120. package/src/daemon/handlers/shared.ts +17 -2
  121. package/src/daemon/ipc-contract/apps.ts +1 -0
  122. package/src/daemon/ipc-contract/inbox.ts +4 -0
  123. package/src/daemon/ipc-contract/integrations.ts +1 -97
  124. package/src/daemon/ipc-contract/messages.ts +47 -1
  125. package/src/daemon/ipc-contract/notifications.ts +11 -0
  126. package/src/daemon/ipc-contract-inventory.json +2 -4
  127. package/src/daemon/lifecycle.ts +17 -0
  128. package/src/daemon/server.ts +16 -2
  129. package/src/daemon/session-agent-loop-handlers.ts +20 -0
  130. package/src/daemon/session-agent-loop.ts +24 -12
  131. package/src/daemon/session-lifecycle.ts +1 -1
  132. package/src/daemon/session-process.ts +11 -1
  133. package/src/daemon/session-runtime-assembly.ts +6 -1
  134. package/src/daemon/session-surfaces.ts +32 -3
  135. package/src/daemon/session.ts +88 -1
  136. package/src/daemon/tool-side-effects.ts +22 -0
  137. package/src/home-base/prebuilt/brain-graph.html +1483 -0
  138. package/src/home-base/prebuilt/index.html +40 -0
  139. package/src/inbound/platform-callback-registration.ts +157 -0
  140. package/src/memory/canonical-guardian-store.ts +1 -1
  141. package/src/memory/conversation-crud.ts +2 -1
  142. package/src/memory/conversation-title-service.ts +16 -2
  143. package/src/memory/db-init.ts +8 -0
  144. package/src/memory/delivery-crud.ts +2 -1
  145. package/src/memory/guardian-action-store.ts +2 -1
  146. package/src/memory/guardian-approvals.ts +3 -2
  147. package/src/memory/ingress-invite-store.ts +12 -2
  148. package/src/memory/ingress-member-store.ts +4 -3
  149. package/src/memory/migrations/038-actor-token-records.ts +39 -0
  150. package/src/memory/migrations/124-voice-invite-display-metadata.ts +14 -0
  151. package/src/memory/migrations/index.ts +2 -0
  152. package/src/memory/schema.ts +26 -5
  153. package/src/messaging/provider-types.ts +24 -0
  154. package/src/messaging/provider.ts +7 -0
  155. package/src/messaging/providers/gmail/adapter.ts +127 -0
  156. package/src/messaging/providers/sms/adapter.ts +40 -37
  157. package/src/notifications/adapters/macos.ts +45 -2
  158. package/src/notifications/broadcaster.ts +16 -0
  159. package/src/notifications/copy-composer.ts +50 -2
  160. package/src/notifications/decision-engine.ts +22 -9
  161. package/src/notifications/destination-resolver.ts +16 -2
  162. package/src/notifications/emit-signal.ts +18 -9
  163. package/src/notifications/guardian-question-mode.ts +419 -0
  164. package/src/notifications/signal.ts +14 -3
  165. package/src/permissions/checker.ts +13 -1
  166. package/src/permissions/prompter.ts +14 -0
  167. package/src/providers/anthropic/client.ts +20 -0
  168. package/src/providers/provider-send-message.ts +15 -3
  169. package/src/runtime/access-request-helper.ts +82 -4
  170. package/src/runtime/actor-token-service.ts +234 -0
  171. package/src/runtime/actor-token-store.ts +236 -0
  172. package/src/runtime/actor-trust-resolver.ts +2 -2
  173. package/src/runtime/assistant-scope.ts +10 -0
  174. package/src/runtime/channel-approvals.ts +5 -3
  175. package/src/runtime/channel-readiness-service.ts +23 -64
  176. package/src/runtime/channel-readiness-types.ts +3 -4
  177. package/src/runtime/channel-retry-sweep.ts +4 -1
  178. package/src/runtime/confirmation-request-guardian-bridge.ts +197 -0
  179. package/src/runtime/guardian-action-followup-executor.ts +1 -1
  180. package/src/runtime/guardian-context-resolver.ts +82 -0
  181. package/src/runtime/guardian-outbound-actions.ts +5 -7
  182. package/src/runtime/guardian-reply-router.ts +67 -30
  183. package/src/runtime/guardian-vellum-migration.ts +57 -0
  184. package/src/runtime/http-server.ts +75 -31
  185. package/src/runtime/http-types.ts +13 -0
  186. package/src/runtime/ingress-service.ts +14 -0
  187. package/src/runtime/invite-redemption-service.ts +10 -1
  188. package/src/runtime/local-actor-identity.ts +76 -0
  189. package/src/runtime/middleware/actor-token.ts +271 -0
  190. package/src/runtime/middleware/twilio-validation.ts +2 -4
  191. package/src/runtime/routes/approval-routes.ts +82 -7
  192. package/src/runtime/routes/brain-graph-routes.ts +222 -0
  193. package/src/runtime/routes/call-routes.ts +2 -1
  194. package/src/runtime/routes/channel-readiness-routes.ts +71 -0
  195. package/src/runtime/routes/channel-route-shared.ts +3 -3
  196. package/src/runtime/routes/conversation-attention-routes.ts +2 -1
  197. package/src/runtime/routes/conversation-routes.ts +142 -53
  198. package/src/runtime/routes/events-routes.ts +22 -8
  199. package/src/runtime/routes/guardian-action-routes.ts +45 -3
  200. package/src/runtime/routes/guardian-approval-interception.ts +29 -0
  201. package/src/runtime/routes/guardian-bootstrap-routes.ts +145 -0
  202. package/src/runtime/routes/inbound-conversation.ts +4 -3
  203. package/src/runtime/routes/inbound-message-handler.ts +147 -5
  204. package/src/runtime/routes/ingress-routes.ts +2 -0
  205. package/src/runtime/routes/integration-routes.ts +7 -15
  206. package/src/runtime/routes/pairing-routes.ts +163 -0
  207. package/src/runtime/routes/twilio-routes.ts +934 -0
  208. package/src/runtime/tool-grant-request-helper.ts +3 -1
  209. package/src/security/oauth2.ts +27 -2
  210. package/src/security/token-manager.ts +46 -10
  211. package/src/tools/browser/browser-execution.ts +4 -3
  212. package/src/tools/browser/browser-handoff.ts +10 -18
  213. package/src/tools/browser/browser-manager.ts +80 -25
  214. package/src/tools/browser/browser-screencast.ts +35 -119
  215. package/src/tools/calls/call-start.ts +2 -1
  216. package/src/tools/permission-checker.ts +15 -4
  217. package/src/tools/terminal/parser.ts +12 -0
  218. package/src/tools/tool-approval-handler.ts +244 -19
  219. package/src/workspace/git-service.ts +19 -0
  220. package/src/__tests__/handlers-twilio-config.test.ts +0 -1928
  221. package/src/daemon/handlers/config-twilio.ts +0 -1082
@@ -55,21 +55,67 @@ describe('notification decision strategy', () => {
55
55
  expect(copy.vellum!.body).toContain('What is the gate code?');
56
56
  });
57
57
 
58
- test('guardian.question template includes request-code instructions when present', () => {
58
+ test('guardian.question template includes free-text answer instructions when requestCode is present', () => {
59
59
  const signal = makeSignal({
60
60
  sourceEventName: 'guardian.question',
61
61
  contextPayload: {
62
+ requestId: 'req-pending-1',
62
63
  questionText: 'What is the gate code?',
63
64
  requestCode: 'A1B2C3',
65
+ requestKind: 'pending_question',
66
+ callSessionId: 'call-1',
67
+ activeGuardianRequestCount: 1,
64
68
  },
65
69
  });
66
70
 
67
71
  const copy = composeFallbackCopy(signal, channels);
68
72
  expect(copy.vellum).toBeDefined();
69
73
  expect(copy.vellum!.body).toContain('A1B2C3');
74
+ expect(copy.vellum!.body).toContain('<your answer>');
75
+ expect(copy.vellum!.body).not.toContain('approve');
76
+ expect(copy.vellum!.body).not.toContain('reject');
77
+ expect(copy.telegram!.deliveryText).toContain('A1B2C3');
78
+ });
79
+
80
+ test('guardian.question template uses approve/reject instructions for approval-kind request', () => {
81
+ const signal = makeSignal({
82
+ sourceEventName: 'guardian.question',
83
+ contextPayload: {
84
+ requestId: 'req-grant-1',
85
+ questionText: 'Allow running host_bash?',
86
+ requestCode: 'D4E5F6',
87
+ requestKind: 'tool_grant_request',
88
+ toolName: 'host_bash',
89
+ },
90
+ });
91
+
92
+ const copy = composeFallbackCopy(signal, channels);
93
+ expect(copy.vellum).toBeDefined();
94
+ expect(copy.vellum!.body).toContain('D4E5F6');
70
95
  expect(copy.vellum!.body).toContain('approve');
71
96
  expect(copy.vellum!.body).toContain('reject');
72
- expect(copy.telegram!.deliveryText).toContain('A1B2C3');
97
+ });
98
+
99
+ test('guardian.question template uses approve/reject for tool-backed pending_question payloads', () => {
100
+ const signal = makeSignal({
101
+ sourceEventName: 'guardian.question',
102
+ contextPayload: {
103
+ requestId: 'req-voice-tool-1',
104
+ questionText: 'Allow send_email to bob@example.com?',
105
+ requestCode: 'A1B2C3',
106
+ requestKind: 'pending_question',
107
+ callSessionId: 'call-1',
108
+ activeGuardianRequestCount: 1,
109
+ toolName: 'send_email',
110
+ },
111
+ });
112
+
113
+ const copy = composeFallbackCopy(signal, channels);
114
+ expect(copy.vellum).toBeDefined();
115
+ expect(copy.vellum!.body).toContain('A1B2C3');
116
+ expect(copy.vellum!.body).toContain('approve');
117
+ expect(copy.vellum!.body).toContain('reject');
118
+ expect(copy.vellum!.body).not.toContain('<your answer>');
73
119
  });
74
120
 
75
121
  test('reminder.fired template uses message from payload', () => {
@@ -196,6 +242,64 @@ describe('notification decision strategy', () => {
196
242
  expect(copy.vellum!.body).toContain('open invite flow');
197
243
  });
198
244
 
245
+ test('ingress.access_request template includes revoked-member context when provided', () => {
246
+ const signal = makeSignal({
247
+ sourceEventName: 'ingress.access_request',
248
+ contextPayload: {
249
+ senderIdentifier: 'Charlie',
250
+ previousMemberStatus: 'revoked',
251
+ },
252
+ });
253
+
254
+ const copy = composeFallbackCopy(signal, channels);
255
+ expect(copy.vellum).toBeDefined();
256
+ expect(copy.vellum!.body).toContain('previously revoked');
257
+ });
258
+
259
+ test('ingress.access_request template includes caller name for voice-originated requests', () => {
260
+ // In production, senderIdentifier resolves to senderName for voice
261
+ // calls (senderName || senderUsername || senderExternalUserId), so
262
+ // both values are the caller's name. The phone number arrives via
263
+ // senderExternalUserId and should appear in the parenthetical.
264
+ const signal = makeSignal({
265
+ sourceEventName: 'ingress.access_request',
266
+ contextPayload: {
267
+ senderIdentifier: 'Alice Smith',
268
+ senderName: 'Alice Smith',
269
+ senderExternalUserId: '+15559998888',
270
+ sourceChannel: 'voice',
271
+ requestCode: 'V1C2E3',
272
+ },
273
+ });
274
+
275
+ const copy = composeFallbackCopy(signal, channels);
276
+ expect(copy.vellum).toBeDefined();
277
+ expect(copy.vellum!.title).toBe('Access Request');
278
+ // Voice-originated requests should include the caller name and phone number in parentheses
279
+ expect(copy.vellum!.body).toContain('Alice Smith');
280
+ expect(copy.vellum!.body).toContain('(+15559998888)');
281
+ expect(copy.vellum!.body).toContain('calling');
282
+ });
283
+
284
+ test('ingress.access_request template falls back to non-voice copy when sourceChannel is not voice', () => {
285
+ const signal = makeSignal({
286
+ sourceEventName: 'ingress.access_request',
287
+ contextPayload: {
288
+ senderIdentifier: 'user-123',
289
+ senderName: 'Bob Jones',
290
+ sourceChannel: 'telegram',
291
+ requestCode: 'T1G2M3',
292
+ },
293
+ });
294
+
295
+ const copy = composeFallbackCopy(signal, channels);
296
+ expect(copy.vellum).toBeDefined();
297
+ // Non-voice should use the standard "requesting access" text, not "calling"
298
+ expect(copy.vellum!.body).toContain('user-123');
299
+ expect(copy.vellum!.body).toContain('requesting access');
300
+ expect(copy.vellum!.body).not.toContain('calling');
301
+ });
302
+
199
303
  test('ingress.access_request Telegram deliveryText is concise', () => {
200
304
  const signal = makeSignal({
201
305
  sourceEventName: 'ingress.access_request',
@@ -181,6 +181,9 @@ describe('ASK_GUARDIAN canonical notification path', () => {
181
181
  const payload = signalParams.contextPayload as Record<string, unknown>;
182
182
  expect(payload.questionText).toBe('What is the gate code?');
183
183
  expect(payload.callSessionId).toBe(session.id);
184
+ expect(payload.requestKind).toBe('pending_question');
185
+ expect(payload.toolName).toBeUndefined();
186
+ expect(payload.pendingQuestionId).toBeUndefined();
184
187
  expect(payload.requestId).toBeDefined();
185
188
  expect(payload.requestCode).toBeDefined();
186
189
  });
@@ -391,6 +391,7 @@ function createCtx(overrides?: Partial<HandlerContext>): {
391
391
  setChannelCapabilities: noop,
392
392
  setGuardianContext: noop,
393
393
  setCommandIntent: noop,
394
+ updateClient: noop,
394
395
  processMessage: async () => {},
395
396
  getQueueDepth: () => 0,
396
397
  setPreactivatedSkillIds: noop,