@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.js
CHANGED
|
@@ -5533,6 +5533,10 @@ var AIChatPanel = ({
|
|
|
5533
5533
|
const queuedToolRequestsRef = (0, import_react14.useRef)(null);
|
|
5534
5534
|
const suppressAbortHistoryUpdateRef = (0, import_react14.useRef)(false);
|
|
5535
5535
|
const toolReplaySummariesByKeyRef = (0, import_react14.useRef)({});
|
|
5536
|
+
const continuationDispatchPendingRef = (0, import_react14.useRef)(false);
|
|
5537
|
+
const successfulMutationSignaturesRef = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
|
|
5538
|
+
const queuedDrainTimerRef = (0, import_react14.useRef)(null);
|
|
5539
|
+
const queuedDrainScheduledRef = (0, import_react14.useRef)(false);
|
|
5536
5540
|
(0, import_react14.useEffect)(() => {
|
|
5537
5541
|
if (!initialHistory) return;
|
|
5538
5542
|
setHistory((prev) => {
|
|
@@ -6041,6 +6045,8 @@ var AIChatPanel = ({
|
|
|
6041
6045
|
return false;
|
|
6042
6046
|
}, [customerEmailCaptureMode, emailInputSet]);
|
|
6043
6047
|
const pendingToolRequestsRef = (0, import_react14.useRef)(pendingToolRequests);
|
|
6048
|
+
const activeToolCallsRef = (0, import_react14.useRef)(activeToolCalls);
|
|
6049
|
+
const turnLockRef = (0, import_react14.useRef)(false);
|
|
6044
6050
|
const streamIdleRef = (0, import_react14.useRef)(idle);
|
|
6045
6051
|
streamIdleRef.current = idle;
|
|
6046
6052
|
const waitForStreamIdle = (0, import_react14.useCallback)((timeoutMs = 2500) => __async(void 0, null, function* () {
|
|
@@ -6054,6 +6060,36 @@ var AIChatPanel = ({
|
|
|
6054
6060
|
(0, import_react14.useEffect)(() => {
|
|
6055
6061
|
pendingToolRequestsRef.current = pendingToolRequests;
|
|
6056
6062
|
}, [pendingToolRequests]);
|
|
6063
|
+
(0, import_react14.useEffect)(() => {
|
|
6064
|
+
activeToolCallsRef.current = activeToolCalls;
|
|
6065
|
+
}, [activeToolCalls]);
|
|
6066
|
+
const hasUnresolvedToolRequestsInLatestResponse = (0, import_react14.useCallback)(() => {
|
|
6067
|
+
const latestResponse = String(responseRef.current || "");
|
|
6068
|
+
if (!latestResponse.trim()) return false;
|
|
6069
|
+
const latestRequests = extractToolRequestMatchesFromText(latestResponse);
|
|
6070
|
+
if (latestRequests.length === 0) return false;
|
|
6071
|
+
return latestRequests.some((request) => {
|
|
6072
|
+
const signature = getToolCallSignature(request.toolName, request.callId);
|
|
6073
|
+
if (!signature) return false;
|
|
6074
|
+
if (handledToolCallSignaturesRef.current.has(signature)) return false;
|
|
6075
|
+
if (inFlightToolCallSignaturesRef.current.has(signature)) return false;
|
|
6076
|
+
return true;
|
|
6077
|
+
});
|
|
6078
|
+
}, [getToolCallSignature]);
|
|
6079
|
+
const hasInFlightTurnWork = (0, import_react14.useCallback)(() => {
|
|
6080
|
+
return toolRequestProcessingRef.current || continuationDispatchPendingRef.current || (queuedToolRequestsRef.current || []).length > 0 || (pendingToolRequestsRef.current || []).length > 0 || (activeToolCallsRef.current || []).length > 0 || !streamIdleRef.current || hasUnresolvedToolRequestsInLatestResponse();
|
|
6081
|
+
}, [hasUnresolvedToolRequestsInLatestResponse]);
|
|
6082
|
+
const queuePromptForLater = (0, import_react14.useCallback)((promptText) => {
|
|
6083
|
+
const normalizedPrompt = String(promptText || "").trim();
|
|
6084
|
+
if (!normalizedPrompt) return;
|
|
6085
|
+
const nextQueuedPrompts = [...queuedPromptsRef.current, normalizedPrompt];
|
|
6086
|
+
queuedPromptsRef.current = nextQueuedPrompts;
|
|
6087
|
+
setQueuedPrompts(nextQueuedPrompts);
|
|
6088
|
+
}, []);
|
|
6089
|
+
const releaseTurnLockIfSettled = (0, import_react14.useCallback)(() => {
|
|
6090
|
+
if (hasInFlightTurnWork()) return;
|
|
6091
|
+
turnLockRef.current = false;
|
|
6092
|
+
}, [hasInFlightTurnWork]);
|
|
6057
6093
|
const processGivenToolRequests = (0, import_react14.useCallback)(
|
|
6058
6094
|
(requests) => __async(void 0, null, function* () {
|
|
6059
6095
|
var _a2, _b, _c;
|
|
@@ -6080,6 +6116,7 @@ var AIChatPanel = ({
|
|
|
6080
6116
|
return;
|
|
6081
6117
|
}
|
|
6082
6118
|
toolRequestProcessingRef.current = true;
|
|
6119
|
+
turnLockRef.current = true;
|
|
6083
6120
|
try {
|
|
6084
6121
|
let requestsToProcess = requests;
|
|
6085
6122
|
if (!requestsToProcess || requestsToProcess.length === 0) {
|
|
@@ -6158,6 +6195,44 @@ ${traceSummary}` : traceSummary;
|
|
|
6158
6195
|
});
|
|
6159
6196
|
}
|
|
6160
6197
|
}
|
|
6198
|
+
const normalizeToolArgsForSignature = (value) => {
|
|
6199
|
+
if (Array.isArray(value)) {
|
|
6200
|
+
return value.map((item) => normalizeToolArgsForSignature(item));
|
|
6201
|
+
}
|
|
6202
|
+
if (value && typeof value === "object") {
|
|
6203
|
+
const normalizedObject = {};
|
|
6204
|
+
Object.keys(value).sort().forEach((key) => {
|
|
6205
|
+
normalizedObject[key] = normalizeToolArgsForSignature(
|
|
6206
|
+
value[key]
|
|
6207
|
+
);
|
|
6208
|
+
});
|
|
6209
|
+
return normalizedObject;
|
|
6210
|
+
}
|
|
6211
|
+
return value != null ? value : null;
|
|
6212
|
+
};
|
|
6213
|
+
const getSemanticMutationSignature = (toolName, args) => {
|
|
6214
|
+
const normalizedName = String(toolName || "").trim().toLowerCase();
|
|
6215
|
+
const normalizedArgs = normalizeToolArgsForSignature(args);
|
|
6216
|
+
return `${normalizedName}::${JSON.stringify(normalizedArgs)}`;
|
|
6217
|
+
};
|
|
6218
|
+
const isLikelyMutatingCall = (toolName, args) => {
|
|
6219
|
+
const normalizedName = String(toolName || "").trim().toLowerCase();
|
|
6220
|
+
const action = String((args == null ? void 0 : args.action) || "").trim().toLowerCase();
|
|
6221
|
+
const mutatingActions = /* @__PURE__ */ new Set([
|
|
6222
|
+
"add",
|
|
6223
|
+
"create",
|
|
6224
|
+
"materialize_from_sourcing_result",
|
|
6225
|
+
"materialize",
|
|
6226
|
+
"update",
|
|
6227
|
+
"delete",
|
|
6228
|
+
"remove",
|
|
6229
|
+
"cancel",
|
|
6230
|
+
"complete",
|
|
6231
|
+
"move"
|
|
6232
|
+
]);
|
|
6233
|
+
if (action && mutatingActions.has(action)) return true;
|
|
6234
|
+
return normalizedName.includes("pipeline") || normalizedName.includes("work_item") || normalizedName.includes("candidate_pipeline") || normalizedName.includes("cron");
|
|
6235
|
+
};
|
|
6161
6236
|
const parsedToolCalls = yield Promise.all(
|
|
6162
6237
|
requestsToProcess.map((req, index) => __async(void 0, null, function* () {
|
|
6163
6238
|
var _a3, _b2, _c2, _d, _e, _f;
|
|
@@ -6186,27 +6261,44 @@ ${traceSummary}` : traceSummary;
|
|
|
6186
6261
|
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 || "";
|
|
6187
6262
|
const callSignature = getToolCallSignature(toolName, callId);
|
|
6188
6263
|
if (!callSignature) return null;
|
|
6264
|
+
const semanticMutationSignature = getSemanticMutationSignature(toolName, args);
|
|
6265
|
+
const likelyMutating = isLikelyMutatingCall(toolName, args);
|
|
6189
6266
|
return {
|
|
6190
6267
|
req,
|
|
6191
6268
|
toolName,
|
|
6192
6269
|
callId,
|
|
6193
6270
|
args,
|
|
6194
6271
|
serviceTag,
|
|
6195
|
-
callSignature
|
|
6272
|
+
callSignature,
|
|
6273
|
+
semanticMutationSignature,
|
|
6274
|
+
likelyMutating
|
|
6196
6275
|
};
|
|
6197
6276
|
}))
|
|
6198
6277
|
);
|
|
6199
6278
|
const toolCallBatch = parsedToolCalls.filter(Boolean);
|
|
6200
6279
|
const seenCallSignatures = /* @__PURE__ */ new Set();
|
|
6280
|
+
const seenMutationSemanticsInBatch = /* @__PURE__ */ new Set();
|
|
6201
6281
|
const callsToRun = [];
|
|
6282
|
+
const suppressedMutationDuplicates = [];
|
|
6202
6283
|
toolCallBatch.forEach((toolCall) => {
|
|
6203
6284
|
if (seenCallSignatures.has(toolCall.callSignature)) return;
|
|
6204
6285
|
seenCallSignatures.add(toolCall.callSignature);
|
|
6205
6286
|
if (handledToolCallSignaturesRef.current.has(toolCall.callSignature)) return;
|
|
6206
6287
|
if (inFlightToolCallSignaturesRef.current.has(toolCall.callSignature)) return;
|
|
6288
|
+
if (toolCall.likelyMutating && seenMutationSemanticsInBatch.has(toolCall.semanticMutationSignature)) {
|
|
6289
|
+
suppressedMutationDuplicates.push(toolCall);
|
|
6290
|
+
return;
|
|
6291
|
+
}
|
|
6292
|
+
if (toolCall.likelyMutating && successfulMutationSignaturesRef.current.has(toolCall.semanticMutationSignature)) {
|
|
6293
|
+
suppressedMutationDuplicates.push(toolCall);
|
|
6294
|
+
return;
|
|
6295
|
+
}
|
|
6296
|
+
if (toolCall.likelyMutating) {
|
|
6297
|
+
seenMutationSemanticsInBatch.add(toolCall.semanticMutationSignature);
|
|
6298
|
+
}
|
|
6207
6299
|
callsToRun.push(toolCall);
|
|
6208
6300
|
});
|
|
6209
|
-
if (callsToRun.length === 0) {
|
|
6301
|
+
if (callsToRun.length === 0 && suppressedMutationDuplicates.length === 0) {
|
|
6210
6302
|
setPendingToolRequests(
|
|
6211
6303
|
(prev) => prev.filter((request) => {
|
|
6212
6304
|
const signature = getToolCallSignature(request.toolName, request.callId);
|
|
@@ -6218,11 +6310,14 @@ ${traceSummary}` : traceSummary;
|
|
|
6218
6310
|
setIsLoading(false);
|
|
6219
6311
|
return;
|
|
6220
6312
|
}
|
|
6221
|
-
const
|
|
6313
|
+
const handledBatchSignatures = /* @__PURE__ */ new Set([
|
|
6314
|
+
...callsToRun.map((toolCall) => toolCall.callSignature),
|
|
6315
|
+
...suppressedMutationDuplicates.map((toolCall) => toolCall.callSignature)
|
|
6316
|
+
]);
|
|
6222
6317
|
setPendingToolRequests(
|
|
6223
6318
|
(prev) => prev.filter((request) => {
|
|
6224
6319
|
const signature = getToolCallSignature(request.toolName, request.callId);
|
|
6225
|
-
return !signature || !
|
|
6320
|
+
return !signature || !handledBatchSignatures.has(signature);
|
|
6226
6321
|
})
|
|
6227
6322
|
);
|
|
6228
6323
|
callsToRun.forEach((toolCall) => {
|
|
@@ -6235,7 +6330,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6235
6330
|
args: toolCall.args
|
|
6236
6331
|
}))
|
|
6237
6332
|
);
|
|
6238
|
-
const finalToolCalls = callsToRun.map((toolCall) => ({
|
|
6333
|
+
const finalToolCalls = [...callsToRun, ...suppressedMutationDuplicates].map((toolCall) => ({
|
|
6239
6334
|
id: toolCall.callId,
|
|
6240
6335
|
type: "tool_use",
|
|
6241
6336
|
name: toolCall.toolName,
|
|
@@ -6366,12 +6461,30 @@ ${traceSummary}` : traceSummary;
|
|
|
6366
6461
|
}
|
|
6367
6462
|
}))
|
|
6368
6463
|
);
|
|
6369
|
-
|
|
6464
|
+
const executedResponses = toolResponses.filter(Boolean);
|
|
6465
|
+
const suppressedResponses = suppressedMutationDuplicates.map((toolCall) => ({
|
|
6466
|
+
tool_call_id: toolCall.callId,
|
|
6467
|
+
tool_name: toolCall.toolName,
|
|
6468
|
+
result: "Duplicate mutating call suppressed: this exact action already succeeded earlier in the same turn.",
|
|
6469
|
+
isError: false
|
|
6470
|
+
}));
|
|
6471
|
+
finalToolResponses = [...executedResponses, ...suppressedResponses];
|
|
6472
|
+
callsToRun.forEach((toolCall) => {
|
|
6473
|
+
const matchedResponse = executedResponses.find(
|
|
6474
|
+
(response2) => (response2 == null ? void 0 : response2.tool_call_id) === toolCall.callId
|
|
6475
|
+
);
|
|
6476
|
+
if (!(matchedResponse == null ? void 0 : matchedResponse.isError) && toolCall.likelyMutating) {
|
|
6477
|
+
successfulMutationSignaturesRef.current.add(toolCall.semanticMutationSignature);
|
|
6478
|
+
}
|
|
6479
|
+
});
|
|
6370
6480
|
} finally {
|
|
6371
6481
|
callsToRun.forEach((toolCall) => {
|
|
6372
6482
|
inFlightToolCallSignaturesRef.current.delete(toolCall.callSignature);
|
|
6373
6483
|
handledToolCallSignaturesRef.current.add(toolCall.callSignature);
|
|
6374
6484
|
});
|
|
6485
|
+
suppressedMutationDuplicates.forEach((toolCall) => {
|
|
6486
|
+
handledToolCallSignaturesRef.current.add(toolCall.callSignature);
|
|
6487
|
+
});
|
|
6375
6488
|
}
|
|
6376
6489
|
setActiveToolCalls([]);
|
|
6377
6490
|
const currentLastKey = lastKeyRef.current;
|
|
@@ -6475,6 +6588,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6475
6588
|
if (!streamIdleRef.current) {
|
|
6476
6589
|
setActiveToolCalls([]);
|
|
6477
6590
|
setIsLoading(false);
|
|
6591
|
+
continuationDispatchPendingRef.current = false;
|
|
6478
6592
|
setError({
|
|
6479
6593
|
message: "Timed out waiting for the previous stream to settle before tool continuation.",
|
|
6480
6594
|
code: "TOOL_CONTINUATION_WAIT_TIMEOUT"
|
|
@@ -6490,6 +6604,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6490
6604
|
} else {
|
|
6491
6605
|
activeStreamAppendBaseRef.current = null;
|
|
6492
6606
|
}
|
|
6607
|
+
continuationDispatchPendingRef.current = true;
|
|
6493
6608
|
send(
|
|
6494
6609
|
"",
|
|
6495
6610
|
newMessages,
|
|
@@ -6507,12 +6622,14 @@ ${traceSummary}` : traceSummary;
|
|
|
6507
6622
|
newController,
|
|
6508
6623
|
void 0,
|
|
6509
6624
|
(errorMsg) => {
|
|
6625
|
+
continuationDispatchPendingRef.current = false;
|
|
6510
6626
|
setActiveToolCalls([]);
|
|
6511
6627
|
setIsLoading(false);
|
|
6512
6628
|
setError({
|
|
6513
6629
|
message: errorMsg,
|
|
6514
6630
|
code: "TOOL_ERROR"
|
|
6515
6631
|
});
|
|
6632
|
+
releaseTurnLockIfSettled();
|
|
6516
6633
|
}
|
|
6517
6634
|
);
|
|
6518
6635
|
} finally {
|
|
@@ -6523,6 +6640,8 @@ ${traceSummary}` : traceSummary;
|
|
|
6523
6640
|
queueMicrotask(() => {
|
|
6524
6641
|
void processGivenToolRequests(queued);
|
|
6525
6642
|
});
|
|
6643
|
+
} else {
|
|
6644
|
+
releaseTurnLockIfSettled();
|
|
6526
6645
|
}
|
|
6527
6646
|
}
|
|
6528
6647
|
}),
|
|
@@ -6541,7 +6660,8 @@ ${traceSummary}` : traceSummary;
|
|
|
6541
6660
|
idle,
|
|
6542
6661
|
stop,
|
|
6543
6662
|
lastController,
|
|
6544
|
-
waitForStreamIdle
|
|
6663
|
+
waitForStreamIdle,
|
|
6664
|
+
releaseTurnLockIfSettled
|
|
6545
6665
|
]
|
|
6546
6666
|
);
|
|
6547
6667
|
const handleToolApproval = (0, import_react14.useCallback)(
|
|
@@ -6566,6 +6686,8 @@ ${traceSummary}` : traceSummary;
|
|
|
6566
6686
|
);
|
|
6567
6687
|
(0, import_react14.useEffect)(() => {
|
|
6568
6688
|
if (pendingToolRequests.length === 0) return;
|
|
6689
|
+
if (!idle) return;
|
|
6690
|
+
if (continuationDispatchPendingRef.current) return;
|
|
6569
6691
|
const configuredAutoApproveTools = Array.isArray(autoApproveTools) ? new Set(
|
|
6570
6692
|
autoApproveTools.map((toolName) => normalizeToolName(String(toolName))).filter(Boolean)
|
|
6571
6693
|
) : null;
|
|
@@ -6594,6 +6716,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6594
6716
|
}
|
|
6595
6717
|
}, [
|
|
6596
6718
|
autoApproveTools,
|
|
6719
|
+
idle,
|
|
6597
6720
|
pendingToolRequests,
|
|
6598
6721
|
sessionApprovedTools,
|
|
6599
6722
|
alwaysApprovedTools,
|
|
@@ -6902,11 +7025,20 @@ ${traceSummary}` : traceSummary;
|
|
|
6902
7025
|
lastScrollTimeRef.current = now;
|
|
6903
7026
|
}, []);
|
|
6904
7027
|
const continueChat = (0, import_react14.useCallback)((promptText) => {
|
|
7028
|
+
const promptToSend = String(promptText || "").trim();
|
|
7029
|
+
if (!promptToSend) return;
|
|
7030
|
+
if (turnLockRef.current || hasInFlightTurnWork()) {
|
|
7031
|
+
queuePromptForLater(promptToSend);
|
|
7032
|
+
return;
|
|
7033
|
+
}
|
|
7034
|
+
turnLockRef.current = true;
|
|
6905
7035
|
handledToolCallSignaturesRef.current = /* @__PURE__ */ new Set();
|
|
6906
7036
|
inFlightToolCallSignaturesRef.current = /* @__PURE__ */ new Set();
|
|
6907
7037
|
toolContinuationCountRef.current = 0;
|
|
7038
|
+
successfulMutationSignaturesRef.current = /* @__PURE__ */ new Set();
|
|
6908
7039
|
activeStreamAppendBaseRef.current = null;
|
|
6909
7040
|
toolReplaySummariesByKeyRef.current = {};
|
|
7041
|
+
continuationDispatchPendingRef.current = false;
|
|
6910
7042
|
setPendingToolRequests([]);
|
|
6911
7043
|
setActiveToolCalls([]);
|
|
6912
7044
|
setCollapsedBlocks((prev) => {
|
|
@@ -6926,29 +7058,17 @@ ${traceSummary}` : traceSummary;
|
|
|
6926
7058
|
setUserHasScrolled(false);
|
|
6927
7059
|
prevResponseLengthRef.current = 0;
|
|
6928
7060
|
setResponse("");
|
|
6929
|
-
if (!idle) {
|
|
6930
|
-
stop(lastController);
|
|
6931
|
-
setHistory((prevHistory) => __spreadProps(__spreadValues({}, prevHistory), {
|
|
6932
|
-
[lastKey != null ? lastKey : ""]: {
|
|
6933
|
-
content: processThinkingTags(response).cleanedText + "\n\n(response cancelled)",
|
|
6934
|
-
callId: lastCallId || ""
|
|
6935
|
-
}
|
|
6936
|
-
}));
|
|
6937
|
-
return;
|
|
6938
|
-
}
|
|
6939
7061
|
if (clearFollowOnQuestionsNextPrompt) {
|
|
6940
7062
|
setFollowOnQuestionsState([]);
|
|
6941
7063
|
}
|
|
6942
|
-
const promptToSend = promptText;
|
|
6943
|
-
if (!promptToSend || !promptToSend.trim()) return;
|
|
6944
7064
|
setIsLoading(true);
|
|
6945
7065
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
6946
|
-
const promptKey = `${timestamp}:${promptToSend
|
|
7066
|
+
const promptKey = `${timestamp}:${promptToSend}`;
|
|
6947
7067
|
setHistory((prevHistory) => __spreadProps(__spreadValues({}, prevHistory), {
|
|
6948
7068
|
[promptKey]: { content: "", callId: "" }
|
|
6949
7069
|
}));
|
|
6950
7070
|
toolReplaySummariesByKeyRef.current[promptKey] = [];
|
|
6951
|
-
setLastPrompt(promptToSend
|
|
7071
|
+
setLastPrompt(promptToSend);
|
|
6952
7072
|
setLastKey(promptKey);
|
|
6953
7073
|
setTimeout(() => {
|
|
6954
7074
|
scrollToBottom(true);
|
|
@@ -6965,7 +7085,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6965
7085
|
messagesAndHistory.push({ role: "user", content: promptForHistory });
|
|
6966
7086
|
messagesAndHistory.push({ role: "assistant", content: assistantContextContent });
|
|
6967
7087
|
});
|
|
6968
|
-
let fullPromptToSend = promptToSend
|
|
7088
|
+
let fullPromptToSend = promptToSend;
|
|
6969
7089
|
if (messagesAndHistory.length === 0 && promptTemplate) {
|
|
6970
7090
|
fullPromptToSend = promptTemplate.replace("{{prompt}}", fullPromptToSend);
|
|
6971
7091
|
}
|
|
@@ -6974,7 +7094,7 @@ ${traceSummary}` : traceSummary;
|
|
|
6974
7094
|
if (onBeforeSend) {
|
|
6975
7095
|
void Promise.resolve(
|
|
6976
7096
|
onBeforeSend({
|
|
6977
|
-
prompt: promptToSend
|
|
7097
|
+
prompt: promptToSend,
|
|
6978
7098
|
conversationId: convId || null,
|
|
6979
7099
|
agentId: agent,
|
|
6980
7100
|
service,
|
|
@@ -7008,6 +7128,7 @@ ${traceSummary}` : traceSummary;
|
|
|
7008
7128
|
if (isAbortError) {
|
|
7009
7129
|
if (suppressAbortHistoryUpdateRef.current) {
|
|
7010
7130
|
setIsLoading(false);
|
|
7131
|
+
releaseTurnLockIfSettled();
|
|
7011
7132
|
return;
|
|
7012
7133
|
}
|
|
7013
7134
|
console.log("[AIChatPanel] Request was aborted by user");
|
|
@@ -7072,6 +7193,7 @@ ${traceSummary}` : traceSummary;
|
|
|
7072
7193
|
}
|
|
7073
7194
|
}
|
|
7074
7195
|
setIsLoading(false);
|
|
7196
|
+
releaseTurnLockIfSettled();
|
|
7075
7197
|
}
|
|
7076
7198
|
);
|
|
7077
7199
|
setLastMessages(messagesAndHistory);
|
|
@@ -7080,15 +7202,16 @@ ${traceSummary}` : traceSummary;
|
|
|
7080
7202
|
onConversationCreated(convId);
|
|
7081
7203
|
}, 100);
|
|
7082
7204
|
}
|
|
7205
|
+
}).catch((error2) => {
|
|
7206
|
+
console.error("[AIChatPanel] Failed to send prompt:", error2);
|
|
7207
|
+
setError({
|
|
7208
|
+
message: error2 instanceof Error ? error2.message : "Failed to send prompt",
|
|
7209
|
+
code: "UNKNOWN_ERROR"
|
|
7210
|
+
});
|
|
7211
|
+
setIsLoading(false);
|
|
7212
|
+
releaseTurnLockIfSettled();
|
|
7083
7213
|
});
|
|
7084
7214
|
}, [
|
|
7085
|
-
idle,
|
|
7086
|
-
stop,
|
|
7087
|
-
lastController,
|
|
7088
|
-
lastKey,
|
|
7089
|
-
response,
|
|
7090
|
-
lastCallId,
|
|
7091
|
-
processThinkingTags,
|
|
7092
7215
|
clearFollowOnQuestionsNextPrompt,
|
|
7093
7216
|
promptTemplate,
|
|
7094
7217
|
send,
|
|
@@ -7102,17 +7225,16 @@ ${traceSummary}` : traceSummary;
|
|
|
7102
7225
|
scrollToBottom,
|
|
7103
7226
|
onConversationCreated,
|
|
7104
7227
|
onBeforeSend,
|
|
7228
|
+
hasInFlightTurnWork,
|
|
7229
|
+
queuePromptForLater,
|
|
7230
|
+
releaseTurnLockIfSettled,
|
|
7105
7231
|
getThinkingBlockCollapseKey,
|
|
7106
7232
|
getThinkingBlockRenderKey,
|
|
7107
7233
|
setResponse
|
|
7108
7234
|
]);
|
|
7109
7235
|
const handleQueuePrompt = (0, import_react14.useCallback)((promptText) => {
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
const nextQueuedPrompts = [...queuedPromptsRef.current, normalizedPrompt];
|
|
7113
|
-
queuedPromptsRef.current = nextQueuedPrompts;
|
|
7114
|
-
setQueuedPrompts(nextQueuedPrompts);
|
|
7115
|
-
}, []);
|
|
7236
|
+
queuePromptForLater(promptText);
|
|
7237
|
+
}, [queuePromptForLater]);
|
|
7116
7238
|
const handleClearQueuedPrompt = (0, import_react14.useCallback)((index) => {
|
|
7117
7239
|
const nextQueuedPrompts = queuedPromptsRef.current.filter((_, queueIndex) => queueIndex !== index);
|
|
7118
7240
|
queuedPromptsRef.current = nextQueuedPrompts;
|
|
@@ -7124,18 +7246,6 @@ ${traceSummary}` : traceSummary;
|
|
|
7124
7246
|
const handleStop = (0, import_react14.useCallback)(() => {
|
|
7125
7247
|
stop(lastController);
|
|
7126
7248
|
}, [stop, lastController]);
|
|
7127
|
-
(0, import_react14.useEffect)(() => {
|
|
7128
|
-
const nextQueuedPrompt = String(queuedPromptsRef.current[0] || "").trim();
|
|
7129
|
-
if (!nextQueuedPrompt) return;
|
|
7130
|
-
if (!idle || isLoading) return;
|
|
7131
|
-
if (pendingToolRequests.length > 0 || activeToolCalls.length > 0) return;
|
|
7132
|
-
if (toolRequestProcessingRef.current) return;
|
|
7133
|
-
if ((queuedToolRequestsRef.current || []).length > 0) return;
|
|
7134
|
-
const remainingQueuedPrompts = queuedPromptsRef.current.slice(1);
|
|
7135
|
-
queuedPromptsRef.current = remainingQueuedPrompts;
|
|
7136
|
-
setQueuedPrompts(remainingQueuedPrompts);
|
|
7137
|
-
continueChat(nextQueuedPrompt);
|
|
7138
|
-
}, [activeToolCalls.length, continueChat, idle, isLoading, pendingToolRequests.length, queuedPrompts.length]);
|
|
7139
7249
|
const handleNewConversation = (0, import_react14.useCallback)(() => {
|
|
7140
7250
|
if (!newConversationConfirm) {
|
|
7141
7251
|
setNewConversationConfirm(true);
|
|
@@ -7176,6 +7286,7 @@ ${traceSummary}` : traceSummary;
|
|
|
7176
7286
|
setUserHasScrolled(false);
|
|
7177
7287
|
setError(null);
|
|
7178
7288
|
setActiveToolCalls([]);
|
|
7289
|
+
turnLockRef.current = false;
|
|
7179
7290
|
setTimeout(() => {
|
|
7180
7291
|
var _a2;
|
|
7181
7292
|
setJustReset(false);
|
|
@@ -7195,6 +7306,7 @@ ${traceSummary}` : traceSummary;
|
|
|
7195
7306
|
if (inFlightToolCallSignaturesRef.current.has(callSignature)) return false;
|
|
7196
7307
|
return true;
|
|
7197
7308
|
});
|
|
7309
|
+
pendingToolRequestsRef.current = unseenToolRequests;
|
|
7198
7310
|
setPendingToolRequests((prev) => {
|
|
7199
7311
|
if (areToolRequestListsEqual(prev, unseenToolRequests)) {
|
|
7200
7312
|
return prev;
|
|
@@ -7285,9 +7397,11 @@ ${traceSummary}` : traceSummary;
|
|
|
7285
7397
|
responseCompleteCallbackRef.current(currentLastCallId, currentLastPrompt || "", entry.content);
|
|
7286
7398
|
}
|
|
7287
7399
|
}
|
|
7400
|
+
releaseTurnLockIfSettled();
|
|
7288
7401
|
}
|
|
7289
7402
|
if (!isNowIdle && hasNotifiedCompletionRef.current) {
|
|
7290
7403
|
hasNotifiedCompletionRef.current = false;
|
|
7404
|
+
continuationDispatchPendingRef.current = false;
|
|
7291
7405
|
prevResponseLengthRef.current = 0;
|
|
7292
7406
|
const currentLastKey = lastKeyRef.current;
|
|
7293
7407
|
const existingContent = currentLastKey ? ((_a2 = latestHistoryRef.current[currentLastKey]) == null ? void 0 : _a2.content) || "" : "";
|
|
@@ -7296,7 +7410,48 @@ ${traceSummary}` : traceSummary;
|
|
|
7296
7410
|
base: existingContent
|
|
7297
7411
|
} : null;
|
|
7298
7412
|
}
|
|
7299
|
-
}, [idle]);
|
|
7413
|
+
}, [idle, releaseTurnLockIfSettled]);
|
|
7414
|
+
(0, import_react14.useEffect)(() => {
|
|
7415
|
+
if (!idle) return;
|
|
7416
|
+
releaseTurnLockIfSettled();
|
|
7417
|
+
}, [idle, response, pendingToolRequests.length, activeToolCalls.length, releaseTurnLockIfSettled]);
|
|
7418
|
+
(0, import_react14.useEffect)(() => {
|
|
7419
|
+
const nextQueuedPrompt = String(queuedPromptsRef.current[0] || "").trim();
|
|
7420
|
+
if (!nextQueuedPrompt) return;
|
|
7421
|
+
if (!idle || isLoading) return;
|
|
7422
|
+
if (pendingToolRequests.length > 0 || activeToolCalls.length > 0) return;
|
|
7423
|
+
if (turnLockRef.current || hasInFlightTurnWork()) return;
|
|
7424
|
+
if (queuedDrainScheduledRef.current) return;
|
|
7425
|
+
queuedDrainScheduledRef.current = true;
|
|
7426
|
+
queuedDrainTimerRef.current = window.setTimeout(() => {
|
|
7427
|
+
queuedDrainScheduledRef.current = false;
|
|
7428
|
+
queuedDrainTimerRef.current = null;
|
|
7429
|
+
const queuedPrompt = String(queuedPromptsRef.current[0] || "").trim();
|
|
7430
|
+
if (!queuedPrompt) return;
|
|
7431
|
+
if (turnLockRef.current || hasInFlightTurnWork()) return;
|
|
7432
|
+
const remainingQueuedPrompts = queuedPromptsRef.current.slice(1);
|
|
7433
|
+
queuedPromptsRef.current = remainingQueuedPrompts;
|
|
7434
|
+
setQueuedPrompts(remainingQueuedPrompts);
|
|
7435
|
+
continueChat(queuedPrompt);
|
|
7436
|
+
}, 0);
|
|
7437
|
+
}, [
|
|
7438
|
+
continueChat,
|
|
7439
|
+
hasInFlightTurnWork,
|
|
7440
|
+
idle,
|
|
7441
|
+
isLoading,
|
|
7442
|
+
pendingToolRequests.length,
|
|
7443
|
+
activeToolCalls.length,
|
|
7444
|
+
queuedPrompts.length
|
|
7445
|
+
]);
|
|
7446
|
+
(0, import_react14.useEffect)(() => {
|
|
7447
|
+
return () => {
|
|
7448
|
+
if (queuedDrainTimerRef.current !== null) {
|
|
7449
|
+
window.clearTimeout(queuedDrainTimerRef.current);
|
|
7450
|
+
queuedDrainTimerRef.current = null;
|
|
7451
|
+
}
|
|
7452
|
+
queuedDrainScheduledRef.current = false;
|
|
7453
|
+
};
|
|
7454
|
+
}, []);
|
|
7300
7455
|
(0, import_react14.useEffect)(() => {
|
|
7301
7456
|
scrollToEndRef.current = scrollToEnd || false;
|
|
7302
7457
|
}, [scrollToEnd]);
|
|
@@ -8589,7 +8744,49 @@ var parseCallMessages = (rawMessages) => {
|
|
|
8589
8744
|
return normalized;
|
|
8590
8745
|
};
|
|
8591
8746
|
var shouldSkipTranscriptMessage = (message) => {
|
|
8592
|
-
|
|
8747
|
+
const normalizedContent = message.content.trim().toLowerCase();
|
|
8748
|
+
const isInternalContinuationPrompt = message.role === "user" && normalizedContent.startsWith("original request:") && normalizedContent.includes("tool execution summary for the previous request:");
|
|
8749
|
+
return message.role === "system" || message.role === "user" && message.content.startsWith("__system__:") || isInternalContinuationPrompt;
|
|
8750
|
+
};
|
|
8751
|
+
var looksLikeToolStubResponse = (value) => {
|
|
8752
|
+
const text = value.trim();
|
|
8753
|
+
if (!text) return false;
|
|
8754
|
+
return text.includes('"type":"tool_use"') || text.includes('"type": "tool_use"') || text.includes('"type":"function"') || text.includes('"type": "function"');
|
|
8755
|
+
};
|
|
8756
|
+
var pickMoreCompleteResponse = (primaryResponse, fallbackResponse) => {
|
|
8757
|
+
const primary = primaryResponse.trim();
|
|
8758
|
+
const fallback = fallbackResponse.trim();
|
|
8759
|
+
if (!fallback) return primary;
|
|
8760
|
+
if (!primary) return fallback;
|
|
8761
|
+
if (primary === fallback) return primary;
|
|
8762
|
+
if (looksLikeToolStubResponse(primary) && !looksLikeToolStubResponse(fallback)) {
|
|
8763
|
+
return fallback;
|
|
8764
|
+
}
|
|
8765
|
+
if (fallback.startsWith(primary) || fallback.length > primary.length + 40) {
|
|
8766
|
+
return fallback;
|
|
8767
|
+
}
|
|
8768
|
+
return primary;
|
|
8769
|
+
};
|
|
8770
|
+
var mergeContinuationResponse = (baseResponse, continuationResponse) => {
|
|
8771
|
+
const base = baseResponse.trim();
|
|
8772
|
+
const continuation = continuationResponse.trim();
|
|
8773
|
+
if (!base) return continuation;
|
|
8774
|
+
if (!continuation) return base;
|
|
8775
|
+
if (looksLikeToolStubResponse(base) && !looksLikeToolStubResponse(continuation)) {
|
|
8776
|
+
return continuation;
|
|
8777
|
+
}
|
|
8778
|
+
if (base.includes(continuation)) {
|
|
8779
|
+
return base;
|
|
8780
|
+
}
|
|
8781
|
+
const maxOverlap = Math.min(base.length, continuation.length);
|
|
8782
|
+
for (let overlap = maxOverlap; overlap > 0; overlap -= 1) {
|
|
8783
|
+
if (base.slice(-overlap) === continuation.slice(0, overlap)) {
|
|
8784
|
+
return `${base}${continuation.slice(overlap)}`;
|
|
8785
|
+
}
|
|
8786
|
+
}
|
|
8787
|
+
return `${base}
|
|
8788
|
+
|
|
8789
|
+
${continuation}`;
|
|
8593
8790
|
};
|
|
8594
8791
|
var parseTimestampMs = (value) => {
|
|
8595
8792
|
const timestamp = toStringValue(value).trim();
|
|
@@ -8669,22 +8866,29 @@ var buildTurnsFromMessages = (messages, fallbackResponse, callId, timestampMs) =
|
|
|
8669
8866
|
const prompt = message.content.trim();
|
|
8670
8867
|
if (!prompt) continue;
|
|
8671
8868
|
let response = "";
|
|
8869
|
+
let lastAssistantIndex = -1;
|
|
8672
8870
|
let reachedNextUser = false;
|
|
8673
8871
|
for (let lookAhead = index + 1; lookAhead < messages.length; lookAhead += 1) {
|
|
8674
8872
|
const nextMessage = messages[lookAhead];
|
|
8675
8873
|
if (!nextMessage) continue;
|
|
8676
8874
|
if (nextMessage.role === "assistant") {
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
|
|
8875
|
+
const assistantResponse = nextMessage.content.trim();
|
|
8876
|
+
if (assistantResponse) {
|
|
8877
|
+
response = assistantResponse;
|
|
8878
|
+
lastAssistantIndex = lookAhead;
|
|
8879
|
+
}
|
|
8880
|
+
continue;
|
|
8680
8881
|
}
|
|
8681
8882
|
if (nextMessage.role === "user") {
|
|
8682
8883
|
reachedNextUser = true;
|
|
8683
8884
|
break;
|
|
8684
8885
|
}
|
|
8685
8886
|
}
|
|
8686
|
-
if (
|
|
8687
|
-
|
|
8887
|
+
if (lastAssistantIndex >= 0) {
|
|
8888
|
+
index = lastAssistantIndex;
|
|
8889
|
+
}
|
|
8890
|
+
if (!reachedNextUser) {
|
|
8891
|
+
response = pickMoreCompleteResponse(response, fallbackResponse);
|
|
8688
8892
|
}
|
|
8689
8893
|
if (!response) continue;
|
|
8690
8894
|
turns.push({
|
|
@@ -8730,6 +8934,17 @@ var buildTranscriptTurnsFromCalls = (calls) => {
|
|
|
8730
8934
|
timestampMs
|
|
8731
8935
|
}
|
|
8732
8936
|
];
|
|
8937
|
+
} else if (fallbackResponse && mergedTurns.length > 0) {
|
|
8938
|
+
const previousTurn = mergedTurns[mergedTurns.length - 1];
|
|
8939
|
+
mergedTurns = [
|
|
8940
|
+
...mergedTurns.slice(0, -1),
|
|
8941
|
+
__spreadProps(__spreadValues({}, previousTurn), {
|
|
8942
|
+
response: mergeContinuationResponse(previousTurn.response, fallbackResponse),
|
|
8943
|
+
callId: callId || previousTurn.callId,
|
|
8944
|
+
timestampMs: Math.max(previousTurn.timestampMs, timestampMs)
|
|
8945
|
+
})
|
|
8946
|
+
];
|
|
8947
|
+
continue;
|
|
8733
8948
|
}
|
|
8734
8949
|
}
|
|
8735
8950
|
mergedTurns = mergeTranscriptTurns(mergedTurns, callTurns);
|