@vellumai/assistant 0.4.32 → 0.4.34

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 (186) hide show
  1. package/docs/architecture/memory.md +1 -1
  2. package/package.json +1 -1
  3. package/src/__tests__/access-request-decision.test.ts +85 -4
  4. package/src/__tests__/actor-token-service.test.ts +4 -12
  5. package/src/__tests__/approval-primitive.test.ts +0 -45
  6. package/src/__tests__/approval-routes-http.test.ts +0 -1
  7. package/src/__tests__/assistant-id-boundary-guard.test.ts +150 -0
  8. package/src/__tests__/call-controller.test.ts +0 -1
  9. package/src/__tests__/call-routes-http.test.ts +0 -1
  10. package/src/__tests__/callback-handoff-copy.test.ts +0 -1
  11. package/src/__tests__/channel-approval-routes.test.ts +5 -45
  12. package/src/__tests__/channel-guardian.test.ts +122 -346
  13. package/src/__tests__/channel-invite-transport.test.ts +52 -40
  14. package/src/__tests__/commit-message-enrichment-service.test.ts +4 -38
  15. package/src/__tests__/computer-use-session-working-dir.test.ts +0 -1
  16. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +4 -3
  17. package/src/__tests__/contacts-tools.test.ts +4 -5
  18. package/src/__tests__/conversation-attention-store.test.ts +2 -65
  19. package/src/__tests__/conversation-attention-telegram.test.ts +0 -2
  20. package/src/__tests__/conversation-pairing.test.ts +0 -1
  21. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  22. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -3
  23. package/src/__tests__/guardian-action-conversation-turn.test.ts +1 -7
  24. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
  25. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -74
  26. package/src/__tests__/guardian-action-late-reply.test.ts +1 -8
  27. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  28. package/src/__tests__/guardian-grant-minting.test.ts +0 -1
  29. package/src/__tests__/guardian-outbound-http.test.ts +0 -1
  30. package/src/__tests__/guardian-routing-state.test.ts +0 -3
  31. package/src/__tests__/handlers-telegram-config.test.ts +0 -1
  32. package/src/__tests__/inbound-invite-redemption.test.ts +1 -7
  33. package/src/__tests__/ingress-reconcile.test.ts +3 -36
  34. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1
  35. package/src/__tests__/migration-export-http.test.ts +0 -1
  36. package/src/__tests__/migration-import-commit-http.test.ts +0 -1
  37. package/src/__tests__/migration-import-preflight-http.test.ts +0 -1
  38. package/src/__tests__/migration-validate-http.test.ts +0 -1
  39. package/src/__tests__/non-member-access-request.test.ts +0 -8
  40. package/src/__tests__/notification-broadcaster.test.ts +1 -2
  41. package/src/__tests__/notification-decision-fallback.test.ts +0 -2
  42. package/src/__tests__/notification-decision-strategy.test.ts +0 -1
  43. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  44. package/src/__tests__/notification-telegram-adapter.test.ts +0 -4
  45. package/src/__tests__/relay-server.test.ts +151 -80
  46. package/src/__tests__/sandbox-host-parity.test.ts +5 -2
  47. package/src/__tests__/scoped-approval-grants.test.ts +9 -40
  48. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -36
  49. package/src/__tests__/send-endpoint-busy.test.ts +0 -1
  50. package/src/__tests__/send-notification-tool.test.ts +0 -1
  51. package/src/__tests__/session-init.benchmark.test.ts +0 -2
  52. package/src/__tests__/slack-channel-config.test.ts +0 -1
  53. package/src/__tests__/slack-inbound-verification.test.ts +2 -5
  54. package/src/__tests__/sms-messaging-provider.test.ts +0 -4
  55. package/src/__tests__/terminal-tools.test.ts +5 -2
  56. package/src/__tests__/thread-seed-composer.test.ts +0 -1
  57. package/src/__tests__/tool-approval-handler.test.ts +0 -1
  58. package/src/__tests__/tool-grant-request-escalation.test.ts +0 -4
  59. package/src/__tests__/trusted-contact-approval-notifier.test.ts +65 -77
  60. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  61. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +1 -18
  62. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -14
  63. package/src/__tests__/trusted-contact-verification.test.ts +3 -16
  64. package/src/__tests__/twilio-routes.test.ts +2 -3
  65. package/src/__tests__/update-bulletin.test.ts +0 -2
  66. package/src/__tests__/user-reference.test.ts +47 -1
  67. package/src/__tests__/voice-invite-redemption.test.ts +0 -1
  68. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -38
  69. package/src/__tests__/workspace-git-service.test.ts +2 -2
  70. package/src/approvals/approval-primitive.ts +0 -15
  71. package/src/approvals/guardian-decision-primitive.ts +0 -3
  72. package/src/approvals/guardian-request-resolvers.ts +0 -5
  73. package/src/calls/call-domain.ts +0 -3
  74. package/src/calls/call-store.ts +0 -3
  75. package/src/calls/guardian-action-sweep.ts +2 -1
  76. package/src/calls/guardian-dispatch.ts +1 -2
  77. package/src/calls/relay-access-wait.ts +0 -4
  78. package/src/calls/relay-server.ts +8 -66
  79. package/src/calls/relay-setup-router.ts +1 -2
  80. package/src/calls/relay-verification.ts +0 -1
  81. package/src/calls/twilio-routes.ts +0 -3
  82. package/src/calls/types.ts +0 -1
  83. package/src/calls/voice-session-bridge.ts +0 -1
  84. package/src/channels/config.ts +41 -2
  85. package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -1
  86. package/src/config/bundled-skills/slack/SKILL.md +2 -0
  87. package/src/config/bundled-skills/slack-digest-setup/SKILL.md +164 -0
  88. package/src/config/env.ts +0 -4
  89. package/src/config/feature-flag-registry.json +4 -4
  90. package/src/config/user-reference.ts +47 -9
  91. package/src/contacts/contact-store.ts +13 -88
  92. package/src/contacts/contacts-write.ts +3 -11
  93. package/src/contacts/types.ts +0 -1
  94. package/src/daemon/handlers/config-channels.ts +19 -44
  95. package/src/daemon/handlers/config-inbox.ts +6 -6
  96. package/src/daemon/handlers/contacts.ts +8 -12
  97. package/src/daemon/handlers/index.ts +0 -2
  98. package/src/daemon/lifecycle.ts +18 -26
  99. package/src/daemon/session-process.ts +0 -4
  100. package/src/memory/channel-delivery-store.ts +1 -0
  101. package/src/memory/conversation-attention-store.ts +4 -19
  102. package/src/memory/conversation-crud.ts +0 -2
  103. package/src/memory/db-init.ts +8 -0
  104. package/src/memory/delivery-crud.ts +13 -0
  105. package/src/memory/guardian-action-store.ts +0 -12
  106. package/src/memory/guardian-approvals.ts +35 -80
  107. package/src/memory/guardian-rate-limits.ts +1 -14
  108. package/src/memory/guardian-verification.ts +6 -34
  109. package/src/memory/invite-store.ts +76 -15
  110. package/src/memory/migrations/040-invite-code-hash-column.ts +16 -0
  111. package/src/memory/migrations/134-contacts-notes-column.ts +64 -45
  112. package/src/memory/migrations/136-drop-assistant-id-columns.ts +263 -0
  113. package/src/memory/migrations/index.ts +2 -0
  114. package/src/memory/migrations/registry.ts +14 -1
  115. package/src/memory/schema/calls.ts +0 -7
  116. package/src/memory/schema/contacts.ts +2 -8
  117. package/src/memory/schema/guardian.ts +0 -5
  118. package/src/memory/schema/infrastructure.ts +0 -2
  119. package/src/memory/schema/notifications.ts +3 -17
  120. package/src/memory/scoped-approval-grants.ts +2 -24
  121. package/src/notifications/adapters/sms.ts +2 -1
  122. package/src/notifications/broadcaster.ts +1 -6
  123. package/src/notifications/decision-engine.ts +3 -4
  124. package/src/notifications/deliveries-store.ts +0 -4
  125. package/src/notifications/destination-resolver.ts +4 -6
  126. package/src/notifications/deterministic-checks.ts +1 -6
  127. package/src/notifications/emit-signal.ts +4 -11
  128. package/src/notifications/events-store.ts +7 -17
  129. package/src/notifications/preference-summary.ts +2 -2
  130. package/src/notifications/preferences-store.ts +2 -9
  131. package/src/notifications/signal.ts +0 -1
  132. package/src/notifications/thread-candidates.ts +1 -11
  133. package/src/notifications/types.ts +0 -3
  134. package/src/runtime/access-request-helper.ts +3 -10
  135. package/src/runtime/actor-refresh-token-store.ts +0 -6
  136. package/src/runtime/actor-token-store.ts +3 -16
  137. package/src/runtime/actor-trust-resolver.ts +1 -4
  138. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -9
  139. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -3
  140. package/src/runtime/auth/credential-service.ts +1 -15
  141. package/src/runtime/auth/require-bound-guardian.ts +1 -4
  142. package/src/runtime/auth/token-service.ts +50 -0
  143. package/src/runtime/channel-guardian-service.ts +16 -49
  144. package/src/runtime/channel-invite-transport.ts +129 -34
  145. package/src/runtime/channel-invite-transports/email.ts +54 -0
  146. package/src/runtime/channel-invite-transports/slack.ts +87 -0
  147. package/src/runtime/channel-invite-transports/sms.ts +74 -0
  148. package/src/runtime/channel-invite-transports/telegram.ts +35 -11
  149. package/src/runtime/channel-invite-transports/voice.ts +12 -12
  150. package/src/runtime/confirmation-request-guardian-bridge.ts +0 -1
  151. package/src/runtime/guardian-action-followup-executor.ts +3 -2
  152. package/src/runtime/guardian-action-grant-minter.ts +0 -1
  153. package/src/runtime/guardian-outbound-actions.ts +2 -12
  154. package/src/runtime/guardian-vellum-migration.ts +2 -3
  155. package/src/runtime/http-server.ts +0 -1
  156. package/src/runtime/invite-redemption-service.ts +191 -11
  157. package/src/runtime/invite-redemption-templates.ts +6 -6
  158. package/src/runtime/invite-service.ts +81 -11
  159. package/src/runtime/local-actor-identity.ts +2 -5
  160. package/src/runtime/routes/access-request-decision.ts +52 -7
  161. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +6 -9
  162. package/src/runtime/routes/channel-readiness-routes.ts +29 -18
  163. package/src/runtime/routes/contact-routes.ts +48 -46
  164. package/src/runtime/routes/conversation-attention-routes.ts +0 -2
  165. package/src/runtime/routes/global-search-routes.ts +0 -2
  166. package/src/runtime/routes/guardian-bootstrap-routes.ts +6 -12
  167. package/src/runtime/routes/guardian-expiry-sweep.ts +3 -2
  168. package/src/runtime/routes/inbound-message-handler.ts +1 -6
  169. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +296 -47
  170. package/src/runtime/routes/inbound-stages/background-dispatch.ts +6 -42
  171. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +1 -6
  172. package/src/runtime/routes/inbound-stages/edit-intercept.ts +10 -0
  173. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +0 -1
  174. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +0 -1
  175. package/src/runtime/routes/inbound-stages/verification-intercept.ts +3 -7
  176. package/src/runtime/routes/invite-routes.ts +1 -0
  177. package/src/runtime/routes/pairing-routes.ts +4 -4
  178. package/src/runtime/tool-grant-request-helper.ts +0 -1
  179. package/src/tools/browser/browser-manager.ts +22 -12
  180. package/src/tools/browser/runtime-check.ts +110 -3
  181. package/src/tools/calls/call-start.ts +1 -3
  182. package/src/tools/followups/followup_create.ts +1 -2
  183. package/src/tools/shared/shell-output.ts +7 -2
  184. package/src/tools/tool-approval-handler.ts +0 -2
  185. package/src/util/platform.ts +0 -4
  186. package/src/workspace/git-service.ts +10 -4
