@copilotkitnext/core 1.54.0 → 1.54.1-next.0

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.umd.js CHANGED
@@ -1,10 +1,128 @@
1
1
  (function(global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@ag-ui/client'), require('@copilotkitnext/shared'), require('rxjs'), require('rxjs/operators'), require('zod-to-json-schema'), require('phoenix')) :
3
- typeof define === 'function' && define.amd ? define(['exports', '@ag-ui/client', '@copilotkitnext/shared', 'rxjs', 'rxjs/operators', 'zod-to-json-schema', 'phoenix'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitNextCore = {}), global.AgUIClient,global.CopilotKitNextShared,global.rxjs,global.rxjs.operators,global.zodToJsonSchema,global.phoenix));
5
- })(this, function(exports, _ag_ui_client, _copilotkitnext_shared, rxjs, rxjs_operators, zod_to_json_schema, phoenix) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@ag-ui/client'), require('@copilotkitnext/shared'), require('rxjs'), require('rxjs/operators'), require('phoenix'), require('zod-to-json-schema'), require('rxjs/fetch')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@ag-ui/client', '@copilotkitnext/shared', 'rxjs', 'rxjs/operators', 'phoenix', 'zod-to-json-schema', 'rxjs/fetch'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitNextCore = {}), global.AgUIClient,global.CopilotKitNextShared,global.rxjs,global.rxjs.operators,global.phoenix,global.zodToJsonSchema,global.rxjs_fetch));
5
+ })(this, function(exports, _ag_ui_client, _copilotkitnext_shared, rxjs, rxjs_operators, phoenix, zod_to_json_schema, rxjs_fetch) {
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
7
7
 
8
+ //#region src/utils/phoenix-observable.ts
9
+ /**
10
+ * Adapt Phoenix socket open/error callbacks into an observable signal stream.
11
+ *
12
+ * The returned observable is shared and replayable by the caller when needed,
13
+ * but this helper itself does not own socket connection teardown.
14
+ */
15
+ function ɵcreatePhoenixSocketSignals$(socket) {
16
+ return new rxjs.Observable((observer) => {
17
+ socket.onOpen(() => observer.next({ type: "open" }));
18
+ socket.onError((error) => observer.next({
19
+ type: "error",
20
+ error
21
+ }));
22
+ });
23
+ }
24
+ /**
25
+ * Adapt a Phoenix channel join attempt into a single-outcome observable.
26
+ */
27
+ function ɵcreatePhoenixJoinOutcome$(channel) {
28
+ return new rxjs.Observable((observer) => {
29
+ channel.join().receive("ok", () => {
30
+ observer.next({ type: "joined" });
31
+ observer.complete();
32
+ }).receive("error", (response) => {
33
+ observer.next({
34
+ type: "error",
35
+ response
36
+ });
37
+ observer.complete();
38
+ }).receive("timeout", () => {
39
+ observer.next({ type: "timeout" });
40
+ observer.complete();
41
+ });
42
+ });
43
+ }
44
+ /**
45
+ * Create a cold Phoenix socket session.
46
+ *
47
+ * The socket is constructed and connected on subscription, and disconnected on
48
+ * teardown. Each subscription creates an isolated socket instance.
49
+ */
50
+ function ɵphoenixSocket$(options) {
51
+ return (0, rxjs.defer)(() => {
52
+ const socket = new phoenix.Socket(options.url, options.options);
53
+ const signals$ = ɵcreatePhoenixSocketSignals$(socket).pipe((0, rxjs_operators.shareReplay)({
54
+ bufferSize: 1,
55
+ refCount: true
56
+ }));
57
+ socket.connect();
58
+ return (0, rxjs.concat)((0, rxjs.of)({
59
+ socket,
60
+ signals$
61
+ }), rxjs.NEVER).pipe((0, rxjs_operators.finalize)(() => socket.disconnect()));
62
+ });
63
+ }
64
+ /**
65
+ * Create a cold Phoenix channel session from a socket session stream.
66
+ *
67
+ * A channel is created and joined for each active socket session. If the
68
+ * upstream socket session changes, the previous channel is left before the
69
+ * next one becomes active.
70
+ */
71
+ function ɵphoenixChannel$(options) {
72
+ return options.socket$.pipe((0, rxjs_operators.switchMap)(({ socket }) => (0, rxjs.defer)(() => {
73
+ const channel = socket.channel(options.topic, options.params);
74
+ return (0, rxjs.concat)((0, rxjs.of)({
75
+ channel,
76
+ joinOutcome$: ɵcreatePhoenixJoinOutcome$(channel).pipe((0, rxjs_operators.shareReplay)({
77
+ bufferSize: 1,
78
+ refCount: true
79
+ }))
80
+ }), rxjs.NEVER).pipe((0, rxjs_operators.finalize)(() => {
81
+ if (options.leaveOnUnsubscribe !== false) channel.leave();
82
+ }));
83
+ })));
84
+ }
85
+ /**
86
+ * Observe a named Phoenix channel event as an observable payload stream.
87
+ */
88
+ function ɵobservePhoenixEvent$(channel, eventName) {
89
+ return new rxjs.Observable((observer) => {
90
+ const ref = channel.on(eventName, (payload) => observer.next(payload));
91
+ return () => {
92
+ channel.off(eventName, ref);
93
+ };
94
+ });
95
+ }
96
+ /**
97
+ * Flatten channel sessions into their join-outcome stream.
98
+ */
99
+ function ɵobservePhoenixJoinOutcome$(channel$) {
100
+ return channel$.pipe((0, rxjs_operators.switchMap)((session) => session.joinOutcome$));
101
+ }
102
+ /**
103
+ * Complete when a channel joins successfully, or error if the join fails.
104
+ */
105
+ function ɵjoinPhoenixChannel$(channel$) {
106
+ return ɵobservePhoenixJoinOutcome$(channel$).pipe((0, rxjs_operators.take)(1), (0, rxjs_operators.mergeMap)((outcome) => {
107
+ if (outcome.type === "joined") return rxjs.EMPTY;
108
+ throw outcome.type === "timeout" ? /* @__PURE__ */ new Error("Timed out joining channel") : /* @__PURE__ */ new Error(`Failed to join channel: ${JSON.stringify(outcome.response)}`);
109
+ }));
110
+ }
111
+ /**
112
+ * Flatten socket sessions into their lifecycle signal stream.
113
+ */
114
+ function ɵobservePhoenixSocketSignals$(socket$) {
115
+ return socket$.pipe((0, rxjs_operators.switchMap)((session) => session.signals$));
116
+ }
117
+ /**
118
+ * Error after a socket emits the configured number of consecutive error
119
+ * signals, resetting the counter after each successful open signal.
120
+ */
121
+ function ɵobservePhoenixSocketHealth$(socketSignals$, maxConsecutiveErrors) {
122
+ return socketSignals$.pipe((0, rxjs_operators.scan)((consecutiveErrors, signal) => signal.type === "open" ? 0 : consecutiveErrors + 1, 0), (0, rxjs_operators.filter)((consecutiveErrors) => consecutiveErrors >= maxConsecutiveErrors), (0, rxjs_operators.take)(1), (0, rxjs_operators.mergeMap)((consecutiveErrors) => (0, rxjs.throwError)(() => /* @__PURE__ */ new Error(`WebSocket connection failed after ${consecutiveErrors} consecutive errors`))));
123
+ }
124
+
125
+ //#endregion
8
126
  //#region \0@oxc-project+runtime@0.112.0/helpers/typeof.js
9
127
  function _typeof(o) {
10
128
  "@babel/helpers - typeof";
@@ -46,28 +164,445 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
46
164
  }) : e[r] = t, e;
47
165
  }
48
166
 
