@copilotkitnext/runtime 0.0.19-threads-and-attachements.1 → 0.0.20
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/dist/index.d.mts +4 -247
- package/dist/index.d.ts +4 -247
- package/dist/index.js +120 -634
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +121 -629
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
// src/runtime.ts
|
|
2
|
-
import { logger } from "@copilotkitnext/shared";
|
|
3
|
-
|
|
4
1
|
// package.json
|
|
5
2
|
var package_default = {
|
|
6
3
|
name: "@copilotkitnext/runtime",
|
|
7
|
-
version: "0.0.
|
|
4
|
+
version: "0.0.20",
|
|
8
5
|
description: "Server-side runtime package for CopilotKit2",
|
|
9
6
|
main: "dist/index.js",
|
|
10
7
|
types: "dist/index.d.ts",
|
|
@@ -40,9 +37,9 @@ var package_default = {
|
|
|
40
37
|
vitest: "^3.0.5"
|
|
41
38
|
},
|
|
42
39
|
dependencies: {
|
|
43
|
-
"@ag-ui/client": "0.0.40-alpha.
|
|
44
|
-
"@ag-ui/core": "0.0.40-alpha.
|
|
45
|
-
"@ag-ui/encoder": "0.0.40-alpha.
|
|
40
|
+
"@ag-ui/client": "0.0.40-alpha.6",
|
|
41
|
+
"@ag-ui/core": "0.0.40-alpha.6",
|
|
42
|
+
"@ag-ui/encoder": "0.0.40-alpha.6",
|
|
46
43
|
"@copilotkitnext/shared": "workspace:*",
|
|
47
44
|
hono: "^4.6.13",
|
|
48
45
|
rxjs: "7.8.1"
|
|
@@ -68,10 +65,8 @@ import {
|
|
|
68
65
|
} from "@ag-ui/client";
|
|
69
66
|
import { finalizeRunEvents } from "@copilotkitnext/shared";
|
|
70
67
|
var InMemoryEventStore = class {
|
|
71
|
-
constructor(threadId
|
|
68
|
+
constructor(threadId) {
|
|
72
69
|
this.threadId = threadId;
|
|
73
|
-
this.resourceIds = resourceIds;
|
|
74
|
-
this.properties = properties;
|
|
75
70
|
}
|
|
76
71
|
/** The subject that current consumers subscribe to. */
|
|
77
72
|
subject = null;
|
|
@@ -91,41 +86,11 @@ var InMemoryEventStore = class {
|
|
|
91
86
|
currentEvents = null;
|
|
92
87
|
};
|
|
93
88
|
var GLOBAL_STORE = /* @__PURE__ */ new Map();
|
|
94
|
-
function matchesScope(store, scope) {
|
|
95
|
-
if (scope === void 0 || scope === null) {
|
|
96
|
-
return true;
|
|
97
|
-
}
|
|
98
|
-
const scopeIds = Array.isArray(scope.resourceId) ? scope.resourceId : [scope.resourceId];
|
|
99
|
-
return scopeIds.some((scopeId) => store.resourceIds.includes(scopeId));
|
|
100
|
-
}
|
|
101
89
|
var InMemoryAgentRunner = class extends AgentRunner {
|
|
102
90
|
run(request) {
|
|
103
91
|
let existingStore = GLOBAL_STORE.get(request.threadId);
|
|
104
|
-
if (!existingStore
|
|
105
|
-
|
|
106
|
-
"Cannot create thread with null scope. Admin users must specify an explicit resourceId for the thread owner."
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
let resourceIds;
|
|
110
|
-
if (request.scope === void 0) {
|
|
111
|
-
resourceIds = ["global"];
|
|
112
|
-
} else if (request.scope === null) {
|
|
113
|
-
resourceIds = [];
|
|
114
|
-
} else if (Array.isArray(request.scope.resourceId)) {
|
|
115
|
-
if (request.scope.resourceId.length === 0) {
|
|
116
|
-
throw new Error("Invalid scope: resourceId array cannot be empty");
|
|
117
|
-
}
|
|
118
|
-
resourceIds = request.scope.resourceId;
|
|
119
|
-
} else {
|
|
120
|
-
resourceIds = [request.scope.resourceId];
|
|
121
|
-
}
|
|
122
|
-
if (existingStore) {
|
|
123
|
-
if (request.scope !== null && !matchesScope(existingStore, request.scope)) {
|
|
124
|
-
throw new Error("Unauthorized: Cannot run on thread owned by different resource");
|
|
125
|
-
}
|
|
126
|
-
resourceIds = existingStore.resourceIds;
|
|
127
|
-
} else {
|
|
128
|
-
existingStore = new InMemoryEventStore(request.threadId, resourceIds, request.scope?.properties);
|
|
92
|
+
if (!existingStore) {
|
|
93
|
+
existingStore = new InMemoryEventStore(request.threadId);
|
|
129
94
|
GLOBAL_STORE.set(request.threadId, existingStore);
|
|
130
95
|
}
|
|
131
96
|
const store = existingStore;
|
|
@@ -169,7 +134,9 @@ var InMemoryAgentRunner = class extends AgentRunner {
|
|
|
169
134
|
if (event.type === EventType.RUN_STARTED) {
|
|
170
135
|
const runStartedEvent = event;
|
|
171
136
|
if (!runStartedEvent.input) {
|
|
172
|
-
const sanitizedMessages = request.input.messages ? request.input.messages.filter(
|
|
137
|
+
const sanitizedMessages = request.input.messages ? request.input.messages.filter(
|
|
138
|
+
(message) => !historicMessageIds.has(message.id)
|
|
139
|
+
) : void 0;
|
|
173
140
|
const updatedInput = {
|
|
174
141
|
...request.input,
|
|
175
142
|
...sanitizedMessages !== void 0 ? { messages: sanitizedMessages } : {}
|
|
@@ -266,7 +233,7 @@ var InMemoryAgentRunner = class extends AgentRunner {
|
|
|
266
233
|
connect(request) {
|
|
267
234
|
const store = GLOBAL_STORE.get(request.threadId);
|
|
268
235
|
const connectionSubject = new ReplaySubject(Infinity);
|
|
269
|
-
if (!store
|
|
236
|
+
if (!store) {
|
|
270
237
|
connectionSubject.complete();
|
|
271
238
|
return connectionSubject.asObservable();
|
|
272
239
|
}
|
|
@@ -302,256 +269,54 @@ var InMemoryAgentRunner = class extends AgentRunner {
|
|
|
302
269
|
const store = GLOBAL_STORE.get(request.threadId);
|
|
303
270
|
return Promise.resolve(store?.isRunning ?? false);
|
|
304
271
|
}
|
|
305
|
-
|
|
272
|
+
stop(request) {
|
|
306
273
|
const store = GLOBAL_STORE.get(request.threadId);
|
|
307
|
-
if (!store) {
|
|
308
|
-
return false;
|
|
309
|
-
}
|
|
310
|
-
if (store.isRunning) {
|
|
311
|
-
store.stopRequested = true;
|
|
312
|
-
store.isRunning = false;
|
|
313
|
-
const agent = store.agent;
|
|
314
|
-
try {
|
|
315
|
-
if (agent) {
|
|
316
|
-
agent.abortRun();
|
|
317
|
-
return true;
|
|
318
|
-
}
|
|
319
|
-
return false;
|
|
320
|
-
} catch (error) {
|
|
321
|
-
console.warn("Failed to abort in-memory runner:", error);
|
|
322
|
-
store.stopRequested = false;
|
|
323
|
-
store.isRunning = true;
|
|
324
|
-
return false;
|
|
325
|
-
}
|
|
274
|
+
if (!store || !store.isRunning) {
|
|
275
|
+
return Promise.resolve(false);
|
|
326
276
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
async listThreads(request) {
|
|
330
|
-
const limit = request.limit ?? 50;
|
|
331
|
-
const offset = request.offset ?? 0;
|
|
332
|
-
if (request.scope !== void 0 && request.scope !== null) {
|
|
333
|
-
const scopeIds = Array.isArray(request.scope.resourceId) ? request.scope.resourceId : [request.scope.resourceId];
|
|
334
|
-
if (scopeIds.length === 0) {
|
|
335
|
-
return { threads: [], total: 0 };
|
|
336
|
-
}
|
|
277
|
+
if (store.stopRequested) {
|
|
278
|
+
return Promise.resolve(false);
|
|
337
279
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
346
|
-
if (store.historicRuns.length === 0) {
|
|
347
|
-
continue;
|
|
348
|
-
}
|
|
349
|
-
const firstRun = store.historicRuns[0];
|
|
350
|
-
const lastRun = store.historicRuns[store.historicRuns.length - 1];
|
|
351
|
-
if (!firstRun || !lastRun) {
|
|
352
|
-
continue;
|
|
353
|
-
}
|
|
354
|
-
threadInfos.push({
|
|
355
|
-
threadId,
|
|
356
|
-
createdAt: firstRun.createdAt,
|
|
357
|
-
lastActivityAt: lastRun.createdAt,
|
|
358
|
-
store
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
threadInfos.sort((a, b) => b.lastActivityAt - a.lastActivityAt);
|
|
362
|
-
const total = threadInfos.length;
|
|
363
|
-
const paginatedInfos = threadInfos.slice(offset, offset + limit);
|
|
364
|
-
const threads = paginatedInfos.map((info) => {
|
|
365
|
-
let firstMessage;
|
|
366
|
-
const firstRun = info.store.historicRuns[0];
|
|
367
|
-
if (firstRun) {
|
|
368
|
-
const textContent = firstRun.events.find((e) => e.type === EventType.TEXT_MESSAGE_CONTENT);
|
|
369
|
-
if (textContent?.delta) {
|
|
370
|
-
firstMessage = textContent.delta.substring(0, 100);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
const messageIds = /* @__PURE__ */ new Set();
|
|
374
|
-
for (const run of info.store.historicRuns) {
|
|
375
|
-
for (const event of run.events) {
|
|
376
|
-
if ("messageId" in event && typeof event.messageId === "string") {
|
|
377
|
-
messageIds.add(event.messageId);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
return {
|
|
382
|
-
threadId: info.threadId,
|
|
383
|
-
createdAt: info.createdAt,
|
|
384
|
-
lastActivityAt: info.lastActivityAt,
|
|
385
|
-
isRunning: info.store.isRunning,
|
|
386
|
-
messageCount: messageIds.size,
|
|
387
|
-
firstMessage,
|
|
388
|
-
resourceId: info.store.resourceIds[0] || "unknown",
|
|
389
|
-
// Return first for backward compatibility
|
|
390
|
-
properties: info.store.properties
|
|
391
|
-
};
|
|
392
|
-
});
|
|
393
|
-
return { threads, total };
|
|
394
|
-
}
|
|
395
|
-
async getThreadMetadata(threadId, scope) {
|
|
396
|
-
const store = GLOBAL_STORE.get(threadId);
|
|
397
|
-
if (!store || !matchesScope(store, scope) || store.historicRuns.length === 0) {
|
|
398
|
-
return null;
|
|
399
|
-
}
|
|
400
|
-
const firstRun = store.historicRuns[0];
|
|
401
|
-
const lastRun = store.historicRuns[store.historicRuns.length - 1];
|
|
402
|
-
if (!firstRun || !lastRun) {
|
|
403
|
-
return null;
|
|
404
|
-
}
|
|
405
|
-
let firstMessage;
|
|
406
|
-
const textContent = firstRun.events.find((e) => e.type === EventType.TEXT_MESSAGE_CONTENT);
|
|
407
|
-
if (textContent?.delta) {
|
|
408
|
-
firstMessage = textContent.delta.substring(0, 100);
|
|
409
|
-
}
|
|
410
|
-
const messageIds = /* @__PURE__ */ new Set();
|
|
411
|
-
for (const run of store.historicRuns) {
|
|
412
|
-
for (const event of run.events) {
|
|
413
|
-
if ("messageId" in event && typeof event.messageId === "string") {
|
|
414
|
-
messageIds.add(event.messageId);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
return {
|
|
419
|
-
threadId,
|
|
420
|
-
createdAt: firstRun.createdAt,
|
|
421
|
-
lastActivityAt: lastRun.createdAt,
|
|
422
|
-
isRunning: store.isRunning,
|
|
423
|
-
messageCount: messageIds.size,
|
|
424
|
-
firstMessage,
|
|
425
|
-
resourceId: store.resourceIds[0] || "unknown",
|
|
426
|
-
// Return first for backward compatibility
|
|
427
|
-
properties: store.properties
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
async deleteThread(threadId, scope) {
|
|
431
|
-
const store = GLOBAL_STORE.get(threadId);
|
|
432
|
-
if (!store || !matchesScope(store, scope)) {
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
if (store.agent) {
|
|
436
|
-
try {
|
|
437
|
-
store.agent.abortRun();
|
|
438
|
-
} catch (error) {
|
|
439
|
-
console.warn("Failed to abort agent during thread deletion:", error);
|
|
440
|
-
}
|
|
280
|
+
store.stopRequested = true;
|
|
281
|
+
store.isRunning = false;
|
|
282
|
+
const agent = store.agent;
|
|
283
|
+
if (!agent) {
|
|
284
|
+
store.stopRequested = false;
|
|
285
|
+
store.isRunning = false;
|
|
286
|
+
return Promise.resolve(false);
|
|
441
287
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
for (const [threadId, store] of GLOBAL_STORE.entries()) {
|
|
451
|
-
if (store.agent) {
|
|
452
|
-
try {
|
|
453
|
-
store.agent.abortRun();
|
|
454
|
-
} catch (error) {
|
|
455
|
-
console.warn("Failed to abort agent during clearAllThreads:", error);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
store.subject?.complete();
|
|
459
|
-
GLOBAL_STORE.delete(threadId);
|
|
288
|
+
try {
|
|
289
|
+
agent.abortRun();
|
|
290
|
+
return Promise.resolve(true);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
console.error("Failed to abort agent run", error);
|
|
293
|
+
store.stopRequested = false;
|
|
294
|
+
store.isRunning = true;
|
|
295
|
+
return Promise.resolve(false);
|
|
460
296
|
}
|
|
461
297
|
}
|
|
462
298
|
};
|
|
463
299
|
|
|
464
300
|
// src/runtime.ts
|
|
465
301
|
var VERSION = package_default.version;
|
|
466
|
-
var CopilotRuntime = class
|
|
467
|
-
/**
|
|
468
|
-
* Built-in global scope for single-user apps or demos.
|
|
469
|
-
*
|
|
470
|
-
* All threads are globally accessible when using this scope.
|
|
471
|
-
*
|
|
472
|
-
* @example
|
|
473
|
-
* ```typescript
|
|
474
|
-
* new CopilotRuntime({
|
|
475
|
-
* agents: { myAgent },
|
|
476
|
-
* resolveThreadsScope: CopilotRuntime.GLOBAL_SCOPE,
|
|
477
|
-
* suppressResourceIdWarning: true
|
|
478
|
-
* });
|
|
479
|
-
* ```
|
|
480
|
-
*/
|
|
481
|
-
static GLOBAL_SCOPE = async (context) => ({
|
|
482
|
-
resourceId: "global"
|
|
483
|
-
});
|
|
484
|
-
/**
|
|
485
|
-
* Parses the client-declared resource ID(s) from the request header.
|
|
486
|
-
*
|
|
487
|
-
* This is a utility method used internally by handlers to extract the
|
|
488
|
-
* `X-CopilotKit-Resource-ID` header sent by the client via `CopilotKitProvider`.
|
|
489
|
-
*
|
|
490
|
-
* **You typically don't need to call this directly** - it's automatically called
|
|
491
|
-
* by the runtime handlers and passed to your `resolveThreadsScope` function as
|
|
492
|
-
* the `clientDeclared` parameter.
|
|
493
|
-
*
|
|
494
|
-
* @param request - The incoming HTTP request
|
|
495
|
-
* @returns The parsed resource ID(s), or undefined if header is missing
|
|
496
|
-
* - Returns a string if single ID
|
|
497
|
-
* - Returns an array if multiple comma-separated IDs
|
|
498
|
-
* - Returns undefined if header not present
|
|
499
|
-
*
|
|
500
|
-
* @example
|
|
501
|
-
* ```typescript
|
|
502
|
-
* // Automatically used internally:
|
|
503
|
-
* const clientDeclared = CopilotRuntime.parseClientDeclaredResourceId(request);
|
|
504
|
-
* const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
|
|
505
|
-
* ```
|
|
506
|
-
*/
|
|
507
|
-
static parseClientDeclaredResourceId(request) {
|
|
508
|
-
const header = request.headers.get("X-CopilotKit-Resource-ID");
|
|
509
|
-
if (!header) {
|
|
510
|
-
return void 0;
|
|
511
|
-
}
|
|
512
|
-
const values = header.split(",").map((v) => decodeURIComponent(v.trim()));
|
|
513
|
-
return values.length === 1 ? values[0] : values;
|
|
514
|
-
}
|
|
302
|
+
var CopilotRuntime = class {
|
|
515
303
|
agents;
|
|
516
304
|
transcriptionService;
|
|
517
305
|
beforeRequestMiddleware;
|
|
518
306
|
afterRequestMiddleware;
|
|
519
307
|
runner;
|
|
520
|
-
resolveThreadsScope;
|
|
521
|
-
suppressResourceIdWarning;
|
|
522
308
|
constructor({
|
|
523
309
|
agents,
|
|
524
310
|
transcriptionService,
|
|
525
311
|
beforeRequestMiddleware,
|
|
526
312
|
afterRequestMiddleware,
|
|
527
|
-
runner
|
|
528
|
-
resolveThreadsScope,
|
|
529
|
-
suppressResourceIdWarning = false
|
|
313
|
+
runner
|
|
530
314
|
}) {
|
|
531
315
|
this.agents = agents;
|
|
532
316
|
this.transcriptionService = transcriptionService;
|
|
533
317
|
this.beforeRequestMiddleware = beforeRequestMiddleware;
|
|
534
318
|
this.afterRequestMiddleware = afterRequestMiddleware;
|
|
535
319
|
this.runner = runner ?? new InMemoryAgentRunner();
|
|
536
|
-
this.resolveThreadsScope = resolveThreadsScope ?? _CopilotRuntime.GLOBAL_SCOPE;
|
|
537
|
-
this.suppressResourceIdWarning = suppressResourceIdWarning;
|
|
538
|
-
if (!resolveThreadsScope && !suppressResourceIdWarning) {
|
|
539
|
-
this.logGlobalScopeWarning();
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
logGlobalScopeWarning() {
|
|
543
|
-
const isProduction = process.env.NODE_ENV === "production";
|
|
544
|
-
if (isProduction) {
|
|
545
|
-
logger.error({
|
|
546
|
-
msg: "CopilotKit Security Warning: GLOBAL_SCOPE in production",
|
|
547
|
-
details: "No resolveThreadsScope configured. All threads are globally accessible to all users. Configure authentication for production: https://docs.copilotkit.ai/security/thread-scoping To suppress this warning (if intentional), set suppressResourceIdWarning: true"
|
|
548
|
-
});
|
|
549
|
-
} else {
|
|
550
|
-
logger.warn({
|
|
551
|
-
msg: "CopilotKit: Using GLOBAL_SCOPE",
|
|
552
|
-
details: "No resolveThreadsScope configured. All threads are globally accessible. This is fine for development, but add authentication for production: https://docs.copilotkit.ai/security/thread-scoping"
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
320
|
}
|
|
556
321
|
};
|
|
557
322
|
|
|
@@ -560,9 +325,15 @@ import { Hono } from "hono";
|
|
|
560
325
|
import { cors } from "hono/cors";
|
|
561
326
|
|
|
562
327
|
// src/handlers/handle-run.ts
|
|
563
|
-
import {
|
|
328
|
+
import {
|
|
329
|
+
RunAgentInputSchema
|
|
330
|
+
} from "@ag-ui/client";
|
|
564
331
|
import { EventEncoder } from "@ag-ui/encoder";
|
|
565
|
-
async function handleRunAgent({
|
|
332
|
+
async function handleRunAgent({
|
|
333
|
+
runtime,
|
|
334
|
+
request,
|
|
335
|
+
agentId
|
|
336
|
+
}) {
|
|
566
337
|
try {
|
|
567
338
|
const agents = await runtime.agents;
|
|
568
339
|
if (!agents[agentId]) {
|
|
@@ -599,23 +370,6 @@ async function handleRunAgent({ runtime, request, agentId }) {
|
|
|
599
370
|
const writer = stream.writable.getWriter();
|
|
600
371
|
const encoder = new EventEncoder();
|
|
601
372
|
let streamClosed = false;
|
|
602
|
-
let subscription;
|
|
603
|
-
let abortListener;
|
|
604
|
-
const cleanupAbortListener = () => {
|
|
605
|
-
if (abortListener) {
|
|
606
|
-
request.signal.removeEventListener("abort", abortListener);
|
|
607
|
-
abortListener = void 0;
|
|
608
|
-
}
|
|
609
|
-
};
|
|
610
|
-
const closeStream = async () => {
|
|
611
|
-
if (!streamClosed) {
|
|
612
|
-
try {
|
|
613
|
-
await writer.close();
|
|
614
|
-
} catch {
|
|
615
|
-
}
|
|
616
|
-
streamClosed = true;
|
|
617
|
-
}
|
|
618
|
-
};
|
|
619
373
|
(async () => {
|
|
620
374
|
let input;
|
|
621
375
|
try {
|
|
@@ -629,26 +383,13 @@ async function handleRunAgent({ runtime, request, agentId }) {
|
|
|
629
383
|
{ status: 400 }
|
|
630
384
|
);
|
|
631
385
|
}
|
|
632
|
-
const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
|
|
633
|
-
const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
|
|
634
|
-
if (scope === void 0) {
|
|
635
|
-
throw new Error("Unauthorized: No resource scope provided");
|
|
636
|
-
}
|
|
637
386
|
agent.setMessages(input.messages);
|
|
638
387
|
agent.setState(input.state);
|
|
639
388
|
agent.threadId = input.threadId;
|
|
640
|
-
|
|
641
|
-
try {
|
|
642
|
-
await runtime.runner.stop({ threadId: input.threadId });
|
|
643
|
-
} catch (stopError) {
|
|
644
|
-
console.error("Error stopping runner:", stopError);
|
|
645
|
-
}
|
|
646
|
-
};
|
|
647
|
-
subscription = runtime.runner.run({
|
|
389
|
+
runtime.runner.run({
|
|
648
390
|
threadId: input.threadId,
|
|
649
391
|
agent,
|
|
650
|
-
input
|
|
651
|
-
scope
|
|
392
|
+
input
|
|
652
393
|
}).subscribe({
|
|
653
394
|
next: async (event) => {
|
|
654
395
|
if (!request.signal.aborted && !streamClosed) {
|
|
@@ -663,39 +404,42 @@ async function handleRunAgent({ runtime, request, agentId }) {
|
|
|
663
404
|
},
|
|
664
405
|
error: async (error) => {
|
|
665
406
|
console.error("Error running agent:", error);
|
|
666
|
-
|
|
667
|
-
|
|
407
|
+
if (!streamClosed) {
|
|
408
|
+
try {
|
|
409
|
+
await writer.close();
|
|
410
|
+
streamClosed = true;
|
|
411
|
+
} catch {
|
|
412
|
+
}
|
|
413
|
+
}
|
|
668
414
|
},
|
|
669
415
|
complete: async () => {
|
|
670
|
-
|
|
671
|
-
|
|
416
|
+
if (!streamClosed) {
|
|
417
|
+
try {
|
|
418
|
+
await writer.close();
|
|
419
|
+
streamClosed = true;
|
|
420
|
+
} catch {
|
|
421
|
+
}
|
|
422
|
+
}
|
|
672
423
|
}
|
|
673
424
|
});
|
|
674
|
-
const handleAbort = () => {
|
|
675
|
-
subscription?.unsubscribe();
|
|
676
|
-
subscription = void 0;
|
|
677
|
-
cleanupAbortListener();
|
|
678
|
-
void stopRunner();
|
|
679
|
-
void closeStream();
|
|
680
|
-
};
|
|
681
|
-
if (request.signal.aborted) {
|
|
682
|
-
handleAbort();
|
|
683
|
-
} else {
|
|
684
|
-
abortListener = handleAbort;
|
|
685
|
-
request.signal.addEventListener("abort", abortListener);
|
|
686
|
-
}
|
|
687
425
|
})().catch((error) => {
|
|
688
426
|
console.error("Error running agent:", error);
|
|
689
|
-
console.error(
|
|
427
|
+
console.error(
|
|
428
|
+
"Error stack:",
|
|
429
|
+
error instanceof Error ? error.stack : "No stack trace"
|
|
430
|
+
);
|
|
690
431
|
console.error("Error details:", {
|
|
691
432
|
name: error instanceof Error ? error.name : "Unknown",
|
|
692
433
|
message: error instanceof Error ? error.message : String(error),
|
|
693
434
|
cause: error instanceof Error ? error.cause : void 0
|
|
694
435
|
});
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
436
|
+
if (!streamClosed) {
|
|
437
|
+
try {
|
|
438
|
+
writer.close();
|
|
439
|
+
streamClosed = true;
|
|
440
|
+
} catch {
|
|
441
|
+
}
|
|
442
|
+
}
|
|
699
443
|
});
|
|
700
444
|
return new Response(stream.readable, {
|
|
701
445
|
status: 200,
|
|
@@ -707,7 +451,10 @@ async function handleRunAgent({ runtime, request, agentId }) {
|
|
|
707
451
|
});
|
|
708
452
|
} catch (error) {
|
|
709
453
|
console.error("Error running agent:", error);
|
|
710
|
-
console.error(
|
|
454
|
+
console.error(
|
|
455
|
+
"Error stack:",
|
|
456
|
+
error instanceof Error ? error.stack : "No stack trace"
|
|
457
|
+
);
|
|
711
458
|
console.error("Error details:", {
|
|
712
459
|
name: error instanceof Error ? error.name : "Unknown",
|
|
713
460
|
message: error instanceof Error ? error.message : String(error),
|
|
@@ -865,10 +612,10 @@ async function handleTranscribe({
|
|
|
865
612
|
}
|
|
866
613
|
|
|
867
614
|
// src/endpoint.ts
|
|
868
|
-
import { logger as
|
|
615
|
+
import { logger as logger2 } from "@copilotkitnext/shared";
|
|
869
616
|
|
|
870
617
|
// src/middleware.ts
|
|
871
|
-
import { logger
|
|
618
|
+
import { logger } from "@copilotkitnext/shared";
|
|
872
619
|
async function callBeforeRequestMiddleware({
|
|
873
620
|
runtime,
|
|
874
621
|
request,
|
|
@@ -879,7 +626,7 @@ async function callBeforeRequestMiddleware({
|
|
|
879
626
|
if (typeof mw === "function") {
|
|
880
627
|
return mw({ runtime, request, path });
|
|
881
628
|
}
|
|
882
|
-
|
|
629
|
+
logger.warn({ mw }, "Unsupported beforeRequestMiddleware value \u2013 skipped");
|
|
883
630
|
return;
|
|
884
631
|
}
|
|
885
632
|
async function callAfterRequestMiddleware({
|
|
@@ -892,13 +639,17 @@ async function callAfterRequestMiddleware({
|
|
|
892
639
|
if (typeof mw === "function") {
|
|
893
640
|
return mw({ runtime, response, path });
|
|
894
641
|
}
|
|
895
|
-
|
|
642
|
+
logger.warn({ mw }, "Unsupported afterRequestMiddleware value \u2013 skipped");
|
|
896
643
|
}
|
|
897
644
|
|
|
898
645
|
// src/handlers/handle-connect.ts
|
|
899
646
|
import { RunAgentInputSchema as RunAgentInputSchema2 } from "@ag-ui/client";
|
|
900
647
|
import { EventEncoder as EventEncoder2 } from "@ag-ui/encoder";
|
|
901
|
-
async function handleConnectAgent({
|
|
648
|
+
async function handleConnectAgent({
|
|
649
|
+
runtime,
|
|
650
|
+
request,
|
|
651
|
+
agentId
|
|
652
|
+
}) {
|
|
902
653
|
try {
|
|
903
654
|
const agents = await runtime.agents;
|
|
904
655
|
if (!agents[agentId]) {
|
|
@@ -917,23 +668,6 @@ async function handleConnectAgent({ runtime, request, agentId }) {
|
|
|
917
668
|
const writer = stream.writable.getWriter();
|
|
918
669
|
const encoder = new EventEncoder2();
|
|
919
670
|
let streamClosed = false;
|
|
920
|
-
let subscription;
|
|
921
|
-
let abortListener;
|
|
922
|
-
const cleanupAbortListener = () => {
|
|
923
|
-
if (abortListener) {
|
|
924
|
-
request.signal.removeEventListener("abort", abortListener);
|
|
925
|
-
abortListener = void 0;
|
|
926
|
-
}
|
|
927
|
-
};
|
|
928
|
-
const closeStream = async () => {
|
|
929
|
-
if (!streamClosed) {
|
|
930
|
-
try {
|
|
931
|
-
await writer.close();
|
|
932
|
-
} catch {
|
|
933
|
-
}
|
|
934
|
-
streamClosed = true;
|
|
935
|
-
}
|
|
936
|
-
};
|
|
937
671
|
(async () => {
|
|
938
672
|
let input;
|
|
939
673
|
try {
|
|
@@ -947,14 +681,8 @@ async function handleConnectAgent({ runtime, request, agentId }) {
|
|
|
947
681
|
{ status: 400 }
|
|
948
682
|
);
|
|
949
683
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
if (scope === void 0) {
|
|
953
|
-
throw new Error("Unauthorized: No resource scope provided");
|
|
954
|
-
}
|
|
955
|
-
subscription = runtime.runner.connect({
|
|
956
|
-
threadId: input.threadId,
|
|
957
|
-
scope
|
|
684
|
+
runtime.runner.connect({
|
|
685
|
+
threadId: input.threadId
|
|
958
686
|
}).subscribe({
|
|
959
687
|
next: async (event) => {
|
|
960
688
|
if (!request.signal.aborted && !streamClosed) {
|
|
@@ -969,38 +697,42 @@ async function handleConnectAgent({ runtime, request, agentId }) {
|
|
|
969
697
|
},
|
|
970
698
|
error: async (error) => {
|
|
971
699
|
console.error("Error running agent:", error);
|
|
972
|
-
|
|
973
|
-
|
|
700
|
+
if (!streamClosed) {
|
|
701
|
+
try {
|
|
702
|
+
await writer.close();
|
|
703
|
+
streamClosed = true;
|
|
704
|
+
} catch {
|
|
705
|
+
}
|
|
706
|
+
}
|
|
974
707
|
},
|
|
975
708
|
complete: async () => {
|
|
976
|
-
|
|
977
|
-
|
|
709
|
+
if (!streamClosed) {
|
|
710
|
+
try {
|
|
711
|
+
await writer.close();
|
|
712
|
+
streamClosed = true;
|
|
713
|
+
} catch {
|
|
714
|
+
}
|
|
715
|
+
}
|
|
978
716
|
}
|
|
979
717
|
});
|
|
980
|
-
const handleAbort = () => {
|
|
981
|
-
subscription?.unsubscribe();
|
|
982
|
-
subscription = void 0;
|
|
983
|
-
cleanupAbortListener();
|
|
984
|
-
void closeStream();
|
|
985
|
-
};
|
|
986
|
-
if (request.signal.aborted) {
|
|
987
|
-
handleAbort();
|
|
988
|
-
} else {
|
|
989
|
-
abortListener = handleAbort;
|
|
990
|
-
request.signal.addEventListener("abort", abortListener);
|
|
991
|
-
}
|
|
992
718
|
})().catch((error) => {
|
|
993
719
|
console.error("Error running agent:", error);
|
|
994
|
-
console.error(
|
|
720
|
+
console.error(
|
|
721
|
+
"Error stack:",
|
|
722
|
+
error instanceof Error ? error.stack : "No stack trace"
|
|
723
|
+
);
|
|
995
724
|
console.error("Error details:", {
|
|
996
725
|
name: error instanceof Error ? error.name : "Unknown",
|
|
997
726
|
message: error instanceof Error ? error.message : String(error),
|
|
998
727
|
cause: error instanceof Error ? error.cause : void 0
|
|
999
728
|
});
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
729
|
+
if (!streamClosed) {
|
|
730
|
+
try {
|
|
731
|
+
writer.close();
|
|
732
|
+
streamClosed = true;
|
|
733
|
+
} catch {
|
|
734
|
+
}
|
|
735
|
+
}
|
|
1004
736
|
});
|
|
1005
737
|
return new Response(stream.readable, {
|
|
1006
738
|
status: 200,
|
|
@@ -1012,7 +744,10 @@ async function handleConnectAgent({ runtime, request, agentId }) {
|
|
|
1012
744
|
});
|
|
1013
745
|
} catch (error) {
|
|
1014
746
|
console.error("Error running agent:", error);
|
|
1015
|
-
console.error(
|
|
747
|
+
console.error(
|
|
748
|
+
"Error stack:",
|
|
749
|
+
error instanceof Error ? error.stack : "No stack trace"
|
|
750
|
+
);
|
|
1016
751
|
console.error("Error details:", {
|
|
1017
752
|
name: error instanceof Error ? error.name : "Unknown",
|
|
1018
753
|
message: error instanceof Error ? error.message : String(error),
|
|
@@ -1053,35 +788,7 @@ async function handleStopAgent({
|
|
|
1053
788
|
}
|
|
1054
789
|
);
|
|
1055
790
|
}
|
|
1056
|
-
const
|
|
1057
|
-
const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
|
|
1058
|
-
if (scope === void 0) {
|
|
1059
|
-
return new Response(
|
|
1060
|
-
JSON.stringify({
|
|
1061
|
-
error: "Unauthorized",
|
|
1062
|
-
message: "No resource scope provided"
|
|
1063
|
-
}),
|
|
1064
|
-
{
|
|
1065
|
-
status: 401,
|
|
1066
|
-
headers: { "Content-Type": "application/json" }
|
|
1067
|
-
}
|
|
1068
|
-
);
|
|
1069
|
-
}
|
|
1070
|
-
const runner = await runtime.runner;
|
|
1071
|
-
const metadata = await runner.getThreadMetadata(threadId, scope);
|
|
1072
|
-
if (!metadata) {
|
|
1073
|
-
return new Response(
|
|
1074
|
-
JSON.stringify({
|
|
1075
|
-
error: "Thread not found",
|
|
1076
|
-
message: `Thread '${threadId}' does not exist or you don't have access`
|
|
1077
|
-
}),
|
|
1078
|
-
{
|
|
1079
|
-
status: 404,
|
|
1080
|
-
headers: { "Content-Type": "application/json" }
|
|
1081
|
-
}
|
|
1082
|
-
);
|
|
1083
|
-
}
|
|
1084
|
-
const stopped = await runner.stop({ threadId });
|
|
791
|
+
const stopped = await runtime.runner.stop({ threadId });
|
|
1085
792
|
if (!stopped) {
|
|
1086
793
|
return new Response(
|
|
1087
794
|
JSON.stringify({
|
|
@@ -1123,141 +830,6 @@ async function handleStopAgent({
|
|
|
1123
830
|
}
|
|
1124
831
|
}
|
|
1125
832
|
|
|
1126
|
-
// src/handlers/handle-threads.ts
|
|
1127
|
-
async function handleListThreads({ runtime, request }) {
|
|
1128
|
-
try {
|
|
1129
|
-
const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
|
|
1130
|
-
const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
|
|
1131
|
-
if (scope === void 0) {
|
|
1132
|
-
return new Response(
|
|
1133
|
-
JSON.stringify({
|
|
1134
|
-
error: "Unauthorized",
|
|
1135
|
-
message: "No resource scope provided"
|
|
1136
|
-
}),
|
|
1137
|
-
{
|
|
1138
|
-
status: 401,
|
|
1139
|
-
headers: { "Content-Type": "application/json" }
|
|
1140
|
-
}
|
|
1141
|
-
);
|
|
1142
|
-
}
|
|
1143
|
-
const url = new URL(request.url);
|
|
1144
|
-
const limitParam = url.searchParams.get("limit");
|
|
1145
|
-
const offsetParam = url.searchParams.get("offset");
|
|
1146
|
-
const parsedLimit = limitParam ? Number.parseInt(limitParam, 10) : NaN;
|
|
1147
|
-
const parsedOffset = offsetParam ? Number.parseInt(offsetParam, 10) : NaN;
|
|
1148
|
-
const limit = Math.max(1, Math.min(100, Number.isNaN(parsedLimit) ? 20 : parsedLimit));
|
|
1149
|
-
const offset = Math.max(0, Number.isNaN(parsedOffset) ? 0 : parsedOffset);
|
|
1150
|
-
const runner = await runtime.runner;
|
|
1151
|
-
const result = await runner.listThreads({ scope, limit, offset });
|
|
1152
|
-
return new Response(JSON.stringify(result), {
|
|
1153
|
-
status: 200,
|
|
1154
|
-
headers: { "Content-Type": "application/json" }
|
|
1155
|
-
});
|
|
1156
|
-
} catch (error) {
|
|
1157
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
1158
|
-
return new Response(
|
|
1159
|
-
JSON.stringify({
|
|
1160
|
-
error: "Failed to list threads",
|
|
1161
|
-
message: errorMessage
|
|
1162
|
-
}),
|
|
1163
|
-
{
|
|
1164
|
-
status: 500,
|
|
1165
|
-
headers: { "Content-Type": "application/json" }
|
|
1166
|
-
}
|
|
1167
|
-
);
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
async function handleGetThread({ runtime, threadId, request }) {
|
|
1171
|
-
try {
|
|
1172
|
-
const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
|
|
1173
|
-
const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
|
|
1174
|
-
if (scope === void 0) {
|
|
1175
|
-
return new Response(
|
|
1176
|
-
JSON.stringify({
|
|
1177
|
-
error: "Unauthorized",
|
|
1178
|
-
message: "No resource scope provided"
|
|
1179
|
-
}),
|
|
1180
|
-
{
|
|
1181
|
-
status: 401,
|
|
1182
|
-
headers: { "Content-Type": "application/json" }
|
|
1183
|
-
}
|
|
1184
|
-
);
|
|
1185
|
-
}
|
|
1186
|
-
const runner = await runtime.runner;
|
|
1187
|
-
const metadata = await runner.getThreadMetadata(threadId, scope);
|
|
1188
|
-
if (!metadata) {
|
|
1189
|
-
return new Response(
|
|
1190
|
-
JSON.stringify({
|
|
1191
|
-
error: "Thread not found",
|
|
1192
|
-
message: `Thread '${threadId}' does not exist`
|
|
1193
|
-
}),
|
|
1194
|
-
{
|
|
1195
|
-
status: 404,
|
|
1196
|
-
headers: { "Content-Type": "application/json" }
|
|
1197
|
-
}
|
|
1198
|
-
);
|
|
1199
|
-
}
|
|
1200
|
-
return new Response(JSON.stringify(metadata), {
|
|
1201
|
-
status: 200,
|
|
1202
|
-
headers: { "Content-Type": "application/json" }
|
|
1203
|
-
});
|
|
1204
|
-
} catch (error) {
|
|
1205
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
1206
|
-
return new Response(
|
|
1207
|
-
JSON.stringify({
|
|
1208
|
-
error: "Failed to get thread",
|
|
1209
|
-
message: errorMessage
|
|
1210
|
-
}),
|
|
1211
|
-
{
|
|
1212
|
-
status: 500,
|
|
1213
|
-
headers: { "Content-Type": "application/json" }
|
|
1214
|
-
}
|
|
1215
|
-
);
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
async function handleDeleteThread({ runtime, threadId, request }) {
|
|
1219
|
-
if (!threadId) {
|
|
1220
|
-
return new Response(JSON.stringify({ error: "Thread ID required" }), {
|
|
1221
|
-
status: 400,
|
|
1222
|
-
headers: { "Content-Type": "application/json" }
|
|
1223
|
-
});
|
|
1224
|
-
}
|
|
1225
|
-
try {
|
|
1226
|
-
const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
|
|
1227
|
-
const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
|
|
1228
|
-
if (scope === void 0) {
|
|
1229
|
-
return new Response(
|
|
1230
|
-
JSON.stringify({
|
|
1231
|
-
error: "Unauthorized",
|
|
1232
|
-
message: "No resource scope provided"
|
|
1233
|
-
}),
|
|
1234
|
-
{
|
|
1235
|
-
status: 401,
|
|
1236
|
-
headers: { "Content-Type": "application/json" }
|
|
1237
|
-
}
|
|
1238
|
-
);
|
|
1239
|
-
}
|
|
1240
|
-
const runner = await runtime.runner;
|
|
1241
|
-
await runner.deleteThread(threadId, scope);
|
|
1242
|
-
return new Response(JSON.stringify({ success: true }), {
|
|
1243
|
-
status: 200,
|
|
1244
|
-
headers: { "Content-Type": "application/json" }
|
|
1245
|
-
});
|
|
1246
|
-
} catch (error) {
|
|
1247
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
1248
|
-
return new Response(
|
|
1249
|
-
JSON.stringify({
|
|
1250
|
-
error: "Failed to delete thread",
|
|
1251
|
-
message: errorMessage
|
|
1252
|
-
}),
|
|
1253
|
-
{
|
|
1254
|
-
status: 500,
|
|
1255
|
-
headers: { "Content-Type": "application/json" }
|
|
1256
|
-
}
|
|
1257
|
-
);
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
833
|
// src/endpoint.ts
|
|
1262
834
|
function createCopilotEndpoint({ runtime, basePath }) {
|
|
1263
835
|
const app = new Hono();
|
|
@@ -1281,7 +853,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
|
|
|
1281
853
|
c.set("modifiedRequest", maybeModifiedRequest);
|
|
1282
854
|
}
|
|
1283
855
|
} catch (error) {
|
|
1284
|
-
|
|
856
|
+
logger2.error({ err: error, url: request.url, path }, "Error running before request middleware");
|
|
1285
857
|
if (error instanceof Response) {
|
|
1286
858
|
return error;
|
|
1287
859
|
}
|
|
@@ -1297,7 +869,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
|
|
|
1297
869
|
response,
|
|
1298
870
|
path
|
|
1299
871
|
}).catch((error) => {
|
|
1300
|
-
|
|
872
|
+
logger2.error({ err: error, url: c.req.url, path }, "Error running after request middleware");
|
|
1301
873
|
});
|
|
1302
874
|
}).post("/agent/:agentId/run", async (c) => {
|
|
1303
875
|
const agentId = c.req.param("agentId");
|
|
@@ -1309,7 +881,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
|
|
|
1309
881
|
agentId
|
|
1310
882
|
});
|
|
1311
883
|
} catch (error) {
|
|
1312
|
-
|
|
884
|
+
logger2.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
|
|
1313
885
|
throw error;
|
|
1314
886
|
}
|
|
1315
887
|
}).post("/agent/:agentId/connect", async (c) => {
|
|
@@ -1322,7 +894,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
|
|
|
1322
894
|
agentId
|
|
1323
895
|
});
|
|
1324
896
|
} catch (error) {
|
|
1325
|
-
|
|
897
|
+
logger2.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
|
|
1326
898
|
throw error;
|
|
1327
899
|
}
|
|
1328
900
|
}).post("/agent/:agentId/stop/:threadId", async (c) => {
|
|
@@ -1337,7 +909,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
|
|
|
1337
909
|
threadId
|
|
1338
910
|
});
|
|
1339
911
|
} catch (error) {
|
|
1340
|
-
|
|
912
|
+
logger2.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
|
|
1341
913
|
throw error;
|
|
1342
914
|
}
|
|
1343
915
|
}).get("/info", async (c) => {
|
|
@@ -1348,7 +920,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
|
|
|
1348
920
|
request
|
|
1349
921
|
});
|
|
1350
922
|
} catch (error) {
|
|
1351
|
-
|
|
923
|
+
logger2.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
|
|
1352
924
|
throw error;
|
|
1353
925
|
}
|
|
1354
926
|
}).post("/transcribe", async (c) => {
|
|
@@ -1359,44 +931,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
|
|
|
1359
931
|
request
|
|
1360
932
|
});
|
|
1361
933
|
} catch (error) {
|
|
1362
|
-
|
|
1363
|
-
throw error;
|
|
1364
|
-
}
|
|
1365
|
-
}).get("/threads", async (c) => {
|
|
1366
|
-
const request = c.get("modifiedRequest") || c.req.raw;
|
|
1367
|
-
try {
|
|
1368
|
-
return await handleListThreads({
|
|
1369
|
-
runtime,
|
|
1370
|
-
request
|
|
1371
|
-
});
|
|
1372
|
-
} catch (error) {
|
|
1373
|
-
logger3.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
|
|
1374
|
-
throw error;
|
|
1375
|
-
}
|
|
1376
|
-
}).get("/threads/:threadId", async (c) => {
|
|
1377
|
-
const threadId = c.req.param("threadId");
|
|
1378
|
-
const request = c.get("modifiedRequest") || c.req.raw;
|
|
1379
|
-
try {
|
|
1380
|
-
return await handleGetThread({
|
|
1381
|
-
runtime,
|
|
1382
|
-
request,
|
|
1383
|
-
threadId
|
|
1384
|
-
});
|
|
1385
|
-
} catch (error) {
|
|
1386
|
-
logger3.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
|
|
1387
|
-
throw error;
|
|
1388
|
-
}
|
|
1389
|
-
}).delete("/threads/:threadId", async (c) => {
|
|
1390
|
-
const threadId = c.req.param("threadId");
|
|
1391
|
-
const request = c.get("modifiedRequest") || c.req.raw;
|
|
1392
|
-
try {
|
|
1393
|
-
return await handleDeleteThread({
|
|
1394
|
-
runtime,
|
|
1395
|
-
request,
|
|
1396
|
-
threadId
|
|
1397
|
-
});
|
|
1398
|
-
} catch (error) {
|
|
1399
|
-
logger3.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
|
|
934
|
+
logger2.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
|
|
1400
935
|
throw error;
|
|
1401
936
|
}
|
|
1402
937
|
}).notFound((c) => {
|
|
@@ -1406,55 +941,12 @@ function createCopilotEndpoint({ runtime, basePath }) {
|
|
|
1406
941
|
|
|
1407
942
|
// src/runner/index.ts
|
|
1408
943
|
import { finalizeRunEvents as finalizeRunEvents2 } from "@copilotkitnext/shared";
|
|
1409
|
-
|
|
1410
|
-
// src/resource-id-helpers.ts
|
|
1411
|
-
function validateResourceIdMatch(clientDeclared, serverAuthorized) {
|
|
1412
|
-
if (!clientDeclared) {
|
|
1413
|
-
return;
|
|
1414
|
-
}
|
|
1415
|
-
const clientIds = Array.isArray(clientDeclared) ? clientDeclared : [clientDeclared];
|
|
1416
|
-
const authorizedIds = Array.isArray(serverAuthorized) ? serverAuthorized : [serverAuthorized];
|
|
1417
|
-
const hasMatch = clientIds.some((clientId) => authorizedIds.includes(clientId));
|
|
1418
|
-
if (!hasMatch) {
|
|
1419
|
-
throw new Error("Unauthorized: Client-declared resourceId does not match authenticated user");
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
function filterAuthorizedResourceIds(clientDeclared, serverAuthorized) {
|
|
1423
|
-
const authorizedIds = Array.isArray(serverAuthorized) ? serverAuthorized : [serverAuthorized];
|
|
1424
|
-
if (!clientDeclared) {
|
|
1425
|
-
return serverAuthorized;
|
|
1426
|
-
}
|
|
1427
|
-
const clientIds = Array.isArray(clientDeclared) ? clientDeclared : [clientDeclared];
|
|
1428
|
-
const filtered = clientIds.filter((id) => authorizedIds.includes(id));
|
|
1429
|
-
if (filtered.length === 0) {
|
|
1430
|
-
throw new Error("Unauthorized: None of the client-declared resourceIds are authorized");
|
|
1431
|
-
}
|
|
1432
|
-
return Array.isArray(clientDeclared) ? filtered : filtered[0];
|
|
1433
|
-
}
|
|
1434
|
-
function createStrictThreadScopeResolver(getUserId) {
|
|
1435
|
-
return async ({ request, clientDeclared }) => {
|
|
1436
|
-
const userId = await getUserId(request);
|
|
1437
|
-
validateResourceIdMatch(clientDeclared, userId);
|
|
1438
|
-
return { resourceId: userId };
|
|
1439
|
-
};
|
|
1440
|
-
}
|
|
1441
|
-
function createFilteringThreadScopeResolver(getUserResourceIds) {
|
|
1442
|
-
return async ({ request, clientDeclared }) => {
|
|
1443
|
-
const userResourceIds = await getUserResourceIds(request);
|
|
1444
|
-
const resourceId = filterAuthorizedResourceIds(clientDeclared, userResourceIds);
|
|
1445
|
-
return { resourceId };
|
|
1446
|
-
};
|
|
1447
|
-
}
|
|
1448
944
|
export {
|
|
1449
945
|
AgentRunner,
|
|
1450
946
|
CopilotRuntime,
|
|
1451
947
|
InMemoryAgentRunner,
|
|
1452
948
|
VERSION,
|
|
1453
949
|
createCopilotEndpoint,
|
|
1454
|
-
|
|
1455
|
-
createStrictThreadScopeResolver,
|
|
1456
|
-
filterAuthorizedResourceIds,
|
|
1457
|
-
finalizeRunEvents2 as finalizeRunEvents,
|
|
1458
|
-
validateResourceIdMatch
|
|
950
|
+
finalizeRunEvents2 as finalizeRunEvents
|
|
1459
951
|
};
|
|
1460
952
|
//# sourceMappingURL=index.mjs.map
|