@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.js CHANGED
@@ -25,21 +25,14 @@ __export(index_exports, {
25
25
  InMemoryAgentRunner: () => InMemoryAgentRunner,
26
26
  VERSION: () => VERSION,
27
27
  createCopilotEndpoint: () => createCopilotEndpoint,
28
- createFilteringThreadScopeResolver: () => createFilteringThreadScopeResolver,
29
- createStrictThreadScopeResolver: () => createStrictThreadScopeResolver,
30
- filterAuthorizedResourceIds: () => filterAuthorizedResourceIds,
31
- finalizeRunEvents: () => import_shared5.finalizeRunEvents,
32
- validateResourceIdMatch: () => validateResourceIdMatch
28
+ finalizeRunEvents: () => import_shared4.finalizeRunEvents
33
29
  });
34
30
  module.exports = __toCommonJS(index_exports);
35
31
 
36
- // src/runtime.ts
37
- var import_shared2 = require("@copilotkitnext/shared");
38
-
39
32
  // package.json
40
33
  var package_default = {
41
34
  name: "@copilotkitnext/runtime",
42
- version: "0.0.19-threads-and-attachements.1",
35
+ version: "0.0.20",
43
36
  description: "Server-side runtime package for CopilotKit2",
44
37
  main: "dist/index.js",
45
38
  types: "dist/index.d.ts",
@@ -75,9 +68,9 @@ var package_default = {
75
68
  vitest: "^3.0.5"
76
69
  },
77
70
  dependencies: {
78
- "@ag-ui/client": "0.0.40-alpha.7",
79
- "@ag-ui/core": "0.0.40-alpha.7",
80
- "@ag-ui/encoder": "0.0.40-alpha.7",
71
+ "@ag-ui/client": "0.0.40-alpha.6",
72
+ "@ag-ui/core": "0.0.40-alpha.6",
73
+ "@ag-ui/encoder": "0.0.40-alpha.6",
81
74
  "@copilotkitnext/shared": "workspace:*",
82
75
  hono: "^4.6.13",
83
76
  rxjs: "7.8.1"
@@ -100,10 +93,8 @@ var import_rxjs = require("rxjs");
100
93
  var import_client = require("@ag-ui/client");
101
94
  var import_shared = require("@copilotkitnext/shared");
102
95
  var InMemoryEventStore = class {
103
- constructor(threadId, resourceIds, properties) {
96
+ constructor(threadId) {
104
97
  this.threadId = threadId;
105
- this.resourceIds = resourceIds;
106
- this.properties = properties;
107
98
  }
108
99
  /** The subject that current consumers subscribe to. */
109
100
  subject = null;
@@ -123,41 +114,11 @@ var InMemoryEventStore = class {
123
114
  currentEvents = null;
124
115
  };
125
116
  var GLOBAL_STORE = /* @__PURE__ */ new Map();
126
- function matchesScope(store, scope) {
127
- if (scope === void 0 || scope === null) {
128
- return true;
129
- }
130
- const scopeIds = Array.isArray(scope.resourceId) ? scope.resourceId : [scope.resourceId];
131
- return scopeIds.some((scopeId) => store.resourceIds.includes(scopeId));
132
- }
133
117
  var InMemoryAgentRunner = class extends AgentRunner {
134
118
  run(request) {
135
119
  let existingStore = GLOBAL_STORE.get(request.threadId);
136
- if (!existingStore && request.scope === null) {
137
- throw new Error(
138
- "Cannot create thread with null scope. Admin users must specify an explicit resourceId for the thread owner."
139
- );
140
- }
141
- let resourceIds;
142
- if (request.scope === void 0) {
143
- resourceIds = ["global"];
144
- } else if (request.scope === null) {
145
- resourceIds = [];
146
- } else if (Array.isArray(request.scope.resourceId)) {
147
- if (request.scope.resourceId.length === 0) {
148
- throw new Error("Invalid scope: resourceId array cannot be empty");
149
- }
150
- resourceIds = request.scope.resourceId;
151
- } else {
152
- resourceIds = [request.scope.resourceId];
153
- }
154
- if (existingStore) {
155
- if (request.scope !== null && !matchesScope(existingStore, request.scope)) {
156
- throw new Error("Unauthorized: Cannot run on thread owned by different resource");
157
- }
158
- resourceIds = existingStore.resourceIds;
159
- } else {
160
- existingStore = new InMemoryEventStore(request.threadId, resourceIds, request.scope?.properties);
120
+ if (!existingStore) {
121
+ existingStore = new InMemoryEventStore(request.threadId);
161
122
  GLOBAL_STORE.set(request.threadId, existingStore);
162
123
  }
163
124
  const store = existingStore;
@@ -201,7 +162,9 @@ var InMemoryAgentRunner = class extends AgentRunner {
201
162
  if (event.type === import_client.EventType.RUN_STARTED) {
202
163
  const runStartedEvent = event;
203
164
  if (!runStartedEvent.input) {
204
- const sanitizedMessages = request.input.messages ? request.input.messages.filter((message) => !historicMessageIds.has(message.id)) : void 0;
165
+ const sanitizedMessages = request.input.messages ? request.input.messages.filter(
166
+ (message) => !historicMessageIds.has(message.id)
167
+ ) : void 0;
205
168
  const updatedInput = {
206
169
  ...request.input,
207
170
  ...sanitizedMessages !== void 0 ? { messages: sanitizedMessages } : {}
@@ -298,7 +261,7 @@ var InMemoryAgentRunner = class extends AgentRunner {
298
261
  connect(request) {
299
262
  const store = GLOBAL_STORE.get(request.threadId);
300
263
  const connectionSubject = new import_rxjs.ReplaySubject(Infinity);
301
- if (!store || !matchesScope(store, request.scope)) {
264
+ if (!store) {
302
265
  connectionSubject.complete();
303
266
  return connectionSubject.asObservable();
304
267
  }
@@ -334,256 +297,54 @@ var InMemoryAgentRunner = class extends AgentRunner {
334
297
  const store = GLOBAL_STORE.get(request.threadId);
335
298
  return Promise.resolve(store?.isRunning ?? false);
336
299
  }
337
- async stop(request) {
300
+ stop(request) {
338
301
  const store = GLOBAL_STORE.get(request.threadId);
339
- if (!store) {
340
- return false;
341
- }
342
- if (store.isRunning) {
343
- store.stopRequested = true;
344
- store.isRunning = false;
345
- const agent = store.agent;
346
- try {
347
- if (agent) {
348
- agent.abortRun();
349
- return true;
350
- }
351
- return false;
352
- } catch (error) {
353
- console.warn("Failed to abort in-memory runner:", error);
354
- store.stopRequested = false;
355
- store.isRunning = true;
356
- return false;
357
- }
302
+ if (!store || !store.isRunning) {
303
+ return Promise.resolve(false);
358
304
  }
359
- return false;
360
- }
361
- async listThreads(request) {
362
- const limit = request.limit ?? 50;
363
- const offset = request.offset ?? 0;
364
- if (request.scope !== void 0 && request.scope !== null) {
365
- const scopeIds = Array.isArray(request.scope.resourceId) ? request.scope.resourceId : [request.scope.resourceId];
366
- if (scopeIds.length === 0) {
367
- return { threads: [], total: 0 };
368
- }
305
+ if (store.stopRequested) {
306
+ return Promise.resolve(false);
369
307
  }
370
- const threadInfos = [];
371
- for (const [threadId, store] of GLOBAL_STORE.entries()) {
372
- if (threadId.includes("-suggestions-")) {
373
- continue;
374
- }
375
- if (!matchesScope(store, request.scope)) {
376
- continue;
377
- }
378
- if (store.historicRuns.length === 0) {
379
- continue;
380
- }
381
- const firstRun = store.historicRuns[0];
382
- const lastRun = store.historicRuns[store.historicRuns.length - 1];
383
- if (!firstRun || !lastRun) {
384
- continue;
385
- }
386
- threadInfos.push({
387
- threadId,
388
- createdAt: firstRun.createdAt,
389
- lastActivityAt: lastRun.createdAt,
390
- store
391
- });
392
- }
393
- threadInfos.sort((a, b) => b.lastActivityAt - a.lastActivityAt);
394
- const total = threadInfos.length;
395
- const paginatedInfos = threadInfos.slice(offset, offset + limit);
396
- const threads = paginatedInfos.map((info) => {
397
- let firstMessage;
398
- const firstRun = info.store.historicRuns[0];
399
- if (firstRun) {
400
- const textContent = firstRun.events.find((e) => e.type === import_client.EventType.TEXT_MESSAGE_CONTENT);
401
- if (textContent?.delta) {
402
- firstMessage = textContent.delta.substring(0, 100);
403
- }
404
- }
405
- const messageIds = /* @__PURE__ */ new Set();
406
- for (const run of info.store.historicRuns) {
407
- for (const event of run.events) {
408
- if ("messageId" in event && typeof event.messageId === "string") {
409
- messageIds.add(event.messageId);
410
- }
411
- }
412
- }
413
- return {
414
- threadId: info.threadId,
415
- createdAt: info.createdAt,
416
- lastActivityAt: info.lastActivityAt,
417
- isRunning: info.store.isRunning,
418
- messageCount: messageIds.size,
419
- firstMessage,
420
- resourceId: info.store.resourceIds[0] || "unknown",
421
- // Return first for backward compatibility
422
- properties: info.store.properties
423
- };
424
- });
425
- return { threads, total };
426
- }
427
- async getThreadMetadata(threadId, scope) {
428
- const store = GLOBAL_STORE.get(threadId);
429
- if (!store || !matchesScope(store, scope) || store.historicRuns.length === 0) {
430
- return null;
431
- }
432
- const firstRun = store.historicRuns[0];
433
- const lastRun = store.historicRuns[store.historicRuns.length - 1];
434
- if (!firstRun || !lastRun) {
435
- return null;
436
- }
437
- let firstMessage;
438
- const textContent = firstRun.events.find((e) => e.type === import_client.EventType.TEXT_MESSAGE_CONTENT);
439
- if (textContent?.delta) {
440
- firstMessage = textContent.delta.substring(0, 100);
441
- }
442
- const messageIds = /* @__PURE__ */ new Set();
443
- for (const run of store.historicRuns) {
444
- for (const event of run.events) {
445
- if ("messageId" in event && typeof event.messageId === "string") {
446
- messageIds.add(event.messageId);
447
- }
448
- }
449
- }
450
- return {
451
- threadId,
452
- createdAt: firstRun.createdAt,
453
- lastActivityAt: lastRun.createdAt,
454
- isRunning: store.isRunning,
455
- messageCount: messageIds.size,
456
- firstMessage,
457
- resourceId: store.resourceIds[0] || "unknown",
458
- // Return first for backward compatibility
459
- properties: store.properties
460
- };
461
- }
462
- async deleteThread(threadId, scope) {
463
- const store = GLOBAL_STORE.get(threadId);
464
- if (!store || !matchesScope(store, scope)) {
465
- return;
466
- }
467
- if (store.agent) {
468
- try {
469
- store.agent.abortRun();
470
- } catch (error) {
471
- console.warn("Failed to abort agent during thread deletion:", error);
472
- }
308
+ store.stopRequested = true;
309
+ store.isRunning = false;
310
+ const agent = store.agent;
311
+ if (!agent) {
312
+ store.stopRequested = false;
313
+ store.isRunning = false;
314
+ return Promise.resolve(false);
473
315
  }
474
- store.subject?.complete();
475
- GLOBAL_STORE.delete(threadId);
476
- }
477
- /**
478
- * Clear all threads from the global store (for testing purposes only)
479
- * @internal
480
- */
481
- clearAllThreads() {
482
- for (const [threadId, store] of GLOBAL_STORE.entries()) {
483
- if (store.agent) {
484
- try {
485
- store.agent.abortRun();
486
- } catch (error) {
487
- console.warn("Failed to abort agent during clearAllThreads:", error);
488
- }
489
- }
490
- store.subject?.complete();
491
- GLOBAL_STORE.delete(threadId);
316
+ try {
317
+ agent.abortRun();
318
+ return Promise.resolve(true);
319
+ } catch (error) {
320
+ console.error("Failed to abort agent run", error);
321
+ store.stopRequested = false;
322
+ store.isRunning = true;
323
+ return Promise.resolve(false);
492
324
  }
493
325
  }
494
326
  };
495
327
 
496
328
  // src/runtime.ts
497
329
  var VERSION = package_default.version;
498
- var CopilotRuntime = class _CopilotRuntime {
499
- /**
500
- * Built-in global scope for single-user apps or demos.
501
- *
502
- * All threads are globally accessible when using this scope.
503
- *
504
- * @example
505
- * ```typescript
506
- * new CopilotRuntime({
507
- * agents: { myAgent },
508
- * resolveThreadsScope: CopilotRuntime.GLOBAL_SCOPE,
509
- * suppressResourceIdWarning: true
510
- * });
511
- * ```
512
- */
513
- static GLOBAL_SCOPE = async (context) => ({
514
- resourceId: "global"
515
- });
516
- /**
517
- * Parses the client-declared resource ID(s) from the request header.
518
- *
519
- * This is a utility method used internally by handlers to extract the
520
- * `X-CopilotKit-Resource-ID` header sent by the client via `CopilotKitProvider`.
521
- *
522
- * **You typically don't need to call this directly** - it's automatically called
523
- * by the runtime handlers and passed to your `resolveThreadsScope` function as
524
- * the `clientDeclared` parameter.
525
- *
526
- * @param request - The incoming HTTP request
527
- * @returns The parsed resource ID(s), or undefined if header is missing
528
- * - Returns a string if single ID
529
- * - Returns an array if multiple comma-separated IDs
530
- * - Returns undefined if header not present
531
- *
532
- * @example
533
- * ```typescript
534
- * // Automatically used internally:
535
- * const clientDeclared = CopilotRuntime.parseClientDeclaredResourceId(request);
536
- * const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
537
- * ```
538
- */
539
- static parseClientDeclaredResourceId(request) {
540
- const header = request.headers.get("X-CopilotKit-Resource-ID");
541
- if (!header) {
542
- return void 0;
543
- }
544
- const values = header.split(",").map((v) => decodeURIComponent(v.trim()));
545
- return values.length === 1 ? values[0] : values;
546
- }
330
+ var CopilotRuntime = class {
547
331
  agents;
548
332
  transcriptionService;
549
333
  beforeRequestMiddleware;
550
334
  afterRequestMiddleware;
551
335
  runner;
552
- resolveThreadsScope;
553
- suppressResourceIdWarning;
554
336
  constructor({
555
337
  agents,
556
338
  transcriptionService,
557
339
  beforeRequestMiddleware,
558
340
  afterRequestMiddleware,
559
- runner,
560
- resolveThreadsScope,
561
- suppressResourceIdWarning = false
341
+ runner
562
342
  }) {
563
343
  this.agents = agents;
564
344
  this.transcriptionService = transcriptionService;
565
345
  this.beforeRequestMiddleware = beforeRequestMiddleware;
566
346
  this.afterRequestMiddleware = afterRequestMiddleware;
567
347
  this.runner = runner ?? new InMemoryAgentRunner();
568
- this.resolveThreadsScope = resolveThreadsScope ?? _CopilotRuntime.GLOBAL_SCOPE;
569
- this.suppressResourceIdWarning = suppressResourceIdWarning;
570
- if (!resolveThreadsScope && !suppressResourceIdWarning) {
571
- this.logGlobalScopeWarning();
572
- }
573
- }
574
- logGlobalScopeWarning() {
575
- const isProduction = process.env.NODE_ENV === "production";
576
- if (isProduction) {
577
- import_shared2.logger.error({
578
- msg: "CopilotKit Security Warning: GLOBAL_SCOPE in production",
579
- 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"
580
- });
581
- } else {
582
- import_shared2.logger.warn({
583
- msg: "CopilotKit: Using GLOBAL_SCOPE",
584
- 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"
585
- });
586
- }
587
348
  }
588
349
  };
589
350
 
@@ -594,7 +355,11 @@ var import_cors = require("hono/cors");
594
355
  // src/handlers/handle-run.ts
595
356
  var import_client2 = require("@ag-ui/client");
596
357
  var import_encoder = require("@ag-ui/encoder");
597
- async function handleRunAgent({ runtime, request, agentId }) {
358
+ async function handleRunAgent({
359
+ runtime,
360
+ request,
361
+ agentId
362
+ }) {
598
363
  try {
599
364
  const agents = await runtime.agents;
600
365
  if (!agents[agentId]) {
@@ -631,23 +396,6 @@ async function handleRunAgent({ runtime, request, agentId }) {
631
396
  const writer = stream.writable.getWriter();
632
397
  const encoder = new import_encoder.EventEncoder();
633
398
  let streamClosed = false;
634
- let subscription;
635
- let abortListener;
636
- const cleanupAbortListener = () => {
637
- if (abortListener) {
638
- request.signal.removeEventListener("abort", abortListener);
639
- abortListener = void 0;
640
- }
641
- };
642
- const closeStream = async () => {
643
- if (!streamClosed) {
644
- try {
645
- await writer.close();
646
- } catch {
647
- }
648
- streamClosed = true;
649
- }
650
- };
651
399
  (async () => {
652
400
  let input;
653
401
  try {
@@ -661,26 +409,13 @@ async function handleRunAgent({ runtime, request, agentId }) {
661
409
  { status: 400 }
662
410
  );
663
411
  }
664
- const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
665
- const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
666
- if (scope === void 0) {
667
- throw new Error("Unauthorized: No resource scope provided");
668
- }
669
412
  agent.setMessages(input.messages);
670
413
  agent.setState(input.state);
671
414
  agent.threadId = input.threadId;
672
- const stopRunner = async () => {
673
- try {
674
- await runtime.runner.stop({ threadId: input.threadId });
675
- } catch (stopError) {
676
- console.error("Error stopping runner:", stopError);
677
- }
678
- };
679
- subscription = runtime.runner.run({
415
+ runtime.runner.run({
680
416
  threadId: input.threadId,
681
417
  agent,
682
- input,
683
- scope
418
+ input
684
419
  }).subscribe({
685
420
  next: async (event) => {
686
421
  if (!request.signal.aborted && !streamClosed) {
@@ -695,39 +430,42 @@ async function handleRunAgent({ runtime, request, agentId }) {
695
430
  },
696
431
  error: async (error) => {
697
432
  console.error("Error running agent:", error);
698
- cleanupAbortListener();
699
- await closeStream();
433
+ if (!streamClosed) {
434
+ try {
435
+ await writer.close();
436
+ streamClosed = true;
437
+ } catch {
438
+ }
439
+ }
700
440
  },
701
441
  complete: async () => {
702
- cleanupAbortListener();
703
- await closeStream();
442
+ if (!streamClosed) {
443
+ try {
444
+ await writer.close();
445
+ streamClosed = true;
446
+ } catch {
447
+ }
448
+ }
704
449
  }
705
450
  });
706
- const handleAbort = () => {
707
- subscription?.unsubscribe();
708
- subscription = void 0;
709
- cleanupAbortListener();
710
- void stopRunner();
711
- void closeStream();
712
- };
713
- if (request.signal.aborted) {
714
- handleAbort();
715
- } else {
716
- abortListener = handleAbort;
717
- request.signal.addEventListener("abort", abortListener);
718
- }
719
451
  })().catch((error) => {
720
452
  console.error("Error running agent:", error);
721
- console.error("Error stack:", error instanceof Error ? error.stack : "No stack trace");
453
+ console.error(
454
+ "Error stack:",
455
+ error instanceof Error ? error.stack : "No stack trace"
456
+ );
722
457
  console.error("Error details:", {
723
458
  name: error instanceof Error ? error.name : "Unknown",
724
459
  message: error instanceof Error ? error.message : String(error),
725
460
  cause: error instanceof Error ? error.cause : void 0
726
461
  });
727
- subscription?.unsubscribe();
728
- subscription = void 0;
729
- cleanupAbortListener();
730
- void closeStream();
462
+ if (!streamClosed) {
463
+ try {
464
+ writer.close();
465
+ streamClosed = true;
466
+ } catch {
467
+ }
468
+ }
731
469
  });
732
470
  return new Response(stream.readable, {
733
471
  status: 200,
@@ -739,7 +477,10 @@ async function handleRunAgent({ runtime, request, agentId }) {
739
477
  });
740
478
  } catch (error) {
741
479
  console.error("Error running agent:", error);
742
- console.error("Error stack:", error instanceof Error ? error.stack : "No stack trace");
480
+ console.error(
481
+ "Error stack:",
482
+ error instanceof Error ? error.stack : "No stack trace"
483
+ );
743
484
  console.error("Error details:", {
744
485
  name: error instanceof Error ? error.name : "Unknown",
745
486
  message: error instanceof Error ? error.message : String(error),
@@ -897,10 +638,10 @@ async function handleTranscribe({
897
638
  }
898
639
 
899
640
  // src/endpoint.ts
900
- var import_shared4 = require("@copilotkitnext/shared");
641
+ var import_shared3 = require("@copilotkitnext/shared");
901
642
 
902
643
  // src/middleware.ts
903
- var import_shared3 = require("@copilotkitnext/shared");
644
+ var import_shared2 = require("@copilotkitnext/shared");
904
645
  async function callBeforeRequestMiddleware({
905
646
  runtime,
906
647
  request,
@@ -911,7 +652,7 @@ async function callBeforeRequestMiddleware({
911
652
  if (typeof mw === "function") {
912
653
  return mw({ runtime, request, path });
913
654
  }
914
- import_shared3.logger.warn({ mw }, "Unsupported beforeRequestMiddleware value \u2013 skipped");
655
+ import_shared2.logger.warn({ mw }, "Unsupported beforeRequestMiddleware value \u2013 skipped");
915
656
  return;
916
657
  }
917
658
  async function callAfterRequestMiddleware({
@@ -924,13 +665,17 @@ async function callAfterRequestMiddleware({
924
665
  if (typeof mw === "function") {
925
666
  return mw({ runtime, response, path });
926
667
  }
927
- import_shared3.logger.warn({ mw }, "Unsupported afterRequestMiddleware value \u2013 skipped");
668
+ import_shared2.logger.warn({ mw }, "Unsupported afterRequestMiddleware value \u2013 skipped");
928
669
  }
929
670
 
930
671
  // src/handlers/handle-connect.ts
931
672
  var import_client3 = require("@ag-ui/client");
932
673
  var import_encoder2 = require("@ag-ui/encoder");
933
- async function handleConnectAgent({ runtime, request, agentId }) {
674
+ async function handleConnectAgent({
675
+ runtime,
676
+ request,
677
+ agentId
678
+ }) {
934
679
  try {
935
680
  const agents = await runtime.agents;
936
681
  if (!agents[agentId]) {
@@ -949,23 +694,6 @@ async function handleConnectAgent({ runtime, request, agentId }) {
949
694
  const writer = stream.writable.getWriter();
950
695
  const encoder = new import_encoder2.EventEncoder();
951
696
  let streamClosed = false;
952
- let subscription;
953
- let abortListener;
954
- const cleanupAbortListener = () => {
955
- if (abortListener) {
956
- request.signal.removeEventListener("abort", abortListener);
957
- abortListener = void 0;
958
- }
959
- };
960
- const closeStream = async () => {
961
- if (!streamClosed) {
962
- try {
963
- await writer.close();
964
- } catch {
965
- }
966
- streamClosed = true;
967
- }
968
- };
969
697
  (async () => {
970
698
  let input;
971
699
  try {
@@ -979,14 +707,8 @@ async function handleConnectAgent({ runtime, request, agentId }) {
979
707
  { status: 400 }
980
708
  );
981
709
  }
982
- const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
983
- const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
984
- if (scope === void 0) {
985
- throw new Error("Unauthorized: No resource scope provided");
986
- }
987
- subscription = runtime.runner.connect({
988
- threadId: input.threadId,
989
- scope
710
+ runtime.runner.connect({
711
+ threadId: input.threadId
990
712
  }).subscribe({
991
713
  next: async (event) => {
992
714
  if (!request.signal.aborted && !streamClosed) {
@@ -1001,38 +723,42 @@ async function handleConnectAgent({ runtime, request, agentId }) {
1001
723
  },
1002
724
  error: async (error) => {
1003
725
  console.error("Error running agent:", error);
1004
- cleanupAbortListener();
1005
- await closeStream();
726
+ if (!streamClosed) {
727
+ try {
728
+ await writer.close();
729
+ streamClosed = true;
730
+ } catch {
731
+ }
732
+ }
1006
733
  },
1007
734
  complete: async () => {
1008
- cleanupAbortListener();
1009
- await closeStream();
735
+ if (!streamClosed) {
736
+ try {
737
+ await writer.close();
738
+ streamClosed = true;
739
+ } catch {
740
+ }
741
+ }
1010
742
  }
1011
743
  });
1012
- const handleAbort = () => {
1013
- subscription?.unsubscribe();
1014
- subscription = void 0;
1015
- cleanupAbortListener();
1016
- void closeStream();
1017
- };
1018
- if (request.signal.aborted) {
1019
- handleAbort();
1020
- } else {
1021
- abortListener = handleAbort;
1022
- request.signal.addEventListener("abort", abortListener);
1023
- }
1024
744
  })().catch((error) => {
1025
745
  console.error("Error running agent:", error);
1026
- console.error("Error stack:", error instanceof Error ? error.stack : "No stack trace");
746
+ console.error(
747
+ "Error stack:",
748
+ error instanceof Error ? error.stack : "No stack trace"
749
+ );
1027
750
  console.error("Error details:", {
1028
751
  name: error instanceof Error ? error.name : "Unknown",
1029
752
  message: error instanceof Error ? error.message : String(error),
1030
753
  cause: error instanceof Error ? error.cause : void 0
1031
754
  });
1032
- subscription?.unsubscribe();
1033
- subscription = void 0;
1034
- cleanupAbortListener();
1035
- void closeStream();
755
+ if (!streamClosed) {
756
+ try {
757
+ writer.close();
758
+ streamClosed = true;
759
+ } catch {
760
+ }
761
+ }
1036
762
  });
1037
763
  return new Response(stream.readable, {
1038
764
  status: 200,
@@ -1044,7 +770,10 @@ async function handleConnectAgent({ runtime, request, agentId }) {
1044
770
  });
1045
771
  } catch (error) {
1046
772
  console.error("Error running agent:", error);
1047
- console.error("Error stack:", error instanceof Error ? error.stack : "No stack trace");
773
+ console.error(
774
+ "Error stack:",
775
+ error instanceof Error ? error.stack : "No stack trace"
776
+ );
1048
777
  console.error("Error details:", {
1049
778
  name: error instanceof Error ? error.name : "Unknown",
1050
779
  message: error instanceof Error ? error.message : String(error),
@@ -1085,35 +814,7 @@ async function handleStopAgent({
1085
814
  }
1086
815
  );
1087
816
  }
1088
- const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
1089
- const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
1090
- if (scope === void 0) {
1091
- return new Response(
1092
- JSON.stringify({
1093
- error: "Unauthorized",
1094
- message: "No resource scope provided"
1095
- }),
1096
- {
1097
- status: 401,
1098
- headers: { "Content-Type": "application/json" }
1099
- }
1100
- );
1101
- }
1102
- const runner = await runtime.runner;
1103
- const metadata = await runner.getThreadMetadata(threadId, scope);
1104
- if (!metadata) {
1105
- return new Response(
1106
- JSON.stringify({
1107
- error: "Thread not found",
1108
- message: `Thread '${threadId}' does not exist or you don't have access`
1109
- }),
1110
- {
1111
- status: 404,
1112
- headers: { "Content-Type": "application/json" }
1113
- }
1114
- );
1115
- }
1116
- const stopped = await runner.stop({ threadId });
817
+ const stopped = await runtime.runner.stop({ threadId });
1117
818
  if (!stopped) {
1118
819
  return new Response(
1119
820
  JSON.stringify({
@@ -1155,141 +856,6 @@ async function handleStopAgent({
1155
856
  }
1156
857
  }
1157
858
 
1158
- // src/handlers/handle-threads.ts
1159
- async function handleListThreads({ runtime, request }) {
1160
- try {
1161
- const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
1162
- const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
1163
- if (scope === void 0) {
1164
- return new Response(
1165
- JSON.stringify({
1166
- error: "Unauthorized",
1167
- message: "No resource scope provided"
1168
- }),
1169
- {
1170
- status: 401,
1171
- headers: { "Content-Type": "application/json" }
1172
- }
1173
- );
1174
- }
1175
- const url = new URL(request.url);
1176
- const limitParam = url.searchParams.get("limit");
1177
- const offsetParam = url.searchParams.get("offset");
1178
- const parsedLimit = limitParam ? Number.parseInt(limitParam, 10) : NaN;
1179
- const parsedOffset = offsetParam ? Number.parseInt(offsetParam, 10) : NaN;
1180
- const limit = Math.max(1, Math.min(100, Number.isNaN(parsedLimit) ? 20 : parsedLimit));
1181
- const offset = Math.max(0, Number.isNaN(parsedOffset) ? 0 : parsedOffset);
1182
- const runner = await runtime.runner;
1183
- const result = await runner.listThreads({ scope, limit, offset });
1184
- return new Response(JSON.stringify(result), {
1185
- status: 200,
1186
- headers: { "Content-Type": "application/json" }
1187
- });
1188
- } catch (error) {
1189
- const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
1190
- return new Response(
1191
- JSON.stringify({
1192
- error: "Failed to list threads",
1193
- message: errorMessage
1194
- }),
1195
- {
1196
- status: 500,
1197
- headers: { "Content-Type": "application/json" }
1198
- }
1199
- );
1200
- }
1201
- }
1202
- async function handleGetThread({ runtime, threadId, request }) {
1203
- try {
1204
- const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
1205
- const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
1206
- if (scope === void 0) {
1207
- return new Response(
1208
- JSON.stringify({
1209
- error: "Unauthorized",
1210
- message: "No resource scope provided"
1211
- }),
1212
- {
1213
- status: 401,
1214
- headers: { "Content-Type": "application/json" }
1215
- }
1216
- );
1217
- }
1218
- const runner = await runtime.runner;
1219
- const metadata = await runner.getThreadMetadata(threadId, scope);
1220
- if (!metadata) {
1221
- return new Response(
1222
- JSON.stringify({
1223
- error: "Thread not found",
1224
- message: `Thread '${threadId}' does not exist`
1225
- }),
1226
- {
1227
- status: 404,
1228
- headers: { "Content-Type": "application/json" }
1229
- }
1230
- );
1231
- }
1232
- return new Response(JSON.stringify(metadata), {
1233
- status: 200,
1234
- headers: { "Content-Type": "application/json" }
1235
- });
1236
- } catch (error) {
1237
- const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
1238
- return new Response(
1239
- JSON.stringify({
1240
- error: "Failed to get thread",
1241
- message: errorMessage
1242
- }),
1243
- {
1244
- status: 500,
1245
- headers: { "Content-Type": "application/json" }
1246
- }
1247
- );
1248
- }
1249
- }
1250
- async function handleDeleteThread({ runtime, threadId, request }) {
1251
- if (!threadId) {
1252
- return new Response(JSON.stringify({ error: "Thread ID required" }), {
1253
- status: 400,
1254
- headers: { "Content-Type": "application/json" }
1255
- });
1256
- }
1257
- try {
1258
- const clientDeclared = CopilotRuntime["parseClientDeclaredResourceId"](request);
1259
- const scope = await runtime.resolveThreadsScope({ request, clientDeclared });
1260
- if (scope === void 0) {
1261
- return new Response(
1262
- JSON.stringify({
1263
- error: "Unauthorized",
1264
- message: "No resource scope provided"
1265
- }),
1266
- {
1267
- status: 401,
1268
- headers: { "Content-Type": "application/json" }
1269
- }
1270
- );
1271
- }
1272
- const runner = await runtime.runner;
1273
- await runner.deleteThread(threadId, scope);
1274
- return new Response(JSON.stringify({ success: true }), {
1275
- status: 200,
1276
- headers: { "Content-Type": "application/json" }
1277
- });
1278
- } catch (error) {
1279
- const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
1280
- return new Response(
1281
- JSON.stringify({
1282
- error: "Failed to delete thread",
1283
- message: errorMessage
1284
- }),
1285
- {
1286
- status: 500,
1287
- headers: { "Content-Type": "application/json" }
1288
- }
1289
- );
1290
- }
1291
- }
1292
-
1293
859
  // src/endpoint.ts
1294
860
  function createCopilotEndpoint({ runtime, basePath }) {
1295
861
  const app = new import_hono.Hono();
@@ -1313,7 +879,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
1313
879
  c.set("modifiedRequest", maybeModifiedRequest);
1314
880
  }
1315
881
  } catch (error) {
1316
- import_shared4.logger.error({ err: error, url: request.url, path }, "Error running before request middleware");
882
+ import_shared3.logger.error({ err: error, url: request.url, path }, "Error running before request middleware");
1317
883
  if (error instanceof Response) {
1318
884
  return error;
1319
885
  }
@@ -1329,7 +895,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
1329
895
  response,
1330
896
  path
1331
897
  }).catch((error) => {
1332
- import_shared4.logger.error({ err: error, url: c.req.url, path }, "Error running after request middleware");
898
+ import_shared3.logger.error({ err: error, url: c.req.url, path }, "Error running after request middleware");
1333
899
  });
1334
900
  }).post("/agent/:agentId/run", async (c) => {
1335
901
  const agentId = c.req.param("agentId");
@@ -1341,7 +907,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
1341
907
  agentId
1342
908
  });
1343
909
  } catch (error) {
1344
- import_shared4.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
910
+ import_shared3.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
1345
911
  throw error;
1346
912
  }
1347
913
  }).post("/agent/:agentId/connect", async (c) => {
@@ -1354,7 +920,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
1354
920
  agentId
1355
921
  });
1356
922
  } catch (error) {
1357
- import_shared4.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
923
+ import_shared3.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
1358
924
  throw error;
1359
925
  }
1360
926
  }).post("/agent/:agentId/stop/:threadId", async (c) => {
@@ -1369,7 +935,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
1369
935
  threadId
1370
936
  });
1371
937
  } catch (error) {
1372
- import_shared4.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
938
+ import_shared3.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
1373
939
  throw error;
1374
940
  }
1375
941
  }).get("/info", async (c) => {
@@ -1380,7 +946,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
1380
946
  request
1381
947
  });
1382
948
  } catch (error) {
1383
- import_shared4.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
949
+ import_shared3.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
1384
950
  throw error;
1385
951
  }
1386
952
  }).post("/transcribe", async (c) => {
@@ -1391,44 +957,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
1391
957
  request
1392
958
  });
1393
959
  } catch (error) {
1394
- import_shared4.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
1395
- throw error;
1396
- }
1397
- }).get("/threads", async (c) => {
1398
- const request = c.get("modifiedRequest") || c.req.raw;
1399
- try {
1400
- return await handleListThreads({
1401
- runtime,
1402
- request
1403
- });
1404
- } catch (error) {
1405
- import_shared4.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
1406
- throw error;
1407
- }
1408
- }).get("/threads/:threadId", async (c) => {
1409
- const threadId = c.req.param("threadId");
1410
- const request = c.get("modifiedRequest") || c.req.raw;
1411
- try {
1412
- return await handleGetThread({
1413
- runtime,
1414
- request,
1415
- threadId
1416
- });
1417
- } catch (error) {
1418
- import_shared4.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
1419
- throw error;
1420
- }
1421
- }).delete("/threads/:threadId", async (c) => {
1422
- const threadId = c.req.param("threadId");
1423
- const request = c.get("modifiedRequest") || c.req.raw;
1424
- try {
1425
- return await handleDeleteThread({
1426
- runtime,
1427
- request,
1428
- threadId
1429
- });
1430
- } catch (error) {
1431
- import_shared4.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
960
+ import_shared3.logger.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
1432
961
  throw error;
1433
962
  }
1434
963
  }).notFound((c) => {
@@ -1437,46 +966,7 @@ function createCopilotEndpoint({ runtime, basePath }) {
1437
966
  }
1438
967
 
1439
968
  // src/runner/index.ts
1440
- var import_shared5 = require("@copilotkitnext/shared");
1441
-
1442
- // src/resource-id-helpers.ts
1443
- function validateResourceIdMatch(clientDeclared, serverAuthorized) {
1444
- if (!clientDeclared) {
1445
- return;
1446
- }
1447
- const clientIds = Array.isArray(clientDeclared) ? clientDeclared : [clientDeclared];
1448
- const authorizedIds = Array.isArray(serverAuthorized) ? serverAuthorized : [serverAuthorized];
1449
- const hasMatch = clientIds.some((clientId) => authorizedIds.includes(clientId));
1450
- if (!hasMatch) {
1451
- throw new Error("Unauthorized: Client-declared resourceId does not match authenticated user");
1452
- }
1453
- }
1454
- function filterAuthorizedResourceIds(clientDeclared, serverAuthorized) {
1455
- const authorizedIds = Array.isArray(serverAuthorized) ? serverAuthorized : [serverAuthorized];
1456
- if (!clientDeclared) {
1457
- return serverAuthorized;
1458
- }
1459
- const clientIds = Array.isArray(clientDeclared) ? clientDeclared : [clientDeclared];
1460
- const filtered = clientIds.filter((id) => authorizedIds.includes(id));
1461
- if (filtered.length === 0) {
1462
- throw new Error("Unauthorized: None of the client-declared resourceIds are authorized");
1463
- }
1464
- return Array.isArray(clientDeclared) ? filtered : filtered[0];
1465
- }
1466
- function createStrictThreadScopeResolver(getUserId) {
1467
- return async ({ request, clientDeclared }) => {
1468
- const userId = await getUserId(request);
1469
- validateResourceIdMatch(clientDeclared, userId);
1470
- return { resourceId: userId };
1471
- };
1472
- }
1473
- function createFilteringThreadScopeResolver(getUserResourceIds) {
1474
- return async ({ request, clientDeclared }) => {
1475
- const userResourceIds = await getUserResourceIds(request);
1476
- const resourceId = filterAuthorizedResourceIds(clientDeclared, userResourceIds);
1477
- return { resourceId };
1478
- };
1479
- }
969
+ var import_shared4 = require("@copilotkitnext/shared");
1480
970
  // Annotate the CommonJS export names for ESM import in node:
1481
971
  0 && (module.exports = {
1482
972
  AgentRunner,
@@ -1484,10 +974,6 @@ function createFilteringThreadScopeResolver(getUserResourceIds) {
1484
974
  InMemoryAgentRunner,
1485
975
  VERSION,
1486
976
  createCopilotEndpoint,
1487
- createFilteringThreadScopeResolver,
1488
- createStrictThreadScopeResolver,
1489
- filterAuthorizedResourceIds,
1490
- finalizeRunEvents,
1491
- validateResourceIdMatch
977
+ finalizeRunEvents
1492
978
  });
1493
979
  //# sourceMappingURL=index.js.map