@agent-native/core 0.84.49 → 0.84.51
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/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/agent-chat-adapter.ts +40 -9
- package/corpus/core/src/client/sse-event-processor.ts +31 -15
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +36 -9
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +4 -3
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +22 -5
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/observability/routes.d.ts +2 -2
- package/package.json +1 -1
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.84.51
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 55e4678: Recover durable background chat runs when action input preparation stops making byte progress, and avoid duplicate tool cards when reconnects replay completed tool events.
|
|
8
|
+
|
|
9
|
+
## 0.84.50
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 24a6bd2: Retry agent chat startup timeouts before showing an error when no run stream starts.
|
|
14
|
+
|
|
3
15
|
## 0.84.49
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.84.
|
|
3
|
+
"version": "0.84.51",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -1380,6 +1380,7 @@ export function createAgentChatAdapter(
|
|
|
1380
1380
|
const turnId = generateTurnId();
|
|
1381
1381
|
let runId: string | null = null;
|
|
1382
1382
|
let lastSeq = -1;
|
|
1383
|
+
const seenRunSeqs = new Map<string, number>();
|
|
1383
1384
|
let currentRunDispatchMode: string | null = null;
|
|
1384
1385
|
let currentMessageText = normalizeMentions(
|
|
1385
1386
|
recoveryMessageText.trim() || userMessageText,
|
|
@@ -1548,6 +1549,27 @@ export function createAgentChatAdapter(
|
|
|
1548
1549
|
if (mode) currentRunDispatchMode = mode;
|
|
1549
1550
|
};
|
|
1550
1551
|
|
|
1552
|
+
const rememberRunSeq = (seq: number) => {
|
|
1553
|
+
lastSeq = seq;
|
|
1554
|
+
if (runId) {
|
|
1555
|
+
seenRunSeqs.set(runId, seq);
|
|
1556
|
+
}
|
|
1557
|
+
};
|
|
1558
|
+
|
|
1559
|
+
const reconnectCursorForRun = (
|
|
1560
|
+
nextRunId: string,
|
|
1561
|
+
previousRunId: string | null,
|
|
1562
|
+
) => {
|
|
1563
|
+
const rememberedSeq = seenRunSeqs.get(nextRunId);
|
|
1564
|
+
if (rememberedSeq !== undefined) {
|
|
1565
|
+
lastSeq = rememberedSeq;
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
if (previousRunId !== nextRunId) {
|
|
1569
|
+
lastSeq = -1;
|
|
1570
|
+
}
|
|
1571
|
+
};
|
|
1572
|
+
|
|
1551
1573
|
const currentSSEOptions = () => ({
|
|
1552
1574
|
durableBackgroundRun:
|
|
1553
1575
|
currentRunDispatchMode?.startsWith("background") === true,
|
|
@@ -1671,7 +1693,7 @@ export function createAgentChatAdapter(
|
|
|
1671
1693
|
toolCallCounter,
|
|
1672
1694
|
tabId,
|
|
1673
1695
|
(seq) => {
|
|
1674
|
-
|
|
1696
|
+
rememberRunSeq(seq);
|
|
1675
1697
|
if (threadId) updateActiveRunSeq(seq);
|
|
1676
1698
|
},
|
|
1677
1699
|
runId,
|
|
@@ -1765,12 +1787,13 @@ export function createAgentChatAdapter(
|
|
|
1765
1787
|
return false;
|
|
1766
1788
|
}
|
|
1767
1789
|
const activeRunId = String(active.runId);
|
|
1790
|
+
const previousRunId = runId;
|
|
1768
1791
|
runId = activeRunId;
|
|
1769
1792
|
if (!attemptedRunIds.includes(activeRunId)) {
|
|
1770
1793
|
attemptedRunIds.push(activeRunId);
|
|
1771
1794
|
}
|
|
1772
|
-
|
|
1773
|
-
setActiveRun({ threadId, runId: activeRunId, lastSeq
|
|
1795
|
+
reconnectCursorForRun(activeRunId, previousRunId);
|
|
1796
|
+
setActiveRun({ threadId, runId: activeRunId, lastSeq });
|
|
1774
1797
|
const reconnected = yield* reconnectCurrentRun();
|
|
1775
1798
|
if (reconnected) return true;
|
|
1776
1799
|
}
|
|
@@ -1844,12 +1867,13 @@ export function createAgentChatAdapter(
|
|
|
1844
1867
|
if (activeStatus !== "running" && activeStatus !== "starting") {
|
|
1845
1868
|
return false;
|
|
1846
1869
|
}
|
|
1870
|
+
const previousRunId = runId;
|
|
1847
1871
|
runId = activeRunId;
|
|
1848
1872
|
if (!attemptedRunIds.includes(activeRunId)) {
|
|
1849
1873
|
attemptedRunIds.push(activeRunId);
|
|
1850
1874
|
}
|
|
1851
|
-
|
|
1852
|
-
setActiveRun({ threadId, runId: activeRunId, lastSeq
|
|
1875
|
+
reconnectCursorForRun(activeRunId, previousRunId);
|
|
1876
|
+
setActiveRun({ threadId, runId: activeRunId, lastSeq });
|
|
1853
1877
|
const reconnected = yield* reconnectCurrentRun();
|
|
1854
1878
|
if (reconnected) return true;
|
|
1855
1879
|
} catch (activeErr: unknown) {
|
|
@@ -2290,13 +2314,14 @@ export function createAgentChatAdapter(
|
|
|
2290
2314
|
}
|
|
2291
2315
|
if (activeRunId) {
|
|
2292
2316
|
try {
|
|
2317
|
+
const previousRunId = runId;
|
|
2293
2318
|
runId = activeRunId;
|
|
2294
2319
|
if (!attemptedRunIds.includes(runId)) {
|
|
2295
2320
|
attemptedRunIds.push(runId);
|
|
2296
2321
|
}
|
|
2297
|
-
|
|
2322
|
+
reconnectCursorForRun(activeRunId, previousRunId);
|
|
2298
2323
|
if (threadId) {
|
|
2299
|
-
setActiveRun({ threadId, runId, lastSeq
|
|
2324
|
+
setActiveRun({ threadId, runId, lastSeq });
|
|
2300
2325
|
}
|
|
2301
2326
|
const reconnected = yield* reconnectCurrentRun();
|
|
2302
2327
|
if (reconnected) return;
|
|
@@ -2423,7 +2448,7 @@ export function createAgentChatAdapter(
|
|
|
2423
2448
|
toolCallCounter,
|
|
2424
2449
|
tabId,
|
|
2425
2450
|
(seq) => {
|
|
2426
|
-
|
|
2451
|
+
rememberRunSeq(seq);
|
|
2427
2452
|
if (runId && threadId) {
|
|
2428
2453
|
updateActiveRunSeq(seq);
|
|
2429
2454
|
}
|
|
@@ -2616,10 +2641,16 @@ export function createAgentChatAdapter(
|
|
|
2616
2641
|
if (activeReconnected) return;
|
|
2617
2642
|
|
|
2618
2643
|
if (err instanceof AgentStartupTimeoutError) {
|
|
2644
|
+
if (startupRecoveryAttempts < MAX_STARTUP_RECOVERY_ATTEMPTS) {
|
|
2645
|
+
await retryDelay(startupRecoveryAttempts++, abortSignal);
|
|
2646
|
+
if (abortSignal.aborted) return;
|
|
2647
|
+
continue;
|
|
2648
|
+
}
|
|
2619
2649
|
const message =
|
|
2620
|
-
"The agent chat endpoint
|
|
2650
|
+
"The agent chat endpoint did not start streaming in time after several recovery attempts. This usually means prompt setup, the LLM gateway, or the provider is stalled.";
|
|
2621
2651
|
captureChatClientError(err, "startup-timeout", {
|
|
2622
2652
|
timeoutMs: err.timeoutMs,
|
|
2653
|
+
startupRecoveryAttempts,
|
|
2623
2654
|
});
|
|
2624
2655
|
const runError = {
|
|
2625
2656
|
message,
|
|
@@ -151,9 +151,10 @@ export const SSE_ACTION_PREPARATION_STALL_TIMEOUT_MS = 90_000;
|
|
|
151
151
|
export interface SSEStreamOptions {
|
|
152
152
|
/**
|
|
153
153
|
* Durable background runs have their own server-side liveness budget and
|
|
154
|
-
* heartbeat. While one is active, keepalive-only periods
|
|
155
|
-
*
|
|
156
|
-
*
|
|
154
|
+
* heartbeat. While one is active, generic keepalive-only periods keep the
|
|
155
|
+
* client attached. Tool-input preparation is stricter: real byte progress
|
|
156
|
+
* keeps long payloads alive, but zero-byte/silent preparation still recovers
|
|
157
|
+
* so one stuck action cannot pin the chat forever.
|
|
157
158
|
*/
|
|
158
159
|
durableBackgroundRun?: boolean;
|
|
159
160
|
}
|
|
@@ -278,6 +279,24 @@ function findPendingToolCallIndex(
|
|
|
278
279
|
return -1;
|
|
279
280
|
}
|
|
280
281
|
|
|
282
|
+
function findCompletedToolCallIndex(
|
|
283
|
+
content: ContentPart[],
|
|
284
|
+
toolCallId?: string,
|
|
285
|
+
): number {
|
|
286
|
+
if (!toolCallId) return -1;
|
|
287
|
+
for (let i = content.length - 1; i >= 0; i--) {
|
|
288
|
+
const part = content[i];
|
|
289
|
+
if (
|
|
290
|
+
part.type === "tool-call" &&
|
|
291
|
+
part.toolCallId === toolCallId &&
|
|
292
|
+
part.result !== undefined
|
|
293
|
+
) {
|
|
294
|
+
return i;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return -1;
|
|
298
|
+
}
|
|
299
|
+
|
|
281
300
|
function appendActivityTrail(
|
|
282
301
|
trail: ActivityTrailEntry[],
|
|
283
302
|
next: ActivityTrailEntry,
|
|
@@ -359,12 +378,7 @@ function updatePreparingActionState(
|
|
|
359
378
|
return undefined;
|
|
360
379
|
}
|
|
361
380
|
|
|
362
|
-
function hasStalledPreparingAction(
|
|
363
|
-
state: PreparingActionState,
|
|
364
|
-
now: number,
|
|
365
|
-
options?: SSEStreamOptions,
|
|
366
|
-
) {
|
|
367
|
-
if (options?.durableBackgroundRun === true) return false;
|
|
381
|
+
function hasStalledPreparingAction(state: PreparingActionState, now: number) {
|
|
368
382
|
// Fire only when a tool input has gone SILENT — no further streaming deltas
|
|
369
383
|
// for the whole window — never merely because a large input has been
|
|
370
384
|
// streaming for a long time. `lastProgressAt` advances on every delta
|
|
@@ -787,6 +801,9 @@ export function processEvent(
|
|
|
787
801
|
if (ev.type === "tool_start") {
|
|
788
802
|
const args = (ev.input ?? {}) as Record<string, string>;
|
|
789
803
|
const tool = ev.tool ?? "unknown";
|
|
804
|
+
if (findCompletedToolCallIndex(content, ev.id) >= 0) {
|
|
805
|
+
return { action: "continue" };
|
|
806
|
+
}
|
|
790
807
|
if (typeof window !== "undefined") {
|
|
791
808
|
window.dispatchEvent(
|
|
792
809
|
new CustomEvent("agent-native:tool-start", {
|
|
@@ -868,6 +885,9 @@ export function processEvent(
|
|
|
868
885
|
// so a tool_done frame with an undefined tool name still matches its
|
|
869
886
|
// pending tool-call entry instead of leaving it forever unresolved.
|
|
870
887
|
const doneTool = ev.tool ?? "unknown";
|
|
888
|
+
if (findCompletedToolCallIndex(content, ev.id) >= 0) {
|
|
889
|
+
return { action: "continue" };
|
|
890
|
+
}
|
|
871
891
|
if (typeof window !== "undefined") {
|
|
872
892
|
window.dispatchEvent(
|
|
873
893
|
new CustomEvent("agent-native:tool-done", {
|
|
@@ -1340,9 +1360,7 @@ export async function* readSSEStream(
|
|
|
1340
1360
|
);
|
|
1341
1361
|
|
|
1342
1362
|
if (result) yield withStreamMetadata(result);
|
|
1343
|
-
if (
|
|
1344
|
-
hasStalledPreparingAction(preparingActionState, Date.now(), options)
|
|
1345
|
-
) {
|
|
1363
|
+
if (hasStalledPreparingAction(preparingActionState, Date.now())) {
|
|
1346
1364
|
throw new AgentAutoContinueSignal({
|
|
1347
1365
|
reason: "no_progress",
|
|
1348
1366
|
activityTrail: [...activityTrail],
|
|
@@ -1525,9 +1543,7 @@ export async function readSSEStreamRaw(
|
|
|
1525
1543
|
: { reason: "stream_ended", activityTrail: [...activityTrail] },
|
|
1526
1544
|
);
|
|
1527
1545
|
}
|
|
1528
|
-
if (
|
|
1529
|
-
hasStalledPreparingAction(preparingActionState, Date.now(), options)
|
|
1530
|
-
) {
|
|
1546
|
+
if (hasStalledPreparingAction(preparingActionState, Date.now())) {
|
|
1531
1547
|
onUpdate(contentSnapshot(content));
|
|
1532
1548
|
throw new AgentAutoContinueSignal({
|
|
1533
1549
|
reason: "no_progress",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-chat-adapter.d.ts","sourceRoot":"","sources":["../../src/client/agent-chat-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,qBAAqB,CAAC;AAOhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAkBrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,oBAAoB;AAC9B;;;;GAIG;AACD,KAAK;AACP,0EAA0E;GACxE,WAAW,CAAC;AA+pChB;;;;GAIG;AACH;;;GAGG;AACH,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC3C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,SAAS,CAAA;KAAE,CAAC;IACrD,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,CAAA;KAAE,CAAC;IAC3D,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC;AAED,wBAAgB,sBAAsB,CACpC,OAAO,CAAC,EAAE,6BAA6B,GACtC,gBAAgB,
|
|
1
|
+
{"version":3,"file":"agent-chat-adapter.d.ts","sourceRoot":"","sources":["../../src/client/agent-chat-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,qBAAqB,CAAC;AAOhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAkBrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,oBAAoB;AAC9B;;;;GAIG;AACD,KAAK;AACP,0EAA0E;GACxE,WAAW,CAAC;AA+pChB;;;;GAIG;AACH;;;GAGG;AACH,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC3C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,SAAS,CAAA;KAAE,CAAC;IACrD,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,CAAA;KAAE,CAAC;IAC3D,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC;AAED,wBAAgB,sBAAsB,CACpC,OAAO,CAAC,EAAE,6BAA6B,GACtC,gBAAgB,CAgjDlB"}
|
|
@@ -1055,6 +1055,7 @@ export function createAgentChatAdapter(options) {
|
|
|
1055
1055
|
const turnId = generateTurnId();
|
|
1056
1056
|
let runId = null;
|
|
1057
1057
|
let lastSeq = -1;
|
|
1058
|
+
const seenRunSeqs = new Map();
|
|
1058
1059
|
let currentRunDispatchMode = null;
|
|
1059
1060
|
let currentMessageText = normalizeMentions(recoveryMessageText.trim() || userMessageText);
|
|
1060
1061
|
let currentHistory = history;
|
|
@@ -1208,6 +1209,22 @@ export function createAgentChatAdapter(options) {
|
|
|
1208
1209
|
if (mode)
|
|
1209
1210
|
currentRunDispatchMode = mode;
|
|
1210
1211
|
};
|
|
1212
|
+
const rememberRunSeq = (seq) => {
|
|
1213
|
+
lastSeq = seq;
|
|
1214
|
+
if (runId) {
|
|
1215
|
+
seenRunSeqs.set(runId, seq);
|
|
1216
|
+
}
|
|
1217
|
+
};
|
|
1218
|
+
const reconnectCursorForRun = (nextRunId, previousRunId) => {
|
|
1219
|
+
const rememberedSeq = seenRunSeqs.get(nextRunId);
|
|
1220
|
+
if (rememberedSeq !== undefined) {
|
|
1221
|
+
lastSeq = rememberedSeq;
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
if (previousRunId !== nextRunId) {
|
|
1225
|
+
lastSeq = -1;
|
|
1226
|
+
}
|
|
1227
|
+
};
|
|
1211
1228
|
const currentSSEOptions = () => ({
|
|
1212
1229
|
durableBackgroundRun: currentRunDispatchMode?.startsWith("background") === true,
|
|
1213
1230
|
});
|
|
@@ -1305,7 +1322,7 @@ export function createAgentChatAdapter(options) {
|
|
|
1305
1322
|
}
|
|
1306
1323
|
updateCurrentRunDispatchMode(reconnectRes.headers.get("X-Dispatch-Mode"));
|
|
1307
1324
|
for await (const result of readSSEStream(reconnectRes.body, content, toolCallCounter, tabId, (seq) => {
|
|
1308
|
-
|
|
1325
|
+
rememberRunSeq(seq);
|
|
1309
1326
|
if (threadId)
|
|
1310
1327
|
updateActiveRunSeq(seq);
|
|
1311
1328
|
}, runId, currentSSEOptions())) {
|
|
@@ -1380,12 +1397,13 @@ export function createAgentChatAdapter(options) {
|
|
|
1380
1397
|
return false;
|
|
1381
1398
|
}
|
|
1382
1399
|
const activeRunId = String(active.runId);
|
|
1400
|
+
const previousRunId = runId;
|
|
1383
1401
|
runId = activeRunId;
|
|
1384
1402
|
if (!attemptedRunIds.includes(activeRunId)) {
|
|
1385
1403
|
attemptedRunIds.push(activeRunId);
|
|
1386
1404
|
}
|
|
1387
|
-
|
|
1388
|
-
setActiveRun({ threadId, runId: activeRunId, lastSeq
|
|
1405
|
+
reconnectCursorForRun(activeRunId, previousRunId);
|
|
1406
|
+
setActiveRun({ threadId, runId: activeRunId, lastSeq });
|
|
1389
1407
|
const reconnected = yield* reconnectCurrentRun();
|
|
1390
1408
|
if (reconnected)
|
|
1391
1409
|
return true;
|
|
@@ -1449,12 +1467,13 @@ export function createAgentChatAdapter(options) {
|
|
|
1449
1467
|
if (activeStatus !== "running" && activeStatus !== "starting") {
|
|
1450
1468
|
return false;
|
|
1451
1469
|
}
|
|
1470
|
+
const previousRunId = runId;
|
|
1452
1471
|
runId = activeRunId;
|
|
1453
1472
|
if (!attemptedRunIds.includes(activeRunId)) {
|
|
1454
1473
|
attemptedRunIds.push(activeRunId);
|
|
1455
1474
|
}
|
|
1456
|
-
|
|
1457
|
-
setActiveRun({ threadId, runId: activeRunId, lastSeq
|
|
1475
|
+
reconnectCursorForRun(activeRunId, previousRunId);
|
|
1476
|
+
setActiveRun({ threadId, runId: activeRunId, lastSeq });
|
|
1458
1477
|
const reconnected = yield* reconnectCurrentRun();
|
|
1459
1478
|
if (reconnected)
|
|
1460
1479
|
return true;
|
|
@@ -1834,13 +1853,14 @@ export function createAgentChatAdapter(options) {
|
|
|
1834
1853
|
}
|
|
1835
1854
|
if (activeRunId) {
|
|
1836
1855
|
try {
|
|
1856
|
+
const previousRunId = runId;
|
|
1837
1857
|
runId = activeRunId;
|
|
1838
1858
|
if (!attemptedRunIds.includes(runId)) {
|
|
1839
1859
|
attemptedRunIds.push(runId);
|
|
1840
1860
|
}
|
|
1841
|
-
|
|
1861
|
+
reconnectCursorForRun(activeRunId, previousRunId);
|
|
1842
1862
|
if (threadId) {
|
|
1843
|
-
setActiveRun({ threadId, runId, lastSeq
|
|
1863
|
+
setActiveRun({ threadId, runId, lastSeq });
|
|
1844
1864
|
}
|
|
1845
1865
|
const reconnected = yield* reconnectCurrentRun();
|
|
1846
1866
|
if (reconnected)
|
|
@@ -1959,7 +1979,7 @@ export function createAgentChatAdapter(options) {
|
|
|
1959
1979
|
setActiveRun({ threadId, runId, lastSeq: -1 });
|
|
1960
1980
|
}
|
|
1961
1981
|
for await (const result of readSSEStream(res.body, content, toolCallCounter, tabId, (seq) => {
|
|
1962
|
-
|
|
1982
|
+
rememberRunSeq(seq);
|
|
1963
1983
|
if (runId && threadId) {
|
|
1964
1984
|
updateActiveRunSeq(seq);
|
|
1965
1985
|
}
|
|
@@ -2132,9 +2152,16 @@ export function createAgentChatAdapter(options) {
|
|
|
2132
2152
|
if (activeReconnected)
|
|
2133
2153
|
return;
|
|
2134
2154
|
if (err instanceof AgentStartupTimeoutError) {
|
|
2135
|
-
|
|
2155
|
+
if (startupRecoveryAttempts < MAX_STARTUP_RECOVERY_ATTEMPTS) {
|
|
2156
|
+
await retryDelay(startupRecoveryAttempts++, abortSignal);
|
|
2157
|
+
if (abortSignal.aborted)
|
|
2158
|
+
return;
|
|
2159
|
+
continue;
|
|
2160
|
+
}
|
|
2161
|
+
const message = "The agent chat endpoint did not start streaming in time after several recovery attempts. This usually means prompt setup, the LLM gateway, or the provider is stalled.";
|
|
2136
2162
|
captureChatClientError(err, "startup-timeout", {
|
|
2137
2163
|
timeoutMs: err.timeoutMs,
|
|
2164
|
+
startupRecoveryAttempts,
|
|
2138
2165
|
});
|
|
2139
2166
|
const runError = {
|
|
2140
2167
|
message,
|