167
+ //#endregion
168
+ //#region src/intelligence-agent.ts
169
+ const CLIENT_AG_UI_EVENT = "ag_ui_event";
170
+ const STOP_RUN_EVENT = "stop_run";
171
+ var IntelligenceAgent = class IntelligenceAgent extends _ag_ui_client.AbstractAgent {
172
+ constructor(config, sharedState = { lastSeenEventIds: /* @__PURE__ */ new Map() }) {
173
+ super();
174
+ _defineProperty(this, "config", void 0);
175
+ _defineProperty(this, "socket", null);
176
+ _defineProperty(this, "activeChannel", null);
177
+ _defineProperty(this, "runId", null);
178
+ _defineProperty(this, "sharedState", void 0);
179
+ this.config = config;
180
+ this.sharedState = sharedState;
181
+ }
182
+ clone() {
183
+ return new IntelligenceAgent(this.config, this.sharedState);
184
+ }
185
+ /**
186
+ * Override of AbstractAgent.connectAgent that removes the `verifyEvents` step.
187
+ *
188
+ * Background: AbstractAgent's connectAgent pipeline runs events through
189
+ * `verifyEvents`, which validates that the stream follows the AG-UI protocol
190
+ * lifecycle — specifically, it expects a RUN_STARTED event before any content
191
+ * events and a RUN_FINISHED/RUN_ERROR event to complete the stream.
192
+ *
193
+ * IntelligenceAgent uses long-lived WebSocket connections rather than
194
+ * request-scoped SSE streams. When connecting to replay historical messages
195
+ * for an existing thread, the connection semantics don't map to a single
196
+ * agent run start/stop cycle. The replayed events may not include
197
+ * RUN_STARTED/RUN_FINISHED bookends (or may contain events from multiple
198
+ * past runs), which causes verifyEvents to either never complete or to
199
+ * error out.
200
+ *
201
+ * This override replicates the base connectAgent implementation exactly,
202
+ * substituting only `transformChunks` (which is still needed for message
203
+ * reassembly) and omitting `verifyEvents`.
204
+ *
205
+ * TODO: Remove this override once AG-UI's AbstractAgent supports opting out
206
+ * of verifyEvents for transports with different connection life-cycles.
207
+ */
208
+ async connectAgent(parameters, subscriber) {
209
+ const self = this;
210
+ try {
211
+ var _this$agentId;
212
+ this.isRunning = true;
213
+ this.agentId = (_this$agentId = this.agentId) !== null && _this$agentId !== void 0 ? _this$agentId : (0, _ag_ui_client.randomUUID)();
214
+ const input = this.prepareRunAgentInput(parameters);
215
+ let result;
216
+ const previousMessageIds = new Set(this.messages.map((m) => m.id));
217
+ const subscribers = [
218
+ { onRunFinishedEvent: (event) => {
219
+ result = event.result;
220
+ } },
221
+ ...this.subscribers,
222
+ subscriber !== null && subscriber !== void 0 ? subscriber : {}
223
+ ];
224
+ await this.onInitialize(input, subscribers);
225
+ self.activeRunDetach$ = new rxjs.Subject();
226
+ let resolveCompletion;
227
+ self.activeRunCompletionPromise = new Promise((resolve) => {
228
+ resolveCompletion = resolve;
229
+ });
230
+ const source$ = (0, rxjs.defer)(() => this.connect(input)).pipe((0, _ag_ui_client.transformChunks)(this.debug), (0, rxjs_operators.takeUntil)(self.activeRunDetach$));
231
+ const applied$ = this.apply(input, source$, subscribers);
232
+ await (0, rxjs.lastValueFrom)(this.processApplyEvents(input, applied$, subscribers).pipe((0, rxjs_operators.catchError)((error) => {
233
+ this.isRunning = false;
234
+ return this.onError(input, error, subscribers);
235
+ }), (0, rxjs_operators.finalize)(() => {
236
+ this.isRunning = false;
237
+ this.onFinalize(input, subscribers);
238
+ resolveCompletion === null || resolveCompletion === void 0 || resolveCompletion();
239
+ resolveCompletion = void 0;
240
+ self.activeRunCompletionPromise = void 0;
241
+ self.activeRunDetach$ = void 0;
242
+ })), { defaultValue: void 0 });
243
+ const newMessages = (0, _ag_ui_client.structuredClone_)(this.messages).filter((m) => !previousMessageIds.has(m.id));
244
+ return {
245
+ result,
246
+ newMessages
247
+ };
248
+ } finally {
249
+ this.isRunning = false;
250
+ }
251
+ }
252
+ abortRun() {
253
+ if (this.activeChannel && this.runId) {
254
+ const fallback = setTimeout(() => clear(), 5e3);
255
+ const clear = () => {
256
+ clearTimeout(fallback);
257
+ this.detachActiveRun();
258
+ this.cleanup();
259
+ };
260
+ this.activeChannel.push(STOP_RUN_EVENT, { run_id: this.runId }).receive("ok", clear).receive("error", clear).receive("timeout", clear);
261
+ } else {
262
+ this.detachActiveRun();
263
+ this.cleanup();
264
+ }
265
+ }
266
+ /**
267
+ * Trigger the run via REST, then join the realtime thread channel and relay
268
+ * server-pushed AG-UI events to the Observable subscriber.
269
+ */
270
+ run(input) {
271
+ this.threadId = input.threadId;
272
+ this.runId = input.runId;
273
+ return (0, rxjs.defer)(() => this.requestJoinCredentials$("run", input)).pipe((0, rxjs.switchMap)((credentials) => this.observeThread$(input, credentials, {
274
+ completeOnRunError: false,
275
+ streamMode: "run"
276
+ })));
277
+ }
278
+ /**
279
+ * Reconnect to an existing thread by fetching websocket credentials and
280
+ * joining the realtime thread channel.
281
+ */
282
+ connect(input) {
283
+ this.threadId = input.threadId;
284
+ this.runId = input.runId;
285
+ return (0, rxjs.defer)(() => this.requestConnectPlan$(input)).pipe((0, rxjs.switchMap)((plan) => {
286
+ if (plan === null) return rxjs.EMPTY;
287
+ if (plan.mode === "bootstrap") {
288
+ this.setLastSeenEventId(input.threadId, plan.latestEventId);
289
+ for (const event of plan.events) this.updateRunIdFromEvent(event);
290
+ return (0, rxjs.from)(plan.events);
291
+ }
292
+ this.setLastSeenEventId(input.threadId, plan.joinFromEventId);
293
+ for (const event of plan.events) this.updateRunIdFromEvent(event);
294
+ return (0, rxjs.concat)((0, rxjs.from)(plan.events), this.observeThread$(input, { joinToken: plan.joinToken }, {
295
+ completeOnRunError: true,
296
+ streamMode: "connect",
297
+ replayCursor: plan.joinFromEventId
298
+ }));
299
+ }));
300
+ }
301
+ /**
302
+ * Tear down a specific channel + socket pair that belongs to one pipeline.
303
+ * Only nulls instance references when they still point to the owned resource,
304
+ * so a concurrent pipeline's resources are never clobbered.
305
+ */
306
+ cleanupOwned(ownChannel, ownSocket) {
307
+ if (ownChannel) {
308
+ ownChannel.leave();
309
+ if (this.activeChannel === ownChannel) this.activeChannel = null;
310
+ }
311
+ if (ownSocket) {
312
+ ownSocket.disconnect();
313
+ if (this.socket === ownSocket) this.socket = null;
314
+ }
315
+ if (this.threadId) this.sharedState.lastSeenEventIds.delete(this.threadId);
316
+ this.runId = null;
317
+ }
318
+ cleanup() {
319
+ this.cleanupOwned(this.activeChannel, this.socket);
320
+ }
321
+ requestJoinCredentials$(mode, input) {
322
+ return (0, rxjs.defer)(async () => {
323
+ try {
324
+ const response = await fetch(this.buildRuntimeUrl(mode), {
325
+ method: "POST",
326
+ headers: {
327
+ "Content-Type": "application/json",
328
+ ...this.config.headers
329
+ },
330
+ body: JSON.stringify({
331
+ threadId: input.threadId,
332
+ runId: input.runId,
333
+ messages: input.messages,
334
+ tools: input.tools,
335
+ context: input.context,
336
+ state: input.state,
337
+ forwardedProps: input.forwardedProps
338
+ }),
339
+ ...this.config.credentials ? { credentials: this.config.credentials } : {}
340
+ });
341
+ if (!response.ok) {
342
+ const text = await response.text().catch(() => "");
343
+ throw new Error(text || response.statusText || String(response.status));
344
+ }
345
+ const payload = await response.json();
346
+ if (!payload.joinToken) throw new Error("missing joinToken");
347
+ return { joinToken: payload.joinToken };
348
+ } catch (error) {
349
+ throw new Error(`REST ${mode} request failed: ${error instanceof Error ? error.message : String(error)}`);
350
+ }
351
+ });
352
+ }
353
+ requestConnectPlan$(input) {
354
+ return (0, rxjs.defer)(async () => {
355
+ try {
356
+ const response = await fetch(this.buildRuntimeUrl("connect"), {
357
+ method: "POST",
358
+ headers: {
359
+ "Content-Type": "application/json",
360
+ ...this.config.headers
361
+ },
362
+ body: JSON.stringify({
363
+ threadId: input.threadId,
364
+ runId: input.runId,
365
+ messages: input.messages,
366
+ tools: input.tools,
367
+ context: input.context,
368
+ state: input.state,
369
+ forwardedProps: input.forwardedProps,
370
+ lastSeenEventId: this.getReconnectCursor(input)
371
+ }),
372
+ ...this.config.credentials ? { credentials: this.config.credentials } : {}
373
+ });
374
+ if (response.status === 204) return null;
375
+ if (!response.ok) {
376
+ const text = await response.text().catch(() => "");
377
+ throw new Error(text || response.statusText || String(response.status));
378
+ }
379
+ return this.normalizeConnectPlan(await response.json());
380
+ } catch (error) {
381
+ throw new Error(`REST connect request failed: ${error instanceof Error ? error.message : String(error)}`);
382
+ }
383
+ });
384
+ }
385
+ normalizeConnectPlan(payload) {
386
+ const envelope = payload && typeof payload === "object" ? payload : null;
387
+ if ((envelope === null || envelope === void 0 ? void 0 : envelope.mode) === "bootstrap") return {
388
+ mode: "bootstrap",
389
+ latestEventId: typeof envelope.latestEventId === "string" ? envelope.latestEventId : null,
390
+ events: Array.isArray(envelope.events) ? envelope.events : []
391
+ };
392
+ if ((envelope === null || envelope === void 0 ? void 0 : envelope.mode) === "live") {
393
+ if (typeof envelope.joinToken !== "string" || envelope.joinToken.length === 0) throw new Error("missing joinToken");
394
+ return {
395
+ mode: "live",
396
+ joinToken: envelope.joinToken,
397
+ joinFromEventId: typeof envelope.joinFromEventId === "string" ? envelope.joinFromEventId : null,
398
+ events: Array.isArray(envelope.events) ? envelope.events : []
399
+ };
400
+ }
401
+ throw new Error("invalid connect plan");
402
+ }
403
+ observeThread$(input, credentials, options) {
404
+ return (0, rxjs.defer)(() => {
405
+ var _this$config$socketPa;
406
+ let ownSocket = null;
407
+ let ownChannel = null;
408
+ const socket$ = ɵphoenixSocket$({
409
+ url: this.config.url,
410
+ options: {
411
+ params: {
412
+ ...(_this$config$socketPa = this.config.socketParams) !== null && _this$config$socketPa !== void 0 ? _this$config$socketPa : {},
413
+ join_token: credentials.joinToken
414
+ },
415
+ reconnectAfterMs: (0, _copilotkitnext_shared.phoenixExponentialBackoff)(100, 1e4),
416
+ rejoinAfterMs: (0, _copilotkitnext_shared.phoenixExponentialBackoff)(1e3, 3e4)
417
+ }
418
+ }).pipe((0, rxjs_operators.tap)(({ socket }) => {
419
+ ownSocket = socket;
420
+ this.socket = ownSocket;
421
+ }), (0, rxjs_operators.shareReplay)({
422
+ bufferSize: 1,
423
+ refCount: true
424
+ }));
425
+ const { topic, params } = this.createThreadChannelDescriptor(input, options.streamMode, options.replayCursor);
426
+ const channel$ = ɵphoenixChannel$({
427
+ socket$,
428
+ topic,
429
+ params
430
+ }).pipe((0, rxjs_operators.tap)(({ channel }) => {
431
+ ownChannel = channel;
432
+ this.activeChannel = ownChannel;
433
+ }), (0, rxjs_operators.shareReplay)({
434
+ bufferSize: 1,
435
+ refCount: true
436
+ }));
437
+ const threadEvents$ = this.observeThreadEvents$(input.threadId, channel$, options).pipe((0, rxjs_operators.share)());
438
+ const threadCompleted$ = threadEvents$.pipe((0, rxjs_operators.ignoreElements)(), (0, rxjs_operators.endWith)(null), (0, rxjs_operators.take)(1));
439
+ return (0, rxjs.merge)(this.joinThreadChannel$(channel$), this.observeSocketHealth$(socket$).pipe((0, rxjs_operators.takeUntil)(threadCompleted$)), threadEvents$).pipe((0, rxjs_operators.finalize)(() => this.cleanupOwned(ownChannel, ownSocket)));
440
+ });
441
+ }
442
+ joinThreadChannel$(channel$) {
443
+ return ɵjoinPhoenixChannel$(channel$);
444
+ }
445
+ observeSocketHealth$(socket$) {
446
+ return ɵobservePhoenixSocketHealth$(ɵobservePhoenixSocketSignals$(socket$), 5);
447
+ }
448
+ observeThreadEvents$(threadId, channel$, options) {
449
+ return channel$.pipe((0, rxjs_operators.switchMap)(({ channel }) => this.observeChannelEvent$(channel, CLIENT_AG_UI_EVENT)), (0, rxjs_operators.tap)((payload) => {
450
+ this.updateLastSeenEventId(threadId, payload);
451
+ this.updateRunIdFromEvent(payload);
452
+ }), (0, rxjs_operators.mergeMap)((payload) => (0, rxjs.from)(this.createThreadNotifications(payload, options.completeOnRunError))), (0, rxjs.dematerialize)());
453
+ }
454
+ observeChannelEvent$(channel, eventName) {
455
+ return ɵobservePhoenixEvent$(channel, eventName);
456
+ }
457
+ createThreadNotifications(payload, completeOnRunError) {
458
+ if (payload.type === _ag_ui_client.EventType.RUN_FINISHED) return [rxjs.Notification.createNext(payload), rxjs.Notification.createComplete()];
459
+ if (payload.type === _ag_ui_client.EventType.RUN_ERROR) {
460
+ var _message;
461
+ const errorMessage = (_message = payload.message) !== null && _message !== void 0 ? _message : "Run error";
462
+ return completeOnRunError ? [rxjs.Notification.createNext(payload), rxjs.Notification.createComplete()] : [rxjs.Notification.createNext(payload), rxjs.Notification.createError(new Error(errorMessage))];
463
+ }
464
+ return [rxjs.Notification.createNext(payload)];
465
+ }
466
+ buildRuntimeUrl(mode) {
467
+ const path = `${this.config.runtimeUrl}/agent/${encodeURIComponent(this.config.agentId)}/${mode}`;
468
+ const origin = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
469
+ return new URL(path, new URL(this.config.runtimeUrl, origin)).toString();
470
+ }
471
+ createThreadChannelDescriptor(input, streamMode, replayCursor) {
472
+ const params = streamMode === "run" ? {
473
+ stream_mode: "run",
474
+ run_id: input.runId
475
+ } : {
476
+ stream_mode: "connect",
477
+ last_seen_event_id: replayCursor === void 0 ? this.getReconnectCursor(input) : replayCursor
478
+ };
479
+ return {
480
+ topic: `thread:${input.threadId}`,
481
+ params
482
+ };
483
+ }
484
+ getLastSeenEventId(threadId) {
485
+ var _this$sharedState$las;
486
+ return (_this$sharedState$las = this.sharedState.lastSeenEventIds.get(threadId)) !== null && _this$sharedState$las !== void 0 ? _this$sharedState$las : null;
487
+ }
488
+ getReconnectCursor(input) {
489
+ return this.hasLocalThreadMessages(input) ? this.getLastSeenEventId(input.threadId) : null;
490
+ }
491
+ hasLocalThreadMessages(input) {
492
+ return Array.isArray(input.messages) && input.messages.length > 0;
493
+ }
494
+ updateLastSeenEventId(threadId, payload) {
495
+ const eventId = this.readEventId(payload);
496
+ if (!eventId) return;
497
+ this.sharedState.lastSeenEventIds.set(threadId, eventId);
498
+ }
499
+ setLastSeenEventId(threadId, eventId) {
500
+ if (!eventId) return;
501
+ this.sharedState.lastSeenEventIds.set(threadId, eventId);
502
+ }
503
+ /**
504
+ * Keep `this.runId` in sync with the backend's actual run ID.
505
+ *
506
+ * During a `connect` (resume) flow the client generates a fresh `runId`
507
+ * via `prepareRunAgentInput`, but the backend is running under its own
508
+ * run ID. If the client later sends `STOP_RUN_EVENT` with the wrong
509
+ * `runId`, the gateway's runner channel will not match it and the agent
510
+ * keeps running. Extracting the run ID from live events fixes this.
511
+ *
512
+ * The runner normalises events to `run_id` (snake_case) before pushing
513
+ * to the gateway, so we check both `runId` and `run_id`.
514
+ */
515
+ updateRunIdFromEvent(payload) {
516
+ var _record$runId;
517
+ const record = payload;
518
+ const eventRunId = (_record$runId = record.runId) !== null && _record$runId !== void 0 ? _record$runId : record.run_id;
519
+ if (typeof eventRunId === "string" && eventRunId.length > 0) this.runId = eventRunId;
520
+ }
521
+ readEventId(payload) {
522
+ const metadata = payload.metadata;
523
+ if (!metadata || typeof metadata !== "object") return null;
524
+ const runnerEventId = metadata.cpki_event_id;
525
+ return typeof runnerEventId === "string" ? runnerEventId : null;
526
+ }
527
+ };
528
+
529
+ //#endregion
530
+ //#region \0@oxc-project+runtime@0.112.0/helpers/checkPrivateRedeclaration.js
531
+ function _checkPrivateRedeclaration(e, t) {
532
+ if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
533
+ }
534
+
535
+ //#endregion
536
+ //#region \0@oxc-project+runtime@0.112.0/helpers/classPrivateMethodInitSpec.js
537
+ function _classPrivateMethodInitSpec(e, a) {
538
+ _checkPrivateRedeclaration(e, a), a.add(e);
539
+ }
540
+
541
+ //#endregion
542
+ //#region \0@oxc-project+runtime@0.112.0/helpers/assertClassBrand.js
543
+ function _assertClassBrand(e, t, n) {
544
+ if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
545
+ throw new TypeError("Private element is not present on this object");
546
+ }
547
+
548
+ //#endregion
549
+ //#region \0@oxc-project+runtime@0.112.0/helpers/getPrototypeOf.js
550
+ function _getPrototypeOf(t) {
551
+ return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function(t) {
552
+ return t.__proto__ || Object.getPrototypeOf(t);
553
+ }, _getPrototypeOf(t);
554
+ }
555
+
556
+ //#endregion
557
+ //#region \0@oxc-project+runtime@0.112.0/helpers/superPropBase.js
558
+ function _superPropBase(t, o) {
559
+ for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t)););
560
+ return t;
561
+ }
562
+
563
+ //#endregion
564
+ //#region \0@oxc-project+runtime@0.112.0/helpers/get.js
565
+ function _get() {
566
+ return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function(e, t, r) {
567
+ var p = _superPropBase(e, t);
568
+ if (p) {
569
+ var n = Object.getOwnPropertyDescriptor(p, t);
570
+ return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value;
571
+ }
572
+ }, _get.apply(null, arguments);
573
+ }
574
+
575
+ //#endregion
576
+ //#region \0@oxc-project+runtime@0.112.0/helpers/superPropGet.js
577
+ function _superPropGet(t, o, e, r) {
578
+ var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e);
579
+ return 2 & r && "function" == typeof p ? function(t) {
580
+ return p.apply(e, t);
581
+ } : p;
582
+ }
583
+
49
584
  //#endregion
