@vellumai/assistant 0.3.27 → 0.4.0

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 (247) hide show
  1. package/ARCHITECTURE.md +81 -4
  2. package/Dockerfile +2 -2
  3. package/bun.lock +4 -1
  4. package/docs/trusted-contact-access.md +9 -2
  5. package/package.json +6 -3
  6. package/scripts/ipc/generate-swift.ts +9 -5
  7. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +80 -0
  8. package/src/__tests__/agent-loop-thinking.test.ts +1 -1
  9. package/src/__tests__/agent-loop.test.ts +119 -0
  10. package/src/__tests__/approval-routes-http.test.ts +13 -5
  11. package/src/__tests__/asset-materialize-tool.test.ts +2 -0
  12. package/src/__tests__/asset-search-tool.test.ts +2 -0
  13. package/src/__tests__/assistant-events-sse-hardening.test.ts +4 -2
  14. package/src/__tests__/attachments-store.test.ts +2 -0
  15. package/src/__tests__/browser-skill-endstate.test.ts +3 -3
  16. package/src/__tests__/bundled-asset.test.ts +107 -0
  17. package/src/__tests__/call-controller.test.ts +30 -29
  18. package/src/__tests__/call-routes-http.test.ts +34 -32
  19. package/src/__tests__/call-start-guardian-guard.test.ts +2 -0
  20. package/src/__tests__/canonical-guardian-store.test.ts +636 -0
  21. package/src/__tests__/channel-approval-routes.test.ts +174 -1
  22. package/src/__tests__/channel-invite-transport.test.ts +6 -6
  23. package/src/__tests__/channel-reply-delivery.test.ts +19 -0
  24. package/src/__tests__/channel-retry-sweep.test.ts +130 -0
  25. package/src/__tests__/clarification-resolver.test.ts +2 -0
  26. package/src/__tests__/claude-code-skill-regression.test.ts +2 -0
  27. package/src/__tests__/claude-code-tool-profiles.test.ts +2 -0
  28. package/src/__tests__/commit-message-enrichment-service.test.ts +9 -1
  29. package/src/__tests__/computer-use-session-lifecycle.test.ts +2 -0
  30. package/src/__tests__/computer-use-session-working-dir.test.ts +1 -0
  31. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +2 -0
  32. package/src/__tests__/config-schema.test.ts +5 -5
  33. package/src/__tests__/config-watcher.test.ts +3 -1
  34. package/src/__tests__/connection-policy.test.ts +14 -5
  35. package/src/__tests__/contacts-tools.test.ts +3 -1
  36. package/src/__tests__/contradiction-checker.test.ts +2 -0
  37. package/src/__tests__/conversation-pairing.test.ts +10 -0
  38. package/src/__tests__/conversation-routes.test.ts +1 -1
  39. package/src/__tests__/credential-security-invariants.test.ts +16 -6
  40. package/src/__tests__/credential-vault-unit.test.ts +2 -2
  41. package/src/__tests__/credential-vault.test.ts +5 -4
  42. package/src/__tests__/daemon-lifecycle.test.ts +9 -0
  43. package/src/__tests__/daemon-server-session-init.test.ts +27 -0
  44. package/src/__tests__/elevenlabs-config.test.ts +2 -0
  45. package/src/__tests__/emit-signal-routing-intent.test.ts +43 -1
  46. package/src/__tests__/encrypted-store.test.ts +10 -5
  47. package/src/__tests__/followup-tools.test.ts +3 -1
  48. package/src/__tests__/gateway-only-enforcement.test.ts +21 -21
  49. package/src/__tests__/gmail-integration.test.ts +0 -1
  50. package/src/__tests__/guardian-actions-endpoint.test.ts +205 -345
  51. package/src/__tests__/guardian-control-plane-policy.test.ts +19 -19
  52. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +599 -0
  53. package/src/__tests__/guardian-dispatch.test.ts +21 -19
  54. package/src/__tests__/guardian-grant-minting.test.ts +68 -1
  55. package/src/__tests__/guardian-outbound-http.test.ts +12 -9
  56. package/src/__tests__/guardian-routing-invariants.test.ts +1092 -0
  57. package/src/__tests__/handle-user-message-secret-resume.test.ts +1 -0
  58. package/src/__tests__/handlers-slack-config.test.ts +3 -1
  59. package/src/__tests__/handlers-telegram-config.test.ts +3 -1
  60. package/src/__tests__/handlers-twilio-config.test.ts +3 -1
  61. package/src/__tests__/handlers-twitter-config.test.ts +3 -1
  62. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +318 -0
  63. package/src/__tests__/heartbeat-service.test.ts +20 -0
  64. package/src/__tests__/inbound-invite-redemption.test.ts +33 -0
  65. package/src/__tests__/ingress-reconcile.test.ts +3 -1
  66. package/src/__tests__/ingress-routes-http.test.ts +231 -4
  67. package/src/__tests__/intent-routing.test.ts +2 -0
  68. package/src/__tests__/ipc-snapshot.test.ts +13 -0
  69. package/src/__tests__/mcp-cli.test.ts +77 -0
  70. package/src/__tests__/media-generate-image.test.ts +21 -0
  71. package/src/__tests__/media-reuse-story.e2e.test.ts +2 -0
  72. package/src/__tests__/memory-regressions.test.ts +20 -20
  73. package/src/__tests__/non-member-access-request.test.ts +212 -36
  74. package/src/__tests__/notification-decision-fallback.test.ts +63 -3
  75. package/src/__tests__/notification-decision-strategy.test.ts +78 -0
  76. package/src/__tests__/notification-guardian-path.test.ts +15 -15
  77. package/src/__tests__/oauth-connect-handler.test.ts +3 -1
  78. package/src/__tests__/oauth2-gateway-transport.test.ts +2 -0
  79. package/src/__tests__/onboarding-starter-tasks.test.ts +4 -4
  80. package/src/__tests__/onboarding-template-contract.test.ts +116 -21
  81. package/src/__tests__/pairing-routes.test.ts +171 -0
  82. package/src/__tests__/playbook-execution.test.ts +3 -1
  83. package/src/__tests__/playbook-tools.test.ts +3 -1
  84. package/src/__tests__/provider-error-scenarios.test.ts +59 -8
  85. package/src/__tests__/proxy-approval-callback.test.ts +2 -0
  86. package/src/__tests__/recording-handler.test.ts +11 -0
  87. package/src/__tests__/recording-intent-handler.test.ts +15 -0
  88. package/src/__tests__/recording-state-machine.test.ts +13 -2
  89. package/src/__tests__/registry.test.ts +7 -3
  90. package/src/__tests__/relay-server.test.ts +148 -28
  91. package/src/__tests__/runtime-attachment-metadata.test.ts +4 -2
  92. package/src/__tests__/runtime-events-sse-parity.test.ts +21 -0
  93. package/src/__tests__/runtime-events-sse.test.ts +4 -2
  94. package/src/__tests__/sandbox-diagnostics.test.ts +2 -0
  95. package/src/__tests__/schedule-tools.test.ts +3 -1
  96. package/src/__tests__/secret-scanner-executor.test.ts +59 -0
  97. package/src/__tests__/secret-scanner.test.ts +8 -0
  98. package/src/__tests__/send-endpoint-busy.test.ts +4 -0
  99. package/src/__tests__/sensitive-output-placeholders.test.ts +208 -0
  100. package/src/__tests__/session-abort-tool-results.test.ts +23 -0
  101. package/src/__tests__/session-agent-loop.test.ts +16 -0
  102. package/src/__tests__/session-conflict-gate.test.ts +21 -0
  103. package/src/__tests__/session-load-history-repair.test.ts +27 -17
  104. package/src/__tests__/session-pre-run-repair.test.ts +23 -0
  105. package/src/__tests__/session-profile-injection.test.ts +21 -0
  106. package/src/__tests__/session-provider-retry-repair.test.ts +20 -0
  107. package/src/__tests__/session-queue.test.ts +23 -0
  108. package/src/__tests__/session-runtime-assembly.test.ts +126 -59
  109. package/src/__tests__/session-skill-tools.test.ts +27 -5
  110. package/src/__tests__/session-slash-known.test.ts +23 -0
  111. package/src/__tests__/session-slash-queue.test.ts +23 -0
  112. package/src/__tests__/session-slash-unknown.test.ts +23 -0
  113. package/src/__tests__/session-workspace-cache-state.test.ts +7 -0
  114. package/src/__tests__/session-workspace-injection.test.ts +21 -0
  115. package/src/__tests__/session-workspace-tool-tracking.test.ts +21 -0
  116. package/src/__tests__/shell-credential-ref.test.ts +2 -0
  117. package/src/__tests__/skill-feature-flags-integration.test.ts +6 -6
  118. package/src/__tests__/skill-load-feature-flag.test.ts +5 -4
  119. package/src/__tests__/skill-projection-feature-flag.test.ts +22 -0
  120. package/src/__tests__/skills.test.ts +8 -4
  121. package/src/__tests__/slack-channel-config.test.ts +3 -1
  122. package/src/__tests__/subagent-tools.test.ts +19 -0
  123. package/src/__tests__/swarm-recursion.test.ts +2 -0
  124. package/src/__tests__/swarm-session-integration.test.ts +2 -0
  125. package/src/__tests__/swarm-tool.test.ts +2 -0
  126. package/src/__tests__/system-prompt.test.ts +3 -1
  127. package/src/__tests__/task-compiler.test.ts +3 -1
  128. package/src/__tests__/task-management-tools.test.ts +3 -1
  129. package/src/__tests__/task-tools.test.ts +3 -1
  130. package/src/__tests__/terminal-sandbox.test.ts +13 -12
  131. package/src/__tests__/terminal-tools.test.ts +2 -0
  132. package/src/__tests__/tool-approval-handler.test.ts +15 -15
  133. package/src/__tests__/tool-execution-abort-cleanup.test.ts +2 -0
  134. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -0
  135. package/src/__tests__/tool-grant-request-escalation.test.ts +497 -0
  136. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +48 -0
  137. package/src/__tests__/trusted-contact-multichannel.test.ts +22 -19
  138. package/src/__tests__/trusted-contact-verification.test.ts +91 -0
  139. package/src/__tests__/twilio-routes-elevenlabs.test.ts +2 -0
  140. package/src/__tests__/twitter-auth-handler.test.ts +3 -1
  141. package/src/__tests__/twitter-cli-routing.test.ts +3 -1
  142. package/src/__tests__/view-image-tool.test.ts +3 -1
  143. package/src/__tests__/voice-invite-redemption.test.ts +329 -0
  144. package/src/__tests__/voice-scoped-grant-consumer.test.ts +7 -5
  145. package/src/__tests__/voice-session-bridge.test.ts +10 -10
  146. package/src/__tests__/work-item-output.test.ts +3 -1
  147. package/src/__tests__/workspace-lifecycle.test.ts +13 -2
  148. package/src/agent/loop.ts +46 -3
  149. package/src/approvals/guardian-decision-primitive.ts +285 -0
  150. package/src/approvals/guardian-request-resolvers.ts +539 -0
  151. package/src/calls/call-controller.ts +26 -23
  152. package/src/calls/guardian-action-sweep.ts +10 -2
  153. package/src/calls/guardian-dispatch.ts +46 -40
  154. package/src/calls/relay-server.ts +358 -24
  155. package/src/calls/types.ts +1 -1
  156. package/src/calls/voice-session-bridge.ts +3 -3
  157. package/src/cli.ts +12 -0
  158. package/src/config/agent-schema.ts +14 -3
  159. package/src/config/calls-schema.ts +6 -6
  160. package/src/config/core-schema.ts +3 -3
  161. package/src/config/feature-flag-registry.json +8 -0
  162. package/src/config/mcp-schema.ts +1 -1
  163. package/src/config/memory-schema.ts +27 -19
  164. package/src/config/schema.ts +21 -21
  165. package/src/config/skills-schema.ts +7 -7
  166. package/src/config/system-prompt.ts +2 -1
  167. package/src/config/templates/BOOTSTRAP.md +47 -31
  168. package/src/config/templates/USER.md +5 -0
  169. package/src/config/update-bulletin-template-path.ts +4 -1
  170. package/src/config/vellum-skills/trusted-contacts/SKILL.md +149 -21
  171. package/src/daemon/handlers/config-inbox.ts +4 -4
  172. package/src/daemon/handlers/guardian-actions.ts +45 -66
  173. package/src/daemon/handlers/sessions.ts +148 -4
  174. package/src/daemon/ipc-contract/guardian-actions.ts +7 -0
  175. package/src/daemon/ipc-contract/messages.ts +16 -0
  176. package/src/daemon/ipc-contract-inventory.json +1 -0
  177. package/src/daemon/lifecycle.ts +22 -16
  178. package/src/daemon/pairing-store.ts +86 -3
  179. package/src/daemon/server.ts +18 -0
  180. package/src/daemon/session-agent-loop-handlers.ts +5 -4
  181. package/src/daemon/session-agent-loop.ts +33 -6
  182. package/src/daemon/session-lifecycle.ts +25 -17
  183. package/src/daemon/session-memory.ts +2 -2
  184. package/src/daemon/session-process.ts +68 -326
  185. package/src/daemon/session-runtime-assembly.ts +119 -25
  186. package/src/daemon/session-tool-setup.ts +3 -2
  187. package/src/daemon/session.ts +4 -3
  188. package/src/home-base/prebuilt/seed.ts +2 -1
  189. package/src/hooks/templates.ts +2 -1
  190. package/src/memory/canonical-guardian-store.ts +586 -0
  191. package/src/memory/channel-guardian-store.ts +2 -0
  192. package/src/memory/conversation-crud.ts +7 -7
  193. package/src/memory/db-init.ts +20 -0
  194. package/src/memory/embedding-local.ts +257 -39
  195. package/src/memory/embedding-runtime-manager.ts +471 -0
  196. package/src/memory/guardian-action-store.ts +7 -60
  197. package/src/memory/guardian-approvals.ts +9 -4
  198. package/src/memory/guardian-bindings.ts +25 -1
  199. package/src/memory/indexer.ts +3 -3
  200. package/src/memory/ingress-invite-store.ts +45 -0
  201. package/src/memory/job-handlers/backfill.ts +16 -9
  202. package/src/memory/migrations/036-normalize-phone-identities.ts +289 -0
  203. package/src/memory/migrations/037-voice-invite-columns.ts +16 -0
  204. package/src/memory/migrations/118-reminder-routing-intent.ts +3 -3
  205. package/src/memory/migrations/121-canonical-guardian-requests.ts +59 -0
  206. package/src/memory/migrations/122-canonical-guardian-requester-chat-id.ts +15 -0
  207. package/src/memory/migrations/123-canonical-guardian-deliveries-destination-index.ts +15 -0
  208. package/src/memory/migrations/index.ts +5 -0
  209. package/src/memory/migrations/registry.ts +5 -0
  210. package/src/memory/qdrant-client.ts +31 -22
  211. package/src/memory/schema-migration.ts +1 -0
  212. package/src/memory/schema.ts +56 -0
  213. package/src/notifications/copy-composer.ts +31 -4
  214. package/src/notifications/decision-engine.ts +57 -0
  215. package/src/permissions/defaults.ts +2 -0
  216. package/src/runtime/access-request-helper.ts +173 -0
  217. package/src/runtime/actor-trust-resolver.ts +221 -0
  218. package/src/runtime/channel-guardian-service.ts +12 -4
  219. package/src/runtime/channel-invite-transports/voice.ts +58 -0
  220. package/src/runtime/channel-retry-sweep.ts +18 -6
  221. package/src/runtime/guardian-context-resolver.ts +38 -71
  222. package/src/runtime/guardian-decision-types.ts +6 -0
  223. package/src/runtime/guardian-reply-router.ts +717 -0
  224. package/src/runtime/http-server.ts +8 -0
  225. package/src/runtime/ingress-service.ts +80 -3
  226. package/src/runtime/invite-redemption-service.ts +141 -2
  227. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +116 -0
  228. package/src/runtime/routes/channel-route-shared.ts +1 -1
  229. package/src/runtime/routes/channel-routes.ts +1 -1
  230. package/src/runtime/routes/conversation-routes.ts +20 -2
  231. package/src/runtime/routes/guardian-action-routes.ts +100 -109
  232. package/src/runtime/routes/guardian-approval-interception.ts +17 -6
  233. package/src/runtime/routes/inbound-message-handler.ts +205 -529
  234. package/src/runtime/routes/ingress-routes.ts +52 -4
  235. package/src/runtime/routes/pairing-routes.ts +3 -0
  236. package/src/runtime/tool-grant-request-helper.ts +195 -0
  237. package/src/tools/executor.ts +13 -1
  238. package/src/tools/guardian-control-plane-policy.ts +2 -2
  239. package/src/tools/sensitive-output-placeholders.ts +203 -0
  240. package/src/tools/tool-approval-handler.ts +53 -10
  241. package/src/tools/types.ts +13 -2
  242. package/src/util/bundled-asset.ts +31 -0
  243. package/src/util/canonicalize-identity.ts +52 -0
  244. package/src/util/logger.ts +20 -8
  245. package/src/util/platform.ts +10 -0
  246. package/src/util/voice-code.ts +29 -0
  247. package/src/daemon/guardian-invite-intent.ts +0 -124
