@copilotkitnext/runtime 0.0.17-alpha.0 → 0.0.18

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,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "@copilotkitnext/runtime",
4
- version: "0.0.17-alpha.0",
4
+ version: "0.0.18",
5
5
  description: "Server-side runtime package for CopilotKit2",
6
6
  main: "dist/index.js",
7
7
  types: "dist/index.d.ts",
@@ -63,6 +63,7 @@ import {
63
63
  EventType,
64
64
  compactEvents
65
65
  } from "@ag-ui/client";
66
+ import { finalizeRunEvents } from "@copilotkitnext/shared";
66
67
  var InMemoryEventStore = class {
67
68
  constructor(threadId) {
68
69
  this.threadId = threadId;
@@ -71,12 +72,18 @@ var InMemoryEventStore = class {
71
72
  subject = null;
72
73
  /** True while a run is actively producing events. */
73
74
  isRunning = false;
74
- /** Lets stop() cancel the current producer. */
75
- abortController = new AbortController();
76
75
  /** Current run ID */
77
76
  currentRunId = null;
78
77
  /** Historic completed runs */
79
78
  historicRuns = [];
79
+ /** Currently running agent instance (if any). */
80
+ agent = null;
81
+ /** Subject returned from run() while the run is active. */
82
+ runSubject = null;
83
+ /** True once stop() has been requested but the run has not yet finalized. */
84
+ stopRequested = false;
85
+ /** Reference to the events emitted in the current run. */
86
+ currentEvents = null;
80
87
  };
81
88
  var GLOBAL_STORE = /* @__PURE__ */ new Map();
82
89
  var InMemoryAgentRunner = class extends AgentRunner {
@@ -92,8 +99,11 @@ var InMemoryAgentRunner = class extends AgentRunner {
92
99
  }
93
100
  store.isRunning = true;
94
101
  store.currentRunId = request.input.runId;
102
+ store.agent = request.agent;
103
+ store.stopRequested = false;
95
104
  const seenMessageIds = /* @__PURE__ */ new Set();
96
105
  const currentRunEvents = [];
106
+ store.currentEvents = currentRunEvents;
97
107
  const historicMessageIds = /* @__PURE__ */ new Set();
98
108
  for (const run of store.historicRuns) {
99
109
  for (const event of run.events) {
@@ -112,8 +122,8 @@ var InMemoryAgentRunner = class extends AgentRunner {
112
122
  const nextSubject = new ReplaySubject(Infinity);
113
123
  const prevSubject = store.subject;
114
124
  store.subject = nextSubject;
115
- store.abortController = new AbortController();
116
125
  const runSubject = new ReplaySubject(Infinity);
126
+ store.runSubject = runSubject;
117
127
  const runAgent = async () => {
118
128
  const lastRun = store.historicRuns[store.historicRuns.length - 1];
119
129
  const parentRunId = lastRun?.runId ?? null;
@@ -156,6 +166,13 @@ var InMemoryAgentRunner = class extends AgentRunner {
156
166
  }
157
167
  }
158
168
  });
169
+ const appendedEvents = finalizeRunEvents(currentRunEvents, {
170
+ stopRequested: store.stopRequested
171
+ });
172
+ for (const event of appendedEvents) {
173
+ runSubject.next(event);
174
+ nextSubject.next(event);
175
+ }
159
176
  if (store.currentRunId) {
160
177
  const compactedEvents = compactEvents(currentRunEvents);
161
178
  store.historicRuns.push({
@@ -166,11 +183,22 @@ var InMemoryAgentRunner = class extends AgentRunner {
166
183
  createdAt: Date.now()
167
184
  });
168
185
  }
169
- store.isRunning = false;
186
+ store.currentEvents = null;
170
187
  store.currentRunId = null;
188
+ store.agent = null;
189
+ store.runSubject = null;
190
+ store.stopRequested = false;
191
+ store.isRunning = false;
171
192
  runSubject.complete();
172
193
  nextSubject.complete();
173
194
  } catch {
195
+ const appendedEvents = finalizeRunEvents(currentRunEvents, {
196
+ stopRequested: store.stopRequested
197
+ });
198
+ for (const event of appendedEvents) {
199
+ runSubject.next(event);
200
+ nextSubject.next(event);
201
+ }
174
202
  if (store.currentRunId && currentRunEvents.length > 0) {
175
203
  const compactedEvents = compactEvents(currentRunEvents);
176
204
  store.historicRuns.push({
@@ -181,8 +209,12 @@ var InMemoryAgentRunner = class extends AgentRunner {
181
209
  createdAt: Date.now()
182
210
  });
183
211
  }
184
- store.isRunning = false;
212
+ store.currentEvents = null;
185
213
  store.currentRunId = null;
214
+ store.agent = null;
215
+ store.runSubject = null;
216
+ store.stopRequested = false;
217
+ store.isRunning = false;
186
218
  runSubject.complete();
187
219
  nextSubject.complete();
188
220
  }
@@ -217,7 +249,7 @@ var InMemoryAgentRunner = class extends AgentRunner {
217
249
  emittedMessageIds.add(event.messageId);
218
250
  }
219
251
  }
220
- if (store.subject && store.isRunning) {
252
+ if (store.subject && (store.isRunning || store.stopRequested)) {
221
253
  store.subject.subscribe({
222
254
  next: (event) => {
223
255
  if ("messageId" in event && typeof event.messageId === "string" && emittedMessageIds.has(event.messageId)) {
@@ -237,9 +269,31 @@ var InMemoryAgentRunner = class extends AgentRunner {
237
269
  const store = GLOBAL_STORE.get(request.threadId);
238
270
  return Promise.resolve(store?.isRunning ?? false);
239
271
  }
240
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
241
- stop(_request) {
242
- throw new Error("Method not implemented.");
272
+ stop(request) {
273
+ const store = GLOBAL_STORE.get(request.threadId);
274
+ if (!store || !store.isRunning) {
275
+ return Promise.resolve(false);
276
+ }
277
+ if (store.stopRequested) {
278
+ return Promise.resolve(false);
279
+ }
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);
287
+ }
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);
296
+ }
243
297
  }
244
298
  };
245
299
 
@@ -562,9 +616,6 @@ import { logger as logger2 } from "@copilotkitnext/shared";
562
616
 
563
617
  // src/middleware.ts
564
618
  import { logger } from "@copilotkitnext/shared";
565
- function isMiddlewareURL(value) {
566
- return typeof value === "string" && /^https?:\/\//.test(value);
567
- }
568
619
  async function callBeforeRequestMiddleware({
569
620
  runtime,
570
621
  request,
@@ -575,77 +626,6 @@ async function callBeforeRequestMiddleware({
575
626
  if (typeof mw === "function") {
576
627
  return mw({ runtime, request, path });
577
628
  }
578
- if (isMiddlewareURL(mw)) {
579
- const clone = request.clone();
580
- const url = new URL(request.url);
581
- const headersObj = {};
582
- clone.headers.forEach((v, k) => {
583
- headersObj[k] = v;
584
- });
585
- let bodyJson = void 0;
586
- try {
587
- bodyJson = await clone.json();
588
- } catch {
589
- }
590
- const payload = {
591
- method: request.method,
592
- path: url.pathname,
593
- query: url.search.startsWith("?") ? url.search.slice(1) : url.search,
594
- headers: headersObj,
595
- body: bodyJson
596
- };
597
- const ac = new AbortController();
598
- const to = setTimeout(() => ac.abort(), 2e3);
599
- let res;
600
- try {
601
- res = await fetch(mw, {
602
- method: "POST",
603
- headers: {
604
- "content-type": "application/json",
605
- "X-CopilotKit-Webhook-Stage": "before_request" /* BeforeRequest */
606
- },
607
- body: JSON.stringify(payload),
608
- signal: ac.signal
609
- });
610
- } catch {
611
- clearTimeout(to);
612
- throw new Response(void 0, { status: 502 });
613
- }
614
- clearTimeout(to);
615
- if (res.status >= 500) {
616
- throw new Response(void 0, { status: 502 });
617
- }
618
- if (res.status >= 400) {
619
- const errBody = await res.text();
620
- throw new Response(errBody || null, {
621
- status: res.status,
622
- headers: {
623
- "content-type": res.headers.get("content-type") || "application/json"
624
- }
625
- });
626
- }
627
- if (res.status === 204) return;
628
- let json;
629
- try {
630
- json = await res.json();
631
- } catch {
632
- return;
633
- }
634
- if (json && typeof json === "object") {
635
- const { headers, body } = json;
636
- const init = {
637
- method: request.method
638
- };
639
- if (headers) {
640
- init.headers = headers;
641
- }
642
- if (body !== void 0 && request.method !== "GET" && request.method !== "HEAD") {
643
- init.body = JSON.stringify(body);
644
- }
645
- return new Request(request.url, init);
646
- }
647
- return;
648
- }
649
629
  logger.warn({ mw }, "Unsupported beforeRequestMiddleware value \u2013 skipped");
650
630
  return;
651
631
  }
@@ -659,45 +639,6 @@ async function callAfterRequestMiddleware({
659
639
  if (typeof mw === "function") {
660
640
  return mw({ runtime, response, path });
661
641
  }
662
- if (isMiddlewareURL(mw)) {
663
- const clone = response.clone();
664
- const headersObj = {};
665
- clone.headers.forEach((v, k) => {
666
- headersObj[k] = v;
667
- });
668
- let body = "";
669
- try {
670
- body = await clone.text();
671
- } catch {
672
- }
673
- const payload = {
674
- status: clone.status,
675
- headers: headersObj,
676
- body
677
- };
678
- const ac = new AbortController();
679
- const to = setTimeout(() => ac.abort(), 2e3);
680
- let res;
681
- try {
682
- res = await fetch(mw, {
683
- method: "POST",
684
- headers: {
685
- "content-type": "application/json",
686
- "X-CopilotKit-Webhook-Stage": "after_request" /* AfterRequest */
687
- },
688
- body: JSON.stringify(payload),
689
- signal: ac.signal
690
- });
691
- } finally {
692
- clearTimeout(to);
693
- }
694
- if (!res.ok) {
695
- throw new Error(
696
- `after_request webhook ${mw} responded with ${res.status}`
697
- );
698
- }
699
- return;
700
- }
701
642
  logger.warn({ mw }, "Unsupported afterRequestMiddleware value \u2013 skipped");
702
643
  }
703
644
 
@@ -825,11 +766,72 @@ async function handleConnectAgent({
825
766
  }
826
767
  }
827
768
 
828
- // src/endpoint.ts
829
- function createCopilotEndpoint({
769
+ // src/handlers/handle-stop.ts
770
+ import { EventType as EventType2 } from "@ag-ui/client";
771
+ async function handleStopAgent({
830
772
  runtime,
831
- basePath
773
+ request,
774
+ agentId,
775
+ threadId
832
776
  }) {
777
+ try {
778
+ const agents = await runtime.agents;
779
+ if (!agents[agentId]) {
780
+ return new Response(
781
+ JSON.stringify({
782
+ error: "Agent not found",
783
+ message: `Agent '${agentId}' does not exist`
784
+ }),
785
+ {
786
+ status: 404,
787
+ headers: { "Content-Type": "application/json" }
788
+ }
789
+ );
790
+ }
791
+ const stopped = await runtime.runner.stop({ threadId });
792
+ if (!stopped) {
793
+ return new Response(
794
+ JSON.stringify({
795
+ stopped: false,
796
+ message: `No active run for thread '${threadId}'.`
797
+ }),
798
+ {
799
+ status: 200,
800
+ headers: { "Content-Type": "application/json" }
801
+ }
802
+ );
803
+ }
804
+ return new Response(
805
+ JSON.stringify({
806
+ stopped: true,
807
+ interrupt: {
808
+ type: EventType2.RUN_ERROR,
809
+ message: "Run stopped by user",
810
+ code: "STOPPED"
811
+ }
812
+ }),
813
+ {
814
+ status: 200,
815
+ headers: { "Content-Type": "application/json" }
816
+ }
817
+ );
818
+ } catch (error) {
819
+ console.error("Error stopping agent run:", error);
820
+ return new Response(
821
+ JSON.stringify({
822
+ error: "Failed to stop agent",
823
+ message: error instanceof Error ? error.message : "Unknown error"
824
+ }),
825
+ {
826
+ status: 500,
827
+ headers: { "Content-Type": "application/json" }
828
+ }
829
+ );
830
+ }
831
+ }
832
+
833
+ // src/endpoint.ts
834
+ function createCopilotEndpoint({ runtime, basePath }) {
833
835
  const app = new Hono();
834
836
  return app.basePath(basePath).use(
835
837
  "*",
@@ -851,10 +853,7 @@ function createCopilotEndpoint({
851
853
  c.set("modifiedRequest", maybeModifiedRequest);
852
854
  }
853
855
  } catch (error) {
854
- logger2.error(
855
- { err: error, url: request.url, path },
856
- "Error running before request middleware"
857
- );
856
+ logger2.error({ err: error, url: request.url, path }, "Error running before request middleware");
858
857
  if (error instanceof Response) {
859
858
  return error;
860
859
  }
@@ -870,10 +869,7 @@ function createCopilotEndpoint({
870
869
  response,
871
870
  path
872
871
  }).catch((error) => {
873
- logger2.error(
874
- { err: error, url: c.req.url, path },
875
- "Error running after request middleware"
876
- );
872
+ logger2.error({ err: error, url: c.req.url, path }, "Error running after request middleware");
877
873
  });
878
874
  }).post("/agent/:agentId/run", async (c) => {
879
875
  const agentId = c.req.param("agentId");
@@ -885,10 +881,7 @@ function createCopilotEndpoint({
885
881
  agentId
886
882
  });
887
883
  } catch (error) {
888
- logger2.error(
889
- { err: error, url: request.url, path: c.req.path },
890
- "Error running request handler"
891
- );
884
+ logger2.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
892
885
  throw error;
893
886
  }
894
887
  }).post("/agent/:agentId/connect", async (c) => {
@@ -901,10 +894,22 @@ function createCopilotEndpoint({
901
894
  agentId
902
895
  });
903
896
  } catch (error) {
904
- logger2.error(
905
- { err: error, url: request.url, path: c.req.path },
906
- "Error running request handler"
907
- );
897
+ logger2.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
898
+ throw error;
899
+ }
900
+ }).post("/agent/:agentId/stop/:threadId", async (c) => {
901
+ const agentId = c.req.param("agentId");
902
+ const threadId = c.req.param("threadId");
903
+ const request = c.get("modifiedRequest") || c.req.raw;
904
+ try {
905
+ return await handleStopAgent({
906
+ runtime,
907
+ request,
908
+ agentId,
909
+ threadId
910
+ });
911
+ } catch (error) {
912
+ logger2.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
908
913
  throw error;
909
914
  }
910
915
  }).get("/info", async (c) => {
@@ -915,10 +920,7 @@ function createCopilotEndpoint({
915
920
  request
916
921
  });
917
922
  } catch (error) {
918
- logger2.error(
919
- { err: error, url: request.url, path: c.req.path },
920
- "Error running request handler"
921
- );
923
+ logger2.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
922
924
  throw error;
923
925
  }
924
926
  }).post("/transcribe", async (c) => {
@@ -929,21 +931,22 @@ function createCopilotEndpoint({
929
931
  request
930
932
  });
931
933
  } catch (error) {
932
- logger2.error(
933
- { err: error, url: request.url, path: c.req.path },
934
- "Error running request handler"
935
- );
934
+ logger2.error({ err: error, url: request.url, path: c.req.path }, "Error running request handler");
936
935
  throw error;
937
936
  }
938
937
  }).notFound((c) => {
939
938
  return c.json({ error: "Not found" }, 404);
940
939
  });
941
940
  }
941
+
942
+ // src/runner/index.ts
943
+ import { finalizeRunEvents as finalizeRunEvents2 } from "@copilotkitnext/shared";
942
944
  export {
943
945
  AgentRunner,
944
946
  CopilotRuntime,
945
947
  InMemoryAgentRunner,
946
948
  VERSION,
947
- createCopilotEndpoint
949
+ createCopilotEndpoint,
950
+ finalizeRunEvents2 as finalizeRunEvents
948
951
  };
949
952
  //# sourceMappingURL=index.mjs.map