50
585
  //#region src/agent.ts
51
- /**
52
- * Check if an error is a ZodError (validation error).
53
- * These can occur when the SSE stream is aborted/truncated mid-event.
54
- */
586
+ var _ProxiedCopilotRuntimeAgent;
587
+ function hasHeaders(agent) {
588
+ return "headers" in agent;
589
+ }
590
+ function hasCredentials(agent) {
591
+ return "credentials" in agent;
592
+ }
55
593
  function isZodError(error) {
56
594
  return error !== null && typeof error === "object" && "name" in error && error.name === "ZodError";
57
595
  }
58
- /**
59
- * Wrap an Observable to catch and suppress ZodErrors that occur during stream abort.
60
- * These errors are expected when the connection is cancelled mid-stream.
61
- */
62
596
  function withAbortErrorHandling(observable) {
63
597
  return observable.pipe((0, rxjs_operators.catchError)((error) => {
64
598
  if (isZodError(error)) return rxjs.EMPTY;
65
599
  throw error;
66
600
  }));
67
601
  }
68
- var ProxiedCopilotRuntimeAgent = class extends _ag_ui_client.HttpAgent {
602
+ var _ProxiedCopilotRuntimeAgent_brand = /* @__PURE__ */ new WeakSet();
603
+ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui_client.HttpAgent {
69
604
  constructor(config) {
70
- var _config$transport, _ref, _config$agentId;
605
+ var _config$transport, _ref, _config$agentId, _config$runtimeMode;
71
606
  const normalizedRuntimeUrl = config.runtimeUrl ? config.runtimeUrl.replace(/\/$/, "") : void 0;
72
607
  const transport = (_config$transport = config.transport) !== null && _config$transport !== void 0 ? _config$transport : "rest";
73
608
  const runUrl = transport === "single" ? (_ref = normalizedRuntimeUrl !== null && normalizedRuntimeUrl !== void 0 ? normalizedRuntimeUrl : config.runtimeUrl) !== null && _ref !== void 0 ? _ref : "" : `${normalizedRuntimeUrl !== null && normalizedRuntimeUrl !== void 0 ? normalizedRuntimeUrl : config.runtimeUrl}/agent/${encodeURIComponent((_config$agentId = config.agentId) !== null && _config$agentId !== void 0 ? _config$agentId : "")}/run`;
@@ -76,16 +611,33 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
76
611
  ...config,
77
612
  url: runUrl
78
613
  });
614
+ _classPrivateMethodInitSpec(this, _ProxiedCopilotRuntimeAgent_brand);
79
615
  _defineProperty(this, "runtimeUrl", void 0);
80
616
  _defineProperty(this, "credentials", void 0);
81
617
  _defineProperty(this, "transport", void 0);
82
618
  _defineProperty(this, "singleEndpointUrl", void 0);
619
+ _defineProperty(this, "runtimeMode", void 0);
620
+ _defineProperty(this, "intelligence", void 0);
621
+ _defineProperty(this, "delegate", void 0);
622
+ _defineProperty(this, "runtimeInfoPromise", void 0);
83
623
  this.runtimeUrl = normalizedRuntimeUrl !== null && normalizedRuntimeUrl !== void 0 ? normalizedRuntimeUrl : config.runtimeUrl;
84
624
  this.credentials = config.credentials;
85
625
  this.transport = transport;
626
+ this.runtimeMode = (_config$runtimeMode = config.runtimeMode) !== null && _config$runtimeMode !== void 0 ? _config$runtimeMode : _copilotkitnext_shared.RUNTIME_MODE_SSE;
627
+ this.intelligence = config.intelligence;
86
628
  if (this.transport === "single") this.singleEndpointUrl = this.runtimeUrl;
87
629
  }
630
+ async detachActiveRun() {
631
+ if (this.delegate) await this.delegate.detachActiveRun();
632
+ await super.detachActiveRun();
633
+ }
88
634
  abortRun() {
635
+ if (this.delegate) {
636
+ this.syncDelegate(this.delegate);
637
+ this.delegate.abortRun();
638
+ this.detachActiveRun();
639
+ return;
640
+ }
89
641
  if (!this.agentId || !this.threadId) return;
90
642
  if (typeof fetch === "undefined") return;
91
643
  if (this.transport === "single") {
@@ -126,30 +678,112 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
126
678
  console.error("ProxiedCopilotRuntimeAgent: stop request failed", error);
127
679
  });
128
680
  }
