@hef2024/llmasaservice-ui 0.22.9 → 0.22.11
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/CONTROLLED-COLLAPSE-IMPLEMENTATION.md +2 -0
- package/dist/index.css +51 -47
- package/dist/index.js +71 -18
- package/dist/index.mjs +71 -18
- package/docs/CONTROLLED-COLLAPSE-QUICK-START.md +2 -0
- package/docs/CONTROLLED-COLLAPSE-STATE.md +2 -0
- package/package.json +1 -1
- package/src/AIAgentPanel.css +52 -47
- package/src/AIChatPanel.css +1 -1
- package/src/AIChatPanel.tsx +112 -24
|
@@ -272,3 +272,5 @@ For questions or issues:
|
|
|
272
272
|
|
|
273
273
|
The controlled collapse state feature is now fully implemented, documented, and tested. It follows React best practices, maintains backward compatibility, and provides a flexible solution for persisting panel state across page navigations.
|
|
274
274
|
|
|
275
|
+
|
|
276
|
+
|
package/dist/index.css
CHANGED
|
@@ -997,12 +997,12 @@ button[data-pending=true]::after {
|
|
|
997
997
|
--ai-panel-collapsed-width: 48px;
|
|
998
998
|
--ai-panel-border-radius: 0;
|
|
999
999
|
--ai-panel-transition: 0.2s ease;
|
|
1000
|
-
--ai-sidebar-bg: #
|
|
1000
|
+
--ai-sidebar-bg: #ffffff;
|
|
1001
1001
|
--ai-sidebar-border: #e5e7eb;
|
|
1002
|
-
--ai-sidebar-text: #
|
|
1002
|
+
--ai-sidebar-text: #111827;
|
|
1003
1003
|
--ai-sidebar-text-muted: #6b7280;
|
|
1004
|
-
--ai-sidebar-hover: #
|
|
1005
|
-
--ai-sidebar-active: #
|
|
1004
|
+
--ai-sidebar-hover: #f9fafb;
|
|
1005
|
+
--ai-sidebar-active: #f3f4f6;
|
|
1006
1006
|
--ai-header-bg: #ffffff;
|
|
1007
1007
|
--ai-header-border: #e5e7eb;
|
|
1008
1008
|
--ai-header-height: 52px;
|
|
@@ -1011,13 +1011,13 @@ button[data-pending=true]::after {
|
|
|
1011
1011
|
--ai-agent-selector-bg: #ffffff;
|
|
1012
1012
|
--ai-agent-selector-border: #e5e7eb;
|
|
1013
1013
|
--ai-conversation-bg: transparent;
|
|
1014
|
-
--ai-conversation-hover: rgba(0, 0, 0, 0.
|
|
1015
|
-
--ai-conversation-active: rgba(0, 0, 0, 0.
|
|
1014
|
+
--ai-conversation-hover: rgba(0, 0, 0, 0.03);
|
|
1015
|
+
--ai-conversation-active: rgba(0, 0, 0, 0.05);
|
|
1016
1016
|
--ai-conversation-title-color: #1f2937;
|
|
1017
1017
|
--ai-conversation-preview-color: #6b7280;
|
|
1018
1018
|
--ai-conversation-meta-color: #9ca3af;
|
|
1019
|
-
--ai-group-label-color: #
|
|
1020
|
-
--ai-group-label-size: 0.
|
|
1019
|
+
--ai-group-label-color: #6b7280;
|
|
1020
|
+
--ai-group-label-size: 0.6875rem;
|
|
1021
1021
|
--ai-button-primary-bg: #3b82f6;
|
|
1022
1022
|
--ai-button-primary-text: #ffffff;
|
|
1023
1023
|
--ai-button-primary-hover: #2563eb;
|
|
@@ -1025,18 +1025,18 @@ button[data-pending=true]::after {
|
|
|
1025
1025
|
--ai-button-secondary-text: #374151;
|
|
1026
1026
|
--ai-button-secondary-border: #d1d5db;
|
|
1027
1027
|
--ai-button-secondary-hover: #e5e7eb;
|
|
1028
|
-
--ai-button-ghost-hover:
|
|
1028
|
+
--ai-button-ghost-hover: #f3f4f6;
|
|
1029
1029
|
--ai-button-destructive-bg: #ef4444;
|
|
1030
1030
|
--ai-button-destructive-text: #ffffff;
|
|
1031
1031
|
--ai-button-destructive-hover: #dc2626;
|
|
1032
|
-
--ai-button-radius:
|
|
1032
|
+
--ai-button-radius: 4px;
|
|
1033
1033
|
--ai-input-bg: #ffffff;
|
|
1034
1034
|
--ai-input-border: #d1d5db;
|
|
1035
1035
|
--ai-input-text: #1f2937;
|
|
1036
1036
|
--ai-input-placeholder: #9ca3af;
|
|
1037
1037
|
--ai-input-focus-border: #3b82f6;
|
|
1038
1038
|
--ai-input-focus-ring: rgba(59, 130, 246, 0.2);
|
|
1039
|
-
--ai-input-radius:
|
|
1039
|
+
--ai-input-radius: 4px;
|
|
1040
1040
|
--ai-select-bg: #ffffff;
|
|
1041
1041
|
--ai-select-border: #d1d5db;
|
|
1042
1042
|
--ai-select-text: #1f2937;
|
|
@@ -1067,21 +1067,21 @@ button[data-pending=true]::after {
|
|
|
1067
1067
|
--ai-chat-bg: #ffffff;
|
|
1068
1068
|
}
|
|
1069
1069
|
.dark-theme {
|
|
1070
|
-
--ai-sidebar-bg: #
|
|
1071
|
-
--ai-sidebar-border: #
|
|
1070
|
+
--ai-sidebar-bg: #111827;
|
|
1071
|
+
--ai-sidebar-border: #1f2937;
|
|
1072
1072
|
--ai-sidebar-text: #f3f4f6;
|
|
1073
1073
|
--ai-sidebar-text-muted: #9ca3af;
|
|
1074
|
-
--ai-sidebar-hover: #
|
|
1075
|
-
--ai-sidebar-active: #
|
|
1076
|
-
--ai-header-bg: #
|
|
1077
|
-
--ai-header-border: #
|
|
1074
|
+
--ai-sidebar-hover: #1f2937;
|
|
1075
|
+
--ai-sidebar-active: #374151;
|
|
1076
|
+
--ai-header-bg: #0d1117;
|
|
1077
|
+
--ai-header-border: #1f2937;
|
|
1078
1078
|
--ai-agent-badge-bg: #1e3a5f;
|
|
1079
1079
|
--ai-agent-badge-text: #60a5fa;
|
|
1080
1080
|
--ai-agent-selector-bg: #1f2937;
|
|
1081
1081
|
--ai-agent-selector-border: #374151;
|
|
1082
|
-
--ai-conversation-hover: rgba(255, 255, 255, 0.
|
|
1082
|
+
--ai-conversation-hover: rgba(255, 255, 255, 0.05);
|
|
1083
1083
|
--ai-conversation-active: rgba(255, 255, 255, 0.08);
|
|
1084
|
-
--ai-conversation-title-color: #
|
|
1084
|
+
--ai-conversation-title-color: #e5e7eb;
|
|
1085
1085
|
--ai-conversation-preview-color: #9ca3af;
|
|
1086
1086
|
--ai-conversation-meta-color: #6b7280;
|
|
1087
1087
|
--ai-group-label-color: #6b7280;
|
|
@@ -1092,7 +1092,7 @@ button[data-pending=true]::after {
|
|
|
1092
1092
|
--ai-button-secondary-text: #f3f4f6;
|
|
1093
1093
|
--ai-button-secondary-border: #4b5563;
|
|
1094
1094
|
--ai-button-secondary-hover: #4b5563;
|
|
1095
|
-
--ai-button-ghost-hover:
|
|
1095
|
+
--ai-button-ghost-hover: #1f2937;
|
|
1096
1096
|
--ai-input-bg: #1f2937;
|
|
1097
1097
|
--ai-input-border: #374151;
|
|
1098
1098
|
--ai-input-text: #f3f4f6;
|
|
@@ -1286,7 +1286,7 @@ button[data-pending=true]::after {
|
|
|
1286
1286
|
.ai-agent-panel__conversations {
|
|
1287
1287
|
flex: 1;
|
|
1288
1288
|
overflow-y: auto;
|
|
1289
|
-
padding: 8px;
|
|
1289
|
+
padding: 8px 0;
|
|
1290
1290
|
}
|
|
1291
1291
|
.ai-agent-panel__empty {
|
|
1292
1292
|
display: flex;
|
|
@@ -1312,15 +1312,15 @@ button[data-pending=true]::after {
|
|
|
1312
1312
|
opacity: 0.7;
|
|
1313
1313
|
}
|
|
1314
1314
|
.ai-agent-panel__group {
|
|
1315
|
-
margin-bottom:
|
|
1315
|
+
margin-bottom: 24px;
|
|
1316
1316
|
}
|
|
1317
1317
|
.ai-agent-panel__group-label {
|
|
1318
1318
|
font-size: var(--ai-group-label-size);
|
|
1319
|
-
font-weight:
|
|
1319
|
+
font-weight: 400;
|
|
1320
1320
|
color: var(--ai-group-label-color);
|
|
1321
1321
|
text-transform: uppercase;
|
|
1322
|
-
letter-spacing: 0.
|
|
1323
|
-
padding: 8px
|
|
1322
|
+
letter-spacing: 0.1em;
|
|
1323
|
+
padding: 8px 12px 4px;
|
|
1324
1324
|
}
|
|
1325
1325
|
.ai-agent-panel__group-label--clickable {
|
|
1326
1326
|
display: flex;
|
|
@@ -1328,10 +1328,10 @@ button[data-pending=true]::after {
|
|
|
1328
1328
|
justify-content: space-between;
|
|
1329
1329
|
cursor: pointer;
|
|
1330
1330
|
user-select: none;
|
|
1331
|
-
transition:
|
|
1331
|
+
transition: opacity 0.15s;
|
|
1332
1332
|
}
|
|
1333
1333
|
.ai-agent-panel__group-label--clickable:hover {
|
|
1334
|
-
|
|
1334
|
+
opacity: 0.7;
|
|
1335
1335
|
}
|
|
1336
1336
|
.ai-agent-panel__group-chevron {
|
|
1337
1337
|
font-size: 8px;
|
|
@@ -1344,10 +1344,11 @@ button[data-pending=true]::after {
|
|
|
1344
1344
|
.ai-agent-panel__conversation {
|
|
1345
1345
|
display: flex;
|
|
1346
1346
|
align-items: flex-start;
|
|
1347
|
-
padding:
|
|
1348
|
-
|
|
1347
|
+
padding: 6px 12px;
|
|
1348
|
+
margin: 0;
|
|
1349
|
+
border-radius: 0;
|
|
1349
1350
|
cursor: pointer;
|
|
1350
|
-
transition: background-color 0.
|
|
1351
|
+
transition: background-color 0.1s ease;
|
|
1351
1352
|
gap: 8px;
|
|
1352
1353
|
}
|
|
1353
1354
|
.ai-agent-panel__conversation:hover {
|
|
@@ -1362,12 +1363,12 @@ button[data-pending=true]::after {
|
|
|
1362
1363
|
}
|
|
1363
1364
|
.ai-agent-panel__conversation-title {
|
|
1364
1365
|
font-weight: 400;
|
|
1365
|
-
font-size:
|
|
1366
|
-
color: var(--ai-conversation-
|
|
1366
|
+
font-size: 13px;
|
|
1367
|
+
color: var(--ai-conversation-title-color);
|
|
1367
1368
|
white-space: nowrap;
|
|
1368
1369
|
overflow: hidden;
|
|
1369
1370
|
text-overflow: ellipsis;
|
|
1370
|
-
|
|
1371
|
+
line-height: 1.5;
|
|
1371
1372
|
}
|
|
1372
1373
|
.ai-agent-panel__conversation-preview {
|
|
1373
1374
|
font-size: 11px;
|
|
@@ -1908,22 +1909,25 @@ button[data-pending=true]::after {
|
|
|
1908
1909
|
}
|
|
1909
1910
|
}
|
|
1910
1911
|
.ai-agent-panel__group--active {
|
|
1911
|
-
|
|
1912
|
-
border-radius: 6px;
|
|
1913
|
-
margin-bottom: 8px;
|
|
1914
|
-
padding: 4px;
|
|
1912
|
+
margin-bottom: 24px;
|
|
1915
1913
|
}
|
|
1916
1914
|
.ai-agent-panel__group--active .ai-agent-panel__group-label {
|
|
1917
|
-
color: var(--ai-
|
|
1918
|
-
font-weight:
|
|
1915
|
+
color: var(--ai-group-label-color);
|
|
1916
|
+
font-weight: 400;
|
|
1917
|
+
padding: 8px 12px 4px;
|
|
1919
1918
|
}
|
|
1920
1919
|
.ai-agent-panel__conversation--active-item {
|
|
1921
1920
|
display: flex;
|
|
1922
1921
|
align-items: center;
|
|
1923
1922
|
justify-content: space-between;
|
|
1924
|
-
background-color:
|
|
1925
|
-
|
|
1926
|
-
margin:
|
|
1923
|
+
background-color: transparent;
|
|
1924
|
+
padding: 6px 12px;
|
|
1925
|
+
margin: 0;
|
|
1926
|
+
transition: background-color 0.1s ease;
|
|
1927
|
+
cursor: pointer;
|
|
1928
|
+
}
|
|
1929
|
+
.ai-agent-panel__conversation--active-item:hover {
|
|
1930
|
+
background-color: var(--ai-conversation-hover);
|
|
1927
1931
|
}
|
|
1928
1932
|
.ai-agent-panel__conversation--active-item .ai-agent-panel__conversation-content {
|
|
1929
1933
|
flex: 1;
|
|
@@ -1935,8 +1939,7 @@ button[data-pending=true]::after {
|
|
|
1935
1939
|
gap: 6px;
|
|
1936
1940
|
}
|
|
1937
1941
|
.ai-agent-panel__conversation--current {
|
|
1938
|
-
background-color:
|
|
1939
|
-
border-left: 2px solid var(--ai-button-primary-bg);
|
|
1942
|
+
background-color: rgba(59, 130, 246, 0.08) !important;
|
|
1940
1943
|
}
|
|
1941
1944
|
.ai-agent-panel__conversation--in-active {
|
|
1942
1945
|
opacity: 0.7;
|
|
@@ -1972,8 +1975,9 @@ button[data-pending=true]::after {
|
|
|
1972
1975
|
}
|
|
1973
1976
|
.ai-agent-panel__active-badge {
|
|
1974
1977
|
color: var(--ai-button-primary-bg);
|
|
1975
|
-
font-size:
|
|
1976
|
-
margin-right:
|
|
1978
|
+
font-size: 7px;
|
|
1979
|
+
margin-right: 4px;
|
|
1980
|
+
opacity: 0.8;
|
|
1977
1981
|
}
|
|
1978
1982
|
.ai-agent-panel__loading-dot {
|
|
1979
1983
|
display: inline-block;
|
|
@@ -1996,7 +2000,7 @@ button[data-pending=true]::after {
|
|
|
1996
2000
|
.ai-agent-panel__group-divider {
|
|
1997
2001
|
height: 1px;
|
|
1998
2002
|
background-color: var(--ai-sidebar-border);
|
|
1999
|
-
margin:
|
|
2003
|
+
margin: 20px 0;
|
|
2000
2004
|
}
|
|
2001
2005
|
.ai-agent-panel__chat-wrapper {
|
|
2002
2006
|
position: absolute;
|
package/dist/index.js
CHANGED
|
@@ -3865,6 +3865,7 @@ var AIChatPanel = ({
|
|
|
3865
3865
|
const [copiedCallId, setCopiedCallId] = (0, import_react12.useState)(null);
|
|
3866
3866
|
const [feedbackCallId, setFeedbackCallId] = (0, import_react12.useState)(null);
|
|
3867
3867
|
const [error, setError] = (0, import_react12.useState)(null);
|
|
3868
|
+
const lastProcessedErrorRef = (0, import_react12.useRef)(null);
|
|
3868
3869
|
const [emailSent, setEmailSent] = (0, import_react12.useState)(false);
|
|
3869
3870
|
const [isToolInfoModalOpen, setIsToolInfoModalOpen] = (0, import_react12.useState)(false);
|
|
3870
3871
|
const [toolInfoData, setToolInfoData] = (0, import_react12.useState)(null);
|
|
@@ -4369,6 +4370,7 @@ var AIChatPanel = ({
|
|
|
4369
4370
|
setThinkingBlocks([]);
|
|
4370
4371
|
setCurrentThinkingIndex(0);
|
|
4371
4372
|
setError(null);
|
|
4373
|
+
lastProcessedErrorRef.current = null;
|
|
4372
4374
|
setUserHasScrolled(false);
|
|
4373
4375
|
prevResponseLengthRef.current = 0;
|
|
4374
4376
|
setResponse("");
|
|
@@ -4442,31 +4444,58 @@ var AIChatPanel = ({
|
|
|
4442
4444
|
// onComplete
|
|
4443
4445
|
(errorMsg) => {
|
|
4444
4446
|
console.log("[AIChatPanel] Error callback triggered:", errorMsg);
|
|
4445
|
-
|
|
4447
|
+
const isAbortError = errorMsg.toLowerCase().includes("abort") || errorMsg.toLowerCase().includes("canceled") || errorMsg.toLowerCase().includes("cancelled");
|
|
4448
|
+
if (isAbortError) {
|
|
4449
|
+
console.log("[AIChatPanel] Request was aborted by user");
|
|
4450
|
+
if (promptKey) {
|
|
4451
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4452
|
+
[promptKey]: {
|
|
4453
|
+
content: "Response canceled",
|
|
4454
|
+
callId: lastCallId || ""
|
|
4455
|
+
}
|
|
4456
|
+
}));
|
|
4457
|
+
}
|
|
4458
|
+
} else if (errorMsg.includes("413") || errorMsg.toLowerCase().includes("content too large")) {
|
|
4446
4459
|
setError({
|
|
4447
4460
|
message: "The context is too large to process. Please start a new conversation or reduce the amount of context.",
|
|
4448
4461
|
code: "413"
|
|
4449
4462
|
});
|
|
4463
|
+
if (promptKey) {
|
|
4464
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4465
|
+
[promptKey]: {
|
|
4466
|
+
content: `Error: ${errorMsg}`,
|
|
4467
|
+
callId: lastCallId || ""
|
|
4468
|
+
}
|
|
4469
|
+
}));
|
|
4470
|
+
}
|
|
4450
4471
|
} else if (errorMsg.toLowerCase().includes("network error") || errorMsg.toLowerCase().includes("fetch")) {
|
|
4451
4472
|
setError({
|
|
4452
4473
|
message: "Network error. Please check your connection and try again.",
|
|
4453
4474
|
code: "NETWORK_ERROR"
|
|
4454
4475
|
});
|
|
4476
|
+
if (promptKey) {
|
|
4477
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4478
|
+
[promptKey]: {
|
|
4479
|
+
content: `Error: ${errorMsg}`,
|
|
4480
|
+
callId: lastCallId || ""
|
|
4481
|
+
}
|
|
4482
|
+
}));
|
|
4483
|
+
}
|
|
4455
4484
|
} else {
|
|
4456
4485
|
setError({
|
|
4457
4486
|
message: errorMsg,
|
|
4458
4487
|
code: "UNKNOWN_ERROR"
|
|
4459
4488
|
});
|
|
4489
|
+
if (promptKey) {
|
|
4490
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4491
|
+
[promptKey]: {
|
|
4492
|
+
content: `Error: ${errorMsg}`,
|
|
4493
|
+
callId: lastCallId || ""
|
|
4494
|
+
}
|
|
4495
|
+
}));
|
|
4496
|
+
}
|
|
4460
4497
|
}
|
|
4461
4498
|
setIsLoading(false);
|
|
4462
|
-
if (promptKey) {
|
|
4463
|
-
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4464
|
-
[promptKey]: {
|
|
4465
|
-
content: `Error: ${errorMsg}`,
|
|
4466
|
-
callId: lastCallId || ""
|
|
4467
|
-
}
|
|
4468
|
-
}));
|
|
4469
|
-
}
|
|
4470
4499
|
}
|
|
4471
4500
|
);
|
|
4472
4501
|
setLastMessages(messagesAndHistory);
|
|
@@ -4656,33 +4685,57 @@ var AIChatPanel = ({
|
|
|
4656
4685
|
}, [followOnPrompt, continueChat]);
|
|
4657
4686
|
(0, import_react12.useEffect)(() => {
|
|
4658
4687
|
if (llmError && llmError.trim()) {
|
|
4688
|
+
if (lastProcessedErrorRef.current === llmError) {
|
|
4689
|
+
console.log("[AIChatPanel] Skipping duplicate error:", llmError);
|
|
4690
|
+
return;
|
|
4691
|
+
}
|
|
4659
4692
|
console.log("[AIChatPanel] Error detected:", llmError);
|
|
4693
|
+
lastProcessedErrorRef.current = llmError;
|
|
4660
4694
|
const errorMessage = llmError;
|
|
4661
|
-
|
|
4695
|
+
const isAbortError = errorMessage.toLowerCase().includes("abort") || errorMessage.toLowerCase().includes("canceled") || errorMessage.toLowerCase().includes("cancelled");
|
|
4696
|
+
if (isAbortError) {
|
|
4697
|
+
console.log("[AIChatPanel] Request was aborted by user (useEffect)");
|
|
4698
|
+
} else if (errorMessage.includes("413") || errorMessage.toLowerCase().includes("content too large")) {
|
|
4662
4699
|
setError({
|
|
4663
4700
|
message: "The context is too large to process. Please start a new conversation or reduce the amount of context.",
|
|
4664
4701
|
code: "413"
|
|
4665
4702
|
});
|
|
4703
|
+
if (lastKey) {
|
|
4704
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4705
|
+
[lastKey]: {
|
|
4706
|
+
content: `Error: ${errorMessage}`,
|
|
4707
|
+
callId: lastCallId || ""
|
|
4708
|
+
}
|
|
4709
|
+
}));
|
|
4710
|
+
}
|
|
4666
4711
|
} else if (errorMessage.toLowerCase().includes("network error") || errorMessage.toLowerCase().includes("fetch")) {
|
|
4667
4712
|
setError({
|
|
4668
4713
|
message: "Network error. Please check your connection and try again.",
|
|
4669
4714
|
code: "NETWORK_ERROR"
|
|
4670
4715
|
});
|
|
4716
|
+
if (lastKey) {
|
|
4717
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4718
|
+
[lastKey]: {
|
|
4719
|
+
content: `Error: ${errorMessage}`,
|
|
4720
|
+
callId: lastCallId || ""
|
|
4721
|
+
}
|
|
4722
|
+
}));
|
|
4723
|
+
}
|
|
4671
4724
|
} else {
|
|
4672
4725
|
setError({
|
|
4673
4726
|
message: errorMessage,
|
|
4674
4727
|
code: "UNKNOWN_ERROR"
|
|
4675
4728
|
});
|
|
4729
|
+
if (lastKey) {
|
|
4730
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4731
|
+
[lastKey]: {
|
|
4732
|
+
content: `Error: ${errorMessage}`,
|
|
4733
|
+
callId: lastCallId || ""
|
|
4734
|
+
}
|
|
4735
|
+
}));
|
|
4736
|
+
}
|
|
4676
4737
|
}
|
|
4677
4738
|
setIsLoading(false);
|
|
4678
|
-
if (lastKey) {
|
|
4679
|
-
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4680
|
-
[lastKey]: {
|
|
4681
|
-
content: `Error: ${errorMessage}`,
|
|
4682
|
-
callId: lastCallId || ""
|
|
4683
|
-
}
|
|
4684
|
-
}));
|
|
4685
|
-
}
|
|
4686
4739
|
}
|
|
4687
4740
|
}, [llmError, lastKey, lastCallId]);
|
|
4688
4741
|
(0, import_react12.useEffect)(() => {
|
package/dist/index.mjs
CHANGED
|
@@ -3832,6 +3832,7 @@ var AIChatPanel = ({
|
|
|
3832
3832
|
const [copiedCallId, setCopiedCallId] = useState6(null);
|
|
3833
3833
|
const [feedbackCallId, setFeedbackCallId] = useState6(null);
|
|
3834
3834
|
const [error, setError] = useState6(null);
|
|
3835
|
+
const lastProcessedErrorRef = useRef5(null);
|
|
3835
3836
|
const [emailSent, setEmailSent] = useState6(false);
|
|
3836
3837
|
const [isToolInfoModalOpen, setIsToolInfoModalOpen] = useState6(false);
|
|
3837
3838
|
const [toolInfoData, setToolInfoData] = useState6(null);
|
|
@@ -4336,6 +4337,7 @@ var AIChatPanel = ({
|
|
|
4336
4337
|
setThinkingBlocks([]);
|
|
4337
4338
|
setCurrentThinkingIndex(0);
|
|
4338
4339
|
setError(null);
|
|
4340
|
+
lastProcessedErrorRef.current = null;
|
|
4339
4341
|
setUserHasScrolled(false);
|
|
4340
4342
|
prevResponseLengthRef.current = 0;
|
|
4341
4343
|
setResponse("");
|
|
@@ -4409,31 +4411,58 @@ var AIChatPanel = ({
|
|
|
4409
4411
|
// onComplete
|
|
4410
4412
|
(errorMsg) => {
|
|
4411
4413
|
console.log("[AIChatPanel] Error callback triggered:", errorMsg);
|
|
4412
|
-
|
|
4414
|
+
const isAbortError = errorMsg.toLowerCase().includes("abort") || errorMsg.toLowerCase().includes("canceled") || errorMsg.toLowerCase().includes("cancelled");
|
|
4415
|
+
if (isAbortError) {
|
|
4416
|
+
console.log("[AIChatPanel] Request was aborted by user");
|
|
4417
|
+
if (promptKey) {
|
|
4418
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4419
|
+
[promptKey]: {
|
|
4420
|
+
content: "Response canceled",
|
|
4421
|
+
callId: lastCallId || ""
|
|
4422
|
+
}
|
|
4423
|
+
}));
|
|
4424
|
+
}
|
|
4425
|
+
} else if (errorMsg.includes("413") || errorMsg.toLowerCase().includes("content too large")) {
|
|
4413
4426
|
setError({
|
|
4414
4427
|
message: "The context is too large to process. Please start a new conversation or reduce the amount of context.",
|
|
4415
4428
|
code: "413"
|
|
4416
4429
|
});
|
|
4430
|
+
if (promptKey) {
|
|
4431
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4432
|
+
[promptKey]: {
|
|
4433
|
+
content: `Error: ${errorMsg}`,
|
|
4434
|
+
callId: lastCallId || ""
|
|
4435
|
+
}
|
|
4436
|
+
}));
|
|
4437
|
+
}
|
|
4417
4438
|
} else if (errorMsg.toLowerCase().includes("network error") || errorMsg.toLowerCase().includes("fetch")) {
|
|
4418
4439
|
setError({
|
|
4419
4440
|
message: "Network error. Please check your connection and try again.",
|
|
4420
4441
|
code: "NETWORK_ERROR"
|
|
4421
4442
|
});
|
|
4443
|
+
if (promptKey) {
|
|
4444
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4445
|
+
[promptKey]: {
|
|
4446
|
+
content: `Error: ${errorMsg}`,
|
|
4447
|
+
callId: lastCallId || ""
|
|
4448
|
+
}
|
|
4449
|
+
}));
|
|
4450
|
+
}
|
|
4422
4451
|
} else {
|
|
4423
4452
|
setError({
|
|
4424
4453
|
message: errorMsg,
|
|
4425
4454
|
code: "UNKNOWN_ERROR"
|
|
4426
4455
|
});
|
|
4456
|
+
if (promptKey) {
|
|
4457
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4458
|
+
[promptKey]: {
|
|
4459
|
+
content: `Error: ${errorMsg}`,
|
|
4460
|
+
callId: lastCallId || ""
|
|
4461
|
+
}
|
|
4462
|
+
}));
|
|
4463
|
+
}
|
|
4427
4464
|
}
|
|
4428
4465
|
setIsLoading(false);
|
|
4429
|
-
if (promptKey) {
|
|
4430
|
-
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4431
|
-
[promptKey]: {
|
|
4432
|
-
content: `Error: ${errorMsg}`,
|
|
4433
|
-
callId: lastCallId || ""
|
|
4434
|
-
}
|
|
4435
|
-
}));
|
|
4436
|
-
}
|
|
4437
4466
|
}
|
|
4438
4467
|
);
|
|
4439
4468
|
setLastMessages(messagesAndHistory);
|
|
@@ -4623,33 +4652,57 @@ var AIChatPanel = ({
|
|
|
4623
4652
|
}, [followOnPrompt, continueChat]);
|
|
4624
4653
|
useEffect7(() => {
|
|
4625
4654
|
if (llmError && llmError.trim()) {
|
|
4655
|
+
if (lastProcessedErrorRef.current === llmError) {
|
|
4656
|
+
console.log("[AIChatPanel] Skipping duplicate error:", llmError);
|
|
4657
|
+
return;
|
|
4658
|
+
}
|
|
4626
4659
|
console.log("[AIChatPanel] Error detected:", llmError);
|
|
4660
|
+
lastProcessedErrorRef.current = llmError;
|
|
4627
4661
|
const errorMessage = llmError;
|
|
4628
|
-
|
|
4662
|
+
const isAbortError = errorMessage.toLowerCase().includes("abort") || errorMessage.toLowerCase().includes("canceled") || errorMessage.toLowerCase().includes("cancelled");
|
|
4663
|
+
if (isAbortError) {
|
|
4664
|
+
console.log("[AIChatPanel] Request was aborted by user (useEffect)");
|
|
4665
|
+
} else if (errorMessage.includes("413") || errorMessage.toLowerCase().includes("content too large")) {
|
|
4629
4666
|
setError({
|
|
4630
4667
|
message: "The context is too large to process. Please start a new conversation or reduce the amount of context.",
|
|
4631
4668
|
code: "413"
|
|
4632
4669
|
});
|
|
4670
|
+
if (lastKey) {
|
|
4671
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4672
|
+
[lastKey]: {
|
|
4673
|
+
content: `Error: ${errorMessage}`,
|
|
4674
|
+
callId: lastCallId || ""
|
|
4675
|
+
}
|
|
4676
|
+
}));
|
|
4677
|
+
}
|
|
4633
4678
|
} else if (errorMessage.toLowerCase().includes("network error") || errorMessage.toLowerCase().includes("fetch")) {
|
|
4634
4679
|
setError({
|
|
4635
4680
|
message: "Network error. Please check your connection and try again.",
|
|
4636
4681
|
code: "NETWORK_ERROR"
|
|
4637
4682
|
});
|
|
4683
|
+
if (lastKey) {
|
|
4684
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4685
|
+
[lastKey]: {
|
|
4686
|
+
content: `Error: ${errorMessage}`,
|
|
4687
|
+
callId: lastCallId || ""
|
|
4688
|
+
}
|
|
4689
|
+
}));
|
|
4690
|
+
}
|
|
4638
4691
|
} else {
|
|
4639
4692
|
setError({
|
|
4640
4693
|
message: errorMessage,
|
|
4641
4694
|
code: "UNKNOWN_ERROR"
|
|
4642
4695
|
});
|
|
4696
|
+
if (lastKey) {
|
|
4697
|
+
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4698
|
+
[lastKey]: {
|
|
4699
|
+
content: `Error: ${errorMessage}`,
|
|
4700
|
+
callId: lastCallId || ""
|
|
4701
|
+
}
|
|
4702
|
+
}));
|
|
4703
|
+
}
|
|
4643
4704
|
}
|
|
4644
4705
|
setIsLoading(false);
|
|
4645
|
-
if (lastKey) {
|
|
4646
|
-
setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4647
|
-
[lastKey]: {
|
|
4648
|
-
content: `Error: ${errorMessage}`,
|
|
4649
|
-
callId: lastCallId || ""
|
|
4650
|
-
}
|
|
4651
|
-
}));
|
|
4652
|
-
}
|
|
4653
4706
|
}
|
|
4654
4707
|
}, [llmError, lastKey, lastCallId]);
|
|
4655
4708
|
useEffect7(() => {
|
package/package.json
CHANGED
package/src/AIAgentPanel.css
CHANGED
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
--ai-panel-transition: 0.2s ease;
|
|
18
18
|
|
|
19
19
|
/* Sidebar Colors */
|
|
20
|
-
--ai-sidebar-bg: #
|
|
20
|
+
--ai-sidebar-bg: #ffffff;
|
|
21
21
|
--ai-sidebar-border: #e5e7eb;
|
|
22
|
-
--ai-sidebar-text: #
|
|
22
|
+
--ai-sidebar-text: #111827;
|
|
23
23
|
--ai-sidebar-text-muted: #6b7280;
|
|
24
|
-
--ai-sidebar-hover: #
|
|
25
|
-
--ai-sidebar-active: #
|
|
24
|
+
--ai-sidebar-hover: #f9fafb;
|
|
25
|
+
--ai-sidebar-active: #f3f4f6;
|
|
26
26
|
|
|
27
27
|
/* Header */
|
|
28
28
|
--ai-header-bg: #ffffff;
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
|
|
38
38
|
/* Conversation List */
|
|
39
39
|
--ai-conversation-bg: transparent;
|
|
40
|
-
--ai-conversation-hover: rgba(0, 0, 0, 0.
|
|
41
|
-
--ai-conversation-active: rgba(0, 0, 0, 0.
|
|
40
|
+
--ai-conversation-hover: rgba(0, 0, 0, 0.03);
|
|
41
|
+
--ai-conversation-active: rgba(0, 0, 0, 0.05);
|
|
42
42
|
--ai-conversation-title-color: #1f2937;
|
|
43
43
|
--ai-conversation-preview-color: #6b7280;
|
|
44
44
|
--ai-conversation-meta-color: #9ca3af;
|
|
45
45
|
|
|
46
46
|
/* Group Labels */
|
|
47
|
-
--ai-group-label-color: #
|
|
48
|
-
--ai-group-label-size: 0.
|
|
47
|
+
--ai-group-label-color: #6b7280;
|
|
48
|
+
--ai-group-label-size: 0.6875rem;
|
|
49
49
|
|
|
50
50
|
/* Buttons */
|
|
51
51
|
--ai-button-primary-bg: #3b82f6;
|
|
@@ -55,11 +55,11 @@
|
|
|
55
55
|
--ai-button-secondary-text: #374151;
|
|
56
56
|
--ai-button-secondary-border: #d1d5db;
|
|
57
57
|
--ai-button-secondary-hover: #e5e7eb;
|
|
58
|
-
--ai-button-ghost-hover:
|
|
58
|
+
--ai-button-ghost-hover: #f3f4f6;
|
|
59
59
|
--ai-button-destructive-bg: #ef4444;
|
|
60
60
|
--ai-button-destructive-text: #ffffff;
|
|
61
61
|
--ai-button-destructive-hover: #dc2626;
|
|
62
|
-
--ai-button-radius:
|
|
62
|
+
--ai-button-radius: 4px;
|
|
63
63
|
|
|
64
64
|
/* Input */
|
|
65
65
|
--ai-input-bg: #ffffff;
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
--ai-input-placeholder: #9ca3af;
|
|
69
69
|
--ai-input-focus-border: #3b82f6;
|
|
70
70
|
--ai-input-focus-ring: rgba(59, 130, 246, 0.2);
|
|
71
|
-
--ai-input-radius:
|
|
71
|
+
--ai-input-radius: 4px;
|
|
72
72
|
|
|
73
73
|
/* Select */
|
|
74
74
|
--ai-select-bg: #ffffff;
|
|
@@ -119,24 +119,24 @@
|
|
|
119
119
|
CSS Variables - Dark Theme
|
|
120
120
|
-------------------------------------------------------- */
|
|
121
121
|
.dark-theme {
|
|
122
|
-
--ai-sidebar-bg: #
|
|
123
|
-
--ai-sidebar-border: #
|
|
122
|
+
--ai-sidebar-bg: #111827;
|
|
123
|
+
--ai-sidebar-border: #1f2937;
|
|
124
124
|
--ai-sidebar-text: #f3f4f6;
|
|
125
125
|
--ai-sidebar-text-muted: #9ca3af;
|
|
126
|
-
--ai-sidebar-hover: #
|
|
127
|
-
--ai-sidebar-active: #
|
|
126
|
+
--ai-sidebar-hover: #1f2937;
|
|
127
|
+
--ai-sidebar-active: #374151;
|
|
128
128
|
|
|
129
|
-
--ai-header-bg: #
|
|
130
|
-
--ai-header-border: #
|
|
129
|
+
--ai-header-bg: #0d1117;
|
|
130
|
+
--ai-header-border: #1f2937;
|
|
131
131
|
|
|
132
132
|
--ai-agent-badge-bg: #1e3a5f;
|
|
133
133
|
--ai-agent-badge-text: #60a5fa;
|
|
134
134
|
--ai-agent-selector-bg: #1f2937;
|
|
135
135
|
--ai-agent-selector-border: #374151;
|
|
136
136
|
|
|
137
|
-
--ai-conversation-hover: rgba(255, 255, 255, 0.
|
|
137
|
+
--ai-conversation-hover: rgba(255, 255, 255, 0.05);
|
|
138
138
|
--ai-conversation-active: rgba(255, 255, 255, 0.08);
|
|
139
|
-
--ai-conversation-title-color: #
|
|
139
|
+
--ai-conversation-title-color: #e5e7eb;
|
|
140
140
|
--ai-conversation-preview-color: #9ca3af;
|
|
141
141
|
--ai-conversation-meta-color: #6b7280;
|
|
142
142
|
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
--ai-button-secondary-text: #f3f4f6;
|
|
150
150
|
--ai-button-secondary-border: #4b5563;
|
|
151
151
|
--ai-button-secondary-hover: #4b5563;
|
|
152
|
-
--ai-button-ghost-hover:
|
|
152
|
+
--ai-button-ghost-hover: #1f2937;
|
|
153
153
|
|
|
154
154
|
--ai-input-bg: #1f2937;
|
|
155
155
|
--ai-input-border: #374151;
|
|
@@ -395,7 +395,7 @@
|
|
|
395
395
|
.ai-agent-panel__conversations {
|
|
396
396
|
flex: 1;
|
|
397
397
|
overflow-y: auto;
|
|
398
|
-
padding: 8px;
|
|
398
|
+
padding: 8px 0;
|
|
399
399
|
}
|
|
400
400
|
|
|
401
401
|
.ai-agent-panel__empty {
|
|
@@ -427,16 +427,16 @@
|
|
|
427
427
|
|
|
428
428
|
/* Groups */
|
|
429
429
|
.ai-agent-panel__group {
|
|
430
|
-
margin-bottom:
|
|
430
|
+
margin-bottom: 24px;
|
|
431
431
|
}
|
|
432
432
|
|
|
433
433
|
.ai-agent-panel__group-label {
|
|
434
434
|
font-size: var(--ai-group-label-size);
|
|
435
|
-
font-weight:
|
|
435
|
+
font-weight: 400;
|
|
436
436
|
color: var(--ai-group-label-color);
|
|
437
437
|
text-transform: uppercase;
|
|
438
|
-
letter-spacing: 0.
|
|
439
|
-
padding: 8px
|
|
438
|
+
letter-spacing: 0.1em;
|
|
439
|
+
padding: 8px 12px 4px;
|
|
440
440
|
}
|
|
441
441
|
|
|
442
442
|
.ai-agent-panel__group-label--clickable {
|
|
@@ -445,11 +445,11 @@
|
|
|
445
445
|
justify-content: space-between;
|
|
446
446
|
cursor: pointer;
|
|
447
447
|
user-select: none;
|
|
448
|
-
transition:
|
|
448
|
+
transition: opacity 0.15s;
|
|
449
449
|
}
|
|
450
450
|
|
|
451
451
|
.ai-agent-panel__group-label--clickable:hover {
|
|
452
|
-
|
|
452
|
+
opacity: 0.7;
|
|
453
453
|
}
|
|
454
454
|
|
|
455
455
|
.ai-agent-panel__group-chevron {
|
|
@@ -466,10 +466,11 @@
|
|
|
466
466
|
.ai-agent-panel__conversation {
|
|
467
467
|
display: flex;
|
|
468
468
|
align-items: flex-start;
|
|
469
|
-
padding:
|
|
470
|
-
|
|
469
|
+
padding: 6px 12px;
|
|
470
|
+
margin: 0;
|
|
471
|
+
border-radius: 0;
|
|
471
472
|
cursor: pointer;
|
|
472
|
-
transition: background-color 0.
|
|
473
|
+
transition: background-color 0.1s ease;
|
|
473
474
|
gap: 8px;
|
|
474
475
|
}
|
|
475
476
|
|
|
@@ -488,12 +489,12 @@
|
|
|
488
489
|
|
|
489
490
|
.ai-agent-panel__conversation-title {
|
|
490
491
|
font-weight: 400;
|
|
491
|
-
font-size:
|
|
492
|
-
color: var(--ai-conversation-
|
|
492
|
+
font-size: 13px;
|
|
493
|
+
color: var(--ai-conversation-title-color);
|
|
493
494
|
white-space: nowrap;
|
|
494
495
|
overflow: hidden;
|
|
495
496
|
text-overflow: ellipsis;
|
|
496
|
-
|
|
497
|
+
line-height: 1.5;
|
|
497
498
|
}
|
|
498
499
|
|
|
499
500
|
.ai-agent-panel__conversation-preview {
|
|
@@ -1169,24 +1170,28 @@
|
|
|
1169
1170
|
-------------------------------------------------------- */
|
|
1170
1171
|
|
|
1171
1172
|
.ai-agent-panel__group--active {
|
|
1172
|
-
|
|
1173
|
-
border-radius: 6px;
|
|
1174
|
-
margin-bottom: 8px;
|
|
1175
|
-
padding: 4px;
|
|
1173
|
+
margin-bottom: 24px;
|
|
1176
1174
|
}
|
|
1177
1175
|
|
|
1178
1176
|
.ai-agent-panel__group--active .ai-agent-panel__group-label {
|
|
1179
|
-
color: var(--ai-
|
|
1180
|
-
font-weight:
|
|
1177
|
+
color: var(--ai-group-label-color);
|
|
1178
|
+
font-weight: 400;
|
|
1179
|
+
padding: 8px 12px 4px;
|
|
1181
1180
|
}
|
|
1182
1181
|
|
|
1183
1182
|
.ai-agent-panel__conversation--active-item {
|
|
1184
1183
|
display: flex;
|
|
1185
1184
|
align-items: center;
|
|
1186
1185
|
justify-content: space-between;
|
|
1187
|
-
background-color:
|
|
1188
|
-
|
|
1189
|
-
margin:
|
|
1186
|
+
background-color: transparent;
|
|
1187
|
+
padding: 6px 12px;
|
|
1188
|
+
margin: 0;
|
|
1189
|
+
transition: background-color 0.1s ease;
|
|
1190
|
+
cursor: pointer;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
.ai-agent-panel__conversation--active-item:hover {
|
|
1194
|
+
background-color: var(--ai-conversation-hover);
|
|
1190
1195
|
}
|
|
1191
1196
|
|
|
1192
1197
|
.ai-agent-panel__conversation--active-item .ai-agent-panel__conversation-content {
|
|
@@ -1201,8 +1206,7 @@
|
|
|
1201
1206
|
}
|
|
1202
1207
|
|
|
1203
1208
|
.ai-agent-panel__conversation--current {
|
|
1204
|
-
background-color:
|
|
1205
|
-
border-left: 2px solid var(--ai-button-primary-bg);
|
|
1209
|
+
background-color: rgba(59, 130, 246, 0.08) !important;
|
|
1206
1210
|
}
|
|
1207
1211
|
|
|
1208
1212
|
.ai-agent-panel__conversation--in-active {
|
|
@@ -1243,8 +1247,9 @@
|
|
|
1243
1247
|
/* Active badge for conversations in history */
|
|
1244
1248
|
.ai-agent-panel__active-badge {
|
|
1245
1249
|
color: var(--ai-button-primary-bg);
|
|
1246
|
-
font-size:
|
|
1247
|
-
margin-right:
|
|
1250
|
+
font-size: 7px;
|
|
1251
|
+
margin-right: 4px;
|
|
1252
|
+
opacity: 0.8;
|
|
1248
1253
|
}
|
|
1249
1254
|
|
|
1250
1255
|
/* Loading dot indicator */
|
|
@@ -1272,7 +1277,7 @@
|
|
|
1272
1277
|
.ai-agent-panel__group-divider {
|
|
1273
1278
|
height: 1px;
|
|
1274
1279
|
background-color: var(--ai-sidebar-border);
|
|
1275
|
-
margin:
|
|
1280
|
+
margin: 20px 0;
|
|
1276
1281
|
}
|
|
1277
1282
|
|
|
1278
1283
|
/* Chat wrapper for multi-conversation support */
|
package/src/AIChatPanel.css
CHANGED
package/src/AIChatPanel.tsx
CHANGED
|
@@ -797,6 +797,7 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
797
797
|
const [copiedCallId, setCopiedCallId] = useState<string | null>(null);
|
|
798
798
|
const [feedbackCallId, setFeedbackCallId] = useState<{ callId: string; type: 'up' | 'down' } | null>(null);
|
|
799
799
|
const [error, setError] = useState<{ message: string; code?: string } | null>(null);
|
|
800
|
+
const lastProcessedErrorRef = useRef<string | null>(null);
|
|
800
801
|
|
|
801
802
|
// Email & Save state
|
|
802
803
|
const [emailSent, setEmailSent] = useState(false);
|
|
@@ -1520,6 +1521,7 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1520
1521
|
|
|
1521
1522
|
// Clear any previous errors
|
|
1522
1523
|
setError(null);
|
|
1524
|
+
lastProcessedErrorRef.current = null; // Allow new errors to be processed
|
|
1523
1525
|
|
|
1524
1526
|
// Reset scroll tracking for new message - enable auto-scroll
|
|
1525
1527
|
setUserHasScrolled(false);
|
|
@@ -1632,12 +1634,44 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1632
1634
|
// Error callback - handle errors immediately
|
|
1633
1635
|
console.log('[AIChatPanel] Error callback triggered:', errorMsg);
|
|
1634
1636
|
|
|
1637
|
+
// Check if this is a user-initiated abort
|
|
1638
|
+
const isAbortError = errorMsg.toLowerCase().includes('abort') ||
|
|
1639
|
+
errorMsg.toLowerCase().includes('canceled') ||
|
|
1640
|
+
errorMsg.toLowerCase().includes('cancelled');
|
|
1641
|
+
|
|
1642
|
+
if (isAbortError) {
|
|
1643
|
+
// User canceled the request - don't show error banner
|
|
1644
|
+
console.log('[AIChatPanel] Request was aborted by user');
|
|
1645
|
+
// Don't set error state - no red banner
|
|
1646
|
+
|
|
1647
|
+
// Update history to show cancellation
|
|
1648
|
+
if (promptKey) {
|
|
1649
|
+
setHistory((prev) => ({
|
|
1650
|
+
...prev,
|
|
1651
|
+
[promptKey]: {
|
|
1652
|
+
content: 'Response canceled',
|
|
1653
|
+
callId: lastCallId || '',
|
|
1654
|
+
},
|
|
1655
|
+
}));
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1635
1658
|
// Detect 413 Content Too Large error
|
|
1636
|
-
if (errorMsg.includes('413') || errorMsg.toLowerCase().includes('content too large')) {
|
|
1659
|
+
else if (errorMsg.includes('413') || errorMsg.toLowerCase().includes('content too large')) {
|
|
1637
1660
|
setError({
|
|
1638
1661
|
message: 'The context is too large to process. Please start a new conversation or reduce the amount of context.',
|
|
1639
1662
|
code: '413',
|
|
1640
1663
|
});
|
|
1664
|
+
|
|
1665
|
+
// Update history to show error
|
|
1666
|
+
if (promptKey) {
|
|
1667
|
+
setHistory((prev) => ({
|
|
1668
|
+
...prev,
|
|
1669
|
+
[promptKey]: {
|
|
1670
|
+
content: `Error: ${errorMsg}`,
|
|
1671
|
+
callId: lastCallId || '',
|
|
1672
|
+
},
|
|
1673
|
+
}));
|
|
1674
|
+
}
|
|
1641
1675
|
}
|
|
1642
1676
|
// Detect other network errors
|
|
1643
1677
|
else if (errorMsg.toLowerCase().includes('network error') || errorMsg.toLowerCase().includes('fetch')) {
|
|
@@ -1645,6 +1679,17 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1645
1679
|
message: 'Network error. Please check your connection and try again.',
|
|
1646
1680
|
code: 'NETWORK_ERROR',
|
|
1647
1681
|
});
|
|
1682
|
+
|
|
1683
|
+
// Update history to show error
|
|
1684
|
+
if (promptKey) {
|
|
1685
|
+
setHistory((prev) => ({
|
|
1686
|
+
...prev,
|
|
1687
|
+
[promptKey]: {
|
|
1688
|
+
content: `Error: ${errorMsg}`,
|
|
1689
|
+
callId: lastCallId || '',
|
|
1690
|
+
},
|
|
1691
|
+
}));
|
|
1692
|
+
}
|
|
1648
1693
|
}
|
|
1649
1694
|
// Generic error
|
|
1650
1695
|
else {
|
|
@@ -1652,21 +1697,21 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1652
1697
|
message: errorMsg,
|
|
1653
1698
|
code: 'UNKNOWN_ERROR',
|
|
1654
1699
|
});
|
|
1700
|
+
|
|
1701
|
+
// Update history to show error
|
|
1702
|
+
if (promptKey) {
|
|
1703
|
+
setHistory((prev) => ({
|
|
1704
|
+
...prev,
|
|
1705
|
+
[promptKey]: {
|
|
1706
|
+
content: `Error: ${errorMsg}`,
|
|
1707
|
+
callId: lastCallId || '',
|
|
1708
|
+
},
|
|
1709
|
+
}));
|
|
1710
|
+
}
|
|
1655
1711
|
}
|
|
1656
1712
|
|
|
1657
1713
|
// Reset loading state
|
|
1658
1714
|
setIsLoading(false);
|
|
1659
|
-
|
|
1660
|
-
// Update history to show error
|
|
1661
|
-
if (promptKey) {
|
|
1662
|
-
setHistory((prev) => ({
|
|
1663
|
-
...prev,
|
|
1664
|
-
[promptKey]: {
|
|
1665
|
-
content: `Error: ${errorMsg}`,
|
|
1666
|
-
callId: lastCallId || '',
|
|
1667
|
-
},
|
|
1668
|
-
}));
|
|
1669
|
-
}
|
|
1670
1715
|
}
|
|
1671
1716
|
);
|
|
1672
1717
|
|
|
@@ -1959,17 +2004,49 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1959
2004
|
// Monitor for errors from useLLM hook
|
|
1960
2005
|
useEffect(() => {
|
|
1961
2006
|
if (llmError && llmError.trim()) {
|
|
2007
|
+
// Skip if we've already processed this exact error
|
|
2008
|
+
if (lastProcessedErrorRef.current === llmError) {
|
|
2009
|
+
console.log('[AIChatPanel] Skipping duplicate error:', llmError);
|
|
2010
|
+
return;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
1962
2013
|
console.log('[AIChatPanel] Error detected:', llmError);
|
|
2014
|
+
lastProcessedErrorRef.current = llmError;
|
|
1963
2015
|
|
|
1964
2016
|
// Parse error message to detect specific error types
|
|
1965
2017
|
const errorMessage = llmError;
|
|
1966
2018
|
|
|
2019
|
+
// Check if this is a user-initiated abort
|
|
2020
|
+
const isAbortError = errorMessage.toLowerCase().includes('abort') ||
|
|
2021
|
+
errorMessage.toLowerCase().includes('canceled') ||
|
|
2022
|
+
errorMessage.toLowerCase().includes('cancelled');
|
|
2023
|
+
|
|
2024
|
+
if (isAbortError) {
|
|
2025
|
+
// User canceled the request - don't show error banner
|
|
2026
|
+
console.log('[AIChatPanel] Request was aborted by user (useEffect)');
|
|
2027
|
+
// Don't set error state - no red banner
|
|
2028
|
+
|
|
2029
|
+
// Don't update history here - the error callback in send() already handled it
|
|
2030
|
+
// with the correct promptKey. Updating here with lastKey can affect the wrong entry
|
|
2031
|
+
// if the user has already submitted a new prompt.
|
|
2032
|
+
}
|
|
1967
2033
|
// Detect 413 Content Too Large error
|
|
1968
|
-
if (errorMessage.includes('413') || errorMessage.toLowerCase().includes('content too large')) {
|
|
2034
|
+
else if (errorMessage.includes('413') || errorMessage.toLowerCase().includes('content too large')) {
|
|
1969
2035
|
setError({
|
|
1970
2036
|
message: 'The context is too large to process. Please start a new conversation or reduce the amount of context.',
|
|
1971
2037
|
code: '413',
|
|
1972
2038
|
});
|
|
2039
|
+
|
|
2040
|
+
// Update history to show error
|
|
2041
|
+
if (lastKey) {
|
|
2042
|
+
setHistory((prev) => ({
|
|
2043
|
+
...prev,
|
|
2044
|
+
[lastKey]: {
|
|
2045
|
+
content: `Error: ${errorMessage}`,
|
|
2046
|
+
callId: lastCallId || '',
|
|
2047
|
+
},
|
|
2048
|
+
}));
|
|
2049
|
+
}
|
|
1973
2050
|
}
|
|
1974
2051
|
// Detect other network errors
|
|
1975
2052
|
else if (errorMessage.toLowerCase().includes('network error') || errorMessage.toLowerCase().includes('fetch')) {
|
|
@@ -1977,6 +2054,17 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1977
2054
|
message: 'Network error. Please check your connection and try again.',
|
|
1978
2055
|
code: 'NETWORK_ERROR',
|
|
1979
2056
|
});
|
|
2057
|
+
|
|
2058
|
+
// Update history to show error
|
|
2059
|
+
if (lastKey) {
|
|
2060
|
+
setHistory((prev) => ({
|
|
2061
|
+
...prev,
|
|
2062
|
+
[lastKey]: {
|
|
2063
|
+
content: `Error: ${errorMessage}`,
|
|
2064
|
+
callId: lastCallId || '',
|
|
2065
|
+
},
|
|
2066
|
+
}));
|
|
2067
|
+
}
|
|
1980
2068
|
}
|
|
1981
2069
|
// Generic error
|
|
1982
2070
|
else {
|
|
@@ -1984,21 +2072,21 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1984
2072
|
message: errorMessage,
|
|
1985
2073
|
code: 'UNKNOWN_ERROR',
|
|
1986
2074
|
});
|
|
2075
|
+
|
|
2076
|
+
// Update history to show error
|
|
2077
|
+
if (lastKey) {
|
|
2078
|
+
setHistory((prev) => ({
|
|
2079
|
+
...prev,
|
|
2080
|
+
[lastKey]: {
|
|
2081
|
+
content: `Error: ${errorMessage}`,
|
|
2082
|
+
callId: lastCallId || '',
|
|
2083
|
+
},
|
|
2084
|
+
}));
|
|
2085
|
+
}
|
|
1987
2086
|
}
|
|
1988
2087
|
|
|
1989
2088
|
// Reset loading state
|
|
1990
2089
|
setIsLoading(false);
|
|
1991
|
-
|
|
1992
|
-
// Update history to show error
|
|
1993
|
-
if (lastKey) {
|
|
1994
|
-
setHistory((prev) => ({
|
|
1995
|
-
...prev,
|
|
1996
|
-
[lastKey]: {
|
|
1997
|
-
content: `Error: ${errorMessage}`,
|
|
1998
|
-
callId: lastCallId || '',
|
|
1999
|
-
},
|
|
2000
|
-
}));
|
|
2001
|
-
}
|
|
2002
2090
|
}
|
|
2003
2091
|
}, [llmError, lastKey, lastCallId]);
|
|
2004
2092
|
|