@hef2024/llmasaservice-ui 0.24.2 → 0.24.4
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.css +256 -62
- package/dist/index.d.mts +158 -115
- package/dist/index.d.ts +158 -115
- package/dist/index.js +3099 -568
- package/dist/index.mjs +3099 -568
- package/index.ts +6 -1
- package/package.json +1 -1
- package/src/AIAgentPanel.tsx +647 -207
- package/src/AIChatPanel.css +286 -37
- package/src/AIChatPanel.tsx +2871 -358
- package/src/AgentPanel.tsx +4 -0
- package/src/ChatPanel.tsx +254 -104
- package/src/hooks/useAgentRegistry.ts +2 -1
- package/src/mcpAuth.ts +36 -0
- package/src/toolArgsParser.ts +346 -0
package/dist/index.js
CHANGED
|
@@ -693,6 +693,302 @@ var ThinkingBlock = ({
|
|
|
693
693
|
);
|
|
694
694
|
};
|
|
695
695
|
|
|
696
|
+
// src/mcpAuth.ts
|
|
697
|
+
function normalizeMcpHeaders(value) {
|
|
698
|
+
const normalized = {};
|
|
699
|
+
if (!value) return normalized;
|
|
700
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
701
|
+
if (typeof raw !== "string") continue;
|
|
702
|
+
const trimmedValue = raw.trim();
|
|
703
|
+
if (!trimmedValue) continue;
|
|
704
|
+
normalized[key] = trimmedValue;
|
|
705
|
+
}
|
|
706
|
+
return normalized;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// src/toolArgsParser.ts
|
|
710
|
+
var TOOL_ARGS_CANDIDATE_PARSE_DEPTH = 3;
|
|
711
|
+
var isPlainObject = (value) => {
|
|
712
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
713
|
+
};
|
|
714
|
+
var stripMarkdownCodeFence = (input) => {
|
|
715
|
+
const trimmed = input.trim();
|
|
716
|
+
if (!trimmed.startsWith("```")) return trimmed;
|
|
717
|
+
const withoutStart = trimmed.replace(/^```[a-zA-Z0-9_-]*\s*/u, "");
|
|
718
|
+
return withoutStart.replace(/```$/u, "").trim();
|
|
719
|
+
};
|
|
720
|
+
var stripOuterQuotes = (input) => {
|
|
721
|
+
const trimmed = input.trim();
|
|
722
|
+
if (trimmed.length < 2) return trimmed;
|
|
723
|
+
const first = trimmed[0];
|
|
724
|
+
const last = trimmed[trimmed.length - 1];
|
|
725
|
+
if (first === '"' && last === '"' || first === "'" && last === "'") {
|
|
726
|
+
return trimmed.slice(1, -1).trim();
|
|
727
|
+
}
|
|
728
|
+
return trimmed;
|
|
729
|
+
};
|
|
730
|
+
var normalizeSmartQuotes = (input) => {
|
|
731
|
+
return input.replace(/[“”]/gu, '"').replace(/[‘’]/gu, "'");
|
|
732
|
+
};
|
|
733
|
+
var convertSingleQuotedStrings = (input) => {
|
|
734
|
+
let output = "";
|
|
735
|
+
let inSingle = false;
|
|
736
|
+
let inDouble = false;
|
|
737
|
+
let escaped = false;
|
|
738
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
739
|
+
const char = input[index];
|
|
740
|
+
if (inSingle) {
|
|
741
|
+
if (escaped) {
|
|
742
|
+
output += char === '"' ? '\\"' : char;
|
|
743
|
+
escaped = false;
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
if (char === "\\") {
|
|
747
|
+
output += "\\";
|
|
748
|
+
escaped = true;
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
if (char === "'") {
|
|
752
|
+
output += '"';
|
|
753
|
+
inSingle = false;
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
output += char === '"' ? '\\"' : char;
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
if (inDouble) {
|
|
760
|
+
output += char;
|
|
761
|
+
if (escaped) {
|
|
762
|
+
escaped = false;
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
if (char === "\\") {
|
|
766
|
+
escaped = true;
|
|
767
|
+
continue;
|
|
768
|
+
}
|
|
769
|
+
if (char === '"') {
|
|
770
|
+
inDouble = false;
|
|
771
|
+
}
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
774
|
+
if (char === "'") {
|
|
775
|
+
output += '"';
|
|
776
|
+
inSingle = true;
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
if (char === '"') {
|
|
780
|
+
output += '"';
|
|
781
|
+
inDouble = true;
|
|
782
|
+
continue;
|
|
783
|
+
}
|
|
784
|
+
output += char;
|
|
785
|
+
}
|
|
786
|
+
return output;
|
|
787
|
+
};
|
|
788
|
+
var quoteBareObjectKeys = (input) => {
|
|
789
|
+
return input.replace(
|
|
790
|
+
/([{,]\s*)([A-Za-z_$][A-Za-z0-9_$-]*)(\s*:)/gu,
|
|
791
|
+
'$1"$2"$3'
|
|
792
|
+
);
|
|
793
|
+
};
|
|
794
|
+
var stripTrailingCommas = (input) => {
|
|
795
|
+
return input.replace(/,\s*([}\]])/gu, "$1");
|
|
796
|
+
};
|
|
797
|
+
var normalizeEscapesOutsideStrings = (input) => {
|
|
798
|
+
let output = "";
|
|
799
|
+
let inDouble = false;
|
|
800
|
+
let inSingle = false;
|
|
801
|
+
let escaped = false;
|
|
802
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
803
|
+
const char = input[index];
|
|
804
|
+
const next = index + 1 < input.length ? input[index + 1] : "";
|
|
805
|
+
if (inDouble || inSingle) {
|
|
806
|
+
output += char;
|
|
807
|
+
if (escaped) {
|
|
808
|
+
escaped = false;
|
|
809
|
+
continue;
|
|
810
|
+
}
|
|
811
|
+
if (char === "\\") {
|
|
812
|
+
escaped = true;
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
if (inDouble && char === '"') {
|
|
816
|
+
inDouble = false;
|
|
817
|
+
} else if (inSingle && char === "'") {
|
|
818
|
+
inSingle = false;
|
|
819
|
+
}
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
if (char === '"') {
|
|
823
|
+
inDouble = true;
|
|
824
|
+
output += char;
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
827
|
+
if (char === "'") {
|
|
828
|
+
inSingle = true;
|
|
829
|
+
output += char;
|
|
830
|
+
continue;
|
|
831
|
+
}
|
|
832
|
+
if (char === "\\") {
|
|
833
|
+
if (next === "n") {
|
|
834
|
+
output += "\n";
|
|
835
|
+
index += 1;
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
838
|
+
if (next === "r") {
|
|
839
|
+
output += "\r";
|
|
840
|
+
index += 1;
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
if (next === "t") {
|
|
844
|
+
output += " ";
|
|
845
|
+
index += 1;
|
|
846
|
+
continue;
|
|
847
|
+
}
|
|
848
|
+
if (next === '"') {
|
|
849
|
+
output += '"';
|
|
850
|
+
index += 1;
|
|
851
|
+
continue;
|
|
852
|
+
}
|
|
853
|
+
if (next === "'") {
|
|
854
|
+
output += "'";
|
|
855
|
+
index += 1;
|
|
856
|
+
continue;
|
|
857
|
+
}
|
|
858
|
+
if (next === "\\") {
|
|
859
|
+
output += "\\";
|
|
860
|
+
index += 1;
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
output += char;
|
|
865
|
+
}
|
|
866
|
+
return output;
|
|
867
|
+
};
|
|
868
|
+
var normalizeJsLikeJson = (input) => {
|
|
869
|
+
const normalizedQuotes = normalizeSmartQuotes(input);
|
|
870
|
+
const normalizedSingleQuotes = convertSingleQuotedStrings(normalizedQuotes);
|
|
871
|
+
const withQuotedKeys = quoteBareObjectKeys(normalizedSingleQuotes);
|
|
872
|
+
return stripTrailingCommas(withQuotedKeys);
|
|
873
|
+
};
|
|
874
|
+
var extractFirstJsonObject = (input) => {
|
|
875
|
+
const start = input.indexOf("{");
|
|
876
|
+
if (start === -1) return null;
|
|
877
|
+
let depth = 0;
|
|
878
|
+
let inString = false;
|
|
879
|
+
let quoteChar = "";
|
|
880
|
+
let escaped = false;
|
|
881
|
+
for (let index = start; index < input.length; index += 1) {
|
|
882
|
+
const char = input[index];
|
|
883
|
+
if (inString) {
|
|
884
|
+
if (escaped) {
|
|
885
|
+
escaped = false;
|
|
886
|
+
continue;
|
|
887
|
+
}
|
|
888
|
+
if (char === "\\") {
|
|
889
|
+
escaped = true;
|
|
890
|
+
continue;
|
|
891
|
+
}
|
|
892
|
+
if (char === quoteChar) {
|
|
893
|
+
inString = false;
|
|
894
|
+
quoteChar = "";
|
|
895
|
+
}
|
|
896
|
+
continue;
|
|
897
|
+
}
|
|
898
|
+
if (char === '"' || char === "'") {
|
|
899
|
+
inString = true;
|
|
900
|
+
quoteChar = char;
|
|
901
|
+
continue;
|
|
902
|
+
}
|
|
903
|
+
if (char === "{") {
|
|
904
|
+
depth += 1;
|
|
905
|
+
continue;
|
|
906
|
+
}
|
|
907
|
+
if (char === "}") {
|
|
908
|
+
depth -= 1;
|
|
909
|
+
if (depth === 0) {
|
|
910
|
+
return input.slice(start, index + 1);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
return null;
|
|
915
|
+
};
|
|
916
|
+
var parseMaybeNestedJson = (input) => {
|
|
917
|
+
let current = input;
|
|
918
|
+
for (let depth = 0; depth < TOOL_ARGS_CANDIDATE_PARSE_DEPTH; depth += 1) {
|
|
919
|
+
if (typeof current !== "string") {
|
|
920
|
+
return current;
|
|
921
|
+
}
|
|
922
|
+
const trimmed = current.trim();
|
|
923
|
+
if (!trimmed) {
|
|
924
|
+
return {};
|
|
925
|
+
}
|
|
926
|
+
current = JSON.parse(trimmed);
|
|
927
|
+
}
|
|
928
|
+
return current;
|
|
929
|
+
};
|
|
930
|
+
var addCandidate = (candidates, value) => {
|
|
931
|
+
if (typeof value !== "string") return;
|
|
932
|
+
const trimmed = value.trim();
|
|
933
|
+
if (!trimmed) return;
|
|
934
|
+
candidates.add(trimmed);
|
|
935
|
+
};
|
|
936
|
+
var buildProgressiveQuoteUnescapes = (input, rounds = 4) => {
|
|
937
|
+
const values = [];
|
|
938
|
+
let current = input;
|
|
939
|
+
for (let round = 0; round < rounds; round += 1) {
|
|
940
|
+
const next = current.replace(/\\"/gu, '"');
|
|
941
|
+
if (next === current) {
|
|
942
|
+
break;
|
|
943
|
+
}
|
|
944
|
+
values.push(next);
|
|
945
|
+
current = next;
|
|
946
|
+
}
|
|
947
|
+
return values;
|
|
948
|
+
};
|
|
949
|
+
var parseToolArguments = (rawArgs) => {
|
|
950
|
+
if (isPlainObject(rawArgs)) {
|
|
951
|
+
return rawArgs;
|
|
952
|
+
}
|
|
953
|
+
if (typeof rawArgs !== "string") {
|
|
954
|
+
return {};
|
|
955
|
+
}
|
|
956
|
+
const base = rawArgs.trim();
|
|
957
|
+
if (!base) {
|
|
958
|
+
return {};
|
|
959
|
+
}
|
|
960
|
+
const codeFenceStripped = stripMarkdownCodeFence(base);
|
|
961
|
+
const extracted = extractFirstJsonObject(codeFenceStripped);
|
|
962
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
963
|
+
addCandidate(candidates, base);
|
|
964
|
+
addCandidate(candidates, codeFenceStripped);
|
|
965
|
+
addCandidate(candidates, stripOuterQuotes(codeFenceStripped));
|
|
966
|
+
buildProgressiveQuoteUnescapes(base).forEach((candidate) => addCandidate(candidates, candidate));
|
|
967
|
+
buildProgressiveQuoteUnescapes(codeFenceStripped).forEach(
|
|
968
|
+
(candidate) => addCandidate(candidates, candidate)
|
|
969
|
+
);
|
|
970
|
+
addCandidate(candidates, extracted);
|
|
971
|
+
buildProgressiveQuoteUnescapes(extracted || "").forEach(
|
|
972
|
+
(candidate) => addCandidate(candidates, candidate)
|
|
973
|
+
);
|
|
974
|
+
addCandidate(candidates, normalizeJsLikeJson(codeFenceStripped));
|
|
975
|
+
addCandidate(candidates, extracted ? normalizeJsLikeJson(extracted) : null);
|
|
976
|
+
Array.from(candidates).forEach((candidate) => {
|
|
977
|
+
addCandidate(candidates, normalizeEscapesOutsideStrings(candidate));
|
|
978
|
+
});
|
|
979
|
+
for (const candidate of candidates) {
|
|
980
|
+
try {
|
|
981
|
+
const parsed = parseMaybeNestedJson(candidate);
|
|
982
|
+
if (isPlainObject(parsed)) {
|
|
983
|
+
return parsed;
|
|
984
|
+
}
|
|
985
|
+
} catch (e) {
|
|
986
|
+
continue;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
return null;
|
|
990
|
+
};
|
|
991
|
+
|
|
696
992
|
// src/ChatPanel.tsx
|
|
697
993
|
var ChatPanel = ({
|
|
698
994
|
project_id,
|
|
@@ -738,7 +1034,8 @@ var ChatPanel = ({
|
|
|
738
1034
|
customerEmailCaptureMode = "HIDE",
|
|
739
1035
|
customerEmailCapturePlaceholder = "Please enter your email...",
|
|
740
1036
|
mcpServers,
|
|
741
|
-
progressiveActions = true
|
|
1037
|
+
progressiveActions = true,
|
|
1038
|
+
resolveMcpAuthHeaders
|
|
742
1039
|
}) => {
|
|
743
1040
|
var _a;
|
|
744
1041
|
const isEmailAddress = (email) => {
|
|
@@ -1064,6 +1361,44 @@ var ChatPanel = ({
|
|
|
1064
1361
|
const [toolList, setToolList] = (0, import_react11.useState)([]);
|
|
1065
1362
|
const [toolsLoading, setToolsLoading] = (0, import_react11.useState)(false);
|
|
1066
1363
|
const [toolsFetchError, setToolsFetchError] = (0, import_react11.useState)(false);
|
|
1364
|
+
const buildMcpRequestHeaders = (0, import_react11.useCallback)(
|
|
1365
|
+
(_0) => __async(void 0, [_0], function* ({
|
|
1366
|
+
phase,
|
|
1367
|
+
mcpServer,
|
|
1368
|
+
toolName,
|
|
1369
|
+
toolArgs
|
|
1370
|
+
}) {
|
|
1371
|
+
const merged = {};
|
|
1372
|
+
const baseAccessToken = typeof mcpServer.accessToken === "string" ? mcpServer.accessToken.trim() : "";
|
|
1373
|
+
if (baseAccessToken) {
|
|
1374
|
+
merged["x-mcp-access-token"] = baseAccessToken;
|
|
1375
|
+
}
|
|
1376
|
+
if (project_id) {
|
|
1377
|
+
merged["x-project-id"] = project_id;
|
|
1378
|
+
}
|
|
1379
|
+
if (!resolveMcpAuthHeaders) return merged;
|
|
1380
|
+
try {
|
|
1381
|
+
const resolved = yield resolveMcpAuthHeaders({
|
|
1382
|
+
phase,
|
|
1383
|
+
mcpServer,
|
|
1384
|
+
projectId: project_id,
|
|
1385
|
+
customer: currentCustomer,
|
|
1386
|
+
toolName,
|
|
1387
|
+
toolArgs
|
|
1388
|
+
});
|
|
1389
|
+
return __spreadValues(__spreadValues({}, merged), normalizeMcpHeaders(
|
|
1390
|
+
resolved
|
|
1391
|
+
));
|
|
1392
|
+
} catch (error2) {
|
|
1393
|
+
console.error(
|
|
1394
|
+
`Failed to resolve MCP auth headers for ${phase} request:`,
|
|
1395
|
+
error2
|
|
1396
|
+
);
|
|
1397
|
+
return merged;
|
|
1398
|
+
}
|
|
1399
|
+
}),
|
|
1400
|
+
[project_id, currentCustomer, resolveMcpAuthHeaders]
|
|
1401
|
+
);
|
|
1067
1402
|
(0, import_react11.useEffect)(() => {
|
|
1068
1403
|
const fetchAndSetTools = () => __async(void 0, null, function* () {
|
|
1069
1404
|
if (!mcpServers || mcpServers.length === 0) {
|
|
@@ -1080,7 +1415,13 @@ var ChatPanel = ({
|
|
|
1080
1415
|
m.url
|
|
1081
1416
|
)}`;
|
|
1082
1417
|
try {
|
|
1083
|
-
const
|
|
1418
|
+
const requestHeaders = yield buildMcpRequestHeaders({
|
|
1419
|
+
phase: "list",
|
|
1420
|
+
mcpServer: m
|
|
1421
|
+
});
|
|
1422
|
+
const response2 = yield fetch(urlToFetch, {
|
|
1423
|
+
headers: requestHeaders
|
|
1424
|
+
});
|
|
1084
1425
|
if (!response2.ok) {
|
|
1085
1426
|
console.error(
|
|
1086
1427
|
`Error fetching tools from ${m.url}: ${response2.status} ${response2.statusText}`
|
|
@@ -1096,7 +1437,7 @@ var ChatPanel = ({
|
|
|
1096
1437
|
return toolsFromServer.map((tool) => __spreadProps(__spreadValues({}, tool), {
|
|
1097
1438
|
url: m.url,
|
|
1098
1439
|
accessToken: m.accessToken || "",
|
|
1099
|
-
headers:
|
|
1440
|
+
headers: requestHeaders
|
|
1100
1441
|
}));
|
|
1101
1442
|
} else {
|
|
1102
1443
|
return [];
|
|
@@ -1125,7 +1466,7 @@ var ChatPanel = ({
|
|
|
1125
1466
|
}
|
|
1126
1467
|
});
|
|
1127
1468
|
fetchAndSetTools();
|
|
1128
|
-
}, [mcpServers, publicAPIUrl]);
|
|
1469
|
+
}, [mcpServers, publicAPIUrl, buildMcpRequestHeaders]);
|
|
1129
1470
|
const llmResult = (0, import_llmasaservice_client.useLLM)({
|
|
1130
1471
|
project_id,
|
|
1131
1472
|
customer: currentCustomer,
|
|
@@ -1490,19 +1831,19 @@ var ChatPanel = ({
|
|
|
1490
1831
|
[]
|
|
1491
1832
|
);
|
|
1492
1833
|
const anthropic_toolAction = {
|
|
1493
|
-
pattern: '\\{"type":"tool_use","id":"([^"]+)","name":"([^"]+)","input":(\\{[\\s\\S]
|
|
1834
|
+
pattern: '\\{"type":"tool_use","id":"([^"]+)","name":"([^"]+)","input":(\\{[\\s\\S]*?\\}),"service":"([^"]+)"\\}',
|
|
1494
1835
|
type: "markdown",
|
|
1495
1836
|
markdown: "<br />*Tool use requested: $2*",
|
|
1496
1837
|
actionType: "tool"
|
|
1497
1838
|
};
|
|
1498
1839
|
const openAI_toolAction = {
|
|
1499
|
-
pattern: '\\{"id":"([^"]+)","type":"function","function":\\{"name":"([^"]+)","arguments":"(
|
|
1840
|
+
pattern: '\\{"id":"([^"]+)","type":"function","function":\\{"name":"([^"]+)","arguments":"([\\s\\S]*?)"\\},"service":"([^"]+)"\\}',
|
|
1500
1841
|
type: "markdown",
|
|
1501
1842
|
markdown: "<br />*Tool use requested: $2*",
|
|
1502
1843
|
actionType: "tool"
|
|
1503
1844
|
};
|
|
1504
1845
|
const google_toolAction = {
|
|
1505
|
-
pattern: '^\\{\\s*"(functionCall)"\\s*:\\s*\\{\\s*"name"\\s*:\\s*"([^"]+)"\\s*,\\s*"args"\\s*:\\s*(\\{[\\s\\S]
|
|
1846
|
+
pattern: '^\\{\\s*"(functionCall)"\\s*:\\s*\\{\\s*"name"\\s*:\\s*"([^"]+)"\\s*,\\s*"args"\\s*:\\s*(\\{[\\s\\S]*?\\})\\s*\\}(?:\\s*,\\s*"thoughtSignature"\\s*:\\s*"[^"]*")?\\s*,\\s*"service"\\s*:\\s*"([^"]+)"\\s*\\}$',
|
|
1506
1847
|
type: "markdown",
|
|
1507
1848
|
markdown: "<br />*Tool use requested: $2*",
|
|
1508
1849
|
actionType: "tool"
|
|
@@ -1644,114 +1985,125 @@ var ChatPanel = ({
|
|
|
1644
1985
|
]
|
|
1645
1986
|
}
|
|
1646
1987
|
];
|
|
1647
|
-
const
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1988
|
+
const parsedToolCalls = yield Promise.all(
|
|
1989
|
+
toolsToProcess.map((req, index) => __async(void 0, null, function* () {
|
|
1990
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
1991
|
+
if (!req) return null;
|
|
1992
|
+
let parsedToolCall = null;
|
|
1993
|
+
try {
|
|
1994
|
+
parsedToolCall = JSON.parse(req.match);
|
|
1995
|
+
} catch (error2) {
|
|
1996
|
+
console.error("Failed to parse tool call:", error2);
|
|
1997
|
+
}
|
|
1998
|
+
const toolName = req.groups[1] || req.toolName || (typeof (parsedToolCall == null ? void 0 : parsedToolCall.name) === "string" ? parsedToolCall.name : "") || (typeof ((_a2 = parsedToolCall == null ? void 0 : parsedToolCall.function) == null ? void 0 : _a2.name) === "string" ? parsedToolCall.function.name : "");
|
|
1999
|
+
if (!toolName) return null;
|
|
2000
|
+
const rawCallId = req.groups[0] || (parsedToolCall == null ? void 0 : parsedToolCall.id) || (parsedToolCall == null ? void 0 : parsedToolCall.tool_call_id) || `${toolName}-${index + 1}`;
|
|
2001
|
+
const callId = typeof rawCallId === "string" && rawCallId.trim().length > 0 && rawCallId !== "functionCall" ? rawCallId : `${toolName}-${index + 1}`;
|
|
2002
|
+
let args = {};
|
|
2003
|
+
const rawArgs = (_f = (_e = (_c = (_b = req.groups[2]) != null ? _b : parsedToolCall == null ? void 0 : parsedToolCall.input) != null ? _c : parsedToolCall == null ? void 0 : parsedToolCall.args) != null ? _e : (_d = parsedToolCall == null ? void 0 : parsedToolCall.function) == null ? void 0 : _d.arguments) != null ? _f : "{}";
|
|
2004
|
+
const parsedArgs = parseToolArguments(rawArgs);
|
|
2005
|
+
if (!parsedArgs) {
|
|
2006
|
+
console.error("Failed to parse tool arguments", {
|
|
2007
|
+
toolName,
|
|
2008
|
+
callId,
|
|
2009
|
+
rawArgsPreview: typeof rawArgs === "string" ? rawArgs.slice(0, 500) : JSON.stringify(rawArgs).slice(0, 500)
|
|
2010
|
+
});
|
|
2011
|
+
return null;
|
|
2012
|
+
}
|
|
2013
|
+
args = parsedArgs;
|
|
2014
|
+
const serviceTag = typeof req.groups[3] === "string" && req.groups[3] || typeof (parsedToolCall == null ? void 0 : parsedToolCall.service) === "string" && parsedToolCall.service || "";
|
|
1655
2015
|
return {
|
|
1656
2016
|
req,
|
|
1657
|
-
|
|
2017
|
+
toolName,
|
|
2018
|
+
callId,
|
|
2019
|
+
args,
|
|
2020
|
+
serviceTag
|
|
1658
2021
|
};
|
|
1659
|
-
}
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
2022
|
+
}))
|
|
2023
|
+
);
|
|
2024
|
+
const toolCallBatch = parsedToolCalls.filter(Boolean);
|
|
2025
|
+
const finalToolCalls = toolCallBatch.map((toolCall) => ({
|
|
2026
|
+
id: toolCall.callId,
|
|
2027
|
+
type: "tool_use",
|
|
2028
|
+
name: toolCall.toolName,
|
|
2029
|
+
input: toolCall.args,
|
|
2030
|
+
service: toolCall.serviceTag
|
|
1663
2031
|
}));
|
|
1664
|
-
const
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
toolCallsMessage.tool_calls.push(item.parsedToolCall);
|
|
1668
|
-
}
|
|
1669
|
-
});
|
|
1670
|
-
newMessages.push(toolCallsMessage);
|
|
1671
|
-
const finalToolCalls = toolCallsMessage.tool_calls;
|
|
1672
|
-
const toolResponsePromises = parsedToolCalls.map((item) => __async(void 0, null, function* () {
|
|
1673
|
-
var _a2;
|
|
1674
|
-
if (!item || !item.req) return null;
|
|
1675
|
-
const req = item.req;
|
|
1676
|
-
const mcpTool = toolList.find((tool) => tool.name === req.toolName);
|
|
2032
|
+
const toolResponsePromises = toolCallBatch.map((toolCall) => __async(void 0, null, function* () {
|
|
2033
|
+
var _a2, _b, _c;
|
|
2034
|
+
const mcpTool = toolList.find((tool) => tool.name === toolCall.toolName);
|
|
1677
2035
|
if (!mcpTool) {
|
|
1678
|
-
console.error(`Tool ${
|
|
1679
|
-
return
|
|
2036
|
+
console.error(`Tool ${toolCall.toolName} not found in tool list`);
|
|
2037
|
+
return {
|
|
2038
|
+
tool_call_id: toolCall.callId,
|
|
2039
|
+
tool_name: toolCall.toolName,
|
|
2040
|
+
result: `Tool ${toolCall.toolName} not found in current tool list.`,
|
|
2041
|
+
isError: true
|
|
2042
|
+
};
|
|
1680
2043
|
}
|
|
1681
2044
|
try {
|
|
1682
|
-
let args;
|
|
1683
|
-
try {
|
|
1684
|
-
args = JSON.parse(req.groups[2]);
|
|
1685
|
-
} catch (e) {
|
|
1686
|
-
try {
|
|
1687
|
-
args = JSON.parse(req.groups[2].replace(/\\"/g, '"'));
|
|
1688
|
-
} catch (err) {
|
|
1689
|
-
console.error("Failed to parse tool arguments:", err);
|
|
1690
|
-
return null;
|
|
1691
|
-
}
|
|
1692
|
-
}
|
|
1693
2045
|
const body = {
|
|
1694
|
-
tool:
|
|
1695
|
-
args
|
|
2046
|
+
tool: toolCall.toolName,
|
|
2047
|
+
args: toolCall.args
|
|
1696
2048
|
};
|
|
1697
2049
|
const result = yield fetch(
|
|
1698
2050
|
`${publicAPIUrl}/tools/${encodeURIComponent(mcpTool.url)}`,
|
|
1699
2051
|
{
|
|
1700
2052
|
method: "POST",
|
|
1701
|
-
headers: {
|
|
1702
|
-
"Content-Type": "application/json"
|
|
1703
|
-
|
|
1704
|
-
"
|
|
1705
|
-
|
|
2053
|
+
headers: __spreadValues({
|
|
2054
|
+
"Content-Type": "application/json"
|
|
2055
|
+
}, yield buildMcpRequestHeaders({
|
|
2056
|
+
phase: "call",
|
|
2057
|
+
mcpServer: mcpTool,
|
|
2058
|
+
toolName: toolCall.toolName,
|
|
2059
|
+
toolArgs: toolCall.args
|
|
2060
|
+
})),
|
|
1706
2061
|
body: JSON.stringify(body)
|
|
1707
2062
|
}
|
|
1708
2063
|
);
|
|
1709
2064
|
if (!result.ok) {
|
|
1710
2065
|
console.error(
|
|
1711
|
-
`Error calling tool ${
|
|
2066
|
+
`Error calling tool ${toolCall.toolName}: ${result.status} ${result.statusText}`
|
|
1712
2067
|
);
|
|
1713
2068
|
const errorBody = yield result.text();
|
|
1714
2069
|
console.error(`Error body: ${errorBody}`);
|
|
1715
|
-
return
|
|
2070
|
+
return {
|
|
2071
|
+
tool_call_id: toolCall.callId,
|
|
2072
|
+
tool_name: toolCall.toolName,
|
|
2073
|
+
result: `HTTP ${result.status} ${result.statusText}: ${errorBody || "Tool call failed"}`,
|
|
2074
|
+
isError: true
|
|
2075
|
+
};
|
|
1716
2076
|
}
|
|
1717
2077
|
let resultData;
|
|
1718
2078
|
try {
|
|
1719
2079
|
resultData = yield result.json();
|
|
1720
2080
|
} catch (jsonError) {
|
|
1721
2081
|
console.error(
|
|
1722
|
-
`Error parsing JSON response for tool ${
|
|
2082
|
+
`Error parsing JSON response for tool ${toolCall.toolName}:`,
|
|
1723
2083
|
jsonError
|
|
1724
2084
|
);
|
|
1725
|
-
try {
|
|
1726
|
-
const textBody = yield result.text();
|
|
1727
|
-
console.error("Response body (text):", textBody);
|
|
1728
|
-
} catch (textError) {
|
|
1729
|
-
console.error(
|
|
1730
|
-
"Failed to read response body as text either:",
|
|
1731
|
-
textError
|
|
1732
|
-
);
|
|
1733
|
-
}
|
|
1734
|
-
return null;
|
|
1735
|
-
}
|
|
1736
|
-
if (resultData && resultData.content && resultData.content.length > 0) {
|
|
1737
|
-
const textResult = (_a2 = resultData.content[0]) == null ? void 0 : _a2.text;
|
|
1738
2085
|
return {
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
text: textResult
|
|
1744
|
-
}
|
|
1745
|
-
],
|
|
1746
|
-
tool_call_id: req.groups[0]
|
|
2086
|
+
tool_call_id: toolCall.callId,
|
|
2087
|
+
tool_name: toolCall.toolName,
|
|
2088
|
+
result: "Tool returned a non-JSON response.",
|
|
2089
|
+
isError: true
|
|
1747
2090
|
};
|
|
1748
|
-
} else {
|
|
1749
|
-
console.error(`No content returned from tool ${req.toolName}`);
|
|
1750
|
-
return null;
|
|
1751
2091
|
}
|
|
2092
|
+
const textResult = (_c = (_b = (_a2 = resultData == null ? void 0 : resultData.content) == null ? void 0 : _a2[0]) == null ? void 0 : _b.text) != null ? _c : (resultData == null ? void 0 : resultData.result) ? JSON.stringify(resultData.result) : JSON.stringify(resultData);
|
|
2093
|
+
return {
|
|
2094
|
+
tool_call_id: toolCall.callId,
|
|
2095
|
+
tool_name: toolCall.toolName,
|
|
2096
|
+
result: textResult || "",
|
|
2097
|
+
isError: (resultData == null ? void 0 : resultData.isError) === true
|
|
2098
|
+
};
|
|
1752
2099
|
} catch (error2) {
|
|
1753
|
-
console.error(`Error processing tool ${
|
|
1754
|
-
return
|
|
2100
|
+
console.error(`Error processing tool ${toolCall.toolName}:`, error2);
|
|
2101
|
+
return {
|
|
2102
|
+
tool_call_id: toolCall.callId,
|
|
2103
|
+
tool_name: toolCall.toolName,
|
|
2104
|
+
result: error2 instanceof Error ? error2.message : `Unhandled error calling ${toolCall.toolName}`,
|
|
2105
|
+
isError: true
|
|
2106
|
+
};
|
|
1755
2107
|
}
|
|
1756
2108
|
}));
|
|
1757
2109
|
const toolResponses = yield Promise.all(toolResponsePromises);
|
|
@@ -1773,11 +2125,49 @@ var ChatPanel = ({
|
|
|
1773
2125
|
});
|
|
1774
2126
|
});
|
|
1775
2127
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
2128
|
+
const toReplayText = (value, maxLength = 2e3) => {
|
|
2129
|
+
const raw = typeof value === "string" ? value : (() => {
|
|
2130
|
+
try {
|
|
2131
|
+
return JSON.stringify(value);
|
|
2132
|
+
} catch (_error) {
|
|
2133
|
+
return String(value != null ? value : "");
|
|
2134
|
+
}
|
|
2135
|
+
})();
|
|
2136
|
+
const normalized = String(raw != null ? raw : "").replace(/\s+/g, " ").trim();
|
|
2137
|
+
if (normalized.length <= maxLength) return normalized;
|
|
2138
|
+
return `${normalized.slice(0, maxLength - 3)}...`;
|
|
2139
|
+
};
|
|
2140
|
+
if (toolCallBatch.length > 0) {
|
|
2141
|
+
const replayLines = toolCallBatch.map((toolCall, index) => {
|
|
2142
|
+
var _a2;
|
|
2143
|
+
const matchedResponse = finalToolResponses.find(
|
|
2144
|
+
(response2) => (response2 == null ? void 0 : response2.tool_call_id) === toolCall.callId
|
|
2145
|
+
) || finalToolResponses[index];
|
|
2146
|
+
const status = (matchedResponse == null ? void 0 : matchedResponse.isError) ? "error" : "ok";
|
|
2147
|
+
const resultText = toReplayText((_a2 = matchedResponse == null ? void 0 : matchedResponse.result) != null ? _a2 : "No result returned");
|
|
2148
|
+
return [
|
|
2149
|
+
`Tool: ${toolCall.toolName}`,
|
|
2150
|
+
`Call ID: ${toolCall.callId}`,
|
|
2151
|
+
`Status: ${status}`,
|
|
2152
|
+
`Args: ${toReplayText(toolCall.args, 600)}`,
|
|
2153
|
+
`Result: ${resultText}`
|
|
2154
|
+
].join("\n");
|
|
2155
|
+
});
|
|
2156
|
+
newMessages.push({
|
|
2157
|
+
role: "user",
|
|
2158
|
+
content: [
|
|
2159
|
+
{
|
|
2160
|
+
type: "text",
|
|
2161
|
+
text: [
|
|
2162
|
+
"Tool execution summary for the previous request:",
|
|
2163
|
+
...replayLines,
|
|
2164
|
+
"Continue the same assistant response from exactly where you paused using these tool results.",
|
|
2165
|
+
"If this response is using meta tags, keep the same format (<thinking>, <reasoning>, <searching>) in the continuation."
|
|
2166
|
+
].join("\n\n")
|
|
2167
|
+
}
|
|
2168
|
+
]
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
1781
2171
|
send(
|
|
1782
2172
|
"",
|
|
1783
2173
|
newMessages,
|
|
@@ -3559,7 +3949,8 @@ var AgentPanel = ({
|
|
|
3559
3949
|
//ragQueryLimit = 10,
|
|
3560
3950
|
//ragRankLimit = 5,
|
|
3561
3951
|
initialHistory = {},
|
|
3562
|
-
hideRagContextInPrompt = true
|
|
3952
|
+
hideRagContextInPrompt = true,
|
|
3953
|
+
resolveMcpAuthHeaders
|
|
3563
3954
|
}) => {
|
|
3564
3955
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
|
|
3565
3956
|
const searchParams = new URLSearchParams(location.search);
|
|
@@ -3697,7 +4088,8 @@ var AgentPanel = ({
|
|
|
3697
4088
|
createConversationOnFirstChat: (_s = agentData == null ? void 0 : agentData.createConversationOnFirstChat) != null ? _s : true,
|
|
3698
4089
|
customerEmailCaptureMode: (_t = agentData == null ? void 0 : agentData.customerEmailCaptureMode) != null ? _t : "HIDE",
|
|
3699
4090
|
customerEmailCapturePlaceholder: (_u = agentData == null ? void 0 : agentData.customerEmailCapturePlaceholder) != null ? _u : "Please enter your email...",
|
|
3700
|
-
mcpServers: mcpData
|
|
4091
|
+
mcpServers: mcpData,
|
|
4092
|
+
resolveMcpAuthHeaders
|
|
3701
4093
|
})
|
|
3702
4094
|
));
|
|
3703
4095
|
};
|
|
@@ -3768,18 +4160,731 @@ var ToolInfoModal2 = ({
|
|
|
3768
4160
|
var ToolInfoModal_default2 = ToolInfoModal2;
|
|
3769
4161
|
|
|
3770
4162
|
// src/AIChatPanel.tsx
|
|
4163
|
+
var areToolRequestListsEqual = (a, b) => {
|
|
4164
|
+
if (a.length !== b.length) return false;
|
|
4165
|
+
for (let index = 0; index < a.length; index += 1) {
|
|
4166
|
+
const left = a[index];
|
|
4167
|
+
const right = b[index];
|
|
4168
|
+
if (!left || !right) return false;
|
|
4169
|
+
if (left.callId !== right.callId) return false;
|
|
4170
|
+
if (left.toolName !== right.toolName) return false;
|
|
4171
|
+
if (left.serviceTag !== right.serviceTag) return false;
|
|
4172
|
+
if (left.match !== right.match) return false;
|
|
4173
|
+
if (left.start !== right.start || left.end !== right.end) return false;
|
|
4174
|
+
}
|
|
4175
|
+
return true;
|
|
4176
|
+
};
|
|
4177
|
+
var mergeContinuationResponseText = (baseText, continuationText) => {
|
|
4178
|
+
const base = typeof baseText === "string" ? baseText : "";
|
|
4179
|
+
const continuation = typeof continuationText === "string" ? continuationText : "";
|
|
4180
|
+
if (!base) return continuation;
|
|
4181
|
+
if (!continuation) return base;
|
|
4182
|
+
if (base.includes(continuation)) {
|
|
4183
|
+
return base;
|
|
4184
|
+
}
|
|
4185
|
+
const maxOverlap = Math.min(base.length, continuation.length);
|
|
4186
|
+
for (let overlap = maxOverlap; overlap > 0; overlap -= 1) {
|
|
4187
|
+
if (base.slice(-overlap) === continuation.slice(0, overlap)) {
|
|
4188
|
+
return `${base}${continuation.slice(overlap)}`;
|
|
4189
|
+
}
|
|
4190
|
+
}
|
|
4191
|
+
return `${base}
|
|
4192
|
+
|
|
4193
|
+
${continuation}`;
|
|
4194
|
+
};
|
|
4195
|
+
var INLINE_TOOL_MARKER_PREFIX = "[[AI_TOOL_CALL:";
|
|
4196
|
+
var INLINE_TOOL_MARKER_SUFFIX = "]]";
|
|
4197
|
+
var INLINE_TOOL_MARKER_REGEX = /\[\[AI_TOOL_CALL:([^|\]]+)\|([^\]]+)\]\]/g;
|
|
4198
|
+
var INLINE_THINKING_MARKER_PREFIX = "[[AI_THINK_BLOCK:";
|
|
4199
|
+
var INLINE_THINKING_MARKER_SUFFIX = "]]";
|
|
4200
|
+
var INLINE_THINKING_MARKER_REGEX = /\[\[AI_THINK_BLOCK:([^|\]]+)\|([^\]]+)\]\]/g;
|
|
4201
|
+
var MAX_TOOL_CONTINUATIONS_PER_TURN = 20;
|
|
4202
|
+
var MAX_TOOL_REPLAY_PAYLOAD_CHARS = 75e4;
|
|
4203
|
+
var MAX_TRACE_SUMMARY_CHARS = 1800;
|
|
4204
|
+
var MAX_TRACE_REASONING_BLOCKS = 4;
|
|
4205
|
+
var MAX_TRACE_TOOL_LINES = 6;
|
|
4206
|
+
var MAX_TRACE_ITEM_CHARS = 220;
|
|
4207
|
+
var MAX_TRACE_LINE_CHARS = 420;
|
|
4208
|
+
var hasInlineRuntimeMarkers = (value) => {
|
|
4209
|
+
const source = typeof value === "string" ? value : "";
|
|
4210
|
+
return source.includes(INLINE_TOOL_MARKER_PREFIX) || source.includes(INLINE_THINKING_MARKER_PREFIX);
|
|
4211
|
+
};
|
|
4212
|
+
var toNonEmptyLines = (value) => String(value || "").split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
4213
|
+
var isBoundarySubsetByLines = (existingLines, incomingLines) => {
|
|
4214
|
+
if (incomingLines.length === 0 || existingLines.length === 0) return false;
|
|
4215
|
+
if (incomingLines.length >= existingLines.length) return false;
|
|
4216
|
+
const prefixMatch = incomingLines.every((line, index) => existingLines[index] === line);
|
|
4217
|
+
if (prefixMatch) return true;
|
|
4218
|
+
const suffixStart = existingLines.length - incomingLines.length;
|
|
4219
|
+
return incomingLines.every((line, index) => existingLines[suffixStart + index] === line);
|
|
4220
|
+
};
|
|
4221
|
+
var shouldPreserveBoundaryDroppedStreamText = (existingContent, incomingContent) => {
|
|
4222
|
+
const existing = String(existingContent || "").trim();
|
|
4223
|
+
const incoming = String(incomingContent || "").trim();
|
|
4224
|
+
if (!existing) return false;
|
|
4225
|
+
if (!incoming) return true;
|
|
4226
|
+
if (incoming === existing) return false;
|
|
4227
|
+
if (!hasInlineRuntimeMarkers(existing)) return false;
|
|
4228
|
+
if (existing.includes(incoming)) {
|
|
4229
|
+
return true;
|
|
4230
|
+
}
|
|
4231
|
+
const existingLines = toNonEmptyLines(existing);
|
|
4232
|
+
const incomingLines = toNonEmptyLines(incoming);
|
|
4233
|
+
return isBoundarySubsetByLines(existingLines, incomingLines);
|
|
4234
|
+
};
|
|
4235
|
+
var isObjectRecord = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
4236
|
+
var stringifyToolArgs = (value) => {
|
|
4237
|
+
if (typeof value === "string") return value;
|
|
4238
|
+
try {
|
|
4239
|
+
return JSON.stringify(value != null ? value : {});
|
|
4240
|
+
} catch (_error) {
|
|
4241
|
+
return "{}";
|
|
4242
|
+
}
|
|
4243
|
+
};
|
|
4244
|
+
var truncateTraceText = (value, maxChars) => {
|
|
4245
|
+
const text = String(value || "").trim();
|
|
4246
|
+
if (!text) return "";
|
|
4247
|
+
if (text.length <= maxChars) return text;
|
|
4248
|
+
return `${text.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
|
|
4249
|
+
};
|
|
4250
|
+
var normalizeTraceText = (value) => {
|
|
4251
|
+
if (value === null || value === void 0) return "";
|
|
4252
|
+
const raw = typeof value === "string" ? value : (() => {
|
|
4253
|
+
try {
|
|
4254
|
+
return JSON.stringify(value);
|
|
4255
|
+
} catch (_error) {
|
|
4256
|
+
return String(value);
|
|
4257
|
+
}
|
|
4258
|
+
})();
|
|
4259
|
+
return String(raw || "").replace(/\s+/g, " ").trim();
|
|
4260
|
+
};
|
|
4261
|
+
var toTraceObjectArray = (value) => {
|
|
4262
|
+
if (!Array.isArray(value)) return [];
|
|
4263
|
+
return value.filter((item) => isObjectRecord(item));
|
|
4264
|
+
};
|
|
4265
|
+
var getTraceStatusLabel = (response) => {
|
|
4266
|
+
if (!response) return "pending";
|
|
4267
|
+
if (response.isError === true || response.error === true) return "error";
|
|
4268
|
+
return "ok";
|
|
4269
|
+
};
|
|
4270
|
+
var buildCompactTraceSummary = ({
|
|
4271
|
+
reasoningBlocks,
|
|
4272
|
+
toolCalls,
|
|
4273
|
+
toolResponses
|
|
4274
|
+
}) => {
|
|
4275
|
+
const sections = [];
|
|
4276
|
+
const normalizedReasoning = (Array.isArray(reasoningBlocks) ? reasoningBlocks : []).filter((block) => !!block && typeof block.content === "string" && block.content.trim().length > 0).slice(-MAX_TRACE_REASONING_BLOCKS).map((block) => {
|
|
4277
|
+
const content = truncateTraceText(normalizeTraceText(block.content), MAX_TRACE_ITEM_CHARS);
|
|
4278
|
+
if (!content) return "";
|
|
4279
|
+
const type = typeof block.type === "string" ? block.type : "thinking";
|
|
4280
|
+
return `- ${type}: ${content}`;
|
|
4281
|
+
}).filter(Boolean);
|
|
4282
|
+
if (normalizedReasoning.length > 0) {
|
|
4283
|
+
sections.push(["reasoning:", ...normalizedReasoning].join("\n"));
|
|
4284
|
+
}
|
|
4285
|
+
const calls = toTraceObjectArray(toolCalls).slice(-MAX_TRACE_TOOL_LINES);
|
|
4286
|
+
const responses = toTraceObjectArray(toolResponses);
|
|
4287
|
+
if (calls.length > 0) {
|
|
4288
|
+
const responsesByCallId = /* @__PURE__ */ new Map();
|
|
4289
|
+
responses.forEach((response) => {
|
|
4290
|
+
const key = typeof response.tool_call_id === "string" ? response.tool_call_id.trim() : "";
|
|
4291
|
+
if (!key || responsesByCallId.has(key)) return;
|
|
4292
|
+
responsesByCallId.set(key, response);
|
|
4293
|
+
});
|
|
4294
|
+
const responseOffset = Math.max(0, responses.length - calls.length);
|
|
4295
|
+
const toolLines = calls.map((call, index) => {
|
|
4296
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4297
|
+
const toolName = typeof call.name === "string" ? call.name.trim() : typeof call.tool_name === "string" ? call.tool_name.trim() : "tool";
|
|
4298
|
+
const callId = typeof call.id === "string" ? call.id.trim() : typeof call.tool_call_id === "string" ? call.tool_call_id.trim() : "";
|
|
4299
|
+
const response = (callId ? responsesByCallId.get(callId) : void 0) || responses[responseOffset + index] || responses[index];
|
|
4300
|
+
const status = getTraceStatusLabel(response);
|
|
4301
|
+
const rawArgs = (_c = (_b = (_a = call.input) != null ? _a : call.args) != null ? _b : call.arguments) != null ? _c : {};
|
|
4302
|
+
const parsedArgs = parseToolArguments(rawArgs);
|
|
4303
|
+
const normalizedArgs = truncateTraceText(
|
|
4304
|
+
normalizeTraceText(parsedArgs != null ? parsedArgs : isObjectRecord(rawArgs) ? rawArgs : rawArgs || {}),
|
|
4305
|
+
MAX_TRACE_ITEM_CHARS
|
|
4306
|
+
);
|
|
4307
|
+
const normalizedResult = truncateTraceText(
|
|
4308
|
+
normalizeTraceText((_f = (_e = (_d = response == null ? void 0 : response.result) != null ? _d : response == null ? void 0 : response.content) != null ? _e : response == null ? void 0 : response.error) != null ? _f : ""),
|
|
4309
|
+
MAX_TRACE_ITEM_CHARS
|
|
4310
|
+
);
|
|
4311
|
+
const base = callId ? `- ${toolName} (${callId}) ${status}` : `- ${toolName} ${status}`;
|
|
4312
|
+
const withArgs = normalizedArgs ? `${base} args=${normalizedArgs}` : base;
|
|
4313
|
+
const withResult = normalizedResult ? `${withArgs} result=${normalizedResult}` : withArgs;
|
|
4314
|
+
return truncateTraceText(withResult, MAX_TRACE_LINE_CHARS);
|
|
4315
|
+
}).filter(Boolean);
|
|
4316
|
+
if (toolLines.length > 0) {
|
|
4317
|
+
sections.push(["tools:", ...toolLines].join("\n"));
|
|
4318
|
+
}
|
|
4319
|
+
}
|
|
4320
|
+
if (sections.length === 0) return "";
|
|
4321
|
+
return truncateTraceText(["TRACE SUMMARY (compact)", ...sections].join("\n"), MAX_TRACE_SUMMARY_CHARS);
|
|
4322
|
+
};
|
|
4323
|
+
var findPreviousNonWhitespaceChar = (text, startIndex) => {
|
|
4324
|
+
for (let index = startIndex; index >= 0; index -= 1) {
|
|
4325
|
+
const char = text[index];
|
|
4326
|
+
if (typeof char !== "string") continue;
|
|
4327
|
+
if (!/\s/.test(char)) {
|
|
4328
|
+
return char;
|
|
4329
|
+
}
|
|
4330
|
+
}
|
|
4331
|
+
return null;
|
|
4332
|
+
};
|
|
4333
|
+
var findNextNonWhitespaceChar = (text, startIndex) => {
|
|
4334
|
+
for (let index = startIndex; index < text.length; index += 1) {
|
|
4335
|
+
const char = text[index];
|
|
4336
|
+
if (typeof char !== "string") continue;
|
|
4337
|
+
if (!/\s/.test(char)) {
|
|
4338
|
+
return char;
|
|
4339
|
+
}
|
|
4340
|
+
}
|
|
4341
|
+
return null;
|
|
4342
|
+
};
|
|
4343
|
+
var isStandaloneToolObjectSegment = (text, openIndex, closeIndex) => {
|
|
4344
|
+
const lineStart = text.lastIndexOf("\n", openIndex - 1) + 1;
|
|
4345
|
+
const lineEndRaw = text.indexOf("\n", closeIndex + 1);
|
|
4346
|
+
const lineEnd = lineEndRaw === -1 ? text.length : lineEndRaw;
|
|
4347
|
+
const linePrefix = text.slice(lineStart, openIndex);
|
|
4348
|
+
const lineSuffix = text.slice(closeIndex + 1, lineEnd);
|
|
4349
|
+
const startsLine = linePrefix.trim().length === 0;
|
|
4350
|
+
const endsLine = lineSuffix.trim().length === 0;
|
|
4351
|
+
const prevChar = findPreviousNonWhitespaceChar(text, openIndex - 1);
|
|
4352
|
+
const nextChar = findNextNonWhitespaceChar(text, closeIndex + 1);
|
|
4353
|
+
const prevDelimited = prevChar !== null && ["{", "}", "[", "]", ","].includes(prevChar);
|
|
4354
|
+
const nextDelimited = nextChar !== null && ["{", "}", "[", "]", ","].includes(nextChar);
|
|
4355
|
+
const prefixWindow = text.slice(Math.max(0, openIndex - 64), openIndex);
|
|
4356
|
+
const hasLabelPrefix = /(?:^|[\r\n])\s*[A-Za-z][A-Za-z0-9 _-]{0,30}:\s*$/.test(prefixWindow);
|
|
4357
|
+
if (hasLabelPrefix) return false;
|
|
4358
|
+
return (startsLine || prevDelimited) && (endsLine || nextDelimited);
|
|
4359
|
+
};
|
|
4360
|
+
var extractTopLevelJsonObjectSegments = (source) => {
|
|
4361
|
+
const text = typeof source === "string" ? source : "";
|
|
4362
|
+
if (!text) return [];
|
|
4363
|
+
const segments = [];
|
|
4364
|
+
let cursor = 0;
|
|
4365
|
+
while (cursor < text.length) {
|
|
4366
|
+
const openIndex = text.indexOf("{", cursor);
|
|
4367
|
+
if (openIndex === -1) break;
|
|
4368
|
+
let depth = 0;
|
|
4369
|
+
let inString = false;
|
|
4370
|
+
let escaped = false;
|
|
4371
|
+
let closeIndex = -1;
|
|
4372
|
+
for (let index = openIndex; index < text.length; index += 1) {
|
|
4373
|
+
const char = text[index];
|
|
4374
|
+
if (inString) {
|
|
4375
|
+
if (escaped) {
|
|
4376
|
+
escaped = false;
|
|
4377
|
+
continue;
|
|
4378
|
+
}
|
|
4379
|
+
if (char === "\\") {
|
|
4380
|
+
escaped = true;
|
|
4381
|
+
continue;
|
|
4382
|
+
}
|
|
4383
|
+
if (char === '"') {
|
|
4384
|
+
inString = false;
|
|
4385
|
+
}
|
|
4386
|
+
continue;
|
|
4387
|
+
}
|
|
4388
|
+
if (char === '"') {
|
|
4389
|
+
inString = true;
|
|
4390
|
+
continue;
|
|
4391
|
+
}
|
|
4392
|
+
if (char === "{") {
|
|
4393
|
+
depth += 1;
|
|
4394
|
+
continue;
|
|
4395
|
+
}
|
|
4396
|
+
if (char === "}") {
|
|
4397
|
+
depth -= 1;
|
|
4398
|
+
if (depth === 0) {
|
|
4399
|
+
closeIndex = index;
|
|
4400
|
+
break;
|
|
4401
|
+
}
|
|
4402
|
+
if (depth < 0) {
|
|
4403
|
+
break;
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
}
|
|
4407
|
+
if (closeIndex === -1) {
|
|
4408
|
+
cursor = openIndex + 1;
|
|
4409
|
+
continue;
|
|
4410
|
+
}
|
|
4411
|
+
const raw = text.slice(openIndex, closeIndex + 1);
|
|
4412
|
+
try {
|
|
4413
|
+
const value = JSON.parse(raw);
|
|
4414
|
+
if (isObjectRecord(value) && isStandaloneToolObjectSegment(text, openIndex, closeIndex)) {
|
|
4415
|
+
segments.push({
|
|
4416
|
+
start: openIndex,
|
|
4417
|
+
end: closeIndex + 1,
|
|
4418
|
+
raw,
|
|
4419
|
+
value
|
|
4420
|
+
});
|
|
4421
|
+
}
|
|
4422
|
+
} catch (_error) {
|
|
4423
|
+
}
|
|
4424
|
+
cursor = closeIndex + 1;
|
|
4425
|
+
}
|
|
4426
|
+
return segments;
|
|
4427
|
+
};
|
|
4428
|
+
var resolveToolRequestFromSegment = (segment, fallbackIndex) => {
|
|
4429
|
+
var _a, _b, _c;
|
|
4430
|
+
const record = segment.value;
|
|
4431
|
+
const serviceTag = typeof record.service === "string" ? record.service : "";
|
|
4432
|
+
const rawId = typeof record.id === "string" ? record.id.trim() : "";
|
|
4433
|
+
if (record.type === "tool_use" && typeof record.name === "string") {
|
|
4434
|
+
const toolName = String(record.name).trim();
|
|
4435
|
+
if (!toolName) return null;
|
|
4436
|
+
const callId = rawId || `${toolName}-${fallbackIndex + 1}`;
|
|
4437
|
+
return {
|
|
4438
|
+
match: segment.raw,
|
|
4439
|
+
groups: [callId, toolName, stringifyToolArgs((_a = record.input) != null ? _a : {}), serviceTag],
|
|
4440
|
+
toolName,
|
|
4441
|
+
callId,
|
|
4442
|
+
serviceTag,
|
|
4443
|
+
start: segment.start,
|
|
4444
|
+
end: segment.end
|
|
4445
|
+
};
|
|
4446
|
+
}
|
|
4447
|
+
if (record.type === "function" && isObjectRecord(record.function)) {
|
|
4448
|
+
const functionRecord = record.function;
|
|
4449
|
+
const toolName = typeof functionRecord.name === "string" ? functionRecord.name.trim() : "";
|
|
4450
|
+
if (!toolName) return null;
|
|
4451
|
+
const callId = rawId || `${toolName}-${fallbackIndex + 1}`;
|
|
4452
|
+
return {
|
|
4453
|
+
match: segment.raw,
|
|
4454
|
+
groups: [callId, toolName, stringifyToolArgs((_b = functionRecord.arguments) != null ? _b : {}), serviceTag],
|
|
4455
|
+
toolName,
|
|
4456
|
+
callId,
|
|
4457
|
+
serviceTag,
|
|
4458
|
+
start: segment.start,
|
|
4459
|
+
end: segment.end
|
|
4460
|
+
};
|
|
4461
|
+
}
|
|
4462
|
+
if (isObjectRecord(record.functionCall) && typeof record.functionCall.name === "string") {
|
|
4463
|
+
const functionCall = record.functionCall;
|
|
4464
|
+
const toolName = String(functionCall.name).trim();
|
|
4465
|
+
if (!toolName) return null;
|
|
4466
|
+
const callId = rawId || `${toolName}-${fallbackIndex + 1}`;
|
|
4467
|
+
return {
|
|
4468
|
+
match: segment.raw,
|
|
4469
|
+
groups: [callId, toolName, stringifyToolArgs((_c = functionCall.args) != null ? _c : {}), serviceTag],
|
|
4470
|
+
toolName,
|
|
4471
|
+
callId,
|
|
4472
|
+
serviceTag,
|
|
4473
|
+
start: segment.start,
|
|
4474
|
+
end: segment.end
|
|
4475
|
+
};
|
|
4476
|
+
}
|
|
4477
|
+
return null;
|
|
4478
|
+
};
|
|
4479
|
+
var extractBalancedObjectCandidate = (input) => {
|
|
4480
|
+
const text = typeof input === "string" ? input : "";
|
|
4481
|
+
const start = text.indexOf("{");
|
|
4482
|
+
if (start === -1) return null;
|
|
4483
|
+
let depth = 0;
|
|
4484
|
+
let inString = false;
|
|
4485
|
+
let escaped = false;
|
|
4486
|
+
for (let index = start; index < text.length; index += 1) {
|
|
4487
|
+
const char = text[index];
|
|
4488
|
+
if (inString) {
|
|
4489
|
+
if (escaped) {
|
|
4490
|
+
escaped = false;
|
|
4491
|
+
continue;
|
|
4492
|
+
}
|
|
4493
|
+
if (char === "\\") {
|
|
4494
|
+
escaped = true;
|
|
4495
|
+
continue;
|
|
4496
|
+
}
|
|
4497
|
+
if (char === '"') {
|
|
4498
|
+
inString = false;
|
|
4499
|
+
}
|
|
4500
|
+
continue;
|
|
4501
|
+
}
|
|
4502
|
+
if (char === '"') {
|
|
4503
|
+
inString = true;
|
|
4504
|
+
continue;
|
|
4505
|
+
}
|
|
4506
|
+
if (char === "{") {
|
|
4507
|
+
depth += 1;
|
|
4508
|
+
continue;
|
|
4509
|
+
}
|
|
4510
|
+
if (char === "}") {
|
|
4511
|
+
depth -= 1;
|
|
4512
|
+
if (depth === 0) {
|
|
4513
|
+
return text.slice(start, index + 1);
|
|
4514
|
+
}
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
return null;
|
|
4518
|
+
};
|
|
4519
|
+
var extractLineLevelFallbackToolRequests = (source, existing) => {
|
|
4520
|
+
const text = typeof source === "string" ? source : "";
|
|
4521
|
+
if (!text) return [];
|
|
4522
|
+
const takenRanges = existing.map((request) => ({
|
|
4523
|
+
start: request.start,
|
|
4524
|
+
end: request.end
|
|
4525
|
+
}));
|
|
4526
|
+
const overlapsExisting = (start, end) => takenRanges.some((range) => start < range.end && end > range.start);
|
|
4527
|
+
const requests = [];
|
|
4528
|
+
let offset = 0;
|
|
4529
|
+
const lines = text.split("\n");
|
|
4530
|
+
const normalizeStandaloneToolJsonLine = (line) => {
|
|
4531
|
+
const trimmed = line.trim();
|
|
4532
|
+
if (!trimmed) return null;
|
|
4533
|
+
let normalized = trimmed;
|
|
4534
|
+
const first = normalized[0];
|
|
4535
|
+
const last = normalized[normalized.length - 1];
|
|
4536
|
+
const hasSymmetricQuote = normalized.length >= 2 && (first === "'" && last === "'" || first === '"' && last === '"' || first === "`" && last === "`");
|
|
4537
|
+
if (hasSymmetricQuote) {
|
|
4538
|
+
const inner = normalized.slice(1, -1).trim();
|
|
4539
|
+
if (first === '"') {
|
|
4540
|
+
try {
|
|
4541
|
+
const decoded = JSON.parse(normalized);
|
|
4542
|
+
if (typeof decoded === "string") {
|
|
4543
|
+
normalized = decoded.trim();
|
|
4544
|
+
} else {
|
|
4545
|
+
normalized = inner;
|
|
4546
|
+
}
|
|
4547
|
+
} catch (_error) {
|
|
4548
|
+
normalized = inner;
|
|
4549
|
+
}
|
|
4550
|
+
} else {
|
|
4551
|
+
normalized = inner;
|
|
4552
|
+
}
|
|
4553
|
+
}
|
|
4554
|
+
const extractedCandidate = extractBalancedObjectCandidate(normalized);
|
|
4555
|
+
if (extractedCandidate) {
|
|
4556
|
+
normalized = extractedCandidate.trim();
|
|
4557
|
+
}
|
|
4558
|
+
if (!normalized.startsWith("{")) return null;
|
|
4559
|
+
if (!normalized.includes('"type"')) return null;
|
|
4560
|
+
return normalized;
|
|
4561
|
+
};
|
|
4562
|
+
const extractBalancedObjectAfterField = (input, fieldName) => {
|
|
4563
|
+
const fieldRegex = new RegExp(`"${fieldName}"\\s*:\\s*`, "i");
|
|
4564
|
+
const fieldMatch = fieldRegex.exec(input);
|
|
4565
|
+
if (!fieldMatch) return null;
|
|
4566
|
+
const startIndex = input.indexOf("{", fieldMatch.index + fieldMatch[0].length);
|
|
4567
|
+
if (startIndex === -1) return null;
|
|
4568
|
+
let depth = 0;
|
|
4569
|
+
let inString = false;
|
|
4570
|
+
let escaped = false;
|
|
4571
|
+
for (let index = startIndex; index < input.length; index += 1) {
|
|
4572
|
+
const char = input[index];
|
|
4573
|
+
if (inString) {
|
|
4574
|
+
if (escaped) {
|
|
4575
|
+
escaped = false;
|
|
4576
|
+
continue;
|
|
4577
|
+
}
|
|
4578
|
+
if (char === "\\") {
|
|
4579
|
+
escaped = true;
|
|
4580
|
+
continue;
|
|
4581
|
+
}
|
|
4582
|
+
if (char === '"') {
|
|
4583
|
+
inString = false;
|
|
4584
|
+
}
|
|
4585
|
+
continue;
|
|
4586
|
+
}
|
|
4587
|
+
if (char === '"') {
|
|
4588
|
+
inString = true;
|
|
4589
|
+
continue;
|
|
4590
|
+
}
|
|
4591
|
+
if (char === "{") {
|
|
4592
|
+
depth += 1;
|
|
4593
|
+
continue;
|
|
4594
|
+
}
|
|
4595
|
+
if (char === "}") {
|
|
4596
|
+
depth -= 1;
|
|
4597
|
+
if (depth === 0) {
|
|
4598
|
+
return input.slice(startIndex, index + 1);
|
|
4599
|
+
}
|
|
4600
|
+
}
|
|
4601
|
+
}
|
|
4602
|
+
return null;
|
|
4603
|
+
};
|
|
4604
|
+
lines.forEach((line, index) => {
|
|
4605
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4606
|
+
const lineStart = offset;
|
|
4607
|
+
const lineEnd = lineStart + line.length;
|
|
4608
|
+
offset = lineEnd + (index < lines.length - 1 ? 1 : 0);
|
|
4609
|
+
const normalized = normalizeStandaloneToolJsonLine(line);
|
|
4610
|
+
if (!normalized) return;
|
|
4611
|
+
if (!(normalized.includes('"tool_use"') || normalized.includes('"function"'))) return;
|
|
4612
|
+
if (/(^|[\r\n])\s*[A-Za-z][A-Za-z0-9 _-]{0,30}:\s*\{/.test(line)) return;
|
|
4613
|
+
if (overlapsExisting(lineStart, lineEnd)) return;
|
|
4614
|
+
try {
|
|
4615
|
+
const parsedLine = JSON.parse(normalized);
|
|
4616
|
+
if (isObjectRecord(parsedLine)) {
|
|
4617
|
+
const type2 = typeof parsedLine.type === "string" ? parsedLine.type.trim().toLowerCase() : "";
|
|
4618
|
+
if (type2 === "tool_use") {
|
|
4619
|
+
const toolName2 = typeof parsedLine.name === "string" ? parsedLine.name.trim() : "";
|
|
4620
|
+
if (!toolName2) return;
|
|
4621
|
+
const callId2 = typeof parsedLine.id === "string" && parsedLine.id.trim().length > 0 ? parsedLine.id.trim() : `tool-call-${index + 1}`;
|
|
4622
|
+
const serviceTag = typeof parsedLine.service === "string" ? parsedLine.service : "";
|
|
4623
|
+
const parsedArgs2 = parseToolArguments((_a = parsedLine.input) != null ? _a : {});
|
|
4624
|
+
if (!parsedArgs2) return;
|
|
4625
|
+
requests.push({
|
|
4626
|
+
match: line,
|
|
4627
|
+
groups: [callId2, toolName2, stringifyToolArgs(parsedArgs2), serviceTag],
|
|
4628
|
+
toolName: toolName2,
|
|
4629
|
+
callId: callId2,
|
|
4630
|
+
serviceTag,
|
|
4631
|
+
start: lineStart,
|
|
4632
|
+
end: lineEnd
|
|
4633
|
+
});
|
|
4634
|
+
return;
|
|
4635
|
+
}
|
|
4636
|
+
if (type2 === "function" && isObjectRecord(parsedLine.function)) {
|
|
4637
|
+
const functionRecord = parsedLine.function;
|
|
4638
|
+
const toolName2 = typeof functionRecord.name === "string" ? functionRecord.name.trim() : "";
|
|
4639
|
+
if (!toolName2) return;
|
|
4640
|
+
const callId2 = typeof parsedLine.id === "string" && parsedLine.id.trim().length > 0 ? parsedLine.id.trim() : `tool-call-${index + 1}`;
|
|
4641
|
+
const serviceTag = typeof parsedLine.service === "string" ? parsedLine.service : "";
|
|
4642
|
+
const parsedArgs2 = parseToolArguments((_b = functionRecord.arguments) != null ? _b : {});
|
|
4643
|
+
if (!parsedArgs2) return;
|
|
4644
|
+
requests.push({
|
|
4645
|
+
match: line,
|
|
4646
|
+
groups: [callId2, toolName2, stringifyToolArgs(parsedArgs2), serviceTag],
|
|
4647
|
+
toolName: toolName2,
|
|
4648
|
+
callId: callId2,
|
|
4649
|
+
serviceTag,
|
|
4650
|
+
start: lineStart,
|
|
4651
|
+
end: lineEnd
|
|
4652
|
+
});
|
|
4653
|
+
return;
|
|
4654
|
+
}
|
|
4655
|
+
}
|
|
4656
|
+
} catch (_error) {
|
|
4657
|
+
}
|
|
4658
|
+
const typeMatch = normalized.match(/"type"\s*:\s*"([^"]+)"/i);
|
|
4659
|
+
const type = (_c = typeMatch == null ? void 0 : typeMatch[1]) == null ? void 0 : _c.trim().toLowerCase();
|
|
4660
|
+
if (type !== "tool_use" && type !== "function") return;
|
|
4661
|
+
const idMatch = normalized.match(/"id"\s*:\s*"([^"]+)"/i);
|
|
4662
|
+
const callId = ((_d = idMatch == null ? void 0 : idMatch[1]) == null ? void 0 : _d.trim()) || `tool-call-${index + 1}`;
|
|
4663
|
+
let toolName = "";
|
|
4664
|
+
let argsRaw = "{}";
|
|
4665
|
+
if (type === "tool_use") {
|
|
4666
|
+
const nameMatch = normalized.match(/"name"\s*:\s*"([^"]+)"/i);
|
|
4667
|
+
toolName = ((_e = nameMatch == null ? void 0 : nameMatch[1]) == null ? void 0 : _e.trim()) || "";
|
|
4668
|
+
const inputObject = extractBalancedObjectAfterField(normalized, "input");
|
|
4669
|
+
if (inputObject) {
|
|
4670
|
+
argsRaw = inputObject;
|
|
4671
|
+
}
|
|
4672
|
+
} else {
|
|
4673
|
+
const fnNameMatch = normalized.match(/"function"\s*:\s*\{[\s\S]*?"name"\s*:\s*"([^"]+)"/i);
|
|
4674
|
+
toolName = ((_f = fnNameMatch == null ? void 0 : fnNameMatch[1]) == null ? void 0 : _f.trim()) || "";
|
|
4675
|
+
const argumentsObject = extractBalancedObjectAfterField(normalized, "arguments");
|
|
4676
|
+
if (argumentsObject) {
|
|
4677
|
+
argsRaw = argumentsObject;
|
|
4678
|
+
} else {
|
|
4679
|
+
const argsStringMatch = normalized.match(/"arguments"\s*:\s*"([\s\S]*?)"(?:\s*,|\s*})/i);
|
|
4680
|
+
if (argsStringMatch == null ? void 0 : argsStringMatch[1]) {
|
|
4681
|
+
const rawArgs = argsStringMatch[1];
|
|
4682
|
+
try {
|
|
4683
|
+
argsRaw = JSON.parse(`"${rawArgs}"`);
|
|
4684
|
+
} catch (_error) {
|
|
4685
|
+
argsRaw = rawArgs;
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
}
|
|
4689
|
+
}
|
|
4690
|
+
if (!toolName) return;
|
|
4691
|
+
const parsedArgs = parseToolArguments(argsRaw);
|
|
4692
|
+
if (!parsedArgs) return;
|
|
4693
|
+
requests.push({
|
|
4694
|
+
match: line,
|
|
4695
|
+
groups: [callId, toolName, stringifyToolArgs(parsedArgs), ""],
|
|
4696
|
+
toolName,
|
|
4697
|
+
callId,
|
|
4698
|
+
serviceTag: "",
|
|
4699
|
+
start: lineStart,
|
|
4700
|
+
end: lineEnd
|
|
4701
|
+
});
|
|
4702
|
+
});
|
|
4703
|
+
return requests;
|
|
4704
|
+
};
|
|
4705
|
+
var stripStandaloneRawToolJsonLines = (source) => {
|
|
4706
|
+
const text = typeof source === "string" ? source : "";
|
|
4707
|
+
if (!text) return text;
|
|
4708
|
+
const normalizeStandaloneToolJsonLine = (line) => {
|
|
4709
|
+
const trimmed = line.trim();
|
|
4710
|
+
if (!trimmed) return null;
|
|
4711
|
+
let normalized = trimmed;
|
|
4712
|
+
const first = normalized[0];
|
|
4713
|
+
const last = normalized[normalized.length - 1];
|
|
4714
|
+
const hasSymmetricQuote = normalized.length >= 2 && (first === "'" && last === "'" || first === '"' && last === '"' || first === "`" && last === "`");
|
|
4715
|
+
if (hasSymmetricQuote) {
|
|
4716
|
+
const inner = normalized.slice(1, -1).trim();
|
|
4717
|
+
if (first === '"') {
|
|
4718
|
+
try {
|
|
4719
|
+
const decoded = JSON.parse(normalized);
|
|
4720
|
+
if (typeof decoded === "string") {
|
|
4721
|
+
normalized = decoded.trim();
|
|
4722
|
+
} else {
|
|
4723
|
+
normalized = inner;
|
|
4724
|
+
}
|
|
4725
|
+
} catch (_error) {
|
|
4726
|
+
normalized = inner;
|
|
4727
|
+
}
|
|
4728
|
+
} else {
|
|
4729
|
+
normalized = inner;
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4732
|
+
const extractedCandidate = extractBalancedObjectCandidate(normalized);
|
|
4733
|
+
if (extractedCandidate) {
|
|
4734
|
+
normalized = extractedCandidate.trim();
|
|
4735
|
+
}
|
|
4736
|
+
if (!normalized.startsWith("{") || !normalized.endsWith("}")) return null;
|
|
4737
|
+
return normalized;
|
|
4738
|
+
};
|
|
4739
|
+
const lines = text.split("\n");
|
|
4740
|
+
let removedAny = false;
|
|
4741
|
+
const kept = lines.filter((line) => {
|
|
4742
|
+
const normalized = normalizeStandaloneToolJsonLine(line);
|
|
4743
|
+
if (!normalized) return true;
|
|
4744
|
+
const hasToolType = /"type"\s*:\s*"(tool_use|function)"/i.test(normalized);
|
|
4745
|
+
if (!hasToolType) return true;
|
|
4746
|
+
const hasName = /"name"\s*:\s*"[^"]+"/i.test(normalized);
|
|
4747
|
+
const hasFunctionName = /"function"\s*:\s*\{[\s\S]*?"name"\s*:\s*"[^"]+"/i.test(normalized);
|
|
4748
|
+
if (!hasName && !hasFunctionName) return true;
|
|
4749
|
+
removedAny = true;
|
|
4750
|
+
return false;
|
|
4751
|
+
});
|
|
4752
|
+
if (!removedAny) return text;
|
|
4753
|
+
return kept.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
4754
|
+
};
|
|
4755
|
+
var extractToolRequestMatchesFromText = (rawResponse) => {
|
|
4756
|
+
const requests = [];
|
|
4757
|
+
const segments = extractTopLevelJsonObjectSegments(rawResponse);
|
|
4758
|
+
segments.forEach((segment, segmentIndex) => {
|
|
4759
|
+
const parsed = resolveToolRequestFromSegment(segment, segmentIndex);
|
|
4760
|
+
if (!parsed) return;
|
|
4761
|
+
requests.push(parsed);
|
|
4762
|
+
});
|
|
4763
|
+
const fallbackRequests = extractLineLevelFallbackToolRequests(rawResponse, requests);
|
|
4764
|
+
fallbackRequests.forEach((request) => {
|
|
4765
|
+
requests.push(request);
|
|
4766
|
+
});
|
|
4767
|
+
if (requests.length === 0) return [];
|
|
4768
|
+
requests.sort((a, b) => a.start - b.start);
|
|
4769
|
+
const seenSignatures = /* @__PURE__ */ new Set();
|
|
4770
|
+
const deduped = requests.filter((request) => {
|
|
4771
|
+
const signature = `${String(request.toolName || "").trim().toLowerCase()}::${String(
|
|
4772
|
+
request.callId || ""
|
|
4773
|
+
).trim().toLowerCase()}::${request.start}`;
|
|
4774
|
+
if (seenSignatures.has(signature)) return false;
|
|
4775
|
+
seenSignatures.add(signature);
|
|
4776
|
+
return true;
|
|
4777
|
+
});
|
|
4778
|
+
deduped.sort((a, b) => a.start - b.start);
|
|
4779
|
+
return deduped;
|
|
4780
|
+
};
|
|
4781
|
+
var hashInlineMarkerValue = (value) => {
|
|
4782
|
+
let hash = 5381;
|
|
4783
|
+
const input = String(value || "");
|
|
4784
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
4785
|
+
hash = (hash << 5) + hash ^ input.charCodeAt(index);
|
|
4786
|
+
}
|
|
4787
|
+
return (hash >>> 0).toString(36);
|
|
4788
|
+
};
|
|
4789
|
+
var getThinkingBlockSignature = (type, content) => {
|
|
4790
|
+
const normalizedContent = String(content || "").trim();
|
|
4791
|
+
return `${type}-${hashInlineMarkerValue(normalizedContent)}-${normalizedContent.length}`;
|
|
4792
|
+
};
|
|
4793
|
+
var buildThinkingBlockMarker = (type, signature) => {
|
|
4794
|
+
const normalizedType = String(type || "thinking").trim();
|
|
4795
|
+
const normalizedSignature = String(signature || "").trim() || `${normalizedType}-block`;
|
|
4796
|
+
return `${INLINE_THINKING_MARKER_PREFIX}${encodeURIComponent(normalizedType)}|${encodeURIComponent(
|
|
4797
|
+
normalizedSignature
|
|
4798
|
+
)}${INLINE_THINKING_MARKER_SUFFIX}`;
|
|
4799
|
+
};
|
|
4800
|
+
var buildInlineToolMarker = (toolName, callId) => {
|
|
4801
|
+
const normalizedToolName = String(toolName || "").trim() || "tool";
|
|
4802
|
+
const normalizedCallId = String(callId || "").trim() || `${normalizedToolName}-call`;
|
|
4803
|
+
return `${INLINE_TOOL_MARKER_PREFIX}${encodeURIComponent(normalizedToolName)}|${encodeURIComponent(
|
|
4804
|
+
normalizedCallId
|
|
4805
|
+
)}${INLINE_TOOL_MARKER_SUFFIX}`;
|
|
4806
|
+
};
|
|
4807
|
+
var parseInlineToolMarkers = (text) => {
|
|
4808
|
+
const source = typeof text === "string" ? text : "";
|
|
4809
|
+
if (!source) return { parts: [""], markers: [] };
|
|
4810
|
+
const parts = [];
|
|
4811
|
+
const markers = [];
|
|
4812
|
+
let lastIndex = 0;
|
|
4813
|
+
INLINE_TOOL_MARKER_REGEX.lastIndex = 0;
|
|
4814
|
+
let match;
|
|
4815
|
+
while ((match = INLINE_TOOL_MARKER_REGEX.exec(source)) !== null) {
|
|
4816
|
+
parts.push(source.slice(lastIndex, match.index));
|
|
4817
|
+
const encodedToolName = match[1] || "";
|
|
4818
|
+
const encodedCallId = match[2] || "";
|
|
4819
|
+
let toolName = encodedToolName;
|
|
4820
|
+
let callId = encodedCallId;
|
|
4821
|
+
try {
|
|
4822
|
+
toolName = decodeURIComponent(encodedToolName);
|
|
4823
|
+
} catch (_error) {
|
|
4824
|
+
toolName = encodedToolName;
|
|
4825
|
+
}
|
|
4826
|
+
try {
|
|
4827
|
+
callId = decodeURIComponent(encodedCallId);
|
|
4828
|
+
} catch (_error) {
|
|
4829
|
+
callId = encodedCallId;
|
|
4830
|
+
}
|
|
4831
|
+
markers.push({
|
|
4832
|
+
toolName: String(toolName || "").trim() || "tool",
|
|
4833
|
+
callId: String(callId || "").trim() || "call"
|
|
4834
|
+
});
|
|
4835
|
+
lastIndex = match.index + match[0].length;
|
|
4836
|
+
}
|
|
4837
|
+
parts.push(source.slice(lastIndex));
|
|
4838
|
+
return { parts, markers };
|
|
4839
|
+
};
|
|
4840
|
+
var parseInlineThinkingMarkers = (text) => {
|
|
4841
|
+
const source = typeof text === "string" ? text : "";
|
|
4842
|
+
if (!source) return { parts: [""], markers: [] };
|
|
4843
|
+
const parts = [];
|
|
4844
|
+
const markers = [];
|
|
4845
|
+
let lastIndex = 0;
|
|
4846
|
+
INLINE_THINKING_MARKER_REGEX.lastIndex = 0;
|
|
4847
|
+
let match;
|
|
4848
|
+
while ((match = INLINE_THINKING_MARKER_REGEX.exec(source)) !== null) {
|
|
4849
|
+
parts.push(source.slice(lastIndex, match.index));
|
|
4850
|
+
const encodedType = match[1] || "";
|
|
4851
|
+
const encodedSignature = match[2] || "";
|
|
4852
|
+
let rawType = encodedType;
|
|
4853
|
+
let signature = encodedSignature;
|
|
4854
|
+
try {
|
|
4855
|
+
rawType = decodeURIComponent(encodedType);
|
|
4856
|
+
} catch (_error) {
|
|
4857
|
+
rawType = encodedType;
|
|
4858
|
+
}
|
|
4859
|
+
try {
|
|
4860
|
+
signature = decodeURIComponent(encodedSignature);
|
|
4861
|
+
} catch (_error) {
|
|
4862
|
+
signature = encodedSignature;
|
|
4863
|
+
}
|
|
4864
|
+
const normalizedType = String(rawType || "").trim().toLowerCase();
|
|
4865
|
+
const type = normalizedType === "reasoning" ? "reasoning" : normalizedType === "searching" ? "searching" : "thinking";
|
|
4866
|
+
markers.push({
|
|
4867
|
+
type,
|
|
4868
|
+
signature: String(signature || "").trim()
|
|
4869
|
+
});
|
|
4870
|
+
lastIndex = match.index + match[0].length;
|
|
4871
|
+
}
|
|
4872
|
+
parts.push(source.slice(lastIndex));
|
|
4873
|
+
return { parts, markers };
|
|
4874
|
+
};
|
|
3771
4875
|
var ArrowUpIcon = () => /* @__PURE__ */ import_react14.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ import_react14.default.createElement("path", { d: "M12 19V5M5 12l7-7 7 7" }));
|
|
3772
4876
|
var StopIcon = () => /* @__PURE__ */ import_react14.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "ai-chat-icon" }, /* @__PURE__ */ import_react14.default.createElement("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }));
|
|
3773
4877
|
var ChevronDownIcon = () => /* @__PURE__ */ import_react14.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ import_react14.default.createElement("path", { d: "m6 9 6 6 6-6" }));
|
|
3774
4878
|
var ChevronUpIcon = () => /* @__PURE__ */ import_react14.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ import_react14.default.createElement("path", { d: "m18 15-6-6-6 6" }));
|
|
3775
4879
|
var AgentIcon = () => /* @__PURE__ */ import_react14.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ import_react14.default.createElement("path", { d: "M12 8V4H8" }), /* @__PURE__ */ import_react14.default.createElement("rect", { width: "16", height: "12", x: "4", y: "8", rx: "2" }), /* @__PURE__ */ import_react14.default.createElement("path", { d: "M2 14h2" }), /* @__PURE__ */ import_react14.default.createElement("path", { d: "M20 14h2" }), /* @__PURE__ */ import_react14.default.createElement("path", { d: "M15 13v2" }), /* @__PURE__ */ import_react14.default.createElement("path", { d: "M9 13v2" }));
|
|
4880
|
+
var ToolIcon = () => /* @__PURE__ */ import_react14.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ import_react14.default.createElement("path", { d: "M14.7 6.3a4 4 0 0 0-5.4 5.4l-6 6a2 2 0 0 0 2.8 2.8l6-6a4 4 0 0 0 5.4-5.4l-2.1 2.1-3.3-3.3 2.6-1.6Z" }));
|
|
3776
4881
|
var CheckIcon = () => /* @__PURE__ */ import_react14.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ import_react14.default.createElement("polyline", { points: "20 6 9 17 4 12" }));
|
|
3777
4882
|
var LLMAsAServiceLogo = () => /* @__PURE__ */ import_react14.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 72 72", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ import_react14.default.createElement("ellipse", { cx: "14.0868", cy: "59.2146", rx: "7.8261", ry: "7.7854", fill: "#2487D8" }), /* @__PURE__ */ import_react14.default.createElement("ellipse", { cx: "24.9013", cy: "43.0776", rx: "6.11858", ry: "6.08676", fill: "#2487D8" }), /* @__PURE__ */ import_react14.default.createElement("ellipse", { cx: "45.391", cy: "43.0776", rx: "6.11858", ry: "6.08676", fill: "#2487D8" }), /* @__PURE__ */ import_react14.default.createElement("ellipse", { cx: "65.8813", cy: "43.0776", rx: "6.11858", ry: "6.08676", fill: "#2487D8" }), /* @__PURE__ */ import_react14.default.createElement("ellipse", { cx: "35.1461", cy: "26.5327", rx: "4.41103", ry: "4.3878", fill: "#2487D8" }), /* @__PURE__ */ import_react14.default.createElement("ellipse", { cx: "55.6364", cy: "26.5327", rx: "4.41103", ry: "4.3878", fill: "#2487D8" }), /* @__PURE__ */ import_react14.default.createElement("ellipse", { cx: "45.391", cy: "10.3959", rx: "2.70351", ry: "2.68919", fill: "#2487D8" }));
|
|
3778
4883
|
var AlertCircleIcon = () => /* @__PURE__ */ import_react14.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ import_react14.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react14.default.createElement("line", { x1: "12", x2: "12", y1: "8", y2: "12" }), /* @__PURE__ */ import_react14.default.createElement("line", { x1: "12", x2: "12.01", y1: "16", y2: "16" }));
|
|
3779
4884
|
var CloseIcon = () => /* @__PURE__ */ import_react14.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ import_react14.default.createElement("line", { x1: "18", x2: "6", y1: "6", y2: "18" }), /* @__PURE__ */ import_react14.default.createElement("line", { x1: "6", x2: "18", y1: "6", y2: "18" }));
|
|
3780
4885
|
var ChatInput = import_react14.default.memo(({
|
|
3781
4886
|
placeholder,
|
|
3782
|
-
|
|
4887
|
+
isBusy,
|
|
3783
4888
|
onSubmit,
|
|
3784
4889
|
onStop,
|
|
3785
4890
|
agentOptions,
|
|
@@ -3812,14 +4917,14 @@ var ChatInput = import_react14.default.memo(({
|
|
|
3812
4917
|
}, []);
|
|
3813
4918
|
const handleSubmit = (0, import_react14.useCallback)(() => {
|
|
3814
4919
|
const trimmed = inputValue.trim();
|
|
3815
|
-
if (trimmed &&
|
|
4920
|
+
if (trimmed && !isBusy) {
|
|
3816
4921
|
onSubmit(trimmed);
|
|
3817
4922
|
setInputValue("");
|
|
3818
4923
|
if (textareaRef.current) {
|
|
3819
4924
|
textareaRef.current.style.height = "auto";
|
|
3820
4925
|
}
|
|
3821
4926
|
}
|
|
3822
|
-
}, [inputValue,
|
|
4927
|
+
}, [inputValue, isBusy, onSubmit]);
|
|
3823
4928
|
(0, import_react14.useEffect)(() => {
|
|
3824
4929
|
const handleClickOutside = (event) => {
|
|
3825
4930
|
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
@@ -3855,9 +4960,6 @@ var ChatInput = import_react14.default.memo(({
|
|
|
3855
4960
|
const hasRawData2 = (section) => {
|
|
3856
4961
|
return typeof section.rawData === "string";
|
|
3857
4962
|
};
|
|
3858
|
-
const hasStructuredData = (section) => {
|
|
3859
|
-
return typeof section.data === "object" && section.data !== null;
|
|
3860
|
-
};
|
|
3861
4963
|
const estimateSectionTokens2 = (section) => {
|
|
3862
4964
|
var _a;
|
|
3863
4965
|
if (typeof section.tokens === "number") {
|
|
@@ -3868,32 +4970,6 @@ var ChatInput = import_react14.default.memo(({
|
|
|
3868
4970
|
}
|
|
3869
4971
|
return Math.ceil(JSON.stringify((_a = section.data) != null ? _a : {}).length / 4);
|
|
3870
4972
|
};
|
|
3871
|
-
const detectFormat = (section) => {
|
|
3872
|
-
if (section.format) {
|
|
3873
|
-
return section.format;
|
|
3874
|
-
}
|
|
3875
|
-
if (!hasRawData2(section)) {
|
|
3876
|
-
return "json";
|
|
3877
|
-
}
|
|
3878
|
-
const raw = section.rawData.trim();
|
|
3879
|
-
if (raw.startsWith("{") || raw.startsWith("[")) return "json";
|
|
3880
|
-
if (raw.includes("# ") || raw.includes("```")) return "markdown";
|
|
3881
|
-
return "text";
|
|
3882
|
-
};
|
|
3883
|
-
const formatBadge = (format) => {
|
|
3884
|
-
if (format === "toon") return "TOON";
|
|
3885
|
-
if (format === "markdown") return "MD";
|
|
3886
|
-
if (format === "text") return "TEXT";
|
|
3887
|
-
return "JSON";
|
|
3888
|
-
};
|
|
3889
|
-
const [detailViewModeBySection, setDetailViewModeBySection] = (0, import_react14.useState)({});
|
|
3890
|
-
const getVisibleDetailMode = (section) => {
|
|
3891
|
-
var _a;
|
|
3892
|
-
if (hasRawData2(section)) {
|
|
3893
|
-
return (_a = detailViewModeBySection[section.id]) != null ? _a : "raw";
|
|
3894
|
-
}
|
|
3895
|
-
return "structured";
|
|
3896
|
-
};
|
|
3897
4973
|
const getStructuredContent = (section) => {
|
|
3898
4974
|
var _a;
|
|
3899
4975
|
return JSON.stringify((_a = section.data) != null ? _a : {}, null, 2);
|
|
@@ -3985,10 +5061,10 @@ var ChatInput = import_react14.default.memo(({
|
|
|
3985
5061
|
className: `ai-chat-context-popover__progress-bar ${isOverLimit ? "ai-chat-context-popover__progress-bar--warning" : ""}`,
|
|
3986
5062
|
style: { width: `${Math.min(tokenPercentage, 100)}%` }
|
|
3987
5063
|
}
|
|
3988
|
-
))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-context-popover__sections" }, contextSections.map((section) => /* @__PURE__ */ import_react14.default.createElement(
|
|
5064
|
+
))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-context-popover__sections" }, contextSections.map((section, index) => /* @__PURE__ */ import_react14.default.createElement(
|
|
3989
5065
|
"div",
|
|
3990
5066
|
{
|
|
3991
|
-
key: section.id
|
|
5067
|
+
key: `${section.id}-${index}`,
|
|
3992
5068
|
className: `ai-chat-context-popover__section-item ${enableContextDetailView ? "ai-chat-context-popover__section-item--clickable" : ""}`,
|
|
3993
5069
|
onClick: () => {
|
|
3994
5070
|
if (enableContextDetailView) {
|
|
@@ -3999,7 +5075,6 @@ var ChatInput = import_react14.default.memo(({
|
|
|
3999
5075
|
},
|
|
4000
5076
|
/* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-context-popover__section-icon" }, "\u{1F4C4}"),
|
|
4001
5077
|
/* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-context-popover__section-title" }, section.title),
|
|
4002
|
-
/* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-context-popover__section-format" }, formatBadge(detectFormat(section))),
|
|
4003
5078
|
/* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-context-popover__section-tokens" }, estimateSectionTokens2(section))
|
|
4004
5079
|
))), enableContextDetailView && /* @__PURE__ */ import_react14.default.createElement(
|
|
4005
5080
|
"button",
|
|
@@ -4041,15 +5116,13 @@ var ChatInput = import_react14.default.memo(({
|
|
|
4041
5116
|
className: `ai-chat-context-popover__progress-bar ${isOverLimit ? "ai-chat-context-popover__progress-bar--warning" : ""}`,
|
|
4042
5117
|
style: { width: `${Math.min(tokenPercentage, 100)}%` }
|
|
4043
5118
|
}
|
|
4044
|
-
))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-context-popover__detail-sections" }, contextSections.map((section) => {
|
|
5119
|
+
))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-context-popover__detail-sections" }, contextSections.map((section, index) => {
|
|
4045
5120
|
const isRawSection = hasRawData2(section);
|
|
4046
|
-
const hasBothViews = isRawSection && hasStructuredData(section);
|
|
4047
|
-
const visibleMode = getVisibleDetailMode(section);
|
|
4048
5121
|
const isEnabled = !disabledSectionIds.has(section.id);
|
|
4049
5122
|
return /* @__PURE__ */ import_react14.default.createElement(
|
|
4050
5123
|
"details",
|
|
4051
5124
|
{
|
|
4052
|
-
key: section.id
|
|
5125
|
+
key: `${section.id}-${index}`,
|
|
4053
5126
|
className: `ai-chat-context-popover__detail-section ${!isEnabled ? "ai-chat-context-popover__detail-section--disabled" : ""}`,
|
|
4054
5127
|
open: expandedSectionId === section.id
|
|
4055
5128
|
},
|
|
@@ -4075,43 +5148,18 @@ var ChatInput = import_react14.default.memo(({
|
|
|
4075
5148
|
}
|
|
4076
5149
|
),
|
|
4077
5150
|
/* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-context-toggle__slider" })
|
|
4078
|
-
)), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-context-popover__detail-section-meta" }, /* @__PURE__ */ import_react14.default.createElement("code", null, `{{${section.id}}}`), /* @__PURE__ */ import_react14.default.createElement("span", null,
|
|
4079
|
-
|
|
4080
|
-
"button",
|
|
4081
|
-
{
|
|
4082
|
-
type: "button",
|
|
4083
|
-
className: `ai-chat-context-popover__detail-view-button ${visibleMode === "raw" ? "active" : ""}`,
|
|
4084
|
-
onClick: (e) => {
|
|
4085
|
-
e.preventDefault();
|
|
4086
|
-
e.stopPropagation();
|
|
4087
|
-
setDetailViewModeBySection((prev) => __spreadProps(__spreadValues({}, prev), { [section.id]: "raw" }));
|
|
4088
|
-
}
|
|
4089
|
-
},
|
|
4090
|
-
"Raw"
|
|
4091
|
-
), /* @__PURE__ */ import_react14.default.createElement(
|
|
4092
|
-
"button",
|
|
4093
|
-
{
|
|
4094
|
-
type: "button",
|
|
4095
|
-
className: `ai-chat-context-popover__detail-view-button ${visibleMode === "structured" ? "active" : ""}`,
|
|
4096
|
-
onClick: (e) => {
|
|
4097
|
-
e.preventDefault();
|
|
4098
|
-
e.stopPropagation();
|
|
4099
|
-
setDetailViewModeBySection((prev) => __spreadProps(__spreadValues({}, prev), { [section.id]: "structured" }));
|
|
4100
|
-
}
|
|
4101
|
-
},
|
|
4102
|
-
"Structured"
|
|
4103
|
-
)),
|
|
4104
|
-
/* @__PURE__ */ import_react14.default.createElement("pre", { className: "ai-chat-context-popover__detail-content" }, /* @__PURE__ */ import_react14.default.createElement("code", null, visibleMode === "raw" && isRawSection ? section.rawData : getStructuredContent(section)))
|
|
5151
|
+
)), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-context-popover__detail-section-meta" }, /* @__PURE__ */ import_react14.default.createElement("code", null, `{{${section.id}}}`), /* @__PURE__ */ import_react14.default.createElement("span", null, "~", estimateSectionTokens2(section)))),
|
|
5152
|
+
/* @__PURE__ */ import_react14.default.createElement("pre", { className: "ai-chat-context-popover__detail-content" }, /* @__PURE__ */ import_react14.default.createElement("code", null, isRawSection ? section.rawData : getStructuredContent(section)))
|
|
4105
5153
|
);
|
|
4106
5154
|
})))
|
|
4107
5155
|
)), /* @__PURE__ */ import_react14.default.createElement(
|
|
4108
5156
|
"button",
|
|
4109
5157
|
{
|
|
4110
|
-
className: `ai-chat-send-button ${
|
|
4111
|
-
onClick: () =>
|
|
4112
|
-
disabled:
|
|
5158
|
+
className: `ai-chat-send-button ${!isBusy && !inputValue.trim() ? "ai-chat-send-button--disabled" : ""} ${isBusy ? "ai-chat-send-button--stop" : ""}`,
|
|
5159
|
+
onClick: () => isBusy ? onStop() : handleSubmit(),
|
|
5160
|
+
disabled: !isBusy && !inputValue.trim()
|
|
4113
5161
|
},
|
|
4114
|
-
|
|
5162
|
+
isBusy ? /* @__PURE__ */ import_react14.default.createElement(StopIcon, null) : /* @__PURE__ */ import_react14.default.createElement(ArrowUpIcon, null)
|
|
4115
5163
|
)),
|
|
4116
5164
|
agentOptions.length > 0 && dropdownOpen && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-agent-selector__dropdown-inside" }, agentOptions.map((option) => /* @__PURE__ */ import_react14.default.createElement(
|
|
4117
5165
|
"button",
|
|
@@ -4168,7 +5216,11 @@ var AIChatPanel = ({
|
|
|
4168
5216
|
initialHistory = {},
|
|
4169
5217
|
hideRagContextInPrompt = true,
|
|
4170
5218
|
createConversationOnFirstChat = true,
|
|
5219
|
+
autoApproveTools = false,
|
|
4171
5220
|
mcpServers = [],
|
|
5221
|
+
resolveMcpAuthHeaders,
|
|
5222
|
+
localToolExecutors,
|
|
5223
|
+
traceContextMode = "standard",
|
|
4172
5224
|
progressiveActions = true,
|
|
4173
5225
|
agentOptions = [],
|
|
4174
5226
|
currentAgentId,
|
|
@@ -4181,6 +5233,7 @@ var AIChatPanel = ({
|
|
|
4181
5233
|
disabledSectionIds: propDisabledSectionIds,
|
|
4182
5234
|
onToggleSection: propOnToggleSection,
|
|
4183
5235
|
onConversationCreated,
|
|
5236
|
+
onBeforeSend,
|
|
4184
5237
|
// UI Customization Props
|
|
4185
5238
|
cssUrl,
|
|
4186
5239
|
markdownClass,
|
|
@@ -4216,6 +5269,8 @@ var AIChatPanel = ({
|
|
|
4216
5269
|
const [collapsedBlocks, setCollapsedBlocks] = (0, import_react14.useState)(/* @__PURE__ */ new Set());
|
|
4217
5270
|
const hasAutoCollapsedRef = (0, import_react14.useRef)(false);
|
|
4218
5271
|
const prevBlockCountRef = (0, import_react14.useRef)(0);
|
|
5272
|
+
const thinkingBlocksByKeyRef = (0, import_react14.useRef)({});
|
|
5273
|
+
const [thinkingBlocksByKey, setThinkingBlocksByKey] = (0, import_react14.useState)({});
|
|
4219
5274
|
const [newConversationConfirm, setNewConversationConfirm] = (0, import_react14.useState)(false);
|
|
4220
5275
|
const [justReset, setJustReset] = (0, import_react14.useState)(false);
|
|
4221
5276
|
const [copiedCallId, setCopiedCallId] = (0, import_react14.useState)(null);
|
|
@@ -4235,8 +5290,64 @@ var AIChatPanel = ({
|
|
|
4235
5290
|
const [pendingToolRequests, setPendingToolRequests] = (0, import_react14.useState)([]);
|
|
4236
5291
|
const [sessionApprovedTools, setSessionApprovedTools] = (0, import_react14.useState)([]);
|
|
4237
5292
|
const [alwaysApprovedTools, setAlwaysApprovedTools] = (0, import_react14.useState)([]);
|
|
5293
|
+
const [toolList, setToolList] = (0, import_react14.useState)([]);
|
|
5294
|
+
const [toolsLoading, setToolsLoading] = (0, import_react14.useState)(false);
|
|
5295
|
+
const [toolsFetchError, setToolsFetchError] = (0, import_react14.useState)(false);
|
|
5296
|
+
const [resolvedMcpServers, setResolvedMcpServers] = (0, import_react14.useState)(mcpServers || []);
|
|
5297
|
+
const [activeToolCalls, setActiveToolCalls] = (0, import_react14.useState)([]);
|
|
5298
|
+
const normalizeToolName = (0, import_react14.useCallback)((toolName) => {
|
|
5299
|
+
return String(toolName != null ? toolName : "").trim().toLowerCase();
|
|
5300
|
+
}, []);
|
|
5301
|
+
const getToolCallSignature = (0, import_react14.useCallback)(
|
|
5302
|
+
(toolName, callId) => {
|
|
5303
|
+
const normalizedToolName = normalizeToolName(toolName);
|
|
5304
|
+
const normalizedCallId = String(callId != null ? callId : "").trim();
|
|
5305
|
+
if (!normalizedToolName || !normalizedCallId) return "";
|
|
5306
|
+
return `${normalizedToolName}::${normalizedCallId}`;
|
|
5307
|
+
},
|
|
5308
|
+
[normalizeToolName]
|
|
5309
|
+
);
|
|
5310
|
+
const alwaysApprovedToolsStorageKey = (0, import_react14.useMemo)(() => {
|
|
5311
|
+
const customerId = (customer == null ? void 0 : customer.customer_id) || (customer == null ? void 0 : customer.id) || (customer == null ? void 0 : customer.customer_user_email) || "anonymous";
|
|
5312
|
+
const agentIdForScope = currentAgentId || agent || "default";
|
|
5313
|
+
return `llmasaservice-ui:always-approved-tools:${project_id}:${customerId}:${agentIdForScope}`;
|
|
5314
|
+
}, [project_id, customer, currentAgentId, agent]);
|
|
4238
5315
|
const [internalDisabledSectionIds, setInternalDisabledSectionIds] = (0, import_react14.useState)(/* @__PURE__ */ new Set());
|
|
4239
5316
|
const disabledSectionIds = propDisabledSectionIds != null ? propDisabledSectionIds : internalDisabledSectionIds;
|
|
5317
|
+
(0, import_react14.useEffect)(() => {
|
|
5318
|
+
if (typeof window === "undefined") return;
|
|
5319
|
+
try {
|
|
5320
|
+
const stored = window.localStorage.getItem(alwaysApprovedToolsStorageKey);
|
|
5321
|
+
if (!stored) return;
|
|
5322
|
+
const parsed = JSON.parse(stored);
|
|
5323
|
+
if (!Array.isArray(parsed)) return;
|
|
5324
|
+
const normalized = Array.from(
|
|
5325
|
+
new Set(
|
|
5326
|
+
parsed.map((value) => normalizeToolName(String(value))).filter((value) => value.length > 0)
|
|
5327
|
+
)
|
|
5328
|
+
);
|
|
5329
|
+
setAlwaysApprovedTools(normalized);
|
|
5330
|
+
} catch (error2) {
|
|
5331
|
+
console.warn("[AIChatPanel] Failed to load always-approved tools from localStorage:", error2);
|
|
5332
|
+
}
|
|
5333
|
+
}, [alwaysApprovedToolsStorageKey, normalizeToolName]);
|
|
5334
|
+
(0, import_react14.useEffect)(() => {
|
|
5335
|
+
if (typeof window === "undefined") return;
|
|
5336
|
+
try {
|
|
5337
|
+
if (alwaysApprovedTools.length === 0) {
|
|
5338
|
+
window.localStorage.removeItem(alwaysApprovedToolsStorageKey);
|
|
5339
|
+
return;
|
|
5340
|
+
}
|
|
5341
|
+
window.localStorage.setItem(
|
|
5342
|
+
alwaysApprovedToolsStorageKey,
|
|
5343
|
+
JSON.stringify(
|
|
5344
|
+
Array.from(new Set(alwaysApprovedTools.map((value) => normalizeToolName(value)).filter(Boolean)))
|
|
5345
|
+
)
|
|
5346
|
+
);
|
|
5347
|
+
} catch (error2) {
|
|
5348
|
+
console.warn("[AIChatPanel] Failed to persist always-approved tools to localStorage:", error2);
|
|
5349
|
+
}
|
|
5350
|
+
}, [alwaysApprovedToolsStorageKey, alwaysApprovedTools, normalizeToolName]);
|
|
4240
5351
|
(0, import_react14.useEffect)(() => {
|
|
4241
5352
|
setShowEmailPanel(customerEmailCaptureMode !== "HIDE");
|
|
4242
5353
|
if (customerEmailCaptureMode === "REQUIRED") {
|
|
@@ -4259,6 +5370,14 @@ var AIChatPanel = ({
|
|
|
4259
5370
|
const latestHistoryRef = (0, import_react14.useRef)(initialHistory);
|
|
4260
5371
|
const initialPromptSentRef = (0, import_react14.useRef)(false);
|
|
4261
5372
|
const lastFollowOnPromptRef = (0, import_react14.useRef)("");
|
|
5373
|
+
const handledToolCallSignaturesRef = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
|
|
5374
|
+
const inFlightToolCallSignaturesRef = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
|
|
5375
|
+
const toolContinuationCountRef = (0, import_react14.useRef)(0);
|
|
5376
|
+
const activeStreamAppendBaseRef = (0, import_react14.useRef)(null);
|
|
5377
|
+
const toolRequestProcessingRef = (0, import_react14.useRef)(false);
|
|
5378
|
+
const queuedToolRequestsRef = (0, import_react14.useRef)(null);
|
|
5379
|
+
const suppressAbortHistoryUpdateRef = (0, import_react14.useRef)(false);
|
|
5380
|
+
const toolReplaySummariesByKeyRef = (0, import_react14.useRef)({});
|
|
4262
5381
|
(0, import_react14.useEffect)(() => {
|
|
4263
5382
|
if (!initialHistory) return;
|
|
4264
5383
|
setHistory((prev) => {
|
|
@@ -4277,10 +5396,158 @@ var AIChatPanel = ({
|
|
|
4277
5396
|
return prev;
|
|
4278
5397
|
});
|
|
4279
5398
|
}, [initialHistory]);
|
|
4280
|
-
|
|
5399
|
+
(0, import_react14.useEffect)(() => {
|
|
5400
|
+
latestHistoryRef.current = history;
|
|
5401
|
+
}, [history]);
|
|
5402
|
+
(0, import_react14.useEffect)(() => {
|
|
5403
|
+
let cancelled = false;
|
|
5404
|
+
const resolveServers = () => __async(void 0, null, function* () {
|
|
5405
|
+
if (!mcpServers || mcpServers.length === 0) {
|
|
5406
|
+
if (!cancelled) {
|
|
5407
|
+
setResolvedMcpServers((prev) => prev.length === 0 ? prev : []);
|
|
5408
|
+
}
|
|
5409
|
+
return;
|
|
5410
|
+
}
|
|
5411
|
+
if (!resolveMcpAuthHeaders) {
|
|
5412
|
+
if (!cancelled) {
|
|
5413
|
+
setResolvedMcpServers((prev) => {
|
|
5414
|
+
const hasSameServers = prev.length === mcpServers.length && prev.every((server, index) => server === mcpServers[index]);
|
|
5415
|
+
return hasSameServers ? prev : mcpServers;
|
|
5416
|
+
});
|
|
5417
|
+
}
|
|
5418
|
+
return;
|
|
5419
|
+
}
|
|
5420
|
+
try {
|
|
5421
|
+
const enriched = yield Promise.all(
|
|
5422
|
+
mcpServers.map((server) => __async(void 0, null, function* () {
|
|
5423
|
+
const resolved = yield resolveMcpAuthHeaders({
|
|
5424
|
+
phase: "list",
|
|
5425
|
+
mcpServer: server || {},
|
|
5426
|
+
projectId: project_id,
|
|
5427
|
+
customer
|
|
5428
|
+
});
|
|
5429
|
+
return __spreadProps(__spreadValues({}, server || {}), {
|
|
5430
|
+
headers: __spreadValues(__spreadValues({}, typeof (server == null ? void 0 : server.headers) === "object" && (server == null ? void 0 : server.headers) ? server.headers : {}), normalizeMcpHeaders(
|
|
5431
|
+
resolved
|
|
5432
|
+
))
|
|
5433
|
+
});
|
|
5434
|
+
}))
|
|
5435
|
+
);
|
|
5436
|
+
if (!cancelled) setResolvedMcpServers(enriched);
|
|
5437
|
+
} catch (error2) {
|
|
5438
|
+
console.error("[AIChatPanel] Failed to resolve MCP auth headers:", error2);
|
|
5439
|
+
if (!cancelled) setResolvedMcpServers(mcpServers);
|
|
5440
|
+
}
|
|
5441
|
+
});
|
|
5442
|
+
void resolveServers();
|
|
5443
|
+
return () => {
|
|
5444
|
+
cancelled = true;
|
|
5445
|
+
};
|
|
5446
|
+
}, [mcpServers, resolveMcpAuthHeaders, project_id, customer]);
|
|
5447
|
+
const buildMcpRequestHeaders = (0, import_react14.useCallback)(
|
|
5448
|
+
(_0) => __async(void 0, [_0], function* ({
|
|
5449
|
+
phase,
|
|
5450
|
+
mcpServer,
|
|
5451
|
+
toolName,
|
|
5452
|
+
toolArgs
|
|
5453
|
+
}) {
|
|
5454
|
+
const merged = {};
|
|
5455
|
+
const packScopeIntoAccessToken = (headers) => {
|
|
5456
|
+
const accessToken = typeof headers["x-mcp-access-token"] === "string" ? headers["x-mcp-access-token"].trim() : "";
|
|
5457
|
+
const scopeToken = typeof headers["x-client-id"] === "string" ? headers["x-client-id"].trim() : "";
|
|
5458
|
+
if (!accessToken || !scopeToken) return headers;
|
|
5459
|
+
return __spreadProps(__spreadValues({}, headers), {
|
|
5460
|
+
"x-mcp-access-token": `${accessToken}::scope::${scopeToken}`
|
|
5461
|
+
});
|
|
5462
|
+
};
|
|
5463
|
+
const baseAccessToken = typeof mcpServer.accessToken === "string" ? mcpServer.accessToken.trim() : "";
|
|
5464
|
+
if (baseAccessToken) {
|
|
5465
|
+
merged["x-mcp-access-token"] = baseAccessToken;
|
|
5466
|
+
}
|
|
5467
|
+
if (project_id) {
|
|
5468
|
+
merged["x-project-id"] = project_id;
|
|
5469
|
+
}
|
|
5470
|
+
if (!resolveMcpAuthHeaders) return merged;
|
|
5471
|
+
try {
|
|
5472
|
+
const resolved = yield resolveMcpAuthHeaders({
|
|
5473
|
+
phase,
|
|
5474
|
+
mcpServer,
|
|
5475
|
+
projectId: project_id,
|
|
5476
|
+
customer,
|
|
5477
|
+
toolName,
|
|
5478
|
+
toolArgs
|
|
5479
|
+
});
|
|
5480
|
+
return packScopeIntoAccessToken(__spreadValues(__spreadValues({}, merged), normalizeMcpHeaders(
|
|
5481
|
+
resolved
|
|
5482
|
+
)));
|
|
5483
|
+
} catch (error2) {
|
|
5484
|
+
console.error(
|
|
5485
|
+
`Failed to resolve MCP auth headers for ${phase} request:`,
|
|
5486
|
+
error2
|
|
5487
|
+
);
|
|
5488
|
+
return merged;
|
|
5489
|
+
}
|
|
5490
|
+
}),
|
|
5491
|
+
[project_id, customer, resolveMcpAuthHeaders]
|
|
5492
|
+
);
|
|
5493
|
+
(0, import_react14.useEffect)(() => {
|
|
5494
|
+
const fetchAndSetTools = () => __async(void 0, null, function* () {
|
|
5495
|
+
if (!resolvedMcpServers || resolvedMcpServers.length === 0) {
|
|
5496
|
+
setToolList((prev) => prev.length === 0 ? prev : []);
|
|
5497
|
+
setToolsLoading((prev) => prev ? false : prev);
|
|
5498
|
+
setToolsFetchError((prev) => prev ? false : prev);
|
|
5499
|
+
return;
|
|
5500
|
+
}
|
|
5501
|
+
setToolsLoading(true);
|
|
5502
|
+
setToolsFetchError(false);
|
|
5503
|
+
try {
|
|
5504
|
+
const fetchPromises = (resolvedMcpServers != null ? resolvedMcpServers : []).map((m) => __async(void 0, null, function* () {
|
|
5505
|
+
const urlToFetch = `${publicAPIUrl}/tools/${encodeURIComponent(m.url)}`;
|
|
5506
|
+
const requestHeaders = yield buildMcpRequestHeaders({
|
|
5507
|
+
phase: "list",
|
|
5508
|
+
mcpServer: m
|
|
5509
|
+
});
|
|
5510
|
+
const response2 = yield fetch(urlToFetch, {
|
|
5511
|
+
headers: requestHeaders
|
|
5512
|
+
});
|
|
5513
|
+
if (!response2.ok) {
|
|
5514
|
+
const errorBody = yield response2.text();
|
|
5515
|
+
throw new Error(
|
|
5516
|
+
`HTTP ${response2.status}: ${response2.statusText} ${errorBody}`
|
|
5517
|
+
);
|
|
5518
|
+
}
|
|
5519
|
+
const toolsFromServer = yield response2.json();
|
|
5520
|
+
if (!Array.isArray(toolsFromServer)) return [];
|
|
5521
|
+
return toolsFromServer.map((tool) => __spreadProps(__spreadValues({}, tool), {
|
|
5522
|
+
url: m.url,
|
|
5523
|
+
accessToken: m.accessToken || "",
|
|
5524
|
+
headers: requestHeaders
|
|
5525
|
+
}));
|
|
5526
|
+
}));
|
|
5527
|
+
const results = yield Promise.all(fetchPromises);
|
|
5528
|
+
const allTools = results.flat();
|
|
5529
|
+
setToolList(allTools);
|
|
5530
|
+
setToolsFetchError(false);
|
|
5531
|
+
} catch (error2) {
|
|
5532
|
+
console.error("[AIChatPanel] Failed to load MCP tools:", error2);
|
|
5533
|
+
setToolList([]);
|
|
5534
|
+
setToolsFetchError(true);
|
|
5535
|
+
} finally {
|
|
5536
|
+
setToolsLoading(false);
|
|
5537
|
+
}
|
|
5538
|
+
});
|
|
5539
|
+
void fetchAndSetTools();
|
|
5540
|
+
}, [resolvedMcpServers, publicAPIUrl, buildMcpRequestHeaders]);
|
|
5541
|
+
const llmResult = (0, import_llmasaservice_client2.useLLM)(__spreadProps(__spreadValues(__spreadValues(__spreadValues({
|
|
4281
5542
|
project_id,
|
|
4282
5543
|
customer
|
|
4283
|
-
}, url && { url }), service && { group_id: service }), agent && { agent }),
|
|
5544
|
+
}, url && { url }), service && { group_id: service }), agent && { agent }), {
|
|
5545
|
+
tools: toolList.map((item) => ({
|
|
5546
|
+
name: item.name,
|
|
5547
|
+
description: item.description,
|
|
5548
|
+
parameters: item.parameters
|
|
5549
|
+
}))
|
|
5550
|
+
}));
|
|
4284
5551
|
const {
|
|
4285
5552
|
send,
|
|
4286
5553
|
response,
|
|
@@ -4290,9 +5557,6 @@ var AIChatPanel = ({
|
|
|
4290
5557
|
setResponse,
|
|
4291
5558
|
error: llmError
|
|
4292
5559
|
} = llmResult;
|
|
4293
|
-
const toolList = llmResult.toolList || [];
|
|
4294
|
-
const toolsLoading = llmResult.toolsLoading || false;
|
|
4295
|
-
const toolsFetchError = llmResult.toolsFetchError || null;
|
|
4296
5560
|
const historyCallbackRef = (0, import_react14.useRef)(historyChangedCallback);
|
|
4297
5561
|
const responseCompleteCallbackRef = (0, import_react14.useRef)(responseCompleteCallback);
|
|
4298
5562
|
const responseRef = (0, import_react14.useRef)(response);
|
|
@@ -4333,18 +5597,26 @@ var AIChatPanel = ({
|
|
|
4333
5597
|
}
|
|
4334
5598
|
}, [propOnToggleSection]);
|
|
4335
5599
|
const ensureConversation = (0, import_react14.useCallback)(() => {
|
|
4336
|
-
|
|
5600
|
+
const normalizedConversationId = typeof currentConversation === "string" ? currentConversation.trim() : "";
|
|
4337
5601
|
console.log("ensureConversation - called with:", {
|
|
4338
|
-
currentConversation,
|
|
5602
|
+
currentConversation: normalizedConversationId || null,
|
|
4339
5603
|
createConversationOnFirstChat,
|
|
4340
5604
|
project_id,
|
|
4341
5605
|
publicAPIUrl
|
|
4342
5606
|
});
|
|
4343
|
-
if (
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
5607
|
+
if (normalizedConversationId) {
|
|
5608
|
+
console.log("ensureConversation - using existing conversation:", normalizedConversationId);
|
|
5609
|
+
return Promise.resolve(normalizedConversationId);
|
|
5610
|
+
}
|
|
5611
|
+
if (!createConversationOnFirstChat) {
|
|
5612
|
+
return Promise.resolve("");
|
|
5613
|
+
}
|
|
5614
|
+
if (!project_id) {
|
|
5615
|
+
console.error("ensureConversation - Cannot create conversation without project_id");
|
|
5616
|
+
return Promise.resolve("");
|
|
5617
|
+
}
|
|
5618
|
+
const createConversation = () => {
|
|
5619
|
+
var _a2, _b;
|
|
4348
5620
|
const requestBody = {
|
|
4349
5621
|
project_id,
|
|
4350
5622
|
agentId: agent,
|
|
@@ -4370,11 +5642,13 @@ var AIChatPanel = ({
|
|
|
4370
5642
|
}
|
|
4371
5643
|
return res.json();
|
|
4372
5644
|
})).then((newConvo) => {
|
|
5645
|
+
var _a3;
|
|
4373
5646
|
console.log("ensureConversation - API response:", newConvo);
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
5647
|
+
const createdId = typeof (newConvo == null ? void 0 : newConvo.id) === "string" && newConvo.id.trim() || typeof (newConvo == null ? void 0 : newConvo.conversationId) === "string" && newConvo.conversationId.trim() || typeof (newConvo == null ? void 0 : newConvo.conversation_id) === "string" && newConvo.conversation_id.trim() || typeof ((_a3 = newConvo == null ? void 0 : newConvo.conversation) == null ? void 0 : _a3.id) === "string" && newConvo.conversation.id.trim() || "";
|
|
5648
|
+
if (createdId) {
|
|
5649
|
+
console.log("ensureConversation - New conversation ID:", createdId);
|
|
5650
|
+
setCurrentConversation(createdId);
|
|
5651
|
+
return createdId;
|
|
4378
5652
|
}
|
|
4379
5653
|
console.warn("ensureConversation - No ID in response");
|
|
4380
5654
|
return "";
|
|
@@ -4382,9 +5656,8 @@ var AIChatPanel = ({
|
|
|
4382
5656
|
console.error("Error creating new conversation", error2);
|
|
4383
5657
|
return "";
|
|
4384
5658
|
});
|
|
4385
|
-
}
|
|
4386
|
-
|
|
4387
|
-
return Promise.resolve(currentConversation);
|
|
5659
|
+
};
|
|
5660
|
+
return createConversation();
|
|
4388
5661
|
}, [currentConversation, createConversationOnFirstChat, publicAPIUrl, project_id, agent, customer, browserInfo]);
|
|
4389
5662
|
const dataWithExtras = (0, import_react14.useCallback)(() => {
|
|
4390
5663
|
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
@@ -4567,19 +5840,565 @@ var AIChatPanel = ({
|
|
|
4567
5840
|
}
|
|
4568
5841
|
return false;
|
|
4569
5842
|
}, [customerEmailCaptureMode, emailInputSet]);
|
|
4570
|
-
const
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
5843
|
+
const pendingToolRequestsRef = (0, import_react14.useRef)(pendingToolRequests);
|
|
5844
|
+
const streamIdleRef = (0, import_react14.useRef)(idle);
|
|
5845
|
+
streamIdleRef.current = idle;
|
|
5846
|
+
const waitForStreamIdle = (0, import_react14.useCallback)((timeoutMs = 2500) => __async(void 0, null, function* () {
|
|
5847
|
+
const startedAt = Date.now();
|
|
5848
|
+
while (!streamIdleRef.current && Date.now() - startedAt < timeoutMs) {
|
|
5849
|
+
yield new Promise((resolve) => {
|
|
5850
|
+
setTimeout(resolve, 25);
|
|
5851
|
+
});
|
|
4576
5852
|
}
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
const getUniqueToolNames = (0, import_react14.useCallback)(() => {
|
|
4581
|
-
return Array.from(new Set(pendingToolRequests.map((r) => r.toolName)));
|
|
5853
|
+
}), []);
|
|
5854
|
+
(0, import_react14.useEffect)(() => {
|
|
5855
|
+
pendingToolRequestsRef.current = pendingToolRequests;
|
|
4582
5856
|
}, [pendingToolRequests]);
|
|
5857
|
+
const processGivenToolRequests = (0, import_react14.useCallback)(
|
|
5858
|
+
(requests) => __async(void 0, null, function* () {
|
|
5859
|
+
var _a2, _b, _c;
|
|
5860
|
+
const dedupeToolRequests = (input) => {
|
|
5861
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5862
|
+
const deduped = [];
|
|
5863
|
+
for (const request of Array.isArray(input) ? input : []) {
|
|
5864
|
+
if (!request) continue;
|
|
5865
|
+
const signature = getToolCallSignature(request.toolName, request.callId) || request.match;
|
|
5866
|
+
if (!signature || seen.has(signature)) continue;
|
|
5867
|
+
seen.add(signature);
|
|
5868
|
+
deduped.push(request);
|
|
5869
|
+
}
|
|
5870
|
+
return deduped;
|
|
5871
|
+
};
|
|
5872
|
+
if (toolRequestProcessingRef.current) {
|
|
5873
|
+
const queued = dedupeToolRequests([
|
|
5874
|
+
...queuedToolRequestsRef.current || [],
|
|
5875
|
+
...Array.isArray(requests) ? requests : []
|
|
5876
|
+
]);
|
|
5877
|
+
if (queued.length > 0) {
|
|
5878
|
+
queuedToolRequestsRef.current = queued;
|
|
5879
|
+
}
|
|
5880
|
+
return;
|
|
5881
|
+
}
|
|
5882
|
+
toolRequestProcessingRef.current = true;
|
|
5883
|
+
try {
|
|
5884
|
+
let requestsToProcess = requests;
|
|
5885
|
+
if (!requestsToProcess || requestsToProcess.length === 0) {
|
|
5886
|
+
requestsToProcess = pendingToolRequestsRef.current || [];
|
|
5887
|
+
}
|
|
5888
|
+
if (!requestsToProcess || requestsToProcess.length === 0) return;
|
|
5889
|
+
setIsLoading(true);
|
|
5890
|
+
const userPrompt = lastPromptRef.current || lastKeyRef.current || "";
|
|
5891
|
+
const lastPromptKey = lastKeyRef.current;
|
|
5892
|
+
const assistantSeedText = lastPromptKey && ((_a2 = latestHistoryRef.current[lastPromptKey]) == null ? void 0 : _a2.content) ? (_b = latestHistoryRef.current[lastPromptKey]) == null ? void 0 : _b.content : "";
|
|
5893
|
+
const historyForContinuation = latestHistoryRef.current || {};
|
|
5894
|
+
const newMessages = [];
|
|
5895
|
+
Object.entries(historyForContinuation).forEach(([historyPrompt, historyEntry]) => {
|
|
5896
|
+
let promptForHistory = String(historyPrompt || "");
|
|
5897
|
+
const isoTimestampRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z:/;
|
|
5898
|
+
if (isoTimestampRegex.test(promptForHistory)) {
|
|
5899
|
+
const colonIndex = promptForHistory.indexOf(":", 19);
|
|
5900
|
+
promptForHistory = promptForHistory.substring(colonIndex + 1);
|
|
5901
|
+
} else if (/^\d+:/.test(promptForHistory)) {
|
|
5902
|
+
const colonIndex = promptForHistory.indexOf(":");
|
|
5903
|
+
promptForHistory = promptForHistory.substring(colonIndex + 1);
|
|
5904
|
+
}
|
|
5905
|
+
const typedHistoryEntry = historyEntry || { content: "", callId: "" };
|
|
5906
|
+
const assistantBaseContent = typeof typedHistoryEntry.content === "string" ? typedHistoryEntry.content : "";
|
|
5907
|
+
let assistantContextContent = assistantBaseContent;
|
|
5908
|
+
if (traceContextMode === "full") {
|
|
5909
|
+
const traceSummary = buildCompactTraceSummary({
|
|
5910
|
+
reasoningBlocks: thinkingBlocksByKeyRef.current[historyPrompt] || [],
|
|
5911
|
+
toolCalls: typedHistoryEntry.toolCalls,
|
|
5912
|
+
toolResponses: typedHistoryEntry.toolResponses
|
|
5913
|
+
});
|
|
5914
|
+
if (traceSummary) {
|
|
5915
|
+
assistantContextContent = assistantBaseContent ? `${assistantBaseContent}
|
|
5916
|
+
|
|
5917
|
+
${traceSummary}` : traceSummary;
|
|
5918
|
+
}
|
|
5919
|
+
}
|
|
5920
|
+
newMessages.push({
|
|
5921
|
+
role: "user",
|
|
5922
|
+
content: [
|
|
5923
|
+
{
|
|
5924
|
+
type: "text",
|
|
5925
|
+
text: promptForHistory
|
|
5926
|
+
}
|
|
5927
|
+
]
|
|
5928
|
+
});
|
|
5929
|
+
newMessages.push({
|
|
5930
|
+
role: "assistant",
|
|
5931
|
+
content: [
|
|
5932
|
+
{
|
|
5933
|
+
type: "text",
|
|
5934
|
+
text: assistantContextContent
|
|
5935
|
+
}
|
|
5936
|
+
]
|
|
5937
|
+
});
|
|
5938
|
+
});
|
|
5939
|
+
if (newMessages.length === 0 && userPrompt.trim().length > 0) {
|
|
5940
|
+
newMessages.push({
|
|
5941
|
+
role: "user",
|
|
5942
|
+
content: [
|
|
5943
|
+
{
|
|
5944
|
+
type: "text",
|
|
5945
|
+
text: userPrompt
|
|
5946
|
+
}
|
|
5947
|
+
]
|
|
5948
|
+
});
|
|
5949
|
+
if (assistantSeedText.trim().length > 0) {
|
|
5950
|
+
newMessages.push({
|
|
5951
|
+
role: "assistant",
|
|
5952
|
+
content: [
|
|
5953
|
+
{
|
|
5954
|
+
type: "text",
|
|
5955
|
+
text: assistantSeedText
|
|
5956
|
+
}
|
|
5957
|
+
]
|
|
5958
|
+
});
|
|
5959
|
+
}
|
|
5960
|
+
}
|
|
5961
|
+
const parsedToolCalls = yield Promise.all(
|
|
5962
|
+
requestsToProcess.map((req, index) => __async(void 0, null, function* () {
|
|
5963
|
+
var _a3, _b2, _c2, _d, _e, _f;
|
|
5964
|
+
let parsedToolCall = null;
|
|
5965
|
+
try {
|
|
5966
|
+
parsedToolCall = JSON.parse(req.match);
|
|
5967
|
+
} catch (error2) {
|
|
5968
|
+
console.error("[AIChatPanel] Failed to parse tool call payload:", error2);
|
|
5969
|
+
}
|
|
5970
|
+
const toolName = req.groups[1] || req.toolName || (typeof (parsedToolCall == null ? void 0 : parsedToolCall.name) === "string" ? parsedToolCall.name : "") || (typeof ((_a3 = parsedToolCall == null ? void 0 : parsedToolCall.function) == null ? void 0 : _a3.name) === "string" ? parsedToolCall.function.name : "");
|
|
5971
|
+
if (!toolName) return null;
|
|
5972
|
+
const rawCallId = req.callId || req.groups[0] || (parsedToolCall == null ? void 0 : parsedToolCall.id) || (parsedToolCall == null ? void 0 : parsedToolCall.tool_call_id) || `${toolName}-${index + 1}`;
|
|
5973
|
+
const callId = typeof rawCallId === "string" && rawCallId.trim().length > 0 && rawCallId !== "functionCall" ? rawCallId : `${toolName}-${index + 1}`;
|
|
5974
|
+
let args = {};
|
|
5975
|
+
const rawArgs = (_f = (_e = (_c2 = (_b2 = req.groups[2]) != null ? _b2 : parsedToolCall == null ? void 0 : parsedToolCall.input) != null ? _c2 : parsedToolCall == null ? void 0 : parsedToolCall.args) != null ? _e : (_d = parsedToolCall == null ? void 0 : parsedToolCall.function) == null ? void 0 : _d.arguments) != null ? _f : "{}";
|
|
5976
|
+
const parsedArgs = parseToolArguments(rawArgs);
|
|
5977
|
+
if (!parsedArgs) {
|
|
5978
|
+
console.error("[AIChatPanel] Failed to parse tool arguments", {
|
|
5979
|
+
toolName,
|
|
5980
|
+
callId,
|
|
5981
|
+
rawArgsPreview: typeof rawArgs === "string" ? rawArgs.slice(0, 500) : JSON.stringify(rawArgs).slice(0, 500)
|
|
5982
|
+
});
|
|
5983
|
+
return null;
|
|
5984
|
+
}
|
|
5985
|
+
args = parsedArgs;
|
|
5986
|
+
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 || "";
|
|
5987
|
+
const callSignature = getToolCallSignature(toolName, callId);
|
|
5988
|
+
if (!callSignature) return null;
|
|
5989
|
+
return {
|
|
5990
|
+
req,
|
|
5991
|
+
toolName,
|
|
5992
|
+
callId,
|
|
5993
|
+
args,
|
|
5994
|
+
serviceTag,
|
|
5995
|
+
callSignature
|
|
5996
|
+
};
|
|
5997
|
+
}))
|
|
5998
|
+
);
|
|
5999
|
+
const toolCallBatch = parsedToolCalls.filter(Boolean);
|
|
6000
|
+
const seenCallSignatures = /* @__PURE__ */ new Set();
|
|
6001
|
+
const callsToRun = [];
|
|
6002
|
+
toolCallBatch.forEach((toolCall) => {
|
|
6003
|
+
if (seenCallSignatures.has(toolCall.callSignature)) return;
|
|
6004
|
+
seenCallSignatures.add(toolCall.callSignature);
|
|
6005
|
+
if (handledToolCallSignaturesRef.current.has(toolCall.callSignature)) return;
|
|
6006
|
+
if (inFlightToolCallSignaturesRef.current.has(toolCall.callSignature)) return;
|
|
6007
|
+
callsToRun.push(toolCall);
|
|
6008
|
+
});
|
|
6009
|
+
if (callsToRun.length === 0) {
|
|
6010
|
+
setPendingToolRequests(
|
|
6011
|
+
(prev) => prev.filter((request) => {
|
|
6012
|
+
const signature = getToolCallSignature(request.toolName, request.callId);
|
|
6013
|
+
if (!signature) return true;
|
|
6014
|
+
return !seenCallSignatures.has(signature);
|
|
6015
|
+
})
|
|
6016
|
+
);
|
|
6017
|
+
setActiveToolCalls([]);
|
|
6018
|
+
setIsLoading(false);
|
|
6019
|
+
return;
|
|
6020
|
+
}
|
|
6021
|
+
const callsToRunSignatures = new Set(callsToRun.map((toolCall) => toolCall.callSignature));
|
|
6022
|
+
setPendingToolRequests(
|
|
6023
|
+
(prev) => prev.filter((request) => {
|
|
6024
|
+
const signature = getToolCallSignature(request.toolName, request.callId);
|
|
6025
|
+
return !signature || !callsToRunSignatures.has(signature);
|
|
6026
|
+
})
|
|
6027
|
+
);
|
|
6028
|
+
callsToRun.forEach((toolCall) => {
|
|
6029
|
+
inFlightToolCallSignaturesRef.current.add(toolCall.callSignature);
|
|
6030
|
+
});
|
|
6031
|
+
setActiveToolCalls(
|
|
6032
|
+
callsToRun.map((toolCall) => ({
|
|
6033
|
+
toolName: toolCall.toolName,
|
|
6034
|
+
callId: toolCall.callId
|
|
6035
|
+
}))
|
|
6036
|
+
);
|
|
6037
|
+
const finalToolCalls = callsToRun.map((toolCall) => ({
|
|
6038
|
+
id: toolCall.callId,
|
|
6039
|
+
type: "tool_use",
|
|
6040
|
+
name: toolCall.toolName,
|
|
6041
|
+
input: toolCall.args,
|
|
6042
|
+
service: toolCall.serviceTag
|
|
6043
|
+
}));
|
|
6044
|
+
let finalToolResponses = [];
|
|
6045
|
+
try {
|
|
6046
|
+
const toolResponses = yield Promise.all(
|
|
6047
|
+
callsToRun.map((toolCall) => __async(void 0, null, function* () {
|
|
6048
|
+
var _a3, _b2, _c2, _d, _e, _f, _g;
|
|
6049
|
+
const mcpTool = toolList.find((tool) => tool.name === toolCall.toolName) || null;
|
|
6050
|
+
const localExecutor = localToolExecutors && typeof localToolExecutors[toolCall.toolName] === "function" ? localToolExecutors[toolCall.toolName] : null;
|
|
6051
|
+
if (localExecutor) {
|
|
6052
|
+
try {
|
|
6053
|
+
const localResult = yield localExecutor(toolCall.args, {
|
|
6054
|
+
toolName: toolCall.toolName,
|
|
6055
|
+
callId: toolCall.callId,
|
|
6056
|
+
serviceTag: toolCall.serviceTag,
|
|
6057
|
+
mcpTool
|
|
6058
|
+
});
|
|
6059
|
+
if (localResult && typeof localResult === "object" && !Array.isArray(localResult)) {
|
|
6060
|
+
const objectResult = localResult;
|
|
6061
|
+
const isError = objectResult.isError === true || objectResult.error === true;
|
|
6062
|
+
const maybeResult = Object.prototype.hasOwnProperty.call(objectResult, "result") ? objectResult.result : localResult;
|
|
6063
|
+
const textResult = typeof maybeResult === "string" ? maybeResult : JSON.stringify(maybeResult != null ? maybeResult : {});
|
|
6064
|
+
return {
|
|
6065
|
+
tool_call_id: toolCall.callId,
|
|
6066
|
+
tool_name: toolCall.toolName,
|
|
6067
|
+
result: textResult || "",
|
|
6068
|
+
isError
|
|
6069
|
+
};
|
|
6070
|
+
}
|
|
6071
|
+
return {
|
|
6072
|
+
tool_call_id: toolCall.callId,
|
|
6073
|
+
tool_name: toolCall.toolName,
|
|
6074
|
+
result: typeof localResult === "string" ? localResult : JSON.stringify(localResult != null ? localResult : {}),
|
|
6075
|
+
isError: false
|
|
6076
|
+
};
|
|
6077
|
+
} catch (error2) {
|
|
6078
|
+
return {
|
|
6079
|
+
tool_call_id: toolCall.callId,
|
|
6080
|
+
tool_name: toolCall.toolName,
|
|
6081
|
+
result: error2 instanceof Error ? error2.message : `Unhandled error calling ${toolCall.toolName}`,
|
|
6082
|
+
isError: true
|
|
6083
|
+
};
|
|
6084
|
+
}
|
|
6085
|
+
}
|
|
6086
|
+
if (!mcpTool) {
|
|
6087
|
+
console.error(`[AIChatPanel] Tool ${toolCall.toolName} not found in tool list`);
|
|
6088
|
+
return {
|
|
6089
|
+
tool_call_id: toolCall.callId,
|
|
6090
|
+
tool_name: toolCall.toolName,
|
|
6091
|
+
result: `Tool ${toolCall.toolName} not found in current tool list.`,
|
|
6092
|
+
isError: true
|
|
6093
|
+
};
|
|
6094
|
+
}
|
|
6095
|
+
const toolUrl = typeof mcpTool.url === "string" ? mcpTool.url : "";
|
|
6096
|
+
if (!toolUrl) {
|
|
6097
|
+
return {
|
|
6098
|
+
tool_call_id: toolCall.callId,
|
|
6099
|
+
tool_name: toolCall.toolName,
|
|
6100
|
+
result: `Tool ${toolCall.toolName} is missing url metadata.`,
|
|
6101
|
+
isError: true
|
|
6102
|
+
};
|
|
6103
|
+
}
|
|
6104
|
+
const body = {
|
|
6105
|
+
tool: toolCall.toolName,
|
|
6106
|
+
args: toolCall.args
|
|
6107
|
+
};
|
|
6108
|
+
try {
|
|
6109
|
+
const result = yield fetch(
|
|
6110
|
+
`${publicAPIUrl}/tools/${encodeURIComponent(toolUrl)}`,
|
|
6111
|
+
{
|
|
6112
|
+
method: "POST",
|
|
6113
|
+
headers: __spreadValues({
|
|
6114
|
+
"Content-Type": "application/json"
|
|
6115
|
+
}, yield buildMcpRequestHeaders({
|
|
6116
|
+
phase: "call",
|
|
6117
|
+
mcpServer: mcpTool,
|
|
6118
|
+
toolName: toolCall.toolName,
|
|
6119
|
+
toolArgs: toolCall.args
|
|
6120
|
+
})),
|
|
6121
|
+
body: JSON.stringify(body)
|
|
6122
|
+
}
|
|
6123
|
+
);
|
|
6124
|
+
if (!result.ok) {
|
|
6125
|
+
const errorBody = yield result.text();
|
|
6126
|
+
console.error(
|
|
6127
|
+
`[AIChatPanel] Tool call failed ${toolCall.toolName}: ${result.status} ${result.statusText} ${errorBody}`
|
|
6128
|
+
);
|
|
6129
|
+
return {
|
|
6130
|
+
tool_call_id: toolCall.callId,
|
|
6131
|
+
tool_name: toolCall.toolName,
|
|
6132
|
+
result: `HTTP ${result.status} ${result.statusText}: ${errorBody || "Tool call failed"}`,
|
|
6133
|
+
isError: true
|
|
6134
|
+
};
|
|
6135
|
+
}
|
|
6136
|
+
let resultData = null;
|
|
6137
|
+
try {
|
|
6138
|
+
resultData = yield result.json();
|
|
6139
|
+
} catch (error2) {
|
|
6140
|
+
console.error("[AIChatPanel] Failed parsing tool call JSON response:", error2);
|
|
6141
|
+
return {
|
|
6142
|
+
tool_call_id: toolCall.callId,
|
|
6143
|
+
tool_name: toolCall.toolName,
|
|
6144
|
+
result: "Tool returned a non-JSON response.",
|
|
6145
|
+
isError: true
|
|
6146
|
+
};
|
|
6147
|
+
}
|
|
6148
|
+
const textResult = (_c2 = (_b2 = (_a3 = resultData == null ? void 0 : resultData.content) == null ? void 0 : _a3[0]) == null ? void 0 : _b2.text) != null ? _c2 : (resultData == null ? void 0 : resultData.result) ? JSON.stringify(resultData.result) : JSON.stringify(resultData);
|
|
6149
|
+
const inferredError = (resultData == null ? void 0 : resultData.isError) === true || (resultData == null ? void 0 : resultData.error) === true || typeof (resultData == null ? void 0 : resultData.error) === "string" || (resultData == null ? void 0 : resultData.status) === "error" || ((_d = resultData == null ? void 0 : resultData.result) == null ? void 0 : _d.isError) === true || ((_e = resultData == null ? void 0 : resultData.result) == null ? void 0 : _e.error) === true || typeof ((_f = resultData == null ? void 0 : resultData.result) == null ? void 0 : _f.error) === "string";
|
|
6150
|
+
const normalizedResultText = typeof textResult === "string" && textResult.trim().length > 0 ? textResult : inferredError && typeof (resultData == null ? void 0 : resultData.error) === "string" ? resultData.error : inferredError && typeof ((_g = resultData == null ? void 0 : resultData.result) == null ? void 0 : _g.error) === "string" ? resultData.result.error : "";
|
|
6151
|
+
return {
|
|
6152
|
+
tool_call_id: toolCall.callId,
|
|
6153
|
+
tool_name: toolCall.toolName,
|
|
6154
|
+
result: normalizedResultText,
|
|
6155
|
+
isError: inferredError
|
|
6156
|
+
};
|
|
6157
|
+
} catch (error2) {
|
|
6158
|
+
console.error(`[AIChatPanel] Error calling tool ${toolCall.toolName}:`, error2);
|
|
6159
|
+
return {
|
|
6160
|
+
tool_call_id: toolCall.callId,
|
|
6161
|
+
tool_name: toolCall.toolName,
|
|
6162
|
+
result: error2 instanceof Error ? error2.message : `Unhandled error calling ${toolCall.toolName}`,
|
|
6163
|
+
isError: true
|
|
6164
|
+
};
|
|
6165
|
+
}
|
|
6166
|
+
}))
|
|
6167
|
+
);
|
|
6168
|
+
finalToolResponses = toolResponses.filter(Boolean);
|
|
6169
|
+
} finally {
|
|
6170
|
+
callsToRun.forEach((toolCall) => {
|
|
6171
|
+
inFlightToolCallSignaturesRef.current.delete(toolCall.callSignature);
|
|
6172
|
+
handledToolCallSignaturesRef.current.add(toolCall.callSignature);
|
|
6173
|
+
});
|
|
6174
|
+
}
|
|
6175
|
+
setActiveToolCalls([]);
|
|
6176
|
+
const currentLastKey = lastKeyRef.current;
|
|
6177
|
+
if (currentLastKey) {
|
|
6178
|
+
setHistory((prev) => {
|
|
6179
|
+
const existingEntry = prev[currentLastKey] || { content: "", callId: "" };
|
|
6180
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
6181
|
+
[currentLastKey]: __spreadProps(__spreadValues({}, existingEntry), {
|
|
6182
|
+
toolCalls: [...existingEntry.toolCalls || [], ...finalToolCalls],
|
|
6183
|
+
toolResponses: [...existingEntry.toolResponses || [], ...finalToolResponses]
|
|
6184
|
+
})
|
|
6185
|
+
});
|
|
6186
|
+
});
|
|
6187
|
+
}
|
|
6188
|
+
const toReplayText = (value) => {
|
|
6189
|
+
const raw = typeof value === "string" ? value : (() => {
|
|
6190
|
+
try {
|
|
6191
|
+
return JSON.stringify(value);
|
|
6192
|
+
} catch (_error) {
|
|
6193
|
+
return String(value != null ? value : "");
|
|
6194
|
+
}
|
|
6195
|
+
})();
|
|
6196
|
+
return String(raw != null ? raw : "");
|
|
6197
|
+
};
|
|
6198
|
+
const replayEntryKey = lastKeyRef.current || "";
|
|
6199
|
+
const previousReplayEntries = replayEntryKey ? toolReplaySummariesByKeyRef.current[replayEntryKey] || [] : [];
|
|
6200
|
+
const currentReplayEntries = callsToRun.map((toolCall, index) => {
|
|
6201
|
+
var _a3;
|
|
6202
|
+
const matchedResponse = finalToolResponses.find((response2) => (response2 == null ? void 0 : response2.tool_call_id) === toolCall.callId) || finalToolResponses[index];
|
|
6203
|
+
return {
|
|
6204
|
+
toolName: toolCall.toolName,
|
|
6205
|
+
callId: toolCall.callId,
|
|
6206
|
+
status: (matchedResponse == null ? void 0 : matchedResponse.isError) ? "error" : "ok",
|
|
6207
|
+
argsText: toReplayText(toolCall.args),
|
|
6208
|
+
resultText: toReplayText((_a3 = matchedResponse == null ? void 0 : matchedResponse.result) != null ? _a3 : "No result returned")
|
|
6209
|
+
};
|
|
6210
|
+
});
|
|
6211
|
+
const replayEntries = [...previousReplayEntries, ...currentReplayEntries];
|
|
6212
|
+
if (replayEntryKey) {
|
|
6213
|
+
toolReplaySummariesByKeyRef.current[replayEntryKey] = replayEntries;
|
|
6214
|
+
}
|
|
6215
|
+
const replayLines = replayEntries.map(
|
|
6216
|
+
(entry) => [
|
|
6217
|
+
`Tool: ${entry.toolName}`,
|
|
6218
|
+
`Call ID: ${entry.callId}`,
|
|
6219
|
+
`Status: ${entry.status}`,
|
|
6220
|
+
`Args: ${entry.argsText}`,
|
|
6221
|
+
`Result: ${entry.resultText}`
|
|
6222
|
+
].join("\n")
|
|
6223
|
+
);
|
|
6224
|
+
const originalRequest = typeof lastPromptRef.current === "string" && lastPromptRef.current.trim() || typeof userPrompt === "string" && userPrompt.trim() || "";
|
|
6225
|
+
const continuationPromptText = [
|
|
6226
|
+
originalRequest ? `Original request: ${originalRequest}` : "",
|
|
6227
|
+
"Tool execution summary for the previous request:",
|
|
6228
|
+
...replayLines,
|
|
6229
|
+
"Continue the same assistant response from exactly where you paused using these tool results.",
|
|
6230
|
+
"Treat successful mutating tool results above as already completed actions. Do not repeat those same mutating tool calls unless the user explicitly asks to retry.",
|
|
6231
|
+
"If you include meta tags, use only <thinking>, <reasoning>, <searching> for internal process.",
|
|
6232
|
+
"Put the final user-facing answer outside all meta tags."
|
|
6233
|
+
].filter(Boolean).join("\n\n");
|
|
6234
|
+
if (continuationPromptText.length > MAX_TOOL_REPLAY_PAYLOAD_CHARS) {
|
|
6235
|
+
setActiveToolCalls([]);
|
|
6236
|
+
setIsLoading(false);
|
|
6237
|
+
setError({
|
|
6238
|
+
message: "Tool result payload is too large to continue safely in a single turn. Narrow the query or fetch steps in chunks.",
|
|
6239
|
+
code: "TOOL_REPLAY_TOO_LARGE"
|
|
6240
|
+
});
|
|
6241
|
+
return;
|
|
6242
|
+
}
|
|
6243
|
+
newMessages.push({
|
|
6244
|
+
role: "user",
|
|
6245
|
+
content: [
|
|
6246
|
+
{
|
|
6247
|
+
type: "text",
|
|
6248
|
+
text: continuationPromptText
|
|
6249
|
+
}
|
|
6250
|
+
]
|
|
6251
|
+
});
|
|
6252
|
+
if (toolContinuationCountRef.current >= MAX_TOOL_CONTINUATIONS_PER_TURN) {
|
|
6253
|
+
setActiveToolCalls([]);
|
|
6254
|
+
setIsLoading(false);
|
|
6255
|
+
setError({
|
|
6256
|
+
message: "Tool continuation limit reached for this response. Please refine the prompt and retry.",
|
|
6257
|
+
code: "TOOL_CONTINUATION_LIMIT"
|
|
6258
|
+
});
|
|
6259
|
+
return;
|
|
6260
|
+
}
|
|
6261
|
+
toolContinuationCountRef.current += 1;
|
|
6262
|
+
if (!streamIdleRef.current) {
|
|
6263
|
+
yield waitForStreamIdle(1e4);
|
|
6264
|
+
}
|
|
6265
|
+
if (!streamIdleRef.current) {
|
|
6266
|
+
suppressAbortHistoryUpdateRef.current = true;
|
|
6267
|
+
try {
|
|
6268
|
+
stop(lastController);
|
|
6269
|
+
yield waitForStreamIdle(3e3);
|
|
6270
|
+
} finally {
|
|
6271
|
+
suppressAbortHistoryUpdateRef.current = false;
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6274
|
+
if (!streamIdleRef.current) {
|
|
6275
|
+
setActiveToolCalls([]);
|
|
6276
|
+
setIsLoading(false);
|
|
6277
|
+
setError({
|
|
6278
|
+
message: "Timed out waiting for the previous stream to settle before tool continuation.",
|
|
6279
|
+
code: "TOOL_CONTINUATION_WAIT_TIMEOUT"
|
|
6280
|
+
});
|
|
6281
|
+
return;
|
|
6282
|
+
}
|
|
6283
|
+
const newController = new AbortController();
|
|
6284
|
+
setLastController(newController);
|
|
6285
|
+
const continuationKey = lastKeyRef.current;
|
|
6286
|
+
if (continuationKey) {
|
|
6287
|
+
const continuationBase = ((_c = latestHistoryRef.current[continuationKey]) == null ? void 0 : _c.content) || "";
|
|
6288
|
+
activeStreamAppendBaseRef.current = continuationBase.trim().length > 0 ? { key: continuationKey, base: continuationBase } : null;
|
|
6289
|
+
} else {
|
|
6290
|
+
activeStreamAppendBaseRef.current = null;
|
|
6291
|
+
}
|
|
6292
|
+
send(
|
|
6293
|
+
"",
|
|
6294
|
+
newMessages,
|
|
6295
|
+
[
|
|
6296
|
+
...dataWithExtras(),
|
|
6297
|
+
{
|
|
6298
|
+
key: "--messages",
|
|
6299
|
+
data: newMessages.length.toString()
|
|
6300
|
+
}
|
|
6301
|
+
],
|
|
6302
|
+
true,
|
|
6303
|
+
true,
|
|
6304
|
+
service,
|
|
6305
|
+
currentConversation,
|
|
6306
|
+
newController,
|
|
6307
|
+
void 0,
|
|
6308
|
+
(errorMsg) => {
|
|
6309
|
+
setActiveToolCalls([]);
|
|
6310
|
+
setIsLoading(false);
|
|
6311
|
+
setError({
|
|
6312
|
+
message: errorMsg,
|
|
6313
|
+
code: "TOOL_ERROR"
|
|
6314
|
+
});
|
|
6315
|
+
}
|
|
6316
|
+
);
|
|
6317
|
+
} finally {
|
|
6318
|
+
toolRequestProcessingRef.current = false;
|
|
6319
|
+
const queued = queuedToolRequestsRef.current;
|
|
6320
|
+
if (queued && queued.length > 0) {
|
|
6321
|
+
queuedToolRequestsRef.current = null;
|
|
6322
|
+
queueMicrotask(() => {
|
|
6323
|
+
void processGivenToolRequests(queued);
|
|
6324
|
+
});
|
|
6325
|
+
}
|
|
6326
|
+
}
|
|
6327
|
+
}),
|
|
6328
|
+
[
|
|
6329
|
+
toolList,
|
|
6330
|
+
localToolExecutors,
|
|
6331
|
+
publicAPIUrl,
|
|
6332
|
+
buildMcpRequestHeaders,
|
|
6333
|
+
dataWithExtras,
|
|
6334
|
+
send,
|
|
6335
|
+
service,
|
|
6336
|
+
currentConversation,
|
|
6337
|
+
setActiveToolCalls,
|
|
6338
|
+
getToolCallSignature,
|
|
6339
|
+
traceContextMode,
|
|
6340
|
+
idle,
|
|
6341
|
+
stop,
|
|
6342
|
+
lastController,
|
|
6343
|
+
waitForStreamIdle
|
|
6344
|
+
]
|
|
6345
|
+
);
|
|
6346
|
+
const handleToolApproval = (0, import_react14.useCallback)(
|
|
6347
|
+
(toolName, scope) => {
|
|
6348
|
+
const normalizedToolName = normalizeToolName(toolName);
|
|
6349
|
+
if (!normalizedToolName) return;
|
|
6350
|
+
if (scope === "session" || scope === "always") {
|
|
6351
|
+
setSessionApprovedTools((prev) => Array.from(/* @__PURE__ */ new Set([...prev, normalizedToolName])));
|
|
6352
|
+
}
|
|
6353
|
+
if (scope === "always") {
|
|
6354
|
+
setAlwaysApprovedTools((prev) => Array.from(/* @__PURE__ */ new Set([...prev, normalizedToolName])));
|
|
6355
|
+
}
|
|
6356
|
+
const requestsToRun = (pendingToolRequestsRef.current || []).filter(
|
|
6357
|
+
(r) => normalizeToolName(r.toolName) === normalizedToolName
|
|
6358
|
+
);
|
|
6359
|
+
void processGivenToolRequests(requestsToRun);
|
|
6360
|
+
setPendingToolRequests(
|
|
6361
|
+
(prev) => prev.filter((r) => normalizeToolName(r.toolName) !== normalizedToolName)
|
|
6362
|
+
);
|
|
6363
|
+
},
|
|
6364
|
+
[processGivenToolRequests, normalizeToolName]
|
|
6365
|
+
);
|
|
6366
|
+
(0, import_react14.useEffect)(() => {
|
|
6367
|
+
if (pendingToolRequests.length === 0) return;
|
|
6368
|
+
const configuredAutoApproveTools = Array.isArray(autoApproveTools) ? new Set(
|
|
6369
|
+
autoApproveTools.map((toolName) => normalizeToolName(String(toolName))).filter(Boolean)
|
|
6370
|
+
) : null;
|
|
6371
|
+
const toAuto = pendingToolRequests.filter(
|
|
6372
|
+
(r) => {
|
|
6373
|
+
const normalized = normalizeToolName(r.toolName);
|
|
6374
|
+
if (!normalized) return false;
|
|
6375
|
+
if (autoApproveTools === true) return true;
|
|
6376
|
+
if (configuredAutoApproveTools == null ? void 0 : configuredAutoApproveTools.has(normalized)) return true;
|
|
6377
|
+
return sessionApprovedTools.includes(normalized) || alwaysApprovedTools.includes(normalized);
|
|
6378
|
+
}
|
|
6379
|
+
);
|
|
6380
|
+
if (toAuto.length > 0) {
|
|
6381
|
+
void processGivenToolRequests(toAuto);
|
|
6382
|
+
setPendingToolRequests(
|
|
6383
|
+
(prev) => prev.filter(
|
|
6384
|
+
(r) => {
|
|
6385
|
+
const normalized = normalizeToolName(r.toolName);
|
|
6386
|
+
if (!normalized) return true;
|
|
6387
|
+
if (autoApproveTools === true) return false;
|
|
6388
|
+
if (configuredAutoApproveTools == null ? void 0 : configuredAutoApproveTools.has(normalized)) return false;
|
|
6389
|
+
return !sessionApprovedTools.includes(normalized) && !alwaysApprovedTools.includes(normalized);
|
|
6390
|
+
}
|
|
6391
|
+
)
|
|
6392
|
+
);
|
|
6393
|
+
}
|
|
6394
|
+
}, [
|
|
6395
|
+
autoApproveTools,
|
|
6396
|
+
pendingToolRequests,
|
|
6397
|
+
sessionApprovedTools,
|
|
6398
|
+
alwaysApprovedTools,
|
|
6399
|
+
processGivenToolRequests,
|
|
6400
|
+
normalizeToolName
|
|
6401
|
+
]);
|
|
4583
6402
|
const cleanContentForDisplay = (0, import_react14.useCallback)((content) => {
|
|
4584
6403
|
let cleaned = content.replace(/\*\*(.*?)\*\*/g, "$1").replace(/\*(.*?)\*/g, "$1").replace(/\n+/g, " ").replace(/\s+/g, " ").trim();
|
|
4585
6404
|
if (cleaned.length > 100) {
|
|
@@ -4588,7 +6407,6 @@ var AIChatPanel = ({
|
|
|
4588
6407
|
return cleaned || "Thinking";
|
|
4589
6408
|
}, []);
|
|
4590
6409
|
const processThinkingTags = (0, import_react14.useCallback)((text) => {
|
|
4591
|
-
var _a2, _b, _c;
|
|
4592
6410
|
if (!text) {
|
|
4593
6411
|
return {
|
|
4594
6412
|
cleanedText: "",
|
|
@@ -4598,30 +6416,28 @@ var AIChatPanel = ({
|
|
|
4598
6416
|
};
|
|
4599
6417
|
}
|
|
4600
6418
|
const processedText = text.replace(/\u200B/g, "");
|
|
4601
|
-
const
|
|
4602
|
-
const
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
allMatches.push({ content, index: match.index, type: "searching" });
|
|
6419
|
+
const completedBlocks = [];
|
|
6420
|
+
const textWithCompleteMarkers = processedText.replace(
|
|
6421
|
+
/<(thinking|reasoning|searching)>([\s\S]*?)<\/\1>/gi,
|
|
6422
|
+
(_fullMatch, rawType, rawContent, offset) => {
|
|
6423
|
+
const normalizedType = String(rawType || "").trim().toLowerCase();
|
|
6424
|
+
const type = normalizedType === "reasoning" ? "reasoning" : normalizedType === "searching" ? "searching" : "thinking";
|
|
6425
|
+
const content = String(rawContent || "").trim();
|
|
6426
|
+
if (!content) return "\n\n";
|
|
6427
|
+
const signature = getThinkingBlockSignature(type, content);
|
|
6428
|
+
completedBlocks.push({
|
|
6429
|
+
type,
|
|
6430
|
+
content,
|
|
6431
|
+
index: Number(offset || 0),
|
|
6432
|
+
signature
|
|
6433
|
+
});
|
|
6434
|
+
return `
|
|
6435
|
+
|
|
6436
|
+
${buildThinkingBlockMarker(type, signature)}
|
|
6437
|
+
|
|
6438
|
+
`;
|
|
4622
6439
|
}
|
|
4623
|
-
|
|
4624
|
-
const completedBlocks = allMatches.sort((a, b) => a.index - b.index);
|
|
6440
|
+
);
|
|
4625
6441
|
let activeBlock = null;
|
|
4626
6442
|
const tagTypes = ["thinking", "reasoning", "searching"];
|
|
4627
6443
|
let latestIncompletePos = -1;
|
|
@@ -4651,7 +6467,7 @@ var AIChatPanel = ({
|
|
|
4651
6467
|
}
|
|
4652
6468
|
}
|
|
4653
6469
|
}
|
|
4654
|
-
let cleanedText =
|
|
6470
|
+
let cleanedText = textWithCompleteMarkers.replace(/<think(?:i(?:n(?:g)?)?)?$/i, "").replace(/<reas(?:o(?:n(?:i(?:n(?:g)?)?)?)?)?$/i, "").replace(/<sear(?:c(?:h(?:i(?:n(?:g)?)?)?)?)?$/i, "").replace(/<thinking>[\s\S]*$/i, "").replace(/<reasoning>[\s\S]*$/i, "").replace(/<searching>[\s\S]*$/i, "").trim();
|
|
4655
6471
|
let lastThinkingContent = "Thinking";
|
|
4656
6472
|
if (completedBlocks.length > 0) {
|
|
4657
6473
|
const lastBlock = completedBlocks[completedBlocks.length - 1];
|
|
@@ -4663,15 +6479,67 @@ var AIChatPanel = ({
|
|
|
4663
6479
|
}
|
|
4664
6480
|
return { cleanedText, completedBlocks, activeBlock, lastThinkingContent };
|
|
4665
6481
|
}, [cleanContentForDisplay]);
|
|
6482
|
+
const mergeThinkingBlocks = (0, import_react14.useCallback)(
|
|
6483
|
+
(existing, incoming) => {
|
|
6484
|
+
if (incoming.length === 0) return existing;
|
|
6485
|
+
if (existing.length === 0) return incoming;
|
|
6486
|
+
const incomingSupersetPrefix = incoming.length >= existing.length && existing.every((block, index) => {
|
|
6487
|
+
const next = incoming[index];
|
|
6488
|
+
return !!next && next.type === block.type && next.content === block.content;
|
|
6489
|
+
});
|
|
6490
|
+
if (incomingSupersetPrefix) {
|
|
6491
|
+
return incoming;
|
|
6492
|
+
}
|
|
6493
|
+
const merged = [...existing];
|
|
6494
|
+
const seen = new Set(existing.map((block) => block.signature || `${block.type}::${block.content}`));
|
|
6495
|
+
for (const block of incoming) {
|
|
6496
|
+
const signature = block.signature || `${block.type}::${block.content}`;
|
|
6497
|
+
if (seen.has(signature)) continue;
|
|
6498
|
+
seen.add(signature);
|
|
6499
|
+
merged.push(block);
|
|
6500
|
+
}
|
|
6501
|
+
return merged;
|
|
6502
|
+
},
|
|
6503
|
+
[]
|
|
6504
|
+
);
|
|
6505
|
+
const getThinkingBlockCollapseKey = (0, import_react14.useCallback)((entryKey, blockKey) => {
|
|
6506
|
+
return `${entryKey}::${blockKey}`;
|
|
6507
|
+
}, []);
|
|
6508
|
+
const getThinkingBlockRenderKey = (0, import_react14.useCallback)((block, fallbackIndex) => {
|
|
6509
|
+
return String((block == null ? void 0 : block.signature) || "").trim() || `block-${fallbackIndex}`;
|
|
6510
|
+
}, []);
|
|
6511
|
+
const AGENT_SUGGESTION_ACTION = {
|
|
6512
|
+
pattern: "\\[SUGGEST_AGENT:([^|\\]]+)\\|([^|\\]]+)\\|([^\\]]+)\\]",
|
|
6513
|
+
markdown: '<agent-suggestion data-agent-id="$1" data-agent-name="$2" data-reason="$3"></agent-suggestion>'
|
|
6514
|
+
};
|
|
6515
|
+
const extractToolRequests = (0, import_react14.useCallback)((rawResponse) => {
|
|
6516
|
+
return extractToolRequestMatchesFromText(rawResponse);
|
|
6517
|
+
}, []);
|
|
6518
|
+
const formatToolRequestsForDisplay = (0, import_react14.useCallback)((rawResponse) => {
|
|
6519
|
+
if (!rawResponse) return rawResponse;
|
|
6520
|
+
const requests = extractToolRequestMatchesFromText(rawResponse);
|
|
6521
|
+
if (requests.length === 0) return stripStandaloneRawToolJsonLines(rawResponse);
|
|
6522
|
+
const output = [];
|
|
6523
|
+
let cursor = 0;
|
|
6524
|
+
requests.forEach((request) => {
|
|
6525
|
+
const start = Math.max(0, Math.min(rawResponse.length, request.start));
|
|
6526
|
+
const end = Math.max(start, Math.min(rawResponse.length, request.end));
|
|
6527
|
+
output.push(rawResponse.slice(cursor, start));
|
|
6528
|
+
output.push(`
|
|
6529
|
+
|
|
6530
|
+
${buildInlineToolMarker(request.toolName, request.callId)}
|
|
6531
|
+
|
|
6532
|
+
`);
|
|
6533
|
+
cursor = end;
|
|
6534
|
+
});
|
|
6535
|
+
output.push(rawResponse.slice(cursor));
|
|
6536
|
+
return stripStandaloneRawToolJsonLines(output.join(""));
|
|
6537
|
+
}, []);
|
|
4666
6538
|
const activeThinkingBlock = (0, import_react14.useMemo)(() => {
|
|
4667
6539
|
if (!response || justReset) return null;
|
|
4668
6540
|
const { activeBlock } = processThinkingTags(response);
|
|
4669
6541
|
return activeBlock;
|
|
4670
6542
|
}, [response, justReset, processThinkingTags]);
|
|
4671
|
-
const AGENT_SUGGESTION_ACTION = {
|
|
4672
|
-
pattern: "\\[SUGGEST_AGENT:([^|\\]]+)\\|([^|\\]]+)\\|([^\\]]+)\\]",
|
|
4673
|
-
markdown: '<agent-suggestion data-agent-id="$1" data-agent-name="$2" data-reason="$3"></agent-suggestion>'
|
|
4674
|
-
};
|
|
4675
6543
|
const processActions = (0, import_react14.useCallback)((content) => {
|
|
4676
6544
|
const allActions = [AGENT_SUGGESTION_ACTION, ...actions || []];
|
|
4677
6545
|
let processed = content;
|
|
@@ -4705,6 +6573,38 @@ var AIChatPanel = ({
|
|
|
4705
6573
|
}
|
|
4706
6574
|
return displayPrompt;
|
|
4707
6575
|
}, [hideRagContextInPrompt]);
|
|
6576
|
+
const normalizeHistoryPromptForContext = (0, import_react14.useCallback)((historyPrompt) => {
|
|
6577
|
+
let promptForHistory = String(historyPrompt || "");
|
|
6578
|
+
const isoTimestampRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z:/;
|
|
6579
|
+
if (isoTimestampRegex.test(promptForHistory)) {
|
|
6580
|
+
const colonIndex = promptForHistory.indexOf(":", 19);
|
|
6581
|
+
promptForHistory = promptForHistory.substring(colonIndex + 1);
|
|
6582
|
+
} else if (/^\d+:/.test(promptForHistory)) {
|
|
6583
|
+
const colonIndex = promptForHistory.indexOf(":");
|
|
6584
|
+
promptForHistory = promptForHistory.substring(colonIndex + 1);
|
|
6585
|
+
}
|
|
6586
|
+
return promptForHistory;
|
|
6587
|
+
}, []);
|
|
6588
|
+
const buildAssistantContextContent = (0, import_react14.useCallback)(
|
|
6589
|
+
(historyPrompt, historyEntry) => {
|
|
6590
|
+
const assistantBaseContent = typeof (historyEntry == null ? void 0 : historyEntry.content) === "string" ? historyEntry.content : "";
|
|
6591
|
+
if (traceContextMode !== "full") {
|
|
6592
|
+
return assistantBaseContent;
|
|
6593
|
+
}
|
|
6594
|
+
const traceSummary = buildCompactTraceSummary({
|
|
6595
|
+
reasoningBlocks: thinkingBlocksByKeyRef.current[historyPrompt] || [],
|
|
6596
|
+
toolCalls: historyEntry == null ? void 0 : historyEntry.toolCalls,
|
|
6597
|
+
toolResponses: historyEntry == null ? void 0 : historyEntry.toolResponses
|
|
6598
|
+
});
|
|
6599
|
+
if (!traceSummary) {
|
|
6600
|
+
return assistantBaseContent;
|
|
6601
|
+
}
|
|
6602
|
+
return assistantBaseContent ? `${assistantBaseContent}
|
|
6603
|
+
|
|
6604
|
+
${traceSummary}` : traceSummary;
|
|
6605
|
+
},
|
|
6606
|
+
[traceContextMode]
|
|
6607
|
+
);
|
|
4708
6608
|
const interactionClicked = (0, import_react14.useCallback)((callId, action, emailaddress = "", comment = "") => __async(void 0, null, function* () {
|
|
4709
6609
|
var _a2, _b;
|
|
4710
6610
|
console.log(`[AIChatPanel] Interaction: ${action} for callId: ${callId}`);
|
|
@@ -4787,9 +6687,24 @@ var AIChatPanel = ({
|
|
|
4787
6687
|
lastScrollTimeRef.current = now;
|
|
4788
6688
|
}, []);
|
|
4789
6689
|
const continueChat = (0, import_react14.useCallback)((promptText) => {
|
|
6690
|
+
handledToolCallSignaturesRef.current = /* @__PURE__ */ new Set();
|
|
6691
|
+
inFlightToolCallSignaturesRef.current = /* @__PURE__ */ new Set();
|
|
6692
|
+
toolContinuationCountRef.current = 0;
|
|
6693
|
+
activeStreamAppendBaseRef.current = null;
|
|
6694
|
+
toolReplaySummariesByKeyRef.current = {};
|
|
6695
|
+
setPendingToolRequests([]);
|
|
6696
|
+
setActiveToolCalls([]);
|
|
6697
|
+
setCollapsedBlocks((prev) => {
|
|
6698
|
+
const next = new Set(prev);
|
|
6699
|
+
Object.entries(thinkingBlocksByKeyRef.current).forEach(([entryKey, blocks]) => {
|
|
6700
|
+
blocks.forEach((block, index) => {
|
|
6701
|
+
next.add(getThinkingBlockCollapseKey(entryKey, getThinkingBlockRenderKey(block, index)));
|
|
6702
|
+
});
|
|
6703
|
+
});
|
|
6704
|
+
return next;
|
|
6705
|
+
});
|
|
4790
6706
|
setThinkingBlocks([]);
|
|
4791
6707
|
setCurrentThinkingIndex(0);
|
|
4792
|
-
setCollapsedBlocks(/* @__PURE__ */ new Set());
|
|
4793
6708
|
hasAutoCollapsedRef.current = false;
|
|
4794
6709
|
prevBlockCountRef.current = 0;
|
|
4795
6710
|
setError(null);
|
|
@@ -4818,6 +6733,7 @@ var AIChatPanel = ({
|
|
|
4818
6733
|
setHistory((prevHistory) => __spreadProps(__spreadValues({}, prevHistory), {
|
|
4819
6734
|
[promptKey]: { content: "", callId: "" }
|
|
4820
6735
|
}));
|
|
6736
|
+
toolReplaySummariesByKeyRef.current[promptKey] = [];
|
|
4821
6737
|
setLastPrompt(promptToSend.trim());
|
|
4822
6738
|
setLastKey(promptKey);
|
|
4823
6739
|
setTimeout(() => {
|
|
@@ -4826,20 +6742,14 @@ var AIChatPanel = ({
|
|
|
4826
6742
|
console.log("AIChatPanel.continueChat - about to call ensureConversation");
|
|
4827
6743
|
ensureConversation().then((convId) => {
|
|
4828
6744
|
console.log("AIChatPanel.continueChat - ensureConversation resolved with:", convId);
|
|
6745
|
+
const historyForCall = latestHistoryRef.current || {};
|
|
4829
6746
|
const messagesAndHistory = [];
|
|
4830
|
-
Object.entries(
|
|
6747
|
+
Object.entries(historyForCall).forEach(([historyPrompt, historyEntry]) => {
|
|
4831
6748
|
if (historyPrompt === promptKey) return;
|
|
4832
|
-
|
|
4833
|
-
const
|
|
4834
|
-
if (isoTimestampRegex.test(historyPrompt)) {
|
|
4835
|
-
const colonIndex = historyPrompt.indexOf(":", 19);
|
|
4836
|
-
promptForHistory = historyPrompt.substring(colonIndex + 1);
|
|
4837
|
-
} else if (/^\d+:/.test(historyPrompt)) {
|
|
4838
|
-
const colonIndex = historyPrompt.indexOf(":");
|
|
4839
|
-
promptForHistory = historyPrompt.substring(colonIndex + 1);
|
|
4840
|
-
}
|
|
6749
|
+
const promptForHistory = normalizeHistoryPromptForContext(historyPrompt);
|
|
6750
|
+
const assistantContextContent = buildAssistantContextContent(historyPrompt, historyEntry);
|
|
4841
6751
|
messagesAndHistory.push({ role: "user", content: promptForHistory });
|
|
4842
|
-
messagesAndHistory.push({ role: "assistant", content:
|
|
6752
|
+
messagesAndHistory.push({ role: "assistant", content: assistantContextContent });
|
|
4843
6753
|
});
|
|
4844
6754
|
let fullPromptToSend = promptToSend.trim();
|
|
4845
6755
|
if (messagesAndHistory.length === 0 && promptTemplate) {
|
|
@@ -4847,6 +6757,19 @@ var AIChatPanel = ({
|
|
|
4847
6757
|
}
|
|
4848
6758
|
const newController = new AbortController();
|
|
4849
6759
|
setLastController(newController);
|
|
6760
|
+
if (onBeforeSend) {
|
|
6761
|
+
void Promise.resolve(
|
|
6762
|
+
onBeforeSend({
|
|
6763
|
+
prompt: promptToSend.trim(),
|
|
6764
|
+
conversationId: convId || null,
|
|
6765
|
+
agentId: agent,
|
|
6766
|
+
service,
|
|
6767
|
+
messages: messagesAndHistory
|
|
6768
|
+
})
|
|
6769
|
+
).catch((error2) => {
|
|
6770
|
+
console.warn("[AIChatPanel] onBeforeSend callback failed:", error2);
|
|
6771
|
+
});
|
|
6772
|
+
}
|
|
4850
6773
|
send(
|
|
4851
6774
|
fullPromptToSend,
|
|
4852
6775
|
messagesAndHistory,
|
|
@@ -4869,14 +6792,21 @@ var AIChatPanel = ({
|
|
|
4869
6792
|
console.log("[AIChatPanel] Error callback triggered:", errorMsg);
|
|
4870
6793
|
const isAbortError = errorMsg.toLowerCase().includes("abort") || errorMsg.toLowerCase().includes("canceled") || errorMsg.toLowerCase().includes("cancelled");
|
|
4871
6794
|
if (isAbortError) {
|
|
6795
|
+
if (suppressAbortHistoryUpdateRef.current) {
|
|
6796
|
+
setIsLoading(false);
|
|
6797
|
+
return;
|
|
6798
|
+
}
|
|
4872
6799
|
console.log("[AIChatPanel] Request was aborted by user");
|
|
4873
6800
|
if (promptKey) {
|
|
4874
|
-
setHistory((prev) =>
|
|
4875
|
-
[promptKey]:
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
6801
|
+
setHistory((prev) => {
|
|
6802
|
+
const existingEntry = prev[promptKey] || { content: "", callId: "" };
|
|
6803
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
6804
|
+
[promptKey]: __spreadProps(__spreadValues({}, existingEntry), {
|
|
6805
|
+
content: "Response canceled",
|
|
6806
|
+
callId: lastCallId || existingEntry.callId || ""
|
|
6807
|
+
})
|
|
6808
|
+
});
|
|
6809
|
+
});
|
|
4880
6810
|
}
|
|
4881
6811
|
} else if (errorMsg.includes("413") || errorMsg.toLowerCase().includes("content too large")) {
|
|
4882
6812
|
setError({
|
|
@@ -4884,12 +6814,15 @@ var AIChatPanel = ({
|
|
|
4884
6814
|
code: "413"
|
|
4885
6815
|
});
|
|
4886
6816
|
if (promptKey) {
|
|
4887
|
-
setHistory((prev) =>
|
|
4888
|
-
[promptKey]:
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
6817
|
+
setHistory((prev) => {
|
|
6818
|
+
const existingEntry = prev[promptKey] || { content: "", callId: "" };
|
|
6819
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
6820
|
+
[promptKey]: __spreadProps(__spreadValues({}, existingEntry), {
|
|
6821
|
+
content: `Error: ${errorMsg}`,
|
|
6822
|
+
callId: lastCallId || existingEntry.callId || ""
|
|
6823
|
+
})
|
|
6824
|
+
});
|
|
6825
|
+
});
|
|
4893
6826
|
}
|
|
4894
6827
|
} else if (errorMsg.toLowerCase().includes("network error") || errorMsg.toLowerCase().includes("fetch")) {
|
|
4895
6828
|
setError({
|
|
@@ -4897,12 +6830,15 @@ var AIChatPanel = ({
|
|
|
4897
6830
|
code: "NETWORK_ERROR"
|
|
4898
6831
|
});
|
|
4899
6832
|
if (promptKey) {
|
|
4900
|
-
setHistory((prev) =>
|
|
4901
|
-
[promptKey]:
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
6833
|
+
setHistory((prev) => {
|
|
6834
|
+
const existingEntry = prev[promptKey] || { content: "", callId: "" };
|
|
6835
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
6836
|
+
[promptKey]: __spreadProps(__spreadValues({}, existingEntry), {
|
|
6837
|
+
content: `Error: ${errorMsg}`,
|
|
6838
|
+
callId: lastCallId || existingEntry.callId || ""
|
|
6839
|
+
})
|
|
6840
|
+
});
|
|
6841
|
+
});
|
|
4906
6842
|
}
|
|
4907
6843
|
} else {
|
|
4908
6844
|
setError({
|
|
@@ -4910,12 +6846,15 @@ var AIChatPanel = ({
|
|
|
4910
6846
|
code: "UNKNOWN_ERROR"
|
|
4911
6847
|
});
|
|
4912
6848
|
if (promptKey) {
|
|
4913
|
-
setHistory((prev) =>
|
|
4914
|
-
[promptKey]:
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
6849
|
+
setHistory((prev) => {
|
|
6850
|
+
const existingEntry = prev[promptKey] || { content: "", callId: "" };
|
|
6851
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
6852
|
+
[promptKey]: __spreadProps(__spreadValues({}, existingEntry), {
|
|
6853
|
+
content: `Error: ${errorMsg}`,
|
|
6854
|
+
callId: lastCallId || existingEntry.callId || ""
|
|
6855
|
+
})
|
|
6856
|
+
});
|
|
6857
|
+
});
|
|
4919
6858
|
}
|
|
4920
6859
|
}
|
|
4921
6860
|
setIsLoading(false);
|
|
@@ -4937,14 +6876,20 @@ var AIChatPanel = ({
|
|
|
4937
6876
|
lastCallId,
|
|
4938
6877
|
processThinkingTags,
|
|
4939
6878
|
clearFollowOnQuestionsNextPrompt,
|
|
4940
|
-
history,
|
|
4941
6879
|
promptTemplate,
|
|
4942
6880
|
send,
|
|
4943
6881
|
service,
|
|
6882
|
+
agent,
|
|
4944
6883
|
ensureConversation,
|
|
6884
|
+
normalizeHistoryPromptForContext,
|
|
6885
|
+
buildAssistantContextContent,
|
|
6886
|
+
traceContextMode,
|
|
4945
6887
|
dataWithExtras,
|
|
4946
6888
|
scrollToBottom,
|
|
4947
6889
|
onConversationCreated,
|
|
6890
|
+
onBeforeSend,
|
|
6891
|
+
getThinkingBlockCollapseKey,
|
|
6892
|
+
getThinkingBlockRenderKey,
|
|
4948
6893
|
setResponse
|
|
4949
6894
|
]);
|
|
4950
6895
|
const handleSuggestionClick = (0, import_react14.useCallback)((question) => {
|
|
@@ -4972,6 +6917,14 @@ var AIChatPanel = ({
|
|
|
4972
6917
|
setLastKey(null);
|
|
4973
6918
|
setIsLoading(false);
|
|
4974
6919
|
setCurrentConversation(null);
|
|
6920
|
+
thinkingBlocksByKeyRef.current = {};
|
|
6921
|
+
setThinkingBlocksByKey({});
|
|
6922
|
+
handledToolCallSignaturesRef.current = /* @__PURE__ */ new Set();
|
|
6923
|
+
inFlightToolCallSignaturesRef.current = /* @__PURE__ */ new Set();
|
|
6924
|
+
toolContinuationCountRef.current = 0;
|
|
6925
|
+
activeStreamAppendBaseRef.current = null;
|
|
6926
|
+
toolReplaySummariesByKeyRef.current = {};
|
|
6927
|
+
setPendingToolRequests([]);
|
|
4975
6928
|
setFollowOnQuestionsState(followOnQuestions);
|
|
4976
6929
|
setThinkingBlocks([]);
|
|
4977
6930
|
setCurrentThinkingIndex(0);
|
|
@@ -4982,6 +6935,7 @@ var AIChatPanel = ({
|
|
|
4982
6935
|
setLastController(new AbortController());
|
|
4983
6936
|
setUserHasScrolled(false);
|
|
4984
6937
|
setError(null);
|
|
6938
|
+
setActiveToolCalls([]);
|
|
4985
6939
|
setTimeout(() => {
|
|
4986
6940
|
var _a2;
|
|
4987
6941
|
setJustReset(false);
|
|
@@ -4990,43 +6944,85 @@ var AIChatPanel = ({
|
|
|
4990
6944
|
}, [newConversationConfirm, idle, stop, lastController, setResponse, followOnQuestions]);
|
|
4991
6945
|
(0, import_react14.useEffect)(() => {
|
|
4992
6946
|
if (!response || !lastKey || justReset) return;
|
|
4993
|
-
const
|
|
4994
|
-
|
|
4995
|
-
|
|
6947
|
+
const extractedToolRequests = extractToolRequests(response);
|
|
6948
|
+
const seenToolCallSignatures = /* @__PURE__ */ new Set();
|
|
6949
|
+
const unseenToolRequests = extractedToolRequests.filter((request) => {
|
|
6950
|
+
const callSignature = getToolCallSignature(request.toolName, request.callId);
|
|
6951
|
+
if (!callSignature) return false;
|
|
6952
|
+
if (seenToolCallSignatures.has(callSignature)) return false;
|
|
6953
|
+
seenToolCallSignatures.add(callSignature);
|
|
6954
|
+
if (handledToolCallSignaturesRef.current.has(callSignature)) return false;
|
|
6955
|
+
if (inFlightToolCallSignaturesRef.current.has(callSignature)) return false;
|
|
6956
|
+
return true;
|
|
6957
|
+
});
|
|
6958
|
+
setPendingToolRequests((prev) => {
|
|
6959
|
+
if (areToolRequestListsEqual(prev, unseenToolRequests)) {
|
|
6960
|
+
return prev;
|
|
6961
|
+
}
|
|
6962
|
+
return unseenToolRequests;
|
|
6963
|
+
});
|
|
6964
|
+
const responseWithInlineToolLabels = formatToolRequestsForDisplay(response);
|
|
6965
|
+
const { cleanedText: parsedCleanedText, completedBlocks } = processThinkingTags(responseWithInlineToolLabels);
|
|
6966
|
+
const cleanedText = parsedCleanedText.trim();
|
|
6967
|
+
const existingBlocks = thinkingBlocksByKeyRef.current[lastKey] || [];
|
|
6968
|
+
const mergedBlocks = mergeThinkingBlocks(existingBlocks, completedBlocks);
|
|
6969
|
+
thinkingBlocksByKeyRef.current[lastKey] = mergedBlocks;
|
|
6970
|
+
setThinkingBlocksByKey((prev) => {
|
|
6971
|
+
const existing = prev[lastKey];
|
|
6972
|
+
const isSame = !!existing && existing.length === mergedBlocks.length && existing.every(
|
|
6973
|
+
(block, index) => {
|
|
6974
|
+
var _a2, _b;
|
|
6975
|
+
return block.type === ((_a2 = mergedBlocks[index]) == null ? void 0 : _a2.type) && block.content === ((_b = mergedBlocks[index]) == null ? void 0 : _b.content);
|
|
6976
|
+
}
|
|
6977
|
+
);
|
|
6978
|
+
if (isSame) return prev;
|
|
6979
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
6980
|
+
[lastKey]: mergedBlocks
|
|
6981
|
+
});
|
|
6982
|
+
});
|
|
6983
|
+
setThinkingBlocks(mergedBlocks);
|
|
6984
|
+
setCurrentThinkingIndex(Math.max(0, mergedBlocks.length - 1));
|
|
6985
|
+
if (mergedBlocks.length > prevBlockCountRef.current) {
|
|
4996
6986
|
setCollapsedBlocks((prev) => {
|
|
4997
6987
|
const next = new Set(prev);
|
|
4998
|
-
for (let i = 0; i <
|
|
4999
|
-
|
|
6988
|
+
for (let i = 0; i < mergedBlocks.length - 1; i++) {
|
|
6989
|
+
const block = mergedBlocks[i];
|
|
6990
|
+
if (!block) continue;
|
|
6991
|
+
next.add(getThinkingBlockCollapseKey(lastKey, getThinkingBlockRenderKey(block, i)));
|
|
5000
6992
|
}
|
|
5001
6993
|
return next;
|
|
5002
6994
|
});
|
|
5003
|
-
prevBlockCountRef.current =
|
|
5004
|
-
}
|
|
5005
|
-
const hasMainContent = cleanedText.trim().length > 0;
|
|
5006
|
-
const hasThinkingContent = completedBlocks.length > 0 || processThinkingTags(response).activeBlock !== null;
|
|
5007
|
-
if (hasMainContent && hasThinkingContent && !hasAutoCollapsedRef.current) {
|
|
5008
|
-
hasAutoCollapsedRef.current = true;
|
|
5009
|
-
setTimeout(() => {
|
|
5010
|
-
setCollapsedBlocks((prev) => {
|
|
5011
|
-
const next = new Set(prev);
|
|
5012
|
-
completedBlocks.forEach((_, index) => next.add(`block-${index}`));
|
|
5013
|
-
next.add("active");
|
|
5014
|
-
return next;
|
|
5015
|
-
});
|
|
5016
|
-
}, 500);
|
|
6995
|
+
prevBlockCountRef.current = mergedBlocks.length;
|
|
5017
6996
|
}
|
|
5018
6997
|
setHistory((prev) => {
|
|
5019
6998
|
const newHistory = __spreadValues({}, prev);
|
|
5020
|
-
newHistory[lastKey]
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
6999
|
+
const existingEntry = newHistory[lastKey] || { content: "", callId: "" };
|
|
7000
|
+
const appendBase = activeStreamAppendBaseRef.current;
|
|
7001
|
+
const mergedContinuationContent = appendBase && appendBase.key === lastKey ? mergeContinuationResponseText(appendBase.base, cleanedText) : cleanedText;
|
|
7002
|
+
const existingContent = typeof existingEntry.content === "string" ? existingEntry.content : "";
|
|
7003
|
+
const nextContent = appendBase && appendBase.key === lastKey && existingContent.length > mergedContinuationContent.length ? existingContent : shouldPreserveBoundaryDroppedStreamText(existingContent, mergedContinuationContent) ? existingContent : mergedContinuationContent;
|
|
7004
|
+
newHistory[lastKey] = __spreadProps(__spreadValues({}, existingEntry), {
|
|
7005
|
+
content: nextContent,
|
|
7006
|
+
// Store raw content without tool JSON or thinking tags
|
|
7007
|
+
callId: lastCallId || existingEntry.callId || ""
|
|
7008
|
+
});
|
|
5025
7009
|
latestHistoryRef.current = newHistory;
|
|
5026
7010
|
return newHistory;
|
|
5027
7011
|
});
|
|
5028
|
-
}, [
|
|
7012
|
+
}, [
|
|
7013
|
+
response,
|
|
7014
|
+
lastKey,
|
|
7015
|
+
lastCallId,
|
|
7016
|
+
processThinkingTags,
|
|
7017
|
+
justReset,
|
|
7018
|
+
extractToolRequests,
|
|
7019
|
+
getToolCallSignature,
|
|
7020
|
+
getThinkingBlockCollapseKey,
|
|
7021
|
+
getThinkingBlockRenderKey,
|
|
7022
|
+
formatToolRequestsForDisplay
|
|
7023
|
+
]);
|
|
5029
7024
|
(0, import_react14.useEffect)(() => {
|
|
7025
|
+
var _a2;
|
|
5030
7026
|
const wasStreaming = !prevIdleRef.current;
|
|
5031
7027
|
const isNowIdle = idle;
|
|
5032
7028
|
prevIdleRef.current = idle;
|
|
@@ -5050,6 +7046,12 @@ var AIChatPanel = ({
|
|
|
5050
7046
|
if (!isNowIdle && hasNotifiedCompletionRef.current) {
|
|
5051
7047
|
hasNotifiedCompletionRef.current = false;
|
|
5052
7048
|
prevResponseLengthRef.current = 0;
|
|
7049
|
+
const currentLastKey = lastKeyRef.current;
|
|
7050
|
+
const existingContent = currentLastKey ? ((_a2 = latestHistoryRef.current[currentLastKey]) == null ? void 0 : _a2.content) || "" : "";
|
|
7051
|
+
activeStreamAppendBaseRef.current = currentLastKey && existingContent.trim().length > 0 ? {
|
|
7052
|
+
key: currentLastKey,
|
|
7053
|
+
base: existingContent
|
|
7054
|
+
} : null;
|
|
5053
7055
|
}
|
|
5054
7056
|
}, [idle]);
|
|
5055
7057
|
(0, import_react14.useEffect)(() => {
|
|
@@ -5070,21 +7072,19 @@ var AIChatPanel = ({
|
|
|
5070
7072
|
scrollToBottom(true);
|
|
5071
7073
|
}
|
|
5072
7074
|
}, [response, idle]);
|
|
5073
|
-
const idleRef = (0, import_react14.useRef)(idle);
|
|
5074
|
-
idleRef.current = idle;
|
|
5075
7075
|
(0, import_react14.useEffect)(() => {
|
|
5076
7076
|
const scrollArea = responseAreaRef.current;
|
|
5077
7077
|
if (!scrollArea) return;
|
|
5078
7078
|
const scrollViewport = scrollArea.querySelector(".ai-scroll-area-viewport");
|
|
5079
7079
|
const scrollElement = scrollViewport || scrollArea;
|
|
5080
7080
|
const handleWheel = (e) => {
|
|
5081
|
-
if (
|
|
7081
|
+
if (streamIdleRef.current) return;
|
|
5082
7082
|
if (e.deltaY < 0 && !userHasScrolledRef.current) {
|
|
5083
7083
|
setUserHasScrolled(true);
|
|
5084
7084
|
}
|
|
5085
7085
|
};
|
|
5086
7086
|
const handleScroll = () => {
|
|
5087
|
-
if (
|
|
7087
|
+
if (streamIdleRef.current || !userHasScrolledRef.current) return;
|
|
5088
7088
|
const scrollHeight = scrollElement.scrollHeight;
|
|
5089
7089
|
const currentScrollTop = scrollElement.scrollTop;
|
|
5090
7090
|
const clientHeight = scrollElement.clientHeight;
|
|
@@ -5101,7 +7101,12 @@ var AIChatPanel = ({
|
|
|
5101
7101
|
};
|
|
5102
7102
|
}, []);
|
|
5103
7103
|
(0, import_react14.useEffect)(() => {
|
|
5104
|
-
setFollowOnQuestionsState(
|
|
7104
|
+
setFollowOnQuestionsState((prev) => {
|
|
7105
|
+
if (prev.length === followOnQuestions.length && prev.every((question, index) => question === followOnQuestions[index])) {
|
|
7106
|
+
return prev;
|
|
7107
|
+
}
|
|
7108
|
+
return followOnQuestions;
|
|
7109
|
+
});
|
|
5105
7110
|
}, [followOnQuestions]);
|
|
5106
7111
|
(0, import_react14.useEffect)(() => {
|
|
5107
7112
|
const currentlyLoading = isLoading || !idle;
|
|
@@ -5119,10 +7124,11 @@ var AIChatPanel = ({
|
|
|
5119
7124
|
const currentLastKey = lastKeyRef.current;
|
|
5120
7125
|
const currentLastCallId = lastCallIdRef.current;
|
|
5121
7126
|
if (currentLastKey && currentResponse) {
|
|
5122
|
-
currentHistory[currentLastKey]
|
|
7127
|
+
const existingEntry = currentHistory[currentLastKey] || { content: "", callId: "" };
|
|
7128
|
+
currentHistory[currentLastKey] = __spreadProps(__spreadValues({}, existingEntry), {
|
|
5123
7129
|
content: currentResponse + "\n\n(response interrupted)",
|
|
5124
|
-
callId: currentLastCallId || ""
|
|
5125
|
-
};
|
|
7130
|
+
callId: currentLastCallId || existingEntry.callId || ""
|
|
7131
|
+
});
|
|
5126
7132
|
}
|
|
5127
7133
|
if (historyCallbackRef.current && Object.keys(currentHistory).length > 0 && !hasNotifiedCompletionRef.current) {
|
|
5128
7134
|
historyCallbackRef.current(currentHistory);
|
|
@@ -5159,12 +7165,15 @@ var AIChatPanel = ({
|
|
|
5159
7165
|
code: "413"
|
|
5160
7166
|
});
|
|
5161
7167
|
if (lastKey) {
|
|
5162
|
-
setHistory((prev) =>
|
|
5163
|
-
[lastKey]:
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
7168
|
+
setHistory((prev) => {
|
|
7169
|
+
const existingEntry = prev[lastKey] || { content: "", callId: "" };
|
|
7170
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
7171
|
+
[lastKey]: __spreadProps(__spreadValues({}, existingEntry), {
|
|
7172
|
+
content: `Error: ${errorMessage}`,
|
|
7173
|
+
callId: lastCallId || existingEntry.callId || ""
|
|
7174
|
+
})
|
|
7175
|
+
});
|
|
7176
|
+
});
|
|
5168
7177
|
}
|
|
5169
7178
|
} else if (errorMessage.toLowerCase().includes("network error") || errorMessage.toLowerCase().includes("fetch")) {
|
|
5170
7179
|
setError({
|
|
@@ -5172,12 +7181,15 @@ var AIChatPanel = ({
|
|
|
5172
7181
|
code: "NETWORK_ERROR"
|
|
5173
7182
|
});
|
|
5174
7183
|
if (lastKey) {
|
|
5175
|
-
setHistory((prev) =>
|
|
5176
|
-
[lastKey]:
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
7184
|
+
setHistory((prev) => {
|
|
7185
|
+
const existingEntry = prev[lastKey] || { content: "", callId: "" };
|
|
7186
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
7187
|
+
[lastKey]: __spreadProps(__spreadValues({}, existingEntry), {
|
|
7188
|
+
content: `Error: ${errorMessage}`,
|
|
7189
|
+
callId: lastCallId || existingEntry.callId || ""
|
|
7190
|
+
})
|
|
7191
|
+
});
|
|
7192
|
+
});
|
|
5181
7193
|
}
|
|
5182
7194
|
} else {
|
|
5183
7195
|
setError({
|
|
@@ -5185,12 +7197,15 @@ var AIChatPanel = ({
|
|
|
5185
7197
|
code: "UNKNOWN_ERROR"
|
|
5186
7198
|
});
|
|
5187
7199
|
if (lastKey) {
|
|
5188
|
-
setHistory((prev) =>
|
|
5189
|
-
[lastKey]:
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
7200
|
+
setHistory((prev) => {
|
|
7201
|
+
const existingEntry = prev[lastKey] || { content: "", callId: "" };
|
|
7202
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
7203
|
+
[lastKey]: __spreadProps(__spreadValues({}, existingEntry), {
|
|
7204
|
+
content: `Error: ${errorMessage}`,
|
|
7205
|
+
callId: lastCallId || existingEntry.callId || ""
|
|
7206
|
+
})
|
|
7207
|
+
});
|
|
7208
|
+
});
|
|
5194
7209
|
}
|
|
5195
7210
|
}
|
|
5196
7211
|
setIsLoading(false);
|
|
@@ -5321,47 +7336,220 @@ var AIChatPanel = ({
|
|
|
5321
7336
|
);
|
|
5322
7337
|
}
|
|
5323
7338
|
}), [CodeBlock, AgentSuggestionCard]);
|
|
5324
|
-
const
|
|
5325
|
-
const
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
7339
|
+
const toggleThinkingBlockCollapsed = (0, import_react14.useCallback)((entryKey, blockKey) => {
|
|
7340
|
+
const collapseKey = getThinkingBlockCollapseKey(entryKey, blockKey);
|
|
7341
|
+
setCollapsedBlocks((prev) => {
|
|
7342
|
+
const next = new Set(prev);
|
|
7343
|
+
if (next.has(collapseKey)) {
|
|
7344
|
+
next.delete(collapseKey);
|
|
7345
|
+
} else {
|
|
7346
|
+
next.add(collapseKey);
|
|
7347
|
+
}
|
|
7348
|
+
return next;
|
|
7349
|
+
});
|
|
7350
|
+
}, [getThinkingBlockCollapseKey]);
|
|
7351
|
+
const renderThinkingBlockCard = (entryKey, block, blockKey, renderKey, isStreaming) => {
|
|
7352
|
+
const collapseKey = getThinkingBlockCollapseKey(entryKey, blockKey);
|
|
7353
|
+
return /* @__PURE__ */ import_react14.default.createElement(
|
|
7354
|
+
ThinkingBlock,
|
|
7355
|
+
{
|
|
7356
|
+
key: renderKey,
|
|
7357
|
+
type: block.type,
|
|
7358
|
+
content: block.content,
|
|
7359
|
+
isStreaming,
|
|
7360
|
+
isCollapsed: collapsedBlocks.has(collapseKey),
|
|
7361
|
+
onToggleCollapse: () => toggleThinkingBlockCollapsed(entryKey, blockKey)
|
|
7362
|
+
}
|
|
7363
|
+
);
|
|
7364
|
+
};
|
|
7365
|
+
const renderActiveThinkingBlock = (entryKey, activeBlock, keyPrefix) => {
|
|
7366
|
+
if (!activeBlock) return null;
|
|
7367
|
+
return /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-inline-thinking-events" }, renderThinkingBlockCard(entryKey, activeBlock, "active", `${keyPrefix}-active`, true));
|
|
7368
|
+
};
|
|
7369
|
+
const panelClasses = ["ai-chat-panel", theme === "dark" ? "dark-theme" : ""].filter(Boolean).join(" ");
|
|
7370
|
+
const getToolStatusRank = (status) => {
|
|
7371
|
+
switch (status) {
|
|
7372
|
+
case "error":
|
|
7373
|
+
return 4;
|
|
7374
|
+
case "completed":
|
|
7375
|
+
return 3;
|
|
7376
|
+
case "running":
|
|
7377
|
+
return 2;
|
|
7378
|
+
case "pending":
|
|
7379
|
+
default:
|
|
7380
|
+
return 1;
|
|
7381
|
+
}
|
|
7382
|
+
};
|
|
7383
|
+
const formatToolCallId = (callId) => {
|
|
7384
|
+
const normalized = String(callId || "").trim();
|
|
7385
|
+
if (normalized.length <= 22) return normalized;
|
|
7386
|
+
return `${normalized.slice(0, 10)}...${normalized.slice(-8)}`;
|
|
7387
|
+
};
|
|
7388
|
+
const renderMarkdownContent = (content, key) => {
|
|
7389
|
+
if (!content || !content.trim()) return null;
|
|
7390
|
+
if (markdownClass) {
|
|
7391
|
+
return /* @__PURE__ */ import_react14.default.createElement("div", { key, className: markdownClass }, /* @__PURE__ */ import_react14.default.createElement(
|
|
7392
|
+
import_react_markdown2.default,
|
|
7393
|
+
{
|
|
7394
|
+
remarkPlugins: [import_remark_gfm2.default],
|
|
7395
|
+
rehypePlugins: [import_rehype_raw2.default],
|
|
7396
|
+
components: markdownComponents
|
|
7397
|
+
},
|
|
7398
|
+
content
|
|
7399
|
+
));
|
|
7400
|
+
}
|
|
7401
|
+
return /* @__PURE__ */ import_react14.default.createElement(
|
|
7402
|
+
import_react_markdown2.default,
|
|
7403
|
+
{
|
|
7404
|
+
key,
|
|
7405
|
+
remarkPlugins: [import_remark_gfm2.default],
|
|
7406
|
+
rehypePlugins: [import_rehype_raw2.default],
|
|
7407
|
+
components: markdownComponents
|
|
7408
|
+
},
|
|
7409
|
+
content
|
|
7410
|
+
);
|
|
7411
|
+
};
|
|
7412
|
+
const renderToolStatusRow = (toolStatusRow, key) => /* @__PURE__ */ import_react14.default.createElement(
|
|
7413
|
+
"div",
|
|
7414
|
+
{
|
|
7415
|
+
key,
|
|
7416
|
+
className: `ai-chat-tool-status-row ai-chat-tool-status-row--${toolStatusRow.status}`
|
|
7417
|
+
},
|
|
7418
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-tool-status-row__main" }, /* @__PURE__ */ import_react14.default.createElement(ToolIcon, null), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-tool-status-row__label" }, toolStatusRow.statusLabel), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-tool-status-row__call-id" }, formatToolCallId(toolStatusRow.callId))),
|
|
7419
|
+
toolStatusRow.status === "pending" && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-tool-status-row__actions" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
7420
|
+
Button,
|
|
7421
|
+
{
|
|
7422
|
+
size: "sm",
|
|
7423
|
+
variant: "ghost",
|
|
7424
|
+
className: "ai-chat-tool-status-row__button",
|
|
7425
|
+
onClick: () => handleToolApproval(toolStatusRow.toolName, "once")
|
|
7426
|
+
},
|
|
7427
|
+
"once"
|
|
7428
|
+
), /* @__PURE__ */ import_react14.default.createElement(
|
|
7429
|
+
Button,
|
|
7430
|
+
{
|
|
7431
|
+
size: "sm",
|
|
7432
|
+
variant: "ghost",
|
|
7433
|
+
className: "ai-chat-tool-status-row__button",
|
|
7434
|
+
onClick: () => handleToolApproval(toolStatusRow.toolName, "session")
|
|
7435
|
+
},
|
|
7436
|
+
"session"
|
|
7437
|
+
), /* @__PURE__ */ import_react14.default.createElement(
|
|
7438
|
+
Button,
|
|
7439
|
+
{
|
|
7440
|
+
size: "sm",
|
|
7441
|
+
variant: "ghost",
|
|
7442
|
+
className: "ai-chat-tool-status-row__button",
|
|
7443
|
+
onClick: () => handleToolApproval(toolStatusRow.toolName, "always")
|
|
7444
|
+
},
|
|
7445
|
+
"always"
|
|
7446
|
+
))
|
|
7447
|
+
);
|
|
7448
|
+
const renderContentWithInlineToolCards = (content, toolStatusRows, thinkingBlocksForEntry, entryKey, keyPrefix) => {
|
|
7449
|
+
const { parts, markers } = parseInlineToolMarkers(content);
|
|
7450
|
+
const thinkingBlocksBySignature = /* @__PURE__ */ new Map();
|
|
7451
|
+
thinkingBlocksForEntry.forEach((block, index) => {
|
|
7452
|
+
const signature = String((block == null ? void 0 : block.signature) || "").trim() || getThinkingBlockRenderKey(block, index);
|
|
7453
|
+
if (!thinkingBlocksBySignature.has(signature)) {
|
|
7454
|
+
thinkingBlocksBySignature.set(signature, __spreadProps(__spreadValues({}, block), {
|
|
7455
|
+
signature
|
|
7456
|
+
}));
|
|
7457
|
+
}
|
|
7458
|
+
});
|
|
7459
|
+
const pendingBySignature = /* @__PURE__ */ new Map();
|
|
7460
|
+
const pendingByCallId = /* @__PURE__ */ new Map();
|
|
7461
|
+
toolStatusRows.forEach((row) => {
|
|
7462
|
+
if (!pendingBySignature.has(row.signature)) {
|
|
7463
|
+
pendingBySignature.set(row.signature, row);
|
|
7464
|
+
}
|
|
7465
|
+
if (!pendingByCallId.has(row.callId)) {
|
|
7466
|
+
pendingByCallId.set(row.callId, row);
|
|
7467
|
+
}
|
|
7468
|
+
});
|
|
7469
|
+
const nodes = [];
|
|
7470
|
+
parts.forEach((part, partIndex) => {
|
|
7471
|
+
const { parts: thinkingParts, markers: thinkingMarkers } = parseInlineThinkingMarkers(part);
|
|
7472
|
+
thinkingParts.forEach((thinkingPart, thinkingIndex) => {
|
|
7473
|
+
const markdownNode = renderMarkdownContent(
|
|
7474
|
+
thinkingPart,
|
|
7475
|
+
`${keyPrefix}-md-${partIndex}-${thinkingIndex}`
|
|
7476
|
+
);
|
|
7477
|
+
if (markdownNode) {
|
|
7478
|
+
nodes.push(markdownNode);
|
|
5335
7479
|
}
|
|
5336
|
-
|
|
7480
|
+
const thinkingMarker = thinkingMarkers[thinkingIndex];
|
|
7481
|
+
if (!thinkingMarker) return;
|
|
7482
|
+
const matchedBlock = thinkingBlocksBySignature.get(thinkingMarker.signature);
|
|
7483
|
+
if (!matchedBlock) return;
|
|
7484
|
+
const blockKey = getThinkingBlockRenderKey(matchedBlock, thinkingIndex);
|
|
7485
|
+
nodes.push(
|
|
7486
|
+
/* @__PURE__ */ import_react14.default.createElement(
|
|
7487
|
+
"div",
|
|
7488
|
+
{
|
|
7489
|
+
key: `${keyPrefix}-thinking-${partIndex}-${thinkingIndex}-${blockKey}`,
|
|
7490
|
+
className: "ai-chat-inline-thinking-events"
|
|
7491
|
+
},
|
|
7492
|
+
renderThinkingBlockCard(
|
|
7493
|
+
entryKey,
|
|
7494
|
+
matchedBlock,
|
|
7495
|
+
blockKey,
|
|
7496
|
+
`${keyPrefix}-thinking-card-${partIndex}-${thinkingIndex}-${blockKey}`,
|
|
7497
|
+
false
|
|
7498
|
+
)
|
|
7499
|
+
)
|
|
7500
|
+
);
|
|
5337
7501
|
});
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
const
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
7502
|
+
const marker = markers[partIndex];
|
|
7503
|
+
if (!marker) return;
|
|
7504
|
+
const markerSignature = getToolCallSignature(marker.toolName, marker.callId);
|
|
7505
|
+
const matchedRow = (markerSignature ? pendingBySignature.get(markerSignature) : void 0) || pendingByCallId.get(marker.callId);
|
|
7506
|
+
const fallbackSignature = markerSignature || getToolCallSignature(marker.toolName, `${marker.callId}-${partIndex + 1}`) || `${marker.toolName}::${marker.callId}::${partIndex}`;
|
|
7507
|
+
const rowToRender = matchedRow || {
|
|
7508
|
+
signature: fallbackSignature,
|
|
7509
|
+
toolName: marker.toolName,
|
|
7510
|
+
callId: marker.callId,
|
|
7511
|
+
status: "running",
|
|
7512
|
+
statusLabel: `tool call ${marker.toolName} running`
|
|
7513
|
+
};
|
|
7514
|
+
if (matchedRow) {
|
|
7515
|
+
pendingBySignature.delete(matchedRow.signature);
|
|
7516
|
+
const pendingByCallIdMatch = pendingByCallId.get(matchedRow.callId);
|
|
7517
|
+
if ((pendingByCallIdMatch == null ? void 0 : pendingByCallIdMatch.signature) === matchedRow.signature) {
|
|
7518
|
+
pendingByCallId.delete(matchedRow.callId);
|
|
5350
7519
|
}
|
|
5351
|
-
);
|
|
5352
|
-
}), activeThinkingBlock && /* @__PURE__ */ import_react14.default.createElement(
|
|
5353
|
-
ThinkingBlock,
|
|
5354
|
-
{
|
|
5355
|
-
key: "active-streaming",
|
|
5356
|
-
type: activeThinkingBlock.type,
|
|
5357
|
-
content: activeThinkingBlock.content,
|
|
5358
|
-
isStreaming: true,
|
|
5359
|
-
isCollapsed: collapsedBlocks.has("active"),
|
|
5360
|
-
onToggleCollapse: () => handleToggleCollapse("active")
|
|
5361
7520
|
}
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
7521
|
+
nodes.push(
|
|
7522
|
+
/* @__PURE__ */ import_react14.default.createElement(
|
|
7523
|
+
"div",
|
|
7524
|
+
{
|
|
7525
|
+
key: `${keyPrefix}-inline-${rowToRender.signature}-${partIndex}`,
|
|
7526
|
+
className: "ai-chat-inline-tool-events",
|
|
7527
|
+
role: "status",
|
|
7528
|
+
"aria-live": "polite"
|
|
7529
|
+
},
|
|
7530
|
+
renderToolStatusRow(rowToRender, `${keyPrefix}-row-${rowToRender.signature}-${partIndex}`)
|
|
7531
|
+
)
|
|
7532
|
+
);
|
|
7533
|
+
});
|
|
7534
|
+
const unmatchedRows = Array.from(pendingBySignature.values());
|
|
7535
|
+
if (unmatchedRows.length > 0) {
|
|
7536
|
+
nodes.push(
|
|
7537
|
+
/* @__PURE__ */ import_react14.default.createElement(
|
|
7538
|
+
"div",
|
|
7539
|
+
{
|
|
7540
|
+
key: `${keyPrefix}-tail`,
|
|
7541
|
+
className: "ai-chat-inline-tool-events ai-chat-inline-tool-events--tail",
|
|
7542
|
+
role: "status",
|
|
7543
|
+
"aria-live": "polite"
|
|
7544
|
+
},
|
|
7545
|
+
unmatchedRows.map(
|
|
7546
|
+
(row, rowIndex) => renderToolStatusRow(row, `${keyPrefix}-tail-${row.signature}-${rowIndex}`)
|
|
7547
|
+
)
|
|
7548
|
+
)
|
|
7549
|
+
);
|
|
7550
|
+
}
|
|
7551
|
+
return /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, nodes);
|
|
7552
|
+
};
|
|
5365
7553
|
return /* @__PURE__ */ import_react14.default.createElement(
|
|
5366
7554
|
"div",
|
|
5367
7555
|
{
|
|
@@ -5394,47 +7582,114 @@ var AIChatPanel = ({
|
|
|
5394
7582
|
initialMessage
|
|
5395
7583
|
))), Object.entries(history).map(([prompt, entry], index, entries) => {
|
|
5396
7584
|
const isLastEntry = index === entries.length - 1;
|
|
7585
|
+
const isStreamingEntry = isLastEntry && (isLoading || !idle) && !justReset;
|
|
7586
|
+
const continuationAppendBase = isStreamingEntry && activeStreamAppendBaseRef.current && activeStreamAppendBaseRef.current.key === prompt && activeStreamAppendBaseRef.current.base.trim().length > 0 ? activeStreamAppendBaseRef.current : null;
|
|
7587
|
+
const isContinuationStreamingEntry = !!continuationAppendBase;
|
|
5397
7588
|
const isSystemMessage = prompt.startsWith("__system__:");
|
|
5398
7589
|
const { cleanedText } = processThinkingTags(entry.content);
|
|
5399
7590
|
const processedContent = processActions(cleanedText);
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
7591
|
+
const entryThinkingBlocks = thinkingBlocksByKey[prompt] || [];
|
|
7592
|
+
const statusBySignature = /* @__PURE__ */ new Map();
|
|
7593
|
+
const upsertToolStatus = (row) => {
|
|
7594
|
+
const existing = statusBySignature.get(row.signature);
|
|
7595
|
+
if (!existing || getToolStatusRank(row.status) >= getToolStatusRank(existing.status)) {
|
|
7596
|
+
statusBySignature.set(row.signature, row);
|
|
7597
|
+
}
|
|
7598
|
+
};
|
|
7599
|
+
const entryToolCalls = Array.isArray(entry.toolCalls) ? entry.toolCalls : [];
|
|
7600
|
+
const entryToolResponses = Array.isArray(entry.toolResponses) ? entry.toolResponses : [];
|
|
7601
|
+
entryToolCalls.forEach((toolCall, toolIndex) => {
|
|
7602
|
+
const toolName = String((toolCall == null ? void 0 : toolCall.name) || "").trim() || "tool";
|
|
7603
|
+
const callId = String((toolCall == null ? void 0 : toolCall.id) || "").trim() || `${toolName}-${toolIndex + 1}`;
|
|
7604
|
+
const signature = getToolCallSignature(toolName, callId) || `completed-${prompt}-${toolIndex}-${toolName}-${callId}`;
|
|
7605
|
+
const matchedResponse = entryToolResponses.find((response2) => String((response2 == null ? void 0 : response2.tool_call_id) || "").trim() === callId) || entryToolResponses[toolIndex];
|
|
7606
|
+
const isError = Boolean(matchedResponse == null ? void 0 : matchedResponse.isError);
|
|
7607
|
+
upsertToolStatus({
|
|
7608
|
+
signature,
|
|
7609
|
+
toolName,
|
|
7610
|
+
callId,
|
|
7611
|
+
status: isError ? "error" : "completed",
|
|
7612
|
+
statusLabel: isError ? `tool call ${toolName} errored` : `tool call ${toolName} completed`
|
|
7613
|
+
});
|
|
7614
|
+
});
|
|
7615
|
+
if (isLastEntry && !justReset) {
|
|
7616
|
+
pendingToolRequests.forEach((request, requestIndex) => {
|
|
7617
|
+
const toolName = String((request == null ? void 0 : request.toolName) || "").trim() || "tool";
|
|
7618
|
+
const callId = String((request == null ? void 0 : request.callId) || "").trim() || `${toolName}-pending-${requestIndex + 1}`;
|
|
7619
|
+
const signature = getToolCallSignature(toolName, callId) || `pending-${prompt}-${requestIndex}-${toolName}-${callId}`;
|
|
7620
|
+
upsertToolStatus({
|
|
7621
|
+
signature,
|
|
7622
|
+
toolName,
|
|
7623
|
+
callId,
|
|
7624
|
+
status: "pending",
|
|
7625
|
+
statusLabel: `tool call ${toolName} awaiting approval`
|
|
7626
|
+
});
|
|
7627
|
+
});
|
|
7628
|
+
activeToolCalls.forEach((activeToolCall, activeIndex) => {
|
|
7629
|
+
const toolName = String((activeToolCall == null ? void 0 : activeToolCall.toolName) || "").trim() || "tool";
|
|
7630
|
+
const callId = String((activeToolCall == null ? void 0 : activeToolCall.callId) || "").trim() || `${toolName}-running-${activeIndex + 1}`;
|
|
7631
|
+
const signature = getToolCallSignature(toolName, callId) || `running-${prompt}-${activeIndex}-${toolName}-${callId}`;
|
|
7632
|
+
upsertToolStatus({
|
|
7633
|
+
signature,
|
|
7634
|
+
toolName,
|
|
7635
|
+
callId,
|
|
7636
|
+
status: "running",
|
|
7637
|
+
statusLabel: `tool call ${toolName} running`
|
|
7638
|
+
});
|
|
7639
|
+
});
|
|
7640
|
+
}
|
|
7641
|
+
const entryToolStatusRows = Array.from(statusBySignature.values());
|
|
7642
|
+
const hasInFlightToolStatus = entryToolStatusRows.some(
|
|
7643
|
+
(row) => row.status === "pending" || row.status === "running"
|
|
7644
|
+
);
|
|
7645
|
+
const isActivePromptEntry = !!lastKey && prompt === lastKey;
|
|
7646
|
+
const shouldShowBusyGapThinkingFallback = isActivePromptEntry && !isStreamingEntry && (isLoading || !idle) && !activeThinkingBlock && !hasInFlightToolStatus;
|
|
7647
|
+
return /* @__PURE__ */ import_react14.default.createElement("div", { key: prompt, className: "ai-chat-entry" }, !(hideInitialPrompt && index === 0) && !isSystemMessage && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-message ai-chat-message--user" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-message__content" }, formatPromptForDisplay(prompt))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-message ai-chat-message--assistant" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-message__content" }, isStreamingEntry ? (() => {
|
|
7648
|
+
if (isContinuationStreamingEntry) {
|
|
7649
|
+
const continuationResponseWithInlineToolLabels = formatToolRequestsForDisplay(response || "");
|
|
7650
|
+
const { cleanedText: continuationCleanedText } = processThinkingTags(
|
|
7651
|
+
continuationResponseWithInlineToolLabels
|
|
7652
|
+
);
|
|
7653
|
+
const appendBase2 = continuationAppendBase || activeStreamAppendBaseRef.current;
|
|
7654
|
+
const continuationMergedText = appendBase2 && appendBase2.key === prompt ? mergeContinuationResponseText(appendBase2.base, continuationCleanedText.trim()) : continuationCleanedText;
|
|
7655
|
+
const continuationDisplaySource = continuationMergedText.trim().length > 0 ? continuationMergedText : cleanedText;
|
|
7656
|
+
const continuationDisplayContent = processActions(continuationDisplaySource);
|
|
7657
|
+
const hasVisibleContinuationContent = continuationDisplayContent.trim().length > 0;
|
|
7658
|
+
const hasFreshContinuationContent = continuationCleanedText.trim().length > 0;
|
|
7659
|
+
const showThinkingFallback2 = !activeThinkingBlock && !hasFreshContinuationContent && !hasInFlightToolStatus;
|
|
7660
|
+
return /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-streaming" }, renderActiveThinkingBlock(prompt, activeThinkingBlock, `${prompt}-continuation`), hasVisibleContinuationContent ? /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, renderContentWithInlineToolCards(
|
|
7661
|
+
continuationDisplayContent,
|
|
7662
|
+
entryToolStatusRows,
|
|
7663
|
+
entryThinkingBlocks,
|
|
7664
|
+
prompt,
|
|
7665
|
+
`${prompt}-continuation`
|
|
7666
|
+
), showThinkingFallback2 && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-loading ai-chat-loading--inline" }, /* @__PURE__ */ import_react14.default.createElement("span", null, "Thinking"), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dots" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" })))) : /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-loading" }, /* @__PURE__ */ import_react14.default.createElement("span", null, "Continuing response"), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dots" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }))));
|
|
7667
|
+
}
|
|
7668
|
+
const streamingResponseWithInlineToolLabels = formatToolRequestsForDisplay(response || "");
|
|
7669
|
+
const { cleanedText: streamingCleanedText } = processThinkingTags(streamingResponseWithInlineToolLabels);
|
|
7670
|
+
const appendBase = activeStreamAppendBaseRef.current;
|
|
7671
|
+
const streamingMergedText = appendBase && appendBase.key === prompt ? mergeContinuationResponseText(appendBase.base, streamingCleanedText.trim()) : streamingCleanedText;
|
|
7672
|
+
const streamingContent = processActions(streamingMergedText);
|
|
5403
7673
|
const hasStreamingContent = streamingContent.trim().length > 0;
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
{
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
{
|
|
5424
|
-
remarkPlugins: [import_remark_gfm2.default],
|
|
5425
|
-
rehypePlugins: [import_rehype_raw2.default],
|
|
5426
|
-
components: markdownComponents
|
|
5427
|
-
},
|
|
5428
|
-
processedContent
|
|
5429
|
-
)) : /* @__PURE__ */ import_react14.default.createElement(
|
|
5430
|
-
import_react_markdown2.default,
|
|
5431
|
-
{
|
|
5432
|
-
remarkPlugins: [import_remark_gfm2.default],
|
|
5433
|
-
rehypePlugins: [import_rehype_raw2.default],
|
|
5434
|
-
components: markdownComponents
|
|
5435
|
-
},
|
|
5436
|
-
processedContent
|
|
5437
|
-
))), (!isLastEntry || !isLoading) && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-message__actions" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
7674
|
+
const hasFreshStreamingContent = streamingCleanedText.trim().length > 0;
|
|
7675
|
+
const fallbackHistoryContent = processedContent.trim();
|
|
7676
|
+
const streamingDisplayContent = hasStreamingContent ? streamingContent : fallbackHistoryContent;
|
|
7677
|
+
const hasDisplayContent = streamingDisplayContent.trim().length > 0;
|
|
7678
|
+
const showThinkingFallback = !activeThinkingBlock && !hasFreshStreamingContent && !hasInFlightToolStatus;
|
|
7679
|
+
return /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-streaming" }, renderActiveThinkingBlock(prompt, activeThinkingBlock, `${prompt}-streaming`), hasDisplayContent ? /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, renderContentWithInlineToolCards(
|
|
7680
|
+
streamingDisplayContent,
|
|
7681
|
+
entryToolStatusRows,
|
|
7682
|
+
entryThinkingBlocks,
|
|
7683
|
+
prompt,
|
|
7684
|
+
`${prompt}-streaming`
|
|
7685
|
+
), showThinkingFallback && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-loading ai-chat-loading--inline" }, /* @__PURE__ */ import_react14.default.createElement("span", null, "Thinking"), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dots" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" })))) : /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-loading" }, /* @__PURE__ */ import_react14.default.createElement("span", null, activeThinkingBlock ? "Still thinking" : "Thinking"), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dots" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }))));
|
|
7686
|
+
})() : /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, renderContentWithInlineToolCards(
|
|
7687
|
+
processedContent,
|
|
7688
|
+
entryToolStatusRows,
|
|
7689
|
+
entryThinkingBlocks,
|
|
7690
|
+
prompt,
|
|
7691
|
+
`${prompt}-final`
|
|
7692
|
+
), shouldShowBusyGapThinkingFallback && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-loading ai-chat-loading--inline", "aria-live": "polite" }, /* @__PURE__ */ import_react14.default.createElement("span", null, "Thinking"), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dots" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-loading__dot" }))))), (!isLastEntry || !isLoading) && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-message__actions" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
5438
7693
|
"button",
|
|
5439
7694
|
{
|
|
5440
7695
|
className: "ai-chat-action-button",
|
|
@@ -5460,7 +7715,7 @@ var AIChatPanel = ({
|
|
|
5460
7715
|
style: (feedbackCallId == null ? void 0 : feedbackCallId.callId) === entry.callId && (feedbackCallId == null ? void 0 : feedbackCallId.type) === "down" ? { color: "#ef4444" } : void 0
|
|
5461
7716
|
},
|
|
5462
7717
|
(feedbackCallId == null ? void 0 : feedbackCallId.callId) === entry.callId && (feedbackCallId == null ? void 0 : feedbackCallId.type) === "down" ? /* @__PURE__ */ import_react14.default.createElement("span", { style: { fontSize: "11px", fontWeight: 500 } }, "Thanks!") : /* @__PURE__ */ import_react14.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ import_react14.default.createElement("path", { d: "M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17" }))
|
|
5463
|
-
),
|
|
7718
|
+
), /* @__PURE__ */ import_react14.default.createElement(
|
|
5464
7719
|
"button",
|
|
5465
7720
|
{
|
|
5466
7721
|
className: "ai-chat-action-button",
|
|
@@ -5486,34 +7741,6 @@ var AIChatPanel = ({
|
|
|
5486
7741
|
},
|
|
5487
7742
|
question
|
|
5488
7743
|
))), /* @__PURE__ */ import_react14.default.createElement("div", { ref: bottomRef })),
|
|
5489
|
-
pendingToolRequests.length > 0 && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-approve-tools-panel" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-approve-tools-header" }, "Tool Approval Required"), /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-approve-tools-description" }, "The AI wants to use the following tools:"), getUniqueToolNames().map((toolName) => /* @__PURE__ */ import_react14.default.createElement("div", { key: toolName, className: "ai-chat-approve-tool-item" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-approve-tool-name" }, toolName), /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-approve-tools-buttons" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
5490
|
-
Button,
|
|
5491
|
-
{
|
|
5492
|
-
size: "sm",
|
|
5493
|
-
variant: "outline",
|
|
5494
|
-
className: "ai-chat-approve-tools-button",
|
|
5495
|
-
onClick: () => handleToolApproval(toolName, "once")
|
|
5496
|
-
},
|
|
5497
|
-
"Once"
|
|
5498
|
-
), /* @__PURE__ */ import_react14.default.createElement(
|
|
5499
|
-
Button,
|
|
5500
|
-
{
|
|
5501
|
-
size: "sm",
|
|
5502
|
-
variant: "outline",
|
|
5503
|
-
className: "ai-chat-approve-tools-button",
|
|
5504
|
-
onClick: () => handleToolApproval(toolName, "session")
|
|
5505
|
-
},
|
|
5506
|
-
"This Session"
|
|
5507
|
-
), /* @__PURE__ */ import_react14.default.createElement(
|
|
5508
|
-
Button,
|
|
5509
|
-
{
|
|
5510
|
-
size: "sm",
|
|
5511
|
-
variant: "default",
|
|
5512
|
-
className: "ai-chat-approve-tools-button",
|
|
5513
|
-
onClick: () => handleToolApproval(toolName, "always")
|
|
5514
|
-
},
|
|
5515
|
-
"Always"
|
|
5516
|
-
))))),
|
|
5517
7744
|
(showSaveButton || showEmailButton || showCallToAction) && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-button-container" }, showSaveButton && /* @__PURE__ */ import_react14.default.createElement(
|
|
5518
7745
|
Button,
|
|
5519
7746
|
{
|
|
@@ -5649,7 +7876,7 @@ var AIChatPanel = ({
|
|
|
5649
7876
|
ChatInput,
|
|
5650
7877
|
{
|
|
5651
7878
|
placeholder,
|
|
5652
|
-
idle,
|
|
7879
|
+
isBusy: isLoading || !idle,
|
|
5653
7880
|
onSubmit: continueChat,
|
|
5654
7881
|
onStop: handleStop,
|
|
5655
7882
|
agentOptions,
|
|
@@ -5896,13 +8123,14 @@ var SparkleIcon = () => /* @__PURE__ */ import_react16.default.createElement("sv
|
|
|
5896
8123
|
var normalizeConversationListPayload = (payload) => {
|
|
5897
8124
|
if (!payload) return [];
|
|
5898
8125
|
const conversations = Array.isArray(payload) ? payload : payload.conversations || [];
|
|
5899
|
-
|
|
8126
|
+
const normalized = conversations.map((conv, index) => {
|
|
5900
8127
|
let title = conv.title && conv.title !== "Conversation" ? conv.title : "";
|
|
5901
8128
|
if (!title) {
|
|
5902
8129
|
title = conv.summary || extractTitleFromConversation(conv);
|
|
5903
8130
|
}
|
|
8131
|
+
const resolvedConversationId = conv.conversationId || conv.id || conv.conversation_id || `conversation-${index}-${Date.now()}`;
|
|
5904
8132
|
return {
|
|
5905
|
-
conversationId:
|
|
8133
|
+
conversationId: resolvedConversationId,
|
|
5906
8134
|
title,
|
|
5907
8135
|
summary: conv.summary,
|
|
5908
8136
|
createdAt: conv.createdAt || conv.created_at || conv.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -5911,6 +8139,20 @@ var normalizeConversationListPayload = (payload) => {
|
|
|
5911
8139
|
messageCount: conv.messageCount || conv.message_count
|
|
5912
8140
|
};
|
|
5913
8141
|
});
|
|
8142
|
+
const dedupedById = /* @__PURE__ */ new Map();
|
|
8143
|
+
for (const conv of normalized) {
|
|
8144
|
+
const existing = dedupedById.get(conv.conversationId);
|
|
8145
|
+
if (!existing) {
|
|
8146
|
+
dedupedById.set(conv.conversationId, conv);
|
|
8147
|
+
continue;
|
|
8148
|
+
}
|
|
8149
|
+
const existingUpdated = new Date(existing.updatedAt).getTime();
|
|
8150
|
+
const incomingUpdated = new Date(conv.updatedAt).getTime();
|
|
8151
|
+
if (incomingUpdated >= existingUpdated) {
|
|
8152
|
+
dedupedById.set(conv.conversationId, conv);
|
|
8153
|
+
}
|
|
8154
|
+
}
|
|
8155
|
+
return Array.from(dedupedById.values());
|
|
5914
8156
|
};
|
|
5915
8157
|
var extractTitleFromConversation = (conv) => {
|
|
5916
8158
|
var _a;
|
|
@@ -5984,6 +8226,248 @@ var groupConversationsByTime = (conversations, showAllGroups = false) => {
|
|
|
5984
8226
|
});
|
|
5985
8227
|
return Object.entries(groups).filter(([_, convs]) => showAllGroups || convs.length > 0).map(([label, conversations2]) => ({ label, conversations: conversations2, count: conversations2.length }));
|
|
5986
8228
|
};
|
|
8229
|
+
var toRecord = (value) => {
|
|
8230
|
+
if (typeof value === "object" && value !== null) {
|
|
8231
|
+
return value;
|
|
8232
|
+
}
|
|
8233
|
+
return null;
|
|
8234
|
+
};
|
|
8235
|
+
var toStringValue = (value) => {
|
|
8236
|
+
if (typeof value === "string") return value;
|
|
8237
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
8238
|
+
return "";
|
|
8239
|
+
};
|
|
8240
|
+
var normalizeContentText = (value) => {
|
|
8241
|
+
if (typeof value === "string") return value;
|
|
8242
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
8243
|
+
if (Array.isArray(value)) {
|
|
8244
|
+
return value.map((item) => normalizeContentText(item)).filter(Boolean).join("\n").trim();
|
|
8245
|
+
}
|
|
8246
|
+
const record = toRecord(value);
|
|
8247
|
+
if (!record) return "";
|
|
8248
|
+
const directText = toStringValue(record.text);
|
|
8249
|
+
if (directText) return directText;
|
|
8250
|
+
const directValue = toStringValue(record.value);
|
|
8251
|
+
if (directValue) return directValue;
|
|
8252
|
+
const directContent = toStringValue(record.content);
|
|
8253
|
+
if (directContent) return directContent;
|
|
8254
|
+
if (Array.isArray(record.content)) {
|
|
8255
|
+
return normalizeContentText(record.content);
|
|
8256
|
+
}
|
|
8257
|
+
if (Array.isArray(record.parts)) {
|
|
8258
|
+
return normalizeContentText(record.parts);
|
|
8259
|
+
}
|
|
8260
|
+
if (record.content && typeof record.content === "object") {
|
|
8261
|
+
return normalizeContentText(record.content);
|
|
8262
|
+
}
|
|
8263
|
+
return "";
|
|
8264
|
+
};
|
|
8265
|
+
var parseCallMessages = (rawMessages) => {
|
|
8266
|
+
var _a, _b;
|
|
8267
|
+
let parsed = rawMessages;
|
|
8268
|
+
if (typeof rawMessages === "string") {
|
|
8269
|
+
try {
|
|
8270
|
+
parsed = JSON.parse(rawMessages);
|
|
8271
|
+
} catch (e) {
|
|
8272
|
+
return [];
|
|
8273
|
+
}
|
|
8274
|
+
}
|
|
8275
|
+
const parsedRecord = toRecord(parsed);
|
|
8276
|
+
if (parsedRecord && Array.isArray(parsedRecord.messages)) {
|
|
8277
|
+
parsed = parsedRecord.messages;
|
|
8278
|
+
}
|
|
8279
|
+
if (!Array.isArray(parsed)) {
|
|
8280
|
+
return [];
|
|
8281
|
+
}
|
|
8282
|
+
const normalized = [];
|
|
8283
|
+
for (const message of parsed) {
|
|
8284
|
+
const messageRecord = toRecord(message);
|
|
8285
|
+
if (!messageRecord) continue;
|
|
8286
|
+
const role = toStringValue(messageRecord.role).toLowerCase().trim();
|
|
8287
|
+
if (!role) continue;
|
|
8288
|
+
const content = normalizeContentText(
|
|
8289
|
+
(_b = (_a = messageRecord.content) != null ? _a : messageRecord.text) != null ? _b : messageRecord.message
|
|
8290
|
+
).trim();
|
|
8291
|
+
if (!content) continue;
|
|
8292
|
+
normalized.push({ role, content });
|
|
8293
|
+
}
|
|
8294
|
+
return normalized;
|
|
8295
|
+
};
|
|
8296
|
+
var shouldSkipTranscriptMessage = (message) => {
|
|
8297
|
+
return message.role === "system" || message.role === "user" && message.content.startsWith("__system__:");
|
|
8298
|
+
};
|
|
8299
|
+
var parseTimestampMs = (value) => {
|
|
8300
|
+
const timestamp = toStringValue(value).trim();
|
|
8301
|
+
if (!timestamp) return null;
|
|
8302
|
+
const parsed = Date.parse(timestamp);
|
|
8303
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
8304
|
+
};
|
|
8305
|
+
var getCallTimestampMs = (call, fallbackIndex) => {
|
|
8306
|
+
const timestampCandidates = [
|
|
8307
|
+
call.createdAt,
|
|
8308
|
+
call.created_at,
|
|
8309
|
+
call.timestamp,
|
|
8310
|
+
call.updatedAt,
|
|
8311
|
+
call.updated_at
|
|
8312
|
+
];
|
|
8313
|
+
for (const candidate of timestampCandidates) {
|
|
8314
|
+
const parsed = parseTimestampMs(candidate);
|
|
8315
|
+
if (parsed !== null) return parsed;
|
|
8316
|
+
}
|
|
8317
|
+
return fallbackIndex;
|
|
8318
|
+
};
|
|
8319
|
+
var getCallId = (call) => {
|
|
8320
|
+
const id = toStringValue(call.id);
|
|
8321
|
+
if (id) return id;
|
|
8322
|
+
return toStringValue(call.callId);
|
|
8323
|
+
};
|
|
8324
|
+
var normalizeCallsPayload = (payload) => {
|
|
8325
|
+
const payloadRecord = toRecord(payload);
|
|
8326
|
+
const calls = Array.isArray(payload) ? payload : payloadRecord && Array.isArray(payloadRecord.calls) ? payloadRecord.calls : [];
|
|
8327
|
+
return calls.map((call) => toRecord(call)).filter((call) => call !== null);
|
|
8328
|
+
};
|
|
8329
|
+
var turnsEqual = (left, right) => {
|
|
8330
|
+
return left.prompt === right.prompt && left.response === right.response;
|
|
8331
|
+
};
|
|
8332
|
+
var getPrefixMatchLength = (existing, incoming) => {
|
|
8333
|
+
const max = Math.min(existing.length, incoming.length);
|
|
8334
|
+
let matched = 0;
|
|
8335
|
+
while (matched < max && turnsEqual(existing[matched], incoming[matched])) {
|
|
8336
|
+
matched += 1;
|
|
8337
|
+
}
|
|
8338
|
+
return matched;
|
|
8339
|
+
};
|
|
8340
|
+
var getSuffixPrefixOverlap = (existing, incoming) => {
|
|
8341
|
+
const max = Math.min(existing.length, incoming.length);
|
|
8342
|
+
for (let overlap = max; overlap > 0; overlap -= 1) {
|
|
8343
|
+
let matches = true;
|
|
8344
|
+
for (let idx = 0; idx < overlap; idx += 1) {
|
|
8345
|
+
const left = existing[existing.length - overlap + idx];
|
|
8346
|
+
const right = incoming[idx];
|
|
8347
|
+
if (!turnsEqual(left, right)) {
|
|
8348
|
+
matches = false;
|
|
8349
|
+
break;
|
|
8350
|
+
}
|
|
8351
|
+
}
|
|
8352
|
+
if (matches) return overlap;
|
|
8353
|
+
}
|
|
8354
|
+
return 0;
|
|
8355
|
+
};
|
|
8356
|
+
var mergeTranscriptTurns = (existing, incoming) => {
|
|
8357
|
+
if (incoming.length === 0) return existing;
|
|
8358
|
+
if (existing.length === 0) return [...incoming];
|
|
8359
|
+
const prefixMatchLength = getPrefixMatchLength(existing, incoming);
|
|
8360
|
+
if (prefixMatchLength > 0) {
|
|
8361
|
+
return [...existing, ...incoming.slice(prefixMatchLength)];
|
|
8362
|
+
}
|
|
8363
|
+
const overlap = getSuffixPrefixOverlap(existing, incoming);
|
|
8364
|
+
if (overlap > 0) {
|
|
8365
|
+
return [...existing, ...incoming.slice(overlap)];
|
|
8366
|
+
}
|
|
8367
|
+
return [...existing, ...incoming];
|
|
8368
|
+
};
|
|
8369
|
+
var buildTurnsFromMessages = (messages, fallbackResponse, callId, timestampMs) => {
|
|
8370
|
+
const turns = [];
|
|
8371
|
+
for (let index = 0; index < messages.length; index += 1) {
|
|
8372
|
+
const message = messages[index];
|
|
8373
|
+
if (!message || message.role !== "user") continue;
|
|
8374
|
+
const prompt = message.content.trim();
|
|
8375
|
+
if (!prompt) continue;
|
|
8376
|
+
let response = "";
|
|
8377
|
+
let reachedNextUser = false;
|
|
8378
|
+
for (let lookAhead = index + 1; lookAhead < messages.length; lookAhead += 1) {
|
|
8379
|
+
const nextMessage = messages[lookAhead];
|
|
8380
|
+
if (!nextMessage) continue;
|
|
8381
|
+
if (nextMessage.role === "assistant") {
|
|
8382
|
+
response = nextMessage.content.trim();
|
|
8383
|
+
index = lookAhead;
|
|
8384
|
+
break;
|
|
8385
|
+
}
|
|
8386
|
+
if (nextMessage.role === "user") {
|
|
8387
|
+
reachedNextUser = true;
|
|
8388
|
+
break;
|
|
8389
|
+
}
|
|
8390
|
+
}
|
|
8391
|
+
if (!response && !reachedNextUser) {
|
|
8392
|
+
response = fallbackResponse;
|
|
8393
|
+
}
|
|
8394
|
+
if (!response) continue;
|
|
8395
|
+
turns.push({
|
|
8396
|
+
prompt,
|
|
8397
|
+
response,
|
|
8398
|
+
callId,
|
|
8399
|
+
timestampMs
|
|
8400
|
+
});
|
|
8401
|
+
}
|
|
8402
|
+
return turns;
|
|
8403
|
+
};
|
|
8404
|
+
var buildTranscriptTurnsFromCalls = (calls) => {
|
|
8405
|
+
const orderedCalls = calls.map((call, index) => ({
|
|
8406
|
+
call,
|
|
8407
|
+
index,
|
|
8408
|
+
timestampMs: getCallTimestampMs(call, index)
|
|
8409
|
+
})).sort((left, right) => {
|
|
8410
|
+
if (left.timestampMs === right.timestampMs) return left.index - right.index;
|
|
8411
|
+
return left.timestampMs - right.timestampMs;
|
|
8412
|
+
});
|
|
8413
|
+
let mergedTurns = [];
|
|
8414
|
+
for (const orderedCall of orderedCalls) {
|
|
8415
|
+
const { call, timestampMs } = orderedCall;
|
|
8416
|
+
const callId = getCallId(call);
|
|
8417
|
+
const fallbackResponse = normalizeContentText(call.response).trim();
|
|
8418
|
+
const parsedMessages = parseCallMessages(call.messages).filter(
|
|
8419
|
+
(message) => !shouldSkipTranscriptMessage(message)
|
|
8420
|
+
);
|
|
8421
|
+
let callTurns = buildTurnsFromMessages(
|
|
8422
|
+
parsedMessages,
|
|
8423
|
+
fallbackResponse,
|
|
8424
|
+
callId,
|
|
8425
|
+
timestampMs
|
|
8426
|
+
);
|
|
8427
|
+
if (callTurns.length === 0) {
|
|
8428
|
+
const fallbackPrompt = normalizeContentText(call.prompt).trim();
|
|
8429
|
+
if (fallbackPrompt && fallbackResponse) {
|
|
8430
|
+
callTurns = [
|
|
8431
|
+
{
|
|
8432
|
+
prompt: fallbackPrompt,
|
|
8433
|
+
response: fallbackResponse,
|
|
8434
|
+
callId,
|
|
8435
|
+
timestampMs
|
|
8436
|
+
}
|
|
8437
|
+
];
|
|
8438
|
+
}
|
|
8439
|
+
}
|
|
8440
|
+
mergedTurns = mergeTranscriptTurns(mergedTurns, callTurns);
|
|
8441
|
+
}
|
|
8442
|
+
return mergedTurns;
|
|
8443
|
+
};
|
|
8444
|
+
var buildHistoryFromTranscriptTurns = (turns) => {
|
|
8445
|
+
const history = {};
|
|
8446
|
+
const keyUsageByPrompt = /* @__PURE__ */ new Map();
|
|
8447
|
+
turns.forEach((turn, index) => {
|
|
8448
|
+
var _a;
|
|
8449
|
+
const prompt = turn.prompt.trim();
|
|
8450
|
+
const response = turn.response.trim();
|
|
8451
|
+
if (!prompt || !response) return;
|
|
8452
|
+
const baseTimestampMs = Number.isFinite(turn.timestampMs) ? turn.timestampMs : index;
|
|
8453
|
+
const keySeed = `${baseTimestampMs}:${prompt}`;
|
|
8454
|
+
const keyUsageCount = (_a = keyUsageByPrompt.get(keySeed)) != null ? _a : 0;
|
|
8455
|
+
keyUsageByPrompt.set(keySeed, keyUsageCount + 1);
|
|
8456
|
+
const uniqueTimestamp = new Date(baseTimestampMs + keyUsageCount).toISOString();
|
|
8457
|
+
const historyKey = `${uniqueTimestamp}:${prompt}`;
|
|
8458
|
+
history[historyKey] = {
|
|
8459
|
+
content: response,
|
|
8460
|
+
callId: turn.callId
|
|
8461
|
+
};
|
|
8462
|
+
});
|
|
8463
|
+
return history;
|
|
8464
|
+
};
|
|
8465
|
+
var truncatePromptForTitle = (prompt) => {
|
|
8466
|
+
if (prompt.length > 60) {
|
|
8467
|
+
return `${prompt.slice(0, 57)}...`;
|
|
8468
|
+
}
|
|
8469
|
+
return prompt;
|
|
8470
|
+
};
|
|
5987
8471
|
var EMPTY_ARRAY = [];
|
|
5988
8472
|
var EMPTY_HISTORY = {};
|
|
5989
8473
|
var ChatPanelWrapper = ({
|
|
@@ -6017,6 +8501,7 @@ var ChatPanelWrapper = ({
|
|
|
6017
8501
|
disabledSectionIds,
|
|
6018
8502
|
onToggleSection,
|
|
6019
8503
|
onConversationCreated,
|
|
8504
|
+
onBeforeSend,
|
|
6020
8505
|
conversationInitialPrompt,
|
|
6021
8506
|
// New props from ChatPanel port
|
|
6022
8507
|
cssUrl,
|
|
@@ -6033,7 +8518,11 @@ var ChatPanelWrapper = ({
|
|
|
6033
8518
|
callToActionEmailAddress,
|
|
6034
8519
|
callToActionEmailSubject,
|
|
6035
8520
|
customerEmailCaptureMode,
|
|
6036
|
-
customerEmailCapturePlaceholder
|
|
8521
|
+
customerEmailCapturePlaceholder,
|
|
8522
|
+
resolveMcpAuthHeaders,
|
|
8523
|
+
localToolExecutors,
|
|
8524
|
+
traceContextMode,
|
|
8525
|
+
autoApproveTools
|
|
6037
8526
|
}) => {
|
|
6038
8527
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
6039
8528
|
const convAgentProfile = getAgent(activeConv.agentId);
|
|
@@ -6057,6 +8546,16 @@ var ChatPanelWrapper = ({
|
|
|
6057
8546
|
},
|
|
6058
8547
|
[onConversationCreated, activeConv.conversationId]
|
|
6059
8548
|
);
|
|
8549
|
+
const beforeSendCallback = (0, import_react16.useCallback)(
|
|
8550
|
+
(payload) => {
|
|
8551
|
+
if (!onBeforeSend) return;
|
|
8552
|
+
return onBeforeSend(__spreadProps(__spreadValues({}, payload), {
|
|
8553
|
+
conversationId: payload.conversationId || activeConv.conversationId,
|
|
8554
|
+
agentId: payload.agentId || activeConv.agentId
|
|
8555
|
+
}));
|
|
8556
|
+
},
|
|
8557
|
+
[onBeforeSend, activeConv.conversationId, activeConv.agentId]
|
|
8558
|
+
);
|
|
6060
8559
|
const agentStatus = convAgentProfile == null ? void 0 : convAgentProfile.status;
|
|
6061
8560
|
const promptsString = (convAgentMetadata == null ? void 0 : convAgentMetadata.displayFollowOnPrompts) || "";
|
|
6062
8561
|
let effectiveFollowOnQuestions;
|
|
@@ -6120,6 +8619,7 @@ var ChatPanelWrapper = ({
|
|
|
6120
8619
|
disabledSectionIds,
|
|
6121
8620
|
onToggleSection,
|
|
6122
8621
|
onConversationCreated: conversationCreatedCallback,
|
|
8622
|
+
onBeforeSend: beforeSendCallback,
|
|
6123
8623
|
cssUrl,
|
|
6124
8624
|
markdownClass,
|
|
6125
8625
|
width,
|
|
@@ -6134,7 +8634,11 @@ var ChatPanelWrapper = ({
|
|
|
6134
8634
|
callToActionEmailAddress: (_g = callToActionEmailAddress != null ? callToActionEmailAddress : convAgentMetadata.displayCallToActionEmailAddress) != null ? _g : "",
|
|
6135
8635
|
callToActionEmailSubject: (_h = callToActionEmailSubject != null ? callToActionEmailSubject : convAgentMetadata.displayCallToActionEmailSubject) != null ? _h : "Agent CTA submitted",
|
|
6136
8636
|
customerEmailCaptureMode: (_i = customerEmailCaptureMode != null ? customerEmailCaptureMode : convAgentMetadata == null ? void 0 : convAgentMetadata.customerEmailCaptureMode) != null ? _i : "HIDE",
|
|
6137
|
-
customerEmailCapturePlaceholder: (_j = customerEmailCapturePlaceholder != null ? customerEmailCapturePlaceholder : convAgentMetadata == null ? void 0 : convAgentMetadata.customerEmailCapturePlaceholder) != null ? _j : "Please enter your email..."
|
|
8637
|
+
customerEmailCapturePlaceholder: (_j = customerEmailCapturePlaceholder != null ? customerEmailCapturePlaceholder : convAgentMetadata == null ? void 0 : convAgentMetadata.customerEmailCapturePlaceholder) != null ? _j : "Please enter your email...",
|
|
8638
|
+
resolveMcpAuthHeaders,
|
|
8639
|
+
localToolExecutors,
|
|
8640
|
+
traceContextMode,
|
|
8641
|
+
autoApproveTools
|
|
6138
8642
|
}
|
|
6139
8643
|
)
|
|
6140
8644
|
);
|
|
@@ -6185,6 +8689,7 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6185
8689
|
enableContextDetailView = false,
|
|
6186
8690
|
onAgentSwitch,
|
|
6187
8691
|
onConversationChange,
|
|
8692
|
+
onBeforeSend,
|
|
6188
8693
|
historyChangedCallback,
|
|
6189
8694
|
responseCompleteCallback,
|
|
6190
8695
|
thumbsUpClick,
|
|
@@ -6216,7 +8721,11 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6216
8721
|
callToActionEmailAddress,
|
|
6217
8722
|
callToActionEmailSubject,
|
|
6218
8723
|
customerEmailCaptureMode,
|
|
6219
|
-
customerEmailCapturePlaceholder
|
|
8724
|
+
customerEmailCapturePlaceholder,
|
|
8725
|
+
resolveMcpAuthHeaders,
|
|
8726
|
+
localToolExecutors,
|
|
8727
|
+
traceContextMode = "standard",
|
|
8728
|
+
autoApproveTools
|
|
6220
8729
|
}, ref) => {
|
|
6221
8730
|
var _a, _b, _c, _d;
|
|
6222
8731
|
(0, import_react16.useEffect)(() => {
|
|
@@ -6236,13 +8745,7 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6236
8745
|
const [uncontrolledIsCollapsed, setUncontrolledIsCollapsed] = (0, import_react16.useState)(collapsible && defaultCollapsed);
|
|
6237
8746
|
const isControlled = controlledIsCollapsed !== void 0;
|
|
6238
8747
|
const isCollapsed = isControlled ? controlledIsCollapsed : uncontrolledIsCollapsed;
|
|
6239
|
-
const [isHistoryCollapsed, setIsHistoryCollapsed] = (0, import_react16.useState)(
|
|
6240
|
-
if (typeof window !== "undefined") {
|
|
6241
|
-
const saved = localStorage.getItem("ai-agent-panel-history-collapsed");
|
|
6242
|
-
return saved === "true";
|
|
6243
|
-
}
|
|
6244
|
-
return false;
|
|
6245
|
-
});
|
|
8748
|
+
const [isHistoryCollapsed, setIsHistoryCollapsed] = (0, import_react16.useState)(true);
|
|
6246
8749
|
const [panelWidth, setPanelWidth] = (0, import_react16.useState)(() => {
|
|
6247
8750
|
if (typeof window !== "undefined") {
|
|
6248
8751
|
const savedWidth = localStorage.getItem("ai-agent-panel-width");
|
|
@@ -6344,8 +8847,12 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6344
8847
|
const [conversationsLoading, setConversationsLoading] = (0, import_react16.useState)(false);
|
|
6345
8848
|
const [conversationsError, setConversationsError] = (0, import_react16.useState)(null);
|
|
6346
8849
|
const [searchQuery, setSearchQuery] = (0, import_react16.useState)("");
|
|
8850
|
+
const controlledConversationId = typeof conversation === "string" && conversation.trim() !== "" ? conversation.trim() : null;
|
|
8851
|
+
const isConversationControlled = controlledConversationId !== null;
|
|
6347
8852
|
const [activeConversations, setActiveConversations] = (0, import_react16.useState)(/* @__PURE__ */ new Map());
|
|
6348
|
-
const [currentConversationId, setCurrentConversationId] = (0, import_react16.useState)(
|
|
8853
|
+
const [currentConversationId, setCurrentConversationId] = (0, import_react16.useState)(
|
|
8854
|
+
controlledConversationId
|
|
8855
|
+
);
|
|
6349
8856
|
const [conversationFirstPrompts, setConversationFirstPrompts] = (0, import_react16.useState)({});
|
|
6350
8857
|
const [loadingPrompts, setLoadingPrompts] = (0, import_react16.useState)(/* @__PURE__ */ new Set());
|
|
6351
8858
|
const [loadingConversationId, setLoadingConversationId] = (0, import_react16.useState)(null);
|
|
@@ -6365,6 +8872,7 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6365
8872
|
agentList
|
|
6366
8873
|
} = useAgentRegistry(agentIds, { url, localOverrides });
|
|
6367
8874
|
const fetchInProgressRef = (0, import_react16.useRef)(false);
|
|
8875
|
+
const loadingTranscriptIdsRef = (0, import_react16.useRef)(/* @__PURE__ */ new Set());
|
|
6368
8876
|
const lastFetchedAgentRef = (0, import_react16.useRef)(null);
|
|
6369
8877
|
const checkedPromptsRef = (0, import_react16.useRef)(/* @__PURE__ */ new Set());
|
|
6370
8878
|
const fetchingPromptsRef = (0, import_react16.useRef)(/* @__PURE__ */ new Set());
|
|
@@ -6373,29 +8881,49 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6373
8881
|
activeConversationsRef.current = activeConversations;
|
|
6374
8882
|
const currentConversationIdRef = (0, import_react16.useRef)(currentConversationId);
|
|
6375
8883
|
currentConversationIdRef.current = currentConversationId;
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
const
|
|
8884
|
+
const commitConversationSelection = (0, import_react16.useCallback)(
|
|
8885
|
+
(conversationId, notifyChange) => {
|
|
8886
|
+
const shouldSyncLocalState = !isConversationControlled || !notifyChange || controlledConversationId === conversationId;
|
|
8887
|
+
if (shouldSyncLocalState) {
|
|
8888
|
+
setCurrentConversationId(conversationId);
|
|
8889
|
+
}
|
|
8890
|
+
if (notifyChange && conversationId && onConversationChange) {
|
|
8891
|
+
const shouldNotifyParent = !isConversationControlled || controlledConversationId !== conversationId;
|
|
8892
|
+
if (shouldNotifyParent) {
|
|
8893
|
+
onConversationChange(conversationId);
|
|
8894
|
+
}
|
|
8895
|
+
}
|
|
8896
|
+
},
|
|
8897
|
+
[controlledConversationId, isConversationControlled, onConversationChange]
|
|
8898
|
+
);
|
|
8899
|
+
const createDraftConversation = (0, import_react16.useCallback)(
|
|
8900
|
+
(agentId, conversationInitialPrompt) => {
|
|
6379
8901
|
const tempId = `new-${Date.now()}`;
|
|
6380
8902
|
setActiveConversations((prev) => {
|
|
6381
8903
|
const next = new Map(prev);
|
|
6382
8904
|
next.set(tempId, {
|
|
6383
8905
|
conversationId: tempId,
|
|
6384
8906
|
stableKey: tempId,
|
|
6385
|
-
agentId
|
|
8907
|
+
agentId,
|
|
6386
8908
|
history: {},
|
|
8909
|
+
transcriptLoaded: true,
|
|
6387
8910
|
isLoading: false,
|
|
6388
8911
|
title: "New conversation",
|
|
6389
|
-
conversationInitialPrompt
|
|
8912
|
+
conversationInitialPrompt
|
|
6390
8913
|
});
|
|
6391
8914
|
return next;
|
|
6392
8915
|
});
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
8916
|
+
return tempId;
|
|
8917
|
+
},
|
|
8918
|
+
[]
|
|
8919
|
+
);
|
|
8920
|
+
import_react16.default.useImperativeHandle(ref, () => ({
|
|
8921
|
+
startNewConversation: (prompt, agent) => {
|
|
8922
|
+
const targetAgent = agent || currentAgentId;
|
|
8923
|
+
const tempId = createDraftConversation(targetAgent, prompt);
|
|
8924
|
+
commitConversationSelection(tempId, true);
|
|
6397
8925
|
}
|
|
6398
|
-
}), [
|
|
8926
|
+
}), [commitConversationSelection, createDraftConversation, currentAgentId]);
|
|
6399
8927
|
const [showContextNotification, setShowContextNotification] = (0, import_react16.useState)(false);
|
|
6400
8928
|
const prevContextRef = (0, import_react16.useRef)(null);
|
|
6401
8929
|
const contextNotificationTimeoutRef = (0, import_react16.useRef)(null);
|
|
@@ -6537,14 +9065,15 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6537
9065
|
}
|
|
6538
9066
|
}
|
|
6539
9067
|
}), [apiKey, customerId, getAgent, fetchFirstPrompt]);
|
|
6540
|
-
const loadConversationTranscript = (0, import_react16.useCallback)((conversationId, agentIdForConversation, title) => __async(void 0, null, function* () {
|
|
9068
|
+
const loadConversationTranscript = (0, import_react16.useCallback)((conversationId, agentIdForConversation, title, notifyConversationChange = true) => __async(void 0, null, function* () {
|
|
6541
9069
|
var _a2;
|
|
6542
9070
|
const existingActive = activeConversationsRef.current.get(conversationId);
|
|
6543
|
-
if (existingActive) {
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
9071
|
+
if (existingActive && (existingActive.transcriptLoaded || Object.keys(existingActive.history || {}).length > 0)) {
|
|
9072
|
+
commitConversationSelection(conversationId, notifyConversationChange);
|
|
9073
|
+
return;
|
|
9074
|
+
}
|
|
9075
|
+
if (loadingTranscriptIdsRef.current.has(conversationId)) {
|
|
9076
|
+
commitConversationSelection(conversationId, notifyConversationChange);
|
|
6548
9077
|
return;
|
|
6549
9078
|
}
|
|
6550
9079
|
const agentIdToUse = agentIdForConversation || currentAgentId;
|
|
@@ -6554,6 +9083,8 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6554
9083
|
setConversationsError("Missing API key or project ID");
|
|
6555
9084
|
return;
|
|
6556
9085
|
}
|
|
9086
|
+
loadingTranscriptIdsRef.current.add(conversationId);
|
|
9087
|
+
setConversationsError(null);
|
|
6557
9088
|
setLoadingConversationId(conversationId);
|
|
6558
9089
|
try {
|
|
6559
9090
|
console.log("loadConversationTranscript - conversationId:", conversationId);
|
|
@@ -6566,57 +9097,34 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6566
9097
|
}
|
|
6567
9098
|
});
|
|
6568
9099
|
if (!response.ok) {
|
|
9100
|
+
if (response.status === 404) {
|
|
9101
|
+
const conversationTitle2 = title || conversationFirstPrompts[conversationId] || "New conversation";
|
|
9102
|
+
setActiveConversations((prev) => {
|
|
9103
|
+
const next = new Map(prev);
|
|
9104
|
+
next.set(conversationId, {
|
|
9105
|
+
conversationId,
|
|
9106
|
+
stableKey: conversationId,
|
|
9107
|
+
agentId: agentIdToUse,
|
|
9108
|
+
history: {},
|
|
9109
|
+
transcriptLoaded: true,
|
|
9110
|
+
isLoading: false,
|
|
9111
|
+
title: conversationTitle2
|
|
9112
|
+
});
|
|
9113
|
+
return next;
|
|
9114
|
+
});
|
|
9115
|
+
commitConversationSelection(conversationId, notifyConversationChange);
|
|
9116
|
+
return;
|
|
9117
|
+
}
|
|
6569
9118
|
throw new Error(`Failed to load conversation (${response.status})`);
|
|
6570
9119
|
}
|
|
6571
9120
|
const payload = yield response.json();
|
|
6572
9121
|
console.log("loadConversationTranscript - API response:", payload);
|
|
6573
|
-
const
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
if (lastCall.messages) {
|
|
6580
|
-
try {
|
|
6581
|
-
const messages2 = JSON.parse(lastCall.messages);
|
|
6582
|
-
console.log("loadConversationTranscript - parsed messages:", messages2);
|
|
6583
|
-
const relevantMessages = messages2.filter(
|
|
6584
|
-
(msg) => msg.role !== "system" && !(msg.role === "user" && msg.content.startsWith("__system__:"))
|
|
6585
|
-
);
|
|
6586
|
-
console.log("loadConversationTranscript - filtered messages:", relevantMessages);
|
|
6587
|
-
for (let i = 0; i < relevantMessages.length; i++) {
|
|
6588
|
-
const msg = relevantMessages[i];
|
|
6589
|
-
if (!msg) continue;
|
|
6590
|
-
if (msg.role === "user") {
|
|
6591
|
-
if (!firstPrompt) {
|
|
6592
|
-
firstPrompt = msg.content.length > 60 ? msg.content.slice(0, 57) + "..." : msg.content;
|
|
6593
|
-
}
|
|
6594
|
-
const nextMsg = relevantMessages[i + 1];
|
|
6595
|
-
if (nextMsg && nextMsg.role === "assistant") {
|
|
6596
|
-
const historyKey = `${timestamp}:${msg.content}`;
|
|
6597
|
-
history[historyKey] = {
|
|
6598
|
-
content: nextMsg.content,
|
|
6599
|
-
callId
|
|
6600
|
-
};
|
|
6601
|
-
i++;
|
|
6602
|
-
} else {
|
|
6603
|
-
if (lastCall.response) {
|
|
6604
|
-
const historyKey = `${timestamp}:${msg.content}`;
|
|
6605
|
-
history[historyKey] = {
|
|
6606
|
-
content: lastCall.response,
|
|
6607
|
-
callId
|
|
6608
|
-
};
|
|
6609
|
-
}
|
|
6610
|
-
}
|
|
6611
|
-
}
|
|
6612
|
-
}
|
|
6613
|
-
} catch (err) {
|
|
6614
|
-
console.error("loadConversationTranscript - failed to parse messages property:", err);
|
|
6615
|
-
}
|
|
6616
|
-
}
|
|
6617
|
-
}
|
|
6618
|
-
console.log("loadConversationTranscript - created", Object.keys(history).length, "history entries");
|
|
6619
|
-
console.log("loadConversationTranscript - parsed history:", history);
|
|
9122
|
+
const calls = normalizeCallsPayload(payload);
|
|
9123
|
+
const transcriptTurns = buildTranscriptTurnsFromCalls(calls);
|
|
9124
|
+
const history = buildHistoryFromTranscriptTurns(transcriptTurns);
|
|
9125
|
+
const firstPrompt = transcriptTurns.length > 0 ? truncatePromptForTitle(transcriptTurns[0].prompt) : null;
|
|
9126
|
+
console.log("loadConversationTranscript - parsed calls:", calls.length);
|
|
9127
|
+
console.log("loadConversationTranscript - created history entries:", Object.keys(history).length);
|
|
6620
9128
|
if (firstPrompt) {
|
|
6621
9129
|
setConversationFirstPrompts((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
6622
9130
|
[conversationId]: firstPrompt
|
|
@@ -6631,22 +9139,85 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6631
9139
|
// Use real ID as stable key when loading from API
|
|
6632
9140
|
agentId: agentIdToUse,
|
|
6633
9141
|
history,
|
|
9142
|
+
transcriptLoaded: true,
|
|
6634
9143
|
isLoading: false,
|
|
6635
9144
|
title: conversationTitle
|
|
6636
9145
|
});
|
|
6637
9146
|
return next;
|
|
6638
9147
|
});
|
|
6639
|
-
|
|
6640
|
-
if (onConversationChange) {
|
|
6641
|
-
onConversationChange(conversationId);
|
|
6642
|
-
}
|
|
6643
|
-
setLoadingConversationId(null);
|
|
9148
|
+
commitConversationSelection(conversationId, notifyConversationChange);
|
|
6644
9149
|
} catch (error) {
|
|
6645
9150
|
console.error("Failed to load conversation:", error);
|
|
6646
9151
|
setConversationsError(error.message || "Failed to load conversation");
|
|
6647
|
-
|
|
9152
|
+
} finally {
|
|
9153
|
+
loadingTranscriptIdsRef.current.delete(conversationId);
|
|
9154
|
+
setLoadingConversationId((prev) => prev === conversationId ? null : prev);
|
|
9155
|
+
}
|
|
9156
|
+
}), [apiKey, commitConversationSelection, conversationFirstPrompts, currentAgentId, getAgent]);
|
|
9157
|
+
(0, import_react16.useEffect)(() => {
|
|
9158
|
+
if (!isConversationControlled) return;
|
|
9159
|
+
const targetConversationId = controlledConversationId;
|
|
9160
|
+
if (!targetConversationId) {
|
|
9161
|
+
if (currentConversationIdRef.current !== null) {
|
|
9162
|
+
setCurrentConversationId(null);
|
|
9163
|
+
}
|
|
9164
|
+
return;
|
|
9165
|
+
}
|
|
9166
|
+
if (targetConversationId.startsWith("new-")) {
|
|
9167
|
+
setActiveConversations((prev) => {
|
|
9168
|
+
if (prev.has(targetConversationId)) {
|
|
9169
|
+
return prev;
|
|
9170
|
+
}
|
|
9171
|
+
const next = new Map(prev);
|
|
9172
|
+
next.set(targetConversationId, {
|
|
9173
|
+
conversationId: targetConversationId,
|
|
9174
|
+
stableKey: targetConversationId,
|
|
9175
|
+
agentId: currentAgentId,
|
|
9176
|
+
history: {},
|
|
9177
|
+
transcriptLoaded: true,
|
|
9178
|
+
isLoading: false,
|
|
9179
|
+
title: "New conversation"
|
|
9180
|
+
});
|
|
9181
|
+
return next;
|
|
9182
|
+
});
|
|
9183
|
+
if (currentConversationIdRef.current !== targetConversationId) {
|
|
9184
|
+
setCurrentConversationId(targetConversationId);
|
|
9185
|
+
}
|
|
9186
|
+
return;
|
|
9187
|
+
}
|
|
9188
|
+
if (loadingConversationId === targetConversationId) {
|
|
9189
|
+
return;
|
|
9190
|
+
}
|
|
9191
|
+
const existingActive = activeConversationsRef.current.get(targetConversationId);
|
|
9192
|
+
if (existingActive && existingActive.transcriptLoaded && currentConversationIdRef.current === targetConversationId) {
|
|
9193
|
+
return;
|
|
9194
|
+
}
|
|
9195
|
+
const apiConversation = apiConversations.find(
|
|
9196
|
+
(conv) => conv.conversationId === targetConversationId
|
|
9197
|
+
);
|
|
9198
|
+
const targetAgentId = (apiConversation == null ? void 0 : apiConversation.agentId) || (existingActive == null ? void 0 : existingActive.agentId) || currentAgentId;
|
|
9199
|
+
if (!targetAgentId) {
|
|
9200
|
+
return;
|
|
9201
|
+
}
|
|
9202
|
+
if (targetAgentId !== currentAgentId) {
|
|
9203
|
+
setCurrentAgentId(targetAgentId);
|
|
6648
9204
|
}
|
|
6649
|
-
|
|
9205
|
+
const targetTitle = conversationFirstPrompts[targetConversationId] || (apiConversation == null ? void 0 : apiConversation.title) || (existingActive == null ? void 0 : existingActive.title);
|
|
9206
|
+
void loadConversationTranscript(
|
|
9207
|
+
targetConversationId,
|
|
9208
|
+
targetAgentId,
|
|
9209
|
+
targetTitle,
|
|
9210
|
+
false
|
|
9211
|
+
);
|
|
9212
|
+
}, [
|
|
9213
|
+
apiConversations,
|
|
9214
|
+
controlledConversationId,
|
|
9215
|
+
conversationFirstPrompts,
|
|
9216
|
+
currentAgentId,
|
|
9217
|
+
isConversationControlled,
|
|
9218
|
+
loadConversationTranscript,
|
|
9219
|
+
loadingConversationId
|
|
9220
|
+
]);
|
|
6650
9221
|
const handleRefreshConversations = (0, import_react16.useCallback)(() => {
|
|
6651
9222
|
fetchConversations(currentAgentId);
|
|
6652
9223
|
}, [currentAgentId, fetchConversations]);
|
|
@@ -6663,30 +9234,18 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6663
9234
|
}
|
|
6664
9235
|
}, [agentsLoading, currentAgentId, apiKey, fetchConversations, getAgent, showConversationHistory]);
|
|
6665
9236
|
const handleNewConversation = (0, import_react16.useCallback)(() => {
|
|
6666
|
-
const tempId =
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
next.set(tempId, {
|
|
6670
|
-
conversationId: tempId,
|
|
6671
|
-
stableKey: tempId,
|
|
6672
|
-
// Stable key never changes even when conversationId updates
|
|
6673
|
-
agentId: currentAgentId,
|
|
6674
|
-
history: {},
|
|
6675
|
-
isLoading: false,
|
|
6676
|
-
title: "New conversation"
|
|
6677
|
-
});
|
|
6678
|
-
return next;
|
|
6679
|
-
});
|
|
6680
|
-
setCurrentConversationId(tempId);
|
|
6681
|
-
}, [currentAgentId]);
|
|
9237
|
+
const tempId = createDraftConversation(currentAgentId);
|
|
9238
|
+
commitConversationSelection(tempId, true);
|
|
9239
|
+
}, [commitConversationSelection, createDraftConversation, currentAgentId]);
|
|
6682
9240
|
(0, import_react16.useEffect)(() => {
|
|
6683
9241
|
var _a2;
|
|
9242
|
+
if (isConversationControlled) return;
|
|
6684
9243
|
const agentProfile = getAgent(currentAgentId);
|
|
6685
9244
|
const isAgentReady = (_a2 = agentProfile == null ? void 0 : agentProfile.metadata) == null ? void 0 : _a2.projectId;
|
|
6686
9245
|
if (isAgentReady && !agentsLoading && activeConversations.size === 0) {
|
|
6687
9246
|
handleNewConversation();
|
|
6688
9247
|
}
|
|
6689
|
-
}, [currentAgentId, agentsLoading, activeConversations.size, getAgent, handleNewConversation]);
|
|
9248
|
+
}, [currentAgentId, agentsLoading, activeConversations.size, getAgent, handleNewConversation, isConversationControlled]);
|
|
6690
9249
|
const handleCloseConversation = (0, import_react16.useCallback)((conversationId, e) => {
|
|
6691
9250
|
var _a2;
|
|
6692
9251
|
if (e) {
|
|
@@ -6700,9 +9259,13 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
6700
9259
|
if (currentConversationIdRef.current === conversationId) {
|
|
6701
9260
|
const remaining = Array.from(activeConversationsRef.current.keys()).filter((id) => id !== conversationId);
|
|
6702
9261
|
const nextId = remaining.length > 0 ? (_a2 = remaining[0]) != null ? _a2 : null : null;
|
|
6703
|
-
|
|
9262
|
+
if (nextId) {
|
|
9263
|
+
commitConversationSelection(nextId, true);
|
|
9264
|
+
} else if (!isConversationControlled) {
|
|
9265
|
+
setCurrentConversationId(null);
|
|
9266
|
+
}
|
|
6704
9267
|
}
|
|
6705
|
-
}, []);
|
|
9268
|
+
}, [commitConversationSelection, isConversationControlled]);
|
|
6706
9269
|
const handleSelectConversation = (0, import_react16.useCallback)((conversationId) => {
|
|
6707
9270
|
loadConversationTranscript(conversationId);
|
|
6708
9271
|
}, [loadConversationTranscript]);
|
|
@@ -7003,6 +9566,7 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
7003
9566
|
}
|
|
7004
9567
|
next.set(targetConversationId, __spreadProps(__spreadValues({}, existing), {
|
|
7005
9568
|
history,
|
|
9569
|
+
transcriptLoaded: true,
|
|
7006
9570
|
title
|
|
7007
9571
|
}));
|
|
7008
9572
|
return next;
|
|
@@ -7092,26 +9656,23 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
7092
9656
|
return prev;
|
|
7093
9657
|
});
|
|
7094
9658
|
if (currentConversationIdRef.current === tempId) {
|
|
7095
|
-
|
|
7096
|
-
if (onConversationChange) {
|
|
7097
|
-
onConversationChange(realId);
|
|
7098
|
-
}
|
|
9659
|
+
commitConversationSelection(realId, true);
|
|
7099
9660
|
}
|
|
7100
|
-
}, [
|
|
9661
|
+
}, [commitConversationSelection]);
|
|
7101
9662
|
const toggleCollapse = (0, import_react16.useCallback)(() => {
|
|
7102
9663
|
if (!collapsible) return;
|
|
7103
9664
|
const newValue = !isCollapsed;
|
|
9665
|
+
if (!newValue) {
|
|
9666
|
+
setIsHistoryCollapsed(true);
|
|
9667
|
+
setShowSearch(false);
|
|
9668
|
+
}
|
|
7104
9669
|
if (!isControlled) {
|
|
7105
9670
|
setUncontrolledIsCollapsed(newValue);
|
|
7106
9671
|
}
|
|
7107
9672
|
onCollapsedChange == null ? void 0 : onCollapsedChange(newValue);
|
|
7108
9673
|
}, [collapsible, isCollapsed, isControlled, onCollapsedChange]);
|
|
7109
9674
|
const toggleHistoryCollapse = (0, import_react16.useCallback)(() => {
|
|
7110
|
-
setIsHistoryCollapsed((prev) =>
|
|
7111
|
-
const next = !prev;
|
|
7112
|
-
localStorage.setItem("ai-agent-panel-history-collapsed", String(next));
|
|
7113
|
-
return next;
|
|
7114
|
-
});
|
|
9675
|
+
setIsHistoryCollapsed((prev) => !prev);
|
|
7115
9676
|
}, []);
|
|
7116
9677
|
const panelClasses = [
|
|
7117
9678
|
"ai-agent-panel",
|
|
@@ -7183,27 +9744,11 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
7183
9744
|
}
|
|
7184
9745
|
onCollapsedChange == null ? void 0 : onCollapsedChange(false);
|
|
7185
9746
|
if (hasActiveConversation && activeConvForAgent) {
|
|
7186
|
-
setCurrentConversationId(activeConvForAgent.conversationId);
|
|
7187
9747
|
setCurrentAgentId(agent.id);
|
|
7188
|
-
|
|
7189
|
-
onConversationChange(activeConvForAgent.conversationId);
|
|
7190
|
-
}
|
|
9748
|
+
commitConversationSelection(activeConvForAgent.conversationId, true);
|
|
7191
9749
|
} else {
|
|
7192
|
-
const tempId =
|
|
7193
|
-
|
|
7194
|
-
const next = new Map(prev);
|
|
7195
|
-
next.set(tempId, {
|
|
7196
|
-
conversationId: tempId,
|
|
7197
|
-
stableKey: tempId,
|
|
7198
|
-
// Stable key never changes
|
|
7199
|
-
agentId: agent.id,
|
|
7200
|
-
history: {},
|
|
7201
|
-
isLoading: false,
|
|
7202
|
-
title: "New conversation"
|
|
7203
|
-
});
|
|
7204
|
-
return next;
|
|
7205
|
-
});
|
|
7206
|
-
setCurrentConversationId(tempId);
|
|
9750
|
+
const tempId = createDraftConversation(agent.id);
|
|
9751
|
+
commitConversationSelection(tempId, true);
|
|
7207
9752
|
setCurrentAgentId(agent.id);
|
|
7208
9753
|
}
|
|
7209
9754
|
},
|
|
@@ -7288,27 +9833,11 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
7288
9833
|
title: agent.name,
|
|
7289
9834
|
onClick: () => {
|
|
7290
9835
|
if (hasActiveConversation && activeConvForAgent) {
|
|
7291
|
-
setCurrentConversationId(activeConvForAgent.conversationId);
|
|
7292
9836
|
setCurrentAgentId(agent.id);
|
|
7293
|
-
|
|
7294
|
-
onConversationChange(activeConvForAgent.conversationId);
|
|
7295
|
-
}
|
|
9837
|
+
commitConversationSelection(activeConvForAgent.conversationId, true);
|
|
7296
9838
|
} else {
|
|
7297
|
-
const tempId =
|
|
7298
|
-
|
|
7299
|
-
const next = new Map(prev);
|
|
7300
|
-
next.set(tempId, {
|
|
7301
|
-
conversationId: tempId,
|
|
7302
|
-
stableKey: tempId,
|
|
7303
|
-
// Stable key never changes
|
|
7304
|
-
agentId: agent.id,
|
|
7305
|
-
history: {},
|
|
7306
|
-
isLoading: false,
|
|
7307
|
-
title: "New conversation"
|
|
7308
|
-
});
|
|
7309
|
-
return next;
|
|
7310
|
-
});
|
|
7311
|
-
setCurrentConversationId(tempId);
|
|
9839
|
+
const tempId = createDraftConversation(agent.id);
|
|
9840
|
+
commitConversationSelection(tempId, true);
|
|
7312
9841
|
setCurrentAgentId(agent.id);
|
|
7313
9842
|
}
|
|
7314
9843
|
},
|
|
@@ -7361,10 +9890,7 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
7361
9890
|
key: activeConv.stableKey,
|
|
7362
9891
|
className: `ai-agent-panel__conversation ai-agent-panel__conversation--active-item ${currentConversationId === activeConv.conversationId ? "ai-agent-panel__conversation--current" : ""}`,
|
|
7363
9892
|
onClick: () => {
|
|
7364
|
-
|
|
7365
|
-
if (onConversationChange) {
|
|
7366
|
-
onConversationChange(activeConv.conversationId);
|
|
7367
|
-
}
|
|
9893
|
+
commitConversationSelection(activeConv.conversationId, true);
|
|
7368
9894
|
}
|
|
7369
9895
|
},
|
|
7370
9896
|
/* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__conversation-content" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__conversation-title" }, activeConv.isLoading && /* @__PURE__ */ import_react16.default.createElement(LoadingDotIcon, null), /* @__PURE__ */ import_react16.default.createElement("span", null, activeConv.title))),
|
|
@@ -7385,12 +9911,12 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
7385
9911
|
},
|
|
7386
9912
|
/* @__PURE__ */ import_react16.default.createElement("span", null, group.label, " ", group.count > 0 && `(${group.count})`),
|
|
7387
9913
|
/* @__PURE__ */ import_react16.default.createElement("span", { className: "ai-agent-panel__group-chevron" }, expandedSections[group.label] ? "\u25BC" : "\u25B6")
|
|
7388
|
-
), expandedSections[group.label] && group.conversations.length > 0 && group.conversations.map((conv) => {
|
|
9914
|
+
), expandedSections[group.label] && group.conversations.length > 0 && group.conversations.map((conv, convIndex) => {
|
|
7389
9915
|
const isActive = activeConversations.has(conv.conversationId);
|
|
7390
9916
|
return /* @__PURE__ */ import_react16.default.createElement(
|
|
7391
9917
|
"div",
|
|
7392
9918
|
{
|
|
7393
|
-
key: conv.conversationId
|
|
9919
|
+
key: `${group.label}-${conv.conversationId}-${convIndex}`,
|
|
7394
9920
|
className: `ai-agent-panel__conversation ${currentConversationId === conv.conversationId ? "ai-agent-panel__conversation--current" : ""} ${isActive ? "ai-agent-panel__conversation--in-active" : ""}`,
|
|
7395
9921
|
onClick: () => handleConversationSelect(conv)
|
|
7396
9922
|
},
|
|
@@ -7400,7 +9926,7 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
7400
9926
|
/* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__chat" }, !showConversationHistory && collapsible && /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__chat-header" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__chat-header-spacer" }), /* @__PURE__ */ import_react16.default.createElement(Tooltip, { content: "Collapse Panel", side: position === "right" ? "left" : "right" }, /* @__PURE__ */ import_react16.default.createElement(Button, { variant: "ghost", size: "icon", onClick: toggleCollapse }, position === "right" ? /* @__PURE__ */ import_react16.default.createElement(ChevronRightIcon, null) : /* @__PURE__ */ import_react16.default.createElement(ChevronLeftIcon, null)))), showContextNotification && /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__context-notification" }, /* @__PURE__ */ import_react16.default.createElement(SparkleIcon, null), /* @__PURE__ */ import_react16.default.createElement("span", null, "Agent now has new context")), activeConversationsList.map((activeConv) => /* @__PURE__ */ import_react16.default.createElement(
|
|
7401
9927
|
ChatPanelWrapper,
|
|
7402
9928
|
{
|
|
7403
|
-
key:
|
|
9929
|
+
key: activeConv.stableKey,
|
|
7404
9930
|
activeConv,
|
|
7405
9931
|
currentConversationId,
|
|
7406
9932
|
getAgent,
|
|
@@ -7431,6 +9957,7 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
7431
9957
|
disabledSectionIds: currentDisabledSections,
|
|
7432
9958
|
onToggleSection: handleContextSectionToggle,
|
|
7433
9959
|
onConversationCreated: handleConversationCreated,
|
|
9960
|
+
onBeforeSend,
|
|
7434
9961
|
conversationInitialPrompt: activeConv.conversationInitialPrompt,
|
|
7435
9962
|
cssUrl,
|
|
7436
9963
|
markdownClass,
|
|
@@ -7446,7 +9973,11 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
7446
9973
|
callToActionEmailAddress,
|
|
7447
9974
|
callToActionEmailSubject,
|
|
7448
9975
|
customerEmailCaptureMode,
|
|
7449
|
-
customerEmailCapturePlaceholder
|
|
9976
|
+
customerEmailCapturePlaceholder,
|
|
9977
|
+
resolveMcpAuthHeaders,
|
|
9978
|
+
localToolExecutors,
|
|
9979
|
+
traceContextMode,
|
|
9980
|
+
autoApproveTools
|
|
7450
9981
|
}
|
|
7451
9982
|
)), loadingConversationId && /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__conversation-loading-overlay" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__loading-spinner" }), /* @__PURE__ */ import_react16.default.createElement("p", null, "Loading conversation...")), currentAgentMetadata && activeConversationsList.length === 0 && !loadingConversationId && /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__empty-chat" }, /* @__PURE__ */ import_react16.default.createElement(MessageIcon, null), /* @__PURE__ */ import_react16.default.createElement("p", null, "Select a conversation or start a new one"), /* @__PURE__ */ import_react16.default.createElement(Button, { variant: "default", size: "sm", onClick: handleNewConversation }, "New Conversation")), agentsLoading && !currentAgentMetadata && /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__loading" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__loading-spinner" }), /* @__PURE__ */ import_react16.default.createElement("p", null, "Loading agent..."))),
|
|
7452
9983
|
/* @__PURE__ */ import_react16.default.createElement(
|