@hef2024/llmasaservice-ui 0.26.0 → 0.26.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +57 -56
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +48 -23
- package/dist/index.mjs +48 -23
- package/package.json +1 -1
- package/src/AIAgentPanel.css +0 -61
- package/src/AIAgentPanel.tsx +8 -43
- package/src/AIChatPanel.css +65 -3
- package/src/AIChatPanel.tsx +50 -2
- package/hef2024-llmasaservice-ui-0.25.3.tgz +0 -0
package/dist/index.css
CHANGED
|
@@ -2575,59 +2575,6 @@ button[data-pending=true]::after {
|
|
|
2575
2575
|
.ai-agent-panel__chat-header-spacer {
|
|
2576
2576
|
flex: 1;
|
|
2577
2577
|
}
|
|
2578
|
-
.ai-agent-panel__context-notification {
|
|
2579
|
-
position: absolute;
|
|
2580
|
-
bottom: 70px;
|
|
2581
|
-
left: 50%;
|
|
2582
|
-
transform: translateX(-50%);
|
|
2583
|
-
z-index: 50;
|
|
2584
|
-
display: flex;
|
|
2585
|
-
align-items: center;
|
|
2586
|
-
gap: 8px;
|
|
2587
|
-
padding: 8px 16px;
|
|
2588
|
-
background-color: var(--ai-agent-badge-bg);
|
|
2589
|
-
color: var(--ai-agent-badge-text);
|
|
2590
|
-
border-radius: 20px;
|
|
2591
|
-
font-size: 13px;
|
|
2592
|
-
font-weight: 500;
|
|
2593
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
2594
|
-
animation: ai-context-notification-in 0.3s ease-out, ai-context-notification-out 0.3s ease-in 2.7s forwards;
|
|
2595
|
-
pointer-events: none;
|
|
2596
|
-
}
|
|
2597
|
-
.ai-agent-panel__context-notification svg {
|
|
2598
|
-
flex-shrink: 0;
|
|
2599
|
-
animation: ai-sparkle-pulse 0.6s ease-in-out infinite alternate;
|
|
2600
|
-
}
|
|
2601
|
-
@keyframes ai-context-notification-in {
|
|
2602
|
-
0% {
|
|
2603
|
-
opacity: 0;
|
|
2604
|
-
transform: translateX(-50%) translateY(10px) scale(0.9);
|
|
2605
|
-
}
|
|
2606
|
-
100% {
|
|
2607
|
-
opacity: 1;
|
|
2608
|
-
transform: translateX(-50%) translateY(0) scale(1);
|
|
2609
|
-
}
|
|
2610
|
-
}
|
|
2611
|
-
@keyframes ai-context-notification-out {
|
|
2612
|
-
0% {
|
|
2613
|
-
opacity: 1;
|
|
2614
|
-
transform: translateX(-50%) translateY(0) scale(1);
|
|
2615
|
-
}
|
|
2616
|
-
100% {
|
|
2617
|
-
opacity: 0;
|
|
2618
|
-
transform: translateX(-50%) translateY(10px) scale(0.9);
|
|
2619
|
-
}
|
|
2620
|
-
}
|
|
2621
|
-
@keyframes ai-sparkle-pulse {
|
|
2622
|
-
0% {
|
|
2623
|
-
opacity: 0.7;
|
|
2624
|
-
transform: scale(0.9);
|
|
2625
|
-
}
|
|
2626
|
-
100% {
|
|
2627
|
-
opacity: 1;
|
|
2628
|
-
transform: scale(1.1);
|
|
2629
|
-
}
|
|
2630
|
-
}
|
|
2631
2578
|
|
|
2632
2579
|
/* src/AIChatPanel.css */
|
|
2633
2580
|
:root {
|
|
@@ -4059,7 +4006,7 @@ button[data-pending=true]::after {
|
|
|
4059
4006
|
align-items: center;
|
|
4060
4007
|
gap: 4px;
|
|
4061
4008
|
flex-shrink: 0;
|
|
4062
|
-
margin-left:
|
|
4009
|
+
margin-left: 0;
|
|
4063
4010
|
}
|
|
4064
4011
|
.ai-chat-context-pill-anchor {
|
|
4065
4012
|
position: relative;
|
|
@@ -4141,8 +4088,10 @@ button[data-pending=true]::after {
|
|
|
4141
4088
|
.ai-chat-context-pill {
|
|
4142
4089
|
display: flex;
|
|
4143
4090
|
align-items: center;
|
|
4144
|
-
|
|
4145
|
-
|
|
4091
|
+
justify-content: center;
|
|
4092
|
+
gap: 0;
|
|
4093
|
+
min-width: 30px;
|
|
4094
|
+
padding: 4px 8px;
|
|
4146
4095
|
background: var(--ai-chat-suggestion-bg, #f3f4f6);
|
|
4147
4096
|
border: none;
|
|
4148
4097
|
border-radius: 999px;
|
|
@@ -4163,6 +4112,9 @@ button[data-pending=true]::after {
|
|
|
4163
4112
|
.ai-chat-context-pill--warning {
|
|
4164
4113
|
color: #f59e0b;
|
|
4165
4114
|
}
|
|
4115
|
+
.ai-chat-context-pill--updated {
|
|
4116
|
+
box-shadow: 0 0 0 1px rgba(245, 158, 11, 0.24), 0 0 10px rgba(245, 158, 11, 0.18);
|
|
4117
|
+
}
|
|
4166
4118
|
.ai-chat-context-pill__count {
|
|
4167
4119
|
display: none;
|
|
4168
4120
|
border-radius: 999px;
|
|
@@ -4172,6 +4124,43 @@ button[data-pending=true]::after {
|
|
|
4172
4124
|
color: var(--ai-sidebar-text-muted, #6b7280);
|
|
4173
4125
|
font-size: 12px;
|
|
4174
4126
|
}
|
|
4127
|
+
.ai-chat-context-pill__icon {
|
|
4128
|
+
position: relative;
|
|
4129
|
+
display: inline-flex;
|
|
4130
|
+
align-items: center;
|
|
4131
|
+
justify-content: center;
|
|
4132
|
+
width: 14px;
|
|
4133
|
+
height: 14px;
|
|
4134
|
+
}
|
|
4135
|
+
.ai-chat-context-pill__icon .ai-chat-icon-sm {
|
|
4136
|
+
width: 14px;
|
|
4137
|
+
height: 14px;
|
|
4138
|
+
}
|
|
4139
|
+
.ai-chat-context-pill__spark {
|
|
4140
|
+
position: absolute;
|
|
4141
|
+
top: -7px;
|
|
4142
|
+
right: -7px;
|
|
4143
|
+
font-size: 10px;
|
|
4144
|
+
line-height: 1;
|
|
4145
|
+
color: #f59e0b;
|
|
4146
|
+
text-shadow: 0 0 6px rgba(245, 158, 11, 0.55);
|
|
4147
|
+
pointer-events: none;
|
|
4148
|
+
animation: contextPillSpark 1.6s ease-out forwards;
|
|
4149
|
+
}
|
|
4150
|
+
@keyframes contextPillSpark {
|
|
4151
|
+
0% {
|
|
4152
|
+
opacity: 0;
|
|
4153
|
+
transform: scale(0.7) translateY(2px);
|
|
4154
|
+
}
|
|
4155
|
+
24% {
|
|
4156
|
+
opacity: 0.95;
|
|
4157
|
+
transform: scale(1) translateY(0);
|
|
4158
|
+
}
|
|
4159
|
+
100% {
|
|
4160
|
+
opacity: 0;
|
|
4161
|
+
transform: scale(1.08) translateY(-2px);
|
|
4162
|
+
}
|
|
4163
|
+
}
|
|
4175
4164
|
.ai-chat-context-pill__tokens {
|
|
4176
4165
|
display: none;
|
|
4177
4166
|
}
|
|
@@ -4541,6 +4530,9 @@ button[data-pending=true]::after {
|
|
|
4541
4530
|
.dark-theme .ai-chat-context-pill--active {
|
|
4542
4531
|
background: var(--ai-chat-suggestion-hover-bg, #4b5563);
|
|
4543
4532
|
}
|
|
4533
|
+
.dark-theme .ai-chat-context-pill--updated {
|
|
4534
|
+
box-shadow: 0 0 0 1px rgba(245, 158, 11, 0.35), 0 0 12px rgba(245, 158, 11, 0.22);
|
|
4535
|
+
}
|
|
4544
4536
|
.dark-theme .ai-chat-context-popover {
|
|
4545
4537
|
background: var(--ai-chat-input-bg, #1f2937);
|
|
4546
4538
|
border-color: var(--ai-chat-input-border, #374151);
|
|
@@ -4580,6 +4572,15 @@ button[data-pending=true]::after {
|
|
|
4580
4572
|
}
|
|
4581
4573
|
}
|
|
4582
4574
|
}
|
|
4575
|
+
@media (prefers-reduced-motion: reduce) {
|
|
4576
|
+
.ai-chat-context-pill {
|
|
4577
|
+
transition: none;
|
|
4578
|
+
}
|
|
4579
|
+
.ai-chat-context-pill__spark {
|
|
4580
|
+
animation: none;
|
|
4581
|
+
opacity: 0.9;
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4583
4584
|
.ai-chat-error-banner {
|
|
4584
4585
|
display: flex;
|
|
4585
4586
|
align-items: flex-start;
|
package/dist/index.d.mts
CHANGED
|
@@ -304,6 +304,7 @@ interface AIChatPanelProps {
|
|
|
304
304
|
contextSections?: ContextSection$1[];
|
|
305
305
|
totalContextTokens?: number;
|
|
306
306
|
maxContextTokens?: number;
|
|
307
|
+
contextUpdateSignal?: number;
|
|
307
308
|
enableContextDetailView?: boolean;
|
|
308
309
|
disabledSectionIds?: Set<string>;
|
|
309
310
|
onToggleSection?: (sectionId: string, enabled: boolean) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -304,6 +304,7 @@ interface AIChatPanelProps {
|
|
|
304
304
|
contextSections?: ContextSection$1[];
|
|
305
305
|
totalContextTokens?: number;
|
|
306
306
|
maxContextTokens?: number;
|
|
307
|
+
contextUpdateSignal?: number;
|
|
307
308
|
enableContextDetailView?: boolean;
|
|
308
309
|
disabledSectionIds?: Set<string>;
|
|
309
310
|
onToggleSection?: (sectionId: string, enabled: boolean) => void;
|
package/dist/index.js
CHANGED
|
@@ -5140,6 +5140,7 @@ var ChevronUpIcon = () => /* @__PURE__ */ import_react14.default.createElement("
|
|
|
5140
5140
|
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" }));
|
|
5141
5141
|
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" }));
|
|
5142
5142
|
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" }));
|
|
5143
|
+
var ContextViewerIcon = () => /* @__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.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" }), /* @__PURE__ */ import_react14.default.createElement("polyline", { points: "14 2 14 8 20 8" }), /* @__PURE__ */ import_react14.default.createElement("line", { x1: "16", x2: "8", y1: "13", y2: "13" }), /* @__PURE__ */ import_react14.default.createElement("line", { x1: "16", x2: "8", y1: "17", y2: "17" }), /* @__PURE__ */ import_react14.default.createElement("line", { x1: "10", x2: "8", y1: "9", y2: "9" }));
|
|
5143
5144
|
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" }));
|
|
5144
5145
|
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" }));
|
|
5145
5146
|
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" }));
|
|
@@ -5162,6 +5163,7 @@ var ChatInput = import_react14.default.memo(({
|
|
|
5162
5163
|
contextSections = [],
|
|
5163
5164
|
totalContextTokens = 0,
|
|
5164
5165
|
maxContextTokens = 8e3,
|
|
5166
|
+
contextUpdateSignal = 0,
|
|
5165
5167
|
enableContextDetailView = false,
|
|
5166
5168
|
disabledSectionIds = /* @__PURE__ */ new Set(),
|
|
5167
5169
|
onToggleSection,
|
|
@@ -5172,9 +5174,12 @@ var ChatInput = import_react14.default.memo(({
|
|
|
5172
5174
|
const [contextViewerOpen, setContextViewerOpen] = (0, import_react14.useState)(false);
|
|
5173
5175
|
const [contextViewMode, setContextViewMode] = (0, import_react14.useState)("summary");
|
|
5174
5176
|
const [expandedSectionId, setExpandedSectionId] = (0, import_react14.useState)(null);
|
|
5177
|
+
const [showContextUpdateCue, setShowContextUpdateCue] = (0, import_react14.useState)(false);
|
|
5178
|
+
const [contextUpdateCueKey, setContextUpdateCueKey] = (0, import_react14.useState)(0);
|
|
5175
5179
|
const textareaRef = (0, import_react14.useRef)(null);
|
|
5176
5180
|
const containerRef = (0, import_react14.useRef)(null);
|
|
5177
5181
|
const contextPopoverRef = (0, import_react14.useRef)(null);
|
|
5182
|
+
const contextUpdateCueTimeoutRef = (0, import_react14.useRef)(null);
|
|
5178
5183
|
const [userInputSelections, setUserInputSelections] = (0, import_react14.useState)({});
|
|
5179
5184
|
const [userInputWriteIns, setUserInputWriteIns] = (0, import_react14.useState)({});
|
|
5180
5185
|
const [userInputValidationError, setUserInputValidationError] = (0, import_react14.useState)("");
|
|
@@ -5284,6 +5289,28 @@ var ChatInput = import_react14.default.memo(({
|
|
|
5284
5289
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
5285
5290
|
}
|
|
5286
5291
|
}, [contextViewerOpen]);
|
|
5292
|
+
(0, import_react14.useEffect)(() => {
|
|
5293
|
+
if (contextUpdateSignal <= 0) {
|
|
5294
|
+
return;
|
|
5295
|
+
}
|
|
5296
|
+
setShowContextUpdateCue(true);
|
|
5297
|
+
setContextUpdateCueKey((prev) => prev + 1);
|
|
5298
|
+
if (contextUpdateCueTimeoutRef.current) {
|
|
5299
|
+
window.clearTimeout(contextUpdateCueTimeoutRef.current);
|
|
5300
|
+
contextUpdateCueTimeoutRef.current = null;
|
|
5301
|
+
}
|
|
5302
|
+
contextUpdateCueTimeoutRef.current = window.setTimeout(() => {
|
|
5303
|
+
setShowContextUpdateCue(false);
|
|
5304
|
+
contextUpdateCueTimeoutRef.current = null;
|
|
5305
|
+
}, 1800);
|
|
5306
|
+
}, [contextUpdateSignal]);
|
|
5307
|
+
(0, import_react14.useEffect)(() => {
|
|
5308
|
+
return () => {
|
|
5309
|
+
if (contextUpdateCueTimeoutRef.current) {
|
|
5310
|
+
window.clearTimeout(contextUpdateCueTimeoutRef.current);
|
|
5311
|
+
}
|
|
5312
|
+
};
|
|
5313
|
+
}, []);
|
|
5287
5314
|
const formatTokens = (tokens) => {
|
|
5288
5315
|
if (tokens >= 1e3) {
|
|
5289
5316
|
return `${(tokens / 1e3).toFixed(1)}K`;
|
|
@@ -5539,11 +5566,12 @@ var ChatInput = import_react14.default.memo(({
|
|
|
5539
5566
|
), agentOptions.length === 0 && !isAgentModeActionVisible ? /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-panel__input-footer-spacer" }) : null), contextSections.length > 0 && /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-context-pill-wrapper" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "ai-chat-context-pill-anchor" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
5540
5567
|
"button",
|
|
5541
5568
|
{
|
|
5542
|
-
className: `ai-chat-context-pill ${contextViewerOpen ? "ai-chat-context-pill--active" : ""} ${isOverLimit ? "ai-chat-context-pill--warning" : ""}`,
|
|
5569
|
+
className: `ai-chat-context-pill ${contextViewerOpen ? "ai-chat-context-pill--active" : ""} ${isOverLimit ? "ai-chat-context-pill--warning" : ""} ${showContextUpdateCue && !contextViewerOpen ? "ai-chat-context-pill--updated" : ""}`,
|
|
5543
5570
|
onClick: (e) => {
|
|
5544
5571
|
e.preventDefault();
|
|
5545
5572
|
e.stopPropagation();
|
|
5546
5573
|
console.log("[ContextViewer] Button clicked, current state:", contextViewerOpen);
|
|
5574
|
+
setShowContextUpdateCue(false);
|
|
5547
5575
|
setContextViewerOpen(!contextViewerOpen);
|
|
5548
5576
|
if (!contextViewerOpen) {
|
|
5549
5577
|
setContextViewMode("summary");
|
|
@@ -5553,9 +5581,18 @@ var ChatInput = import_react14.default.memo(({
|
|
|
5553
5581
|
}
|
|
5554
5582
|
},
|
|
5555
5583
|
type: "button",
|
|
5556
|
-
title: "View context"
|
|
5584
|
+
title: "View context",
|
|
5585
|
+
"aria-label": "View context"
|
|
5557
5586
|
},
|
|
5558
|
-
/* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-context-
|
|
5587
|
+
/* @__PURE__ */ import_react14.default.createElement("span", { className: "ai-chat-context-pill__icon", "aria-hidden": "true" }, /* @__PURE__ */ import_react14.default.createElement(ContextViewerIcon, null), showContextUpdateCue && !contextViewerOpen && /* @__PURE__ */ import_react14.default.createElement(
|
|
5588
|
+
"span",
|
|
5589
|
+
{
|
|
5590
|
+
key: contextUpdateCueKey,
|
|
5591
|
+
className: "ai-chat-context-pill__spark",
|
|
5592
|
+
"aria-hidden": "true"
|
|
5593
|
+
},
|
|
5594
|
+
"*"
|
|
5595
|
+
))
|
|
5559
5596
|
), contextViewerOpen && /* @__PURE__ */ import_react14.default.createElement(
|
|
5560
5597
|
"div",
|
|
5561
5598
|
{
|
|
@@ -5749,6 +5786,7 @@ var AIChatPanel = ({
|
|
|
5749
5786
|
contextSections = [],
|
|
5750
5787
|
totalContextTokens = 0,
|
|
5751
5788
|
maxContextTokens = 8e3,
|
|
5789
|
+
contextUpdateSignal = 0,
|
|
5752
5790
|
enableContextDetailView = false,
|
|
5753
5791
|
disabledSectionIds: propDisabledSectionIds,
|
|
5754
5792
|
onToggleSection: propOnToggleSection,
|
|
@@ -8931,6 +8969,7 @@ ${traceSummary}` : traceSummary;
|
|
|
8931
8969
|
contextSections,
|
|
8932
8970
|
totalContextTokens,
|
|
8933
8971
|
maxContextTokens,
|
|
8972
|
+
contextUpdateSignal,
|
|
8934
8973
|
enableContextDetailView,
|
|
8935
8974
|
disabledSectionIds,
|
|
8936
8975
|
onToggleSection: handleToggleSection,
|
|
@@ -9163,7 +9202,6 @@ var MessageIcon = () => /* @__PURE__ */ import_react16.default.createElement("sv
|
|
|
9163
9202
|
var CloseIcon2 = () => /* @__PURE__ */ import_react16.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ import_react16.default.createElement("path", { d: "M9 3L3 9M3 3l6 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }));
|
|
9164
9203
|
var LoadingDotIcon = () => /* @__PURE__ */ import_react16.default.createElement("span", { className: "ai-agent-panel__loading-dot" });
|
|
9165
9204
|
var SidebarIcon = () => /* @__PURE__ */ import_react16.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ import_react16.default.createElement("rect", { x: "2", y: "2", width: "12", height: "12", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }), /* @__PURE__ */ import_react16.default.createElement("path", { d: "M6 2v12", stroke: "currentColor", strokeWidth: "1.5" }));
|
|
9166
|
-
var SparkleIcon = () => /* @__PURE__ */ import_react16.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ import_react16.default.createElement("path", { d: "M8 1v3M8 12v3M3 8H0M16 8h-3M12.95 3.05l-2.12 2.12M5.17 10.83l-2.12 2.12M12.95 12.95l-2.12-2.12M5.17 5.17L3.05 3.05", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }), /* @__PURE__ */ import_react16.default.createElement("circle", { cx: "8", cy: "8", r: "2", fill: "currentColor" }));
|
|
9167
9205
|
var normalizeConversationListPayload = (payload) => {
|
|
9168
9206
|
if (!payload) return [];
|
|
9169
9207
|
const conversations = Array.isArray(payload) ? payload : payload.conversations || [];
|
|
@@ -9656,6 +9694,7 @@ var ChatPanelWrapper = ({
|
|
|
9656
9694
|
contextSections,
|
|
9657
9695
|
totalContextTokens,
|
|
9658
9696
|
maxContextTokens,
|
|
9697
|
+
contextUpdateSignal,
|
|
9659
9698
|
enableContextDetailView,
|
|
9660
9699
|
disabledSectionIds,
|
|
9661
9700
|
onToggleSection,
|
|
@@ -9778,6 +9817,7 @@ var ChatPanelWrapper = ({
|
|
|
9778
9817
|
contextSections,
|
|
9779
9818
|
totalContextTokens,
|
|
9780
9819
|
maxContextTokens,
|
|
9820
|
+
contextUpdateSignal,
|
|
9781
9821
|
enableContextDetailView,
|
|
9782
9822
|
disabledSectionIds,
|
|
9783
9823
|
onToggleSection,
|
|
@@ -10129,9 +10169,8 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
10129
10169
|
commitConversationSelection(tempId, true);
|
|
10130
10170
|
}
|
|
10131
10171
|
}), [commitConversationSelection, createDraftConversation, currentAgentId]);
|
|
10132
|
-
const [
|
|
10172
|
+
const [contextUpdateSignal, setContextUpdateSignal] = (0, import_react16.useState)(0);
|
|
10133
10173
|
const prevContextRef = (0, import_react16.useRef)(null);
|
|
10134
|
-
const contextNotificationTimeoutRef = (0, import_react16.useRef)(null);
|
|
10135
10174
|
const prevDefaultAgentRef = (0, import_react16.useRef)(null);
|
|
10136
10175
|
const fetchFirstPrompt = (0, import_react16.useCallback)((conversationId, agentIdForConversation) => __async(void 0, null, function* () {
|
|
10137
10176
|
var _a2, _b2;
|
|
@@ -10692,24 +10731,9 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
10692
10731
|
const changed = prevContextRef.current !== contextString;
|
|
10693
10732
|
if (changed) {
|
|
10694
10733
|
prevContextRef.current = contextString;
|
|
10695
|
-
|
|
10696
|
-
clearTimeout(contextNotificationTimeoutRef.current);
|
|
10697
|
-
contextNotificationTimeoutRef.current = null;
|
|
10698
|
-
}
|
|
10699
|
-
setShowContextNotification(true);
|
|
10700
|
-
contextNotificationTimeoutRef.current = setTimeout(() => {
|
|
10701
|
-
setShowContextNotification(false);
|
|
10702
|
-
contextNotificationTimeoutRef.current = null;
|
|
10703
|
-
}, 3e3);
|
|
10734
|
+
setContextUpdateSignal((prev) => prev + 1);
|
|
10704
10735
|
}
|
|
10705
10736
|
}, [mergedContext.sections]);
|
|
10706
|
-
(0, import_react16.useEffect)(() => {
|
|
10707
|
-
return () => {
|
|
10708
|
-
if (contextNotificationTimeoutRef.current) {
|
|
10709
|
-
clearTimeout(contextNotificationTimeoutRef.current);
|
|
10710
|
-
}
|
|
10711
|
-
};
|
|
10712
|
-
}, []);
|
|
10713
10737
|
(0, import_react16.useEffect)(() => {
|
|
10714
10738
|
var _a2, _b2;
|
|
10715
10739
|
let foundDefaultAgent = null;
|
|
@@ -11240,7 +11264,7 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
11240
11264
|
/* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__conversation-content" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__conversation-title" }, isActive && /* @__PURE__ */ import_react16.default.createElement("span", { className: "ai-agent-panel__active-badge" }, "\u25CF"), conversationFirstPrompts[conv.conversationId] || conv.title), subtitle ? /* @__PURE__ */ import_react16.default.createElement("div", { className: "ai-agent-panel__conversation-subtitle" }, subtitle) : null)
|
|
11241
11265
|
);
|
|
11242
11266
|
}))))))),
|
|
11243
|
-
/* @__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)))),
|
|
11267
|
+
/* @__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)))), activeConversationsList.map((activeConv) => /* @__PURE__ */ import_react16.default.createElement(
|
|
11244
11268
|
ChatPanelWrapper,
|
|
11245
11269
|
{
|
|
11246
11270
|
key: activeConv.stableKey,
|
|
@@ -11270,6 +11294,7 @@ var AIAgentPanel = import_react16.default.forwardRef(({
|
|
|
11270
11294
|
contextSections: mergedContext.sections,
|
|
11271
11295
|
totalContextTokens: filteredContext.totalTokens,
|
|
11272
11296
|
maxContextTokens,
|
|
11297
|
+
contextUpdateSignal,
|
|
11273
11298
|
enableContextDetailView,
|
|
11274
11299
|
disabledSectionIds: currentDisabledSections,
|
|
11275
11300
|
onToggleSection: handleContextSectionToggle,
|
package/dist/index.mjs
CHANGED
|
@@ -5105,6 +5105,7 @@ var ChevronUpIcon = () => /* @__PURE__ */ React14.createElement("svg", { xmlns:
|
|
|
5105
5105
|
var AgentIcon = () => /* @__PURE__ */ React14.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__ */ React14.createElement("path", { d: "M12 8V4H8" }), /* @__PURE__ */ React14.createElement("rect", { width: "16", height: "12", x: "4", y: "8", rx: "2" }), /* @__PURE__ */ React14.createElement("path", { d: "M2 14h2" }), /* @__PURE__ */ React14.createElement("path", { d: "M20 14h2" }), /* @__PURE__ */ React14.createElement("path", { d: "M15 13v2" }), /* @__PURE__ */ React14.createElement("path", { d: "M9 13v2" }));
|
|
5106
5106
|
var ToolIcon = () => /* @__PURE__ */ React14.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__ */ React14.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" }));
|
|
5107
5107
|
var CheckIcon = () => /* @__PURE__ */ React14.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__ */ React14.createElement("polyline", { points: "20 6 9 17 4 12" }));
|
|
5108
|
+
var ContextViewerIcon = () => /* @__PURE__ */ React14.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__ */ React14.createElement("path", { d: "M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" }), /* @__PURE__ */ React14.createElement("polyline", { points: "14 2 14 8 20 8" }), /* @__PURE__ */ React14.createElement("line", { x1: "16", x2: "8", y1: "13", y2: "13" }), /* @__PURE__ */ React14.createElement("line", { x1: "16", x2: "8", y1: "17", y2: "17" }), /* @__PURE__ */ React14.createElement("line", { x1: "10", x2: "8", y1: "9", y2: "9" }));
|
|
5108
5109
|
var LLMAsAServiceLogo = () => /* @__PURE__ */ React14.createElement("svg", { width: "16", height: "16", viewBox: "0 0 72 72", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React14.createElement("ellipse", { cx: "14.0868", cy: "59.2146", rx: "7.8261", ry: "7.7854", fill: "#2487D8" }), /* @__PURE__ */ React14.createElement("ellipse", { cx: "24.9013", cy: "43.0776", rx: "6.11858", ry: "6.08676", fill: "#2487D8" }), /* @__PURE__ */ React14.createElement("ellipse", { cx: "45.391", cy: "43.0776", rx: "6.11858", ry: "6.08676", fill: "#2487D8" }), /* @__PURE__ */ React14.createElement("ellipse", { cx: "65.8813", cy: "43.0776", rx: "6.11858", ry: "6.08676", fill: "#2487D8" }), /* @__PURE__ */ React14.createElement("ellipse", { cx: "35.1461", cy: "26.5327", rx: "4.41103", ry: "4.3878", fill: "#2487D8" }), /* @__PURE__ */ React14.createElement("ellipse", { cx: "55.6364", cy: "26.5327", rx: "4.41103", ry: "4.3878", fill: "#2487D8" }), /* @__PURE__ */ React14.createElement("ellipse", { cx: "45.391", cy: "10.3959", rx: "2.70351", ry: "2.68919", fill: "#2487D8" }));
|
|
5109
5110
|
var AlertCircleIcon = () => /* @__PURE__ */ React14.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__ */ React14.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React14.createElement("line", { x1: "12", x2: "12", y1: "8", y2: "12" }), /* @__PURE__ */ React14.createElement("line", { x1: "12", x2: "12.01", y1: "16", y2: "16" }));
|
|
5110
5111
|
var CloseIcon = () => /* @__PURE__ */ React14.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__ */ React14.createElement("line", { x1: "18", x2: "6", y1: "6", y2: "18" }), /* @__PURE__ */ React14.createElement("line", { x1: "6", x2: "18", y1: "6", y2: "18" }));
|
|
@@ -5127,6 +5128,7 @@ var ChatInput = React14.memo(({
|
|
|
5127
5128
|
contextSections = [],
|
|
5128
5129
|
totalContextTokens = 0,
|
|
5129
5130
|
maxContextTokens = 8e3,
|
|
5131
|
+
contextUpdateSignal = 0,
|
|
5130
5132
|
enableContextDetailView = false,
|
|
5131
5133
|
disabledSectionIds = /* @__PURE__ */ new Set(),
|
|
5132
5134
|
onToggleSection,
|
|
@@ -5137,9 +5139,12 @@ var ChatInput = React14.memo(({
|
|
|
5137
5139
|
const [contextViewerOpen, setContextViewerOpen] = useState7(false);
|
|
5138
5140
|
const [contextViewMode, setContextViewMode] = useState7("summary");
|
|
5139
5141
|
const [expandedSectionId, setExpandedSectionId] = useState7(null);
|
|
5142
|
+
const [showContextUpdateCue, setShowContextUpdateCue] = useState7(false);
|
|
5143
|
+
const [contextUpdateCueKey, setContextUpdateCueKey] = useState7(0);
|
|
5140
5144
|
const textareaRef = useRef6(null);
|
|
5141
5145
|
const containerRef = useRef6(null);
|
|
5142
5146
|
const contextPopoverRef = useRef6(null);
|
|
5147
|
+
const contextUpdateCueTimeoutRef = useRef6(null);
|
|
5143
5148
|
const [userInputSelections, setUserInputSelections] = useState7({});
|
|
5144
5149
|
const [userInputWriteIns, setUserInputWriteIns] = useState7({});
|
|
5145
5150
|
const [userInputValidationError, setUserInputValidationError] = useState7("");
|
|
@@ -5249,6 +5254,28 @@ var ChatInput = React14.memo(({
|
|
|
5249
5254
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
5250
5255
|
}
|
|
5251
5256
|
}, [contextViewerOpen]);
|
|
5257
|
+
useEffect8(() => {
|
|
5258
|
+
if (contextUpdateSignal <= 0) {
|
|
5259
|
+
return;
|
|
5260
|
+
}
|
|
5261
|
+
setShowContextUpdateCue(true);
|
|
5262
|
+
setContextUpdateCueKey((prev) => prev + 1);
|
|
5263
|
+
if (contextUpdateCueTimeoutRef.current) {
|
|
5264
|
+
window.clearTimeout(contextUpdateCueTimeoutRef.current);
|
|
5265
|
+
contextUpdateCueTimeoutRef.current = null;
|
|
5266
|
+
}
|
|
5267
|
+
contextUpdateCueTimeoutRef.current = window.setTimeout(() => {
|
|
5268
|
+
setShowContextUpdateCue(false);
|
|
5269
|
+
contextUpdateCueTimeoutRef.current = null;
|
|
5270
|
+
}, 1800);
|
|
5271
|
+
}, [contextUpdateSignal]);
|
|
5272
|
+
useEffect8(() => {
|
|
5273
|
+
return () => {
|
|
5274
|
+
if (contextUpdateCueTimeoutRef.current) {
|
|
5275
|
+
window.clearTimeout(contextUpdateCueTimeoutRef.current);
|
|
5276
|
+
}
|
|
5277
|
+
};
|
|
5278
|
+
}, []);
|
|
5252
5279
|
const formatTokens = (tokens) => {
|
|
5253
5280
|
if (tokens >= 1e3) {
|
|
5254
5281
|
return `${(tokens / 1e3).toFixed(1)}K`;
|
|
@@ -5504,11 +5531,12 @@ var ChatInput = React14.memo(({
|
|
|
5504
5531
|
), agentOptions.length === 0 && !isAgentModeActionVisible ? /* @__PURE__ */ React14.createElement("div", { className: "ai-chat-panel__input-footer-spacer" }) : null), contextSections.length > 0 && /* @__PURE__ */ React14.createElement("div", { className: "ai-chat-context-pill-wrapper" }, /* @__PURE__ */ React14.createElement("div", { className: "ai-chat-context-pill-anchor" }, /* @__PURE__ */ React14.createElement(
|
|
5505
5532
|
"button",
|
|
5506
5533
|
{
|
|
5507
|
-
className: `ai-chat-context-pill ${contextViewerOpen ? "ai-chat-context-pill--active" : ""} ${isOverLimit ? "ai-chat-context-pill--warning" : ""}`,
|
|
5534
|
+
className: `ai-chat-context-pill ${contextViewerOpen ? "ai-chat-context-pill--active" : ""} ${isOverLimit ? "ai-chat-context-pill--warning" : ""} ${showContextUpdateCue && !contextViewerOpen ? "ai-chat-context-pill--updated" : ""}`,
|
|
5508
5535
|
onClick: (e) => {
|
|
5509
5536
|
e.preventDefault();
|
|
5510
5537
|
e.stopPropagation();
|
|
5511
5538
|
console.log("[ContextViewer] Button clicked, current state:", contextViewerOpen);
|
|
5539
|
+
setShowContextUpdateCue(false);
|
|
5512
5540
|
setContextViewerOpen(!contextViewerOpen);
|
|
5513
5541
|
if (!contextViewerOpen) {
|
|
5514
5542
|
setContextViewMode("summary");
|
|
@@ -5518,9 +5546,18 @@ var ChatInput = React14.memo(({
|
|
|
5518
5546
|
}
|
|
5519
5547
|
},
|
|
5520
5548
|
type: "button",
|
|
5521
|
-
title: "View context"
|
|
5549
|
+
title: "View context",
|
|
5550
|
+
"aria-label": "View context"
|
|
5522
5551
|
},
|
|
5523
|
-
/* @__PURE__ */ React14.createElement("span", { className: "ai-chat-context-
|
|
5552
|
+
/* @__PURE__ */ React14.createElement("span", { className: "ai-chat-context-pill__icon", "aria-hidden": "true" }, /* @__PURE__ */ React14.createElement(ContextViewerIcon, null), showContextUpdateCue && !contextViewerOpen && /* @__PURE__ */ React14.createElement(
|
|
5553
|
+
"span",
|
|
5554
|
+
{
|
|
5555
|
+
key: contextUpdateCueKey,
|
|
5556
|
+
className: "ai-chat-context-pill__spark",
|
|
5557
|
+
"aria-hidden": "true"
|
|
5558
|
+
},
|
|
5559
|
+
"*"
|
|
5560
|
+
))
|
|
5524
5561
|
), contextViewerOpen && /* @__PURE__ */ React14.createElement(
|
|
5525
5562
|
"div",
|
|
5526
5563
|
{
|
|
@@ -5714,6 +5751,7 @@ var AIChatPanel = ({
|
|
|
5714
5751
|
contextSections = [],
|
|
5715
5752
|
totalContextTokens = 0,
|
|
5716
5753
|
maxContextTokens = 8e3,
|
|
5754
|
+
contextUpdateSignal = 0,
|
|
5717
5755
|
enableContextDetailView = false,
|
|
5718
5756
|
disabledSectionIds: propDisabledSectionIds,
|
|
5719
5757
|
onToggleSection: propOnToggleSection,
|
|
@@ -8896,6 +8934,7 @@ ${traceSummary}` : traceSummary;
|
|
|
8896
8934
|
contextSections,
|
|
8897
8935
|
totalContextTokens,
|
|
8898
8936
|
maxContextTokens,
|
|
8937
|
+
contextUpdateSignal,
|
|
8899
8938
|
enableContextDetailView,
|
|
8900
8939
|
disabledSectionIds,
|
|
8901
8940
|
onToggleSection: handleToggleSection,
|
|
@@ -9128,7 +9167,6 @@ var MessageIcon = () => /* @__PURE__ */ React15.createElement("svg", { width: "1
|
|
|
9128
9167
|
var CloseIcon2 = () => /* @__PURE__ */ React15.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React15.createElement("path", { d: "M9 3L3 9M3 3l6 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }));
|
|
9129
9168
|
var LoadingDotIcon = () => /* @__PURE__ */ React15.createElement("span", { className: "ai-agent-panel__loading-dot" });
|
|
9130
9169
|
var SidebarIcon = () => /* @__PURE__ */ React15.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React15.createElement("rect", { x: "2", y: "2", width: "12", height: "12", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }), /* @__PURE__ */ React15.createElement("path", { d: "M6 2v12", stroke: "currentColor", strokeWidth: "1.5" }));
|
|
9131
|
-
var SparkleIcon = () => /* @__PURE__ */ React15.createElement("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React15.createElement("path", { d: "M8 1v3M8 12v3M3 8H0M16 8h-3M12.95 3.05l-2.12 2.12M5.17 10.83l-2.12 2.12M12.95 12.95l-2.12-2.12M5.17 5.17L3.05 3.05", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }), /* @__PURE__ */ React15.createElement("circle", { cx: "8", cy: "8", r: "2", fill: "currentColor" }));
|
|
9132
9170
|
var normalizeConversationListPayload = (payload) => {
|
|
9133
9171
|
if (!payload) return [];
|
|
9134
9172
|
const conversations = Array.isArray(payload) ? payload : payload.conversations || [];
|
|
@@ -9621,6 +9659,7 @@ var ChatPanelWrapper = ({
|
|
|
9621
9659
|
contextSections,
|
|
9622
9660
|
totalContextTokens,
|
|
9623
9661
|
maxContextTokens,
|
|
9662
|
+
contextUpdateSignal,
|
|
9624
9663
|
enableContextDetailView,
|
|
9625
9664
|
disabledSectionIds,
|
|
9626
9665
|
onToggleSection,
|
|
@@ -9743,6 +9782,7 @@ var ChatPanelWrapper = ({
|
|
|
9743
9782
|
contextSections,
|
|
9744
9783
|
totalContextTokens,
|
|
9745
9784
|
maxContextTokens,
|
|
9785
|
+
contextUpdateSignal,
|
|
9746
9786
|
enableContextDetailView,
|
|
9747
9787
|
disabledSectionIds,
|
|
9748
9788
|
onToggleSection,
|
|
@@ -10094,9 +10134,8 @@ var AIAgentPanel = React15.forwardRef(({
|
|
|
10094
10134
|
commitConversationSelection(tempId, true);
|
|
10095
10135
|
}
|
|
10096
10136
|
}), [commitConversationSelection, createDraftConversation, currentAgentId]);
|
|
10097
|
-
const [
|
|
10137
|
+
const [contextUpdateSignal, setContextUpdateSignal] = useState9(0);
|
|
10098
10138
|
const prevContextRef = useRef7(null);
|
|
10099
|
-
const contextNotificationTimeoutRef = useRef7(null);
|
|
10100
10139
|
const prevDefaultAgentRef = useRef7(null);
|
|
10101
10140
|
const fetchFirstPrompt = useCallback4((conversationId, agentIdForConversation) => __async(void 0, null, function* () {
|
|
10102
10141
|
var _a2, _b2;
|
|
@@ -10657,24 +10696,9 @@ var AIAgentPanel = React15.forwardRef(({
|
|
|
10657
10696
|
const changed = prevContextRef.current !== contextString;
|
|
10658
10697
|
if (changed) {
|
|
10659
10698
|
prevContextRef.current = contextString;
|
|
10660
|
-
|
|
10661
|
-
clearTimeout(contextNotificationTimeoutRef.current);
|
|
10662
|
-
contextNotificationTimeoutRef.current = null;
|
|
10663
|
-
}
|
|
10664
|
-
setShowContextNotification(true);
|
|
10665
|
-
contextNotificationTimeoutRef.current = setTimeout(() => {
|
|
10666
|
-
setShowContextNotification(false);
|
|
10667
|
-
contextNotificationTimeoutRef.current = null;
|
|
10668
|
-
}, 3e3);
|
|
10699
|
+
setContextUpdateSignal((prev) => prev + 1);
|
|
10669
10700
|
}
|
|
10670
10701
|
}, [mergedContext.sections]);
|
|
10671
|
-
useEffect10(() => {
|
|
10672
|
-
return () => {
|
|
10673
|
-
if (contextNotificationTimeoutRef.current) {
|
|
10674
|
-
clearTimeout(contextNotificationTimeoutRef.current);
|
|
10675
|
-
}
|
|
10676
|
-
};
|
|
10677
|
-
}, []);
|
|
10678
10702
|
useEffect10(() => {
|
|
10679
10703
|
var _a2, _b2;
|
|
10680
10704
|
let foundDefaultAgent = null;
|
|
@@ -11205,7 +11229,7 @@ var AIAgentPanel = React15.forwardRef(({
|
|
|
11205
11229
|
/* @__PURE__ */ React15.createElement("div", { className: "ai-agent-panel__conversation-content" }, /* @__PURE__ */ React15.createElement("div", { className: "ai-agent-panel__conversation-title" }, isActive && /* @__PURE__ */ React15.createElement("span", { className: "ai-agent-panel__active-badge" }, "\u25CF"), conversationFirstPrompts[conv.conversationId] || conv.title), subtitle ? /* @__PURE__ */ React15.createElement("div", { className: "ai-agent-panel__conversation-subtitle" }, subtitle) : null)
|
|
11206
11230
|
);
|
|
11207
11231
|
}))))))),
|
|
11208
|
-
/* @__PURE__ */ React15.createElement("div", { className: "ai-agent-panel__chat" }, !showConversationHistory && collapsible && /* @__PURE__ */ React15.createElement("div", { className: "ai-agent-panel__chat-header" }, /* @__PURE__ */ React15.createElement("div", { className: "ai-agent-panel__chat-header-spacer" }), /* @__PURE__ */ React15.createElement(Tooltip, { content: "Collapse Panel", side: position === "right" ? "left" : "right" }, /* @__PURE__ */ React15.createElement(Button, { variant: "ghost", size: "icon", onClick: toggleCollapse }, position === "right" ? /* @__PURE__ */ React15.createElement(ChevronRightIcon, null) : /* @__PURE__ */ React15.createElement(ChevronLeftIcon, null)))),
|
|
11232
|
+
/* @__PURE__ */ React15.createElement("div", { className: "ai-agent-panel__chat" }, !showConversationHistory && collapsible && /* @__PURE__ */ React15.createElement("div", { className: "ai-agent-panel__chat-header" }, /* @__PURE__ */ React15.createElement("div", { className: "ai-agent-panel__chat-header-spacer" }), /* @__PURE__ */ React15.createElement(Tooltip, { content: "Collapse Panel", side: position === "right" ? "left" : "right" }, /* @__PURE__ */ React15.createElement(Button, { variant: "ghost", size: "icon", onClick: toggleCollapse }, position === "right" ? /* @__PURE__ */ React15.createElement(ChevronRightIcon, null) : /* @__PURE__ */ React15.createElement(ChevronLeftIcon, null)))), activeConversationsList.map((activeConv) => /* @__PURE__ */ React15.createElement(
|
|
11209
11233
|
ChatPanelWrapper,
|
|
11210
11234
|
{
|
|
11211
11235
|
key: activeConv.stableKey,
|
|
@@ -11235,6 +11259,7 @@ var AIAgentPanel = React15.forwardRef(({
|
|
|
11235
11259
|
contextSections: mergedContext.sections,
|
|
11236
11260
|
totalContextTokens: filteredContext.totalTokens,
|
|
11237
11261
|
maxContextTokens,
|
|
11262
|
+
contextUpdateSignal,
|
|
11238
11263
|
enableContextDetailView,
|
|
11239
11264
|
disabledSectionIds: currentDisabledSections,
|
|
11240
11265
|
onToggleSection: handleContextSectionToggle,
|
package/package.json
CHANGED
package/src/AIAgentPanel.css
CHANGED
|
@@ -1407,64 +1407,3 @@
|
|
|
1407
1407
|
.ai-agent-panel__chat-header-spacer {
|
|
1408
1408
|
flex: 1;
|
|
1409
1409
|
}
|
|
1410
|
-
|
|
1411
|
-
/* --------------------------------------------------------
|
|
1412
|
-
Context Change Notification
|
|
1413
|
-
-------------------------------------------------------- */
|
|
1414
|
-
.ai-agent-panel__context-notification {
|
|
1415
|
-
position: absolute;
|
|
1416
|
-
bottom: 70px;
|
|
1417
|
-
left: 50%;
|
|
1418
|
-
transform: translateX(-50%);
|
|
1419
|
-
z-index: 50;
|
|
1420
|
-
display: flex;
|
|
1421
|
-
align-items: center;
|
|
1422
|
-
gap: 8px;
|
|
1423
|
-
padding: 8px 16px;
|
|
1424
|
-
background-color: var(--ai-agent-badge-bg);
|
|
1425
|
-
color: var(--ai-agent-badge-text);
|
|
1426
|
-
border-radius: 20px;
|
|
1427
|
-
font-size: 13px;
|
|
1428
|
-
font-weight: 500;
|
|
1429
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
1430
|
-
animation: ai-context-notification-in 0.3s ease-out, ai-context-notification-out 0.3s ease-in 2.7s forwards;
|
|
1431
|
-
pointer-events: none;
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
.ai-agent-panel__context-notification svg {
|
|
1435
|
-
flex-shrink: 0;
|
|
1436
|
-
animation: ai-sparkle-pulse 0.6s ease-in-out infinite alternate;
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
|
-
@keyframes ai-context-notification-in {
|
|
1440
|
-
0% {
|
|
1441
|
-
opacity: 0;
|
|
1442
|
-
transform: translateX(-50%) translateY(10px) scale(0.9);
|
|
1443
|
-
}
|
|
1444
|
-
100% {
|
|
1445
|
-
opacity: 1;
|
|
1446
|
-
transform: translateX(-50%) translateY(0) scale(1);
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
|
|
1450
|
-
@keyframes ai-context-notification-out {
|
|
1451
|
-
0% {
|
|
1452
|
-
opacity: 1;
|
|
1453
|
-
transform: translateX(-50%) translateY(0) scale(1);
|
|
1454
|
-
}
|
|
1455
|
-
100% {
|
|
1456
|
-
opacity: 0;
|
|
1457
|
-
transform: translateX(-50%) translateY(10px) scale(0.9);
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
@keyframes ai-sparkle-pulse {
|
|
1462
|
-
0% {
|
|
1463
|
-
opacity: 0.7;
|
|
1464
|
-
transform: scale(0.9);
|
|
1465
|
-
}
|
|
1466
|
-
100% {
|
|
1467
|
-
opacity: 1;
|
|
1468
|
-
transform: scale(1.1);
|
|
1469
|
-
}
|
|
1470
|
-
}
|
package/src/AIAgentPanel.tsx
CHANGED
|
@@ -269,13 +269,6 @@ const SidebarIcon = () => (
|
|
|
269
269
|
</svg>
|
|
270
270
|
);
|
|
271
271
|
|
|
272
|
-
const SparkleIcon = () => (
|
|
273
|
-
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
274
|
-
<path d="M8 1v3M8 12v3M3 8H0M16 8h-3M12.95 3.05l-2.12 2.12M5.17 10.83l-2.12 2.12M12.95 12.95l-2.12-2.12M5.17 5.17L3.05 3.05" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
|
|
275
|
-
<circle cx="8" cy="8" r="2" fill="currentColor"/>
|
|
276
|
-
</svg>
|
|
277
|
-
);
|
|
278
|
-
|
|
279
272
|
/**
|
|
280
273
|
* AIAgentPanel - Cursor-inspired multi-agent panel
|
|
281
274
|
*/
|
|
@@ -955,6 +948,7 @@ interface ChatPanelWrapperProps {
|
|
|
955
948
|
contextSections: ContextSection[];
|
|
956
949
|
totalContextTokens: number;
|
|
957
950
|
maxContextTokens: number;
|
|
951
|
+
contextUpdateSignal: number;
|
|
958
952
|
enableContextDetailView: boolean;
|
|
959
953
|
disabledSectionIds: Set<string>;
|
|
960
954
|
onToggleSection: (sectionId: string, enabled: boolean) => void;
|
|
@@ -1017,6 +1011,7 @@ const ChatPanelWrapper = (({
|
|
|
1017
1011
|
contextSections,
|
|
1018
1012
|
totalContextTokens,
|
|
1019
1013
|
maxContextTokens,
|
|
1014
|
+
contextUpdateSignal,
|
|
1020
1015
|
enableContextDetailView,
|
|
1021
1016
|
disabledSectionIds,
|
|
1022
1017
|
onToggleSection,
|
|
@@ -1165,6 +1160,7 @@ const ChatPanelWrapper = (({
|
|
|
1165
1160
|
contextSections={contextSections}
|
|
1166
1161
|
totalContextTokens={totalContextTokens}
|
|
1167
1162
|
maxContextTokens={maxContextTokens}
|
|
1163
|
+
contextUpdateSignal={contextUpdateSignal}
|
|
1168
1164
|
enableContextDetailView={enableContextDetailView}
|
|
1169
1165
|
disabledSectionIds={disabledSectionIds}
|
|
1170
1166
|
onToggleSection={onToggleSection}
|
|
@@ -1627,10 +1623,9 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
|
|
|
1627
1623
|
}
|
|
1628
1624
|
}), [commitConversationSelection, createDraftConversation, currentAgentId]);
|
|
1629
1625
|
|
|
1630
|
-
//
|
|
1631
|
-
const [
|
|
1626
|
+
// Bumps when context changes so child components can show a subtle cue.
|
|
1627
|
+
const [contextUpdateSignal, setContextUpdateSignal] = useState(0);
|
|
1632
1628
|
const prevContextRef = useRef<string | null>(null);
|
|
1633
|
-
const contextNotificationTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
1634
1629
|
|
|
1635
1630
|
// Track previous defaultAgent to avoid re-suggesting the same agent
|
|
1636
1631
|
const prevDefaultAgentRef = useRef<string | null>(null);
|
|
@@ -2373,7 +2368,7 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
|
|
|
2373
2368
|
}, [context, sharedContextSections, pageContextSections, contextDataSources]);
|
|
2374
2369
|
|
|
2375
2370
|
|
|
2376
|
-
// Detect context changes and
|
|
2371
|
+
// Detect context changes and notify the context icon.
|
|
2377
2372
|
useEffect(() => {
|
|
2378
2373
|
// Create a stable string representation of the context for comparison
|
|
2379
2374
|
const contextString = JSON.stringify(
|
|
@@ -2397,33 +2392,10 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
|
|
|
2397
2392
|
|
|
2398
2393
|
if (changed) {
|
|
2399
2394
|
prevContextRef.current = contextString;
|
|
2400
|
-
|
|
2401
|
-
// Clear any existing timeout before setting a new one
|
|
2402
|
-
if (contextNotificationTimeoutRef.current) {
|
|
2403
|
-
clearTimeout(contextNotificationTimeoutRef.current);
|
|
2404
|
-
contextNotificationTimeoutRef.current = null;
|
|
2405
|
-
}
|
|
2406
|
-
|
|
2407
|
-
// Show the notification
|
|
2408
|
-
setShowContextNotification(true);
|
|
2409
|
-
|
|
2410
|
-
// Auto-hide after 3 seconds
|
|
2411
|
-
contextNotificationTimeoutRef.current = setTimeout(() => {
|
|
2412
|
-
setShowContextNotification(false);
|
|
2413
|
-
contextNotificationTimeoutRef.current = null;
|
|
2414
|
-
}, 3000);
|
|
2395
|
+
setContextUpdateSignal((prev) => prev + 1);
|
|
2415
2396
|
}
|
|
2416
2397
|
}, [mergedContext.sections]);
|
|
2417
2398
|
|
|
2418
|
-
// Separate cleanup effect for unmount only
|
|
2419
|
-
useEffect(() => {
|
|
2420
|
-
return () => {
|
|
2421
|
-
if (contextNotificationTimeoutRef.current) {
|
|
2422
|
-
clearTimeout(contextNotificationTimeoutRef.current);
|
|
2423
|
-
}
|
|
2424
|
-
};
|
|
2425
|
-
}, []);
|
|
2426
|
-
|
|
2427
2399
|
// Auto-suggest agent switch when page context includes a defaultAgent
|
|
2428
2400
|
// Injects a synthetic message with [SUGGEST_AGENT:...] into the chat history
|
|
2429
2401
|
useEffect(() => {
|
|
@@ -3215,14 +3187,6 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
|
|
|
3215
3187
|
</div>
|
|
3216
3188
|
)}
|
|
3217
3189
|
|
|
3218
|
-
{/* Context change notification */}
|
|
3219
|
-
{showContextNotification && (
|
|
3220
|
-
<div className="ai-agent-panel__context-notification">
|
|
3221
|
-
<SparkleIcon />
|
|
3222
|
-
<span>Agent now has new context</span>
|
|
3223
|
-
</div>
|
|
3224
|
-
)}
|
|
3225
|
-
|
|
3226
3190
|
{/* Chat panels - one per active conversation, shown/hidden via CSS */}
|
|
3227
3191
|
{activeConversationsList.map((activeConv) => (
|
|
3228
3192
|
<ChatPanelWrapper
|
|
@@ -3253,6 +3217,7 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
|
|
|
3253
3217
|
contextSections={mergedContext.sections}
|
|
3254
3218
|
totalContextTokens={filteredContext.totalTokens}
|
|
3255
3219
|
maxContextTokens={maxContextTokens}
|
|
3220
|
+
contextUpdateSignal={contextUpdateSignal}
|
|
3256
3221
|
enableContextDetailView={enableContextDetailView}
|
|
3257
3222
|
disabledSectionIds={currentDisabledSections}
|
|
3258
3223
|
onToggleSection={handleContextSectionToggle}
|
package/src/AIChatPanel.css
CHANGED
|
@@ -1781,7 +1781,7 @@
|
|
|
1781
1781
|
align-items: center;
|
|
1782
1782
|
gap: 4px;
|
|
1783
1783
|
flex-shrink: 0;
|
|
1784
|
-
margin-left:
|
|
1784
|
+
margin-left: 0;
|
|
1785
1785
|
}
|
|
1786
1786
|
|
|
1787
1787
|
.ai-chat-context-pill-anchor {
|
|
@@ -1872,8 +1872,10 @@
|
|
|
1872
1872
|
.ai-chat-context-pill {
|
|
1873
1873
|
display: flex;
|
|
1874
1874
|
align-items: center;
|
|
1875
|
-
|
|
1876
|
-
|
|
1875
|
+
justify-content: center;
|
|
1876
|
+
gap: 0;
|
|
1877
|
+
min-width: 30px;
|
|
1878
|
+
padding: 4px 8px;
|
|
1877
1879
|
background: var(--ai-chat-suggestion-bg, #f3f4f6);
|
|
1878
1880
|
border: none;
|
|
1879
1881
|
border-radius: 999px;
|
|
@@ -1898,6 +1900,10 @@
|
|
|
1898
1900
|
color: #f59e0b;
|
|
1899
1901
|
}
|
|
1900
1902
|
|
|
1903
|
+
.ai-chat-context-pill--updated {
|
|
1904
|
+
box-shadow: 0 0 0 1px rgba(245, 158, 11, 0.24), 0 0 10px rgba(245, 158, 11, 0.18);
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1901
1907
|
.ai-chat-context-pill__count {
|
|
1902
1908
|
display: none;
|
|
1903
1909
|
border-radius: 999px;
|
|
@@ -1909,6 +1915,47 @@
|
|
|
1909
1915
|
font-size: 12px;
|
|
1910
1916
|
}
|
|
1911
1917
|
|
|
1918
|
+
.ai-chat-context-pill__icon {
|
|
1919
|
+
position: relative;
|
|
1920
|
+
display: inline-flex;
|
|
1921
|
+
align-items: center;
|
|
1922
|
+
justify-content: center;
|
|
1923
|
+
width: 14px;
|
|
1924
|
+
height: 14px;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
.ai-chat-context-pill__icon .ai-chat-icon-sm {
|
|
1928
|
+
width: 14px;
|
|
1929
|
+
height: 14px;
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
.ai-chat-context-pill__spark {
|
|
1933
|
+
position: absolute;
|
|
1934
|
+
top: -7px;
|
|
1935
|
+
right: -7px;
|
|
1936
|
+
font-size: 10px;
|
|
1937
|
+
line-height: 1;
|
|
1938
|
+
color: #f59e0b;
|
|
1939
|
+
text-shadow: 0 0 6px rgba(245, 158, 11, 0.55);
|
|
1940
|
+
pointer-events: none;
|
|
1941
|
+
animation: contextPillSpark 1.6s ease-out forwards;
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
@keyframes contextPillSpark {
|
|
1945
|
+
0% {
|
|
1946
|
+
opacity: 0;
|
|
1947
|
+
transform: scale(0.7) translateY(2px);
|
|
1948
|
+
}
|
|
1949
|
+
24% {
|
|
1950
|
+
opacity: 0.95;
|
|
1951
|
+
transform: scale(1) translateY(0);
|
|
1952
|
+
}
|
|
1953
|
+
100% {
|
|
1954
|
+
opacity: 0;
|
|
1955
|
+
transform: scale(1.08) translateY(-2px);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1912
1959
|
.ai-chat-context-pill__tokens {
|
|
1913
1960
|
display: none;
|
|
1914
1961
|
}
|
|
@@ -2352,6 +2399,10 @@
|
|
|
2352
2399
|
background: var(--ai-chat-suggestion-hover-bg, #4b5563);
|
|
2353
2400
|
}
|
|
2354
2401
|
|
|
2402
|
+
.dark-theme .ai-chat-context-pill--updated {
|
|
2403
|
+
box-shadow: 0 0 0 1px rgba(245, 158, 11, 0.35), 0 0 12px rgba(245, 158, 11, 0.22);
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2355
2406
|
.dark-theme .ai-chat-context-popover {
|
|
2356
2407
|
background: var(--ai-chat-input-bg, #1f2937);
|
|
2357
2408
|
border-color: var(--ai-chat-input-border, #374151);
|
|
@@ -2400,6 +2451,17 @@
|
|
|
2400
2451
|
}
|
|
2401
2452
|
}
|
|
2402
2453
|
|
|
2454
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2455
|
+
.ai-chat-context-pill {
|
|
2456
|
+
transition: none;
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
.ai-chat-context-pill__spark {
|
|
2460
|
+
animation: none;
|
|
2461
|
+
opacity: 0.9;
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2403
2465
|
/* ============================================================================
|
|
2404
2466
|
Error Banner
|
|
2405
2467
|
============================================================================ */
|
package/src/AIChatPanel.tsx
CHANGED
|
@@ -195,6 +195,7 @@ export interface AIChatPanelProps {
|
|
|
195
195
|
contextSections?: ContextSection[];
|
|
196
196
|
totalContextTokens?: number;
|
|
197
197
|
maxContextTokens?: number;
|
|
198
|
+
contextUpdateSignal?: number;
|
|
198
199
|
enableContextDetailView?: boolean;
|
|
199
200
|
disabledSectionIds?: Set<string>;
|
|
200
201
|
onToggleSection?: (sectionId: string, enabled: boolean) => void;
|
|
@@ -1726,6 +1727,7 @@ interface ChatInputProps {
|
|
|
1726
1727
|
contextSections?: ContextSection[];
|
|
1727
1728
|
totalContextTokens?: number;
|
|
1728
1729
|
maxContextTokens?: number;
|
|
1730
|
+
contextUpdateSignal?: number;
|
|
1729
1731
|
enableContextDetailView?: boolean;
|
|
1730
1732
|
disabledSectionIds?: Set<string>;
|
|
1731
1733
|
onToggleSection?: (sectionId: string, enabled: boolean) => void;
|
|
@@ -1752,6 +1754,7 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
1752
1754
|
contextSections = [],
|
|
1753
1755
|
totalContextTokens = 0,
|
|
1754
1756
|
maxContextTokens = 8000,
|
|
1757
|
+
contextUpdateSignal = 0,
|
|
1755
1758
|
enableContextDetailView = false,
|
|
1756
1759
|
disabledSectionIds = new Set(),
|
|
1757
1760
|
onToggleSection,
|
|
@@ -1762,9 +1765,12 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
1762
1765
|
const [contextViewerOpen, setContextViewerOpen] = useState(false);
|
|
1763
1766
|
const [contextViewMode, setContextViewMode] = useState<'summary' | 'detail'>('summary');
|
|
1764
1767
|
const [expandedSectionId, setExpandedSectionId] = useState<string | null>(null);
|
|
1768
|
+
const [showContextUpdateCue, setShowContextUpdateCue] = useState(false);
|
|
1769
|
+
const [contextUpdateCueKey, setContextUpdateCueKey] = useState(0);
|
|
1765
1770
|
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
|
|
1766
1771
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
1767
1772
|
const contextPopoverRef = useRef<HTMLDivElement | null>(null);
|
|
1773
|
+
const contextUpdateCueTimeoutRef = useRef<number | null>(null);
|
|
1768
1774
|
const [userInputSelections, setUserInputSelections] = useState<Record<string, string>>({});
|
|
1769
1775
|
const [userInputWriteIns, setUserInputWriteIns] = useState<Record<string, string>>({});
|
|
1770
1776
|
const [userInputValidationError, setUserInputValidationError] = useState('');
|
|
@@ -1892,6 +1898,33 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
1892
1898
|
}
|
|
1893
1899
|
}, [contextViewerOpen]);
|
|
1894
1900
|
|
|
1901
|
+
useEffect(() => {
|
|
1902
|
+
if (contextUpdateSignal <= 0) {
|
|
1903
|
+
return;
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
setShowContextUpdateCue(true);
|
|
1907
|
+
setContextUpdateCueKey((prev) => prev + 1);
|
|
1908
|
+
|
|
1909
|
+
if (contextUpdateCueTimeoutRef.current) {
|
|
1910
|
+
window.clearTimeout(contextUpdateCueTimeoutRef.current);
|
|
1911
|
+
contextUpdateCueTimeoutRef.current = null;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
contextUpdateCueTimeoutRef.current = window.setTimeout(() => {
|
|
1915
|
+
setShowContextUpdateCue(false);
|
|
1916
|
+
contextUpdateCueTimeoutRef.current = null;
|
|
1917
|
+
}, 1800);
|
|
1918
|
+
}, [contextUpdateSignal]);
|
|
1919
|
+
|
|
1920
|
+
useEffect(() => {
|
|
1921
|
+
return () => {
|
|
1922
|
+
if (contextUpdateCueTimeoutRef.current) {
|
|
1923
|
+
window.clearTimeout(contextUpdateCueTimeoutRef.current);
|
|
1924
|
+
}
|
|
1925
|
+
};
|
|
1926
|
+
}, []);
|
|
1927
|
+
|
|
1895
1928
|
// Format tokens for display
|
|
1896
1929
|
const formatTokens = (tokens: number): string => {
|
|
1897
1930
|
if (tokens >= 1000) {
|
|
@@ -2251,11 +2284,12 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
2251
2284
|
<div className="ai-chat-context-pill-wrapper">
|
|
2252
2285
|
<div className="ai-chat-context-pill-anchor">
|
|
2253
2286
|
<button
|
|
2254
|
-
className={`ai-chat-context-pill ${contextViewerOpen ? 'ai-chat-context-pill--active' : ''} ${isOverLimit ? 'ai-chat-context-pill--warning' : ''}`}
|
|
2287
|
+
className={`ai-chat-context-pill ${contextViewerOpen ? 'ai-chat-context-pill--active' : ''} ${isOverLimit ? 'ai-chat-context-pill--warning' : ''} ${showContextUpdateCue && !contextViewerOpen ? 'ai-chat-context-pill--updated' : ''}`}
|
|
2255
2288
|
onClick={(e) => {
|
|
2256
2289
|
e.preventDefault();
|
|
2257
2290
|
e.stopPropagation();
|
|
2258
2291
|
console.log('[ContextViewer] Button clicked, current state:', contextViewerOpen);
|
|
2292
|
+
setShowContextUpdateCue(false);
|
|
2259
2293
|
setContextViewerOpen(!contextViewerOpen);
|
|
2260
2294
|
if (!contextViewerOpen) {
|
|
2261
2295
|
setContextViewMode('summary');
|
|
@@ -2266,8 +2300,20 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
2266
2300
|
}}
|
|
2267
2301
|
type="button"
|
|
2268
2302
|
title="View context"
|
|
2303
|
+
aria-label="View context"
|
|
2269
2304
|
>
|
|
2270
|
-
<span className="ai-chat-context-
|
|
2305
|
+
<span className="ai-chat-context-pill__icon" aria-hidden="true">
|
|
2306
|
+
<ContextViewerIcon />
|
|
2307
|
+
{showContextUpdateCue && !contextViewerOpen && (
|
|
2308
|
+
<span
|
|
2309
|
+
key={contextUpdateCueKey}
|
|
2310
|
+
className="ai-chat-context-pill__spark"
|
|
2311
|
+
aria-hidden="true"
|
|
2312
|
+
>
|
|
2313
|
+
*
|
|
2314
|
+
</span>
|
|
2315
|
+
)}
|
|
2316
|
+
</span>
|
|
2271
2317
|
</button>
|
|
2272
2318
|
|
|
2273
2319
|
{/* Context popover - positioned relative to context pill */}
|
|
@@ -2552,6 +2598,7 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
2552
2598
|
contextSections = [],
|
|
2553
2599
|
totalContextTokens = 0,
|
|
2554
2600
|
maxContextTokens = 8000,
|
|
2601
|
+
contextUpdateSignal = 0,
|
|
2555
2602
|
enableContextDetailView = false,
|
|
2556
2603
|
disabledSectionIds: propDisabledSectionIds,
|
|
2557
2604
|
onToggleSection: propOnToggleSection,
|
|
@@ -6969,6 +7016,7 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
6969
7016
|
contextSections={contextSections}
|
|
6970
7017
|
totalContextTokens={totalContextTokens}
|
|
6971
7018
|
maxContextTokens={maxContextTokens}
|
|
7019
|
+
contextUpdateSignal={contextUpdateSignal}
|
|
6972
7020
|
enableContextDetailView={enableContextDetailView}
|
|
6973
7021
|
disabledSectionIds={disabledSectionIds}
|
|
6974
7022
|
onToggleSection={handleToggleSection}
|
|
Binary file
|