@hef2024/llmasaservice-ui 0.25.1 → 0.25.2
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 +270 -55
- package/dist/index.mjs +270 -55
- package/package.json +1 -1
- package/src/AIAgentPanel.tsx +93 -7
- package/src/AIChatPanel.tsx +270 -55
package/dist/index.mjs
CHANGED
|
@@ -5498,6 +5498,10 @@ var AIChatPanel = ({
|
|
|
5498
5498
|
const queuedToolRequestsRef = useRef6(null);
|
|
5499
5499
|
const suppressAbortHistoryUpdateRef = useRef6(false);
|
|
5500
5500
|
const toolReplaySummariesByKeyRef = useRef6({});
|
|
5501
|
+
const continuationDispatchPendingRef = useRef6(false);
|
|
5502
|
+
const successfulMutationSignaturesRef = useRef6(/* @__PURE__ */ new Set());
|
|
5503
|
+
const queuedDrainTimerRef = useRef6(null);
|
|
5504
|
+
const queuedDrainScheduledRef = useRef6(false);
|
|
5501
5505
|
useEffect8(() => {
|
|
5502
5506
|
if (!initialHistory) return;
|
|
5503
5507
|
setHistory((prev) => {
|
|
@@ -6006,6 +6010,8 @@ var AIChatPanel = ({
|
|
|
6006
6010
|
return false;
|
|
6007
6011
|
}, [customerEmailCaptureMode, emailInputSet]);
|
|
6008
6012
|
const pendingToolRequestsRef = useRef6(pendingToolRequests);
|
|
6013
|
+
const activeToolCallsRef = useRef6(activeToolCalls);
|
|
6014
|
+
const turnLockRef = useRef6(false);
|
|
6009
6015
|
const streamIdleRef = useRef6(idle);
|
|
6010
6016
|
streamIdleRef.current = idle;
|
|
6011
6017
|
const waitForStreamIdle = useCallback2((timeoutMs = 2500) => __async(void 0, null, function* () {
|
|
@@ -6019,6 +6025,36 @@ var AIChatPanel = ({
|
|
|
6019
6025
|
useEffect8(() => {
|
|
6020
6026
|
pendingToolRequestsRef.current = pendingToolRequests;
|
|
6021
6027
|
}, [pendingToolRequests]);
|
|
6028
|
+
useEffect8(() => {
|
|
6029
|
+
activeToolCallsRef.current = activeToolCalls;
|
|
6030
|
+
}, [activeToolCalls]);
|
|
6031
|
+
const hasUnresolvedToolRequestsInLatestResponse = useCallback2(() => {
|
|
6032
|
+
const latestResponse = String(responseRef.current || "");
|
|
6033
|
+
if (!latestResponse.trim()) return false;
|
|
6034
|
+
const latestRequests = extractToolRequestMatchesFromText(latestResponse);
|
|
6035
|
+
if (latestRequests.length === 0) return false;
|
|
6036
|
+
return latestRequests.some((request) => {
|
|
6037
|
+
const signature = getToolCallSignature(request.toolName, request.callId);
|
|
6038
|
+
if (!signature) return false;
|
|
6039
|
+
if (handledToolCallSignaturesRef.current.has(signature)) return false;
|
|
6040
|
+
if (inFlightToolCallSignaturesRef.current.has(signature)) return false;
|
|
6041
|
+
return true;
|
|
6042
|
+
});
|
|
6043
|
+
}, [getToolCallSignature]);
|
|
6044
|
+
const hasInFlightTurnWork = useCallback2(() => {
|
|
6045
|
+
return toolRequestProcessingRef.current || continuationDispatchPendingRef.current || (queuedToolRequestsRef.current || []).length > 0 || (pendingToolRequestsRef.current || []).length > 0 || (activeToolCallsRef.current || []).length > 0 || !streamIdleRef.current || hasUnresolvedToolRequestsInLatestResponse();
|
|
6046
|
+
}, [hasUnresolvedToolRequestsInLatestResponse]);
|
|
6047
|
+
const queuePromptForLater = useCallback2((promptText) => {
|
|
6048
|
+
const normalizedPrompt = String(promptText || "").trim();
|
|
6049
|
+
if (!normalizedPrompt) return;
|
|
6050
|
+
const nextQueuedPrompts = [...queuedPromptsRef.current, normalizedPrompt];
|
|
6051
|
+
queuedPromptsRef.current = nextQueuedPrompts;
|
|
6052
|
+
setQueuedPrompts(nextQueuedPrompts);
|
|
6053
|
+
}, []);
|
|
6054
|
+
const releaseTurnLockIfSettled = useCallback2(() => {
|
|
6055
|
+
if (hasInFlightTurnWork()) return;
|
|
6056
|
+
turnLockRef.current = false;
|
|
6057
|
+
}, [hasInFlightTurnWork]);
|
|
6022
6058
|
const processGivenToolRequests = useCallback2(
|
|
6023
6059
|
(requests) => __async(void 0, null, function* () {
|
|
6024
6060
|
var _a2, _b, _c;
|
|
@@ -6045,6 +6081,7 @@ var AIChatPanel = ({
|
|
|
6045
6081
|
return;
|
|
6046
6082
|
}
|
|
6047
6083
|
toolRequestProcessingRef.current = true;
|
|
6084
|
+
turnLockRef.current = true;
|
|
6048
6085
|
try {
|
|
6049
6086
|
let requestsToProcess = requests;
|
|
6050
6087
|
if (!requestsToProcess || requestsToProcess.length === 0) {
|
|
@@ -6123,6 +6160,44 @@ ${traceSummary}` : traceSummary;
|
|
|
6123
6160
|
});
|
|
6124
6161
|
}
|
|
6125
6162
|
}
|
|
6163
|
+
const normalizeToolArgsForSignature = (value) => {
|
|
6164
|
+
if (Array.isArray(value)) {
|
|
6165
|
+
return value.map((item) => normalizeToolArgsForSignature(item));
|
|
6166
|
+
}
|
|
6167
|
+
if (value && typeof value === "object") {
|
|
6168
|
+
const normalizedObject = {};
|
|
6169
|
+
Object.keys(value).sort().forEach((key) => {
|
|
6170
|
+
normalizedObject[key] = normalizeToolArgsForSignature(
|
|
6171
|
+
value[key]
|
|
6172
|
+
);
|
|
6173
|
+
});
|
|
6174
|
+
return normalizedObject;
|
|
6175
|
+
}
|
|
6176
|
+
return value != null ? value : null;
|
|
6177
|
+
};
|
|
6178
|
+
const getSemanticMutationSignature = (toolName, args) => {
|
|
6179
|
+
const normalizedName = String(toolName || "").trim().toLowerCase();
|
|
6180
|
+
const normalizedArgs = normalizeToolArgsForSignature(args);
|
|
6181
|
+
return `${normalizedName}::${JSON.stringify(normalizedArgs)}`;
|
|
6182
|
+
};
|
|
6183
|
+
const isLikelyMutatingCall = (toolName, args) => {
|
|
6184
|
+
const normalizedName = String(toolName || "").trim().toLowerCase();
|
|
6185
|
+
const action = String((args == null ? void 0 : args.action) || "").trim().toLowerCase();
|
|
6186
|
+
const mutatingActions = /* @__PURE__ */ new Set([
|
|
6187
|
+
"add",
|
|
6188
|
+
"create",
|
|
6189
|
+
"materialize_from_sourcing_result",
|
|
6190
|
+
"materialize",
|
|
6191
|
+
"update",
|
|
6192
|
+
"delete",
|
|
6193
|
+
"remove",
|
|
6194
|
+
"cancel",
|
|
6195
|
+
"complete",
|
|
6196
|
+
"move"
|
|
6197
|
+
]);
|
|
6198
|
+
if (action && mutatingActions.has(action)) return true;
|
|
6199
|
+
return normalizedName.includes("pipeline") || normalizedName.includes("work_item") || normalizedName.includes("candidate_pipeline") || normalizedName.includes("cron");
|
|
6200
|
+
};
|
|
6126
6201
|
const parsedToolCalls = yield Promise.all(
|
|
6127
6202
|
requestsToProcess.map((req, index) => __async(void 0, null, function* () {
|
|
6128
6203
|
var _a3, _b2, _c2, _d, _e, _f;
|
|
@@ -6151,27 +6226,44 @@ ${traceSummary}` : traceSummary;
|
|
|
6151
6226
|
const serviceTag = typeof req.serviceTag === "string" && req.serviceTag || typeof req.groups[3] === "string" && req.groups[3] || typeof (parsedToolCall == null ? void 0 : parsedToolCall.service) === "string" && parsedToolCall.service || "";
|
|
6152
6227
|
const callSignature = getToolCallSignature(toolName, callId);
|
|
6153
6228
|
if (!callSignature) return null;
|
|
6229
|
+
const semanticMutationSignature = getSemanticMutationSignature(toolName, args);
|
|
6230
|
+
const likelyMutating = isLikelyMutatingCall(toolName, args);
|
|
6154
6231
|
return {
|
|
6155
6232
|
req,
|
|
6156
6233
|
toolName,
|
|
6157
6234
|
callId,
|
|
6158
6235
|
args,
|
|
6159
6236
|
serviceTag,
|
|
6160
|
-
callSignature
|
|
6237
|
+
callSignature,
|
|
6238
|
+
semanticMutationSignature,
|
|
6239
|
+
likelyMutating
|
|
6161
6240
|
};
|
|
6162
6241
|
}))
|
|
6163
6242
|
);
|
|
6164
6243
|
const toolCallBatch = parsedToolCalls.filter(Boolean);
|
|
6165
6244
|
const seenCallSignatures = /* @__PURE__ */ new Set();
|
|
6245
|
+
const seenMutationSemanticsInBatch = /* @__PURE__ */ new Set();
|
|
6166
6246
|
const callsToRun = [];
|
|
6247
|
+
const suppressedMutationDuplicates = [];
|
|
6167
6248
|
toolCallBatch.forEach((toolCall) => {
|
|
6168
6249
|
if (seenCallSignatures.has(toolCall.callSignature)) return;
|
|
6169
6250
|
seenCallSignatures.add(toolCall.callSignature);
|
|
6170
6251
|
if (handledToolCallSignaturesRef.current.has(toolCall.callSignature)) return;
|
|
6171
6252
|
if (inFlightToolCallSignaturesRef.current.has(toolCall.callSignature)) return;
|
|
6253
|
+
if (toolCall.likelyMutating && seenMutationSemanticsInBatch.has(toolCall.semanticMutationSignature)) {
|
|
6254
|
+
suppressedMutationDuplicates.push(toolCall);
|
|
6255
|
+
return;
|
|
6256
|
+
}
|
|
6257
|
+
if (toolCall.likelyMutating && successfulMutationSignaturesRef.current.has(toolCall.semanticMutationSignature)) {
|
|
6258
|
+
suppressedMutationDuplicates.push(toolCall);
|
|
6259
|
+
return;
|
|
6260
|
+
}
|
|
6261
|
+
if (toolCall.likelyMutating) {
|
|
6262
|
+
seenMutationSemanticsInBatch.add(toolCall.semanticMutationSignature);
|
|
6263
|
+
}
|
|
6172
6264
|
callsToRun.push(toolCall);
|
|
6173
6265
|
});
|
|
6174
|
-
if (callsToRun.length === 0) {
|
|
6266
|
+
if (callsToRun.length === 0 && suppressedMutationDuplicates.length === 0) {
|
|
6175
6267
|
setPendingToolRequests(
|
|
6176
6268
|
(prev) => prev.filter((request) => {
|
|
6177
6269
|
const signature = getToolCallSignature(request.toolName, request.callId);
|
|
@@ -6183,11 +6275,14 @@ ${traceSummary}` : traceSummary;
|
|
|
6183
6275
|
setIsLoading(false);
|
|
6184
6276
|
return;
|
|
6185
6277
|
}
|
|
6186
|
-
const
|
|
6278
|
+
const handledBatchSignatures = /* @__PURE__ */ new Set([
|
|
6279
|
+
...callsToRun.map((toolCall) => toolCall.callSignature),
|
|
6280
|
+
...suppressedMutationDuplicates.map((toolCall) => toolCall.callSignature)
|
|
6281
|
+
]);
|
|
6187
6282
|
setPendingToolRequests(
|
|
6188
6283
|
(prev) => prev.filter((request) => {
|
|
6189
6284
|
const signature = getToolCallSignature(request.toolName, request.callId);
|
|
6190
|
-
return !signature || !
|
|
6285
|
+
return !signature || !handledBatchSignatures.has(signature);
|
|
6191
6286
|
})
|
|
6192
6287
|
);
|
|
6193
6288
|
callsToRun.forEach((toolCall) => {
|
|
@@ -6200,7 +6295,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6200
6295
|
args: toolCall.args
|
|
6201
6296
|
}))
|
|
6202
6297
|
);
|
|
6203
|
-
const finalToolCalls = callsToRun.map((toolCall) => ({
|
|
6298
|
+
const finalToolCalls = [...callsToRun, ...suppressedMutationDuplicates].map((toolCall) => ({
|
|
6204
6299
|
id: toolCall.callId,
|
|
6205
6300
|
type: "tool_use",
|
|
6206
6301
|
name: toolCall.toolName,
|
|
@@ -6331,12 +6426,30 @@ ${traceSummary}` : traceSummary;
|
|
|
6331
6426
|
}
|
|
6332
6427
|
}))
|
|
6333
6428
|
);
|
|
6334
|
-
|
|
6429
|
+
const executedResponses = toolResponses.filter(Boolean);
|
|
6430
|
+
const suppressedResponses = suppressedMutationDuplicates.map((toolCall) => ({
|
|
6431
|
+
tool_call_id: toolCall.callId,
|
|
6432
|
+
tool_name: toolCall.toolName,
|
|
6433
|
+
result: "Duplicate mutating call suppressed: this exact action already succeeded earlier in the same turn.",
|
|
6434
|
+
isError: false
|
|
6435
|
+
}));
|
|
6436
|
+
finalToolResponses = [...executedResponses, ...suppressedResponses];
|
|
6437
|
+
callsToRun.forEach((toolCall) => {
|
|
6438
|
+
const matchedResponse = executedResponses.find(
|
|
6439
|
+
(response2) => (response2 == null ? void 0 : response2.tool_call_id) === toolCall.callId
|
|
6440
|
+
);
|
|
6441
|
+
if (!(matchedResponse == null ? void 0 : matchedResponse.isError) && toolCall.likelyMutating) {
|
|
6442
|
+
successfulMutationSignaturesRef.current.add(toolCall.semanticMutationSignature);
|
|
6443
|
+
}
|
|
6444
|
+
});
|
|
6335
6445
|
} finally {
|
|
6336
6446
|
callsToRun.forEach((toolCall) => {
|
|
6337
6447
|
inFlightToolCallSignaturesRef.current.delete(toolCall.callSignature);
|
|
6338
6448
|
handledToolCallSignaturesRef.current.add(toolCall.callSignature);
|
|
6339
6449
|
});
|
|
6450
|
+
suppressedMutationDuplicates.forEach((toolCall) => {
|
|
6451
|
+
handledToolCallSignaturesRef.current.add(toolCall.callSignature);
|
|
6452
|
+
});
|
|
6340
6453
|
}
|
|
6341
6454
|
setActiveToolCalls([]);
|
|
6342
6455
|
const currentLastKey = lastKeyRef.current;
|
|
@@ -6440,6 +6553,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6440
6553
|
if (!streamIdleRef.current) {
|
|
6441
6554
|
setActiveToolCalls([]);
|
|
6442
6555
|
setIsLoading(false);
|
|
6556
|
+
continuationDispatchPendingRef.current = false;
|
|
6443
6557
|
setError({
|
|
6444
6558
|
message: "Timed out waiting for the previous stream to settle before tool continuation.",
|
|
6445
6559
|
code: "TOOL_CONTINUATION_WAIT_TIMEOUT"
|
|
@@ -6455,6 +6569,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6455
6569
|
} else {
|
|
6456
6570
|
activeStreamAppendBaseRef.current = null;
|
|
6457
6571
|
}
|
|
6572
|
+
continuationDispatchPendingRef.current = true;
|
|
6458
6573
|
send(
|
|
6459
6574
|
"",
|
|
6460
6575
|
newMessages,
|
|
@@ -6472,12 +6587,14 @@ ${traceSummary}` : traceSummary;
|
|
|
6472
6587
|
newController,
|
|
6473
6588
|
void 0,
|
|
6474
6589
|
(errorMsg) => {
|
|
6590
|
+
continuationDispatchPendingRef.current = false;
|
|
6475
6591
|
setActiveToolCalls([]);
|
|
6476
6592
|
setIsLoading(false);
|
|
6477
6593
|
setError({
|
|
6478
6594
|
message: errorMsg,
|
|
6479
6595
|
code: "TOOL_ERROR"
|
|
6480
6596
|
});
|
|
6597
|
+
releaseTurnLockIfSettled();
|
|
6481
6598
|
}
|
|
6482
6599
|
);
|
|
6483
6600
|
} finally {
|
|
@@ -6488,6 +6605,8 @@ ${traceSummary}` : traceSummary;
|
|
|
6488
6605
|
queueMicrotask(() => {
|
|
6489
6606
|
void processGivenToolRequests(queued);
|
|
6490
6607
|
});
|
|
6608
|
+
} else {
|
|
6609
|
+
releaseTurnLockIfSettled();
|
|
6491
6610
|
}
|
|
6492
6611
|
}
|
|
6493
6612
|
}),
|
|
@@ -6506,7 +6625,8 @@ ${traceSummary}` : traceSummary;
|
|
|
6506
6625
|
idle,
|
|
6507
6626
|
stop,
|
|
6508
6627
|
lastController,
|
|
6509
|
-
waitForStreamIdle
|
|
6628
|
+
waitForStreamIdle,
|
|
6629
|
+
releaseTurnLockIfSettled
|
|
6510
6630
|
]
|
|
6511
6631
|
);
|
|
6512
6632
|
const handleToolApproval = useCallback2(
|
|
@@ -6531,6 +6651,8 @@ ${traceSummary}` : traceSummary;
|
|
|
6531
6651
|
);
|
|
6532
6652
|
useEffect8(() => {
|
|
6533
6653
|
if (pendingToolRequests.length === 0) return;
|
|
6654
|
+
if (!idle) return;
|
|
6655
|
+
if (continuationDispatchPendingRef.current) return;
|
|
6534
6656
|
const configuredAutoApproveTools = Array.isArray(autoApproveTools) ? new Set(
|
|
6535
6657
|
autoApproveTools.map((toolName) => normalizeToolName(String(toolName))).filter(Boolean)
|
|
6536
6658
|
) : null;
|
|
@@ -6559,6 +6681,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6559
6681
|
}
|
|
6560
6682
|
}, [
|
|
6561
6683
|
autoApproveTools,
|
|
6684
|
+
idle,
|
|
6562
6685
|
pendingToolRequests,
|
|
6563
6686
|
sessionApprovedTools,
|
|
6564
6687
|
alwaysApprovedTools,
|
|
@@ -6867,11 +6990,20 @@ ${traceSummary}` : traceSummary;
|
|
|
6867
6990
|
lastScrollTimeRef.current = now;
|
|
6868
6991
|
}, []);
|
|
6869
6992
|
const continueChat = useCallback2((promptText) => {
|
|
6993
|
+
const promptToSend = String(promptText || "").trim();
|
|
6994
|
+
if (!promptToSend) return;
|
|
6995
|
+
if (turnLockRef.current || hasInFlightTurnWork()) {
|
|
6996
|
+
queuePromptForLater(promptToSend);
|
|
6997
|
+
return;
|
|
6998
|
+
}
|
|
6999
|
+
turnLockRef.current = true;
|
|
6870
7000
|
handledToolCallSignaturesRef.current = /* @__PURE__ */ new Set();
|
|
6871
7001
|
inFlightToolCallSignaturesRef.current = /* @__PURE__ */ new Set();
|
|
6872
7002
|
toolContinuationCountRef.current = 0;
|
|
7003
|
+
successfulMutationSignaturesRef.current = /* @__PURE__ */ new Set();
|
|
6873
7004
|
activeStreamAppendBaseRef.current = null;
|
|
6874
7005
|
toolReplaySummariesByKeyRef.current = {};
|
|
7006
|
+
continuationDispatchPendingRef.current = false;
|
|
6875
7007
|
setPendingToolRequests([]);
|
|
6876
7008
|
setActiveToolCalls([]);
|
|
6877
7009
|
setCollapsedBlocks((prev) => {
|
|
@@ -6891,29 +7023,17 @@ ${traceSummary}` : traceSummary;
|
|
|
6891
7023
|
setUserHasScrolled(false);
|
|
6892
7024
|
prevResponseLengthRef.current = 0;
|
|
6893
7025
|
setResponse("");
|
|
6894
|
-
if (!idle) {
|
|
6895
|
-
stop(lastController);
|
|
6896
|
-
setHistory((prevHistory) => __spreadProps(__spreadValues({}, prevHistory), {
|
|
6897
|
-
[lastKey != null ? lastKey : ""]: {
|
|
6898
|
-
content: processThinkingTags(response).cleanedText + "\n\n(response cancelled)",
|
|
6899
|
-
callId: lastCallId || ""
|
|
6900
|
-
}
|
|
6901
|
-
}));
|
|
6902
|
-
return;
|
|
6903
|
-
}
|
|
6904
7026
|
if (clearFollowOnQuestionsNextPrompt) {
|
|
6905
7027
|
setFollowOnQuestionsState([]);
|
|
6906
7028
|
}
|
|
6907
|
-
const promptToSend = promptText;
|
|
6908
|
-
if (!promptToSend || !promptToSend.trim()) return;
|
|
6909
7029
|
setIsLoading(true);
|
|
6910
7030
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
6911
|
-
const promptKey = `${timestamp}:${promptToSend
|
|
7031
|
+
const promptKey = `${timestamp}:${promptToSend}`;
|
|
6912
7032
|
setHistory((prevHistory) => __spreadProps(__spreadValues({}, prevHistory), {
|
|
6913
7033
|
[promptKey]: { content: "", callId: "" }
|
|
6914
7034
|
}));
|
|
6915
7035
|
toolReplaySummariesByKeyRef.current[promptKey] = [];
|
|
6916
|
-
setLastPrompt(promptToSend
|
|
7036
|
+
setLastPrompt(promptToSend);
|
|
6917
7037
|
setLastKey(promptKey);
|
|
6918
7038
|
setTimeout(() => {
|
|
6919
7039
|
scrollToBottom(true);
|
|
@@ -6930,7 +7050,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6930
7050
|
messagesAndHistory.push({ role: "user", content: promptForHistory });
|
|
6931
7051
|
messagesAndHistory.push({ role: "assistant", content: assistantContextContent });
|
|
6932
7052
|
});
|
|
6933
|
-
let fullPromptToSend = promptToSend
|
|
7053
|
+
let fullPromptToSend = promptToSend;
|
|
6934
7054
|
if (messagesAndHistory.length === 0 && promptTemplate) {
|
|
6935
7055
|
fullPromptToSend = promptTemplate.replace("{{prompt}}", fullPromptToSend);
|
|
6936
7056
|
}
|
|
@@ -6939,7 +7059,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6939
7059
|
if (onBeforeSend) {
|
|
6940
7060
|
void Promise.resolve(
|
|
6941
7061
|
onBeforeSend({
|
|
6942
|
-
prompt: promptToSend
|
|
7062
|
+
prompt: promptToSend,
|
|
6943
7063
|
conversationId: convId || null,
|
|
6944
7064
|
agentId: agent,
|
|
6945
7065
|
service,
|
|
@@ -6973,6 +7093,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6973
7093
|
if (isAbortError) {
|
|
6974
7094
|
if (suppressAbortHistoryUpdateRef.current) {
|
|
6975
7095
|
setIsLoading(false);
|
|
7096
|
+
releaseTurnLockIfSettled();
|
|
6976
7097
|
return;
|
|
6977
7098
|
}
|
|
6978
7099
|
console.log("[AIChatPanel] Request was aborted by user");
|
|
@@ -7037,6 +7158,7 @@ ${traceSummary}` : traceSummary;
|
|
|
7037
7158
|
}
|
|
7038
7159
|
}
|
|
7039
7160
|
setIsLoading(false);
|
|
7161
|
+
releaseTurnLockIfSettled();
|
|
7040
7162
|
}
|
|
7041
7163
|
);
|
|
7042
7164
|
setLastMessages(messagesAndHistory);
|
|
@@ -7045,15 +7167,16 @@ ${traceSummary}` : traceSummary;
|
|
|
7045
7167
|
onConversationCreated(convId);
|
|
7046
7168
|
}, 100);
|
|
7047
7169
|
}
|
|
7170
|
+
}).catch((error2) => {
|
|
7171
|
+
console.error("[AIChatPanel] Failed to send prompt:", error2);
|
|
7172
|
+
setError({
|
|
7173
|
+
message: error2 instanceof Error ? error2.message : "Failed to send prompt",
|
|
7174
|
+
code: "UNKNOWN_ERROR"
|
|
7175
|
+
});
|
|
7176
|
+
setIsLoading(false);
|
|
7177
|
+
releaseTurnLockIfSettled();
|
|
7048
7178
|
});
|
|
7049
7179
|
}, [
|
|
7050
|
-
idle,
|
|
7051
|
-
stop,
|
|
7052
|
-
lastController,
|
|
7053
|
-
lastKey,
|
|
7054
|
-
response,
|
|
7055
|
-
lastCallId,
|
|
7056
|
-
processThinkingTags,
|
|
7057
7180
|
clearFollowOnQuestionsNextPrompt,
|
|
7058
7181
|
promptTemplate,
|
|
7059
7182
|
send,
|
|
@@ -7067,17 +7190,16 @@ ${traceSummary}` : traceSummary;
|
|
|
7067
7190
|
scrollToBottom,
|
|
7068
7191
|
onConversationCreated,
|
|
7069
7192
|
onBeforeSend,
|
|
7193
|
+
hasInFlightTurnWork,
|
|
7194
|
+
queuePromptForLater,
|
|
7195
|
+
releaseTurnLockIfSettled,
|
|
7070
7196
|
getThinkingBlockCollapseKey,
|
|
7071
7197
|
getThinkingBlockRenderKey,
|
|
7072
7198
|
setResponse
|
|
7073
7199
|
]);
|
|
7074
7200
|
const handleQueuePrompt = useCallback2((promptText) => {
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
const nextQueuedPrompts = [...queuedPromptsRef.current, normalizedPrompt];
|
|
7078
|
-
queuedPromptsRef.current = nextQueuedPrompts;
|
|
7079
|
-
setQueuedPrompts(nextQueuedPrompts);
|
|
7080
|
-
}, []);
|
|
7201
|
+
queuePromptForLater(promptText);
|
|
7202
|
+
}, [queuePromptForLater]);
|
|
7081
7203
|
const handleClearQueuedPrompt = useCallback2((index) => {
|
|
7082
7204
|
const nextQueuedPrompts = queuedPromptsRef.current.filter((_, queueIndex) => queueIndex !== index);
|
|
7083
7205
|
queuedPromptsRef.current = nextQueuedPrompts;
|
|
@@ -7089,18 +7211,6 @@ ${traceSummary}` : traceSummary;
|
|
|
7089
7211
|
const handleStop = useCallback2(() => {
|
|
7090
7212
|
stop(lastController);
|
|
7091
7213
|
}, [stop, lastController]);
|
|
7092
|
-
useEffect8(() => {
|
|
7093
|
-
const nextQueuedPrompt = String(queuedPromptsRef.current[0] || "").trim();
|
|
7094
|
-
if (!nextQueuedPrompt) return;
|
|
7095
|
-
if (!idle || isLoading) return;
|
|
7096
|
-
if (pendingToolRequests.length > 0 || activeToolCalls.length > 0) return;
|
|
7097
|
-
if (toolRequestProcessingRef.current) return;
|
|
7098
|
-
if ((queuedToolRequestsRef.current || []).length > 0) return;
|
|
7099
|
-
const remainingQueuedPrompts = queuedPromptsRef.current.slice(1);
|
|
7100
|
-
queuedPromptsRef.current = remainingQueuedPrompts;
|
|
7101
|
-
setQueuedPrompts(remainingQueuedPrompts);
|
|
7102
|
-
continueChat(nextQueuedPrompt);
|
|
7103
|
-
}, [activeToolCalls.length, continueChat, idle, isLoading, pendingToolRequests.length, queuedPrompts.length]);
|
|
7104
7214
|
const handleNewConversation = useCallback2(() => {
|
|
7105
7215
|
if (!newConversationConfirm) {
|
|
7106
7216
|
setNewConversationConfirm(true);
|
|
@@ -7141,6 +7251,7 @@ ${traceSummary}` : traceSummary;
|
|
|
7141
7251
|
setUserHasScrolled(false);
|
|
7142
7252
|
setError(null);
|
|
7143
7253
|
setActiveToolCalls([]);
|
|
7254
|
+
turnLockRef.current = false;
|
|
7144
7255
|
setTimeout(() => {
|
|
7145
7256
|
var _a2;
|
|
7146
7257
|
setJustReset(false);
|
|
@@ -7160,6 +7271,7 @@ ${traceSummary}` : traceSummary;
|
|
|
7160
7271
|
if (inFlightToolCallSignaturesRef.current.has(callSignature)) return false;
|
|
7161
7272
|
return true;
|
|
7162
7273
|
});
|
|
7274
|
+
pendingToolRequestsRef.current = unseenToolRequests;
|
|
7163
7275
|
setPendingToolRequests((prev) => {
|
|
7164
7276
|
if (areToolRequestListsEqual(prev, unseenToolRequests)) {
|
|
7165
7277
|
return prev;
|
|
@@ -7250,9 +7362,11 @@ ${traceSummary}` : traceSummary;
|
|
|
7250
7362
|
responseCompleteCallbackRef.current(currentLastCallId, currentLastPrompt || "", entry.content);
|
|
7251
7363
|
}
|
|
7252
7364
|
}
|
|
7365
|
+
releaseTurnLockIfSettled();
|
|
7253
7366
|
}
|
|
7254
7367
|
if (!isNowIdle && hasNotifiedCompletionRef.current) {
|
|
7255
7368
|
hasNotifiedCompletionRef.current = false;
|
|
7369
|
+
continuationDispatchPendingRef.current = false;
|
|
7256
7370
|
prevResponseLengthRef.current = 0;
|
|
7257
7371
|
const currentLastKey = lastKeyRef.current;
|
|
7258
7372
|
const existingContent = currentLastKey ? ((_a2 = latestHistoryRef.current[currentLastKey]) == null ? void 0 : _a2.content) || "" : "";
|
|
@@ -7261,7 +7375,48 @@ ${traceSummary}` : traceSummary;
|
|
|
7261
7375
|
base: existingContent
|
|
7262
7376
|
} : null;
|
|
7263
7377
|
}
|
|
7264
|
-
}, [idle]);
|
|
7378
|
+
}, [idle, releaseTurnLockIfSettled]);
|
|
7379
|
+
useEffect8(() => {
|
|
7380
|
+
if (!idle) return;
|
|
7381
|
+
releaseTurnLockIfSettled();
|
|
7382
|
+
}, [idle, response, pendingToolRequests.length, activeToolCalls.length, releaseTurnLockIfSettled]);
|
|
7383
|
+
useEffect8(() => {
|
|
7384
|
+
const nextQueuedPrompt = String(queuedPromptsRef.current[0] || "").trim();
|
|
7385
|
+
if (!nextQueuedPrompt) return;
|
|
7386
|
+
if (!idle || isLoading) return;
|
|
7387
|
+
if (pendingToolRequests.length > 0 || activeToolCalls.length > 0) return;
|
|
7388
|
+
if (turnLockRef.current || hasInFlightTurnWork()) return;
|
|
7389
|
+
if (queuedDrainScheduledRef.current) return;
|
|
7390
|
+
queuedDrainScheduledRef.current = true;
|
|
7391
|
+
queuedDrainTimerRef.current = window.setTimeout(() => {
|
|
7392
|
+
queuedDrainScheduledRef.current = false;
|
|
7393
|
+
queuedDrainTimerRef.current = null;
|
|
7394
|
+
const queuedPrompt = String(queuedPromptsRef.current[0] || "").trim();
|
|
7395
|
+
if (!queuedPrompt) return;
|
|
7396
|
+
if (turnLockRef.current || hasInFlightTurnWork()) return;
|
|
7397
|
+
const remainingQueuedPrompts = queuedPromptsRef.current.slice(1);
|
|
7398
|
+
queuedPromptsRef.current = remainingQueuedPrompts;
|
|
7399
|
+
setQueuedPrompts(remainingQueuedPrompts);
|
|
7400
|
+
continueChat(queuedPrompt);
|
|
7401
|
+
}, 0);
|
|
7402
|
+
}, [
|
|
7403
|
+
continueChat,
|
|
7404
|
+
hasInFlightTurnWork,
|
|
7405
|
+
idle,
|
|
7406
|
+
isLoading,
|
|
7407
|
+
pendingToolRequests.length,
|
|
7408
|
+
activeToolCalls.length,
|
|
7409
|
+
queuedPrompts.length
|
|
7410
|
+
]);
|
|
7411
|
+
useEffect8(() => {
|
|
7412
|
+
return () => {
|
|
7413
|
+
if (queuedDrainTimerRef.current !== null) {
|
|
7414
|
+
window.clearTimeout(queuedDrainTimerRef.current);
|
|
7415
|
+
queuedDrainTimerRef.current = null;
|
|
7416
|
+
}
|
|
7417
|
+
queuedDrainScheduledRef.current = false;
|
|
7418
|
+
};
|
|
7419
|
+
}, []);
|
|
7265
7420
|
useEffect8(() => {
|
|
7266
7421
|
scrollToEndRef.current = scrollToEnd || false;
|
|
7267
7422
|
}, [scrollToEnd]);
|
|
@@ -8554,7 +8709,49 @@ var parseCallMessages = (rawMessages) => {
|
|
|
8554
8709
|
return normalized;
|
|
8555
8710
|
};
|
|
8556
8711
|
var shouldSkipTranscriptMessage = (message) => {
|
|
8557
|
-
|
|
8712
|
+
const normalizedContent = message.content.trim().toLowerCase();
|
|
8713
|
+
const isInternalContinuationPrompt = message.role === "user" && normalizedContent.startsWith("original request:") && normalizedContent.includes("tool execution summary for the previous request:");
|
|
8714
|
+
return message.role === "system" || message.role === "user" && message.content.startsWith("__system__:") || isInternalContinuationPrompt;
|
|
8715
|
+
};
|
|
8716
|
+
var looksLikeToolStubResponse = (value) => {
|
|
8717
|
+
const text = value.trim();
|
|
8718
|
+
if (!text) return false;
|
|
8719
|
+
return text.includes('"type":"tool_use"') || text.includes('"type": "tool_use"') || text.includes('"type":"function"') || text.includes('"type": "function"');
|
|
8720
|
+
};
|
|
8721
|
+
var pickMoreCompleteResponse = (primaryResponse, fallbackResponse) => {
|
|
8722
|
+
const primary = primaryResponse.trim();
|
|
8723
|
+
const fallback = fallbackResponse.trim();
|
|
8724
|
+
if (!fallback) return primary;
|
|
8725
|
+
if (!primary) return fallback;
|
|
8726
|
+
if (primary === fallback) return primary;
|
|
8727
|
+
if (looksLikeToolStubResponse(primary) && !looksLikeToolStubResponse(fallback)) {
|
|
8728
|
+
return fallback;
|
|
8729
|
+
}
|
|
8730
|
+
if (fallback.startsWith(primary) || fallback.length > primary.length + 40) {
|
|
8731
|
+
return fallback;
|
|
8732
|
+
}
|
|
8733
|
+
return primary;
|
|
8734
|
+
};
|
|
8735
|
+
var mergeContinuationResponse = (baseResponse, continuationResponse) => {
|
|
8736
|
+
const base = baseResponse.trim();
|
|
8737
|
+
const continuation = continuationResponse.trim();
|
|
8738
|
+
if (!base) return continuation;
|
|
8739
|
+
if (!continuation) return base;
|
|
8740
|
+
if (looksLikeToolStubResponse(base) && !looksLikeToolStubResponse(continuation)) {
|
|
8741
|
+
return continuation;
|
|
8742
|
+
}
|
|
8743
|
+
if (base.includes(continuation)) {
|
|
8744
|
+
return base;
|
|
8745
|
+
}
|
|
8746
|
+
const maxOverlap = Math.min(base.length, continuation.length);
|
|
8747
|
+
for (let overlap = maxOverlap; overlap > 0; overlap -= 1) {
|
|
8748
|
+
if (base.slice(-overlap) === continuation.slice(0, overlap)) {
|
|
8749
|
+
return `${base}${continuation.slice(overlap)}`;
|
|
8750
|
+
}
|
|
8751
|
+
}
|
|
8752
|
+
return `${base}
|
|
8753
|
+
|
|
8754
|
+
${continuation}`;
|
|
8558
8755
|
};
|
|
8559
8756
|
var parseTimestampMs = (value) => {
|
|
8560
8757
|
const timestamp = toStringValue(value).trim();
|
|
@@ -8634,22 +8831,29 @@ var buildTurnsFromMessages = (messages, fallbackResponse, callId, timestampMs) =
|
|
|
8634
8831
|
const prompt = message.content.trim();
|
|
8635
8832
|
if (!prompt) continue;
|
|
8636
8833
|
let response = "";
|
|
8834
|
+
let lastAssistantIndex = -1;
|
|
8637
8835
|
let reachedNextUser = false;
|
|
8638
8836
|
for (let lookAhead = index + 1; lookAhead < messages.length; lookAhead += 1) {
|
|
8639
8837
|
const nextMessage = messages[lookAhead];
|
|
8640
8838
|
if (!nextMessage) continue;
|
|
8641
8839
|
if (nextMessage.role === "assistant") {
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8840
|
+
const assistantResponse = nextMessage.content.trim();
|
|
8841
|
+
if (assistantResponse) {
|
|
8842
|
+
response = assistantResponse;
|
|
8843
|
+
lastAssistantIndex = lookAhead;
|
|
8844
|
+
}
|
|
8845
|
+
continue;
|
|
8645
8846
|
}
|
|
8646
8847
|
if (nextMessage.role === "user") {
|
|
8647
8848
|
reachedNextUser = true;
|
|
8648
8849
|
break;
|
|
8649
8850
|
}
|
|
8650
8851
|
}
|
|
8651
|
-
if (
|
|
8652
|
-
|
|
8852
|
+
if (lastAssistantIndex >= 0) {
|
|
8853
|
+
index = lastAssistantIndex;
|
|
8854
|
+
}
|
|
8855
|
+
if (!reachedNextUser) {
|
|
8856
|
+
response = pickMoreCompleteResponse(response, fallbackResponse);
|
|
8653
8857
|
}
|
|
8654
8858
|
if (!response) continue;
|
|
8655
8859
|
turns.push({
|
|
@@ -8695,6 +8899,17 @@ var buildTranscriptTurnsFromCalls = (calls) => {
|
|
|
8695
8899
|
timestampMs
|
|
8696
8900
|
}
|
|
8697
8901
|
];
|
|
8902
|
+
} else if (fallbackResponse && mergedTurns.length > 0) {
|
|
8903
|
+
const previousTurn = mergedTurns[mergedTurns.length - 1];
|
|
8904
|
+
mergedTurns = [
|
|
8905
|
+
...mergedTurns.slice(0, -1),
|
|
8906
|
+
__spreadProps(__spreadValues({}, previousTurn), {
|
|
8907
|
+
response: mergeContinuationResponse(previousTurn.response, fallbackResponse),
|
|
8908
|
+
callId: callId || previousTurn.callId,
|
|
8909
|
+
timestampMs: Math.max(previousTurn.timestampMs, timestampMs)
|
|
8910
|
+
})
|
|
8911
|
+
];
|
|
8912
|
+
continue;
|
|
8698
8913
|
}
|
|
8699
8914
|
}
|
|
8700
8915
|
mergedTurns = mergeTranscriptTurns(mergedTurns, callTurns);
|