@vellumai/assistant 0.3.2 → 0.3.3
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/README.md +82 -13
- package/package.json +1 -1
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +16 -0
- package/src/__tests__/app-git-history.test.ts +22 -27
- package/src/__tests__/app-git-service.test.ts +44 -78
- package/src/__tests__/channel-approval-routes.test.ts +930 -14
- package/src/__tests__/channel-approval.test.ts +2 -0
- package/src/__tests__/channel-delivery-store.test.ts +104 -1
- package/src/__tests__/channel-guardian.test.ts +184 -1
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/daemon-server-session-init.test.ts +5 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +87 -8
- package/src/__tests__/handlers-telegram-config.test.ts +82 -0
- package/src/__tests__/handlers-twilio-config.test.ts +665 -5
- package/src/__tests__/ingress-url-consistency.test.ts +64 -0
- package/src/__tests__/ipc-snapshot.test.ts +10 -0
- package/src/__tests__/run-orchestrator.test.ts +1 -1
- package/src/__tests__/session-process-bridge.test.ts +2 -0
- package/src/__tests__/tool-permission-simulate-handler.test.ts +2 -2
- package/src/calls/twilio-config.ts +10 -1
- package/src/calls/twilio-rest.ts +70 -0
- package/src/config/bundled-skills/email-setup/SKILL.md +56 -0
- package/src/config/bundled-skills/subagent/SKILL.md +4 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
- package/src/config/schema.ts +3 -0
- package/src/config/vellum-skills/twilio-setup/SKILL.md +11 -4
- package/src/daemon/handlers/config.ts +168 -15
- package/src/daemon/handlers/sessions.ts +5 -3
- package/src/daemon/handlers/skills.ts +61 -17
- package/src/daemon/ipc-contract-inventory.json +4 -0
- package/src/daemon/ipc-contract.ts +10 -0
- package/src/daemon/session-agent-loop.ts +4 -0
- package/src/daemon/session-process.ts +20 -3
- package/src/daemon/session-slash.ts +50 -2
- package/src/daemon/session-surfaces.ts +17 -1
- package/src/inbound/public-ingress-urls.ts +20 -3
- package/src/index.ts +1 -23
- package/src/memory/app-git-service.ts +24 -0
- package/src/memory/app-store.ts +0 -21
- package/src/memory/channel-delivery-store.ts +74 -3
- package/src/memory/channel-guardian-store.ts +54 -26
- package/src/memory/conversation-key-store.ts +20 -0
- package/src/memory/conversation-store.ts +14 -2
- package/src/memory/db.ts +12 -0
- package/src/memory/schema.ts +5 -0
- package/src/runtime/http-server.ts +13 -5
- package/src/runtime/routes/channel-routes.ts +134 -43
- package/src/skills/clawhub.ts +6 -2
- package/src/subagent/manager.ts +4 -1
- package/src/subagent/types.ts +2 -0
- package/src/tools/skills/vellum-catalog.ts +45 -2
- package/src/tools/subagent/spawn.ts +2 -0
|
@@ -58,6 +58,7 @@ export interface GuardianApprovalRequest {
|
|
|
58
58
|
id: string;
|
|
59
59
|
runId: string;
|
|
60
60
|
conversationId: string;
|
|
61
|
+
assistantId: string;
|
|
61
62
|
channel: string;
|
|
62
63
|
requesterExternalUserId: string;
|
|
63
64
|
requesterChatId: string;
|
|
@@ -114,6 +115,7 @@ function rowToApprovalRequest(row: typeof channelGuardianApprovalRequests.$infer
|
|
|
114
115
|
id: row.id,
|
|
115
116
|
runId: row.runId,
|
|
116
117
|
conversationId: row.conversationId,
|
|
118
|
+
assistantId: row.assistantId,
|
|
117
119
|
channel: row.channel,
|
|
118
120
|
requesterExternalUserId: row.requesterExternalUserId,
|
|
119
121
|
requesterChatId: row.requesterChatId,
|
|
@@ -305,6 +307,7 @@ export function consumeChallenge(
|
|
|
305
307
|
export function createApprovalRequest(params: {
|
|
306
308
|
runId: string;
|
|
307
309
|
conversationId: string;
|
|
310
|
+
assistantId?: string;
|
|
308
311
|
channel: string;
|
|
309
312
|
requesterExternalUserId: string;
|
|
310
313
|
requesterChatId: string;
|
|
@@ -323,6 +326,7 @@ export function createApprovalRequest(params: {
|
|
|
323
326
|
id,
|
|
324
327
|
runId: params.runId,
|
|
325
328
|
conversationId: params.conversationId,
|
|
329
|
+
assistantId: params.assistantId ?? 'self',
|
|
326
330
|
channel: params.channel,
|
|
327
331
|
requesterExternalUserId: params.requesterExternalUserId,
|
|
328
332
|
requesterChatId: params.requesterChatId,
|
|
@@ -388,25 +392,32 @@ export function getUnresolvedApprovalForRun(runId: string): GuardianApprovalRequ
|
|
|
388
392
|
/**
|
|
389
393
|
* Find a pending guardian approval request by the guardian's chat ID.
|
|
390
394
|
* Used when the guardian sends a decision from their chat.
|
|
395
|
+
*
|
|
396
|
+
* When `assistantId` is provided, the lookup is scoped to that assistant,
|
|
397
|
+
* preventing cross-assistant approval consumption in shared guardian chats.
|
|
391
398
|
*/
|
|
392
399
|
export function getPendingApprovalByGuardianChat(
|
|
393
400
|
channel: string,
|
|
394
401
|
guardianChatId: string,
|
|
402
|
+
assistantId?: string,
|
|
395
403
|
): GuardianApprovalRequest | null {
|
|
396
404
|
const db = getDb();
|
|
397
405
|
const now = Date.now();
|
|
398
406
|
|
|
407
|
+
const conditions = [
|
|
408
|
+
eq(channelGuardianApprovalRequests.channel, channel),
|
|
409
|
+
eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
|
|
410
|
+
eq(channelGuardianApprovalRequests.status, 'pending'),
|
|
411
|
+
gt(channelGuardianApprovalRequests.expiresAt, now),
|
|
412
|
+
];
|
|
413
|
+
if (assistantId) {
|
|
414
|
+
conditions.push(eq(channelGuardianApprovalRequests.assistantId, assistantId));
|
|
415
|
+
}
|
|
416
|
+
|
|
399
417
|
const row = db
|
|
400
418
|
.select()
|
|
401
419
|
.from(channelGuardianApprovalRequests)
|
|
402
|
-
.where(
|
|
403
|
-
and(
|
|
404
|
-
eq(channelGuardianApprovalRequests.channel, channel),
|
|
405
|
-
eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
|
|
406
|
-
eq(channelGuardianApprovalRequests.status, 'pending'),
|
|
407
|
-
gt(channelGuardianApprovalRequests.expiresAt, now),
|
|
408
|
-
),
|
|
409
|
-
)
|
|
420
|
+
.where(and(...conditions))
|
|
410
421
|
.orderBy(desc(channelGuardianApprovalRequests.createdAt))
|
|
411
422
|
.get();
|
|
412
423
|
|
|
@@ -418,27 +429,34 @@ export function getPendingApprovalByGuardianChat(
|
|
|
418
429
|
* guardian chat, and channel. Used when a callback button provides a run ID,
|
|
419
430
|
* so the decision is applied to exactly the right approval even when
|
|
420
431
|
* multiple approvals target the same guardian chat.
|
|
432
|
+
*
|
|
433
|
+
* When `assistantId` is provided, the lookup is further scoped to that
|
|
434
|
+
* assistant to prevent cross-assistant approval consumption.
|
|
421
435
|
*/
|
|
422
436
|
export function getPendingApprovalByRunAndGuardianChat(
|
|
423
437
|
runId: string,
|
|
424
438
|
channel: string,
|
|
425
439
|
guardianChatId: string,
|
|
440
|
+
assistantId?: string,
|
|
426
441
|
): GuardianApprovalRequest | null {
|
|
427
442
|
const db = getDb();
|
|
428
443
|
const now = Date.now();
|
|
429
444
|
|
|
445
|
+
const conditions = [
|
|
446
|
+
eq(channelGuardianApprovalRequests.runId, runId),
|
|
447
|
+
eq(channelGuardianApprovalRequests.channel, channel),
|
|
448
|
+
eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
|
|
449
|
+
eq(channelGuardianApprovalRequests.status, 'pending'),
|
|
450
|
+
gt(channelGuardianApprovalRequests.expiresAt, now),
|
|
451
|
+
];
|
|
452
|
+
if (assistantId) {
|
|
453
|
+
conditions.push(eq(channelGuardianApprovalRequests.assistantId, assistantId));
|
|
454
|
+
}
|
|
455
|
+
|
|
430
456
|
const row = db
|
|
431
457
|
.select()
|
|
432
458
|
.from(channelGuardianApprovalRequests)
|
|
433
|
-
.where(
|
|
434
|
-
and(
|
|
435
|
-
eq(channelGuardianApprovalRequests.runId, runId),
|
|
436
|
-
eq(channelGuardianApprovalRequests.channel, channel),
|
|
437
|
-
eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
|
|
438
|
-
eq(channelGuardianApprovalRequests.status, 'pending'),
|
|
439
|
-
gt(channelGuardianApprovalRequests.expiresAt, now),
|
|
440
|
-
),
|
|
441
|
-
)
|
|
459
|
+
.where(and(...conditions))
|
|
442
460
|
.get();
|
|
443
461
|
|
|
444
462
|
return row ? rowToApprovalRequest(row) : null;
|
|
@@ -448,25 +466,32 @@ export function getPendingApprovalByRunAndGuardianChat(
|
|
|
448
466
|
* Return all pending (non-expired) guardian approval requests for a given
|
|
449
467
|
* guardian chat and channel. Used to detect ambiguity when a guardian sends
|
|
450
468
|
* a plain-text decision while multiple approvals are pending.
|
|
469
|
+
*
|
|
470
|
+
* When `assistantId` is provided, the results are scoped to that assistant
|
|
471
|
+
* to prevent cross-assistant approval consumption.
|
|
451
472
|
*/
|
|
452
473
|
export function getAllPendingApprovalsByGuardianChat(
|
|
453
474
|
channel: string,
|
|
454
475
|
guardianChatId: string,
|
|
476
|
+
assistantId?: string,
|
|
455
477
|
): GuardianApprovalRequest[] {
|
|
456
478
|
const db = getDb();
|
|
457
479
|
const now = Date.now();
|
|
458
480
|
|
|
481
|
+
const conditions = [
|
|
482
|
+
eq(channelGuardianApprovalRequests.channel, channel),
|
|
483
|
+
eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
|
|
484
|
+
eq(channelGuardianApprovalRequests.status, 'pending'),
|
|
485
|
+
gt(channelGuardianApprovalRequests.expiresAt, now),
|
|
486
|
+
];
|
|
487
|
+
if (assistantId) {
|
|
488
|
+
conditions.push(eq(channelGuardianApprovalRequests.assistantId, assistantId));
|
|
489
|
+
}
|
|
490
|
+
|
|
459
491
|
const rows = db
|
|
460
492
|
.select()
|
|
461
493
|
.from(channelGuardianApprovalRequests)
|
|
462
|
-
.where(
|
|
463
|
-
and(
|
|
464
|
-
eq(channelGuardianApprovalRequests.channel, channel),
|
|
465
|
-
eq(channelGuardianApprovalRequests.guardianChatId, guardianChatId),
|
|
466
|
-
eq(channelGuardianApprovalRequests.status, 'pending'),
|
|
467
|
-
gt(channelGuardianApprovalRequests.expiresAt, now),
|
|
468
|
-
),
|
|
469
|
-
)
|
|
494
|
+
.where(and(...conditions))
|
|
470
495
|
.orderBy(desc(channelGuardianApprovalRequests.createdAt))
|
|
471
496
|
.all();
|
|
472
497
|
|
|
@@ -525,7 +550,7 @@ export interface VerificationRateLimit {
|
|
|
525
550
|
actorChatId: string;
|
|
526
551
|
/** Individual attempt timestamps (epoch-ms) within the sliding window. */
|
|
527
552
|
attemptTimestamps: number[];
|
|
528
|
-
/**
|
|
553
|
+
/** Total stored attempt count (may include expired timestamps; use lockedUntil for enforcement decisions). */
|
|
529
554
|
invalidAttempts: number;
|
|
530
555
|
lockedUntil: number | null;
|
|
531
556
|
createdAt: number;
|
|
@@ -645,6 +670,9 @@ export function recordInvalidAttempt(
|
|
|
645
670
|
channel,
|
|
646
671
|
actorExternalUserId,
|
|
647
672
|
actorChatId,
|
|
673
|
+
// Legacy columns kept for backward compatibility with upgraded databases
|
|
674
|
+
invalidAttempts: 0,
|
|
675
|
+
windowStartedAt: 0,
|
|
648
676
|
attemptTimestampsJson: JSON.stringify(timestamps),
|
|
649
677
|
lockedUntil,
|
|
650
678
|
createdAt: now,
|
|
@@ -67,6 +67,26 @@ export function setConversationKey(conversationKey: string, conversationId: stri
|
|
|
67
67
|
.run();
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Insert a conversation-key mapping only if the key does not already exist.
|
|
72
|
+
*
|
|
73
|
+
* Uses `onConflictDoNothing` on the unique `conversationKey` column to
|
|
74
|
+
* avoid unique-constraint races when concurrent first messages attempt
|
|
75
|
+
* to migrate a legacy key to a new scoped alias.
|
|
76
|
+
*/
|
|
77
|
+
export function setConversationKeyIfAbsent(conversationKey: string, conversationId: string): void {
|
|
78
|
+
const db = getDb();
|
|
79
|
+
db.insert(conversationKeys)
|
|
80
|
+
.values({
|
|
81
|
+
id: uuid(),
|
|
82
|
+
conversationKey,
|
|
83
|
+
conversationId,
|
|
84
|
+
createdAt: Date.now(),
|
|
85
|
+
})
|
|
86
|
+
.onConflictDoNothing()
|
|
87
|
+
.run();
|
|
88
|
+
}
|
|
89
|
+
|
|
70
90
|
/**
|
|
71
91
|
* Get or create a conversation for the given conversationKey.
|
|
72
92
|
*
|
|
@@ -84,7 +84,7 @@ export function deleteConversation(id: string): void {
|
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
export function listConversations(limit?: number, includeBackground = false) {
|
|
87
|
+
export function listConversations(limit?: number, includeBackground = false, offset = 0) {
|
|
88
88
|
const db = getDb();
|
|
89
89
|
const where = includeBackground ? undefined : sql`${conversations.threadType} != 'background'`;
|
|
90
90
|
const query = db
|
|
@@ -92,10 +92,22 @@ export function listConversations(limit?: number, includeBackground = false) {
|
|
|
92
92
|
.from(conversations)
|
|
93
93
|
.where(where)
|
|
94
94
|
.orderBy(desc(conversations.updatedAt))
|
|
95
|
-
.limit(limit ?? 100)
|
|
95
|
+
.limit(limit ?? 100)
|
|
96
|
+
.offset(offset);
|
|
96
97
|
return query.all();
|
|
97
98
|
}
|
|
98
99
|
|
|
100
|
+
export function countConversations(includeBackground = false): number {
|
|
101
|
+
const db = getDb();
|
|
102
|
+
const where = includeBackground ? undefined : sql`${conversations.threadType} != 'background'`;
|
|
103
|
+
const [{ total }] = db
|
|
104
|
+
.select({ total: count() })
|
|
105
|
+
.from(conversations)
|
|
106
|
+
.where(where)
|
|
107
|
+
.all();
|
|
108
|
+
return total;
|
|
109
|
+
}
|
|
110
|
+
|
|
99
111
|
export function getLatestConversation() {
|
|
100
112
|
const db = getDb();
|
|
101
113
|
const result = db
|
package/src/memory/db.ts
CHANGED
|
@@ -992,6 +992,10 @@ export function initializeDb(): void {
|
|
|
992
992
|
database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_channel_guardian_approval_run ON channel_guardian_approval_requests(run_id, status)`);
|
|
993
993
|
database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_channel_guardian_approval_status ON channel_guardian_approval_requests(status)`);
|
|
994
994
|
|
|
995
|
+
// Migration: add assistant_id column to scope approval requests by assistant.
|
|
996
|
+
// Existing rows default to 'self' for backward compatibility.
|
|
997
|
+
try { database.run(/*sql*/ `ALTER TABLE channel_guardian_approval_requests ADD COLUMN assistant_id TEXT NOT NULL DEFAULT 'self'`); } catch { /* already exists */ }
|
|
998
|
+
|
|
995
999
|
// ── Channel Guardian Verification Rate Limits ─────────────────────
|
|
996
1000
|
|
|
997
1001
|
database.run(/*sql*/ `
|
|
@@ -1001,6 +1005,8 @@ export function initializeDb(): void {
|
|
|
1001
1005
|
channel TEXT NOT NULL,
|
|
1002
1006
|
actor_external_user_id TEXT NOT NULL,
|
|
1003
1007
|
actor_chat_id TEXT NOT NULL,
|
|
1008
|
+
invalid_attempts INTEGER NOT NULL DEFAULT 0,
|
|
1009
|
+
window_started_at INTEGER NOT NULL DEFAULT 0,
|
|
1004
1010
|
attempt_timestamps_json TEXT NOT NULL DEFAULT '[]',
|
|
1005
1011
|
locked_until INTEGER,
|
|
1006
1012
|
created_at INTEGER NOT NULL,
|
|
@@ -1013,6 +1019,12 @@ export function initializeDb(): void {
|
|
|
1013
1019
|
// doesn't support DROP COLUMN in older versions) but are no longer read by the app.
|
|
1014
1020
|
try { database.run(/*sql*/ `ALTER TABLE channel_guardian_rate_limits ADD COLUMN attempt_timestamps_json TEXT NOT NULL DEFAULT '[]'`); } catch { /* already exists */ }
|
|
1015
1021
|
|
|
1022
|
+
// Migration: re-add legacy columns for databases created during the brief window when
|
|
1023
|
+
// PR #6748 was live (columns were absent from CREATE TABLE). These columns are not read
|
|
1024
|
+
// by app logic but must exist so drizzle inserts don't fail.
|
|
1025
|
+
try { database.run(/*sql*/ `ALTER TABLE channel_guardian_rate_limits ADD COLUMN invalid_attempts INTEGER NOT NULL DEFAULT 0`); } catch { /* already exists */ }
|
|
1026
|
+
try { database.run(/*sql*/ `ALTER TABLE channel_guardian_rate_limits ADD COLUMN window_started_at INTEGER NOT NULL DEFAULT 0`); } catch { /* already exists */ }
|
|
1027
|
+
|
|
1016
1028
|
database.run(/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_channel_guardian_rate_limits_actor ON channel_guardian_rate_limits(assistant_id, channel, actor_external_user_id, actor_chat_id)`);
|
|
1017
1029
|
|
|
1018
1030
|
migrateMemoryFtsBackfill(database);
|
package/src/memory/schema.ts
CHANGED
|
@@ -646,6 +646,7 @@ export const channelGuardianApprovalRequests = sqliteTable('channel_guardian_app
|
|
|
646
646
|
id: text('id').primaryKey(),
|
|
647
647
|
runId: text('run_id').notNull(),
|
|
648
648
|
conversationId: text('conversation_id').notNull(),
|
|
649
|
+
assistantId: text('assistant_id').notNull().default('self'),
|
|
649
650
|
channel: text('channel').notNull(),
|
|
650
651
|
requesterExternalUserId: text('requester_external_user_id').notNull(),
|
|
651
652
|
requesterChatId: text('requester_chat_id').notNull(),
|
|
@@ -669,6 +670,10 @@ export const channelGuardianRateLimits = sqliteTable('channel_guardian_rate_limi
|
|
|
669
670
|
channel: text('channel').notNull(),
|
|
670
671
|
actorExternalUserId: text('actor_external_user_id').notNull(),
|
|
671
672
|
actorChatId: text('actor_chat_id').notNull(),
|
|
673
|
+
// Legacy columns kept with defaults for backward compatibility with upgraded databases
|
|
674
|
+
// that still have the old NOT NULL columns without DEFAULT. Not read by app logic.
|
|
675
|
+
invalidAttempts: integer('invalid_attempts').notNull().default(0),
|
|
676
|
+
windowStartedAt: integer('window_started_at').notNull().default(0),
|
|
672
677
|
attemptTimestampsJson: text('attempt_timestamps_json').notNull().default('[]'),
|
|
673
678
|
lockedUntil: integer('locked_until'),
|
|
674
679
|
createdAt: integer('created_at').notNull(),
|
|
@@ -154,13 +154,16 @@ const GATEWAY_SUBPATH_MAP: Record<string, string> = {
|
|
|
154
154
|
voice: 'voice-webhook',
|
|
155
155
|
status: 'status',
|
|
156
156
|
'connect-action': 'connect-action',
|
|
157
|
+
sms: 'sms',
|
|
157
158
|
};
|
|
158
159
|
|
|
159
160
|
/**
|
|
160
161
|
* Direct Twilio webhook subpaths that are blocked in gateway_only mode.
|
|
162
|
+
* Includes all public-facing webhook paths (voice, status, connect-action, SMS)
|
|
163
|
+
* because the runtime must never serve as a direct ingress for external webhooks.
|
|
161
164
|
* Internal forwarding endpoints (gateway→runtime) are unaffected.
|
|
162
165
|
*/
|
|
163
|
-
const GATEWAY_ONLY_BLOCKED_SUBPATHS = new Set(['voice-webhook', 'status', 'connect-action']);
|
|
166
|
+
const GATEWAY_ONLY_BLOCKED_SUBPATHS = new Set(['voice-webhook', 'status', 'connect-action', 'sms']);
|
|
164
167
|
|
|
165
168
|
/**
|
|
166
169
|
* Check if a request origin is from a private/internal network address.
|
|
@@ -616,7 +619,7 @@ export class RuntimeHttpServer {
|
|
|
616
619
|
const assistantId = match[1];
|
|
617
620
|
const endpoint = match[2];
|
|
618
621
|
log.warn({ endpoint, assistantId }, '[deprecated] /v1/assistants/:assistantId/... route used; migrate to /v1/...');
|
|
619
|
-
return this.dispatchEndpoint(endpoint, req, url);
|
|
622
|
+
return this.dispatchEndpoint(endpoint, req, url, assistantId);
|
|
620
623
|
}
|
|
621
624
|
|
|
622
625
|
/**
|
|
@@ -628,6 +631,7 @@ export class RuntimeHttpServer {
|
|
|
628
631
|
endpoint: string,
|
|
629
632
|
req: Request,
|
|
630
633
|
url: URL,
|
|
634
|
+
assistantId: string = 'self',
|
|
631
635
|
): Promise<Response> {
|
|
632
636
|
try {
|
|
633
637
|
if (endpoint === 'health' && req.method === 'GET') {
|
|
@@ -636,7 +640,9 @@ export class RuntimeHttpServer {
|
|
|
636
640
|
|
|
637
641
|
if (endpoint === 'conversations' && req.method === 'GET') {
|
|
638
642
|
const limit = Number(url.searchParams.get('limit') ?? 50);
|
|
639
|
-
const
|
|
643
|
+
const offset = Number(url.searchParams.get('offset') ?? 0);
|
|
644
|
+
const conversations = conversationStore.listConversations(limit, false, offset);
|
|
645
|
+
const totalCount = conversationStore.countConversations();
|
|
640
646
|
const bindings = externalConversationStore.getBindingsForConversations(
|
|
641
647
|
conversations.map((c) => c.id),
|
|
642
648
|
);
|
|
@@ -659,6 +665,7 @@ export class RuntimeHttpServer {
|
|
|
659
665
|
} : {}),
|
|
660
666
|
};
|
|
661
667
|
}),
|
|
668
|
+
hasMore: offset + conversations.length < totalCount,
|
|
662
669
|
});
|
|
663
670
|
}
|
|
664
671
|
|
|
@@ -732,11 +739,12 @@ export class RuntimeHttpServer {
|
|
|
732
739
|
}
|
|
733
740
|
|
|
734
741
|
if (endpoint === 'channels/conversation' && req.method === 'DELETE') {
|
|
735
|
-
return await handleDeleteConversation(req);
|
|
742
|
+
return await handleDeleteConversation(req, assistantId);
|
|
736
743
|
}
|
|
737
744
|
|
|
738
745
|
if (endpoint === 'channels/inbound' && req.method === 'POST') {
|
|
739
|
-
|
|
746
|
+
const gatewayOriginSecret = process.env.RUNTIME_GATEWAY_ORIGIN_SECRET || undefined;
|
|
747
|
+
return await handleChannelInbound(req, this.processMessage, this.bearerToken, this.runOrchestrator, assistantId, gatewayOriginSecret);
|
|
740
748
|
}
|
|
741
749
|
|
|
742
750
|
if (endpoint === 'channels/delivery-ack' && req.method === 'POST') {
|