@open-mercato/ai-assistant 0.5.1-develop.2856.35de414092 → 0.5.1-develop.2874.77704bccbd
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/frontend/components/AiDot/AiDot.js +2 -2
- package/dist/frontend/components/AiDot/AiDot.js.map +1 -1
- package/dist/frontend/components/CommandPalette/CommandFooter.js +2 -2
- package/dist/frontend/components/CommandPalette/CommandFooter.js.map +1 -1
- package/dist/frontend/components/CommandPalette/CommandPalette.js +4 -4
- package/dist/frontend/components/CommandPalette/CommandPalette.js.map +2 -2
- package/dist/frontend/components/CommandPalette/DebugPanel.js +1 -1
- package/dist/frontend/components/CommandPalette/DebugPanel.js.map +1 -1
- package/dist/frontend/components/CommandPalette/MessageBubble.js +2 -2
- package/dist/frontend/components/CommandPalette/MessageBubble.js.map +1 -1
- package/dist/frontend/components/CommandPalette/ToolCallConfirmation.js +3 -3
- package/dist/frontend/components/CommandPalette/ToolCallConfirmation.js.map +2 -2
- package/dist/frontend/components/CommandPalette/ToolChatPage.js +1 -1
- package/dist/frontend/components/CommandPalette/ToolChatPage.js.map +1 -1
- package/dist/frontend/components/DockableChat/DockableChat.js +4 -4
- package/dist/frontend/components/DockableChat/DockableChat.js.map +1 -1
- package/dist/modules/ai_assistant/components/AiAssistantSettingsPageClient.js +14 -14
- package/dist/modules/ai_assistant/components/AiAssistantSettingsPageClient.js.map +2 -2
- package/dist/modules/ai_assistant/components/McpConfigDialog.js +3 -3
- package/dist/modules/ai_assistant/components/McpConfigDialog.js.map +2 -2
- package/dist/modules/ai_assistant/frontend/components/AiAssistantSettingsPageClient.js +14 -14
- package/dist/modules/ai_assistant/frontend/components/AiAssistantSettingsPageClient.js.map +2 -2
- package/package.json +4 -4
- package/src/frontend/components/AiDot/AiDot.tsx +2 -2
- package/src/frontend/components/CommandPalette/CommandFooter.tsx +2 -2
- package/src/frontend/components/CommandPalette/CommandPalette.tsx +4 -4
- package/src/frontend/components/CommandPalette/DebugPanel.tsx +1 -1
- package/src/frontend/components/CommandPalette/MessageBubble.tsx +2 -2
- package/src/frontend/components/CommandPalette/ToolCallConfirmation.tsx +3 -3
- package/src/frontend/components/CommandPalette/ToolChatPage.tsx +1 -1
- package/src/frontend/components/DockableChat/DockableChat.tsx +4 -4
- package/src/modules/ai_assistant/components/AiAssistantSettingsPageClient.tsx +15 -15
- package/src/modules/ai_assistant/components/McpConfigDialog.tsx +3 -3
- package/src/modules/ai_assistant/frontend/components/AiAssistantSettingsPageClient.tsx +15 -15
|
@@ -14,13 +14,13 @@ function AiDot({ onClick, isActive, hasMessages, position, className }) {
|
|
|
14
14
|
type: "button",
|
|
15
15
|
onClick,
|
|
16
16
|
className: cn(
|
|
17
|
-
"fixed z-
|
|
17
|
+
"fixed z-sticky group",
|
|
18
18
|
"w-14 h-14 rounded-full",
|
|
19
19
|
"flex items-center justify-center",
|
|
20
20
|
"cursor-pointer",
|
|
21
21
|
"transition-transform duration-200 ease-out",
|
|
22
22
|
"hover:scale-110 active:scale-95",
|
|
23
|
-
"focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
23
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
24
24
|
className
|
|
25
25
|
),
|
|
26
26
|
style: floatingPositionStyles[position],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/frontend/components/AiDot/AiDot.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport type { FloatingPosition } from '../../types'\n\nexport interface AiDotProps {\n onClick: () => void\n isActive?: boolean\n hasMessages?: boolean\n position: FloatingPosition\n className?: string\n}\n\nconst floatingPositionStyles: Record<FloatingPosition, React.CSSProperties> = {\n 'bottom-right': { bottom: 24, right: 24 },\n 'bottom-left': { bottom: 24, left: 24 },\n 'top-right': { top: 24, right: 24 },\n 'top-left': { top: 24, left: 24 },\n}\n\nexport function AiDot({ onClick, isActive, hasMessages, position, className }: AiDotProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n 'fixed z-
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport type { FloatingPosition } from '../../types'\n\nexport interface AiDotProps {\n onClick: () => void\n isActive?: boolean\n hasMessages?: boolean\n position: FloatingPosition\n className?: string\n}\n\nconst floatingPositionStyles: Record<FloatingPosition, React.CSSProperties> = {\n 'bottom-right': { bottom: 24, right: 24 },\n 'bottom-left': { bottom: 24, left: 24 },\n 'top-right': { top: 24, right: 24 },\n 'top-left': { top: 24, left: 24 },\n}\n\nexport function AiDot({ onClick, isActive, hasMessages, position, className }: AiDotProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n 'fixed z-sticky group',\n 'w-14 h-14 rounded-full',\n 'flex items-center justify-center',\n 'cursor-pointer',\n 'transition-transform duration-200 ease-out',\n 'hover:scale-110 active:scale-95',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className\n )}\n style={floatingPositionStyles[position]}\n aria-label=\"Open AI Assistant\"\n >\n {/* Outer glow effect */}\n <div\n className={cn(\n 'absolute inset-0 rounded-full',\n 'bg-gradient-to-r from-violet-500/30 via-fuchsia-500/30 to-cyan-500/30',\n 'blur-xl',\n isActive ? 'animate-ai-glow-active' : 'animate-ai-glow'\n )}\n />\n\n {/* Main gradient orb */}\n <div\n className={cn(\n 'relative w-12 h-12 rounded-full',\n 'bg-gradient-to-br from-violet-600 via-fuchsia-500 to-cyan-400',\n 'shadow-lg shadow-violet-500/25',\n isActive ? 'animate-ai-pulse-active' : 'animate-ai-pulse'\n )}\n >\n {/* Inner highlight */}\n <div className=\"absolute inset-1 rounded-full bg-gradient-to-br from-white/20 to-transparent\" />\n\n {/* Animated gradient overlay */}\n <div\n className={cn(\n 'absolute inset-0 rounded-full',\n 'bg-gradient-conic from-violet-600 via-fuchsia-500 via-cyan-400 to-violet-600',\n 'opacity-60',\n 'animate-ai-spin'\n )}\n style={{ mixBlendMode: 'overlay' }}\n />\n\n {/* Center sparkle icon */}\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className=\"text-white drop-shadow-sm\"\n >\n <path\n d=\"M12 2L14.5 9.5L22 12L14.5 14.5L12 22L9.5 14.5L2 12L9.5 9.5L12 2Z\"\n fill=\"currentColor\"\n className={cn(\n 'origin-center',\n isActive ? 'animate-ai-sparkle-active' : 'animate-ai-sparkle'\n )}\n />\n </svg>\n </div>\n </div>\n\n {/* Message indicator badge */}\n {hasMessages && (\n <div\n className={cn(\n 'absolute top-1 right-1',\n 'w-3 h-3 rounded-full',\n 'bg-emerald-500 border-2 border-white',\n 'shadow-sm',\n 'animate-pulse'\n )}\n />\n )}\n </button>\n )\n}\n\nexport default AiDot\n"],
|
|
5
5
|
"mappings": ";AAwCM,cAUA,YAVA;AArCN,SAAS,UAAU;AAWnB,MAAM,yBAAwE;AAAA,EAC5E,gBAAgB,EAAE,QAAQ,IAAI,OAAO,GAAG;AAAA,EACxC,eAAe,EAAE,QAAQ,IAAI,MAAM,GAAG;AAAA,EACtC,aAAa,EAAE,KAAK,IAAI,OAAO,GAAG;AAAA,EAClC,YAAY,EAAE,KAAK,IAAI,MAAM,GAAG;AAClC;AAEO,SAAS,MAAM,EAAE,SAAS,UAAU,aAAa,UAAU,UAAU,GAAe;AACzF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO,uBAAuB,QAAQ;AAAA,MACtC,cAAW;AAAA,MAGX;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACA,WAAW,2BAA2B;AAAA,YACxC;AAAA;AAAA,QACF;AAAA,QAGA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACA,WAAW,4BAA4B;AAAA,YACzC;AAAA,YAGA;AAAA,kCAAC,SAAI,WAAU,gFAA+E;AAAA,cAG9F;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAW;AAAA,oBACT;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,kBACF;AAAA,kBACA,OAAO,EAAE,cAAc,UAAU;AAAA;AAAA,cACnC;AAAA,cAGA,oBAAC,SAAI,WAAU,qDACb;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAM;AAAA,kBACN,QAAO;AAAA,kBACP,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,WAAU;AAAA,kBAEV;AAAA,oBAAC;AAAA;AAAA,sBACC,GAAE;AAAA,sBACF,MAAK;AAAA,sBACL,WAAW;AAAA,wBACT;AAAA,wBACA,WAAW,8BAA8B;AAAA,sBAC3C;AAAA;AAAA,kBACF;AAAA;AAAA,cACF,GACF;AAAA;AAAA;AAAA,QACF;AAAA,QAGC,eACC;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,IAAO,gBAAQ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -21,7 +21,7 @@ function KeyboardShortcut({ keys }) {
|
|
|
21
21
|
{
|
|
22
22
|
className: cn(
|
|
23
23
|
"inline-flex h-5 min-w-[20px] items-center justify-center rounded",
|
|
24
|
-
"bg-muted px-1.5 text-
|
|
24
|
+
"bg-muted px-1.5 text-overline font-medium text-muted-foreground"
|
|
25
25
|
),
|
|
26
26
|
children: key
|
|
27
27
|
},
|
|
@@ -44,7 +44,7 @@ function CommandFooter({
|
|
|
44
44
|
{ label: "Back", keys: ["Esc"] }
|
|
45
45
|
];
|
|
46
46
|
const shortcuts = phase === "idle" ? idleShortcuts : chatShortcuts;
|
|
47
|
-
return /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-between px-3 py-2 border-t bg-muted/
|
|
47
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-between px-3 py-2 border-t bg-muted/30 text-xs", children: [
|
|
48
48
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
49
49
|
/* @__PURE__ */ jsx(ConnectionIndicator, { status: connectionStatus }),
|
|
50
50
|
isSessionAuthorized && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-xs text-emerald-600 dark:text-emerald-400", children: [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/frontend/components/CommandPalette/CommandFooter.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Code, ShieldCheck } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport type { PalettePhase, ConnectionStatus } from '../../types'\n\ninterface CommandFooterProps {\n phase: PalettePhase\n connectionStatus: ConnectionStatus\n isSessionAuthorized?: boolean\n showDebug?: boolean\n onToggleDebug?: () => void\n}\n\nfunction ConnectionIndicator({ status }: { status: ConnectionStatus }) {\n const statusConfig: Record<ConnectionStatus, { color: string; text: string }> = {\n connected: { color: 'bg-emerald-500', text: 'Connected' },\n connecting: { color: 'bg-yellow-500 animate-pulse', text: 'Connecting...' },\n disconnected: { color: 'bg-gray-400', text: 'Disconnected' },\n error: { color: 'bg-red-500', text: 'Error' },\n }\n\n const config = statusConfig[status]\n\n return (\n <div className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <div className={cn('h-1.5 w-1.5 rounded-full', config.color)} />\n <span>{config.text}</span>\n </div>\n )\n}\n\nfunction KeyboardShortcut({ keys }: { keys: string[] }) {\n return (\n <div className=\"flex items-center gap-0.5\">\n {keys.map((key, i) => (\n <kbd\n key={i}\n className={cn(\n 'inline-flex h-5 min-w-[20px] items-center justify-center rounded',\n 'bg-muted px-1.5 text-
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Code, ShieldCheck } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport type { PalettePhase, ConnectionStatus } from '../../types'\n\ninterface CommandFooterProps {\n phase: PalettePhase\n connectionStatus: ConnectionStatus\n isSessionAuthorized?: boolean\n showDebug?: boolean\n onToggleDebug?: () => void\n}\n\nfunction ConnectionIndicator({ status }: { status: ConnectionStatus }) {\n const statusConfig: Record<ConnectionStatus, { color: string; text: string }> = {\n connected: { color: 'bg-emerald-500', text: 'Connected' },\n connecting: { color: 'bg-yellow-500 animate-pulse', text: 'Connecting...' },\n disconnected: { color: 'bg-gray-400', text: 'Disconnected' },\n error: { color: 'bg-red-500', text: 'Error' },\n }\n\n const config = statusConfig[status]\n\n return (\n <div className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <div className={cn('h-1.5 w-1.5 rounded-full', config.color)} />\n <span>{config.text}</span>\n </div>\n )\n}\n\nfunction KeyboardShortcut({ keys }: { keys: string[] }) {\n return (\n <div className=\"flex items-center gap-0.5\">\n {keys.map((key, i) => (\n <kbd\n key={i}\n className={cn(\n 'inline-flex h-5 min-w-[20px] items-center justify-center rounded',\n 'bg-muted px-1.5 text-overline font-medium text-muted-foreground'\n )}\n >\n {key}\n </kbd>\n ))}\n </div>\n )\n}\n\nexport function CommandFooter({\n phase,\n connectionStatus,\n isSessionAuthorized = false,\n showDebug = false,\n onToggleDebug,\n}: CommandFooterProps) {\n const idleShortcuts = [\n { label: 'Submit', keys: ['\\u21B5'] },\n { label: 'Close', keys: ['Esc'] },\n ]\n\n const chatShortcuts = [\n { label: 'Send', keys: ['\\u21B5'] },\n { label: 'Back', keys: ['Esc'] },\n ]\n\n const shortcuts = phase === 'idle' ? idleShortcuts : chatShortcuts\n\n return (\n <div className=\"relative flex items-center justify-between px-3 py-2 border-t bg-muted/30 text-xs\">\n <div className=\"flex items-center gap-3\">\n <ConnectionIndicator status={connectionStatus} />\n\n {/* Session authorization indicator */}\n {isSessionAuthorized && (\n <div className=\"flex items-center gap-1 text-xs text-emerald-600 dark:text-emerald-400\">\n <ShieldCheck className=\"h-3 w-3\" />\n <span>Authorized</span>\n </div>\n )}\n\n {/* Debug toggle button */}\n {onToggleDebug && (\n <button\n type=\"button\"\n onClick={onToggleDebug}\n className={cn(\n 'flex items-center gap-1 transition-colors',\n showDebug\n ? 'text-blue-500 hover:text-blue-400'\n : 'text-muted-foreground hover:text-foreground'\n )}\n title=\"Toggle debug panel\"\n >\n <Code className=\"w-3 h-3\" />\n <span>{showDebug ? 'Hide Debug' : 'Debug'}</span>\n </button>\n )}\n </div>\n\n <div className=\"flex items-center gap-3\">\n {shortcuts.map((shortcut, i) => (\n <div key={i} className=\"flex items-center gap-1.5 text-muted-foreground\">\n <span>{shortcut.label}</span>\n <KeyboardShortcut keys={shortcut.keys} />\n </div>\n ))}\n </div>\n </div>\n )\n}\n"],
|
|
5
5
|
"mappings": ";AA0BI,SACE,KADF;AAvBJ,SAAS,MAAM,mBAAmB;AAClC,SAAS,UAAU;AAWnB,SAAS,oBAAoB,EAAE,OAAO,GAAiC;AACrE,QAAM,eAA0E;AAAA,IAC9E,WAAW,EAAE,OAAO,kBAAkB,MAAM,YAAY;AAAA,IACxD,YAAY,EAAE,OAAO,+BAA+B,MAAM,gBAAgB;AAAA,IAC1E,cAAc,EAAE,OAAO,eAAe,MAAM,eAAe;AAAA,IAC3D,OAAO,EAAE,OAAO,cAAc,MAAM,QAAQ;AAAA,EAC9C;AAEA,QAAM,SAAS,aAAa,MAAM;AAElC,SACE,qBAAC,SAAI,WAAU,2DACb;AAAA,wBAAC,SAAI,WAAW,GAAG,4BAA4B,OAAO,KAAK,GAAG;AAAA,IAC9D,oBAAC,UAAM,iBAAO,MAAK;AAAA,KACrB;AAEJ;AAEA,SAAS,iBAAiB,EAAE,KAAK,GAAuB;AACtD,SACE,oBAAC,SAAI,WAAU,6BACZ,eAAK,IAAI,CAAC,KAAK,MACd;AAAA,IAAC;AAAA;AAAA,MAEC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,IANI;AAAA,EAOP,CACD,GACH;AAEJ;AAEO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,sBAAsB;AAAA,EACtB,YAAY;AAAA,EACZ;AACF,GAAuB;AACrB,QAAM,gBAAgB;AAAA,IACpB,EAAE,OAAO,UAAU,MAAM,CAAC,QAAQ,EAAE;AAAA,IACpC,EAAE,OAAO,SAAS,MAAM,CAAC,KAAK,EAAE;AAAA,EAClC;AAEA,QAAM,gBAAgB;AAAA,IACpB,EAAE,OAAO,QAAQ,MAAM,CAAC,QAAQ,EAAE;AAAA,IAClC,EAAE,OAAO,QAAQ,MAAM,CAAC,KAAK,EAAE;AAAA,EACjC;AAEA,QAAM,YAAY,UAAU,SAAS,gBAAgB;AAErD,SACE,qBAAC,SAAI,WAAU,qFACb;AAAA,yBAAC,SAAI,WAAU,2BACb;AAAA,0BAAC,uBAAoB,QAAQ,kBAAkB;AAAA,MAG9C,uBACC,qBAAC,SAAI,WAAU,0EACb;AAAA,4BAAC,eAAY,WAAU,WAAU;AAAA,QACjC,oBAAC,UAAK,wBAAU;AAAA,SAClB;AAAA,MAID,iBACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,WAAW;AAAA,YACT;AAAA,YACA,YACI,sCACA;AAAA,UACN;AAAA,UACA,OAAM;AAAA,UAEN;AAAA,gCAAC,QAAK,WAAU,WAAU;AAAA,YAC1B,oBAAC,UAAM,sBAAY,eAAe,SAAQ;AAAA;AAAA;AAAA,MAC5C;AAAA,OAEJ;AAAA,IAEA,oBAAC,SAAI,WAAU,2BACZ,oBAAU,IAAI,CAAC,UAAU,MACxB,qBAAC,SAAY,WAAU,mDACrB;AAAA,0BAAC,UAAM,mBAAS,OAAM;AAAA,MACtB,oBAAC,oBAAiB,MAAM,SAAS,MAAM;AAAA,SAF/B,CAGV,CACD,GACH;AAAA,KACF;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -115,12 +115,12 @@ function CommandPalette() {
|
|
|
115
115
|
}
|
|
116
116
|
};
|
|
117
117
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
118
|
-
isOpen && showDebug && /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-
|
|
118
|
+
isOpen && showDebug && /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-overlay bg-black/50 backdrop-blur-sm pointer-events-none" }),
|
|
119
119
|
/* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: handleOpenChange, modal: !showDebug, children: /* @__PURE__ */ jsxs(
|
|
120
120
|
DialogContent,
|
|
121
121
|
{
|
|
122
122
|
className: cn(
|
|
123
|
-
"fixed left-1/2 top-[10vh] z-
|
|
123
|
+
"fixed left-1/2 top-[10vh] z-modal -translate-x-1/2",
|
|
124
124
|
"w-full max-w-2xl p-0",
|
|
125
125
|
"rounded-xl border bg-background shadow-2xl",
|
|
126
126
|
"flex flex-col"
|
|
@@ -189,7 +189,7 @@ function CommandPalette() {
|
|
|
189
189
|
placeholder: "Describe what you want to do...",
|
|
190
190
|
className: cn(
|
|
191
191
|
"flex-1 bg-muted rounded-lg px-4 py-2 text-sm outline-none",
|
|
192
|
-
"focus:ring-2 focus:ring-ring",
|
|
192
|
+
"focus-visible:ring-2 focus-visible:ring-ring",
|
|
193
193
|
"disabled:opacity-50"
|
|
194
194
|
),
|
|
195
195
|
disabled: isStreaming
|
|
@@ -226,7 +226,7 @@ function CommandPalette() {
|
|
|
226
226
|
"div",
|
|
227
227
|
{
|
|
228
228
|
"data-debug-panel": true,
|
|
229
|
-
className: "fixed z-
|
|
229
|
+
className: "fixed z-top bg-gray-900 rounded-xl border border-gray-700 shadow-2xl flex flex-col overflow-hidden",
|
|
230
230
|
style: { top: "80px", right: "20px", width: "400px", minWidth: "400px", maxWidth: "400px", maxHeight: "calc(100vh - 100px)" },
|
|
231
231
|
children: /* @__PURE__ */ jsx(
|
|
232
232
|
DebugPanel,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/frontend/components/CommandPalette/CommandPalette.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\nimport { Command } from 'cmdk'\nimport { Loader2, Send, Square } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Dialog, DialogContent, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { VisuallyHidden } from '@radix-ui/react-visually-hidden'\nimport { useCommandPaletteContext } from './CommandPaletteProvider'\nimport { CommandInput } from './CommandInput'\nimport { CommandHeader } from './CommandHeader'\nimport { CommandFooter } from './CommandFooter'\nimport { ToolChatPage } from './ToolChatPage'\nimport { DebugPanel } from './DebugPanel'\n\n// Idle state - shown when palette is open but no query submitted\nfunction IdleState() {\n return (\n <div className=\"py-8 px-4 text-center text-muted-foreground\">\n <p className=\"mb-2\">Ask me anything or describe what you want to do.</p>\n <p className=\"text-sm\">Examples:</p>\n <ul className=\"text-sm mt-2 space-y-1\">\n <li>"Search for customers in New York"</li>\n <li>"Create a new product"</li>\n <li>"Show me recent orders"</li>\n </ul>\n </div>\n )\n}\n\n// Routing indicator - shown while fast model analyzes intent\nfunction RoutingIndicator() {\n return (\n <div className=\"py-8 flex items-center justify-center gap-2\">\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n <span className=\"text-sm text-muted-foreground\">Analyzing request...</span>\n </div>\n )\n}\n\nexport function CommandPalette() {\n const {\n state,\n isThinking,\n agentStatus,\n isSessionAuthorized,\n messages,\n pendingToolCalls,\n selectedTool,\n close,\n setInputValue,\n handleSubmit,\n reset,\n sendAgenticMessage,\n stopExecution,\n approveToolCall,\n rejectToolCall,\n debugEvents,\n showDebug,\n setShowDebug,\n clearDebugEvents,\n pendingQuestion,\n answerQuestion,\n } = useCommandPaletteContext()\n\n const {\n isOpen,\n phase,\n inputValue,\n isLoading,\n isStreaming,\n connectionStatus,\n } = state\n\n const [localInput, setLocalInput] = React.useState('')\n const [chatInput, setChatInput] = React.useState('')\n const chatInputRef = React.useRef<HTMLInputElement>(null)\n\n // Reset local input when phase changes to idle\n React.useEffect(() => {\n if (phase === 'idle') {\n setLocalInput('')\n setChatInput('')\n }\n }, [phase])\n\n // Focus chat input when entering chatting phase\n React.useEffect(() => {\n if (phase === 'chatting' || phase === 'confirming' || phase === 'executing') {\n // Small delay to ensure DOM is ready\n setTimeout(() => chatInputRef.current?.focus(), 50)\n }\n }, [phase])\n\n const handleOpenChange = (open: boolean) => {\n if (!open) {\n close()\n }\n }\n\n const handleInputSubmit = async () => {\n const query = localInput.trim()\n if (!query) return\n setLocalInput('')\n await handleSubmit(query)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && phase === 'idle' && localInput.trim()) {\n e.preventDefault()\n handleInputSubmit()\n }\n }\n\n const handleChatSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n if (!chatInput.trim() || isStreaming) return\n\n const content = chatInput\n setChatInput('')\n await sendAgenticMessage(content)\n }\n\n const handleChatKeyDown = (e: React.KeyboardEvent) => {\n // Prevent escape from bubbling to close the palette\n if (e.key === 'Escape') {\n e.stopPropagation()\n }\n // Submit on Enter (not Shift+Enter for multiline)\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n if (chatInput.trim() && !isStreaming) {\n const content = chatInput\n setChatInput('')\n sendAgenticMessage(content)\n }\n }\n }\n\n return (\n <>\n {/* Custom blur overlay when debug mode is on (since modal=false removes it) */}\n {isOpen && showDebug && (\n <div className=\"fixed inset-0 z-
|
|
5
|
-
"mappings": ";AAqBM,SAyHF,UAzHE,KAEA,YAFA;AAnBN,YAAY,WAAW;AACvB,SAAS,oBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,SAAS,MAAM,cAAc;AACtC,SAAS,UAAU;AACnB,SAAS,cAAc;AACvB,SAAS,QAAQ,eAAe,mBAAmB;AACnD,SAAS,sBAAsB;AAC/B,SAAS,gCAAgC;AACzC,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAG3B,SAAS,YAAY;AACnB,SACE,qBAAC,SAAI,WAAU,+CACb;AAAA,wBAAC,OAAE,WAAU,QAAO,8DAAgD;AAAA,IACpE,oBAAC,OAAE,WAAU,WAAU,uBAAS;AAAA,IAChC,qBAAC,QAAG,WAAU,0BACZ;AAAA,0BAAC,QAAG,gDAA4C;AAAA,MAChD,oBAAC,QAAG,oCAAgC;AAAA,MACpC,oBAAC,QAAG,qCAAiC;AAAA,OACvC;AAAA,KACF;AAEJ;AAGA,SAAS,mBAAmB;AAC1B,SACE,qBAAC,SAAI,WAAU,+CACb;AAAA,wBAAC,WAAQ,WAAU,wBAAuB;AAAA,IAC1C,oBAAC,UAAK,WAAU,iCAAgC,kCAAoB;AAAA,KACtE;AAEJ;AAEO,SAAS,iBAAiB;AAC/B,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,yBAAyB;AAE7B,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,EAAE;AACrD,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,EAAE;AACnD,QAAM,eAAe,MAAM,OAAyB,IAAI;AAGxD,QAAM,UAAU,MAAM;AACpB,QAAI,UAAU,QAAQ;AACpB,oBAAc,EAAE;AAChB,mBAAa,EAAE;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AAGV,QAAM,UAAU,MAAM;AACpB,QAAI,UAAU,cAAc,UAAU,gBAAgB,UAAU,aAAa;AAE3E,iBAAW,MAAM,aAAa,SAAS,MAAM,GAAG,EAAE;AAAA,IACpD;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,mBAAmB,CAAC,SAAkB;AAC1C,QAAI,CAAC,MAAM;AACT,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,oBAAoB,YAAY;AACpC,UAAM,QAAQ,WAAW,KAAK;AAC9B,QAAI,CAAC,MAAO;AACZ,kBAAc,EAAE;AAChB,UAAM,aAAa,KAAK;AAAA,EAC1B;AAEA,QAAM,gBAAgB,CAAC,MAA2B;AAChD,QAAI,EAAE,QAAQ,WAAW,UAAU,UAAU,WAAW,KAAK,GAAG;AAC9D,QAAE,eAAe;AACjB,wBAAkB;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,mBAAmB,OAAO,MAAuB;AACrD,MAAE,eAAe;AACjB,QAAI,CAAC,UAAU,KAAK,KAAK,YAAa;AAEtC,UAAM,UAAU;AAChB,iBAAa,EAAE;AACf,UAAM,mBAAmB,OAAO;AAAA,EAClC;AAEA,QAAM,oBAAoB,CAAC,MAA2B;AAEpD,QAAI,EAAE,QAAQ,UAAU;AACtB,QAAE,gBAAgB;AAAA,IACpB;AAEA,QAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AACpC,QAAE,eAAe;AACjB,UAAI,UAAU,KAAK,KAAK,CAAC,aAAa;AACpC,cAAM,UAAU;AAChB,qBAAa,EAAE;AACf,2BAAmB,OAAO;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAEA,SACE,iCAEG;AAAA,cAAU,aACT,oBAAC,SAAI,WAAU,
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\nimport { Command } from 'cmdk'\nimport { Loader2, Send, Square } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Dialog, DialogContent, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { VisuallyHidden } from '@radix-ui/react-visually-hidden'\nimport { useCommandPaletteContext } from './CommandPaletteProvider'\nimport { CommandInput } from './CommandInput'\nimport { CommandHeader } from './CommandHeader'\nimport { CommandFooter } from './CommandFooter'\nimport { ToolChatPage } from './ToolChatPage'\nimport { DebugPanel } from './DebugPanel'\n\n// Idle state - shown when palette is open but no query submitted\nfunction IdleState() {\n return (\n <div className=\"py-8 px-4 text-center text-muted-foreground\">\n <p className=\"mb-2\">Ask me anything or describe what you want to do.</p>\n <p className=\"text-sm\">Examples:</p>\n <ul className=\"text-sm mt-2 space-y-1\">\n <li>"Search for customers in New York"</li>\n <li>"Create a new product"</li>\n <li>"Show me recent orders"</li>\n </ul>\n </div>\n )\n}\n\n// Routing indicator - shown while fast model analyzes intent\nfunction RoutingIndicator() {\n return (\n <div className=\"py-8 flex items-center justify-center gap-2\">\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n <span className=\"text-sm text-muted-foreground\">Analyzing request...</span>\n </div>\n )\n}\n\nexport function CommandPalette() {\n const {\n state,\n isThinking,\n agentStatus,\n isSessionAuthorized,\n messages,\n pendingToolCalls,\n selectedTool,\n close,\n setInputValue,\n handleSubmit,\n reset,\n sendAgenticMessage,\n stopExecution,\n approveToolCall,\n rejectToolCall,\n debugEvents,\n showDebug,\n setShowDebug,\n clearDebugEvents,\n pendingQuestion,\n answerQuestion,\n } = useCommandPaletteContext()\n\n const {\n isOpen,\n phase,\n inputValue,\n isLoading,\n isStreaming,\n connectionStatus,\n } = state\n\n const [localInput, setLocalInput] = React.useState('')\n const [chatInput, setChatInput] = React.useState('')\n const chatInputRef = React.useRef<HTMLInputElement>(null)\n\n // Reset local input when phase changes to idle\n React.useEffect(() => {\n if (phase === 'idle') {\n setLocalInput('')\n setChatInput('')\n }\n }, [phase])\n\n // Focus chat input when entering chatting phase\n React.useEffect(() => {\n if (phase === 'chatting' || phase === 'confirming' || phase === 'executing') {\n // Small delay to ensure DOM is ready\n setTimeout(() => chatInputRef.current?.focus(), 50)\n }\n }, [phase])\n\n const handleOpenChange = (open: boolean) => {\n if (!open) {\n close()\n }\n }\n\n const handleInputSubmit = async () => {\n const query = localInput.trim()\n if (!query) return\n setLocalInput('')\n await handleSubmit(query)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && phase === 'idle' && localInput.trim()) {\n e.preventDefault()\n handleInputSubmit()\n }\n }\n\n const handleChatSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n if (!chatInput.trim() || isStreaming) return\n\n const content = chatInput\n setChatInput('')\n await sendAgenticMessage(content)\n }\n\n const handleChatKeyDown = (e: React.KeyboardEvent) => {\n // Prevent escape from bubbling to close the palette\n if (e.key === 'Escape') {\n e.stopPropagation()\n }\n // Submit on Enter (not Shift+Enter for multiline)\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n if (chatInput.trim() && !isStreaming) {\n const content = chatInput\n setChatInput('')\n sendAgenticMessage(content)\n }\n }\n }\n\n return (\n <>\n {/* Custom blur overlay when debug mode is on (since modal=false removes it) */}\n {isOpen && showDebug && (\n <div className=\"fixed inset-0 z-overlay bg-black/50 backdrop-blur-sm pointer-events-none\" />\n )}\n <Dialog open={isOpen} onOpenChange={handleOpenChange} modal={!showDebug}>\n <DialogContent\n className={cn(\n 'fixed left-1/2 top-[10vh] z-modal -translate-x-1/2',\n 'w-full max-w-2xl p-0',\n 'rounded-xl border bg-background shadow-2xl',\n 'flex flex-col'\n )}\n style={{ maxHeight: 500, overflow: 'hidden' }}\n onKeyDown={handleKeyDown}\n onPointerDownOutside={(e) => {\n // Prevent closing on outside click when debug mode is on\n if (showDebug) {\n e.preventDefault()\n }\n }}\n onInteractOutside={(e) => {\n // Prevent closing on outside interaction when debug mode is on\n if (showDebug) {\n e.preventDefault()\n }\n }}\n >\n {/* Visually hidden title for accessibility */}\n <VisuallyHidden>\n <DialogTitle>AI Command Palette</DialogTitle>\n </VisuallyHidden>\n <Command className=\"flex flex-col flex-1 min-h-0\" shouldFilter={false}>\n {/* Header - shows phase/tool info */}\n <CommandHeader\n phase={phase}\n selectedTool={selectedTool}\n onBack={reset}\n />\n\n {/* Input - shown in idle phase */}\n {phase === 'idle' && (\n <CommandInput\n value={localInput}\n onValueChange={setLocalInput}\n mode=\"commands\"\n isLoading={isLoading}\n placeholder=\"Ask me anything or describe what you want to do...\"\n />\n )}\n\n {/* Content area */}\n <div className=\"flex-1 min-h-0 overflow-y-auto\">\n {phase === 'idle' && !localInput && <IdleState />}\n\n {phase === 'routing' && <RoutingIndicator />}\n\n {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (\n <ToolChatPage\n tool={selectedTool}\n messages={messages}\n pendingToolCalls={pendingToolCalls}\n isStreaming={isStreaming}\n isThinking={isThinking}\n agentStatus={agentStatus}\n onApproveToolCall={approveToolCall}\n onRejectToolCall={rejectToolCall}\n pendingQuestion={pendingQuestion}\n onAnswerQuestion={answerQuestion}\n />\n )}\n </div>\n\n {/* Chat input - shown in chatting phases */}\n {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (\n <form onSubmit={handleChatSubmit} className=\"shrink-0 border-t p-3\">\n <div className=\"flex items-center gap-2\">\n <input\n ref={chatInputRef}\n type=\"text\"\n value={chatInput}\n onChange={(e) => setChatInput(e.target.value)}\n onKeyDown={handleChatKeyDown}\n placeholder=\"Describe what you want to do...\"\n className={cn(\n 'flex-1 bg-muted rounded-lg px-4 py-2 text-sm outline-none',\n 'focus-visible:ring-2 focus-visible:ring-ring',\n 'disabled:opacity-50'\n )}\n disabled={isStreaming}\n />\n <Button\n type={isStreaming ? 'button' : 'submit'}\n size=\"icon\"\n variant={isStreaming ? 'destructive' : 'default'}\n onClick={isStreaming ? stopExecution : undefined}\n disabled={!isStreaming && !chatInput.trim()}\n >\n {isStreaming ? (\n <Square className=\"h-4 w-4\" />\n ) : (\n <Send className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </form>\n )}\n\n {/* Footer with connection status and keyboard hints */}\n <CommandFooter\n phase={phase}\n connectionStatus={connectionStatus}\n isSessionAuthorized={isSessionAuthorized}\n showDebug={showDebug}\n onToggleDebug={() => setShowDebug(!showDebug)}\n />\n </Command>\n </DialogContent>\n </Dialog>\n\n {/* Debug panel - rendered via portal outside the dialog DOM tree */}\n {isOpen && showDebug && typeof document !== 'undefined' && createPortal(\n <div\n data-debug-panel\n className=\"fixed z-top bg-gray-900 rounded-xl border border-gray-700 shadow-2xl flex flex-col overflow-hidden\"\n style={{ top: '80px', right: '20px', width: '400px', minWidth: '400px', maxWidth: '400px', maxHeight: 'calc(100vh - 100px)' }}\n >\n <DebugPanel\n events={debugEvents}\n onClear={clearDebugEvents}\n isOpen={true}\n onToggle={() => setShowDebug(false)}\n />\n </div>,\n document.body\n )}\n </>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -74,7 +74,7 @@ function parseNestedJson(data) {
|
|
|
74
74
|
return data;
|
|
75
75
|
}
|
|
76
76
|
const customDarkStyles = {
|
|
77
|
-
container: "bg-transparent text-
|
|
77
|
+
container: "bg-transparent text-overline leading-relaxed font-mono",
|
|
78
78
|
basicChildStyle: "pl-4 ml-0",
|
|
79
79
|
label: "text-purple-400 mr-1",
|
|
80
80
|
nullValue: "text-gray-500 italic",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/frontend/components/CommandPalette/DebugPanel.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Code, X, Trash2 } from 'lucide-react'\nimport { JsonView } from 'react-json-view-lite'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nexport interface DebugEvent {\n id: string\n timestamp: Date\n type: 'thinking' | 'tool-call' | 'tool-result' | 'text' | 'error' | 'done' | 'message' | 'connection' | 'metadata' | 'debug' | 'question' | 'session-authorized'\n data: unknown\n}\n\ninterface DebugPanelProps {\n events: DebugEvent[]\n onClear: () => void\n isOpen: boolean\n onToggle: () => void\n}\n\nexport function DebugPanel({ events, onClear, isOpen, onToggle }: DebugPanelProps) {\n const scrollRef = React.useRef<HTMLDivElement>(null)\n\n // Filter out text events - only show tool calls, results, errors, etc.\n const filteredEvents = React.useMemo(\n () => events.filter((e) => e.type !== 'text'),\n [events]\n )\n\n React.useEffect(() => {\n if (scrollRef.current) {\n scrollRef.current.scrollTop = scrollRef.current.scrollHeight\n }\n }, [filteredEvents])\n\n if (!isOpen) {\n return null\n }\n\n return (\n <div className=\"flex flex-col h-full min-h-0\">\n <div className=\"flex-shrink-0 flex items-center justify-between px-3 py-2 border-b border-gray-700\">\n <span className=\"text-xs font-medium text-gray-300\">Debug Events ({filteredEvents.length})</span>\n <div className=\"flex gap-2\">\n <button\n onClick={onClear}\n className=\"text-gray-400 hover:text-gray-200\"\n title=\"Clear events\"\n >\n <Trash2 className=\"w-3 h-3\" />\n </button>\n <button\n onClick={onToggle}\n className=\"text-gray-400 hover:text-gray-200\"\n title=\"Close debug panel\"\n >\n <X className=\"w-3 h-3\" />\n </button>\n </div>\n </div>\n <div ref={scrollRef} className=\"flex-1 min-h-0 overflow-y-auto p-2 space-y-1\">\n {filteredEvents.map((event) => (\n <DebugEventRow key={event.id} event={event} />\n ))}\n {filteredEvents.length === 0 && (\n <p className=\"text-xs text-gray-500 text-center py-4\">No events yet</p>\n )}\n </div>\n </div>\n )\n}\n\n// Recursively parse stringified JSON fields\nfunction parseNestedJson(data: unknown): unknown {\n if (typeof data === 'string') {\n try {\n const parsed = JSON.parse(data)\n return parseNestedJson(parsed)\n } catch {\n return data\n }\n }\n if (Array.isArray(data)) {\n return data.map(parseNestedJson)\n }\n if (data && typeof data === 'object') {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(data)) {\n result[key] = parseNestedJson(value)\n }\n return result\n }\n return data\n}\n\n// Custom dark styles for better readability (no external CSS needed)\nconst customDarkStyles: Record<string, string> = {\n container: 'bg-transparent text-
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Code, X, Trash2 } from 'lucide-react'\nimport { JsonView } from 'react-json-view-lite'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nexport interface DebugEvent {\n id: string\n timestamp: Date\n type: 'thinking' | 'tool-call' | 'tool-result' | 'text' | 'error' | 'done' | 'message' | 'connection' | 'metadata' | 'debug' | 'question' | 'session-authorized'\n data: unknown\n}\n\ninterface DebugPanelProps {\n events: DebugEvent[]\n onClear: () => void\n isOpen: boolean\n onToggle: () => void\n}\n\nexport function DebugPanel({ events, onClear, isOpen, onToggle }: DebugPanelProps) {\n const scrollRef = React.useRef<HTMLDivElement>(null)\n\n // Filter out text events - only show tool calls, results, errors, etc.\n const filteredEvents = React.useMemo(\n () => events.filter((e) => e.type !== 'text'),\n [events]\n )\n\n React.useEffect(() => {\n if (scrollRef.current) {\n scrollRef.current.scrollTop = scrollRef.current.scrollHeight\n }\n }, [filteredEvents])\n\n if (!isOpen) {\n return null\n }\n\n return (\n <div className=\"flex flex-col h-full min-h-0\">\n <div className=\"flex-shrink-0 flex items-center justify-between px-3 py-2 border-b border-gray-700\">\n <span className=\"text-xs font-medium text-gray-300\">Debug Events ({filteredEvents.length})</span>\n <div className=\"flex gap-2\">\n <button\n onClick={onClear}\n className=\"text-gray-400 hover:text-gray-200\"\n title=\"Clear events\"\n >\n <Trash2 className=\"w-3 h-3\" />\n </button>\n <button\n onClick={onToggle}\n className=\"text-gray-400 hover:text-gray-200\"\n title=\"Close debug panel\"\n >\n <X className=\"w-3 h-3\" />\n </button>\n </div>\n </div>\n <div ref={scrollRef} className=\"flex-1 min-h-0 overflow-y-auto p-2 space-y-1\">\n {filteredEvents.map((event) => (\n <DebugEventRow key={event.id} event={event} />\n ))}\n {filteredEvents.length === 0 && (\n <p className=\"text-xs text-gray-500 text-center py-4\">No events yet</p>\n )}\n </div>\n </div>\n )\n}\n\n// Recursively parse stringified JSON fields\nfunction parseNestedJson(data: unknown): unknown {\n if (typeof data === 'string') {\n try {\n const parsed = JSON.parse(data)\n return parseNestedJson(parsed)\n } catch {\n return data\n }\n }\n if (Array.isArray(data)) {\n return data.map(parseNestedJson)\n }\n if (data && typeof data === 'object') {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(data)) {\n result[key] = parseNestedJson(value)\n }\n return result\n }\n return data\n}\n\n// Custom dark styles for better readability (no external CSS needed)\nconst customDarkStyles: Record<string, string> = {\n container: 'bg-transparent text-overline leading-relaxed font-mono',\n basicChildStyle: 'pl-4 ml-0',\n label: 'text-purple-400 mr-1',\n nullValue: 'text-gray-500 italic',\n undefinedValue: 'text-gray-500 italic',\n stringValue: 'text-green-400',\n booleanValue: 'text-yellow-400',\n numberValue: 'text-blue-400',\n otherValue: 'text-gray-300',\n punctuation: 'text-gray-500',\n collapseIcon: 'text-gray-400 cursor-pointer select-none mr-1',\n expandIcon: 'text-gray-400 cursor-pointer select-none mr-1',\n collapsedContent: 'text-gray-500',\n}\n\nfunction DebugEventRow({ event }: { event: DebugEvent }) {\n const [expanded, setExpanded] = React.useState(false)\n const typeColors: Record<string, string> = {\n 'thinking': 'text-orange-400',\n 'tool-call': 'text-blue-400',\n 'tool-result': 'text-green-400',\n 'text': 'text-gray-300',\n 'error': 'text-red-400',\n 'done': 'text-purple-400',\n 'message': 'text-yellow-400',\n 'connection': 'text-cyan-400',\n 'metadata': 'text-teal-400',\n 'debug': 'text-gray-500',\n 'question': 'text-amber-400',\n }\n\n const formatTime = (date: Date) => {\n return date.toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n }) + '.' + String(date.getMilliseconds()).padStart(3, '0')\n }\n\n // Parse nested JSON strings for better display\n const parsedData = React.useMemo(() => parseNestedJson(event.data), [event.data])\n\n return (\n <div className=\"text-xs font-mono\">\n <button\n onClick={() => setExpanded(!expanded)}\n className=\"w-full text-left flex items-center gap-2 hover:bg-gray-800 rounded px-1 py-0.5\"\n >\n <span className=\"text-gray-500 flex-shrink-0\">\n {formatTime(event.timestamp)}\n </span>\n <span className={cn('font-medium flex-shrink-0', typeColors[event.type] || 'text-gray-400')}>\n {event.type}\n </span>\n <span className=\"text-gray-400 truncate flex-1\">\n {getEventPreview(event)}\n </span>\n <span className=\"text-gray-600 flex-shrink-0\">\n {expanded ? '\u25BC' : '\u25B6'}\n </span>\n </button>\n {expanded && (\n <div className=\"bg-gray-800 rounded p-2 mt-1 overflow-x-auto max-h-[300px] overflow-y-auto\">\n <JsonView\n data={parsedData as object}\n style={customDarkStyles}\n shouldExpandNode={(level) => level < 2}\n />\n </div>\n )}\n </div>\n )\n}\n\nfunction getEventPreview(event: DebugEvent): string {\n const data = event.data as Record<string, unknown>\n\n if (event.type === 'thinking') {\n return 'Agent is processing...'\n }\n if (event.type === 'tool-call') {\n const toolName = data?.toolName as string || 'unknown'\n const args = data?.args\n const argsPreview = args ? JSON.stringify(args).substring(0, 40) : ''\n return `${toolName}(${argsPreview}${argsPreview.length >= 40 ? '...' : ''})`\n }\n if (event.type === 'tool-result') {\n const result = data?.result\n const resultPreview = typeof result === 'string'\n ? result.substring(0, 50)\n : JSON.stringify(result)?.substring(0, 50)\n return `\u2192 ${resultPreview}${resultPreview && resultPreview.length >= 50 ? '...' : ''}`\n }\n if (event.type === 'text') {\n const content = data?.content as string || ''\n return content.substring(0, 50) + (content.length > 50 ? '...' : '')\n }\n if (event.type === 'error') {\n return data?.error as string || 'Unknown error'\n }\n if (event.type === 'message') {\n const role = data?.role as string || ''\n const content = data?.content as string || ''\n return `[${role}] ${content.substring(0, 40)}...`\n }\n if (event.type === 'connection') {\n return data?.status as string || ''\n }\n if (event.type === 'metadata') {\n const model = data?.model as string || ''\n const tokens = data?.tokens as { input?: number; output?: number } | undefined\n const durationMs = data?.durationMs as number | undefined\n const parts: string[] = []\n if (model) parts.push(model)\n if (tokens) parts.push(`${tokens.input || 0}\u2192${tokens.output || 0} tokens`)\n if (durationMs) parts.push(`${(durationMs / 1000).toFixed(1)}s`)\n return parts.join(' | ') || 'No metadata'\n }\n if (event.type === 'debug') {\n const partType = data?.partType as string || 'unknown'\n return `Unknown part: ${partType}`\n }\n if (event.type === 'question') {\n // Use the enriched questionText field if available (added by frontend)\n const questionText = (data?.questionText as string)\n || (data?.question as { questions?: Array<{ question: string }> })?.questions?.[0]?.question\n || (data?.header as string)\n || 'Confirmation required'\n return questionText.substring(0, 50) + (questionText.length > 50 ? '...' : '')\n }\n return ''\n}\n\n// Export a toggle button component for use in footer\nexport function DebugToggleButton({\n isOpen,\n onToggle\n}: {\n isOpen: boolean\n onToggle: () => void\n}) {\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className={cn(\n 'flex items-center gap-1 text-xs transition-colors',\n isOpen\n ? 'text-blue-500 hover:text-blue-400'\n : 'text-muted-foreground hover:text-foreground'\n )}\n title=\"Toggle debug panel\"\n >\n <Code className=\"w-3 h-3\" />\n <span>{isOpen ? 'Hide Debug' : 'Debug'}</span>\n </button>\n )\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -45,8 +45,8 @@ function MessageBubble({ message }) {
|
|
|
45
45
|
"[&_h2]:text-sm [&_h2]:font-semibold [&_h2]:mt-3 [&_h2]:mb-1",
|
|
46
46
|
"[&_h3]:text-sm [&_h3]:font-medium [&_h3]:mt-2 [&_h3]:mb-1",
|
|
47
47
|
// Code blocks
|
|
48
|
-
"[&_pre]:bg-background/
|
|
49
|
-
"[&_code]:bg-background/
|
|
48
|
+
"[&_pre]:bg-background/80 [&_pre]:rounded [&_pre]:p-2 [&_pre]:my-2 [&_pre]:overflow-x-auto",
|
|
49
|
+
"[&_code]:bg-background/80 [&_code]:px-1 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-xs",
|
|
50
50
|
// Strong/emphasis
|
|
51
51
|
"[&_strong]:font-semibold [&_em]:italic",
|
|
52
52
|
// Blockquotes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/frontend/components/CommandPalette/MessageBubble.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { User, Bot } from 'lucide-react'\nimport Markdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport type { ChatMessage } from '../../types'\n\ninterface MessageBubbleProps {\n message: ChatMessage\n}\n\nexport function MessageBubble({ message }: MessageBubbleProps) {\n const isUser = message.role === 'user'\n\n return (\n <div\n className={cn(\n 'flex gap-3 py-3',\n isUser ? 'flex-row-reverse' : 'flex-row'\n )}\n >\n <div\n className={cn(\n 'flex items-center justify-center w-8 h-8 rounded-full shrink-0',\n isUser ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'\n )}\n >\n {isUser ? <User className=\"h-4 w-4\" /> : <Bot className=\"h-4 w-4\" />}\n </div>\n\n <div\n className={cn(\n 'flex-1 min-w-0 px-4 py-2 rounded-lg text-sm',\n isUser\n ? 'bg-primary text-primary-foreground ml-12'\n : 'bg-muted text-foreground mr-12'\n )}\n >\n {isUser ? (\n <div className=\"whitespace-pre-wrap break-words\">{message.content}</div>\n ) : (\n <div className={cn(\n 'prose prose-sm dark:prose-invert max-w-none break-words',\n // Reset margins for first/last children\n '[&>*:first-child]:mt-0 [&>*:last-child]:mb-0',\n // Paragraph spacing - also handle plain text with whitespace-pre-line\n '[&_p]:my-2 [&_p]:leading-relaxed [&_p]:whitespace-pre-line',\n // List styling\n '[&_ul]:my-2 [&_ul]:pl-4 [&_ol]:my-2 [&_ol]:pl-4',\n '[&_li]:my-0.5 [&_li]:leading-relaxed',\n // Headers\n '[&_h1]:text-base [&_h1]:font-semibold [&_h1]:mt-3 [&_h1]:mb-2',\n '[&_h2]:text-sm [&_h2]:font-semibold [&_h2]:mt-3 [&_h2]:mb-1',\n '[&_h3]:text-sm [&_h3]:font-medium [&_h3]:mt-2 [&_h3]:mb-1',\n // Code blocks\n '[&_pre]:bg-background/
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { User, Bot } from 'lucide-react'\nimport Markdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport type { ChatMessage } from '../../types'\n\ninterface MessageBubbleProps {\n message: ChatMessage\n}\n\nexport function MessageBubble({ message }: MessageBubbleProps) {\n const isUser = message.role === 'user'\n\n return (\n <div\n className={cn(\n 'flex gap-3 py-3',\n isUser ? 'flex-row-reverse' : 'flex-row'\n )}\n >\n <div\n className={cn(\n 'flex items-center justify-center w-8 h-8 rounded-full shrink-0',\n isUser ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'\n )}\n >\n {isUser ? <User className=\"h-4 w-4\" /> : <Bot className=\"h-4 w-4\" />}\n </div>\n\n <div\n className={cn(\n 'flex-1 min-w-0 px-4 py-2 rounded-lg text-sm',\n isUser\n ? 'bg-primary text-primary-foreground ml-12'\n : 'bg-muted text-foreground mr-12'\n )}\n >\n {isUser ? (\n <div className=\"whitespace-pre-wrap break-words\">{message.content}</div>\n ) : (\n <div className={cn(\n 'prose prose-sm dark:prose-invert max-w-none break-words',\n // Reset margins for first/last children\n '[&>*:first-child]:mt-0 [&>*:last-child]:mb-0',\n // Paragraph spacing - also handle plain text with whitespace-pre-line\n '[&_p]:my-2 [&_p]:leading-relaxed [&_p]:whitespace-pre-line',\n // List styling\n '[&_ul]:my-2 [&_ul]:pl-4 [&_ol]:my-2 [&_ol]:pl-4',\n '[&_li]:my-0.5 [&_li]:leading-relaxed',\n // Headers\n '[&_h1]:text-base [&_h1]:font-semibold [&_h1]:mt-3 [&_h1]:mb-2',\n '[&_h2]:text-sm [&_h2]:font-semibold [&_h2]:mt-3 [&_h2]:mb-1',\n '[&_h3]:text-sm [&_h3]:font-medium [&_h3]:mt-2 [&_h3]:mb-1',\n // Code blocks\n '[&_pre]:bg-background/80 [&_pre]:rounded [&_pre]:p-2 [&_pre]:my-2 [&_pre]:overflow-x-auto',\n '[&_code]:bg-background/80 [&_code]:px-1 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-xs',\n // Strong/emphasis\n '[&_strong]:font-semibold [&_em]:italic',\n // Blockquotes\n '[&_blockquote]:border-l-2 [&_blockquote]:border-muted-foreground/30 [&_blockquote]:pl-3 [&_blockquote]:italic'\n )}>\n <Markdown remarkPlugins={[remarkGfm]}>\n {message.content}\n </Markdown>\n </div>\n )}\n </div>\n </div>\n )\n}\n"],
|
|
5
5
|
"mappings": ";AAiBI,SAYc,KAZd;AAdJ,SAAS,MAAM,WAAW;AAC1B,OAAO,cAAc;AACrB,OAAO,eAAe;AACtB,SAAS,UAAU;AAOZ,SAAS,cAAc,EAAE,QAAQ,GAAuB;AAC7D,QAAM,SAAS,QAAQ,SAAS;AAEhC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,SAAS,qBAAqB;AAAA,MAChC;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,SAAS,uCAAuC;AAAA,YAClD;AAAA,YAEC,mBAAS,oBAAC,QAAK,WAAU,WAAU,IAAK,oBAAC,OAAI,WAAU,WAAU;AAAA;AAAA,QACpE;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,SACI,6CACA;AAAA,YACN;AAAA,YAEC,mBACC,oBAAC,SAAI,WAAU,mCAAmC,kBAAQ,SAAQ,IAElE,oBAAC,SAAI,WAAW;AAAA,cACd;AAAA;AAAA,cAEA;AAAA;AAAA,cAEA;AAAA;AAAA,cAEA;AAAA,cACA;AAAA;AAAA,cAEA;AAAA,cACA;AAAA,cACA;AAAA;AAAA,cAEA;AAAA,cACA;AAAA;AAAA,cAEA;AAAA;AAAA,cAEA;AAAA,YACF,GACE,8BAAC,YAAS,eAAe,CAAC,SAAS,GAChC,kBAAQ,SACX,GACF;AAAA;AAAA,QAEJ;AAAA;AAAA;AAAA,EACF;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -24,9 +24,9 @@ function ToolCallConfirmation({
|
|
|
24
24
|
] }) });
|
|
25
25
|
}
|
|
26
26
|
if (toolCall.status === "completed") {
|
|
27
|
-
return /* @__PURE__ */ jsx("div", { className: "bg-
|
|
28
|
-
/* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-
|
|
29
|
-
/* @__PURE__ */ jsxs("span", { className: "text-sm text-
|
|
27
|
+
return /* @__PURE__ */ jsx("div", { className: "bg-status-success-bg rounded-lg p-3 border border-status-success-border", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
28
|
+
/* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-status-success-icon" }),
|
|
29
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm text-status-success-text", children: [
|
|
30
30
|
toolCall.toolName,
|
|
31
31
|
" completed successfully"
|
|
32
32
|
] })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/frontend/components/CommandPalette/ToolCallConfirmation.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Wrench, AlertTriangle, Loader2, Check, X } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport type { PendingToolCall } from '../../types'\n\ninterface ToolCallConfirmationProps {\n toolCall: PendingToolCall\n onApprove: () => void\n onReject: () => void\n}\n\nconst DESTRUCTIVE_PATTERNS = [/^delete/i, /^remove/i, /\\.delete$/i, /\\.remove$/i]\n\nfunction isDestructive(toolName: string): boolean {\n return DESTRUCTIVE_PATTERNS.some((p) => p.test(toolName))\n}\n\nexport function ToolCallConfirmation({\n toolCall,\n onApprove,\n onReject,\n}: ToolCallConfirmationProps) {\n const destructive = isDestructive(toolCall.toolName)\n\n // Show different UI based on status\n if (toolCall.status === 'executing') {\n return (\n <div className=\"bg-muted/50 rounded-lg p-3 border animate-pulse\">\n <div className=\"flex items-center gap-2\">\n <Loader2 className=\"h-4 w-4 animate-spin text-primary\" />\n <span className=\"text-sm\">Executing {toolCall.toolName}...</span>\n </div>\n </div>\n )\n }\n\n if (toolCall.status === 'completed') {\n return (\n <div className=\"bg-
|
|
5
|
-
"mappings": ";AAgCU,cACA,YADA;AA7BV,SAAS,QAAQ,eAAe,SAAS,OAAO,SAAS;AACzD,SAAS,UAAU;AACnB,SAAS,cAAc;AASvB,MAAM,uBAAuB,CAAC,YAAY,YAAY,cAAc,YAAY;AAEhF,SAAS,cAAc,UAA2B;AAChD,SAAO,qBAAqB,KAAK,CAAC,MAAM,EAAE,KAAK,QAAQ,CAAC;AAC1D;AAEO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,cAAc,cAAc,SAAS,QAAQ;AAGnD,MAAI,SAAS,WAAW,aAAa;AACnC,WACE,oBAAC,SAAI,WAAU,mDACb,+BAAC,SAAI,WAAU,2BACb;AAAA,0BAAC,WAAQ,WAAU,qCAAoC;AAAA,MACvD,qBAAC,UAAK,WAAU,WAAU;AAAA;AAAA,QAAW,SAAS;AAAA,QAAS;AAAA,SAAG;AAAA,OAC5D,GACF;AAAA,EAEJ;AAEA,MAAI,SAAS,WAAW,aAAa;AACnC,WACE,oBAAC,SAAI,WAAU,
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Wrench, AlertTriangle, Loader2, Check, X } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport type { PendingToolCall } from '../../types'\n\ninterface ToolCallConfirmationProps {\n toolCall: PendingToolCall\n onApprove: () => void\n onReject: () => void\n}\n\nconst DESTRUCTIVE_PATTERNS = [/^delete/i, /^remove/i, /\\.delete$/i, /\\.remove$/i]\n\nfunction isDestructive(toolName: string): boolean {\n return DESTRUCTIVE_PATTERNS.some((p) => p.test(toolName))\n}\n\nexport function ToolCallConfirmation({\n toolCall,\n onApprove,\n onReject,\n}: ToolCallConfirmationProps) {\n const destructive = isDestructive(toolCall.toolName)\n\n // Show different UI based on status\n if (toolCall.status === 'executing') {\n return (\n <div className=\"bg-muted/50 rounded-lg p-3 border animate-pulse\">\n <div className=\"flex items-center gap-2\">\n <Loader2 className=\"h-4 w-4 animate-spin text-primary\" />\n <span className=\"text-sm\">Executing {toolCall.toolName}...</span>\n </div>\n </div>\n )\n }\n\n if (toolCall.status === 'completed') {\n return (\n <div className=\"bg-status-success-bg rounded-lg p-3 border border-status-success-border\">\n <div className=\"flex items-center gap-2\">\n <Check className=\"h-4 w-4 text-status-success-icon\" />\n <span className=\"text-sm text-status-success-text\">\n {toolCall.toolName} completed successfully\n </span>\n </div>\n </div>\n )\n }\n\n if (toolCall.status === 'error') {\n return (\n <div className=\"bg-destructive/10 rounded-lg p-3 border border-destructive/20\">\n <div className=\"flex items-center gap-2\">\n <X className=\"h-4 w-4 text-destructive\" />\n <span className=\"text-sm text-destructive\">\n {toolCall.toolName} failed: {toolCall.error || 'Unknown error'}\n </span>\n </div>\n </div>\n )\n }\n\n if (toolCall.status === 'rejected') {\n return (\n <div className=\"bg-muted/30 rounded-lg p-3 border opacity-60\">\n <div className=\"flex items-center gap-2\">\n <X className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-sm text-muted-foreground line-through\">\n {toolCall.toolName} cancelled\n </span>\n </div>\n </div>\n )\n }\n\n // Pending state - show confirmation UI\n return (\n <div\n className={cn(\n 'rounded-lg p-3 border',\n destructive\n ? 'bg-destructive/5 border-destructive/20'\n : 'bg-muted/50 border-border'\n )}\n >\n <div className=\"flex items-center gap-2 mb-2\">\n {destructive ? (\n <AlertTriangle className=\"h-4 w-4 text-destructive\" />\n ) : (\n <Wrench className=\"h-4 w-4 text-primary\" />\n )}\n <span className=\"font-medium text-sm\">\n {destructive ? 'Destructive action requested' : 'AI wants to execute:'}\n </span>\n </div>\n\n <div className=\"font-mono text-xs bg-background rounded p-2 mb-3 overflow-auto max-h-32\">\n <div className={cn('font-medium', destructive ? 'text-destructive' : 'text-primary')}>\n {toolCall.toolName}\n </div>\n {toolCall.args && Object.keys(toolCall.args).length > 0 && (\n <pre className=\"text-muted-foreground mt-1 whitespace-pre-wrap break-all\">\n {JSON.stringify(toolCall.args, null, 2)}\n </pre>\n )}\n </div>\n\n {destructive && (\n <p className=\"text-xs text-destructive mb-3\">This action may not be reversible.</p>\n )}\n\n <div className=\"flex gap-2\">\n <Button size=\"sm\" variant=\"outline\" onClick={onReject} className=\"flex-1\">\n Cancel\n </Button>\n <Button\n size=\"sm\"\n variant={destructive ? 'destructive' : 'default'}\n onClick={onApprove}\n className=\"flex-1\"\n >\n {destructive ? 'Delete' : 'Execute'}\n </Button>\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAgCU,cACA,YADA;AA7BV,SAAS,QAAQ,eAAe,SAAS,OAAO,SAAS;AACzD,SAAS,UAAU;AACnB,SAAS,cAAc;AASvB,MAAM,uBAAuB,CAAC,YAAY,YAAY,cAAc,YAAY;AAEhF,SAAS,cAAc,UAA2B;AAChD,SAAO,qBAAqB,KAAK,CAAC,MAAM,EAAE,KAAK,QAAQ,CAAC;AAC1D;AAEO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,cAAc,cAAc,SAAS,QAAQ;AAGnD,MAAI,SAAS,WAAW,aAAa;AACnC,WACE,oBAAC,SAAI,WAAU,mDACb,+BAAC,SAAI,WAAU,2BACb;AAAA,0BAAC,WAAQ,WAAU,qCAAoC;AAAA,MACvD,qBAAC,UAAK,WAAU,WAAU;AAAA;AAAA,QAAW,SAAS;AAAA,QAAS;AAAA,SAAG;AAAA,OAC5D,GACF;AAAA,EAEJ;AAEA,MAAI,SAAS,WAAW,aAAa;AACnC,WACE,oBAAC,SAAI,WAAU,2EACb,+BAAC,SAAI,WAAU,2BACb;AAAA,0BAAC,SAAM,WAAU,oCAAmC;AAAA,MACpD,qBAAC,UAAK,WAAU,oCACb;AAAA,iBAAS;AAAA,QAAS;AAAA,SACrB;AAAA,OACF,GACF;AAAA,EAEJ;AAEA,MAAI,SAAS,WAAW,SAAS;AAC/B,WACE,oBAAC,SAAI,WAAU,iEACb,+BAAC,SAAI,WAAU,2BACb;AAAA,0BAAC,KAAE,WAAU,4BAA2B;AAAA,MACxC,qBAAC,UAAK,WAAU,4BACb;AAAA,iBAAS;AAAA,QAAS;AAAA,QAAU,SAAS,SAAS;AAAA,SACjD;AAAA,OACF,GACF;AAAA,EAEJ;AAEA,MAAI,SAAS,WAAW,YAAY;AAClC,WACE,oBAAC,SAAI,WAAU,gDACb,+BAAC,SAAI,WAAU,2BACb;AAAA,0BAAC,KAAE,WAAU,iCAAgC;AAAA,MAC7C,qBAAC,UAAK,WAAU,8CACb;AAAA,iBAAS;AAAA,QAAS;AAAA,SACrB;AAAA,OACF,GACF;AAAA,EAEJ;AAGA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,cACI,2CACA;AAAA,MACN;AAAA,MAEA;AAAA,6BAAC,SAAI,WAAU,gCACZ;AAAA,wBACC,oBAAC,iBAAc,WAAU,4BAA2B,IAEpD,oBAAC,UAAO,WAAU,wBAAuB;AAAA,UAE3C,oBAAC,UAAK,WAAU,uBACb,wBAAc,iCAAiC,wBAClD;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,2EACb;AAAA,8BAAC,SAAI,WAAW,GAAG,eAAe,cAAc,qBAAqB,cAAc,GAChF,mBAAS,UACZ;AAAA,UACC,SAAS,QAAQ,OAAO,KAAK,SAAS,IAAI,EAAE,SAAS,KACpD,oBAAC,SAAI,WAAU,4DACZ,eAAK,UAAU,SAAS,MAAM,MAAM,CAAC,GACxC;AAAA,WAEJ;AAAA,QAEC,eACC,oBAAC,OAAE,WAAU,iCAAgC,gDAAkC;AAAA,QAGjF,qBAAC,SAAI,WAAU,cACb;AAAA,8BAAC,UAAO,MAAK,MAAK,SAAQ,WAAU,SAAS,UAAU,WAAU,UAAS,oBAE1E;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,cAAc,gBAAgB;AAAA,cACvC,SAAS;AAAA,cACT,WAAU;AAAA,cAET,wBAAc,WAAW;AAAA;AAAA,UAC5B;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -27,7 +27,7 @@ function ToolChatPage({
|
|
|
27
27
|
return () => clearTimeout(timeoutId);
|
|
28
28
|
}, [messages, pendingToolCalls, isStreaming, isThinking, agentStatus, pendingQuestion]);
|
|
29
29
|
return /* @__PURE__ */ jsxs("div", { className: "p-3 space-y-3", children: [
|
|
30
|
-
tool && /* @__PURE__ */ jsx("div", { className: "-mx-3 -mt-3 mb-3 px-3 py-2 border-b bg-muted/
|
|
30
|
+
tool && /* @__PURE__ */ jsx("div", { className: "-mx-3 -mt-3 mb-3 px-3 py-2 border-b bg-muted/30", children: /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground line-clamp-2", children: tool.description }) }),
|
|
31
31
|
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
32
32
|
messages.map((message) => /* @__PURE__ */ jsx(MessageBubble, { message }, message.id)),
|
|
33
33
|
pendingToolCalls.filter((tc) => tc.status === "pending" || tc.status === "error").map((toolCall) => /* @__PURE__ */ jsx(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/frontend/components/CommandPalette/ToolChatPage.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useRef, useEffect } from 'react'\nimport { Loader2 } from 'lucide-react'\nimport Markdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport type { ToolInfo, ChatMessage, PendingToolCall, OpenCodeQuestion, AgentStatus } from '../../types'\nimport { MessageBubble } from './MessageBubble'\nimport { ToolCallConfirmation } from './ToolCallConfirmation'\nimport { AgentStatusIndicator } from './AgentStatusIndicator'\n\ninterface ToolChatPageProps {\n tool: ToolInfo | null // Can be null for general chat\n messages: ChatMessage[]\n pendingToolCalls: PendingToolCall[]\n isStreaming: boolean\n isThinking?: boolean\n agentStatus?: AgentStatus\n onApproveToolCall: (toolCallId: string) => Promise<void>\n onRejectToolCall: (toolCallId: string) => void\n pendingQuestion?: OpenCodeQuestion | null\n onAnswerQuestion?: (answer: number) => Promise<void>\n}\n\nexport function ToolChatPage({\n tool,\n messages,\n pendingToolCalls,\n isStreaming,\n isThinking = false,\n agentStatus = { type: 'idle' },\n onApproveToolCall,\n onRejectToolCall,\n pendingQuestion,\n onAnswerQuestion,\n}: ToolChatPageProps) {\n const bottomRef = useRef<HTMLDivElement>(null)\n\n // Auto-scroll to bottom on new messages (debounced)\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n bottomRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n }, 100)\n\n return () => clearTimeout(timeoutId)\n }, [messages, pendingToolCalls, isStreaming, isThinking, agentStatus, pendingQuestion])\n\n return (\n <div className=\"p-3 space-y-3\">\n {/* Tool description header - only shown if tool is selected */}\n {tool && (\n <div className=\"-mx-3 -mt-3 mb-3 px-3 py-2 border-b bg-muted/
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useRef, useEffect } from 'react'\nimport { Loader2 } from 'lucide-react'\nimport Markdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport type { ToolInfo, ChatMessage, PendingToolCall, OpenCodeQuestion, AgentStatus } from '../../types'\nimport { MessageBubble } from './MessageBubble'\nimport { ToolCallConfirmation } from './ToolCallConfirmation'\nimport { AgentStatusIndicator } from './AgentStatusIndicator'\n\ninterface ToolChatPageProps {\n tool: ToolInfo | null // Can be null for general chat\n messages: ChatMessage[]\n pendingToolCalls: PendingToolCall[]\n isStreaming: boolean\n isThinking?: boolean\n agentStatus?: AgentStatus\n onApproveToolCall: (toolCallId: string) => Promise<void>\n onRejectToolCall: (toolCallId: string) => void\n pendingQuestion?: OpenCodeQuestion | null\n onAnswerQuestion?: (answer: number) => Promise<void>\n}\n\nexport function ToolChatPage({\n tool,\n messages,\n pendingToolCalls,\n isStreaming,\n isThinking = false,\n agentStatus = { type: 'idle' },\n onApproveToolCall,\n onRejectToolCall,\n pendingQuestion,\n onAnswerQuestion,\n}: ToolChatPageProps) {\n const bottomRef = useRef<HTMLDivElement>(null)\n\n // Auto-scroll to bottom on new messages (debounced)\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n bottomRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n }, 100)\n\n return () => clearTimeout(timeoutId)\n }, [messages, pendingToolCalls, isStreaming, isThinking, agentStatus, pendingQuestion])\n\n return (\n <div className=\"p-3 space-y-3\">\n {/* Tool description header - only shown if tool is selected */}\n {tool && (\n <div className=\"-mx-3 -mt-3 mb-3 px-3 py-2 border-b bg-muted/30\">\n <p className=\"text-xs text-muted-foreground line-clamp-2\">{tool.description}</p>\n </div>\n )}\n\n {/* Chat messages */}\n <div className=\"space-y-3\">\n {messages.map((message) => (\n <MessageBubble key={message.id} message={message} />\n ))}\n\n {/* Only show tool calls that require user action (pending dangerous tools or errors) */}\n {pendingToolCalls\n .filter((tc) => tc.status === 'pending' || tc.status === 'error')\n .map((toolCall) => (\n <ToolCallConfirmation\n key={toolCall.id}\n toolCall={toolCall}\n onApprove={() => onApproveToolCall(toolCall.id)}\n onReject={() => onRejectToolCall(toolCall.id)}\n />\n ))}\n\n {/* OpenCode confirmation question */}\n {pendingQuestion && pendingQuestion.questions[0] && (\n <div className=\"p-4 bg-amber-500/10 border border-amber-500/30 rounded-lg space-y-3\">\n <div className=\"flex items-center gap-2 text-amber-600 dark:text-amber-400 text-sm font-medium\">\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n <span>{pendingQuestion.questions[0].header || 'Confirmation Required'}</span>\n </div>\n <div className=\"text-sm prose prose-sm dark:prose-invert max-w-none [&>*:first-child]:mt-0 [&>*:last-child]:mb-0 [&_p]:my-1 [&_strong]:font-semibold\">\n <Markdown remarkPlugins={[remarkGfm]}>\n {pendingQuestion.questions[0].question}\n </Markdown>\n </div>\n <div className=\"flex gap-2 flex-wrap\">\n {pendingQuestion.questions[0].options.map((option, index) => (\n <Button\n key={index}\n variant={index === 0 ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => onAnswerQuestion?.(index)}\n disabled={isStreaming}\n >\n {option.label}\n </Button>\n ))}\n </div>\n </div>\n )}\n\n {/* Agent status indicator - shows what the agent is doing */}\n {!pendingQuestion && <AgentStatusIndicator status={agentStatus} />}\n\n {/* Scroll anchor */}\n <div ref={bottomRef} />\n </div>\n </div>\n )\n}\n"],
|
|
5
5
|
"mappings": ";AAsDU,cAyBE,YAzBF;AAnDV,SAAS,QAAQ,iBAAiB;AAElC,OAAO,cAAc;AACrB,OAAO,eAAe;AACtB,SAAS,cAAc;AAEvB,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC,SAAS,4BAA4B;AAe9B,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,cAAc,EAAE,MAAM,OAAO;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,QAAM,YAAY,OAAuB,IAAI;AAG7C,YAAU,MAAM;AACd,UAAM,YAAY,WAAW,MAAM;AACjC,gBAAU,SAAS,eAAe,EAAE,UAAU,UAAU,OAAO,MAAM,CAAC;AAAA,IACxE,GAAG,GAAG;AAEN,WAAO,MAAM,aAAa,SAAS;AAAA,EACrC,GAAG,CAAC,UAAU,kBAAkB,aAAa,YAAY,aAAa,eAAe,CAAC;AAEtF,SACE,qBAAC,SAAI,WAAU,iBAEZ;AAAA,YACC,oBAAC,SAAI,WAAU,mDACb,8BAAC,OAAE,WAAU,8CAA8C,eAAK,aAAY,GAC9E;AAAA,IAIF,qBAAC,SAAI,WAAU,aACZ;AAAA,eAAS,IAAI,CAAC,YACb,oBAAC,iBAA+B,WAAZ,QAAQ,EAAsB,CACnD;AAAA,MAGA,iBACE,OAAO,CAAC,OAAO,GAAG,WAAW,aAAa,GAAG,WAAW,OAAO,EAC/D,IAAI,CAAC,aACJ;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,WAAW,MAAM,kBAAkB,SAAS,EAAE;AAAA,UAC9C,UAAU,MAAM,iBAAiB,SAAS,EAAE;AAAA;AAAA,QAHvC,SAAS;AAAA,MAIhB,CACD;AAAA,MAGF,mBAAmB,gBAAgB,UAAU,CAAC,KAC7C,qBAAC,SAAI,WAAU,uEACb;AAAA,6BAAC,SAAI,WAAU,kFACb;AAAA,8BAAC,SAAI,WAAU,WAAU,MAAK,QAAO,QAAO,gBAAe,SAAQ,aACjE,8BAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,wIAAuI,GAC9M;AAAA,UACA,oBAAC,UAAM,0BAAgB,UAAU,CAAC,EAAE,UAAU,yBAAwB;AAAA,WACxE;AAAA,QACA,oBAAC,SAAI,WAAU,wIACb,8BAAC,YAAS,eAAe,CAAC,SAAS,GAChC,0BAAgB,UAAU,CAAC,EAAE,UAChC,GACF;AAAA,QACA,oBAAC,SAAI,WAAU,wBACZ,0BAAgB,UAAU,CAAC,EAAE,QAAQ,IAAI,CAAC,QAAQ,UACjD;AAAA,UAAC;AAAA;AAAA,YAEC,SAAS,UAAU,IAAI,YAAY;AAAA,YACnC,MAAK;AAAA,YACL,SAAS,MAAM,mBAAmB,KAAK;AAAA,YACvC,UAAU;AAAA,YAET,iBAAO;AAAA;AAAA,UANH;AAAA,QAOP,CACD,GACH;AAAA,SACF;AAAA,MAID,CAAC,mBAAmB,oBAAC,wBAAqB,QAAQ,aAAa;AAAA,MAGhE,oBAAC,SAAI,KAAK,WAAW;AAAA,OACvB;AAAA,KACF;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -224,7 +224,7 @@ function DockableChat() {
|
|
|
224
224
|
"div",
|
|
225
225
|
{
|
|
226
226
|
className: cn(
|
|
227
|
-
"fixed z-
|
|
227
|
+
"fixed z-modal",
|
|
228
228
|
"rounded-xl border bg-background shadow-2xl",
|
|
229
229
|
"flex flex-col",
|
|
230
230
|
"transition-all duration-200 ease-out"
|
|
@@ -295,7 +295,7 @@ function DockableChat() {
|
|
|
295
295
|
placeholder: t("ai_assistant.chat.describePlaceholder"),
|
|
296
296
|
className: cn(
|
|
297
297
|
"flex-1 bg-muted rounded-lg px-4 py-2 text-sm outline-none",
|
|
298
|
-
"focus:ring-2 focus:ring-ring",
|
|
298
|
+
"focus-visible:ring-2 focus-visible:ring-ring",
|
|
299
299
|
"disabled:opacity-50"
|
|
300
300
|
),
|
|
301
301
|
disabled: isStreaming
|
|
@@ -330,7 +330,7 @@ function DockableChat() {
|
|
|
330
330
|
"div",
|
|
331
331
|
{
|
|
332
332
|
"data-debug-panel": true,
|
|
333
|
-
className: "fixed z-
|
|
333
|
+
className: "fixed z-top bg-gray-900 rounded-xl border border-gray-700 shadow-2xl flex flex-col overflow-hidden",
|
|
334
334
|
style: {
|
|
335
335
|
top: "24px",
|
|
336
336
|
left: "24px",
|
|
@@ -452,7 +452,7 @@ function DockableChat() {
|
|
|
452
452
|
placeholder: t("ai_assistant.chat.describePlaceholder"),
|
|
453
453
|
className: cn(
|
|
454
454
|
"flex-1 bg-muted rounded-lg px-4 py-2 text-sm outline-none",
|
|
455
|
-
"focus:ring-2 focus:ring-ring",
|
|
455
|
+
"focus-visible:ring-2 focus-visible:ring-ring",
|
|
456
456
|
"disabled:opacity-50"
|
|
457
457
|
),
|
|
458
458
|
disabled: isStreaming
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/frontend/components/DockableChat/DockableChat.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\nimport { Command } from 'cmdk'\nimport {\n Loader2,\n Send,\n Square,\n X,\n Minimize2,\n PanelRight,\n PanelLeft,\n PanelBottom,\n MessageCircle,\n} from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useCommandPaletteContext } from '../CommandPalette/CommandPaletteProvider'\nimport { CommandInput } from '../CommandPalette/CommandInput'\nimport { CommandHeader } from '../CommandPalette/CommandHeader'\nimport { CommandFooter } from '../CommandPalette/CommandFooter'\nimport { ToolChatPage } from '../CommandPalette/ToolChatPage'\nimport { DebugPanel } from '../CommandPalette/DebugPanel'\nimport { AiDot } from '../AiDot'\nimport type { DockPosition } from '../../types'\nimport { useDockPosition } from '../../hooks/useDockPosition'\n\n// Idle state - shown when palette is open but no query submitted\nfunction IdleState() {\n const t = useT()\n return (\n <div className=\"py-8 px-4 text-center text-muted-foreground\">\n <p className=\"mb-2\">{t('ai_assistant.chat.idleTitle')}</p>\n <p className=\"text-sm\">{t('ai_assistant.chat.idleExamples')}</p>\n <ul className=\"text-sm mt-2 space-y-1\">\n <li>"{t('ai_assistant.chat.example.search')}"</li>\n <li>"{t('ai_assistant.chat.example.create')}"</li>\n <li>"{t('ai_assistant.chat.example.show')}"</li>\n </ul>\n </div>\n )\n}\n\n// Routing indicator - shown while fast model analyzes intent\nfunction RoutingIndicator() {\n const t = useT()\n return (\n <div className=\"py-8 flex items-center justify-center gap-2\">\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n <span className=\"text-sm text-muted-foreground\">{t('ai_assistant.status.analyzing')}</span>\n </div>\n )\n}\n\ninterface DockControlsProps {\n position: DockPosition\n onPositionChange: (position: DockPosition) => void\n onMinimize: () => void\n onClose: () => void\n}\n\nfunction DockControls({\n position,\n onPositionChange,\n onMinimize,\n onClose,\n}: DockControlsProps) {\n const t = useT()\n const positions: { value: DockPosition; icon: React.ReactNode; labelKey: string }[] = [\n { value: 'floating', icon: <MessageCircle className=\"h-3.5 w-3.5\" />, labelKey: 'ai_assistant.dock.floating' },\n { value: 'left', icon: <PanelLeft className=\"h-3.5 w-3.5\" />, labelKey: 'ai_assistant.dock.left' },\n { value: 'bottom', icon: <PanelBottom className=\"h-3.5 w-3.5\" />, labelKey: 'ai_assistant.dock.bottom' },\n { value: 'right', icon: <PanelRight className=\"h-3.5 w-3.5\" />, labelKey: 'ai_assistant.dock.right' },\n ]\n\n return (\n <div className=\"flex items-center gap-1\">\n {positions.map((pos) => (\n <Button\n key={pos.value}\n variant=\"ghost\"\n size=\"icon\"\n className={cn('h-6 w-6', position === pos.value && 'bg-accent')}\n onClick={() => onPositionChange(pos.value)}\n title={t(pos.labelKey)}\n >\n {pos.icon}\n </Button>\n ))}\n <div className=\"w-px h-4 bg-border mx-1\" />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={onMinimize}\n title={t('ai_assistant.dock.minimize')}\n >\n <Minimize2 className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={onClose}\n title={t('ai_assistant.dock.close')}\n >\n <X className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n )\n}\n\nconst FLOATING_POSITION_STYLE: React.CSSProperties = {\n bottom: 24,\n right: 24,\n}\n\nexport function DockableChat() {\n const t = useT()\n const {\n state,\n isThinking,\n agentStatus,\n isSessionAuthorized,\n messages,\n pendingToolCalls,\n selectedTool,\n close,\n reset,\n handleSubmit,\n sendAgenticMessage,\n stopExecution,\n approveToolCall,\n rejectToolCall,\n debugEvents,\n showDebug,\n setShowDebug,\n clearDebugEvents,\n pendingQuestion,\n answerQuestion,\n } = useCommandPaletteContext()\n\n const {\n dockState,\n setPosition,\n toggleMinimized,\n setMinimized,\n isFloating,\n isHydrated,\n } = useDockPosition()\n\n const {\n isOpen,\n phase,\n isLoading,\n isStreaming,\n connectionStatus,\n } = state\n\n const [localInput, setLocalInput] = React.useState('')\n const [chatInput, setChatInput] = React.useState('')\n const chatInputRef = React.useRef<HTMLInputElement>(null)\n\n // Reset local input when phase changes to idle\n React.useEffect(() => {\n if (phase === 'idle') {\n setLocalInput('')\n setChatInput('')\n }\n }, [phase])\n\n // Focus chat input when entering chatting phase\n React.useEffect(() => {\n if (phase === 'chatting' || phase === 'confirming' || phase === 'executing') {\n setTimeout(() => chatInputRef.current?.focus(), 50)\n }\n }, [phase])\n\n const handleInputSubmit = async () => {\n const query = localInput.trim()\n if (!query) return\n setLocalInput('')\n await handleSubmit(query)\n }\n\n const handleInputKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && phase === 'idle' && localInput.trim()) {\n e.preventDefault()\n handleInputSubmit()\n }\n }\n\n const handleChatSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n if (!chatInput.trim() || isStreaming) return\n\n const content = chatInput\n setChatInput('')\n await sendAgenticMessage(content)\n }\n\n const handleChatKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n if (phase !== 'idle') {\n reset()\n } else {\n close()\n }\n }\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n if (chatInput.trim() && !isStreaming) {\n const content = chatInput\n setChatInput('')\n sendAgenticMessage(content)\n }\n }\n }\n\n // Don't render until hydrated to avoid SSR mismatch\n if (!isHydrated) return null\n\n // When minimized in any mode, show the AiDot in bottom-right corner\n if (isOpen && dockState.isMinimized) {\n return typeof document !== 'undefined' ? createPortal(\n <AiDot\n onClick={() => setMinimized(false)}\n isActive={isStreaming || isThinking}\n hasMessages={messages.length > 0}\n position=\"bottom-right\"\n />,\n document.body\n ) : null\n }\n\n // Render as floating panel when in floating mode\n if (isFloating) {\n if (!isOpen) return null\n\n return typeof document !== 'undefined' ? createPortal(\n <>\n <div\n className={cn(\n 'fixed z-50',\n 'rounded-xl border bg-background shadow-2xl',\n 'flex flex-col',\n 'transition-all duration-200 ease-out'\n )}\n style={{\n ...FLOATING_POSITION_STYLE,\n width: dockState.width,\n height: dockState.height,\n maxHeight: 'calc(100vh - 48px)',\n }}\n onKeyDown={handleInputKeyDown}\n >\n <Command className=\"flex flex-col flex-1 min-h-0 rounded-xl overflow-hidden\" shouldFilter={false}>\n {/* Dock controls header */}\n <div className=\"flex items-center justify-end px-2 py-1.5 border-b shrink-0\">\n <DockControls\n position={dockState.position}\n onPositionChange={setPosition}\n onMinimize={toggleMinimized}\n onClose={close}\n />\n </div>\n\n <CommandHeader\n phase={phase}\n selectedTool={selectedTool}\n onBack={reset}\n />\n\n {phase === 'idle' && (\n <CommandInput\n value={localInput}\n onValueChange={setLocalInput}\n mode=\"commands\"\n isLoading={isLoading}\n placeholder={t('ai_assistant.chat.placeholder')}\n />\n )}\n\n <div className=\"flex-1 min-h-0 overflow-y-auto\">\n {phase === 'idle' && !localInput && <IdleState />}\n {phase === 'routing' && <RoutingIndicator />}\n {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (\n <ToolChatPage\n tool={selectedTool}\n messages={messages}\n pendingToolCalls={pendingToolCalls}\n isStreaming={isStreaming}\n isThinking={isThinking}\n agentStatus={agentStatus}\n onApproveToolCall={approveToolCall}\n onRejectToolCall={rejectToolCall}\n pendingQuestion={pendingQuestion}\n onAnswerQuestion={answerQuestion}\n />\n )}\n </div>\n\n {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (\n <form onSubmit={handleChatSubmit} className=\"shrink-0 border-t p-3\">\n <div className=\"flex items-center gap-2\">\n <input\n ref={chatInputRef}\n type=\"text\"\n value={chatInput}\n onChange={(e) => setChatInput(e.target.value)}\n onKeyDown={handleChatKeyDown}\n placeholder={t('ai_assistant.chat.describePlaceholder')}\n className={cn(\n 'flex-1 bg-muted rounded-lg px-4 py-2 text-sm outline-none',\n 'focus:ring-2 focus:ring-ring',\n 'disabled:opacity-50'\n )}\n disabled={isStreaming}\n />\n <Button\n type={isStreaming ? 'button' : 'submit'}\n size=\"icon\"\n variant={isStreaming ? 'destructive' : 'default'}\n onClick={isStreaming ? stopExecution : undefined}\n disabled={!isStreaming && !chatInput.trim()}\n >\n {isStreaming ? (\n <Square className=\"h-4 w-4\" />\n ) : (\n <Send className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </form>\n )}\n\n <CommandFooter\n phase={phase}\n connectionStatus={connectionStatus}\n isSessionAuthorized={isSessionAuthorized}\n showDebug={showDebug}\n onToggleDebug={() => setShowDebug(!showDebug)}\n />\n </Command>\n </div>\n\n {showDebug && (\n <div\n data-debug-panel\n className=\"fixed z-[9999] bg-gray-900 rounded-xl border border-gray-700 shadow-2xl flex flex-col overflow-hidden\"\n style={{\n top: '24px',\n left: '24px',\n width: '400px',\n maxHeight: 'calc(100vh - 48px)',\n }}\n >\n <DebugPanel\n events={debugEvents}\n onClear={clearDebugEvents}\n isOpen={true}\n onToggle={() => setShowDebug(false)}\n />\n </div>\n )}\n </>,\n document.body\n ) : null\n }\n\n // Render as docked panel (right, left, bottom)\n if (!isOpen) return null\n\n const positionStyles: Record<Exclude<DockPosition, 'floating'>, React.CSSProperties> = {\n right: {\n position: 'fixed',\n top: 0,\n right: 0,\n bottom: 0,\n width: dockState.width,\n zIndex: 40,\n },\n left: {\n position: 'fixed',\n top: 0,\n left: 0,\n bottom: 0,\n width: dockState.width,\n zIndex: 40,\n },\n bottom: {\n position: 'fixed',\n bottom: 0,\n left: 0,\n right: 0,\n height: dockState.height,\n zIndex: 40,\n },\n }\n\n const panelPosition = dockState.position as Exclude<DockPosition, 'floating'>\n\n return typeof document !== 'undefined' ? createPortal(\n <div\n className={cn(\n 'bg-background border shadow-xl flex flex-col',\n panelPosition === 'right' && 'border-l',\n panelPosition === 'left' && 'border-r',\n panelPosition === 'bottom' && 'border-t'\n )}\n style={positionStyles[panelPosition]}\n onKeyDown={handleInputKeyDown}\n >\n {/* Docked panel header */}\n <div className=\"flex items-center justify-end px-2 py-1.5 border-b shrink-0\">\n <DockControls\n position={dockState.position}\n onPositionChange={setPosition}\n onMinimize={toggleMinimized}\n onClose={close}\n />\n </div>\n\n {!dockState.isMinimized && (\n <>\n <Command className=\"flex flex-col flex-1 min-h-0\" shouldFilter={false}>\n <CommandHeader\n phase={phase}\n selectedTool={selectedTool}\n onBack={reset}\n />\n\n {phase === 'idle' && (\n <CommandInput\n value={localInput}\n onValueChange={setLocalInput}\n mode=\"commands\"\n isLoading={isLoading}\n placeholder={t('ai_assistant.chat.placeholder')}\n />\n )}\n\n <div className=\"flex-1 min-h-0 overflow-y-auto\">\n {phase === 'idle' && !localInput && <IdleState />}\n {phase === 'routing' && <RoutingIndicator />}\n {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (\n <ToolChatPage\n tool={selectedTool}\n messages={messages}\n pendingToolCalls={pendingToolCalls}\n isStreaming={isStreaming}\n isThinking={isThinking}\n agentStatus={agentStatus}\n onApproveToolCall={approveToolCall}\n onRejectToolCall={rejectToolCall}\n pendingQuestion={pendingQuestion}\n onAnswerQuestion={answerQuestion}\n />\n )}\n </div>\n\n {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (\n <form onSubmit={handleChatSubmit} className=\"shrink-0 border-t p-3\">\n <div className=\"flex items-center gap-2\">\n <input\n ref={chatInputRef}\n type=\"text\"\n value={chatInput}\n onChange={(e) => setChatInput(e.target.value)}\n onKeyDown={handleChatKeyDown}\n placeholder={t('ai_assistant.chat.describePlaceholder')}\n className={cn(\n 'flex-1 bg-muted rounded-lg px-4 py-2 text-sm outline-none',\n 'focus:ring-2 focus:ring-ring',\n 'disabled:opacity-50'\n )}\n disabled={isStreaming}\n />\n <Button\n type={isStreaming ? 'button' : 'submit'}\n size=\"icon\"\n variant={isStreaming ? 'destructive' : 'default'}\n onClick={isStreaming ? stopExecution : undefined}\n disabled={!isStreaming && !chatInput.trim()}\n >\n {isStreaming ? (\n <Square className=\"h-4 w-4\" />\n ) : (\n <Send className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </form>\n )}\n\n <CommandFooter\n phase={phase}\n connectionStatus={connectionStatus}\n isSessionAuthorized={isSessionAuthorized}\n showDebug={showDebug}\n onToggleDebug={() => setShowDebug(!showDebug)}\n />\n </Command>\n </>\n )}\n\n {showDebug && (\n <div\n className={cn(\n 'bg-gray-900 border-gray-700 flex flex-col overflow-hidden',\n panelPosition === 'right' && 'absolute left-0 top-0 bottom-0 w-[400px] -translate-x-full border-r',\n panelPosition === 'left' && 'absolute right-0 top-0 bottom-0 w-[400px] translate-x-full border-l',\n panelPosition === 'bottom' && 'absolute bottom-full left-0 right-0 h-[300px] border-t'\n )}\n >\n <DebugPanel\n events={debugEvents}\n onClear={clearDebugEvents}\n isOpen={true}\n onToggle={() => setShowDebug(false)}\n />\n </div>\n )}\n </div>,\n document.body\n ) : null\n}\n"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\nimport { Command } from 'cmdk'\nimport {\n Loader2,\n Send,\n Square,\n X,\n Minimize2,\n PanelRight,\n PanelLeft,\n PanelBottom,\n MessageCircle,\n} from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useCommandPaletteContext } from '../CommandPalette/CommandPaletteProvider'\nimport { CommandInput } from '../CommandPalette/CommandInput'\nimport { CommandHeader } from '../CommandPalette/CommandHeader'\nimport { CommandFooter } from '../CommandPalette/CommandFooter'\nimport { ToolChatPage } from '../CommandPalette/ToolChatPage'\nimport { DebugPanel } from '../CommandPalette/DebugPanel'\nimport { AiDot } from '../AiDot'\nimport type { DockPosition } from '../../types'\nimport { useDockPosition } from '../../hooks/useDockPosition'\n\n// Idle state - shown when palette is open but no query submitted\nfunction IdleState() {\n const t = useT()\n return (\n <div className=\"py-8 px-4 text-center text-muted-foreground\">\n <p className=\"mb-2\">{t('ai_assistant.chat.idleTitle')}</p>\n <p className=\"text-sm\">{t('ai_assistant.chat.idleExamples')}</p>\n <ul className=\"text-sm mt-2 space-y-1\">\n <li>"{t('ai_assistant.chat.example.search')}"</li>\n <li>"{t('ai_assistant.chat.example.create')}"</li>\n <li>"{t('ai_assistant.chat.example.show')}"</li>\n </ul>\n </div>\n )\n}\n\n// Routing indicator - shown while fast model analyzes intent\nfunction RoutingIndicator() {\n const t = useT()\n return (\n <div className=\"py-8 flex items-center justify-center gap-2\">\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n <span className=\"text-sm text-muted-foreground\">{t('ai_assistant.status.analyzing')}</span>\n </div>\n )\n}\n\ninterface DockControlsProps {\n position: DockPosition\n onPositionChange: (position: DockPosition) => void\n onMinimize: () => void\n onClose: () => void\n}\n\nfunction DockControls({\n position,\n onPositionChange,\n onMinimize,\n onClose,\n}: DockControlsProps) {\n const t = useT()\n const positions: { value: DockPosition; icon: React.ReactNode; labelKey: string }[] = [\n { value: 'floating', icon: <MessageCircle className=\"h-3.5 w-3.5\" />, labelKey: 'ai_assistant.dock.floating' },\n { value: 'left', icon: <PanelLeft className=\"h-3.5 w-3.5\" />, labelKey: 'ai_assistant.dock.left' },\n { value: 'bottom', icon: <PanelBottom className=\"h-3.5 w-3.5\" />, labelKey: 'ai_assistant.dock.bottom' },\n { value: 'right', icon: <PanelRight className=\"h-3.5 w-3.5\" />, labelKey: 'ai_assistant.dock.right' },\n ]\n\n return (\n <div className=\"flex items-center gap-1\">\n {positions.map((pos) => (\n <Button\n key={pos.value}\n variant=\"ghost\"\n size=\"icon\"\n className={cn('h-6 w-6', position === pos.value && 'bg-accent')}\n onClick={() => onPositionChange(pos.value)}\n title={t(pos.labelKey)}\n >\n {pos.icon}\n </Button>\n ))}\n <div className=\"w-px h-4 bg-border mx-1\" />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={onMinimize}\n title={t('ai_assistant.dock.minimize')}\n >\n <Minimize2 className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={onClose}\n title={t('ai_assistant.dock.close')}\n >\n <X className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n )\n}\n\nconst FLOATING_POSITION_STYLE: React.CSSProperties = {\n bottom: 24,\n right: 24,\n}\n\nexport function DockableChat() {\n const t = useT()\n const {\n state,\n isThinking,\n agentStatus,\n isSessionAuthorized,\n messages,\n pendingToolCalls,\n selectedTool,\n close,\n reset,\n handleSubmit,\n sendAgenticMessage,\n stopExecution,\n approveToolCall,\n rejectToolCall,\n debugEvents,\n showDebug,\n setShowDebug,\n clearDebugEvents,\n pendingQuestion,\n answerQuestion,\n } = useCommandPaletteContext()\n\n const {\n dockState,\n setPosition,\n toggleMinimized,\n setMinimized,\n isFloating,\n isHydrated,\n } = useDockPosition()\n\n const {\n isOpen,\n phase,\n isLoading,\n isStreaming,\n connectionStatus,\n } = state\n\n const [localInput, setLocalInput] = React.useState('')\n const [chatInput, setChatInput] = React.useState('')\n const chatInputRef = React.useRef<HTMLInputElement>(null)\n\n // Reset local input when phase changes to idle\n React.useEffect(() => {\n if (phase === 'idle') {\n setLocalInput('')\n setChatInput('')\n }\n }, [phase])\n\n // Focus chat input when entering chatting phase\n React.useEffect(() => {\n if (phase === 'chatting' || phase === 'confirming' || phase === 'executing') {\n setTimeout(() => chatInputRef.current?.focus(), 50)\n }\n }, [phase])\n\n const handleInputSubmit = async () => {\n const query = localInput.trim()\n if (!query) return\n setLocalInput('')\n await handleSubmit(query)\n }\n\n const handleInputKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && phase === 'idle' && localInput.trim()) {\n e.preventDefault()\n handleInputSubmit()\n }\n }\n\n const handleChatSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n if (!chatInput.trim() || isStreaming) return\n\n const content = chatInput\n setChatInput('')\n await sendAgenticMessage(content)\n }\n\n const handleChatKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n if (phase !== 'idle') {\n reset()\n } else {\n close()\n }\n }\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n if (chatInput.trim() && !isStreaming) {\n const content = chatInput\n setChatInput('')\n sendAgenticMessage(content)\n }\n }\n }\n\n // Don't render until hydrated to avoid SSR mismatch\n if (!isHydrated) return null\n\n // When minimized in any mode, show the AiDot in bottom-right corner\n if (isOpen && dockState.isMinimized) {\n return typeof document !== 'undefined' ? createPortal(\n <AiDot\n onClick={() => setMinimized(false)}\n isActive={isStreaming || isThinking}\n hasMessages={messages.length > 0}\n position=\"bottom-right\"\n />,\n document.body\n ) : null\n }\n\n // Render as floating panel when in floating mode\n if (isFloating) {\n if (!isOpen) return null\n\n return typeof document !== 'undefined' ? createPortal(\n <>\n <div\n className={cn(\n 'fixed z-modal',\n 'rounded-xl border bg-background shadow-2xl',\n 'flex flex-col',\n 'transition-all duration-200 ease-out'\n )}\n style={{\n ...FLOATING_POSITION_STYLE,\n width: dockState.width,\n height: dockState.height,\n maxHeight: 'calc(100vh - 48px)',\n }}\n onKeyDown={handleInputKeyDown}\n >\n <Command className=\"flex flex-col flex-1 min-h-0 rounded-xl overflow-hidden\" shouldFilter={false}>\n {/* Dock controls header */}\n <div className=\"flex items-center justify-end px-2 py-1.5 border-b shrink-0\">\n <DockControls\n position={dockState.position}\n onPositionChange={setPosition}\n onMinimize={toggleMinimized}\n onClose={close}\n />\n </div>\n\n <CommandHeader\n phase={phase}\n selectedTool={selectedTool}\n onBack={reset}\n />\n\n {phase === 'idle' && (\n <CommandInput\n value={localInput}\n onValueChange={setLocalInput}\n mode=\"commands\"\n isLoading={isLoading}\n placeholder={t('ai_assistant.chat.placeholder')}\n />\n )}\n\n <div className=\"flex-1 min-h-0 overflow-y-auto\">\n {phase === 'idle' && !localInput && <IdleState />}\n {phase === 'routing' && <RoutingIndicator />}\n {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (\n <ToolChatPage\n tool={selectedTool}\n messages={messages}\n pendingToolCalls={pendingToolCalls}\n isStreaming={isStreaming}\n isThinking={isThinking}\n agentStatus={agentStatus}\n onApproveToolCall={approveToolCall}\n onRejectToolCall={rejectToolCall}\n pendingQuestion={pendingQuestion}\n onAnswerQuestion={answerQuestion}\n />\n )}\n </div>\n\n {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (\n <form onSubmit={handleChatSubmit} className=\"shrink-0 border-t p-3\">\n <div className=\"flex items-center gap-2\">\n <input\n ref={chatInputRef}\n type=\"text\"\n value={chatInput}\n onChange={(e) => setChatInput(e.target.value)}\n onKeyDown={handleChatKeyDown}\n placeholder={t('ai_assistant.chat.describePlaceholder')}\n className={cn(\n 'flex-1 bg-muted rounded-lg px-4 py-2 text-sm outline-none',\n 'focus-visible:ring-2 focus-visible:ring-ring',\n 'disabled:opacity-50'\n )}\n disabled={isStreaming}\n />\n <Button\n type={isStreaming ? 'button' : 'submit'}\n size=\"icon\"\n variant={isStreaming ? 'destructive' : 'default'}\n onClick={isStreaming ? stopExecution : undefined}\n disabled={!isStreaming && !chatInput.trim()}\n >\n {isStreaming ? (\n <Square className=\"h-4 w-4\" />\n ) : (\n <Send className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </form>\n )}\n\n <CommandFooter\n phase={phase}\n connectionStatus={connectionStatus}\n isSessionAuthorized={isSessionAuthorized}\n showDebug={showDebug}\n onToggleDebug={() => setShowDebug(!showDebug)}\n />\n </Command>\n </div>\n\n {showDebug && (\n <div\n data-debug-panel\n className=\"fixed z-top bg-gray-900 rounded-xl border border-gray-700 shadow-2xl flex flex-col overflow-hidden\"\n style={{\n top: '24px',\n left: '24px',\n width: '400px',\n maxHeight: 'calc(100vh - 48px)',\n }}\n >\n <DebugPanel\n events={debugEvents}\n onClear={clearDebugEvents}\n isOpen={true}\n onToggle={() => setShowDebug(false)}\n />\n </div>\n )}\n </>,\n document.body\n ) : null\n }\n\n // Render as docked panel (right, left, bottom)\n if (!isOpen) return null\n\n const positionStyles: Record<Exclude<DockPosition, 'floating'>, React.CSSProperties> = {\n right: {\n position: 'fixed',\n top: 0,\n right: 0,\n bottom: 0,\n width: dockState.width,\n zIndex: 40,\n },\n left: {\n position: 'fixed',\n top: 0,\n left: 0,\n bottom: 0,\n width: dockState.width,\n zIndex: 40,\n },\n bottom: {\n position: 'fixed',\n bottom: 0,\n left: 0,\n right: 0,\n height: dockState.height,\n zIndex: 40,\n },\n }\n\n const panelPosition = dockState.position as Exclude<DockPosition, 'floating'>\n\n return typeof document !== 'undefined' ? createPortal(\n <div\n className={cn(\n 'bg-background border shadow-xl flex flex-col',\n panelPosition === 'right' && 'border-l',\n panelPosition === 'left' && 'border-r',\n panelPosition === 'bottom' && 'border-t'\n )}\n style={positionStyles[panelPosition]}\n onKeyDown={handleInputKeyDown}\n >\n {/* Docked panel header */}\n <div className=\"flex items-center justify-end px-2 py-1.5 border-b shrink-0\">\n <DockControls\n position={dockState.position}\n onPositionChange={setPosition}\n onMinimize={toggleMinimized}\n onClose={close}\n />\n </div>\n\n {!dockState.isMinimized && (\n <>\n <Command className=\"flex flex-col flex-1 min-h-0\" shouldFilter={false}>\n <CommandHeader\n phase={phase}\n selectedTool={selectedTool}\n onBack={reset}\n />\n\n {phase === 'idle' && (\n <CommandInput\n value={localInput}\n onValueChange={setLocalInput}\n mode=\"commands\"\n isLoading={isLoading}\n placeholder={t('ai_assistant.chat.placeholder')}\n />\n )}\n\n <div className=\"flex-1 min-h-0 overflow-y-auto\">\n {phase === 'idle' && !localInput && <IdleState />}\n {phase === 'routing' && <RoutingIndicator />}\n {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (\n <ToolChatPage\n tool={selectedTool}\n messages={messages}\n pendingToolCalls={pendingToolCalls}\n isStreaming={isStreaming}\n isThinking={isThinking}\n agentStatus={agentStatus}\n onApproveToolCall={approveToolCall}\n onRejectToolCall={rejectToolCall}\n pendingQuestion={pendingQuestion}\n onAnswerQuestion={answerQuestion}\n />\n )}\n </div>\n\n {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (\n <form onSubmit={handleChatSubmit} className=\"shrink-0 border-t p-3\">\n <div className=\"flex items-center gap-2\">\n <input\n ref={chatInputRef}\n type=\"text\"\n value={chatInput}\n onChange={(e) => setChatInput(e.target.value)}\n onKeyDown={handleChatKeyDown}\n placeholder={t('ai_assistant.chat.describePlaceholder')}\n className={cn(\n 'flex-1 bg-muted rounded-lg px-4 py-2 text-sm outline-none',\n 'focus-visible:ring-2 focus-visible:ring-ring',\n 'disabled:opacity-50'\n )}\n disabled={isStreaming}\n />\n <Button\n type={isStreaming ? 'button' : 'submit'}\n size=\"icon\"\n variant={isStreaming ? 'destructive' : 'default'}\n onClick={isStreaming ? stopExecution : undefined}\n disabled={!isStreaming && !chatInput.trim()}\n >\n {isStreaming ? (\n <Square className=\"h-4 w-4\" />\n ) : (\n <Send className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </form>\n )}\n\n <CommandFooter\n phase={phase}\n connectionStatus={connectionStatus}\n isSessionAuthorized={isSessionAuthorized}\n showDebug={showDebug}\n onToggleDebug={() => setShowDebug(!showDebug)}\n />\n </Command>\n </>\n )}\n\n {showDebug && (\n <div\n className={cn(\n 'bg-gray-900 border-gray-700 flex flex-col overflow-hidden',\n panelPosition === 'right' && 'absolute left-0 top-0 bottom-0 w-[400px] -translate-x-full border-r',\n panelPosition === 'left' && 'absolute right-0 top-0 bottom-0 w-[400px] translate-x-full border-l',\n panelPosition === 'bottom' && 'absolute bottom-full left-0 right-0 h-[300px] border-t'\n )}\n >\n <DebugPanel\n events={debugEvents}\n onClear={clearDebugEvents}\n isOpen={true}\n onToggle={() => setShowDebug(false)}\n />\n </div>\n )}\n </div>,\n document.body\n ) : null\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|