@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.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.19-threads-and-attachements.1",
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.7",
44
- "@ag-ui/core": "0.0.40-alpha.7",
45
- "@ag-ui/encoder": "0.0.40-alpha.7",
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, resourceIds, properties) {
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 && request.scope === null) {
105
- throw new Error(
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((message) => !historicMessageIds.has(message.id)) : void 0;
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 || !matchesScope(store, request.scope)) {
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
- async stop(request) {
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
- return false;
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
- const threadInfos = [];
339
- for (const [threadId, store] of GLOBAL_STORE.entries()) {
340
- if (threadId.includes("-suggestions-")) {
341
- continue;
342
- }
343
- if (!matchesScope(store, request.scope)) {
344
- continue;
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
- store.subject?.complete();
443
- GLOBAL_STORE.delete(threadId);
444
- }
445
- /**
446
- * Clear all threads from the global store (for testing purposes only)
447
- * @internal
448
- */
449
- clearAllThreads() {
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 _CopilotRuntime {
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 { RunAgentInputSchema } from "@ag-ui/client";
328
+ import {
329
+ RunAgentInputSchema
330
+ } from "@ag-ui/client";
564
331
  import { EventEncoder } from "@ag-ui/encoder";
565
- async function handleRunAgent({ runtime, request, agentId }) {
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
- const stopRunner = async () => {
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
- cleanupAbortListener();
667
- await closeStream();
407
+ if (!streamClosed) {
408
+ try {
409
+ await writer.close();
410
+ streamClosed = true;
411
+ } catch {
412
+ }
413
+ }
668
414
  },
669
415
  complete: async () => {
670
- cleanupAbortListener();
671
- await closeStream();
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("Error stack:", error instanceof Error ? error.stack : "No stack trace");
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
- subscription?.unsubscribe();
696
- subscription = void 0;
697
- cleanupAbortListener();
698
- void closeStream();
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("Error stack:", error instanceof Error ? error.stack : "No stack trace");
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 logger3 } from "@copilotkitnext/shared";
615
+ import { logger as logger2 } from "@copilotkitnext/shared";
869
616
 
870
617
  // src/middleware.ts
871
- import { logger as logger2 } from "@copilotkitnext/shared";
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
- logger2.warn({ mw }, "Unsupported beforeRequestMiddleware value \u2013 skipped");
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
- logger2.warn({ mw }, "Unsupported afterRequestMiddleware value \u2013 skipped");
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({ runtime, request, agentId }) {
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
- const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
951
- const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
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
- cleanupAbortListener();
973
- await closeStream();
700
+ if (!streamClosed) {
701
+ try {
702
+ await writer.close();
703
+ streamClosed = true;
704
+ } catch {
705
+ }
706
+ }
974
707
  },
975
708
  complete: async () => {
976
- cleanupAbortListener();
977
- await closeStream();
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("Error stack:", error instanceof Error ? error.stack : "No stack trace");
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
- subscription?.unsubscribe();
1001
- subscription = void 0;
1002
- cleanupAbortListener();
1003
- void closeStream();
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("Error stack:", error instanceof Error ? error.stack : "No stack trace");
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 clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
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
- logger3.error({ err: error, url: request.url, path }, "Error running before request middleware");
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
- logger3.error({ err: error, url: c.req.url, path }, "Error running after request middleware");
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
- logger3.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
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
- logger3.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
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
- logger3.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
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
- logger3.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
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
- logger3.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
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
- createFilteringThreadScopeResolver,
1455
- createStrictThreadScopeResolver,
1456
- filterAuthorizedResourceIds,
1457
- finalizeRunEvents2 as finalizeRunEvents,
1458
- validateResourceIdMatch
950
+ finalizeRunEvents2 as finalizeRunEvents
1459
951
  };
1460
952
  //# sourceMappingURL=index.mjs.map