@vellumai/assistant 0.4.33 → 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.
- 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 +150 -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/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/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/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 +0 -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 +5 -6
- 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/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
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
import type { ChannelId } from "../channels/types.js";
|
|
10
10
|
import type { GuardianBinding } from "../memory/channel-guardian-store.js";
|
|
11
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
12
11
|
import { canonicalizeInboundIdentity } from "../util/canonicalize-identity.js";
|
|
13
12
|
import { getLogger } from "../util/logger.js";
|
|
14
13
|
import { emitContactChange } from "./contact-events.js";
|
|
@@ -58,7 +57,6 @@ function parseDisplayNameFromMetadata(
|
|
|
58
57
|
* (so callers expecting binding.id still work).
|
|
59
58
|
*/
|
|
60
59
|
export function createGuardianBinding(params: {
|
|
61
|
-
assistantId: string;
|
|
62
60
|
channel: string;
|
|
63
61
|
guardianExternalUserId: string;
|
|
64
62
|
guardianDeliveryChatId: string;
|
|
@@ -81,7 +79,6 @@ export function createGuardianBinding(params: {
|
|
|
81
79
|
role: "guardian",
|
|
82
80
|
notes: "guardian",
|
|
83
81
|
principalId: params.guardianPrincipalId,
|
|
84
|
-
assistantId: params.assistantId,
|
|
85
82
|
channels: [
|
|
86
83
|
{
|
|
87
84
|
type: params.channel,
|
|
@@ -98,7 +95,7 @@ export function createGuardianBinding(params: {
|
|
|
98
95
|
const now = Date.now();
|
|
99
96
|
const result: GuardianBinding = {
|
|
100
97
|
id: `contact-binding-${params.channel}`,
|
|
101
|
-
assistantId:
|
|
98
|
+
assistantId: "self",
|
|
102
99
|
channel: params.channel,
|
|
103
100
|
guardianExternalUserId: params.guardianExternalUserId,
|
|
104
101
|
guardianDeliveryChatId: params.guardianDeliveryChatId,
|
|
@@ -118,11 +115,8 @@ export function createGuardianBinding(params: {
|
|
|
118
115
|
* Revoke a guardian binding by updating the contacts table.
|
|
119
116
|
* Returns true when a guardian channel was found and revoked, false otherwise.
|
|
120
117
|
*/
|
|
121
|
-
export function revokeGuardianBinding(
|
|
122
|
-
|
|
123
|
-
channel: string,
|
|
124
|
-
): boolean {
|
|
125
|
-
const guardian = findGuardianForChannel(channel, assistantId);
|
|
118
|
+
export function revokeGuardianBinding(channel: string): boolean {
|
|
119
|
+
const guardian = findGuardianForChannel(channel);
|
|
126
120
|
if (!guardian) return false;
|
|
127
121
|
|
|
128
122
|
updateChannelStatus(guardian.channel.id, {
|
|
@@ -150,7 +144,6 @@ export function upsertMember(params: {
|
|
|
150
144
|
status?: string;
|
|
151
145
|
inviteId?: string;
|
|
152
146
|
createdBySessionId?: string;
|
|
153
|
-
assistantId?: string;
|
|
154
147
|
}): ContactWriteResult | null {
|
|
155
148
|
let address: string;
|
|
156
149
|
|
|
@@ -179,7 +172,6 @@ export function upsertMember(params: {
|
|
|
179
172
|
|
|
180
173
|
upsertContact({
|
|
181
174
|
displayName,
|
|
182
|
-
assistantId: params.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID,
|
|
183
175
|
channels: [
|
|
184
176
|
{
|
|
185
177
|
type: params.sourceChannel,
|
package/src/contacts/types.ts
CHANGED
|
@@ -2,7 +2,10 @@ import * as net from "node:net";
|
|
|
2
2
|
|
|
3
3
|
import type { ChannelId } from "../../channels/types.js";
|
|
4
4
|
import { resolveGuardianName } from "../../config/user-reference.js";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
findContactChannel,
|
|
7
|
+
findGuardianForChannel,
|
|
8
|
+
} from "../../contacts/contact-store.js";
|
|
6
9
|
import { revokeMember } from "../../contacts/contacts-write.js";
|
|
7
10
|
import type { ChannelStatus } from "../../contacts/types.js";
|
|
8
11
|
import * as externalConversationStore from "../../memory/external-conversation-store.js";
|
|
@@ -88,11 +91,7 @@ export function createGuardianChallenge(
|
|
|
88
91
|
};
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
const result = createVerificationChallenge(
|
|
92
|
-
resolvedAssistantId,
|
|
93
|
-
resolvedChannel,
|
|
94
|
-
sessionId,
|
|
95
|
-
);
|
|
94
|
+
const result = createVerificationChallenge(resolvedChannel, sessionId);
|
|
96
95
|
|
|
97
96
|
return {
|
|
98
97
|
success: true,
|
|
@@ -110,36 +109,15 @@ export function getGuardianStatus(
|
|
|
110
109
|
|
|
111
110
|
const binding = getGuardianBinding(resolvedAssistantId, resolvedChannel);
|
|
112
111
|
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
let guardianUsername: string | undefined;
|
|
118
|
-
let bindingDisplayName: string | undefined;
|
|
119
|
-
if (binding?.metadataJson) {
|
|
120
|
-
try {
|
|
121
|
-
const parsed = JSON.parse(binding.metadataJson) as Record<
|
|
122
|
-
string,
|
|
123
|
-
unknown
|
|
124
|
-
>;
|
|
125
|
-
if (
|
|
126
|
-
typeof parsed.username === "string" &&
|
|
127
|
-
parsed.username.trim().length > 0
|
|
128
|
-
) {
|
|
129
|
-
guardianUsername = parsed.username.trim();
|
|
130
|
-
}
|
|
131
|
-
if (
|
|
132
|
-
typeof parsed.displayName === "string" &&
|
|
133
|
-
parsed.displayName.trim().length > 0
|
|
134
|
-
) {
|
|
135
|
-
bindingDisplayName = parsed.displayName.trim();
|
|
136
|
-
}
|
|
137
|
-
} catch {
|
|
138
|
-
// ignore malformed metadata
|
|
139
|
-
}
|
|
140
|
-
}
|
|
112
|
+
// Read the contact directly to get displayName — getGuardianBinding is a
|
|
113
|
+
// compatibility shim that doesn't carry metadataJson.
|
|
114
|
+
const guardianResult = findGuardianForChannel(resolvedChannel);
|
|
115
|
+
const bindingDisplayName = guardianResult?.contact.displayName;
|
|
141
116
|
const guardianDisplayName = resolveGuardianName(bindingDisplayName);
|
|
142
|
-
|
|
117
|
+
|
|
118
|
+
// Resolve username from external conversation store.
|
|
119
|
+
let guardianUsername: string | undefined;
|
|
120
|
+
if (binding?.guardianDeliveryChatId) {
|
|
143
121
|
const ext = externalConversationStore.getBindingByChannelChat(
|
|
144
122
|
resolvedChannel,
|
|
145
123
|
binding.guardianDeliveryChatId,
|
|
@@ -148,15 +126,11 @@ export function getGuardianStatus(
|
|
|
148
126
|
guardianUsername = ext.username;
|
|
149
127
|
}
|
|
150
128
|
}
|
|
151
|
-
const hasPendingChallenge =
|
|
152
|
-
getPendingChallenge(resolvedAssistantId, resolvedChannel) != null;
|
|
129
|
+
const hasPendingChallenge = getPendingChallenge(resolvedChannel) != null;
|
|
153
130
|
|
|
154
131
|
// Include active outbound session state so the UI can resume
|
|
155
132
|
// after app restart and detect bootstrap completion.
|
|
156
|
-
const activeOutboundSession = findActiveSession(
|
|
157
|
-
resolvedAssistantId,
|
|
158
|
-
resolvedChannel,
|
|
159
|
-
);
|
|
133
|
+
const activeOutboundSession = findActiveSession(resolvedChannel);
|
|
160
134
|
const outboundFields: Record<string, unknown> = {};
|
|
161
135
|
if (activeOutboundSession) {
|
|
162
136
|
outboundFields.verificationSessionId = activeOutboundSession.id;
|
|
@@ -195,7 +169,7 @@ export function revokeGuardianForChannel(
|
|
|
195
169
|
// Always revoke pending challenges first — the macOS app uses
|
|
196
170
|
// action: "revoke" to cancel an in-flight challenge even before
|
|
197
171
|
// a binding exists (e.g. during verification setup).
|
|
198
|
-
revokePendingChallenges(
|
|
172
|
+
revokePendingChallenges(resolvedChannel);
|
|
199
173
|
|
|
200
174
|
// Capture binding before revoking so we can revoke the guardian's
|
|
201
175
|
// contact record — without this, the guardian would still pass
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from "../../memory/channel-guardian-store.js";
|
|
13
13
|
import { addMessage, getMessages } from "../../memory/conversation-store.js";
|
|
14
14
|
import { getBindingByConversation } from "../../memory/external-conversation-store.js";
|
|
15
|
+
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
15
16
|
import { mintDaemonDeliveryToken } from "../../runtime/auth/token-service.js";
|
|
16
17
|
import { deliverChannelReply } from "../../runtime/gateway-client.js";
|
|
17
18
|
import {
|
|
@@ -153,7 +154,6 @@ export function handleInboxEscalation(
|
|
|
153
154
|
switch (msg.action) {
|
|
154
155
|
case "list": {
|
|
155
156
|
const escalations = listPendingApprovalRequests({
|
|
156
|
-
assistantId: msg.assistantId,
|
|
157
157
|
status: (msg.status as ApprovalRequestStatus) ?? undefined,
|
|
158
158
|
});
|
|
159
159
|
ctx.send(socket, {
|
|
@@ -279,7 +279,7 @@ async function executeApprove(
|
|
|
279
279
|
approval: GuardianApprovalRequest,
|
|
280
280
|
ctx: HandlerContext,
|
|
281
281
|
): Promise<void> {
|
|
282
|
-
const { conversationId,
|
|
282
|
+
const { conversationId, channel } = approval;
|
|
283
283
|
|
|
284
284
|
// Recover the original message content from the stored payload
|
|
285
285
|
const payload = getLatestStoredPayload(conversationId);
|
|
@@ -316,7 +316,7 @@ async function executeApprove(
|
|
|
316
316
|
});
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
|
-
session.setAssistantId(
|
|
319
|
+
session.setAssistantId(DAEMON_INTERNAL_ASSISTANT_ID);
|
|
320
320
|
// The guardian already approved this escalation via the inbox, so we
|
|
321
321
|
// directly set guardian trust. Going through resolveLocalIpcTrustContext
|
|
322
322
|
// would look up the vellum binding's guardian ID and compare it against
|
|
@@ -368,7 +368,7 @@ async function executeApprove(
|
|
|
368
368
|
{
|
|
369
369
|
chatId: externalChatId,
|
|
370
370
|
text: rendered.text,
|
|
371
|
-
assistantId,
|
|
371
|
+
assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
|
|
372
372
|
},
|
|
373
373
|
bearerToken,
|
|
374
374
|
);
|
|
@@ -388,7 +388,7 @@ async function executeDeny(
|
|
|
388
388
|
approval: GuardianApprovalRequest,
|
|
389
389
|
reason: string | undefined,
|
|
390
390
|
): Promise<void> {
|
|
391
|
-
const { conversationId,
|
|
391
|
+
const { conversationId, channel } = approval;
|
|
392
392
|
|
|
393
393
|
const binding = getBindingByConversation(conversationId);
|
|
394
394
|
if (!binding) {
|
|
@@ -423,7 +423,7 @@ async function executeDeny(
|
|
|
423
423
|
{
|
|
424
424
|
chatId: binding.externalChatId,
|
|
425
425
|
text: denialText,
|
|
426
|
-
assistantId,
|
|
426
|
+
assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
|
|
427
427
|
},
|
|
428
428
|
bearerToken,
|
|
429
429
|
);
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
updateChannelStatus,
|
|
8
8
|
} from "../../contacts/contact-store.js";
|
|
9
9
|
import type { ContactWithChannels } from "../../contacts/types.js";
|
|
10
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
11
10
|
import type {
|
|
12
11
|
ContactChannelPayload,
|
|
13
12
|
ContactPayload,
|
|
@@ -58,11 +57,7 @@ export function handleContacts(
|
|
|
58
57
|
try {
|
|
59
58
|
switch (msg.action) {
|
|
60
59
|
case "list": {
|
|
61
|
-
const results = listContacts(
|
|
62
|
-
DAEMON_INTERNAL_ASSISTANT_ID,
|
|
63
|
-
msg.limit ?? 50,
|
|
64
|
-
msg.role,
|
|
65
|
-
);
|
|
60
|
+
const results = listContacts(msg.limit ?? 50, msg.role);
|
|
66
61
|
ctx.send(socket, {
|
|
67
62
|
type: "contacts_response",
|
|
68
63
|
success: true,
|
|
@@ -80,7 +75,7 @@ export function handleContacts(
|
|
|
80
75
|
});
|
|
81
76
|
return;
|
|
82
77
|
}
|
|
83
|
-
const contact = getContact(msg.contactId
|
|
78
|
+
const contact = getContact(msg.contactId);
|
|
84
79
|
if (!contact) {
|
|
85
80
|
ctx.send(socket, {
|
|
86
81
|
type: "contacts_response",
|
|
@@ -131,10 +126,7 @@ export function handleContacts(
|
|
|
131
126
|
return;
|
|
132
127
|
}
|
|
133
128
|
// Return the parent contact with all channels so the client has the full picture
|
|
134
|
-
const parentContact = getContact(
|
|
135
|
-
updated.contactId,
|
|
136
|
-
DAEMON_INTERNAL_ASSISTANT_ID,
|
|
137
|
-
);
|
|
129
|
+
const parentContact = getContact(updated.contactId);
|
|
138
130
|
ctx.send(socket, {
|
|
139
131
|
type: "contacts_response",
|
|
140
132
|
success: true,
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
type SignalType,
|
|
7
7
|
} from "../../memory/conversation-attention-store.js";
|
|
8
8
|
import { updateDeliveryClientOutcome } from "../../notifications/deliveries-store.js";
|
|
9
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
10
9
|
import type { ClientMessage } from "../ipc-protocol.js";
|
|
11
10
|
import {
|
|
12
11
|
handleRideShotgunStart,
|
|
@@ -120,7 +119,6 @@ const inlineHandlers = defineHandlers({
|
|
|
120
119
|
try {
|
|
121
120
|
recordConversationSeenSignal({
|
|
122
121
|
conversationId: msg.conversationId,
|
|
123
|
-
assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
|
|
124
122
|
sourceChannel: msg.sourceChannel,
|
|
125
123
|
signalType: msg.signalType as SignalType,
|
|
126
124
|
confidence: msg.confidence as Confidence,
|
|
@@ -434,13 +434,11 @@ export async function drainQueue(
|
|
|
434
434
|
// Fire-and-forget: detect notification preferences in the queued message
|
|
435
435
|
// and persist any that are found, mirroring the logic in processMessage.
|
|
436
436
|
if (session.assistantId) {
|
|
437
|
-
const aid = session.assistantId;
|
|
438
437
|
extractPreferences(resolvedContent)
|
|
439
438
|
.then((result) => {
|
|
440
439
|
if (!result.detected) return;
|
|
441
440
|
for (const pref of result.preferences) {
|
|
442
441
|
createPreference({
|
|
443
|
-
assistantId: aid,
|
|
444
442
|
preferenceText: pref.preferenceText,
|
|
445
443
|
appliesWhen: pref.appliesWhen,
|
|
446
444
|
priority: pref.priority,
|
|
@@ -735,13 +733,11 @@ export async function processMessage(
|
|
|
735
733
|
// and persist any that are found. Runs in the background so it doesn't
|
|
736
734
|
// block the main conversation flow.
|
|
737
735
|
if (session.assistantId) {
|
|
738
|
-
const aid = session.assistantId;
|
|
739
736
|
extractPreferences(resolvedContent)
|
|
740
737
|
.then((result) => {
|
|
741
738
|
if (!result.detected) return;
|
|
742
739
|
for (const pref of result.preferences) {
|
|
743
740
|
createPreference({
|
|
744
|
-
assistantId: aid,
|
|
745
741
|
preferenceText: pref.preferenceText,
|
|
746
742
|
appliesWhen: pref.appliesWhen,
|
|
747
743
|
priority: pref.priority,
|
|
@@ -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,
|
|
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
|
-
|
|
377
|
-
|
|
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
|
});
|
package/src/memory/db-init.ts
CHANGED
|
@@ -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,
|
|
@@ -289,6 +290,9 @@ export function initializeDb(): void {
|
|
|
289
290
|
// 39. Backfill contact interaction stats from channel lastSeenAt
|
|
290
291
|
migrateBackfillContactInteractionStats(database);
|
|
291
292
|
|
|
293
|
+
// 40. Drop assistant_id columns from all 16 daemon tables
|
|
294
|
+
migrateDropAssistantIdColumns(database);
|
|
295
|
+
|
|
292
296
|
validateMigrationState(database);
|
|
293
297
|
|
|
294
298
|
if (process.env.BUN_TEST === "1") {
|
|
@@ -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),
|