129
- connect(input) {
130
- if (this.transport === "single") {
131
- if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
132
- const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId: this.agentId });
133
- return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
681
+ async connectAgent(parameters, subscriber) {
682
+ if (this.runtimeMode !== _copilotkitnext_shared.RUNTIME_MODE_INTELLIGENCE) return super.connectAgent(parameters, subscriber);
683
+ if (this.delegate) await this.delegate.detachActiveRun();
684
+ await this.resolveDelegate();
685
+ const delegate = this.delegate;
686
+ const bridgeSub = delegate.subscribe({
687
+ onMessagesChanged: () => {
688
+ this.setMessages([...delegate.messages]);
689
+ },
690
+ onStateChanged: () => {
691
+ this.setState({ ...delegate.state });
692
+ },
693
+ onRunInitialized: () => {
694
+ this.isRunning = true;
695
+ },
696
+ onRunFinalized: () => {
697
+ this.isRunning = false;
698
+ },
699
+ onRunFailed: () => {
700
+ this.isRunning = false;
701
+ }
702
+ });
703
+ const forwardedSubs = this.subscribers.map((s) => delegate.subscribe(s));
704
+ try {
705
+ const result = await delegate.connectAgent(parameters, subscriber);
706
+ this.setMessages([...delegate.messages]);
707
+ this.setState({ ...delegate.state });
708
+ return result;
709
+ } finally {
710
+ this.isRunning = false;
711
+ bridgeSub.unsubscribe();
712
+ for (const sub of forwardedSubs) sub.unsubscribe();
134
713
  }
135
- return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(`${this.runtimeUrl}/agent/${this.agentId}/connect`, this.requestInit(input))));
714
+ }
715
+ connect(input) {
716
+ if (this.runtimeMode === _copilotkitnext_shared.RUNTIME_MODE_INTELLIGENCE) return _assertClassBrand(_ProxiedCopilotRuntimeAgent_brand, this, _connectViaDelegate).call(this, input);
717
+ return _assertClassBrand(_ProxiedCopilotRuntimeAgent_brand, this, _connectViaHttp).call(this, input);
136
718
  }
137
719
  run(input) {
138
- if (this.transport === "single") {
139
- if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
140
- const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.agentId });
141
- return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
142
- }
143
- return withAbortErrorHandling(super.run(input));
720
+ if (this.runtimeMode === _copilotkitnext_shared.RUNTIME_MODE_INTELLIGENCE) return _assertClassBrand(_ProxiedCopilotRuntimeAgent_brand, this, _runViaDelegate).call(this, input);
721
+ return _assertClassBrand(_ProxiedCopilotRuntimeAgent_brand, this, _runViaHttp).call(this, input);
144
722
  }
145
723
  clone() {
146
- const cloned = super.clone();
147
- cloned.runtimeUrl = this.runtimeUrl;
148
- cloned.credentials = this.credentials;
149
- cloned.transport = this.transport;
150
- cloned.singleEndpointUrl = this.singleEndpointUrl;
724
+ const cloned = new ProxiedCopilotRuntimeAgent({
725
+ runtimeUrl: this.runtimeUrl,
726
+ agentId: this.agentId,
727
+ description: this.description,
728
+ headers: { ...this.headers },
729
+ credentials: this.credentials,
730
+ transport: this.transport,
731
+ runtimeMode: this.runtimeMode,
732
+ intelligence: this.intelligence
733
+ });
734
+ cloned.threadId = this.threadId;
735
+ cloned.setState(this.state);
736
+ cloned.setMessages(this.messages);
737
+ if (this.delegate) {
738
+ cloned.delegate = this.delegate.clone();
739
+ cloned.syncDelegate(cloned.delegate);
740
+ }
151
741
  return cloned;
152
742
  }
743
+ async resolveDelegate() {
744
+ await this.ensureRuntimeMode();
745
+ if (!this.delegate) {
746
+ if (this.runtimeMode !== _copilotkitnext_shared.RUNTIME_MODE_INTELLIGENCE) throw new Error("A delegate is only created for Intelligence mode");
747
+ this.delegate = this.createIntelligenceDelegate();
748
+ }
749
+ this.syncDelegate(this.delegate);
750
+ return this.delegate;
751
+ }
752
+ async ensureRuntimeMode() {
753
+ var _this$runtimeInfoProm;
754
+ if (this.runtimeMode !== "pending") return;
755
+ if (!this.runtimeUrl) throw new Error("Runtime URL is not set");
756
+ (_this$runtimeInfoProm = this.runtimeInfoPromise) !== null && _this$runtimeInfoProm !== void 0 || (this.runtimeInfoPromise = this.fetchRuntimeInfo().then((runtimeInfo) => {
757
+ var _runtimeInfo$mode;
758
+ this.runtimeMode = (_runtimeInfo$mode = runtimeInfo.mode) !== null && _runtimeInfo$mode !== void 0 ? _runtimeInfo$mode : _copilotkitnext_shared.RUNTIME_MODE_SSE;
759
+ this.intelligence = runtimeInfo.intelligence;
760
+ }));
761
+ await this.runtimeInfoPromise;
762
+ }
763
+ async fetchRuntimeInfo() {
764
+ const headers = { ...this.headers };
765
+ let init;
766
+ let url;
767
+ if (this.transport === "single") {
768
+ if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
769
+ if (!headers["Content-Type"]) headers["Content-Type"] = "application/json";
770
+ url = this.runtimeUrl;
771
+ init = {
772
+ method: "POST",
773
+ body: JSON.stringify({ method: "info" })
774
+ };
775
+ } else {
776
+ url = `${this.runtimeUrl}/info`;
777
+ init = {};
778
+ }
779
+ const response = await fetch(url, {
780
+ ...init,
781
+ headers,
782
+ ...this.credentials ? { credentials: this.credentials } : {}
783
+ });
784
+ if (!response.ok) throw new Error(`Runtime info request failed with status ${response.status}`);
785
+ return await response.json();
786
+ }
153
787
  createSingleRouteRequestInit(input, method, params) {
154
788
  var _baseInit$headers, _headers$get;
155
789
  if (!this.agentId) throw new Error("ProxiedCopilotRuntimeAgent requires agentId to make runtime requests");
@@ -162,7 +796,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
162
796
  originalBody = JSON.parse(baseInit.body);
163
797
  } catch (error) {
164
798
  console.warn("ProxiedCopilotRuntimeAgent: failed to parse request body for single route transport", error);
165
- originalBody = void 0;
166
799
  }
167
800
  const envelope = { method };
168
801
  if (params && Object.keys(params).length > 0) envelope.params = params;
@@ -174,7 +807,50 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
174
807
  ...this.credentials ? { credentials: this.credentials } : {}
175
808
  };
176
809
  }
810
+ createIntelligenceDelegate() {
811
+ var _this$intelligence;
812
+ if (!this.runtimeUrl || !this.agentId || !((_this$intelligence = this.intelligence) === null || _this$intelligence === void 0 ? void 0 : _this$intelligence.wsUrl)) throw new Error("Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata");
813
+ return new IntelligenceAgent({
814
+ url: this.intelligence.wsUrl,
815
+ runtimeUrl: this.runtimeUrl,
816
+ agentId: this.agentId,
817
+ headers: { ...this.headers },
818
+ credentials: this.credentials
819
+ });
820
+ }
821
+ syncDelegate(delegate) {
822
+ delegate.agentId = this.agentId;
823
+ delegate.description = this.description;
824
+ delegate.threadId = this.threadId;
825
+ delegate.setMessages(this.messages);
826
+ delegate.setState(this.state);
827
+ if (hasHeaders(delegate)) delegate.headers = { ...this.headers };
828
+ if (hasCredentials(delegate)) delegate.credentials = this.credentials;
829
+ }
177
830
  };
831
+ _ProxiedCopilotRuntimeAgent = ProxiedCopilotRuntimeAgent;
832
+ function _connectViaDelegate(input) {
833
+ return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.connect(input))));
834
+ }
835
+ function _connectViaHttp(input) {
836
+ if (this.transport === "single") {
837
+ if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
838
+ const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId: this.agentId });
839
+ return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
840
+ }
841
+ return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(`${this.runtimeUrl}/agent/${this.agentId}/connect`, this.requestInit(input))));
842
+ }
843
+ function _runViaDelegate(input) {
844
+ return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.run(input))));
845
+ }
846
+ function _runViaHttp(input) {
847
+ if (this.transport === "single") {
848
+ if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
849
+ const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.agentId });
850
+ return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
851
+ }
852
+ return withAbortErrorHandling(_superPropGet(_ProxiedCopilotRuntimeAgent.prototype, "run", this, 2)([input]));
853
+ }
178
854
 
179
855
  //#endregion
180
856
  //#region src/core/agent-registry.ts
@@ -193,6 +869,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
193
869
  _defineProperty(this, "_runtimeConnectionStatus", CopilotKitCoreRuntimeConnectionStatus.Disconnected);
194
870
  _defineProperty(this, "_runtimeTransport", "rest");
195
871
  _defineProperty(this, "_audioFileTranscriptionEnabled", false);
872
+ _defineProperty(this, "_runtimeMode", _copilotkitnext_shared.RUNTIME_MODE_SSE);
873
+ _defineProperty(this, "_intelligence", void 0);
196
874
  _defineProperty(this, "_a2uiEnabled", false);
197
875
  }