@@ -22,6 +22,7 @@ export {
22
22
  export type { InboundResult, RecordInboundOptions } from "./delivery-crud.js";
23
23
  export {
24
24
  clearPayload,
25
+ deleteInbound,
25
26
  findMessageBySourceId,
26
27
  getLatestStoredPayload,
27
28
  linkMessage,
@@ -32,7 +32,6 @@ export type Confidence = "explicit" | "inferred";
32
32
  export interface AttentionEvent {
33
33
  id: string;
34
34
  conversationId: string;
35
- assistantId: string;
36
35
  sourceChannel: string;
37
36
  signalType: SignalType;
38
37
  confidence: Confidence;
@@ -45,7 +44,6 @@ export interface AttentionEvent {
45
44
 
46
45
  export interface AttentionState {
47
46
  conversationId: string;
48
- assistantId: string;
49
47
  latestAssistantMessageId: string | null;
50
48
  latestAssistantMessageAt: number | null;
51
49
  lastSeenAssistantMessageId: string | null;
@@ -68,7 +66,6 @@ function rowToEvent(
68
66
  return {
69
67
  id: row.id,
70
68
  conversationId: row.conversationId,
71
- assistantId: row.assistantId,
72
69
  sourceChannel: row.sourceChannel,
73
70
  signalType: row.signalType as SignalType,
74
71
  confidence: row.confidence as Confidence,
@@ -85,7 +82,6 @@ function rowToState(
85
82
  ): AttentionState {
86
83
  return {
87
84
  conversationId: row.conversationId,
88
- assistantId: row.assistantId,
89
85
  latestAssistantMessageId: row.latestAssistantMessageId,
90
86
  latestAssistantMessageAt: row.latestAssistantMessageAt,
91
87
  lastSeenAssistantMessageId: row.lastSeenAssistantMessageId,
@@ -109,11 +105,10 @@ function rowToState(
109
105
  */
110
106
  export function projectAssistantMessage(params: {
111
107
  conversationId: string;
112
- assistantId: string;
113
108
  messageId: string;
114
109
  messageAt: number;
115
110
  }): void {
116
- const { conversationId, assistantId, messageId, messageAt } = params;
111
+ const { conversationId, messageId, messageAt } = params;
117
112
  const db = getDb();
118
113
  const now = Date.now();
119
114
 
@@ -129,7 +124,6 @@ export function projectAssistantMessage(params: {
129
124
  db.insert(conversationAssistantAttentionState)
130
125
  .values({
131
126
  conversationId,
132
- assistantId,
133
127
  latestAssistantMessageId: messageId,
134
128
  latestAssistantMessageAt: messageAt,
135
129
  lastSeenAssistantMessageId: null,
@@ -175,7 +169,6 @@ export function projectAssistantMessage(params: {
175
169
  */
176
170
  export function recordConversationSeenSignal(params: {
177
171
  conversationId: string;
178
- assistantId: string;
179
172
  sourceChannel: string;
180
173
  signalType: SignalType;
181
174
  confidence: Confidence;
@@ -186,7 +179,6 @@ export function recordConversationSeenSignal(params: {
186
179
  }): AttentionEvent {
187
180
  const {
188
181
  conversationId,
189
- assistantId,
190
182
  sourceChannel,
191
183
  signalType,
192
184
  confidence,
@@ -205,7 +197,6 @@ export function recordConversationSeenSignal(params: {
205
197
  const event: typeof conversationAttentionEvents.$inferInsert = {
206
198
  id: eventId,
207
199
  conversationId,
208
- assistantId,
209
200
  sourceChannel,
210
201
  signalType,
211
202
  confidence,
@@ -252,7 +243,6 @@ export function recordConversationSeenSignal(params: {
252
243
  tx.insert(conversationAssistantAttentionState)
253
244
  .values({
254
245
  conversationId,
255
- assistantId,
256
246
  latestAssistantMessageId: latestMsgId,
257
247
  latestAssistantMessageAt: latestMsgAt,
258
248
  lastSeenAssistantMessageId: latestMsgId,
@@ -348,7 +338,6 @@ export function getAttentionStateByConversationIds(
348
338
  export type AttentionFilterState = "seen" | "unseen" | "all";
349
339
 
350
340
  export interface ListConversationAttentionParams {
351
- assistantId: string;
352
341
  state?: AttentionFilterState;
353
342
  sourceChannel?: string;
354
343
  source?: string;
@@ -364,7 +353,6 @@ export function listConversationAttention(
364
353
  params: ListConversationAttentionParams,
365
354
  ): AttentionState[] {
366
355
  const {
367
- assistantId,
368
356
  state: filterState = "all",
369
357
  sourceChannel,
370
358
  source,
@@ -373,9 +361,8 @@ export function listConversationAttention(
373
361
  } = params;
374
362
 
375
363
  const db = getDb();
376
- const conditions = [
377
- eq(conversationAssistantAttentionState.assistantId, assistantId),
378
- ];
364
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
365
+ const conditions: any[] = [];
379
366
 
380
367
  if (sourceChannel) {
381
368
  conditions.push(eq(conversations.originChannel, sourceChannel));
@@ -415,7 +402,6 @@ export function listConversationAttention(
415
402
  let query = db
416
403
  .select({
417
404
  conversationId: conversationAssistantAttentionState.conversationId,
418
- assistantId: conversationAssistantAttentionState.assistantId,
419
405
  latestAssistantMessageId:
420
406
  conversationAssistantAttentionState.latestAssistantMessageId,
421
407
  latestAssistantMessageAt:
@@ -448,8 +434,7 @@ export function listConversationAttention(
448
434
  );
449
435
  }
450
436
 
451
- const rows = query
452
- .where(and(...conditions))
437
+ const rows = (conditions.length > 0 ? query.where(and(...conditions)) : query)
453
438
  .orderBy(desc(conversationAssistantAttentionState.latestAssistantMessageAt))
454
439
  .limit(limit)
455
440
  .all();
@@ -7,7 +7,6 @@ import { parseChannelId, parseInterfaceId } from "../channels/types.js";
7
7
  import { CHANNEL_IDS, INTERFACE_IDS, isChannelId } from "../channels/types.js";
8
8
  import { getConfig } from "../config/loader.js";
9
9
  import type { TrustContext } from "../daemon/session-runtime-assembly.js";
10
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
11
10
  import { getLogger } from "../util/logger.js";
12
11
  import { createRowMapper } from "../util/row-mapper.js";
13
12
  import { deleteOrphanAttachments } from "./attachments-store.js";
@@ -394,7 +393,6 @@ export async function addMessage(
394
393
  try {
395
394
  projectAssistantMessage({
396
395
  conversationId,
397
- assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
398
396
  messageId: message.id,
399
397
  messageAt: message.createdAt,
400
398
  });
@@ -36,6 +36,7 @@ import {
36
36
  migrateBackfillContactInteractionStats,
37
37
  migrateBackfillGuardianPrincipalId,
38
38
  migrateCallSessionMode,
39
+ migrateDropAssistantIdColumns,
39
40
  migrateCanonicalGuardianDeliveriesDestinationIndex,
40
41
  migrateCanonicalGuardianRequesterChatId,
41
42
  migrateChannelInboundDeliveredSegments,
@@ -56,6 +57,7 @@ import {
56
57
  migrateGuardianPrincipalIdNotNull,
57
58
  migrateGuardianVerificationPurpose,
58
59
  migrateGuardianVerificationSessions,
60
+ migrateInviteCodeHashColumn,
59
61
  migrateMessagesFtsBackfill,
60
62
  migrateNormalizePhoneIdentities,
61
63
  migrateNotificationDeliveryThreadDecision,
@@ -246,6 +248,9 @@ export function initializeDb(): void {
246
248
  // 27. Voice invite display metadata (friend_name, guardian_name) for personalized prompts
247
249
  migrateVoiceInviteDisplayMetadata(database);
248
250
 
251
+ // 27b. 6-digit invite code hash column for non-voice channel invite redemption
252
+ migrateInviteCodeHashColumn(database);
253
+
249
254
  // 28. Actor token records (hash-only actor token persistence)
250
255
  createActorTokenRecordsTable(database);
251
256
 
@@ -285,6 +290,9 @@ export function initializeDb(): void {
285
290
  // 39. Backfill contact interaction stats from channel lastSeenAt
286
291
  migrateBackfillContactInteractionStats(database);
287
292
 
293
+ // 40. Drop assistant_id columns from all 16 daemon tables
294
+ migrateDropAssistantIdColumns(database);
295
+
288
296
  validateMigrationState(database);
289
297
 
290
298
  if (process.env.BUN_TEST === "1") {
@@ -125,6 +125,19 @@ export function recordInbound(
125
125
  };
126
126
  }
127
127
 
128
+ /**
129
+ * Delete an inbound event record by its event ID. Used to roll back a
130
+ * dedup record when downstream processing (e.g. invite redemption) fails,
131
+ * so that webhook retries can re-attempt instead of short-circuiting as
132
+ * duplicates.
133
+ */
134
+ export function deleteInbound(eventId: string): void {
135
+ const db = getDb();
136
+ db.delete(channelInboundEvents)
137
+ .where(eq(channelInboundEvents.id, eventId))
138
+ .run();
139
+ }
140
+
128
141
  /**
129
142
  * Link an inbound event to the user message it created, so edits can
130
143
  * later find the correct message by source_message_id -> message_id.
@@ -10,7 +10,6 @@
10
10
  import { and, desc, eq, inArray, lt } from "drizzle-orm";
11
11
  import { v4 as uuid } from "uuid";
12
12
 
13
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
14
13
  import { getLogger } from "../util/logger.js";
15
14
  import { getDb, rawChanges } from "./db.js";
16
15
  import { guardianActionDeliveries, guardianActionRequests } from "./schema.js";
@@ -49,7 +48,6 @@ export type FollowupAction = "call_back" | "message_back" | "decline";
49
48
 
50
49
  export interface GuardianActionRequest {
51
50
  id: string;
52
- assistantId: string;
53
51
  kind: string;
54
52
  sourceChannel: string;
55
53
  sourceConversationId: string;
@@ -101,7 +99,6 @@ function rowToRequest(
101
99
  ): GuardianActionRequest {
102
100
  return {
103
101
  id: row.id,
104
- assistantId: row.assistantId,
105
102
  kind: row.kind,
106
103
  sourceChannel: row.sourceChannel,
107
104
  sourceConversationId: row.sourceConversationId,
@@ -165,7 +162,6 @@ function generateRequestCode(): string {
165
162
  * legacy guardian action rows continue to compile.
166
163
  */
167
164
  export function createGuardianActionRequest(params: {
168
- assistantId?: string;
169
165
  kind: string;
170
166
  sourceChannel: string;
171
167
  sourceConversationId: string;
@@ -182,7 +178,6 @@ export function createGuardianActionRequest(params: {
182
178
 
183
179
  const row = {
184
180
  id,
185
- assistantId: params.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID,
186
181
  kind: params.kind,
187
182
  sourceChannel: params.sourceChannel,
188
183
  sourceConversationId: params.sourceConversationId,
@@ -693,14 +688,12 @@ export function createGuardianActionDelivery(params: {
693
688
  * Used by inbound message routing to match incoming answers to deliveries.
694
689
  */
695
690
  export function getPendingDeliveriesByDestination(
696
- assistantId: string,
697
691
  channel: string,
698
692
  chatId: string,
699
693
  ): GuardianActionDelivery[] {
700
694
  try {
701
695
  const db = getDb();
702
696
 
703
- // Join deliveries with requests to filter by assistantId
704
697
  const rows = db
705
698
  .select({
706
699
  delivery: guardianActionDeliveries,
@@ -712,7 +705,6 @@ export function getPendingDeliveriesByDestination(
712
705
  )
713
706
  .where(
714
707
  and(
715
- eq(guardianActionRequests.assistantId, assistantId),
716
708
  eq(guardianActionRequests.status, "pending"),
717
709
  eq(guardianActionDeliveries.destinationChannel, channel),
718
710
  eq(guardianActionDeliveries.destinationChatId, chatId),
@@ -784,7 +776,6 @@ export function getPendingDeliveriesByConversation(
784
776
  * Used by inbound message routing to match late guardian answers to expired requests.
785
777
  */
786
778
  export function getExpiredDeliveriesByDestination(
787
- assistantId: string,
788
779
  channel: string,
789
780
  chatId: string,
790
781
  ): GuardianActionDelivery[] {
@@ -802,7 +793,6 @@ export function getExpiredDeliveriesByDestination(
802
793
  )
803
794
  .where(
804
795
  and(
805
- eq(guardianActionRequests.assistantId, assistantId),
806
796
  eq(guardianActionRequests.status, "expired"),
807
797
  eq(guardianActionRequests.followupState, "none"),
808
798
  eq(guardianActionDeliveries.destinationChannel, channel),
@@ -877,7 +867,6 @@ export function getExpiredDeliveriesByConversation(
877
867
  * on channel paths (Telegram, SMS).
878
868
  */
879
869
  export function getFollowupDeliveriesByDestination(
880
- assistantId: string,
881
870
  channel: string,
882
871
  chatId: string,
883
872
  ): GuardianActionDelivery[] {
@@ -895,7 +884,6 @@ export function getFollowupDeliveriesByDestination(
895
884
  )
896
885
  .where(
897
886
  and(
898
- eq(guardianActionRequests.assistantId, assistantId),
899
887
  eq(guardianActionRequests.status, "expired"),
900
888
  eq(guardianActionRequests.followupState, "awaiting_guardian_choice"),
901
889
  eq(guardianActionDeliveries.destinationChannel, channel),
@@ -9,7 +9,6 @@
9
9
  import { and, count, desc, eq, gt, lte } from "drizzle-orm";
10
10
  import { v4 as uuid } from "uuid";
11
11
 
12
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
13
12
  import { getDb } from "./db.js";
14
13
  import { channelGuardianApprovalRequests } from "./schema.js";
15
14
 
@@ -29,7 +28,6 @@ export interface GuardianApprovalRequest {
29
28
  runId: string;
30
29
  requestId: string;
31
30
  conversationId: string;
32
- assistantId: string;
33
31
  channel: string;
34
32
  requesterExternalUserId: string;
35
33
  requesterChatId: string;
@@ -57,7 +55,6 @@ function rowToApprovalRequest(
57
55
  runId: row.runId,
58
56
  requestId: row.requestId ?? row.runId,
59
57
  conversationId: row.conversationId,
60
- assistantId: row.assistantId,
61
58
  channel: row.channel,
62
59
  requesterExternalUserId: row.requesterExternalUserId,
63
60
  requesterChatId: row.requesterChatId,
@@ -88,7 +85,6 @@ export function createApprovalRequest(params: {
88
85
  runId: string;
89
86
  requestId?: string;
90
87
  conversationId: string;
91
- assistantId?: string;
92
88
  channel: string;
93
89
  requesterExternalUserId: string;
94
90
  requesterChatId: string;
@@ -108,7 +104,6 @@ export function createApprovalRequest(params: {
108
104
  runId: params.runId,
109
105
  requestId: params.requestId ?? null,
110
106
  conversationId: params.conversationId,
111
- assistantId: params.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID,
112
107
  channel: params.channel,
113
108
  requesterExternalUserId: params.requesterExternalUserId,
114
109
  requesterChatId: params.requesterChatId,
@@ -172,34 +167,25 @@ export function getUnresolvedApprovalForRequest(
172
167
  /**
173
168
  * Find a pending guardian approval request by the guardian's chat ID.
174
169
  * Used when the guardian sends a decision from their chat.
175
- *
176
- * When `assistantId` is provided, the lookup is scoped to that assistant,
177
- * preventing cross-assistant approval consumption in shared guardian chats.
178
170
  */
179
171
  export function getPendingApprovalByGuardianChat(
180
172
  channel: string,
181
173
  guardianChatId: string,
182
- assistantId?: string,
183
174
  ): GuardianApprovalRequest | null {
184
175
  const db = getDb();
185
176
  const now = Date.now();
186
177
 
187
- const conditions = [
188
- eq(channelGuardianApprovalRequests.channel, channel),
189
- eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
190
- eq(channelGuardianApprovalRequests.status, "pending"),
191
- gt(channelGuardianApprovalRequests.expiresAt, now),
192
- ];
193
- if (assistantId) {
194
- conditions.push(
195
- eq(channelGuardianApprovalRequests.assistantId, assistantId),
196
- );
197
- }
198
-
199
178
  const row = db
200
179
  .select()
201
180
  .from(channelGuardianApprovalRequests)
202
- .where(and(...conditions))
181
+ .where(
182
+ and(
183
+ eq(channelGuardianApprovalRequests.channel, channel),
184
+ eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
185
+ eq(channelGuardianApprovalRequests.status, "pending"),
186
+ gt(channelGuardianApprovalRequests.expiresAt, now),
187
+ ),
188
+ )
203
189
  .orderBy(desc(channelGuardianApprovalRequests.createdAt))
204
190
  .get();
205
191
 
@@ -216,28 +202,22 @@ export function getPendingApprovalByRequestAndGuardianChat(
216
202
  requestId: string,
217
203
  channel: string,
218
204
  guardianChatId: string,
219
- assistantId?: string,
220
205
  ): GuardianApprovalRequest | null {
221
206
  const db = getDb();
222
207
  const now = Date.now();
223
208
 
224
- const conditions = [
225
- eq(channelGuardianApprovalRequests.requestId, requestId),
226
- eq(channelGuardianApprovalRequests.channel, channel),
227
- eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
228
- eq(channelGuardianApprovalRequests.status, "pending"),
229
- gt(channelGuardianApprovalRequests.expiresAt, now),
230
- ];
231
- if (assistantId) {
232
- conditions.push(
233
- eq(channelGuardianApprovalRequests.assistantId, assistantId),
234
- );
235
- }
236
-
237
209
  const row = db
238
210
  .select()
239
211
  .from(channelGuardianApprovalRequests)
240
- .where(and(...conditions))
212
+ .where(
213
+ and(
214
+ eq(channelGuardianApprovalRequests.requestId, requestId),
215
+ eq(channelGuardianApprovalRequests.channel, channel),
216
+ eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
217
+ eq(channelGuardianApprovalRequests.status, "pending"),
218
+ gt(channelGuardianApprovalRequests.expiresAt, now),
219
+ ),
220
+ )
241
221
  .get();
242
222
 
243
223
  return row ? rowToApprovalRequest(row) : null;
@@ -247,34 +227,25 @@ export function getPendingApprovalByRequestAndGuardianChat(
247
227
  * Return all pending (non-expired) guardian approval requests for a given
248
228
  * guardian chat and channel. Used to detect ambiguity when a guardian sends
249
229
  * a plain-text decision while multiple approvals are pending.
250
- *
251
- * When `assistantId` is provided, the results are scoped to that assistant
252
- * to prevent cross-assistant approval consumption.
253
230
  */
254
231
  export function getAllPendingApprovalsByGuardianChat(
255
232
  channel: string,
256
233
  guardianChatId: string,
257
- assistantId?: string,
258
234
  ): GuardianApprovalRequest[] {
259
235
  const db = getDb();
260
236
  const now = Date.now();
261
237
 
262
- const conditions = [
263
- eq(channelGuardianApprovalRequests.channel, channel),
264
- eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
265
- eq(channelGuardianApprovalRequests.status, "pending"),
266
- gt(channelGuardianApprovalRequests.expiresAt, now),
267
- ];
268
- if (assistantId) {
269
- conditions.push(
270
- eq(channelGuardianApprovalRequests.assistantId, assistantId),
271
- );
272
- }
273
-
274
238
  const rows = db
275
239
  .select()
276
240
  .from(channelGuardianApprovalRequests)
277
- .where(and(...conditions))
241
+ .where(
242
+ and(
243
+ eq(channelGuardianApprovalRequests.channel, channel),
244
+ eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
245
+ eq(channelGuardianApprovalRequests.status, "pending"),
246
+ gt(channelGuardianApprovalRequests.expiresAt, now),
247
+ ),
248
+ )
278
249
  .orderBy(desc(channelGuardianApprovalRequests.createdAt))
279
250
  .all();
280
251
 
@@ -326,11 +297,10 @@ export function updateApprovalDecision(
326
297
  // ---------------------------------------------------------------------------
327
298
 
328
299
  /**
329
- * List approval requests filtered by assistant, and optionally by channel,
330
- * conversation, and status. Returns a paginated list of escalations.
300
+ * List approval requests optionally filtered by channel, conversation, and
301
+ * status. Returns a paginated list of escalations.
331
302
  */
332
303
  export function listPendingApprovalRequests(params: {
333
- assistantId?: string;
334
304
  channel?: string;
335
305
  conversationId?: string;
336
306
  status?: ApprovalRequestStatus;
@@ -339,12 +309,7 @@ export function listPendingApprovalRequests(params: {
339
309
  }): GuardianApprovalRequest[] {
340
310
  const db = getDb();
341
311
 
342
- const conditions = [
343
- eq(
344
- channelGuardianApprovalRequests.assistantId,
345
- params.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID,
346
- ),
347
- ];
312
+ const conditions: ReturnType<typeof eq>[] = [];
348
313
  if (params.channel) {
349
314
  conditions.push(
350
315
  eq(channelGuardianApprovalRequests.channel, params.channel),
@@ -447,26 +412,18 @@ export function resolveApprovalRequest(
447
412
  * Count pending approval requests for a given conversation.
448
413
  * Used by thread state projection to compute `pending_escalation_count`.
449
414
  */
450
- export function countPendingByConversation(
451
- conversationId: string,
452
- assistantId?: string,
453
- ): number {
415
+ export function countPendingByConversation(conversationId: string): number {
454
416
  const db = getDb();
455
417
 
456
- const conditions = [
457
- eq(channelGuardianApprovalRequests.conversationId, conversationId),
458
- eq(channelGuardianApprovalRequests.status, "pending"),
459
- ];
460
- if (assistantId) {
461
- conditions.push(
462
- eq(channelGuardianApprovalRequests.assistantId, assistantId),
463
- );
464
- }
465
-
466
418
  const result = db
467
419
  .select({ count: count() })
468
420
  .from(channelGuardianApprovalRequests)
469
- .where(and(...conditions))
421
+ .where(
422
+ and(
423
+ eq(channelGuardianApprovalRequests.conversationId, conversationId),
424
+ eq(channelGuardianApprovalRequests.status, "pending"),
425
+ ),
426
+ )
470
427
  .get();
471
428
 
472
429
  return result?.count ?? 0;
@@ -478,7 +435,6 @@ export function countPendingByConversation(
478
435
  * Retained for existing test fixtures that check legacy approval dedup.
479
436
  */
480
437
  export function findPendingAccessRequestForRequester(
481
- assistantId: string,
482
438
  channel: string,
483
439
  requesterExternalUserId: string,
484
440
  toolName: string,
@@ -491,7 +447,6 @@ export function findPendingAccessRequestForRequester(
491
447
  .from(channelGuardianApprovalRequests)
492
448
  .where(
493
449
  and(
494
- eq(channelGuardianApprovalRequests.assistantId, assistantId),
495
450
  eq(channelGuardianApprovalRequests.channel, channel),
496
451
  eq(
497
452
  channelGuardianApprovalRequests.requesterExternalUserId,
@@ -17,7 +17,6 @@ import { channelGuardianRateLimits } from "./schema.js";
17
17
 
18
18
  export interface VerificationRateLimit {
19
19
  id: string;
20
- assistantId: string;
21
20
  channel: string;
22
21
  actorExternalUserId: string;
23
22
  actorChatId: string;
@@ -49,7 +48,6 @@ function rowToRateLimit(
49
48
  const timestamps = parseTimestamps(row.attemptTimestampsJson);
50
49
  return {
51
50
  id: row.id,
52
- assistantId: row.assistantId,
53
51
  channel: row.channel,
54
52
  actorExternalUserId: row.actorExternalUserId,
55
53
  actorChatId: row.actorChatId,
@@ -69,7 +67,6 @@ function rowToRateLimit(
69
67
  * Get the rate-limit record for a given actor on a specific channel.
70
68
  */
71
69
  export function getRateLimit(
72
- assistantId: string,
73
70
  channel: string,
74
71
  actorExternalUserId: string,
75
72
  actorChatId: string,
@@ -80,7 +77,6 @@ export function getRateLimit(
80
77
  .from(channelGuardianRateLimits)
81
78
  .where(
82
79
  and(
83
- eq(channelGuardianRateLimits.assistantId, assistantId),
84
80
  eq(channelGuardianRateLimits.channel, channel),
85
81
  eq(channelGuardianRateLimits.actorExternalUserId, actorExternalUserId),
86
82
  eq(channelGuardianRateLimits.actorChatId, actorChatId),
@@ -101,7 +97,6 @@ export function getRateLimit(
101
97
  * accumulate indefinitely.
102
98
  */
103
99
  export function recordInvalidAttempt(
104
- assistantId: string,
105
100
  channel: string,
106
101
  actorExternalUserId: string,
107
102
  actorChatId: string,
@@ -113,12 +108,7 @@ export function recordInvalidAttempt(
113
108
  const now = Date.now();
114
109
  const cutoff = now - windowMs;
115
110
 
116
- const existing = getRateLimit(
117
- assistantId,
118
- channel,
119
- actorExternalUserId,
120
- actorChatId,
121
- );
111
+ const existing = getRateLimit(channel, actorExternalUserId, actorChatId);
122
112
 
123
113
  if (existing) {
124
114
  // Keep only timestamps within the sliding window, then add the new one
@@ -158,7 +148,6 @@ export function recordInvalidAttempt(
158
148
  const lockedUntil = 1 >= maxAttempts ? now + lockoutMs : null;
159
149
  const row = {
160
150
  id,
161
- assistantId,
162
151
  channel,
163
152
  actorExternalUserId,
164
153
  actorChatId,
@@ -181,7 +170,6 @@ export function recordInvalidAttempt(
181
170
  * successful verification).
182
171
  */
183
172
  export function resetRateLimit(
184
- assistantId: string,
185
173
  channel: string,
186
174
  actorExternalUserId: string,
187
175
  actorChatId: string,
@@ -197,7 +185,6 @@ export function resetRateLimit(
197
185
  })
198
186
  .where(
199
187
  and(
200
- eq(channelGuardianRateLimits.assistantId, assistantId),
201
188
  eq(channelGuardianRateLimits.channel, channel),
202
189
  eq(channelGuardianRateLimits.actorExternalUserId, actorExternalUserId),
203
190
  eq(channelGuardianRateLimits.actorChatId, actorChatId),