@copilotkit/core 1.56.1 → 1.56.2-canary.pin-to-send
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.cjs +192 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +84 -20
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +84 -20
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +192 -37
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +197 -42
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Throttler } from "@tanstack/pacer";
|
|
1
2
|
import { AbstractAgent, EventType, HttpAgent, randomUUID, runHttpRequest, structuredClone_, transformChunks, transformHttpEventStream } from "@ag-ui/client";
|
|
2
3
|
import { RUNTIME_MODE_INTELLIGENCE, RUNTIME_MODE_SSE, logger, partialJSONParse, phoenixExponentialBackoff, randomUUID as randomUUID$1, resolveDebugConfig, schemaToJsonSchema } from "@copilotkit/shared";
|
|
3
4
|
import { BehaviorSubject, EMPTY, NEVER, Notification, Observable, Subject, Subscription, asapScheduler, concat, defer, dematerialize, firstValueFrom, from, lastValueFrom, merge, of, switchMap, throwError } from "rxjs";
|
|
@@ -137,7 +138,7 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
137
138
|
config;
|
|
138
139
|
socket = null;
|
|
139
140
|
activeChannel = null;
|
|
140
|
-
|
|
141
|
+
canonicalRunId = null;
|
|
141
142
|
sharedState;
|
|
142
143
|
constructor(config, sharedState = { lastSeenEventIds: /* @__PURE__ */ new Map() }) {
|
|
143
144
|
super();
|
|
@@ -175,7 +176,11 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
175
176
|
try {
|
|
176
177
|
this.isRunning = true;
|
|
177
178
|
this.agentId = this.agentId ?? randomUUID();
|
|
178
|
-
const
|
|
179
|
+
const effectiveParameters = parameters?.runId || !this.canonicalRunId ? parameters : {
|
|
180
|
+
...parameters,
|
|
181
|
+
runId: this.canonicalRunId
|
|
182
|
+
};
|
|
183
|
+
const input = this.prepareRunAgentInput(effectiveParameters);
|
|
179
184
|
let result;
|
|
180
185
|
const previousMessageIds = new Set(this.messages.map((m) => m.id));
|
|
181
186
|
const subscribers = [
|
|
@@ -214,14 +219,14 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
214
219
|
}
|
|
215
220
|
}
|
|
216
221
|
abortRun() {
|
|
217
|
-
if (this.activeChannel && this.
|
|
222
|
+
if (this.activeChannel && this.canonicalRunId) {
|
|
218
223
|
const fallback = setTimeout(() => clear(), 5e3);
|
|
219
224
|
const clear = () => {
|
|
220
225
|
clearTimeout(fallback);
|
|
221
226
|
this.detachActiveRun();
|
|
222
227
|
this.cleanup();
|
|
223
228
|
};
|
|
224
|
-
this.activeChannel.push(STOP_RUN_EVENT, { run_id: this.
|
|
229
|
+
this.activeChannel.push(STOP_RUN_EVENT, { run_id: this.canonicalRunId }).receive("ok", clear).receive("error", clear).receive("timeout", clear);
|
|
225
230
|
} else {
|
|
226
231
|
this.detachActiveRun();
|
|
227
232
|
this.cleanup();
|
|
@@ -233,7 +238,7 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
233
238
|
*/
|
|
234
239
|
run(input) {
|
|
235
240
|
this.threadId = input.threadId;
|
|
236
|
-
this.
|
|
241
|
+
this.canonicalRunId = input.runId;
|
|
237
242
|
return defer(() => this.requestJoinCredentials$("run", input)).pipe(switchMap((credentials) => this.observeThread$(input, credentials, {
|
|
238
243
|
completeOnRunError: false,
|
|
239
244
|
streamMode: "run"
|
|
@@ -245,16 +250,14 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
245
250
|
*/
|
|
246
251
|
connect(input) {
|
|
247
252
|
this.threadId = input.threadId;
|
|
248
|
-
this.
|
|
253
|
+
this.canonicalRunId = input.runId;
|
|
249
254
|
return defer(() => this.requestConnectPlan$(input)).pipe(switchMap((plan) => {
|
|
250
255
|
if (plan === null) return EMPTY;
|
|
251
256
|
if (plan.mode === "bootstrap") {
|
|
252
257
|
this.setLastSeenEventId(input.threadId, plan.latestEventId);
|
|
253
|
-
for (const event of plan.events) this.updateRunIdFromEvent(event);
|
|
254
258
|
return from(plan.events);
|
|
255
259
|
}
|
|
256
260
|
this.setLastSeenEventId(input.threadId, plan.joinFromEventId);
|
|
257
|
-
for (const event of plan.events) this.updateRunIdFromEvent(event);
|
|
258
261
|
return concat(from(plan.events), this.observeThread$(input, { joinToken: plan.joinToken }, {
|
|
259
262
|
completeOnRunError: true,
|
|
260
263
|
streamMode: "connect",
|
|
@@ -277,7 +280,7 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
277
280
|
if (this.socket === ownSocket) this.socket = null;
|
|
278
281
|
}
|
|
279
282
|
if (this.threadId) this.sharedState.lastSeenEventIds.delete(this.threadId);
|
|
280
|
-
this.
|
|
283
|
+
this.canonicalRunId = null;
|
|
281
284
|
}
|
|
282
285
|
cleanup() {
|
|
283
286
|
this.cleanupOwned(this.activeChannel, this.socket);
|
|
@@ -413,7 +416,6 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
413
416
|
observeThreadEvents$(threadId, channel$, options) {
|
|
414
417
|
return channel$.pipe(switchMap$1(({ channel }) => this.observeChannelEvent$(channel, CLIENT_AG_UI_EVENT)), tap((payload) => {
|
|
415
418
|
this.updateLastSeenEventId(threadId, payload);
|
|
416
|
-
this.updateRunIdFromEvent(payload);
|
|
417
419
|
}), mergeMap((payload) => from(this.createThreadNotifications(payload, options.completeOnRunError))), dematerialize());
|
|
418
420
|
}
|
|
419
421
|
observeChannelEvent$(channel, eventName) {
|
|
@@ -463,23 +465,6 @@ var IntelligenceAgent = class IntelligenceAgent extends AbstractAgent {
|
|
|
463
465
|
if (!eventId) return;
|
|
464
466
|
this.sharedState.lastSeenEventIds.set(threadId, eventId);
|
|
465
467
|
}
|
|
466
|
-
/**
|
|
467
|
-
* Keep `this.runId` in sync with the backend's actual run ID.
|
|
468
|
-
*
|
|
469
|
-
* During a `connect` (resume) flow the client generates a fresh `runId`
|
|
470
|
-
* via `prepareRunAgentInput`, but the backend is running under its own
|
|
471
|
-
* run ID. If the client later sends `STOP_RUN_EVENT` with the wrong
|
|
472
|
-
* `runId`, the gateway's runner channel will not match it and the agent
|
|
473
|
-
* keeps running. Extracting the run ID from live events fixes this.
|
|
474
|
-
*
|
|
475
|
-
* The runner normalises events to `run_id` (snake_case) before pushing
|
|
476
|
-
* to the gateway, so we check both `runId` and `run_id`.
|
|
477
|
-
*/
|
|
478
|
-
updateRunIdFromEvent(payload) {
|
|
479
|
-
const record = payload;
|
|
480
|
-
const eventRunId = record.runId ?? record.run_id;
|
|
481
|
-
if (typeof eventRunId === "string" && eventRunId.length > 0) this.runId = eventRunId;
|
|
482
|
-
}
|
|
483
468
|
readEventId(payload) {
|
|
484
469
|
const metadata = payload.metadata;
|
|
485
470
|
if (!metadata || typeof metadata !== "object") return null;
|
|
@@ -2308,8 +2293,21 @@ let CopilotKitCoreErrorCode = /* @__PURE__ */ function(CopilotKitCoreErrorCode)
|
|
|
2308
2293
|
CopilotKitCoreErrorCode["TRANSCRIPTION_RATE_LIMITED"] = "transcription_rate_limited";
|
|
2309
2294
|
CopilotKitCoreErrorCode["TRANSCRIPTION_AUTH_FAILED"] = "transcription_auth_failed";
|
|
2310
2295
|
CopilotKitCoreErrorCode["TRANSCRIPTION_NETWORK_ERROR"] = "transcription_network_error";
|
|
2296
|
+
CopilotKitCoreErrorCode["SUBSCRIBER_CALLBACK_FAILED"] = "subscriber_callback_failed";
|
|
2311
2297
|
return CopilotKitCoreErrorCode;
|
|
2312
2298
|
}({});
|
|
2299
|
+
/**
|
|
2300
|
+
* Runtime allowlist derived from {@link SUBSCRIBE_TO_AGENT_KEYS}. Hoisted
|
|
2301
|
+
* to module scope so the Set is allocated once, not per-subscription.
|
|
2302
|
+
*/
|
|
2303
|
+
const ALLOWED_KEYS = new Set([
|
|
2304
|
+
"onMessagesChanged",
|
|
2305
|
+
"onStateChanged",
|
|
2306
|
+
"onRunInitialized",
|
|
2307
|
+
"onRunFinalized",
|
|
2308
|
+
"onRunFailed",
|
|
2309
|
+
"onRunErrorEvent"
|
|
2310
|
+
]);
|
|
2313
2311
|
let CopilotKitCoreRuntimeConnectionStatus = /* @__PURE__ */ function(CopilotKitCoreRuntimeConnectionStatus) {
|
|
2314
2312
|
CopilotKitCoreRuntimeConnectionStatus["Disconnected"] = "disconnected";
|
|
2315
2313
|
CopilotKitCoreRuntimeConnectionStatus["Connected"] = "connected";
|
|
@@ -2375,6 +2373,16 @@ var CopilotKitCore = class {
|
|
|
2375
2373
|
}), "Subscriber onError error:");
|
|
2376
2374
|
}
|
|
2377
2375
|
/**
|
|
2376
|
+
* Log a message to the console and emit an error to subscribers.
|
|
2377
|
+
* Catches failures from `emitError` itself to prevent unhandled rejections.
|
|
2378
|
+
*/
|
|
2379
|
+
logAndEmitError(message, params, logLevel = "error") {
|
|
2380
|
+
console[logLevel](message, params.error);
|
|
2381
|
+
this.emitError(params).catch((emitErr) => {
|
|
2382
|
+
console.error(message + " — emitError itself failed:", emitErr);
|
|
2383
|
+
});
|
|
2384
|
+
}
|
|
2385
|
+
/**
|
|
2378
2386
|
* Snapshot accessors
|
|
2379
2387
|
*/
|
|
2380
2388
|
get context() {
|
|
@@ -2411,17 +2419,30 @@ var CopilotKitCore = class {
|
|
|
2411
2419
|
return this._properties;
|
|
2412
2420
|
}
|
|
2413
2421
|
/**
|
|
2414
|
-
* Default throttle interval (ms)
|
|
2415
|
-
*
|
|
2416
|
-
* `
|
|
2417
|
-
* or `<CopilotChat>` overrides this default and disables throttling.
|
|
2422
|
+
* Default throttle interval (ms) used by `subscribeToAgentWithOptions()`
|
|
2423
|
+
* when the caller does not specify an explicit `throttleMs`.
|
|
2424
|
+
* `undefined` means no default is configured; `0` means no throttling.
|
|
2418
2425
|
*/
|
|
2419
2426
|
get defaultThrottleMs() {
|
|
2420
2427
|
return this._defaultThrottleMs;
|
|
2421
2428
|
}
|
|
2429
|
+
/**
|
|
2430
|
+
* Set the default throttle interval (ms) for `subscribeToAgentWithOptions()`.
|
|
2431
|
+
*
|
|
2432
|
+
* Accepts a non-negative finite number or `undefined` (to clear the
|
|
2433
|
+
* default). Invalid values (NaN, Infinity, negative) are logged as
|
|
2434
|
+
* errors and ignored — the previous valid value is preserved.
|
|
2435
|
+
*/
|
|
2422
2436
|
setDefaultThrottleMs(value) {
|
|
2423
2437
|
if (value !== void 0 && (!Number.isFinite(value) || value < 0)) {
|
|
2424
|
-
this.
|
|
2438
|
+
this.logAndEmitError(`CopilotKitCore.setDefaultThrottleMs: value must be a non-negative finite number or undefined, got ${value}. Keeping current value (${this._defaultThrottleMs}).`, {
|
|
2439
|
+
error: /* @__PURE__ */ new Error(`setDefaultThrottleMs: invalid value (${value}), keeping current value (${this._defaultThrottleMs})`),
|
|
2440
|
+
code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,
|
|
2441
|
+
context: {
|
|
2442
|
+
value,
|
|
2443
|
+
currentValue: this._defaultThrottleMs
|
|
2444
|
+
}
|
|
2445
|
+
});
|
|
2425
2446
|
return;
|
|
2426
2447
|
}
|
|
2427
2448
|
this._defaultThrottleMs = value;
|
|
@@ -2542,6 +2563,137 @@ var CopilotKitCore = class {
|
|
|
2542
2563
|
} };
|
|
2543
2564
|
}
|
|
2544
2565
|
/**
|
|
2566
|
+
* Subscribe to an agent's notification and lifecycle events with
|
|
2567
|
+
* optional configuration (e.g. throttling).
|
|
2568
|
+
*
|
|
2569
|
+
* Wraps every callback with error protection (`safeCall`) and applies
|
|
2570
|
+
* the options before delegating to `agent.subscribe()`.
|
|
2571
|
+
*
|
|
2572
|
+
* See {@link SubscribeToAgentSubscriber} for the accepted callback subset
|
|
2573
|
+
* and the rationale for excluding AG-UI event handlers.
|
|
2574
|
+
*/
|
|
2575
|
+
subscribeToAgentWithOptions(agent, subscriber, options) {
|
|
2576
|
+
const resolved = options?.throttleMs ?? this._defaultThrottleMs ?? 0;
|
|
2577
|
+
let effectiveMs = 0;
|
|
2578
|
+
if (!Number.isFinite(resolved) || resolved < 0) {
|
|
2579
|
+
const source = options?.throttleMs !== void 0 ? "throttleMs" : "defaultThrottleMs";
|
|
2580
|
+
this.logAndEmitError(`CopilotKitCore.subscribeToAgentWithOptions: ${source} must be a non-negative finite number, got ${resolved}. Falling back to unthrottled.`, {
|
|
2581
|
+
error: /* @__PURE__ */ new Error(`subscribeToAgentWithOptions: invalid ${source} (${resolved}), falling back to unthrottled`),
|
|
2582
|
+
code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,
|
|
2583
|
+
context: {
|
|
2584
|
+
agentId: agent.agentId,
|
|
2585
|
+
source,
|
|
2586
|
+
value: resolved
|
|
2587
|
+
}
|
|
2588
|
+
});
|
|
2589
|
+
} else effectiveMs = resolved;
|
|
2590
|
+
const agentLabel = agent.agentId || "(unknown agent)";
|
|
2591
|
+
const safeCall = (label, fn, ...args) => {
|
|
2592
|
+
const reportError = (err, verb) => {
|
|
2593
|
+
this.logAndEmitError(`CopilotKitCore.subscribeToAgentWithOptions[${agentLabel}]: ${label} callback ${verb}:`, {
|
|
2594
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
2595
|
+
code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,
|
|
2596
|
+
context: {
|
|
2597
|
+
agentId: agent.agentId,
|
|
2598
|
+
callback: label
|
|
2599
|
+
}
|
|
2600
|
+
});
|
|
2601
|
+
};
|
|
2602
|
+
try {
|
|
2603
|
+
const result = fn(...args);
|
|
2604
|
+
if (result instanceof Promise) return result.catch((err) => {
|
|
2605
|
+
reportError(err, "rejected");
|
|
2606
|
+
});
|
|
2607
|
+
return result;
|
|
2608
|
+
} catch (err) {
|
|
2609
|
+
reportError(err, "threw");
|
|
2610
|
+
}
|
|
2611
|
+
};
|
|
2612
|
+
const guardAll = (sub) => {
|
|
2613
|
+
const guarded = {};
|
|
2614
|
+
if (sub.onMessagesChanged) {
|
|
2615
|
+
const fn = sub.onMessagesChanged;
|
|
2616
|
+
guarded.onMessagesChanged = (params) => safeCall("onMessagesChanged", fn, params);
|
|
2617
|
+
}
|
|
2618
|
+
if (sub.onStateChanged) {
|
|
2619
|
+
const fn = sub.onStateChanged;
|
|
2620
|
+
guarded.onStateChanged = (params) => safeCall("onStateChanged", fn, params);
|
|
2621
|
+
}
|
|
2622
|
+
if (sub.onRunInitialized) {
|
|
2623
|
+
const fn = sub.onRunInitialized;
|
|
2624
|
+
guarded.onRunInitialized = (params) => safeCall("onRunInitialized", fn, params);
|
|
2625
|
+
}
|
|
2626
|
+
if (sub.onRunFinalized) {
|
|
2627
|
+
const fn = sub.onRunFinalized;
|
|
2628
|
+
guarded.onRunFinalized = (params) => safeCall("onRunFinalized", fn, params);
|
|
2629
|
+
}
|
|
2630
|
+
if (sub.onRunFailed) {
|
|
2631
|
+
const fn = sub.onRunFailed;
|
|
2632
|
+
guarded.onRunFailed = (params) => safeCall("onRunFailed", fn, params);
|
|
2633
|
+
}
|
|
2634
|
+
if (sub.onRunErrorEvent) {
|
|
2635
|
+
const fn = sub.onRunErrorEvent;
|
|
2636
|
+
guarded.onRunErrorEvent = (params) => safeCall("onRunErrorEvent", fn, params);
|
|
2637
|
+
}
|
|
2638
|
+
return guarded;
|
|
2639
|
+
};
|
|
2640
|
+
for (const key of Object.keys(subscriber)) if (typeof subscriber[key] === "function" && !ALLOWED_KEYS.has(key)) {
|
|
2641
|
+
const message = `CopilotKitCore.subscribeToAgentWithOptions[${agentLabel}]: callback "${key}" is not supported and was dropped. Supported callbacks: ${Array.from(ALLOWED_KEYS).join(", ")}. Use agent.subscribe() directly for event handlers and per-item notifications.`;
|
|
2642
|
+
this.logAndEmitError(message, {
|
|
2643
|
+
error: new Error(message),
|
|
2644
|
+
code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,
|
|
2645
|
+
context: {
|
|
2646
|
+
agentId: agent.agentId,
|
|
2647
|
+
droppedCallback: key
|
|
2648
|
+
}
|
|
2649
|
+
}, "warn");
|
|
2650
|
+
}
|
|
2651
|
+
if (effectiveMs <= 0) {
|
|
2652
|
+
const subscription = agent.subscribe(guardAll(subscriber));
|
|
2653
|
+
return { unsubscribe: () => subscription.unsubscribe() };
|
|
2654
|
+
}
|
|
2655
|
+
let active = true;
|
|
2656
|
+
let latestMessagesParams = null;
|
|
2657
|
+
let latestStateParams = null;
|
|
2658
|
+
const flushPending = () => {
|
|
2659
|
+
if (active && subscriber.onMessagesChanged && latestMessagesParams) {
|
|
2660
|
+
const params = latestMessagesParams;
|
|
2661
|
+
latestMessagesParams = null;
|
|
2662
|
+
safeCall("onMessagesChanged", subscriber.onMessagesChanged, params);
|
|
2663
|
+
}
|
|
2664
|
+
if (active && subscriber.onStateChanged && latestStateParams) {
|
|
2665
|
+
const params = latestStateParams;
|
|
2666
|
+
latestStateParams = null;
|
|
2667
|
+
safeCall("onStateChanged", subscriber.onStateChanged, params);
|
|
2668
|
+
}
|
|
2669
|
+
};
|
|
2670
|
+
const throttler = new Throttler(flushPending, {
|
|
2671
|
+
wait: effectiveMs,
|
|
2672
|
+
leading: true,
|
|
2673
|
+
trailing: true
|
|
2674
|
+
});
|
|
2675
|
+
const lifecycleOnly = {};
|
|
2676
|
+
if (subscriber.onRunInitialized) lifecycleOnly.onRunInitialized = subscriber.onRunInitialized;
|
|
2677
|
+
if (subscriber.onRunFinalized) lifecycleOnly.onRunFinalized = subscriber.onRunFinalized;
|
|
2678
|
+
if (subscriber.onRunFailed) lifecycleOnly.onRunFailed = subscriber.onRunFailed;
|
|
2679
|
+
if (subscriber.onRunErrorEvent) lifecycleOnly.onRunErrorEvent = subscriber.onRunErrorEvent;
|
|
2680
|
+
const wrappedSubscriber = guardAll(lifecycleOnly);
|
|
2681
|
+
if (subscriber.onMessagesChanged) wrappedSubscriber.onMessagesChanged = (params) => {
|
|
2682
|
+
latestMessagesParams = params;
|
|
2683
|
+
throttler.maybeExecute();
|
|
2684
|
+
};
|
|
2685
|
+
if (subscriber.onStateChanged) wrappedSubscriber.onStateChanged = (params) => {
|
|
2686
|
+
latestStateParams = params;
|
|
2687
|
+
throttler.maybeExecute();
|
|
2688
|
+
};
|
|
2689
|
+
const subscription = agent.subscribe(wrappedSubscriber);
|
|
2690
|
+
return { unsubscribe: () => {
|
|
2691
|
+
active = false;
|
|
2692
|
+
throttler.cancel();
|
|
2693
|
+
subscription.unsubscribe();
|
|
2694
|
+
} };
|
|
2695
|
+
}
|
|
2696
|
+
/**
|
|
2545
2697
|
* Agent connectivity (delegated to RunHandler)
|
|
2546
2698
|
*/
|
|
2547
2699
|
async connectAgent(params) {
|
|
@@ -3088,15 +3240,18 @@ const threadDomainEvents = createActionGroup("Thread Domain", {
|
|
|
3088
3240
|
threadUpserted: props(),
|
|
3089
3241
|
threadDeleted: props()
|
|
3090
3242
|
});
|
|
3091
|
-
function
|
|
3092
|
-
return [...threads].sort((left, right) =>
|
|
3243
|
+
function sortThreadsByRecency(threads) {
|
|
3244
|
+
return [...threads].sort((left, right) => {
|
|
3245
|
+
const leftKey = left.lastRunAt ?? left.updatedAt ?? left.createdAt;
|
|
3246
|
+
return (right.lastRunAt ?? right.updatedAt ?? right.createdAt).localeCompare(leftKey);
|
|
3247
|
+
});
|
|
3093
3248
|
}
|
|
3094
3249
|
function upsertThread(threads, thread) {
|
|
3095
3250
|
const existingIndex = threads.findIndex((item) => item.id === thread.id);
|
|
3096
|
-
if (existingIndex === -1) return
|
|
3251
|
+
if (existingIndex === -1) return sortThreadsByRecency([...threads, thread]);
|
|
3097
3252
|
const next = [...threads];
|
|
3098
3253
|
next[existingIndex] = thread;
|
|
3099
|
-
return
|
|
3254
|
+
return sortThreadsByRecency(next);
|
|
3100
3255
|
}
|
|
3101
3256
|
const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.contextChanged, (state, { context }) => ({
|
|
3102
3257
|
...state,
|
|
@@ -3129,7 +3284,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
|
|
|
3129
3284
|
if (sessionId !== state.sessionId) return state;
|
|
3130
3285
|
return {
|
|
3131
3286
|
...state,
|
|
3132
|
-
threads:
|
|
3287
|
+
threads: sortThreadsByRecency(threads),
|
|
3133
3288
|
isLoading: false,
|
|
3134
3289
|
error: null,
|
|
3135
3290
|
metadataJoinCode: joinCode,
|