198
876
  /**
@@ -216,6 +894,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
216
894
  get audioFileTranscriptionEnabled() {
217
895
  return this._audioFileTranscriptionEnabled;
218
896
  }
897
+ get runtimeMode() {
898
+ return this._runtimeMode;
899
+ }
900
+ get intelligence() {
901
+ return this._intelligence;
902
+ }
219
903
  get a2uiEnabled() {
220
904
  return this._a2uiEnabled;
221
905
  }
@@ -325,6 +1009,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
325
1009
  this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Disconnected;
326
1010
  this._runtimeVersion = void 0;
327
1011
  this._audioFileTranscriptionEnabled = false;
1012
+ this._runtimeMode = _copilotkitnext_shared.RUNTIME_MODE_SSE;
1013
+ this._intelligence = void 0;
328
1014
  this._a2uiEnabled = false;
329
1015
  this.remoteAgents = {};
330
1016
  this._agents = this.localAgents;
@@ -335,17 +1021,20 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
335
1021
  this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Connecting;
336
1022
  await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Connecting);
337
1023
  try {
338
- var _runtimeInfoResponse$, _runtimeInfoResponse$2;
1024
+ var _runtimeInfoResponse$2, _runtimeInfoResponse$3, _runtimeInfoResponse$4;
339
1025
  const runtimeInfoResponse = await this.fetchRuntimeInfo();
340
1026
  const { version, ...runtimeInfo } = runtimeInfoResponse;
341
1027
  const credentials = this.core.credentials;
342
1028
  this.remoteAgents = Object.fromEntries(Object.entries(runtimeInfo.agents).map(([id, { description }]) => {
1029
+ var _runtimeInfoResponse$;
343
1030
  const agent = new ProxiedCopilotRuntimeAgent({
344
1031
  runtimeUrl: this.runtimeUrl,
345
1032
  agentId: id,
346
1033
  description,
347
1034
  transport: this._runtimeTransport,
348
- credentials
1035
+ credentials,
1036
+ runtimeMode: (_runtimeInfoResponse$ = runtimeInfoResponse.mode) !== null && _runtimeInfoResponse$ !== void 0 ? _runtimeInfoResponse$ : _copilotkitnext_shared.RUNTIME_MODE_SSE,
1037
+ intelligence: runtimeInfoResponse.intelligence
349
1038
  });
350
1039
  this.applyHeadersToAgent(agent);
351
1040
  return [id, agent];
@@ -356,14 +1045,18 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
356
1045
  };
357
1046
  this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Connected;
358
1047
  this._runtimeVersion = version;
359
- this._audioFileTranscriptionEnabled = (_runtimeInfoResponse$ = runtimeInfoResponse.audioFileTranscriptionEnabled) !== null && _runtimeInfoResponse$ !== void 0 ? _runtimeInfoResponse$ : false;
360
- this._a2uiEnabled = (_runtimeInfoResponse$2 = runtimeInfoResponse.a2uiEnabled) !== null && _runtimeInfoResponse$2 !== void 0 ? _runtimeInfoResponse$2 : false;
1048
+ this._audioFileTranscriptionEnabled = (_runtimeInfoResponse$2 = runtimeInfoResponse.audioFileTranscriptionEnabled) !== null && _runtimeInfoResponse$2 !== void 0 ? _runtimeInfoResponse$2 : false;
1049
+ this._runtimeMode = (_runtimeInfoResponse$3 = runtimeInfoResponse.mode) !== null && _runtimeInfoResponse$3 !== void 0 ? _runtimeInfoResponse$3 : _copilotkitnext_shared.RUNTIME_MODE_SSE;
1050
+ this._intelligence = runtimeInfoResponse.intelligence;
1051
+ this._a2uiEnabled = (_runtimeInfoResponse$4 = runtimeInfoResponse.a2uiEnabled) !== null && _runtimeInfoResponse$4 !== void 0 ? _runtimeInfoResponse$4 : false;
361
1052
  await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Connected);
362
1053
  await this.notifyAgentsChanged();
363
1054
  } catch (error) {
364
1055
  this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Error;
365
1056
  this._runtimeVersion = void 0;
366
1057
  this._audioFileTranscriptionEnabled = false;
1058
+ this._runtimeMode = _copilotkitnext_shared.RUNTIME_MODE_SSE;
1059
+ this._intelligence = void 0;
367
1060
  this._a2uiEnabled = false;
368
1061
  this.remoteAgents = {};
369
1062
  this._agents = this.localAgents;
@@ -915,6 +1608,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
915
1608
  async runAgent({ agent, forwardedProps }) {
916
1609
  if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
917
1610
  if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
1611
+ if (agent.detachActiveRun) agent.detachActiveRun();
918
1612
  try {
919
1613
  const runAgentResult = await agent.runAgent({
920
1614
  forwardedProps: {
@@ -1659,6 +2353,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1659
2353
  get audioFileTranscriptionEnabled() {
1660
2354
  return this.agentRegistry.audioFileTranscriptionEnabled;
1661
2355
  }
2356
+ get runtimeMode() {
2357
+ return this.agentRegistry.runtimeMode;
2358
+ }
2359
+ get intelligence() {
2360
+ return this.agentRegistry.intelligence;
2361
+ }
1662
2362
  get a2uiEnabled() {
1663
2363
  return this.agentRegistry.a2uiEnabled;
1664
2364
  }
@@ -1995,183 +2695,635 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1995
2695
  }
1996
2696
 
1997
2697
  //#endregion
1998
- //#region src/intelligence-agent.ts
1999
- var IntelligenceAgent = class IntelligenceAgent extends _ag_ui_client.AbstractAgent {
2000
- constructor(config) {
2001
- super();
2002
- _defineProperty(this, "config", void 0);
2003
- _defineProperty(this, "socket", null);
2004
- _defineProperty(this, "activeChannel", null);
2005
- _defineProperty(this, "threadId", null);
2006
- this.config = config;
2007
- }
2008
- clone() {
2009
- return new IntelligenceAgent(this.config);
2698
+ //#region src/utils/micro-redux.ts
2699
+ const INTERNAL_ACTION_TYPES = {
2700
+ boot: "@@micro-redux/boot",
2701
+ init: "@@micro-redux/init",
2702
+ stop: "@@micro-redux/stop"
2703
+ };
2704
+ const INTERNAL_BOOT_ACTION = { type: INTERNAL_ACTION_TYPES.boot };
2705
+ /**
2706
+ * Builds a typed action creator from a type string and payload factory.
2707
+ */
2708
+ function createTypedActionCreator(type, factory) {
2709
+ const creator = ((...args) => ({
2710
+ ...factory(...args),
2711
+ type
2712
+ }));
2713
+ creator.type = type;
2714
+ creator.match = (action) => action.type === type;
2715
+ return creator;
2716
+ }
2717
+ /**
2718
+ * Declares a payload-based action config for `createActionGroup`.
2719
+ *
2720
+ * @example
2721
+ * ```ts
2722
+ * const actions = createActionGroup("User", {
2723
+ * loaded: props<{ id: string }>(),
2724
+ * });
2725
+ * ```
2726
+ */
2727
+ function props() {
2728
+ return { kind: "props" };
2729
+ }
2730
+ /**
2731
+ * Declares a no-payload action config for `createActionGroup`.
2732
+ *
2733
+ * @example
2734
+ * ```ts
2735
+ * const actions = createActionGroup("User", {
2736
+ * reset: empty(),
2737
+ * });
2738
+ * ```
2739
+ */
2740
+ function empty() {
2741
+ return { kind: "empty" };
2742
+ }
2743
+ /**
2744
+ * Creates a namespaced group of typed action creators.
2745
+ *
2746
+ * Action types are formatted as: `[Source] actionName`.
2747
+ */
2748
+ function createActionGroup(source, config) {
2749
+ const group = {};
2750
+ for (const eventName of Object.keys(config)) {
2751
+ const eventConfig = config[eventName];
2752
+ if (!eventConfig) continue;
2753
+ const actionType = `[${source}] ${eventName}`;
2754
+ if (eventConfig.kind === "props") {
2755
+ group[eventName] = createTypedActionCreator(actionType, (payload) => ({ ...payload }));
2756
+ continue;
2757
+ }
2758
+ group[eventName] = createTypedActionCreator(actionType, () => ({}));
2010
2759
  }
2011
- abortRun() {
2012
- if (this.activeChannel && this.threadId) {
2013
- const fallback = setTimeout(() => this.cleanup(), 5e3);
2014
- const clear = () => {
2015
- clearTimeout(fallback);
2016
- this.cleanup();
2017
- };
2018
- this.activeChannel.push(_copilotkitnext_shared.AG_UI_CHANNEL_EVENT, {
2019
- type: _ag_ui_client.EventType.CUSTOM,
2020
- name: "stop",
2021
- value: { threadId: this.threadId }
2022
- }).receive("ok", clear).receive("error", clear).receive("timeout", clear);
2023
- } else this.cleanup();
2760
+ return group;
2761
+ }
2762
+ /**
2763
+ * Registers one reducer handler for one or more action creators.
2764
+ *
2765
+ * @throws Error when called without at least one action creator and reducer.
2766
+ */
2767
+ function on(...args) {
2768
+ if (args.length < 2) throw new Error("on requires at least one action creator and one reducer");
2769
+ const reducer = args[args.length - 1];
2770
+ return {
2771
+ creators: args.slice(0, -1),
2772
+ reducer
2773
+ };
2774
+ }
2775
+ /**
2776
+ * Creates a reducer from an initial state and `on(...)` handler entries.
2777
+ *
2778
+ * Unknown action types return the current state unchanged.
2779
+ */
2780
+ function createReducer(initialState, ...entries) {
2781
+ const reducerMap = /* @__PURE__ */ new Map();
2782
+ for (const entry of entries) for (const creator of entry.creators) {
2783
+ var _reducerMap$get;
2784
+ const handlers = (_reducerMap$get = reducerMap.get(creator.type)) !== null && _reducerMap$get !== void 0 ? _reducerMap$get : [];
2785
+ handlers.push(entry.reducer);
2786
+ reducerMap.set(creator.type, handlers);
2787
+ }
2788
+ return (state, action) => {
2789
+ const currentState = state !== null && state !== void 0 ? state : initialState;
2790
+ const handlers = reducerMap.get(action.type);
2791
+ if (!handlers || handlers.length === 0) return currentState;
2792
+ let nextState = currentState;
2793
+ for (const handler of handlers) nextState = handler(nextState, action);
2794
+ return nextState;
2795
+ };
2796
+ }
2797
+ /**
2798
+ * Creates a selector that caches and reuses the last computed result
2799
+ * when all input references are unchanged.
2800
+ */
2801
+ function createSelector(...args) {
2802
+ if (args.length === 1) {
2803
+ const projector = args[0];
2804
+ let hasCached = false;
2805
+ let lastState;
2806
+ let lastResult;
2807
+ return (state) => {
2808
+ if (hasCached && state === lastState) return lastResult;
2809
+ lastState = state;
2810
+ lastResult = projector(state);
2811
+ hasCached = true;
2812
+ return lastResult;
2813
+ };
2024
2814
  }
2025
- /**
2026
- * Connect to a Phoenix channel scoped to the thread, trigger the run via
2027
- * REST, and relay server-pushed AG-UI events to the Observable subscriber.
2028
- *
2029
- * The server pushes each AG-UI event using its EventType string as the
2030
- * Phoenix event name (e.g. "TEXT_MESSAGE_CHUNK", "TOOL_CALL_START"), with
2031
- * the full BaseEvent as payload. RUN_FINISHED and RUN_ERROR are terminal
2032
- * events that complete or error the Observable.
2033
- */
2034
- run(input) {
2035
- return new rxjs.Observable((observer) => {
2036
- var _this$config$socketPa;
2037
- this.threadId = input.threadId;
2038
- const socket = new phoenix.Socket(this.config.url, {
2039
- params: (_this$config$socketPa = this.config.socketParams) !== null && _this$config$socketPa !== void 0 ? _this$config$socketPa : {},
2040
- reconnectAfterMs: (0, _copilotkitnext_shared.phoenixExponentialBackoff)(100, 1e4),
2041
- rejoinAfterMs: (0, _copilotkitnext_shared.phoenixExponentialBackoff)(1e3, 3e4)
2042
- });
2043
- this.socket = socket;
2044
- socket.connect();
2045
- const channel = socket.channel(`agent:${input.threadId}`, { runId: input.runId });
2046
- this.activeChannel = channel;
2047
- channel.on(_copilotkitnext_shared.AG_UI_CHANNEL_EVENT, (payload) => {
2048
- observer.next(payload);
2049
- if (payload.type === _ag_ui_client.EventType.RUN_FINISHED) {
2050
- observer.complete();
2051
- this.cleanup();
2052
- } else if (payload.type === _ag_ui_client.EventType.RUN_ERROR) {
2053
- var _message;
2054
- observer.error(new Error((_message = payload.message) !== null && _message !== void 0 ? _message : "Run error"));
2055
- this.cleanup();
2056
- }
2057
- });
2058
- const MAX_CONSECUTIVE_ERRORS = 5;
2059
- let consecutiveErrors = 0;
2060
- socket.onError(() => {
2061
- consecutiveErrors++;
2062
- if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
2063
- observer.error(/* @__PURE__ */ new Error(`WebSocket connection failed after ${MAX_CONSECUTIVE_ERRORS} consecutive errors`));
2064
- this.cleanup();
2065
- }
2066
- });
2067
- socket.onOpen(() => {
2068
- consecutiveErrors = 0;
2069
- });
2070
- channel.onError(() => {});
2071
- channel.join().receive("ok", () => {
2072
- const { runtimeUrl, agentId, headers, credentials } = this.config;
2073
- const runPath = `${runtimeUrl}/agent/${encodeURIComponent(agentId)}/run`;
2074
- const origin = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
2075
- const runUrl = new URL(runPath, new URL(runtimeUrl, origin));
2076
- fetch(runUrl.toString(), {
2077
- method: "POST",
2078
- headers: {
2079
- "Content-Type": "application/json",
2080
- ...headers
2815
+ const projector = args[args.length - 1];
2816
+ const selectors = args.slice(0, -1);
2817
+ let hasCached = false;
2818
+ let lastInputs = [];
2819
+ let lastResult;
2820
+ return (state) => {
2821
+ const inputs = selectors.map((selector) => selector(state));
2822
+ if (hasCached && inputs.length === lastInputs.length && inputs.every((value, index) => value === lastInputs[index])) return lastResult;
2823
+ lastInputs = inputs;
2824
+ lastResult = projector(...inputs);
2825
+ hasCached = true;
2826
+ return lastResult;
2827
+ };
2828
+ }
2829
+ /**
2830
+ * RxJS operator that maps state emissions through a selector and suppresses
2831
+ * unchanged projected values via reference equality.
2832
+ */
2833
+ function select(selector) {
2834
+ return (source$) => source$.pipe((0, rxjs_operators.map)(selector), (0, rxjs_operators.distinctUntilChanged)());
2835
+ }
2836
+ /**
2837
+ * RxJS operator that filters an action stream by action creators and narrows
2838
+ * the output action type to the matched creator union.
2839
+ *
2840
+ * @throws Error when called without at least one action creator.
2841
+ */
2842
+ function ofType(...creators) {
2843
+ if (creators.length === 0) throw new Error("ofType requires at least one action creator");
2844
+ const actionTypes = new Set(creators.map((creator) => creator.type));
2845
+ return (source$) => {
2846
+ return source$.pipe((0, rxjs_operators.filter)((action) => {
2847
+ return actionTypes.has(action.type);
2848
+ }));
2849
+ };
2850
+ }
2851
+ /**
2852
+ * Creates an effect descriptor consumed by `createStore`.
2853
+ */
2854
+ function createEffect(factory, options = {}) {
2855
+ if (options.dispatch === false) return {
2856
+ run: factory,
2857
+ dispatch: false
2858
+ };
2859
+ return {
2860
+ run: factory,
2861
+ dispatch: true
2862
+ };
2863
+ }
2864
+ /**
2865
+ * Creates a small observable store with reducer + effects.
2866
+ *
2867
+ * Behavior:
2868
+ * - `init()` starts effects and dispatches `@@micro-redux/init`.
2869
+ * - `stop()` dispatches `@@micro-redux/stop` and unsubscribes all effects.
2870
+ * - Effect action observation is scheduled on `asapScheduler` to avoid
2871
+ * synchronous re-entrancy in the effect loop.
2872
+ * - Any effect error triggers fail-fast teardown and errors both `actions$`
2873
+ * and `state$`.
2874
+ */
2875
+ function createStore(options) {
2876
+ var _options$effects;
2877
+ const reducer = options.reducer;
2878
+ const effects = (_options$effects = options.effects) !== null && _options$effects !== void 0 ? _options$effects : [];
2879
+ let hasFatalError = false;
2880
+ let isRunning = false;
2881
+ let effectSubscriptions = new rxjs.Subscription();
2882
+ let currentState = reducer(void 0, INTERNAL_BOOT_ACTION);
2883
+ const stateSubject = new rxjs.BehaviorSubject(currentState);
2884
+ const actionsSubject = new rxjs.Subject();
2885
+ const dispatchInternal = (action) => {
2886
+ if (hasFatalError) throw new Error("Store is in a failed state due to an effect error");
2887
+ currentState = reducer(currentState, action);
2888
+ stateSubject.next(currentState);
2889
+ actionsSubject.next(action);
2890
+ };
2891
+ const failFast = (error) => {
2892
+ if (hasFatalError) return;
2893
+ hasFatalError = true;
2894
+ isRunning = false;
2895
+ effectSubscriptions.unsubscribe();
2896
+ effectSubscriptions = new rxjs.Subscription();
2897
+ actionsSubject.error(error);
2898
+ stateSubject.error(error);
2899
+ };
2900
+ const startEffects = () => {
2901
+ for (const effect of effects) {
2902
+ const scheduledActions$ = actionsSubject.asObservable().pipe((0, rxjs_operators.observeOn)(rxjs.asapScheduler));
2903
+ const state$ = stateSubject.asObservable();
2904
+ if (effect.dispatch) {
2905
+ const subscription = effect.run(scheduledActions$, state$).subscribe({
2906
+ next: (effectAction) => {
2907
+ if (hasFatalError) return;
2908
+ dispatchInternal(effectAction);
2081
2909
  },
2082
- body: JSON.stringify({
2083
- threadId: input.threadId,
2084
- runId: input.runId,
2085
- messages: input.messages,
2086
- tools: input.tools,
2087
- context: input.context,
2088
- state: input.state,
2089
- forwardedProps: input.forwardedProps
2090
- }),
2091
- ...credentials ? { credentials } : {}
2092
- }).catch((error) => {
2093
- var _error$message;
2094
- observer.error(/* @__PURE__ */ new Error(`REST run request failed: ${(_error$message = error.message) !== null && _error$message !== void 0 ? _error$message : error}`));
2095
- this.cleanup();
2910
+ error: (error) => {
2911
+ failFast(error);
2912
+ }
2096
2913
  });
2097
- }).receive("error", (resp) => {
2098
- observer.error(/* @__PURE__ */ new Error(`Failed to join channel: ${JSON.stringify(resp)}`));
2099
- this.cleanup();
2100
- }).receive("timeout", () => {
2101
- observer.error(/* @__PURE__ */ new Error("Timed out joining channel"));
2102
- this.cleanup();
2103
- });
2104
- return () => {
2105
- this.cleanup();
2106
- };
2914
+ effectSubscriptions.add(subscription);
2915
+ continue;
2916
+ }
2917
+ const subscription = effect.run(scheduledActions$, state$).subscribe({ error: (error) => {
2918
+ failFast(error);
2919
+ } });
2920
+ effectSubscriptions.add(subscription);
2921
+ }
2922
+ };
2923
+ return {
2924
+ dispatch(action) {
2925
+ dispatchInternal(action);
2926
+ },
2927
+ getState() {
2928
+ return currentState;
2929
+ },
2930
+ get state$() {
2931
+ return stateSubject.asObservable();
2932
+ },
2933
+ get actions$() {
2934
+ return actionsSubject.asObservable();
2935
+ },
2936
+ select(selector) {
2937
+ return stateSubject.asObservable().pipe(select(selector));
2938
+ },
2939
+ init() {
2940
+ if (hasFatalError || isRunning) return;
2941
+ isRunning = true;
2942
+ startEffects();
2943
+ if (hasFatalError) return;
2944
+ dispatchInternal({ type: INTERNAL_ACTION_TYPES.init });
2945
+ },
2946
+ stop() {
2947
+ if (hasFatalError || !isRunning) return;
2948
+ dispatchInternal({ type: INTERNAL_ACTION_TYPES.stop });
2949
+ effectSubscriptions.unsubscribe();
2950
+ effectSubscriptions = new rxjs.Subscription();
2951
+ isRunning = false;
2952
+ }
2953
+ };
2954
+ }
2955
+
2956
+ //#endregion
2957
+ //#region src/threads.ts
2958
+ const THREADS_CHANNEL_EVENT = "thread_metadata";
2959
+ const THREAD_SUBSCRIBE_PATH = "/threads/subscribe";
2960
+ const MAX_SOCKET_RETRIES = 5;
2961
+ const REQUEST_TIMEOUT_MS = 15e3;
2962
+ const initialThreadState = {
2963
+ threads: [],
2964
+ isLoading: false,
2965
+ error: null,
2966
+ context: null,
2967
+ sessionId: 0,
2968
+ metadataCredentialsRequested: false
2969
+ };
2970
+ const threadAdapterEvents = createActionGroup("Thread Adapter", {
2971
+ started: empty(),
2972
+ stopped: empty(),
2973
+ contextChanged: props(),
2974
+ renameRequested: props(),
2975
+ archiveRequested: props(),
2976
+ deleteRequested: props()
2977
+ });
2978
+ const threadRestEvents = createActionGroup("Thread REST", {
2979
+ listRequested: props(),
2980
+ listSucceeded: props(),
2981
+ listFailed: props(),
2982
+ metadataCredentialsRequested: props(),
2983
+ metadataCredentialsSucceeded: props(),
2984
+ metadataCredentialsFailed: props(),
2985
+ mutationFinished: props()
2986
+ });
2987
+ const threadSocketEvents = createActionGroup("Thread Socket", {
2988
+ opened: props(),
2989
+ errored: props(),
2990
+ joinFailed: props(),
2991
+ joinTimedOut: props(),
2992
+ metadataReceived: props()
2993
+ });
2994
+ const threadDomainEvents = createActionGroup("Thread Domain", {
2995
+ threadUpserted: props(),
2996
+ threadDeleted: props()
2997
+ });
2998
+ function sortThreadsByUpdatedAt(threads) {
2999
+ return [...threads].sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
3000
+ }
3001
+ function upsertThread(threads, thread) {
3002
+ const existingIndex = threads.findIndex((item) => item.id === thread.id);
3003
+ if (existingIndex === -1) return sortThreadsByUpdatedAt([...threads, thread]);
3004
+ const next = [...threads];
3005
+ next[existingIndex] = thread;
3006
+ return sortThreadsByUpdatedAt(next);
3007
+ }
3008
+ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.contextChanged, (state, { context }) => ({
3009
+ ...state,
3010
+ context,
3011
+ sessionId: state.sessionId + 1,
3012
+ threads: [],
3013
+ isLoading: Boolean(context),
3014
+ error: null,
3015
+ metadataCredentialsRequested: false
3016
+ })), on(threadAdapterEvents.stopped, (state) => ({
3017
+ ...state,
3018
+ threads: [],
3019
+ isLoading: false,
3020
+ error: null,
3021
+ metadataCredentialsRequested: false
3022
+ })), on(threadRestEvents.listRequested, (state, { sessionId }) => {
3023
+ if (sessionId !== state.sessionId || !state.context) return state;
3024
+ return {
3025
+ ...state,
3026
+ isLoading: true,
3027
+ error: null
3028
+ };
3029
+ }), on(threadRestEvents.listSucceeded, (state, { sessionId, threads }) => {
3030
+ if (sessionId !== state.sessionId) return state;
3031
+ return {
3032
+ ...state,
3033
+ threads: sortThreadsByUpdatedAt(threads),
3034
+ isLoading: false,
3035
+ error: null
3036
+ };
3037
+ }), on(threadRestEvents.listFailed, (state, { sessionId, error }) => {
3038
+ if (sessionId !== state.sessionId) return state;
3039
+ return {
3040
+ ...state,
3041
+ isLoading: false,
3042
+ error
3043
+ };
3044
+ }), on(threadRestEvents.metadataCredentialsFailed, (state, { sessionId, error }) => {
3045
+ if (sessionId !== state.sessionId) return state;
3046
+ return {
3047
+ ...state,
3048
+ error
3049
+ };
3050
+ }), on(threadRestEvents.metadataCredentialsRequested, (state, { sessionId }) => {
3051
+ if (sessionId !== state.sessionId) return state;
3052
+ return {
3053
+ ...state,
3054
+ metadataCredentialsRequested: true
3055
+ };
3056
+ }), on(threadRestEvents.mutationFinished, (state, { outcome }) => ({
3057
+ ...state,
3058
+ error: outcome.ok ? state.error : outcome.error
3059
+ })), on(threadDomainEvents.threadUpserted, (state, { sessionId, thread }) => {
3060
+ if (sessionId !== state.sessionId) return state;
3061
+ return {
3062
+ ...state,
3063
+ threads: upsertThread(state.threads, thread)
3064
+ };
3065
+ }), on(threadDomainEvents.threadDeleted, (state, { sessionId, threadId }) => {
3066
+ if (sessionId !== state.sessionId) return state;
3067
+ return {
3068
+ ...state,
3069
+ threads: state.threads.filter((thread) => thread.id !== threadId)
3070
+ };
3071
+ }));
3072
+ const selectThreads = createSelector((state) => state.threads);
3073
+ const selectThreadsIsLoading = createSelector((state) => state.isLoading);
3074
+ const selectThreadsError = createSelector((state) => state.error);
3075
+ let threadRequestId = 0;
3076
+ function createThreadRequestId() {
3077
+ threadRequestId += 1;
3078
+ return `thread-request-${threadRequestId}`;
3079
+ }
3080
+ function createThreadFetchObservable(environment, context, sessionId) {
3081
+ return (0, rxjs.defer)(() => {
3082
+ const params = new URLSearchParams({
3083
+ userId: context.userId,
3084
+ agentId: context.agentId
2107
3085
  });
2108
- }
2109
- /**
2110
- * Reconnect to an existing thread by joining the Phoenix channel in
2111
- * "connect" mode and requesting the server replay history.
2112
- */
2113
- connect(input) {
2114
- return new rxjs.Observable((observer) => {
2115
- var _this$config$socketPa2;
2116
- this.threadId = input.threadId;
2117
- const socket = new phoenix.Socket(this.config.url, {
2118
- params: (_this$config$socketPa2 = this.config.socketParams) !== null && _this$config$socketPa2 !== void 0 ? _this$config$socketPa2 : {},
2119
- reconnectAfterMs: (0, _copilotkitnext_shared.phoenixExponentialBackoff)(100, 1e4),
2120
- rejoinAfterMs: (0, _copilotkitnext_shared.phoenixExponentialBackoff)(1e3, 3e4)
2121
- });
2122
- this.socket = socket;
2123
- socket.connect();
2124
- const channel = socket.channel(`agent:${input.threadId}`, { mode: "connect" });
2125
- this.activeChannel = channel;
2126
- channel.on(_copilotkitnext_shared.AG_UI_CHANNEL_EVENT, (payload) => {
2127
- observer.next(payload);
2128
- if (payload.type === _ag_ui_client.EventType.RUN_FINISHED || payload.type === _ag_ui_client.EventType.RUN_ERROR) {
2129
- observer.complete();
2130
- this.cleanup();
2131
- }
3086
+ return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}/threads?${params.toString()}`, {
3087
+ selector: (response) => {
3088
+ if (!response.ok) throw new Error(`Failed to fetch threads: ${response.status}`);
3089
+ return response.json();
3090
+ },
3091
+ fetch: environment.fetch,
3092
+ method: "GET",
3093
+ headers: { ...context.headers }
3094
+ }).pipe((0, rxjs_operators.timeout)({
3095
+ first: REQUEST_TIMEOUT_MS,
3096
+ with: () => {
3097
+ throw new Error("Request timed out");
3098
+ }
3099
+ }), (0, rxjs_operators.map)((data) => threadRestEvents.listSucceeded({
3100
+ sessionId,
3101
+ threads: data.threads
3102
+ })), (0, rxjs_operators.catchError)((error) => {
3103
+ return (0, rxjs.of)(threadRestEvents.listFailed({
3104
+ sessionId,
3105
+ error: error instanceof Error ? error : new Error(String(error))
3106
+ }));
3107
+ }));
3108
+ });
3109
+ }
3110
+ function createThreadMetadataCredentialsObservable(environment, context, sessionId) {
3111
+ return (0, rxjs.defer)(() => {
3112
+ return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}${THREAD_SUBSCRIBE_PATH}`, {
3113
+ selector: async (response) => {
3114
+ if (!response.ok) throw new Error(`Failed to fetch thread metadata credentials: ${response.status}`);
3115
+ return response.json();
3116
+ },
3117
+ fetch: environment.fetch,
3118
+ method: "POST",
3119
+ headers: {
3120
+ ...context.headers,
3121
+ "Content-Type": "application/json"
3122
+ },
3123
+ body: JSON.stringify({ userId: context.userId })
3124
+ }).pipe((0, rxjs_operators.timeout)({
3125
+ first: REQUEST_TIMEOUT_MS,
3126
+ with: () => {
3127
+ throw new Error("Request timed out");
3128
+ }
3129
+ }), (0, rxjs_operators.map)((data) => {
3130
+ if (typeof data.joinToken !== "string" || data.joinToken.length === 0) throw new Error("missing joinToken");
3131
+ return threadRestEvents.metadataCredentialsSucceeded({
3132
+ sessionId,
3133
+ joinToken: data.joinToken
2132
3134
  });
2133
- const MAX_CONSECUTIVE_ERRORS = 5;
2134
- let consecutiveErrors = 0;
2135
- socket.onError(() => {
2136
- consecutiveErrors++;
2137
- if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
2138
- observer.error(/* @__PURE__ */ new Error(`WebSocket connection failed after ${MAX_CONSECUTIVE_ERRORS} consecutive errors`));
2139
- this.cleanup();
3135
+ }), (0, rxjs_operators.catchError)((error) => {
3136
+ return (0, rxjs.of)(threadRestEvents.metadataCredentialsFailed({
3137
+ sessionId,
3138
+ error: error instanceof Error ? error : new Error(String(error))
3139
+ }));
3140
+ }));
3141
+ });
3142
+ }
3143
+ function createThreadMutationObservable(environment, context, request) {
3144
+ return (0, rxjs.defer)(() => {
3145
+ return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}${request.path}`, {
3146
+ selector: async (response) => {
3147
+ if (!response.ok) throw new Error(`Request failed: ${response.status}`);
3148
+ return null;
3149
+ },
3150
+ fetch: environment.fetch,
3151
+ method: request.method,
3152
+ headers: {
3153
+ ...context.headers,
3154
+ "Content-Type": "application/json"
3155
+ },
3156
+ body: JSON.stringify(request.body)
3157
+ }).pipe((0, rxjs_operators.map)(() => threadRestEvents.mutationFinished({ outcome: {
3158
+ requestId: request.requestId,
3159
+ ok: true
3160
+ } })), (0, rxjs_operators.catchError)((error) => {
3161
+ return (0, rxjs.of)(threadRestEvents.mutationFinished({ outcome: {
3162
+ requestId: request.requestId,
3163
+ ok: false,
3164
+ error: error instanceof Error ? error : new Error(String(error))
3165
+ } }));
3166
+ }));
3167
+ });
3168
+ }
3169
+ function createThreadStore(environment) {
3170
+ const store = createStore({
3171
+ reducer: threadReducer,
3172
+ effects: [
3173
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadAdapterEvents.contextChanged), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([, state]) => Boolean(state.context)), (0, rxjs_operators.map)(([, state]) => threadRestEvents.listRequested({ sessionId: state.sessionId })))),
3174
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadRestEvents.listRequested), (0, rxjs_operators.switchMap)((action) => state$.pipe((0, rxjs_operators.map)((state) => state.context), (0, rxjs_operators.filter)((context) => Boolean(context)), (0, rxjs_operators.take)(1), (0, rxjs_operators.map)((context) => ({
3175
+ action,
3176
+ context
3177
+ })), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped))), (0, rxjs_operators.switchMap)(({ action: currentAction, context }) => createThreadFetchObservable(environment, context, currentAction.sessionId)))))),
3178
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadRestEvents.listSucceeded), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => {
3179
+ var _state$context;
3180
+ return action.sessionId === state.sessionId && !state.metadataCredentialsRequested && Boolean((_state$context = state.context) === null || _state$context === void 0 ? void 0 : _state$context.wsUrl);
3181
+ }), (0, rxjs_operators.map)(([action]) => threadRestEvents.metadataCredentialsRequested({ sessionId: action.sessionId })))),
3182
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadRestEvents.metadataCredentialsRequested), (0, rxjs_operators.switchMap)((action) => state$.pipe((0, rxjs_operators.map)((state) => state.context), (0, rxjs_operators.filter)((context) => Boolean(context)), (0, rxjs_operators.take)(1), (0, rxjs_operators.map)((context) => ({
3183
+ action,
3184
+ context
3185
+ })), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped))), (0, rxjs_operators.switchMap)(({ action: currentAction, context }) => createThreadMetadataCredentialsObservable(environment, context, currentAction.sessionId)))))),
3186
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadRestEvents.metadataCredentialsSucceeded), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => {
3187
+ var _state$context2;
3188
+ return action.sessionId === state.sessionId && Boolean((_state$context2 = state.context) === null || _state$context2 === void 0 ? void 0 : _state$context2.wsUrl);
3189
+ }), (0, rxjs_operators.switchMap)(([action, state]) => {
3190
+ const context = state.context;
3191
+ const joinToken = action.joinToken;
3192
+ const shutdown$ = actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped));
3193
+ return (0, rxjs.defer)(() => {
3194
+ const socket$ = ɵphoenixSocket$({
3195
+ url: context.wsUrl,
3196
+ options: {
3197
+ params: { join_token: joinToken },
3198
+ reconnectAfterMs: (0, _copilotkitnext_shared.phoenixExponentialBackoff)(100, 1e4),
3199
+ rejoinAfterMs: (0, _copilotkitnext_shared.phoenixExponentialBackoff)(1e3, 3e4)
3200
+ }
3201
+ }).pipe((0, rxjs_operators.shareReplay)({
3202
+ bufferSize: 1,
3203
+ refCount: true
3204
+ }));
3205
+ const channel$ = ɵphoenixChannel$({
3206
+ socket$,
3207
+ topic: `user_meta:${context.userId}`
3208
+ }).pipe((0, rxjs_operators.shareReplay)({
3209
+ bufferSize: 1,
3210
+ refCount: true
3211
+ }));
3212
+ const socketSignals$ = ɵobservePhoenixSocketSignals$(socket$).pipe((0, rxjs_operators.share)());
3213
+ const fatalSocketShutdown$ = ɵobservePhoenixSocketHealth$(socketSignals$, MAX_SOCKET_RETRIES).pipe((0, rxjs_operators.catchError)(() => {
3214
+ console.warn(`[threads] WebSocket failed after ${MAX_SOCKET_RETRIES} attempts, giving up`);
3215
+ return (0, rxjs.of)(void 0);
3216
+ }), (0, rxjs_operators.share)());
3217
+ return (0, rxjs.merge)(socketSignals$.pipe((0, rxjs_operators.map)((signal) => signal.type === "open" ? threadSocketEvents.opened({ sessionId: action.sessionId }) : threadSocketEvents.errored({ sessionId: action.sessionId }))), channel$.pipe((0, rxjs_operators.switchMap)(({ channel }) => ɵobservePhoenixEvent$(channel, THREADS_CHANNEL_EVENT)), (0, rxjs_operators.map)((payload) => threadSocketEvents.metadataReceived({
3218
+ sessionId: action.sessionId,
3219
+ payload
3220
+ }))), ɵobservePhoenixJoinOutcome$(channel$).pipe((0, rxjs_operators.filter)((outcome) => outcome.type !== "joined"), (0, rxjs_operators.map)((outcome) => outcome.type === "timeout" ? threadSocketEvents.joinTimedOut({ sessionId: action.sessionId }) : threadSocketEvents.joinFailed({ sessionId: action.sessionId })))).pipe((0, rxjs_operators.takeUntil)((0, rxjs.merge)(shutdown$, fatalSocketShutdown$)));
3221
+ });
3222
+ }))),
3223
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadSocketEvents.metadataReceived), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => {
3224
+ var _state$context3;
3225
+ return action.sessionId === state.sessionId && action.payload.userId === ((_state$context3 = state.context) === null || _state$context3 === void 0 ? void 0 : _state$context3.userId);
3226
+ }), (0, rxjs_operators.map)(([action]) => {
3227
+ if (action.payload.operation === "deleted") return threadDomainEvents.threadDeleted({
3228
+ sessionId: action.sessionId,
3229
+ threadId: action.payload.deleted.id
3230
+ });
3231
+ return threadDomainEvents.threadUpserted({
3232
+ sessionId: action.sessionId,
3233
+ thread: action.payload.thread
3234
+ });
3235
+ }))),
3236
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadAdapterEvents.renameRequested, threadAdapterEvents.archiveRequested, threadAdapterEvents.deleteRequested), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.mergeMap)(([action, state]) => {
3237
+ const context = state.context;
3238
+ if (!(context === null || context === void 0 ? void 0 : context.runtimeUrl)) {
3239
+ const requestId = action.requestId;
3240
+ return (0, rxjs.of)(threadRestEvents.mutationFinished({ outcome: {
3241
+ requestId,
3242
+ ok: false,
3243
+ error: /* @__PURE__ */ new Error("Runtime URL is not configured")
3244
+ } }));
2140
3245
  }
2141
- });
2142
- socket.onOpen(() => {
2143
- consecutiveErrors = 0;
2144
- });
2145
- channel.onError(() => {});
2146
- channel.join().receive("ok", () => {
2147
- channel.push(_ag_ui_client.EventType.CUSTOM, {
2148
- type: _ag_ui_client.EventType.CUSTOM,
2149
- name: "connect",
2150
- value: { threadId: input.threadId }
3246
+ const commonBody = {
3247
+ userId: context.userId,
3248
+ agentId: context.agentId
3249
+ };
3250
+ if (threadAdapterEvents.renameRequested.match(action)) return createThreadMutationObservable(environment, context, {
3251
+ requestId: action.requestId,
3252
+ method: "PATCH",
3253
+ path: `/threads/${encodeURIComponent(action.threadId)}`,
3254
+ body: {
3255
+ ...commonBody,
3256
+ name: action.name
3257
+ }
2151
3258
  });
2152
- }).receive("error", (resp) => {
2153
- observer.error(/* @__PURE__ */ new Error(`Failed to join channel: ${JSON.stringify(resp)}`));
2154
- this.cleanup();
2155
- }).receive("timeout", () => {
2156
- observer.error(/* @__PURE__ */ new Error("Timed out joining channel"));
2157
- this.cleanup();
2158
- });
2159
- return () => {
2160
- this.cleanup();
2161
- };
3259
+ if (threadAdapterEvents.archiveRequested.match(action)) return createThreadMutationObservable(environment, context, {
3260
+ requestId: action.requestId,
3261
+ method: "POST",
3262
+ path: `/threads/${encodeURIComponent(action.threadId)}/archive`,
3263
+ body: commonBody
3264
+ });
3265
+ return createThreadMutationObservable(environment, context, {
3266
+ requestId: action.requestId,
3267
+ method: "DELETE",
3268
+ path: `/threads/${encodeURIComponent(action.threadId)}`,
3269
+ body: commonBody
3270
+ });
3271
+ })))
3272
+ ]
3273
+ });
3274
+ function trackMutation(dispatchAction) {
3275
+ const resultPromise = (0, rxjs.firstValueFrom)((0, rxjs.merge)(store.actions$.pipe(ofType(threadRestEvents.mutationFinished), (0, rxjs_operators.filter)((action) => action.outcome.requestId === dispatchAction.requestId), (0, rxjs_operators.map)((action) => action.outcome)), store.actions$.pipe(ofType(threadAdapterEvents.stopped), (0, rxjs_operators.map)(() => ({
3276
+ requestId: dispatchAction.requestId,
3277
+ ok: false,
3278
+ error: /* @__PURE__ */ new Error("Thread store stopped before mutation completed")
3279
+ })))).pipe((0, rxjs_operators.take)(1))).then((outcome) => {
3280
+ if (outcome.ok) return;
3281
+ throw outcome.error;
2162
3282
  });
2163
- }
2164
- cleanup() {
2165
- if (this.activeChannel) {
2166
- this.activeChannel.leave();
2167
- this.activeChannel = null;
2168
- }
2169
- if (this.socket) {
2170
- this.socket.disconnect();
2171
- this.socket = null;
2172
- }
2173
- }
2174
- };
3283
+ store.dispatch(dispatchAction);
3284
+ return resultPromise;
3285
+ }
3286
+ return {
3287
+ start() {
3288
+ store.init();
3289
+ store.dispatch(threadAdapterEvents.started());
3290
+ },
3291
+ stop() {
3292
+ store.dispatch(threadAdapterEvents.stopped());
3293
+ store.stop();
3294
+ },
3295
+ setContext(context) {
3296
+ store.dispatch(threadAdapterEvents.contextChanged({ context }));
3297
+ },
3298
+ renameThread(threadId, name) {
3299
+ return trackMutation(threadAdapterEvents.renameRequested({
3300
+ requestId: createThreadRequestId(),
3301
+ threadId,
3302
+ name
3303
+ }));
3304
+ },
3305
+ archiveThread(threadId) {
3306
+ return trackMutation(threadAdapterEvents.archiveRequested({
3307
+ requestId: createThreadRequestId(),
3308
+ threadId
3309
+ }));
3310
+ },
3311
+ deleteThread(threadId) {
3312
+ return trackMutation(threadAdapterEvents.deleteRequested({
3313
+ requestId: createThreadRequestId(),
3314
+ threadId
3315
+ }));
3316
+ },
3317
+ getState() {
3318
+ return store.getState();
3319
+ },
3320
+ select: store.select.bind(store)
3321
+ };
3322
+ }
3323
+ const ɵthreadAdapterEvents = threadAdapterEvents;
3324
+ const ɵselectThreads = selectThreads;
3325
+ const ɵselectThreadsIsLoading = selectThreadsIsLoading;
3326
+ const ɵselectThreadsError = selectThreadsError;
2175
3327
 
2176
3328
  //#endregion
2177
3329
  exports.AgentRegistry = AgentRegistry;
@@ -2186,6 +3338,28 @@ exports.StateManager = StateManager;
2186
3338
  exports.SuggestionEngine = SuggestionEngine;
2187
3339
  exports.ToolCallStatus = ToolCallStatus;
2188
3340
  exports.completePartialMarkdown = completePartialMarkdown;
3341
+ exports.createActionGroup = createActionGroup;
3342
+ exports.createEffect = createEffect;
3343
+ exports.createReducer = createReducer;
3344
+ exports.createSelector = createSelector;
3345
+ exports.createStore = createStore;
3346
+ exports.empty = empty;
2189
3347
  exports.ensureObjectArgs = ensureObjectArgs;
3348
+ exports.ofType = ofType;
3349
+ exports.on = on;
3350
+ exports.props = props;
3351
+ exports.select = select;
3352
+ exports.ɵcreateThreadStore = createThreadStore;
3353
+ exports.ɵjoinPhoenixChannel$ = ɵjoinPhoenixChannel$;
3354
+ exports.ɵobservePhoenixEvent$ = ɵobservePhoenixEvent$;
3355
+ exports.ɵobservePhoenixJoinOutcome$ = ɵobservePhoenixJoinOutcome$;
3356
+ exports.ɵobservePhoenixSocketHealth$ = ɵobservePhoenixSocketHealth$;
3357
+ exports.ɵobservePhoenixSocketSignals$ = ɵobservePhoenixSocketSignals$;
3358
+ exports.ɵphoenixChannel$ = ɵphoenixChannel$;
3359
+ exports.ɵphoenixSocket$ = ɵphoenixSocket$;
3360
+ exports.ɵselectThreads = ɵselectThreads;
3361
+ exports.ɵselectThreadsError = ɵselectThreadsError;
3362
+ exports.ɵselectThreadsIsLoading = ɵselectThreadsIsLoading;
3363
+ exports.ɵthreadAdapterEvents = ɵthreadAdapterEvents;
2190
3364
  });
2191
3365
  //# sourceMappingURL=index.umd.js.map