@copilotz/chat-adapter 0.9.19 → 0.9.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +109 -9
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -583,6 +583,20 @@ async function fetchThreads(userId, getRequestHeaders) {
|
|
|
583
583
|
}
|
|
584
584
|
return data;
|
|
585
585
|
}
|
|
586
|
+
async function fetchThreadActivity(threadId, getRequestHeaders) {
|
|
587
|
+
const res = await fetch(apiUrl(`/v1/threads/${encodeURIComponent(threadId)}/activity`), {
|
|
588
|
+
headers: await withAuthHeaders(
|
|
589
|
+
{ Accept: "application/json" },
|
|
590
|
+
getRequestHeaders
|
|
591
|
+
)
|
|
592
|
+
});
|
|
593
|
+
if (!res.ok) {
|
|
594
|
+
const errorText = await res.text().catch(() => res.statusText);
|
|
595
|
+
throw new Error(errorText || `Failed to load thread activity (${res.status})`);
|
|
596
|
+
}
|
|
597
|
+
const { data } = await res.json();
|
|
598
|
+
return data;
|
|
599
|
+
}
|
|
586
600
|
async function fetchAgents(getRequestHeaders) {
|
|
587
601
|
const response = await fetch(apiUrl("/v1/agents"), {
|
|
588
602
|
method: "GET",
|
|
@@ -1665,6 +1679,8 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
|
|
|
1665
1679
|
});
|
|
1666
1680
|
const persistedToolUpdatesRef = useRef2([]);
|
|
1667
1681
|
const liveToolUpdatesRef = useRef2([]);
|
|
1682
|
+
const stopRequestedRef = useRef2(false);
|
|
1683
|
+
const recoveryPollGenerationRef = useRef2(0);
|
|
1668
1684
|
threadsRef.current = threads;
|
|
1669
1685
|
threadMetadataMapRef.current = threadMetadataMap;
|
|
1670
1686
|
threadExternalIdMapRef.current = threadExternalIdMap;
|
|
@@ -2070,6 +2086,8 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
|
|
|
2070
2086
|
[userId, fetchAndSetThreadsState, loadThreadMessages, getRequestHeaders]
|
|
2071
2087
|
);
|
|
2072
2088
|
const handleStop = useCallback2(() => {
|
|
2089
|
+
stopRequestedRef.current = true;
|
|
2090
|
+
recoveryPollGenerationRef.current += 1;
|
|
2073
2091
|
abortControllerRef.current?.abort();
|
|
2074
2092
|
abortControllerRef.current = null;
|
|
2075
2093
|
setIsStreaming(false);
|
|
@@ -2100,6 +2118,52 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
|
|
|
2100
2118
|
)
|
|
2101
2119
|
);
|
|
2102
2120
|
}, []);
|
|
2121
|
+
const finalizeStreamingPlaceholders = useCallback2(() => {
|
|
2122
|
+
setIsStreaming(false);
|
|
2123
|
+
setMessages((prev) => {
|
|
2124
|
+
const hasStreaming = prev.some((msg) => msg.isStreaming);
|
|
2125
|
+
if (!hasStreaming) return prev;
|
|
2126
|
+
return prev.map((msg) => msg.isStreaming ? closeAssistantMessage(msg) : msg);
|
|
2127
|
+
});
|
|
2128
|
+
}, []);
|
|
2129
|
+
const startThreadActivityRecovery = useCallback2(
|
|
2130
|
+
(threadId) => {
|
|
2131
|
+
const generation = ++recoveryPollGenerationRef.current;
|
|
2132
|
+
setIsStreaming(true);
|
|
2133
|
+
void (async () => {
|
|
2134
|
+
let delayMs = 2e3;
|
|
2135
|
+
let attempts = 0;
|
|
2136
|
+
while (recoveryPollGenerationRef.current === generation) {
|
|
2137
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
2138
|
+
if (recoveryPollGenerationRef.current !== generation) return;
|
|
2139
|
+
if (currentThreadIdRef.current !== threadId) return;
|
|
2140
|
+
try {
|
|
2141
|
+
const activity = await fetchThreadActivity(threadId, getRequestHeaders);
|
|
2142
|
+
if (activity.status === "running") {
|
|
2143
|
+
attempts += 1;
|
|
2144
|
+
if (attempts % 3 === 0) {
|
|
2145
|
+
await loadThreadMessages(threadId);
|
|
2146
|
+
}
|
|
2147
|
+
if (attempts >= 15) {
|
|
2148
|
+
delayMs = 5e3;
|
|
2149
|
+
}
|
|
2150
|
+
continue;
|
|
2151
|
+
}
|
|
2152
|
+
await loadThreadMessages(threadId);
|
|
2153
|
+
finalizeStreamingPlaceholders();
|
|
2154
|
+
return;
|
|
2155
|
+
} catch (error) {
|
|
2156
|
+
if (isAbortError(error)) return;
|
|
2157
|
+
attempts += 1;
|
|
2158
|
+
if (attempts >= 15) {
|
|
2159
|
+
delayMs = 5e3;
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
})();
|
|
2164
|
+
},
|
|
2165
|
+
[finalizeStreamingPlaceholders, getRequestHeaders, loadThreadMessages]
|
|
2166
|
+
);
|
|
2103
2167
|
const sendCopilotzMessage = useCallback2(
|
|
2104
2168
|
async (params) => {
|
|
2105
2169
|
let currentAssistantId = params.assistantMessageId ?? generateId();
|
|
@@ -2242,8 +2306,22 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
|
|
|
2242
2306
|
const abortController = new AbortController();
|
|
2243
2307
|
abortControllerRef.current?.abort();
|
|
2244
2308
|
abortControllerRef.current = abortController;
|
|
2309
|
+
stopRequestedRef.current = false;
|
|
2310
|
+
recoveryPollGenerationRef.current += 1;
|
|
2245
2311
|
setIsStreaming(true);
|
|
2246
2312
|
liveToolUpdatesRef.current = [];
|
|
2313
|
+
let streamError = null;
|
|
2314
|
+
const resolveActivityThreadId = async () => {
|
|
2315
|
+
if (params.threadId) return params.threadId;
|
|
2316
|
+
const curId = currentThreadIdRef.current;
|
|
2317
|
+
if (curId && threadExternalIdMapRef.current[curId] !== curId) {
|
|
2318
|
+
return curId;
|
|
2319
|
+
}
|
|
2320
|
+
if (params.threadExternalId) {
|
|
2321
|
+
return await fetchAndSetThreadsState(params.userId, params.threadExternalId);
|
|
2322
|
+
}
|
|
2323
|
+
return null;
|
|
2324
|
+
};
|
|
2247
2325
|
try {
|
|
2248
2326
|
const normalizedUserMetadata = params.userMetadata ? JSON.parse(JSON.stringify(params.userMetadata)) : void 0;
|
|
2249
2327
|
const contextSeed = userContextSeedRef.current;
|
|
@@ -2405,18 +2483,40 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
|
|
|
2405
2483
|
},
|
|
2406
2484
|
signal: abortController.signal
|
|
2407
2485
|
});
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2486
|
+
} catch (error) {
|
|
2487
|
+
streamError = error;
|
|
2488
|
+
}
|
|
2489
|
+
const wasStopped = stopRequestedRef.current || abortController.signal.aborted || isAbortError(streamError);
|
|
2490
|
+
let recoveryStarted = false;
|
|
2491
|
+
if (!wasStopped) {
|
|
2492
|
+
try {
|
|
2493
|
+
const activityThreadId = await resolveActivityThreadId();
|
|
2494
|
+
if (activityThreadId) {
|
|
2495
|
+
const activity = await fetchThreadActivity(activityThreadId, getRequestHeaders);
|
|
2496
|
+
if (activity.status === "running") {
|
|
2497
|
+
recoveryStarted = true;
|
|
2498
|
+
startThreadActivityRecovery(activityThreadId);
|
|
2499
|
+
} else if (streamError || activity.status === "failed") {
|
|
2500
|
+
await loadThreadMessages(activityThreadId);
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
} catch (activityError) {
|
|
2504
|
+
if (!streamError) {
|
|
2505
|
+
console.warn("Unable to verify Copilotz thread activity after stream close", activityError);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
abortControllerRef.current = null;
|
|
2510
|
+
if (recoveryStarted) {
|
|
2511
|
+
return currentAssistantId;
|
|
2512
|
+
}
|
|
2513
|
+
finalizeStreamingPlaceholders();
|
|
2514
|
+
if (streamError) {
|
|
2515
|
+
throw streamError;
|
|
2416
2516
|
}
|
|
2417
2517
|
return currentAssistantId;
|
|
2418
2518
|
},
|
|
2419
|
-
[applyEventInterceptor, handleStreamMessageEvent, handleStreamAssetEvent, getRequestHeaders]
|
|
2519
|
+
[applyEventInterceptor, handleStreamMessageEvent, handleStreamAssetEvent, fetchAndSetThreadsState, finalizeStreamingPlaceholders, getRequestHeaders, loadThreadMessages, startThreadActivityRecovery]
|
|
2420
2520
|
);
|
|
2421
2521
|
const handleSendMessage = useCallback2(
|
|
2422
2522
|
async (content, attachments = []) => {
|