@@ -14,11 +14,20 @@ const log = getLogger('runtime-http');
14
14
  function parseGuardianRuntimeContext(value: unknown): GuardianRuntimeContext | undefined {
15
15
  if (!value || typeof value !== 'object') return undefined;
16
16
  const raw = value as Record<string, unknown>;
17
- const actorRole = raw.actorRole;
17
+ const trustClass = raw.trustClass
18
+ ?? (
19
+ raw.actorRole === 'guardian'
20
+ ? 'guardian'
21
+ : raw.actorRole === 'non-guardian'
22
+ ? 'trusted_contact'
23
+ : raw.actorRole === 'unverified_channel'
24
+ ? 'unknown'
25
+ : undefined
26
+ );
18
27
  if (
19
- actorRole !== 'guardian'
20
- && actorRole !== 'non-guardian'
21
- && actorRole !== 'unverified_channel'
28
+ trustClass !== 'guardian'
29
+ && trustClass !== 'trusted_contact'
30
+ && trustClass !== 'unknown'
22
31
  ) {
23
32
  return undefined;
24
33
  }
@@ -33,10 +42,13 @@ function parseGuardianRuntimeContext(value: unknown): GuardianRuntimeContext | u
33
42
  : undefined;
34
43
  return {
35
44
  sourceChannel,
36
- actorRole,
45
+ trustClass,
37
46
  guardianChatId: typeof raw.guardianChatId === 'string' ? raw.guardianChatId : undefined,
38
47
  guardianExternalUserId: typeof raw.guardianExternalUserId === 'string' ? raw.guardianExternalUserId : undefined,
39
48
  requesterIdentifier: typeof raw.requesterIdentifier === 'string' ? raw.requesterIdentifier : undefined,
49
+ requesterDisplayName: typeof raw.requesterDisplayName === 'string' ? raw.requesterDisplayName : undefined,
50
+ requesterSenderDisplayName: typeof raw.requesterSenderDisplayName === 'string' ? raw.requesterSenderDisplayName : undefined,
51
+ requesterMemberDisplayName: typeof raw.requesterMemberDisplayName === 'string' ? raw.requesterMemberDisplayName : undefined,
40
52
  requesterExternalUserId: typeof raw.requesterExternalUserId === 'string' ? raw.requesterExternalUserId : undefined,
41
53
  requesterChatId: typeof raw.requesterChatId === 'string' ? raw.requesterChatId : undefined,
42
54
  denialReason,
@@ -117,7 +129,7 @@ export async function sweepFailedEvents(
117
129
  },
118
130
  assistantId,
119
131
  guardianContext,
120
- isInteractive: guardianContext?.actorRole === 'guardian',
132
+ isInteractive: guardianContext?.trustClass === 'guardian',
121
133
  },
122
134
  sourceChannel,
123
135
  sourceInterface,
@@ -1,106 +1,73 @@
1
1
  /**
2
- * Shared guardian actor-role resolution for inbound channels.
2
+ * Shared inbound trust resolution for channel actors.
3
3
  *
4
- * This module centralizes how we classify an inbound actor as
5
- * guardian/non-guardian/unverified so every channel path uses the same
6
- * source-of-truth logic.
4
+ * This module provides a compact route-level shape used by channel routes
5
+ * while delegating canonical classification to the unified actor trust
6
+ * resolver.
7
7
  */
8
8
  import type { ChannelId } from '../channels/types.js';
9
9
  import type { GuardianRuntimeContext } from '../daemon/session-runtime-assembly.js';
10
- import { normalizeAssistantId } from '../util/platform.js';
11
- import { getGuardianBinding } from './channel-guardian-service.js';
10
+ import {
11
+ type DenialReason,
12
+ resolveActorTrust,
13
+ type ResolveActorTrustInput,
14
+ type TrustClass,
15
+ } from './actor-trust-resolver.js';
16
+ export type { DenialReason } from './actor-trust-resolver.js';
12
17
 
13
- /** Sub-reason for unverified-channel denials. */
14
- export type DenialReason = 'no_binding' | 'no_identity';
15
- export type ActorRole = 'guardian' | 'non-guardian' | 'unverified_channel';
18
+ /** Trust classification used by route-level channel logic. */
19
+ export type ActorTrustClass = TrustClass;
16
20
 
17
21
  /** Guardian actor context used by route-level approval logic. */
18
22
  export interface GuardianContext {
19
- actorRole: ActorRole;
23
+ trustClass: ActorTrustClass;
20
24
  guardianChatId?: string;
21
25
  guardianExternalUserId?: string;
22
26
  requesterIdentifier?: string;
27
+ requesterDisplayName?: string;
28
+ requesterSenderDisplayName?: string;
29
+ requesterMemberDisplayName?: string;
23
30
  requesterExternalUserId?: string;
24
31
  requesterChatId?: string;
32
+ memberStatus?: string;
33
+ memberPolicy?: string;
25
34
  denialReason?: DenialReason;
26
35
  }
27
36
 
28
- export interface ResolveGuardianContextInput {
29
- assistantId: string;
30
- sourceChannel: ChannelId;
31
- externalChatId: string;
32
- senderExternalUserId?: string;
33
- senderUsername?: string;
34
- }
37
+ export type ResolveGuardianContextInput = ResolveActorTrustInput;
35
38
 
36
39
  /**
37
- * Resolve guardian actor role from canonical binding state + sender identity.
38
- *
39
- * Behavior:
40
- * - sender matches active binding -> guardian
41
- * - active binding exists but sender differs -> non-guardian
42
- * - no sender identity -> unverified_channel (no_identity)
43
- * - no binding -> unverified_channel (no_binding)
40
+ * Resolve route-level trust context from canonical identity state.
44
41
  */
45
42
  export function resolveGuardianContext(input: ResolveGuardianContextInput): GuardianContext {
46
- const assistantId = normalizeAssistantId(input.assistantId);
47
- const senderExternalUserId = typeof input.senderExternalUserId === 'string' && input.senderExternalUserId.trim().length > 0
48
- ? input.senderExternalUserId.trim()
49
- : undefined;
50
- const senderUsername = typeof input.senderUsername === 'string' && input.senderUsername.trim().length > 0
51
- ? input.senderUsername.trim()
52
- : undefined;
53
- const requesterIdentifier = senderUsername ? `@${senderUsername}` : senderExternalUserId;
54
-
55
- if (!senderExternalUserId) {
56
- return {
57
- actorRole: 'unverified_channel',
58
- denialReason: 'no_identity',
59
- requesterIdentifier,
60
- requesterExternalUserId: undefined,
61
- requesterChatId: input.externalChatId,
62
- };
63
- }
64
-
65
- const binding = getGuardianBinding(assistantId, input.sourceChannel);
66
- if (!binding) {
67
- return {
68
- actorRole: 'unverified_channel',
69
- denialReason: 'no_binding',
70
- requesterIdentifier,
71
- requesterExternalUserId: senderExternalUserId,
72
- requesterChatId: input.externalChatId,
73
- };
74
- }
75
-
76
- if (binding.guardianExternalUserId === senderExternalUserId) {
77
- return {
78
- actorRole: 'guardian',
79
- guardianChatId: binding.guardianDeliveryChatId || input.externalChatId,
80
- guardianExternalUserId: binding.guardianExternalUserId,
81
- requesterIdentifier,
82
- requesterExternalUserId: senderExternalUserId,
83
- requesterChatId: input.externalChatId,
84
- };
85
- }
86
-
43
+ const trust = resolveActorTrust(input);
87
44
  return {
88
- actorRole: 'non-guardian',
89
- guardianChatId: binding.guardianDeliveryChatId,
90
- guardianExternalUserId: binding.guardianExternalUserId,
91
- requesterIdentifier,
92
- requesterExternalUserId: senderExternalUserId,
45
+ trustClass: trust.trustClass,
46
+ guardianChatId: trust.guardianBindingMatch?.guardianDeliveryChatId ??
47
+ (trust.trustClass === 'guardian' ? input.externalChatId : undefined),
48
+ guardianExternalUserId: trust.guardianBindingMatch?.guardianExternalUserId,
49
+ requesterIdentifier: trust.actorMetadata.identifier,
50
+ requesterDisplayName: trust.actorMetadata.displayName,
51
+ requesterSenderDisplayName: trust.actorMetadata.senderDisplayName,
52
+ requesterMemberDisplayName: trust.actorMetadata.memberDisplayName,
53
+ requesterExternalUserId: trust.canonicalSenderId ?? undefined,
93
54
  requesterChatId: input.externalChatId,
55
+ memberStatus: trust.memberRecord?.status ?? undefined,
56
+ memberPolicy: trust.memberRecord?.policy ?? undefined,
57
+ denialReason: trust.denialReason,
94
58
  };
95
59
  }
96
60
 
97
61
  export function toGuardianRuntimeContext(sourceChannel: ChannelId, ctx: GuardianContext): GuardianRuntimeContext {
98
62
  return {
99
63
  sourceChannel,
100
- actorRole: ctx.actorRole,
64
+ trustClass: ctx.trustClass,
101
65
  guardianChatId: ctx.guardianChatId,
102
66
  guardianExternalUserId: ctx.guardianExternalUserId,
103
67
  requesterIdentifier: ctx.requesterIdentifier,
68
+ requesterDisplayName: ctx.requesterDisplayName,
69
+ requesterSenderDisplayName: ctx.requesterSenderDisplayName,
70
+ requesterMemberDisplayName: ctx.requesterMemberDisplayName,
104
71
  requesterExternalUserId: ctx.requesterExternalUserId,
105
72
  requesterChatId: ctx.requesterChatId,
106
73
  denialReason: ctx.denialReason,
@@ -22,6 +22,12 @@ export interface GuardianDecisionPrompt {
22
22
  expiresAt: number;
23
23
  conversationId: string;
24
24
  callSessionId: string | null;
25
+ /**
26
+ * Canonical request kind (e.g. 'tool_approval', 'pending_question').
27
+ * Present when the prompt originates from the canonical guardian request
28
+ * store. Absent for legacy-only prompts.
29
+ */
30
+ kind?: string;
25
31
  }
26
32
 
27
33
  export interface GuardianDecisionAction {