@vellumai/assistant 0.4.33 → 0.4.35
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.
- package/package.json +1 -1
- package/src/__tests__/access-request-decision.test.ts +2 -3
- package/src/__tests__/actor-token-service.test.ts +4 -11
- package/src/__tests__/approval-primitive.test.ts +0 -45
- package/src/__tests__/assistant-id-boundary-guard.test.ts +169 -0
- package/src/__tests__/callback-handoff-copy.test.ts +0 -1
- package/src/__tests__/channel-approval-routes.test.ts +5 -45
- package/src/__tests__/channel-guardian.test.ts +122 -345
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +4 -3
- package/src/__tests__/contacts-tools.test.ts +4 -5
- package/src/__tests__/conversation-attention-store.test.ts +2 -65
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -2
- package/src/__tests__/conversation-pairing.test.ts +0 -1
- package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -2
- package/src/__tests__/guardian-action-conversation-turn.test.ts +1 -7
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -74
- package/src/__tests__/guardian-action-late-reply.test.ts +1 -8
- package/src/__tests__/guardian-grant-minting.test.ts +0 -1
- package/src/__tests__/guardian-routing-state.test.ts +0 -3
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -3
- package/src/__tests__/non-member-access-request.test.ts +0 -7
- package/src/__tests__/notification-broadcaster.test.ts +1 -2
- package/src/__tests__/notification-decision-fallback.test.ts +0 -2
- package/src/__tests__/notification-decision-strategy.test.ts +0 -1
- package/src/__tests__/relay-server.test.ts +11 -83
- package/src/__tests__/scoped-approval-grants.test.ts +9 -40
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -36
- package/src/__tests__/send-endpoint-busy.test.ts +0 -1
- package/src/__tests__/send-notification-tool.test.ts +0 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -4
- package/src/__tests__/thread-seed-composer.test.ts +0 -1
- package/src/__tests__/tool-approval-handler.test.ts +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +0 -4
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -5
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +1 -17
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -13
- package/src/__tests__/trusted-contact-verification.test.ts +3 -15
- package/src/__tests__/twilio-routes.test.ts +2 -2
- package/src/__tests__/voice-invite-redemption.test.ts +0 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -37
- package/src/approvals/approval-primitive.ts +0 -15
- package/src/approvals/guardian-decision-primitive.ts +0 -3
- package/src/approvals/guardian-request-resolvers.ts +0 -5
- package/src/calls/call-domain.ts +0 -3
- package/src/calls/call-store.ts +0 -3
- package/src/calls/guardian-action-sweep.ts +2 -1
- package/src/calls/guardian-dispatch.ts +1 -2
- package/src/calls/relay-access-wait.ts +0 -4
- package/src/calls/relay-server.ts +3 -11
- package/src/calls/relay-setup-router.ts +1 -2
- package/src/calls/relay-verification.ts +0 -1
- package/src/calls/twilio-routes.ts +0 -3
- package/src/calls/types.ts +0 -1
- package/src/calls/voice-session-bridge.ts +0 -1
- package/src/config/bundled-skills/google-oauth-setup/SKILL.md +100 -171
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -1
- package/src/contacts/contact-store.ts +13 -88
- package/src/contacts/contacts-write.ts +3 -11
- package/src/contacts/types.ts +0 -1
- package/src/daemon/handlers/config-channels.ts +16 -42
- package/src/daemon/handlers/config-inbox.ts +6 -6
- package/src/daemon/handlers/contacts.ts +3 -11
- package/src/daemon/handlers/index.ts +0 -2
- package/src/daemon/session-process.ts +0 -4
- package/src/memory/conversation-attention-store.ts +4 -19
- package/src/memory/conversation-crud.ts +0 -2
- package/src/memory/db-init.ts +4 -0
- package/src/memory/guardian-action-store.ts +0 -12
- package/src/memory/guardian-approvals.ts +35 -80
- package/src/memory/guardian-rate-limits.ts +1 -14
- package/src/memory/guardian-verification.ts +6 -34
- package/src/memory/invite-store.ts +5 -14
- package/src/memory/migrations/026-guardian-verification-sessions.ts +28 -9
- package/src/memory/migrations/027a-guardian-bootstrap-token.ts +16 -3
- package/src/memory/migrations/038-actor-token-records.ts +8 -1
- package/src/memory/migrations/039-actor-refresh-token-records.ts +11 -2
- package/src/memory/migrations/110-channel-guardian.ts +27 -6
- package/src/memory/migrations/112-assistant-inbox.ts +39 -15
- package/src/memory/migrations/114-notifications.ts +37 -15
- package/src/memory/migrations/117-conversation-attention.ts +33 -9
- package/src/memory/migrations/134-contacts-notes-column.ts +64 -45
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +263 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/migrations/registry.ts +14 -1
- package/src/memory/migrations/schema-introspection.ts +18 -0
- package/src/memory/schema/calls.ts +0 -7
- package/src/memory/schema/contacts.ts +0 -8
- package/src/memory/schema/guardian.ts +0 -5
- package/src/memory/schema/infrastructure.ts +0 -2
- package/src/memory/schema/notifications.ts +3 -17
- package/src/memory/scoped-approval-grants.ts +2 -24
- package/src/notifications/adapters/sms.ts +2 -1
- package/src/notifications/broadcaster.ts +1 -6
- package/src/notifications/decision-engine.ts +3 -4
- package/src/notifications/deliveries-store.ts +0 -4
- package/src/notifications/destination-resolver.ts +4 -6
- package/src/notifications/deterministic-checks.ts +1 -6
- package/src/notifications/emit-signal.ts +4 -11
- package/src/notifications/events-store.ts +7 -17
- package/src/notifications/preference-summary.ts +2 -2
- package/src/notifications/preferences-store.ts +2 -9
- package/src/notifications/signal.ts +0 -1
- package/src/notifications/thread-candidates.ts +1 -11
- package/src/notifications/types.ts +0 -3
- package/src/runtime/access-request-helper.ts +3 -10
- package/src/runtime/actor-refresh-token-store.ts +0 -6
- package/src/runtime/actor-token-store.ts +3 -16
- package/src/runtime/actor-trust-resolver.ts +1 -4
- package/src/runtime/auth/__tests__/credential-service.test.ts +0 -9
- package/src/runtime/auth/credential-service.ts +1 -15
- package/src/runtime/auth/require-bound-guardian.ts +1 -4
- package/src/runtime/channel-guardian-service.ts +15 -46
- package/src/runtime/channel-invite-transport.ts +8 -0
- package/src/runtime/channel-invite-transports/email.ts +4 -0
- package/src/runtime/channel-invite-transports/slack.ts +6 -0
- package/src/runtime/channel-invite-transports/sms.ts +4 -0
- package/src/runtime/channel-invite-transports/telegram.ts +6 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +0 -1
- package/src/runtime/guardian-action-followup-executor.ts +3 -2
- package/src/runtime/guardian-action-grant-minter.ts +0 -1
- package/src/runtime/guardian-outbound-actions.ts +2 -12
- package/src/runtime/guardian-vellum-migration.ts +2 -3
- package/src/runtime/http-server.ts +3 -10
- package/src/runtime/http-types.ts +13 -1
- package/src/runtime/invite-redemption-service.ts +1 -14
- package/src/runtime/local-actor-identity.ts +2 -5
- package/src/runtime/routes/access-request-decision.ts +0 -1
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +0 -9
- package/src/runtime/routes/channel-readiness-routes.ts +29 -18
- package/src/runtime/routes/contact-routes.ts +15 -40
- package/src/runtime/routes/conversation-attention-routes.ts +0 -2
- package/src/runtime/routes/global-search-routes.ts +0 -2
- package/src/runtime/routes/guardian-bootstrap-routes.ts +6 -7
- package/src/runtime/routes/guardian-expiry-sweep.ts +3 -2
- package/src/runtime/routes/inbound-message-handler.ts +0 -3
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +7 -43
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +1 -4
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +1 -6
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +0 -1
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +0 -1
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +3 -7
- package/src/runtime/routes/pairing-routes.ts +4 -4
- package/src/runtime/routes/surface-content-routes.ts +104 -0
- package/src/runtime/tool-grant-request-helper.ts +0 -1
- package/src/tools/browser/browser-manager.ts +22 -21
- package/src/tools/browser/runtime-check.ts +111 -6
- package/src/tools/calls/call-start.ts +1 -3
- package/src/tools/followups/followup_create.ts +1 -2
- package/src/tools/tool-approval-handler.ts +0 -2
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { getLogger } from "../../util/logger.js";
|
|
2
|
+
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
3
|
+
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
4
|
+
|
|
5
|
+
const log = getLogger("migration-136");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Drop `assistant_id` columns from all 16 daemon tables that carried the
|
|
9
|
+
* per-assistant scoping column. After wave-1 PRs normalised every value to
|
|
10
|
+
* 'self' (the implicit single-tenant identity), the column is dead weight.
|
|
11
|
+
*
|
|
12
|
+
* Steps:
|
|
13
|
+
* 1. Safety assertion: verify all rows are 'self' or NULL.
|
|
14
|
+
* 2. Drop composite indexes that include `assistant_id`.
|
|
15
|
+
* 3. `ALTER TABLE ... DROP COLUMN assistant_id` for each table.
|
|
16
|
+
* 4. Recreate indexes without the `assistant_id` column.
|
|
17
|
+
*/
|
|
18
|
+
export function migrateDropAssistantIdColumns(database: DrizzleDb): void {
|
|
19
|
+
withCrashRecovery(database, "migration_drop_assistant_id_columns_v1", () => {
|
|
20
|
+
const raw = getSqliteFrom(database);
|
|
21
|
+
|
|
22
|
+
// The 16 tables that carry assistant_id.
|
|
23
|
+
const tables = [
|
|
24
|
+
"contacts",
|
|
25
|
+
"assistant_ingress_invites",
|
|
26
|
+
"assistant_inbox_thread_state",
|
|
27
|
+
"call_sessions",
|
|
28
|
+
"channel_guardian_verification_challenges",
|
|
29
|
+
"channel_guardian_approval_requests",
|
|
30
|
+
"channel_guardian_rate_limits",
|
|
31
|
+
"guardian_action_requests",
|
|
32
|
+
"scoped_approval_grants",
|
|
33
|
+
"notification_events",
|
|
34
|
+
"notification_preferences",
|
|
35
|
+
"notification_deliveries",
|
|
36
|
+
"conversation_attention_events",
|
|
37
|
+
"conversation_assistant_attention_state",
|
|
38
|
+
"actor_token_records",
|
|
39
|
+
"actor_refresh_token_records",
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
// --- Safety assertion ---
|
|
43
|
+
// Verify all existing assistant_id values are 'self' or NULL before dropping.
|
|
44
|
+
for (const table of tables) {
|
|
45
|
+
const cols = new Set(
|
|
46
|
+
(
|
|
47
|
+
raw.query(`PRAGMA table_info(${table})`).all() as Array<{
|
|
48
|
+
name: string;
|
|
49
|
+
}>
|
|
50
|
+
).map((c) => c.name),
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
if (!cols.has("assistant_id")) {
|
|
54
|
+
log.info(
|
|
55
|
+
{ table },
|
|
56
|
+
"Table does not have assistant_id column — skipping",
|
|
57
|
+
);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const unexpected = raw
|
|
62
|
+
.query(
|
|
63
|
+
`SELECT DISTINCT assistant_id FROM ${table} WHERE assistant_id IS NOT NULL AND assistant_id != 'self'`,
|
|
64
|
+
)
|
|
65
|
+
.all() as Array<{ assistant_id: string }>;
|
|
66
|
+
|
|
67
|
+
if (unexpected.length > 0) {
|
|
68
|
+
log.warn(
|
|
69
|
+
{ table, values: unexpected.map((r) => r.assistant_id) },
|
|
70
|
+
"Unexpected assistant_id values found — skipping table",
|
|
71
|
+
);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// --- Drop ALL indexes that include assistant_id ---
|
|
77
|
+
// Every index below references the assistant_id column. SQLite will error
|
|
78
|
+
// on ALTER TABLE ... DROP COLUMN if any index still references the column.
|
|
79
|
+
|
|
80
|
+
// channel_guardian_verification_challenges indexes (migrations 110, 026, 027a)
|
|
81
|
+
raw.exec(
|
|
82
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_channel_guardian_challenges_lookup`,
|
|
83
|
+
);
|
|
84
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_guardian_sessions_active`);
|
|
85
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_guardian_sessions_identity`);
|
|
86
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_guardian_sessions_destination`);
|
|
87
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_guardian_sessions_bootstrap`);
|
|
88
|
+
|
|
89
|
+
// channel_guardian_rate_limits indexes (migration 110)
|
|
90
|
+
raw.exec(
|
|
91
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_channel_guardian_rate_limits_actor`,
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// assistant_ingress_invites indexes (migration 112)
|
|
95
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_ingress_invites_channel_status`);
|
|
96
|
+
raw.exec(
|
|
97
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_ingress_invites_channel_created`,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
// assistant_inbox_thread_state indexes (migration 112)
|
|
101
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_inbox_thread_state_channel`);
|
|
102
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_inbox_thread_state_last_msg`);
|
|
103
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_inbox_thread_state_escalation`);
|
|
104
|
+
|
|
105
|
+
// notification_preferences indexes (migration 114)
|
|
106
|
+
raw.exec(
|
|
107
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_notification_preferences_assistant_id`,
|
|
108
|
+
);
|
|
109
|
+
raw.exec(
|
|
110
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_notification_preferences_assistant_priority`,
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// notification_events indexes (migration 114)
|
|
114
|
+
raw.exec(
|
|
115
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_notification_events_assistant_event_created`,
|
|
116
|
+
);
|
|
117
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_notification_events_dedupe`);
|
|
118
|
+
|
|
119
|
+
// notification_deliveries indexes (migration 114)
|
|
120
|
+
raw.exec(
|
|
121
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_notification_deliveries_assistant_status`,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// conversation_attention_events indexes (migration 117)
|
|
125
|
+
raw.exec(
|
|
126
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_conv_attn_events_assistant_observed`,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// conversation_assistant_attention_state indexes (migration 117)
|
|
130
|
+
raw.exec(
|
|
131
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_conv_attn_state_assistant_latest_msg`,
|
|
132
|
+
);
|
|
133
|
+
raw.exec(
|
|
134
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_conv_attn_state_assistant_last_seen`,
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
// actor_token_records indexes (migration 038)
|
|
138
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_actor_tokens_active_device`);
|
|
139
|
+
|
|
140
|
+
// actor_refresh_token_records indexes (migration 039)
|
|
141
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_refresh_tokens_active_device`);
|
|
142
|
+
|
|
143
|
+
// --- Drop assistant_id column from each table ---
|
|
144
|
+
for (const table of tables) {
|
|
145
|
+
const cols = new Set(
|
|
146
|
+
(
|
|
147
|
+
raw.query(`PRAGMA table_info(${table})`).all() as Array<{
|
|
148
|
+
name: string;
|
|
149
|
+
}>
|
|
150
|
+
).map((c) => c.name),
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
if (!cols.has("assistant_id")) continue;
|
|
154
|
+
|
|
155
|
+
// Re-verify safety before each drop
|
|
156
|
+
const unexpected = raw
|
|
157
|
+
.query(
|
|
158
|
+
`SELECT DISTINCT assistant_id FROM ${table} WHERE assistant_id IS NOT NULL AND assistant_id != 'self'`,
|
|
159
|
+
)
|
|
160
|
+
.all() as Array<{ assistant_id: string }>;
|
|
161
|
+
|
|
162
|
+
if (unexpected.length > 0) {
|
|
163
|
+
log.warn(
|
|
164
|
+
{ table, values: unexpected.map((r) => r.assistant_id) },
|
|
165
|
+
"Unexpected assistant_id values — skipping column drop",
|
|
166
|
+
);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
raw.exec(/*sql*/ `ALTER TABLE ${table} DROP COLUMN assistant_id`);
|
|
171
|
+
log.info({ table }, "Dropped assistant_id column");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// --- Recreate indexes without assistant_id ---
|
|
175
|
+
// Each index below is the equivalent of the dropped index but with the
|
|
176
|
+
// assistant_id column removed. Index names are updated to avoid
|
|
177
|
+
// collisions with the old names.
|
|
178
|
+
|
|
179
|
+
// channel_guardian_verification_challenges
|
|
180
|
+
raw.exec(
|
|
181
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_channel_guardian_challenges_lookup ON channel_guardian_verification_challenges(channel, challenge_hash, status)`,
|
|
182
|
+
);
|
|
183
|
+
raw.exec(
|
|
184
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_guardian_sessions_active ON channel_guardian_verification_challenges(channel, status)`,
|
|
185
|
+
);
|
|
186
|
+
raw.exec(
|
|
187
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_guardian_sessions_identity ON channel_guardian_verification_challenges(channel, expected_external_user_id, expected_chat_id, status)`,
|
|
188
|
+
);
|
|
189
|
+
raw.exec(
|
|
190
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_guardian_sessions_destination ON channel_guardian_verification_challenges(channel, destination_address)`,
|
|
191
|
+
);
|
|
192
|
+
raw.exec(
|
|
193
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_guardian_sessions_bootstrap ON channel_guardian_verification_challenges(channel, bootstrap_token_hash, status)`,
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// channel_guardian_rate_limits
|
|
197
|
+
raw.exec(
|
|
198
|
+
/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_channel_guardian_rate_limits_actor ON channel_guardian_rate_limits(channel, actor_external_user_id, actor_chat_id)`,
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// assistant_ingress_invites
|
|
202
|
+
raw.exec(
|
|
203
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_ingress_invites_channel_status ON assistant_ingress_invites(source_channel, status, expires_at)`,
|
|
204
|
+
);
|
|
205
|
+
raw.exec(
|
|
206
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_ingress_invites_channel_created ON assistant_ingress_invites(source_channel, created_at)`,
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
// assistant_inbox_thread_state
|
|
210
|
+
raw.exec(
|
|
211
|
+
/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_inbox_thread_state_channel ON assistant_inbox_thread_state(source_channel, external_chat_id)`,
|
|
212
|
+
);
|
|
213
|
+
raw.exec(
|
|
214
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_inbox_thread_state_last_msg ON assistant_inbox_thread_state(last_message_at)`,
|
|
215
|
+
);
|
|
216
|
+
raw.exec(
|
|
217
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_inbox_thread_state_escalation ON assistant_inbox_thread_state(has_pending_escalation, last_message_at)`,
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// notification_preferences
|
|
221
|
+
raw.exec(
|
|
222
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_notification_preferences_priority ON notification_preferences(priority DESC)`,
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
// notification_events
|
|
226
|
+
raw.exec(
|
|
227
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_notification_events_event_created ON notification_events(source_event_name, created_at)`,
|
|
228
|
+
);
|
|
229
|
+
raw.exec(
|
|
230
|
+
/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_notification_events_dedupe ON notification_events(dedupe_key) WHERE dedupe_key IS NOT NULL`,
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
// notification_deliveries
|
|
234
|
+
raw.exec(
|
|
235
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_notification_deliveries_status ON notification_deliveries(status)`,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
// conversation_attention_events
|
|
239
|
+
raw.exec(
|
|
240
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_conv_attn_events_observed ON conversation_attention_events(observed_at)`,
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
// conversation_assistant_attention_state
|
|
244
|
+
raw.exec(
|
|
245
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_conv_attn_state_latest_msg ON conversation_assistant_attention_state(latest_assistant_message_at)`,
|
|
246
|
+
);
|
|
247
|
+
raw.exec(
|
|
248
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_conv_attn_state_last_seen ON conversation_assistant_attention_state(last_seen_assistant_message_at)`,
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// actor_token_records
|
|
252
|
+
raw.exec(
|
|
253
|
+
/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_actor_tokens_active_device ON actor_token_records(guardian_principal_id, hashed_device_id) WHERE status = 'active'`,
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
// actor_refresh_token_records
|
|
257
|
+
raw.exec(
|
|
258
|
+
/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_refresh_tokens_active_device ON actor_refresh_token_records(guardian_principal_id, hashed_device_id) WHERE status = 'active'`,
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
log.info("Completed dropping assistant_id columns from all tables");
|
|
262
|
+
});
|
|
263
|
+
}
|
|
@@ -78,6 +78,7 @@ export { migrateContactsAssistantId } from "./132-contacts-assistant-id.js";
|
|
|
78
78
|
export { migrateAssistantContactMetadata } from "./133-assistant-contact-metadata.js";
|
|
79
79
|
export { migrateContactsNotesColumn } from "./134-contacts-notes-column.js";
|
|
80
80
|
export { migrateBackfillContactInteractionStats } from "./135-backfill-contact-interaction-stats.js";
|
|
81
|
+
export { migrateDropAssistantIdColumns } from "./136-drop-assistant-id-columns.js";
|
|
81
82
|
export {
|
|
82
83
|
MIGRATION_REGISTRY,
|
|
83
84
|
type MigrationRegistryEntry,
|
|
@@ -123,11 +123,24 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
|
|
|
123
123
|
"Enforce NOT NULL on channel_guardian_bindings.guardian_principal_id after backfill",
|
|
124
124
|
},
|
|
125
125
|
{
|
|
126
|
-
key: "
|
|
126
|
+
key: "migration_contacts_notes_column_v1",
|
|
127
127
|
version: 17,
|
|
128
|
+
description:
|
|
129
|
+
"Consolidate relationship/importance/response_expectation/preferred_tone into a single notes TEXT column, then drop the legacy columns",
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
key: "backfill_contact_interaction_stats",
|
|
133
|
+
version: 18,
|
|
128
134
|
description:
|
|
129
135
|
"Backfill contacts.last_interaction from the max lastSeenAt across each contact's channels",
|
|
130
136
|
},
|
|
137
|
+
{
|
|
138
|
+
key: "migration_drop_assistant_id_columns_v1",
|
|
139
|
+
version: 19,
|
|
140
|
+
dependsOn: ["migration_normalize_assistant_id_to_self_v1"],
|
|
141
|
+
description:
|
|
142
|
+
"Drop assistant_id columns from all 16 daemon tables after normalization to single-tenant identity",
|
|
143
|
+
},
|
|
131
144
|
];
|
|
132
145
|
|
|
133
146
|
export interface MigrationValidationResult {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Startup still replays the historical table/index bootstrap helpers on every
|
|
5
|
+
* process launch, so migrations need a cheap way to branch on the live schema.
|
|
6
|
+
*/
|
|
7
|
+
export function tableHasColumn(
|
|
8
|
+
database: DrizzleDb,
|
|
9
|
+
tableName: string,
|
|
10
|
+
columnName: string,
|
|
11
|
+
): boolean {
|
|
12
|
+
const raw = getSqliteFrom(database);
|
|
13
|
+
const columns = raw.query(`PRAGMA table_info(${tableName})`).all() as Array<{
|
|
14
|
+
name: string;
|
|
15
|
+
}>;
|
|
16
|
+
|
|
17
|
+
return columns.some((column) => column.name === columnName);
|
|
18
|
+
}
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
text,
|
|
7
7
|
} from "drizzle-orm/sqlite-core";
|
|
8
8
|
|
|
9
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
10
9
|
import { conversations } from "./conversations.js";
|
|
11
10
|
|
|
12
11
|
export const callSessions = sqliteTable(
|
|
@@ -26,7 +25,6 @@ export const callSessions = sqliteTable(
|
|
|
26
25
|
guardianVerificationSessionId: text("guardian_verification_session_id"),
|
|
27
26
|
callerIdentityMode: text("caller_identity_mode"),
|
|
28
27
|
callerIdentitySource: text("caller_identity_source"),
|
|
29
|
-
assistantId: text("assistant_id"),
|
|
30
28
|
initiatedFromConversationId: text("initiated_from_conversation_id"),
|
|
31
29
|
startedAt: integer("started_at"),
|
|
32
30
|
endedAt: integer("ended_at"),
|
|
@@ -91,7 +89,6 @@ export const channelGuardianVerificationChallenges = sqliteTable(
|
|
|
91
89
|
"channel_guardian_verification_challenges",
|
|
92
90
|
{
|
|
93
91
|
id: text("id").primaryKey(),
|
|
94
|
-
assistantId: text("assistant_id").notNull(),
|
|
95
92
|
channel: text("channel").notNull(),
|
|
96
93
|
challengeHash: text("challenge_hash").notNull(),
|
|
97
94
|
expiresAt: integer("expires_at").notNull(),
|
|
@@ -128,9 +125,6 @@ export const channelGuardianApprovalRequests = sqliteTable(
|
|
|
128
125
|
runId: text("run_id").notNull(),
|
|
129
126
|
requestId: text("request_id"),
|
|
130
127
|
conversationId: text("conversation_id").notNull(),
|
|
131
|
-
assistantId: text("assistant_id")
|
|
132
|
-
.notNull()
|
|
133
|
-
.default(DAEMON_INTERNAL_ASSISTANT_ID),
|
|
134
128
|
channel: text("channel").notNull(),
|
|
135
129
|
requesterExternalUserId: text("requester_external_user_id").notNull(),
|
|
136
130
|
requesterChatId: text("requester_chat_id").notNull(),
|
|
@@ -151,7 +145,6 @@ export const channelGuardianRateLimits = sqliteTable(
|
|
|
151
145
|
"channel_guardian_rate_limits",
|
|
152
146
|
{
|
|
153
147
|
id: text("id").primaryKey(),
|
|
154
|
-
assistantId: text("assistant_id").notNull(),
|
|
155
148
|
channel: text("channel").notNull(),
|
|
156
149
|
actorExternalUserId: text("actor_external_user_id").notNull(),
|
|
157
150
|
actorChatId: text("actor_chat_id").notNull(),
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
2
2
|
|
|
3
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
4
3
|
import { conversations } from "./conversations.js";
|
|
5
4
|
|
|
6
5
|
export const contacts = sqliteTable("contacts", {
|
|
@@ -13,7 +12,6 @@ export const contacts = sqliteTable("contacts", {
|
|
|
13
12
|
updatedAt: integer("updated_at").notNull(),
|
|
14
13
|
role: text("role").notNull().default("contact"), // 'guardian' | 'contact'
|
|
15
14
|
principalId: text("principal_id"), // internal auth principal (nullable)
|
|
16
|
-
assistantId: text("assistant_id"), // which assistant this guardian is for (nullable, daemon default is DAEMON_INTERNAL_ASSISTANT_ID)
|
|
17
15
|
contactType: text("contact_type").notNull().default("human"), // 'human' | 'assistant'
|
|
18
16
|
});
|
|
19
17
|
|
|
@@ -69,9 +67,6 @@ export const assistantIngressInvites = sqliteTable(
|
|
|
69
67
|
"assistant_ingress_invites",
|
|
70
68
|
{
|
|
71
69
|
id: text("id").primaryKey(),
|
|
72
|
-
assistantId: text("assistant_id")
|
|
73
|
-
.notNull()
|
|
74
|
-
.default(DAEMON_INTERNAL_ASSISTANT_ID),
|
|
75
70
|
sourceChannel: text("source_channel").notNull(),
|
|
76
71
|
tokenHash: text("token_hash").notNull(),
|
|
77
72
|
createdBySessionId: text("created_by_session_id"),
|
|
@@ -103,9 +98,6 @@ export const assistantInboxThreadState = sqliteTable(
|
|
|
103
98
|
conversationId: text("conversation_id")
|
|
104
99
|
.primaryKey()
|
|
105
100
|
.references(() => conversations.id, { onDelete: "cascade" }),
|
|
106
|
-
assistantId: text("assistant_id")
|
|
107
|
-
.notNull()
|
|
108
|
-
.default(DAEMON_INTERNAL_ASSISTANT_ID),
|
|
109
101
|
sourceChannel: text("source_channel").notNull(),
|
|
110
102
|
externalChatId: text("external_chat_id").notNull(),
|
|
111
103
|
externalUserId: text("external_user_id"),
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
2
2
|
|
|
3
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
4
3
|
import { callPendingQuestions, callSessions } from "./calls.js";
|
|
5
4
|
|
|
6
5
|
export const guardianActionRequests = sqliteTable(
|
|
7
6
|
"guardian_action_requests",
|
|
8
7
|
{
|
|
9
8
|
id: text("id").primaryKey(),
|
|
10
|
-
assistantId: text("assistant_id")
|
|
11
|
-
.notNull()
|
|
12
|
-
.default(DAEMON_INTERNAL_ASSISTANT_ID),
|
|
13
9
|
kind: text("kind").notNull(), // 'ask_guardian'
|
|
14
10
|
sourceChannel: text("source_channel").notNull(), // 'voice'
|
|
15
11
|
sourceConversationId: text("source_conversation_id").notNull(),
|
|
@@ -145,7 +141,6 @@ export const scopedApprovalGrants = sqliteTable(
|
|
|
145
141
|
"scoped_approval_grants",
|
|
146
142
|
{
|
|
147
143
|
id: text("id").primaryKey(),
|
|
148
|
-
assistantId: text("assistant_id").notNull(),
|
|
149
144
|
scopeMode: text("scope_mode").notNull(), // 'request_id' | 'tool_signature'
|
|
150
145
|
requestId: text("request_id"),
|
|
151
146
|
toolName: text("tool_name"),
|
|
@@ -173,7 +173,6 @@ export const llmUsageEvents = sqliteTable(
|
|
|
173
173
|
export const actorTokenRecords = sqliteTable("actor_token_records", {
|
|
174
174
|
id: text("id").primaryKey(),
|
|
175
175
|
tokenHash: text("token_hash").notNull(),
|
|
176
|
-
assistantId: text("assistant_id").notNull(),
|
|
177
176
|
guardianPrincipalId: text("guardian_principal_id").notNull(),
|
|
178
177
|
hashedDeviceId: text("hashed_device_id").notNull(),
|
|
179
178
|
platform: text("platform").notNull(),
|
|
@@ -190,7 +189,6 @@ export const actorRefreshTokenRecords = sqliteTable(
|
|
|
190
189
|
id: text("id").primaryKey(),
|
|
191
190
|
tokenHash: text("token_hash").notNull(),
|
|
192
191
|
familyId: text("family_id").notNull(),
|
|
193
|
-
assistantId: text("assistant_id").notNull(),
|
|
194
192
|
guardianPrincipalId: text("guardian_principal_id").notNull(),
|
|
195
193
|
hashedDeviceId: text("hashed_device_id").notNull(),
|
|
196
194
|
platform: text("platform").notNull(),
|
|
@@ -11,7 +11,6 @@ import { conversations } from "./conversations.js";
|
|
|
11
11
|
|
|
12
12
|
export const notificationEvents = sqliteTable("notification_events", {
|
|
13
13
|
id: text("id").primaryKey(),
|
|
14
|
-
assistantId: text("assistant_id").notNull(),
|
|
15
14
|
sourceEventName: text("source_event_name").notNull(),
|
|
16
15
|
sourceChannel: text("source_channel").notNull(),
|
|
17
16
|
sourceSessionId: text("source_session_id").notNull(),
|
|
@@ -39,7 +38,6 @@ export const notificationDecisions = sqliteTable("notification_decisions", {
|
|
|
39
38
|
|
|
40
39
|
export const notificationPreferences = sqliteTable("notification_preferences", {
|
|
41
40
|
id: text("id").primaryKey(),
|
|
42
|
-
assistantId: text("assistant_id").notNull(),
|
|
43
41
|
preferenceText: text("preference_text").notNull(),
|
|
44
42
|
appliesWhenJson: text("applies_when_json").notNull().default("{}"),
|
|
45
43
|
priority: integer("priority").notNull().default(0),
|
|
@@ -95,7 +93,6 @@ export const notificationDeliveries = sqliteTable(
|
|
|
95
93
|
notificationDecisionId: text("notification_decision_id")
|
|
96
94
|
.notNull()
|
|
97
95
|
.references(() => notificationDecisions.id, { onDelete: "cascade" }),
|
|
98
|
-
assistantId: text("assistant_id").notNull(),
|
|
99
96
|
channel: text("channel").notNull(),
|
|
100
97
|
destination: text("destination").notNull(),
|
|
101
98
|
status: text("status").notNull().default("pending"),
|
|
@@ -132,7 +129,6 @@ export const conversationAttentionEvents = sqliteTable(
|
|
|
132
129
|
conversationId: text("conversation_id")
|
|
133
130
|
.notNull()
|
|
134
131
|
.references(() => conversations.id, { onDelete: "cascade" }),
|
|
135
|
-
assistantId: text("assistant_id").notNull(),
|
|
136
132
|
sourceChannel: text("source_channel").notNull(),
|
|
137
133
|
signalType: text("signal_type").notNull(),
|
|
138
134
|
confidence: text("confidence").notNull(),
|
|
@@ -147,10 +143,7 @@ export const conversationAttentionEvents = sqliteTable(
|
|
|
147
143
|
table.conversationId,
|
|
148
144
|
table.observedAt,
|
|
149
145
|
),
|
|
150
|
-
index("
|
|
151
|
-
table.assistantId,
|
|
152
|
-
table.observedAt,
|
|
153
|
-
),
|
|
146
|
+
index("idx_conv_attn_events_observed").on(table.observedAt),
|
|
154
147
|
index("idx_conv_attn_events_channel_observed").on(
|
|
155
148
|
table.sourceChannel,
|
|
156
149
|
table.observedAt,
|
|
@@ -164,7 +157,6 @@ export const conversationAssistantAttentionState = sqliteTable(
|
|
|
164
157
|
conversationId: text("conversation_id")
|
|
165
158
|
.primaryKey()
|
|
166
159
|
.references(() => conversations.id, { onDelete: "cascade" }),
|
|
167
|
-
assistantId: text("assistant_id").notNull(),
|
|
168
160
|
latestAssistantMessageId: text("latest_assistant_message_id"),
|
|
169
161
|
latestAssistantMessageAt: integer("latest_assistant_message_at"),
|
|
170
162
|
lastSeenAssistantMessageId: text("last_seen_assistant_message_id"),
|
|
@@ -179,13 +171,7 @@ export const conversationAssistantAttentionState = sqliteTable(
|
|
|
179
171
|
updatedAt: integer("updated_at").notNull(),
|
|
180
172
|
},
|
|
181
173
|
(table) => [
|
|
182
|
-
index("
|
|
183
|
-
|
|
184
|
-
table.latestAssistantMessageAt,
|
|
185
|
-
),
|
|
186
|
-
index("idx_conv_attn_state_assistant_last_seen").on(
|
|
187
|
-
table.assistantId,
|
|
188
|
-
table.lastSeenAssistantMessageAt,
|
|
189
|
-
),
|
|
174
|
+
index("idx_conv_attn_state_latest_msg").on(table.latestAssistantMessageAt),
|
|
175
|
+
index("idx_conv_attn_state_last_seen").on(table.lastSeenAssistantMessageAt),
|
|
190
176
|
],
|
|
191
177
|
);
|
|
@@ -29,7 +29,6 @@ export type GrantStatus = "active" | "consumed" | "expired" | "revoked";
|
|
|
29
29
|
|
|
30
30
|
export interface ScopedApprovalGrant {
|
|
31
31
|
id: string;
|
|
32
|
-
assistantId: string;
|
|
33
32
|
scopeMode: ScopeMode;
|
|
34
33
|
requestId: string | null;
|
|
35
34
|
toolName: string | null;
|
|
@@ -65,7 +64,6 @@ function rowToGrant(
|
|
|
65
64
|
): ScopedApprovalGrant {
|
|
66
65
|
return {
|
|
67
66
|
id: row.id,
|
|
68
|
-
assistantId: row.assistantId,
|
|
69
67
|
scopeMode: row.scopeMode as ScopeMode,
|
|
70
68
|
requestId: row.requestId,
|
|
71
69
|
toolName: row.toolName,
|
|
@@ -91,7 +89,6 @@ function rowToGrant(
|
|
|
91
89
|
// ---------------------------------------------------------------------------
|
|
92
90
|
|
|
93
91
|
export interface CreateScopedApprovalGrantParams {
|
|
94
|
-
assistantId: string;
|
|
95
92
|
scopeMode: ScopeMode;
|
|
96
93
|
requestId?: string | null;
|
|
97
94
|
toolName?: string | null;
|
|
@@ -115,7 +112,6 @@ function createScopedApprovalGrant(
|
|
|
115
112
|
|
|
116
113
|
const row = {
|
|
117
114
|
id,
|
|
118
|
-
assistantId: params.assistantId,
|
|
119
115
|
scopeMode: params.scopeMode,
|
|
120
116
|
requestId: params.requestId ?? null,
|
|
121
117
|
toolName: params.toolName ?? null,
|
|
@@ -143,7 +139,6 @@ function createScopedApprovalGrant(
|
|
|
143
139
|
grantId: id,
|
|
144
140
|
scopeMode: params.scopeMode,
|
|
145
141
|
toolName: params.toolName ?? null,
|
|
146
|
-
assistantId: params.assistantId,
|
|
147
142
|
requestChannel: params.requestChannel,
|
|
148
143
|
decisionChannel: params.decisionChannel,
|
|
149
144
|
executionChannel: params.executionChannel ?? null,
|
|
@@ -168,13 +163,12 @@ export interface ConsumeByRequestIdResult {
|
|
|
168
163
|
* Atomically consume a grant by request ID.
|
|
169
164
|
*
|
|
170
165
|
* Only succeeds when exactly one active, non-expired grant matches the
|
|
171
|
-
* given `requestId
|
|
172
|
-
*
|
|
166
|
+
* given `requestId`. Uses compare-and-swap on the `status` column so
|
|
167
|
+
* concurrent consumers race safely — at most one wins.
|
|
173
168
|
*/
|
|
174
169
|
function consumeScopedApprovalGrantByRequestId(
|
|
175
170
|
requestId: string,
|
|
176
171
|
consumingRequestId: string,
|
|
177
|
-
assistantId: string,
|
|
178
172
|
now?: string,
|
|
179
173
|
): ConsumeByRequestIdResult {
|
|
180
174
|
const db = getDb();
|
|
@@ -189,7 +183,6 @@ function consumeScopedApprovalGrantByRequestId(
|
|
|
189
183
|
.where(
|
|
190
184
|
and(
|
|
191
185
|
eq(scopedApprovalGrants.requestId, requestId),
|
|
192
|
-
eq(scopedApprovalGrants.assistantId, assistantId),
|
|
193
186
|
eq(scopedApprovalGrants.scopeMode, "request_id"),
|
|
194
187
|
eq(scopedApprovalGrants.status, "active"),
|
|
195
188
|
sql`${scopedApprovalGrants.expiresAt} > ${currentTime}`,
|
|
@@ -204,7 +197,6 @@ function consumeScopedApprovalGrantByRequestId(
|
|
|
204
197
|
event: "scoped_grant_consume_miss",
|
|
205
198
|
requestId,
|
|
206
199
|
consumingRequestId,
|
|
207
|
-
assistantId,
|
|
208
200
|
scopeMode: "request_id",
|
|
209
201
|
attempt,
|
|
210
202
|
},
|
|
@@ -247,7 +239,6 @@ function consumeScopedApprovalGrantByRequestId(
|
|
|
247
239
|
grantId: grant?.id,
|
|
248
240
|
requestId,
|
|
249
241
|
consumingRequestId,
|
|
250
|
-
assistantId,
|
|
251
242
|
scopeMode: "request_id",
|
|
252
243
|
},
|
|
253
244
|
"Scoped approval grant consumed by request ID",
|
|
@@ -262,7 +253,6 @@ function consumeScopedApprovalGrantByRequestId(
|
|
|
262
253
|
event: "scoped_grant_consume_miss",
|
|
263
254
|
requestId,
|
|
264
255
|
consumingRequestId,
|
|
265
|
-
assistantId,
|
|
266
256
|
scopeMode: "request_id",
|
|
267
257
|
reason: "cas_exhausted",
|
|
268
258
|
},
|
|
@@ -280,7 +270,6 @@ export interface ConsumeByToolSignatureParams {
|
|
|
280
270
|
inputDigest: string;
|
|
281
271
|
consumingRequestId: string;
|
|
282
272
|
/** Optional context constraints — only matched when the grant has a non-null value */
|
|
283
|
-
assistantId?: string;
|
|
284
273
|
executionChannel?: string;
|
|
285
274
|
conversationId?: string;
|
|
286
275
|
callSessionId?: string;
|
|
@@ -319,12 +308,6 @@ function consumeScopedApprovalGrantByToolSignature(
|
|
|
319
308
|
sql`${scopedApprovalGrants.expiresAt} > ${currentTime}`,
|
|
320
309
|
];
|
|
321
310
|
|
|
322
|
-
// assistantId is always set on grants — scope consumption to the current
|
|
323
|
-
// assistant so grants minted for one assistant cannot be consumed by another.
|
|
324
|
-
if (params.assistantId !== undefined) {
|
|
325
|
-
conditions.push(eq(scopedApprovalGrants.assistantId, params.assistantId));
|
|
326
|
-
}
|
|
327
|
-
|
|
328
311
|
// Context constraints: grant field must be NULL (any) or match exactly
|
|
329
312
|
if (params.executionChannel !== undefined) {
|
|
330
313
|
conditions.push(
|
|
@@ -488,7 +471,6 @@ export function expireScopedApprovalGrants(now?: string): number {
|
|
|
488
471
|
// ---------------------------------------------------------------------------
|
|
489
472
|
|
|
490
473
|
export interface RevokeContextParams {
|
|
491
|
-
assistantId?: string;
|
|
492
474
|
conversationId?: string;
|
|
493
475
|
callSessionId?: string;
|
|
494
476
|
requestChannel?: string;
|
|
@@ -510,9 +492,6 @@ export function revokeScopedApprovalGrantsForContext(
|
|
|
510
492
|
|
|
511
493
|
const conditions = [eq(scopedApprovalGrants.status, "active")];
|
|
512
494
|
|
|
513
|
-
if (params.assistantId !== undefined) {
|
|
514
|
-
conditions.push(eq(scopedApprovalGrants.assistantId, params.assistantId));
|
|
515
|
-
}
|
|
516
495
|
if (params.conversationId !== undefined) {
|
|
517
496
|
conditions.push(
|
|
518
497
|
eq(scopedApprovalGrants.conversationId, params.conversationId),
|
|
@@ -550,7 +529,6 @@ export function revokeScopedApprovalGrantsForContext(
|
|
|
550
529
|
{
|
|
551
530
|
event: "scoped_grant_revoked",
|
|
552
531
|
count,
|
|
553
|
-
assistantId: params.assistantId,
|
|
554
532
|
conversationId: params.conversationId,
|
|
555
533
|
callSessionId: params.callSessionId,
|
|
556
534
|
requestChannel: params.requestChannel,
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { getGatewayInternalBaseUrl } from "../../config/env.js";
|
|
16
|
+
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
16
17
|
import { mintDaemonDeliveryToken } from "../../runtime/auth/token-service.js";
|
|
17
18
|
import { deliverChannelReply } from "../../runtime/gateway-client.js";
|
|
18
19
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -70,7 +71,7 @@ export class SmsAdapter implements ChannelAdapter {
|
|
|
70
71
|
{
|
|
71
72
|
chatId: phoneNumber,
|
|
72
73
|
text: messageText,
|
|
73
|
-
assistantId:
|
|
74
|
+
assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
|
|
74
75
|
},
|
|
75
76
|
mintDaemonDeliveryToken(),
|
|
76
77
|
);
|
|
@@ -77,10 +77,7 @@ export class NotificationBroadcaster {
|
|
|
77
77
|
decision: NotificationDecision,
|
|
78
78
|
options?: BroadcastDecisionOptions,
|
|
79
79
|
): Promise<NotificationDeliveryResult[]> {
|
|
80
|
-
const destinations = resolveDestinations(
|
|
81
|
-
signal.assistantId,
|
|
82
|
-
decision.selectedChannels,
|
|
83
|
-
);
|
|
80
|
+
const destinations = resolveDestinations(decision.selectedChannels);
|
|
84
81
|
|
|
85
82
|
// Ensure vellum is processed first so the notification_thread_created IPC
|
|
86
83
|
// push fires immediately, before slower channel sends (e.g. Telegram 30s
|
|
@@ -271,7 +268,6 @@ export class NotificationBroadcaster {
|
|
|
271
268
|
const payload: ChannelDeliveryPayload = {
|
|
272
269
|
deliveryId,
|
|
273
270
|
sourceEventName: signal.sourceEventName,
|
|
274
|
-
assistantId: signal.assistantId,
|
|
275
271
|
copy,
|
|
276
272
|
deepLinkTarget,
|
|
277
273
|
};
|
|
@@ -291,7 +287,6 @@ export class NotificationBroadcaster {
|
|
|
291
287
|
createDelivery({
|
|
292
288
|
id: deliveryId,
|
|
293
289
|
notificationDecisionId: persistedDecisionId,
|
|
294
|
-
assistantId: signal.assistantId,
|
|
295
290
|
channel,
|
|
296
291
|
destination: destinationLabel,
|
|
297
292
|
status: "pending",
|