@open-mercato/ai-assistant 0.4.2-canary-c02407ff85
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/AGENTS.md +1090 -0
- package/README.md +607 -0
- package/build.mjs +92 -0
- package/dist/di.js +8 -0
- package/dist/di.js.map +7 -0
- package/dist/frontend/components/CommandPalette/CommandFooter.js +80 -0
- package/dist/frontend/components/CommandPalette/CommandFooter.js.map +7 -0
- package/dist/frontend/components/CommandPalette/CommandHeader.js +53 -0
- package/dist/frontend/components/CommandPalette/CommandHeader.js.map +7 -0
- package/dist/frontend/components/CommandPalette/CommandInput.js +29 -0
- package/dist/frontend/components/CommandPalette/CommandInput.js.map +7 -0
- package/dist/frontend/components/CommandPalette/CommandItem.js +92 -0
- package/dist/frontend/components/CommandPalette/CommandItem.js.map +7 -0
- package/dist/frontend/components/CommandPalette/CommandPalette.js +244 -0
- package/dist/frontend/components/CommandPalette/CommandPalette.js.map +7 -0
- package/dist/frontend/components/CommandPalette/CommandPaletteProvider.js +42 -0
- package/dist/frontend/components/CommandPalette/CommandPaletteProvider.js.map +7 -0
- package/dist/frontend/components/CommandPalette/CommandPaletteWrapper.js +18 -0
- package/dist/frontend/components/CommandPalette/CommandPaletteWrapper.js.map +7 -0
- package/dist/frontend/components/CommandPalette/DebugPanel.js +215 -0
- package/dist/frontend/components/CommandPalette/DebugPanel.js.map +7 -0
- package/dist/frontend/components/CommandPalette/MessageBubble.js +64 -0
- package/dist/frontend/components/CommandPalette/MessageBubble.js.map +7 -0
- package/dist/frontend/components/CommandPalette/ToolCallConfirmation.js +91 -0
- package/dist/frontend/components/CommandPalette/ToolCallConfirmation.js.map +7 -0
- package/dist/frontend/components/CommandPalette/ToolCallDisplay.js +47 -0
- package/dist/frontend/components/CommandPalette/ToolCallDisplay.js.map +7 -0
- package/dist/frontend/components/CommandPalette/ToolChatPage.js +74 -0
- package/dist/frontend/components/CommandPalette/ToolChatPage.js.map +7 -0
- package/dist/frontend/components/CommandPalette/index.js +28 -0
- package/dist/frontend/components/CommandPalette/index.js.map +7 -0
- package/dist/frontend/constants.js +41 -0
- package/dist/frontend/constants.js.map +7 -0
- package/dist/frontend/hooks/index.js +13 -0
- package/dist/frontend/hooks/index.js.map +7 -0
- package/dist/frontend/hooks/useCommandPalette.js +1094 -0
- package/dist/frontend/hooks/useCommandPalette.js.map +7 -0
- package/dist/frontend/hooks/useMcpTools.js +66 -0
- package/dist/frontend/hooks/useMcpTools.js.map +7 -0
- package/dist/frontend/hooks/usePageContext.js +48 -0
- package/dist/frontend/hooks/usePageContext.js.map +7 -0
- package/dist/frontend/hooks/useRecentActions.js +56 -0
- package/dist/frontend/hooks/useRecentActions.js.map +7 -0
- package/dist/frontend/hooks/useRecentTools.js +55 -0
- package/dist/frontend/hooks/useRecentTools.js.map +7 -0
- package/dist/frontend/index.js +35 -0
- package/dist/frontend/index.js.map +7 -0
- package/dist/frontend/types.js +1 -0
- package/dist/frontend/types.js.map +7 -0
- package/dist/frontend/utils/index.js +7 -0
- package/dist/frontend/utils/index.js.map +7 -0
- package/dist/frontend/utils/toolMatcher.js +95 -0
- package/dist/frontend/utils/toolMatcher.js.map +7 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +7 -0
- package/dist/modules/ai_assistant/acl.js +14 -0
- package/dist/modules/ai_assistant/acl.js.map +7 -0
- package/dist/modules/ai_assistant/api/chat/route.js +152 -0
- package/dist/modules/ai_assistant/api/chat/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/health/route.js +27 -0
- package/dist/modules/ai_assistant/api/health/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/route/route.js +123 -0
- package/dist/modules/ai_assistant/api/route/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/settings/route.js +60 -0
- package/dist/modules/ai_assistant/api/settings/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/tools/execute/route.js +58 -0
- package/dist/modules/ai_assistant/api/tools/execute/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/tools/route.js +48 -0
- package/dist/modules/ai_assistant/api/tools/route.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/page.js +10 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/page.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/page.meta.js +28 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/page.meta.js.map +7 -0
- package/dist/modules/ai_assistant/cli.js +192 -0
- package/dist/modules/ai_assistant/cli.js.map +7 -0
- package/dist/modules/ai_assistant/di.js +11 -0
- package/dist/modules/ai_assistant/di.js.map +7 -0
- package/dist/modules/ai_assistant/frontend/components/AiAssistantSettingsPageClient.js +257 -0
- package/dist/modules/ai_assistant/frontend/components/AiAssistantSettingsPageClient.js.map +7 -0
- package/dist/modules/ai_assistant/index.js +13 -0
- package/dist/modules/ai_assistant/index.js.map +7 -0
- package/dist/modules/ai_assistant/lib/ai-sdk.js +13 -0
- package/dist/modules/ai_assistant/lib/ai-sdk.js.map +7 -0
- package/dist/modules/ai_assistant/lib/api-discovery-tools.js +249 -0
- package/dist/modules/ai_assistant/lib/api-discovery-tools.js.map +7 -0
- package/dist/modules/ai_assistant/lib/api-endpoint-index-config.js +177 -0
- package/dist/modules/ai_assistant/lib/api-endpoint-index-config.js.map +7 -0
- package/dist/modules/ai_assistant/lib/api-endpoint-index.js +210 -0
- package/dist/modules/ai_assistant/lib/api-endpoint-index.js.map +7 -0
- package/dist/modules/ai_assistant/lib/auth.js +87 -0
- package/dist/modules/ai_assistant/lib/auth.js.map +7 -0
- package/dist/modules/ai_assistant/lib/chat-config.js +117 -0
- package/dist/modules/ai_assistant/lib/chat-config.js.map +7 -0
- package/dist/modules/ai_assistant/lib/client-factory.js +60 -0
- package/dist/modules/ai_assistant/lib/client-factory.js.map +7 -0
- package/dist/modules/ai_assistant/lib/http-server.js +367 -0
- package/dist/modules/ai_assistant/lib/http-server.js.map +7 -0
- package/dist/modules/ai_assistant/lib/in-process-client.js +126 -0
- package/dist/modules/ai_assistant/lib/in-process-client.js.map +7 -0
- package/dist/modules/ai_assistant/lib/mcp-client.js +146 -0
- package/dist/modules/ai_assistant/lib/mcp-client.js.map +7 -0
- package/dist/modules/ai_assistant/lib/mcp-dev-server.js +283 -0
- package/dist/modules/ai_assistant/lib/mcp-dev-server.js.map +7 -0
- package/dist/modules/ai_assistant/lib/mcp-server-config.js +160 -0
- package/dist/modules/ai_assistant/lib/mcp-server-config.js.map +7 -0
- package/dist/modules/ai_assistant/lib/mcp-server.js +156 -0
- package/dist/modules/ai_assistant/lib/mcp-server.js.map +7 -0
- package/dist/modules/ai_assistant/lib/mcp-tool-adapter.js +44 -0
- package/dist/modules/ai_assistant/lib/mcp-tool-adapter.js.map +7 -0
- package/dist/modules/ai_assistant/lib/opencode-client.js +247 -0
- package/dist/modules/ai_assistant/lib/opencode-client.js.map +7 -0
- package/dist/modules/ai_assistant/lib/opencode-handlers.js +398 -0
- package/dist/modules/ai_assistant/lib/opencode-handlers.js.map +7 -0
- package/dist/modules/ai_assistant/lib/schema-utils.js +94 -0
- package/dist/modules/ai_assistant/lib/schema-utils.js.map +7 -0
- package/dist/modules/ai_assistant/lib/tool-executor.js +55 -0
- package/dist/modules/ai_assistant/lib/tool-executor.js.map +7 -0
- package/dist/modules/ai_assistant/lib/tool-index-config.js +125 -0
- package/dist/modules/ai_assistant/lib/tool-index-config.js.map +7 -0
- package/dist/modules/ai_assistant/lib/tool-loader.js +88 -0
- package/dist/modules/ai_assistant/lib/tool-loader.js.map +7 -0
- package/dist/modules/ai_assistant/lib/tool-registry.js +65 -0
- package/dist/modules/ai_assistant/lib/tool-registry.js.map +7 -0
- package/dist/modules/ai_assistant/lib/tool-search.js +192 -0
- package/dist/modules/ai_assistant/lib/tool-search.js.map +7 -0
- package/dist/modules/ai_assistant/lib/types.js +1 -0
- package/dist/modules/ai_assistant/lib/types.js.map +7 -0
- package/package.json +108 -0
- package/src/di.ts +11 -0
- package/src/frontend/components/CommandPalette/CommandFooter.tsx +113 -0
- package/src/frontend/components/CommandPalette/CommandHeader.tsx +76 -0
- package/src/frontend/components/CommandPalette/CommandInput.tsx +50 -0
- package/src/frontend/components/CommandPalette/CommandItem.tsx +111 -0
- package/src/frontend/components/CommandPalette/CommandPalette.tsx +276 -0
- package/src/frontend/components/CommandPalette/CommandPaletteProvider.tsx +60 -0
- package/src/frontend/components/CommandPalette/CommandPaletteWrapper.tsx +21 -0
- package/src/frontend/components/CommandPalette/DebugPanel.tsx +257 -0
- package/src/frontend/components/CommandPalette/MessageBubble.tsx +73 -0
- package/src/frontend/components/CommandPalette/ToolCallConfirmation.tsx +130 -0
- package/src/frontend/components/CommandPalette/ToolCallDisplay.tsx +57 -0
- package/src/frontend/components/CommandPalette/ToolChatPage.tsx +125 -0
- package/src/frontend/components/CommandPalette/index.ts +14 -0
- package/src/frontend/constants.ts +35 -0
- package/src/frontend/hooks/index.ts +5 -0
- package/src/frontend/hooks/useCommandPalette.ts +1389 -0
- package/src/frontend/hooks/useMcpTools.ts +73 -0
- package/src/frontend/hooks/usePageContext.ts +61 -0
- package/src/frontend/hooks/useRecentActions.ts +64 -0
- package/src/frontend/hooks/useRecentTools.ts +69 -0
- package/src/frontend/index.ts +39 -0
- package/src/frontend/types.ts +260 -0
- package/src/frontend/utils/index.ts +1 -0
- package/src/frontend/utils/toolMatcher.ts +127 -0
- package/src/index.ts +92 -0
- package/src/modules/ai_assistant/acl.ts +10 -0
- package/src/modules/ai_assistant/api/chat/route.ts +213 -0
- package/src/modules/ai_assistant/api/health/route.ts +30 -0
- package/src/modules/ai_assistant/api/route/route.ts +149 -0
- package/src/modules/ai_assistant/api/settings/route.ts +73 -0
- package/src/modules/ai_assistant/api/tools/execute/route.ts +71 -0
- package/src/modules/ai_assistant/api/tools/route.ts +57 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/page.meta.ts +26 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/page.tsx +12 -0
- package/src/modules/ai_assistant/cli.ts +233 -0
- package/src/modules/ai_assistant/di.ts +9 -0
- package/src/modules/ai_assistant/frontend/components/AiAssistantSettingsPageClient.tsx +418 -0
- package/src/modules/ai_assistant/index.ts +11 -0
- package/src/modules/ai_assistant/lib/ai-sdk.ts +5 -0
- package/src/modules/ai_assistant/lib/api-discovery-tools.ts +334 -0
- package/src/modules/ai_assistant/lib/api-endpoint-index-config.ts +243 -0
- package/src/modules/ai_assistant/lib/api-endpoint-index.ts +381 -0
- package/src/modules/ai_assistant/lib/auth.ts +185 -0
- package/src/modules/ai_assistant/lib/chat-config.ts +152 -0
- package/src/modules/ai_assistant/lib/client-factory.ts +130 -0
- package/src/modules/ai_assistant/lib/http-server.ts +498 -0
- package/src/modules/ai_assistant/lib/in-process-client.ts +205 -0
- package/src/modules/ai_assistant/lib/mcp-client.ts +221 -0
- package/src/modules/ai_assistant/lib/mcp-dev-server.ts +373 -0
- package/src/modules/ai_assistant/lib/mcp-server-config.ts +287 -0
- package/src/modules/ai_assistant/lib/mcp-server.ts +214 -0
- package/src/modules/ai_assistant/lib/mcp-tool-adapter.ts +76 -0
- package/src/modules/ai_assistant/lib/opencode-client.ts +426 -0
- package/src/modules/ai_assistant/lib/opencode-handlers.ts +676 -0
- package/src/modules/ai_assistant/lib/schema-utils.ts +142 -0
- package/src/modules/ai_assistant/lib/tool-executor.ts +71 -0
- package/src/modules/ai_assistant/lib/tool-index-config.ts +178 -0
- package/src/modules/ai_assistant/lib/tool-loader.ts +149 -0
- package/src/modules/ai_assistant/lib/tool-registry.ts +114 -0
- package/src/modules/ai_assistant/lib/tool-search.ts +308 -0
- package/src/modules/ai_assistant/lib/types.ts +147 -0
- package/test-schema.ts +37 -0
- package/tsconfig.json +10 -0
- package/watch.mjs +6 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/frontend/components/CommandPalette/CommandPaletteProvider.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { createContext, useContext, useState, useEffect } from 'react'\nimport type { PageContext, SelectedEntity } from '../../types'\nimport { usePageContext } from '../../hooks/usePageContext'\nimport { useCommandPalette } from '../../hooks/useCommandPalette'\n\ninterface CommandPaletteProviderProps {\n children: React.ReactNode\n tenantId: string\n organizationId: string | null\n disableKeyboardShortcut?: boolean\n}\n\ntype CommandPaletteContextValue = ReturnType<typeof useCommandPalette>\n\nconst CommandPaletteContext = createContext<CommandPaletteContextValue | null>(null)\n\nexport function CommandPaletteProvider({\n children,\n tenantId,\n organizationId,\n disableKeyboardShortcut = true,\n}: CommandPaletteProviderProps) {\n const pageContext = usePageContext({ tenantId, organizationId })\n const [selectedEntities, setSelectedEntities] = useState<SelectedEntity[]>([])\n\n // Listen for DataTable selection events\n useEffect(() => {\n const handleSelectionChange = (event: CustomEvent<SelectedEntity[]>) => {\n setSelectedEntities(event.detail || [])\n }\n\n window.addEventListener('om:selection-change', handleSelectionChange as EventListener)\n return () => {\n window.removeEventListener('om:selection-change', handleSelectionChange as EventListener)\n }\n }, [])\n\n const commandPalette = useCommandPalette({\n pageContext,\n selectedEntities,\n disableKeyboardShortcut,\n })\n\n return (\n <CommandPaletteContext.Provider value={commandPalette}>\n {children}\n </CommandPaletteContext.Provider>\n )\n}\n\nexport function useCommandPaletteContext(): CommandPaletteContextValue {\n const context = useContext(CommandPaletteContext)\n if (!context) {\n throw new Error('useCommandPaletteContext must be used within CommandPaletteProvider')\n }\n return context\n}\n"],
|
|
5
|
+
"mappings": ";AA+CI;AA5CJ,SAAS,eAAe,YAAY,UAAU,iBAAiB;AAE/D,SAAS,sBAAsB;AAC/B,SAAS,yBAAyB;AAWlC,MAAM,wBAAwB,cAAiD,IAAI;AAE5E,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA,0BAA0B;AAC5B,GAAgC;AAC9B,QAAM,cAAc,eAAe,EAAE,UAAU,eAAe,CAAC;AAC/D,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAA2B,CAAC,CAAC;AAG7E,YAAU,MAAM;AACd,UAAM,wBAAwB,CAAC,UAAyC;AACtE,0BAAoB,MAAM,UAAU,CAAC,CAAC;AAAA,IACxC;AAEA,WAAO,iBAAiB,uBAAuB,qBAAsC;AACrF,WAAO,MAAM;AACX,aAAO,oBAAoB,uBAAuB,qBAAsC;AAAA,IAC1F;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAiB,kBAAkB;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE,oBAAC,sBAAsB,UAAtB,EAA+B,OAAO,gBACpC,UACH;AAEJ;AAEO,SAAS,2BAAuD;AACrE,QAAM,UAAU,WAAW,qBAAqB;AAChD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,qEAAqE;AAAA,EACvF;AACA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { CommandPaletteProvider } from "./CommandPaletteProvider.js";
|
|
4
|
+
import { CommandPalette } from "./CommandPalette.js";
|
|
5
|
+
function CommandPaletteWrapper({ tenantId, organizationId }) {
|
|
6
|
+
return /* @__PURE__ */ jsx(
|
|
7
|
+
CommandPaletteProvider,
|
|
8
|
+
{
|
|
9
|
+
tenantId: tenantId ?? "",
|
|
10
|
+
organizationId,
|
|
11
|
+
children: /* @__PURE__ */ jsx(CommandPalette, {})
|
|
12
|
+
}
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
CommandPaletteWrapper
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=CommandPaletteWrapper.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/frontend/components/CommandPalette/CommandPaletteWrapper.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { CommandPaletteProvider } from './CommandPaletteProvider'\nimport { CommandPalette } from './CommandPalette'\n\ninterface CommandPaletteWrapperProps {\n tenantId: string | null\n organizationId: string | null\n}\n\nexport function CommandPaletteWrapper({ tenantId, organizationId }: CommandPaletteWrapperProps) {\n return (\n <CommandPaletteProvider\n tenantId={tenantId ?? ''}\n organizationId={organizationId}\n >\n <CommandPalette />\n </CommandPaletteProvider>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAiBM;AAdN,SAAS,8BAA8B;AACvC,SAAS,sBAAsB;AAOxB,SAAS,sBAAsB,EAAE,UAAU,eAAe,GAA+B;AAC9F,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB;AAAA,MAEA,8BAAC,kBAAe;AAAA;AAAA,EAClB;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Code, X, Trash2 } from "lucide-react";
|
|
5
|
+
import { JsonView } from "react-json-view-lite";
|
|
6
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
7
|
+
function DebugPanel({ events, onClear, isOpen, onToggle }) {
|
|
8
|
+
const scrollRef = React.useRef(null);
|
|
9
|
+
const filteredEvents = React.useMemo(
|
|
10
|
+
() => events.filter((e) => e.type !== "text"),
|
|
11
|
+
[events]
|
|
12
|
+
);
|
|
13
|
+
React.useEffect(() => {
|
|
14
|
+
if (scrollRef.current) {
|
|
15
|
+
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
16
|
+
}
|
|
17
|
+
}, [filteredEvents]);
|
|
18
|
+
if (!isOpen) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full min-h-0", children: [
|
|
22
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-shrink-0 flex items-center justify-between px-3 py-2 border-b border-gray-700", children: [
|
|
23
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-gray-300", children: [
|
|
24
|
+
"Debug Events (",
|
|
25
|
+
filteredEvents.length,
|
|
26
|
+
")"
|
|
27
|
+
] }),
|
|
28
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
29
|
+
/* @__PURE__ */ jsx(
|
|
30
|
+
"button",
|
|
31
|
+
{
|
|
32
|
+
onClick: onClear,
|
|
33
|
+
className: "text-gray-400 hover:text-gray-200",
|
|
34
|
+
title: "Clear events",
|
|
35
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "w-3 h-3" })
|
|
36
|
+
}
|
|
37
|
+
),
|
|
38
|
+
/* @__PURE__ */ jsx(
|
|
39
|
+
"button",
|
|
40
|
+
{
|
|
41
|
+
onClick: onToggle,
|
|
42
|
+
className: "text-gray-400 hover:text-gray-200",
|
|
43
|
+
title: "Close debug panel",
|
|
44
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-3 h-3" })
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
] })
|
|
48
|
+
] }),
|
|
49
|
+
/* @__PURE__ */ jsxs("div", { ref: scrollRef, className: "flex-1 min-h-0 overflow-y-auto p-2 space-y-1", children: [
|
|
50
|
+
filteredEvents.map((event) => /* @__PURE__ */ jsx(DebugEventRow, { event }, event.id)),
|
|
51
|
+
filteredEvents.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 text-center py-4", children: "No events yet" })
|
|
52
|
+
] })
|
|
53
|
+
] });
|
|
54
|
+
}
|
|
55
|
+
function parseNestedJson(data) {
|
|
56
|
+
if (typeof data === "string") {
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(data);
|
|
59
|
+
return parseNestedJson(parsed);
|
|
60
|
+
} catch {
|
|
61
|
+
return data;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(data)) {
|
|
65
|
+
return data.map(parseNestedJson);
|
|
66
|
+
}
|
|
67
|
+
if (data && typeof data === "object") {
|
|
68
|
+
const result = {};
|
|
69
|
+
for (const [key, value] of Object.entries(data)) {
|
|
70
|
+
result[key] = parseNestedJson(value);
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
return data;
|
|
75
|
+
}
|
|
76
|
+
const customDarkStyles = {
|
|
77
|
+
container: "bg-transparent text-[11px] leading-relaxed font-mono",
|
|
78
|
+
basicChildStyle: "pl-4 ml-0",
|
|
79
|
+
label: "text-purple-400 mr-1",
|
|
80
|
+
nullValue: "text-gray-500 italic",
|
|
81
|
+
undefinedValue: "text-gray-500 italic",
|
|
82
|
+
stringValue: "text-green-400",
|
|
83
|
+
booleanValue: "text-yellow-400",
|
|
84
|
+
numberValue: "text-blue-400",
|
|
85
|
+
otherValue: "text-gray-300",
|
|
86
|
+
punctuation: "text-gray-500",
|
|
87
|
+
collapseIcon: "text-gray-400 cursor-pointer select-none mr-1",
|
|
88
|
+
expandIcon: "text-gray-400 cursor-pointer select-none mr-1",
|
|
89
|
+
collapsedContent: "text-gray-500"
|
|
90
|
+
};
|
|
91
|
+
function DebugEventRow({ event }) {
|
|
92
|
+
const [expanded, setExpanded] = React.useState(false);
|
|
93
|
+
const typeColors = {
|
|
94
|
+
"thinking": "text-orange-400",
|
|
95
|
+
"tool-call": "text-blue-400",
|
|
96
|
+
"tool-result": "text-green-400",
|
|
97
|
+
"text": "text-gray-300",
|
|
98
|
+
"error": "text-red-400",
|
|
99
|
+
"done": "text-purple-400",
|
|
100
|
+
"message": "text-yellow-400",
|
|
101
|
+
"connection": "text-cyan-400",
|
|
102
|
+
"metadata": "text-teal-400",
|
|
103
|
+
"debug": "text-gray-500",
|
|
104
|
+
"question": "text-amber-400"
|
|
105
|
+
};
|
|
106
|
+
const formatTime = (date) => {
|
|
107
|
+
return date.toLocaleTimeString("en-US", {
|
|
108
|
+
hour12: false,
|
|
109
|
+
hour: "2-digit",
|
|
110
|
+
minute: "2-digit",
|
|
111
|
+
second: "2-digit"
|
|
112
|
+
}) + "." + String(date.getMilliseconds()).padStart(3, "0");
|
|
113
|
+
};
|
|
114
|
+
const parsedData = React.useMemo(() => parseNestedJson(event.data), [event.data]);
|
|
115
|
+
return /* @__PURE__ */ jsxs("div", { className: "text-xs font-mono", children: [
|
|
116
|
+
/* @__PURE__ */ jsxs(
|
|
117
|
+
"button",
|
|
118
|
+
{
|
|
119
|
+
onClick: () => setExpanded(!expanded),
|
|
120
|
+
className: "w-full text-left flex items-center gap-2 hover:bg-gray-800 rounded px-1 py-0.5",
|
|
121
|
+
children: [
|
|
122
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-500 flex-shrink-0", children: formatTime(event.timestamp) }),
|
|
123
|
+
/* @__PURE__ */ jsx("span", { className: cn("font-medium flex-shrink-0", typeColors[event.type] || "text-gray-400"), children: event.type }),
|
|
124
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-400 truncate flex-1", children: getEventPreview(event) }),
|
|
125
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 flex-shrink-0", children: expanded ? "\u25BC" : "\u25B6" })
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
),
|
|
129
|
+
expanded && /* @__PURE__ */ jsx("div", { className: "bg-gray-800 rounded p-2 mt-1 overflow-x-auto max-h-[300px] overflow-y-auto", children: /* @__PURE__ */ jsx(
|
|
130
|
+
JsonView,
|
|
131
|
+
{
|
|
132
|
+
data: parsedData,
|
|
133
|
+
style: customDarkStyles,
|
|
134
|
+
shouldExpandNode: (level) => level < 2
|
|
135
|
+
}
|
|
136
|
+
) })
|
|
137
|
+
] });
|
|
138
|
+
}
|
|
139
|
+
function getEventPreview(event) {
|
|
140
|
+
const data = event.data;
|
|
141
|
+
if (event.type === "thinking") {
|
|
142
|
+
return "Agent is processing...";
|
|
143
|
+
}
|
|
144
|
+
if (event.type === "tool-call") {
|
|
145
|
+
const toolName = data?.toolName || "unknown";
|
|
146
|
+
const args = data?.args;
|
|
147
|
+
const argsPreview = args ? JSON.stringify(args).substring(0, 40) : "";
|
|
148
|
+
return `${toolName}(${argsPreview}${argsPreview.length >= 40 ? "..." : ""})`;
|
|
149
|
+
}
|
|
150
|
+
if (event.type === "tool-result") {
|
|
151
|
+
const result = data?.result;
|
|
152
|
+
const resultPreview = typeof result === "string" ? result.substring(0, 50) : JSON.stringify(result)?.substring(0, 50);
|
|
153
|
+
return `\u2192 ${resultPreview}${resultPreview && resultPreview.length >= 50 ? "..." : ""}`;
|
|
154
|
+
}
|
|
155
|
+
if (event.type === "text") {
|
|
156
|
+
const content = data?.content || "";
|
|
157
|
+
return content.substring(0, 50) + (content.length > 50 ? "..." : "");
|
|
158
|
+
}
|
|
159
|
+
if (event.type === "error") {
|
|
160
|
+
return data?.error || "Unknown error";
|
|
161
|
+
}
|
|
162
|
+
if (event.type === "message") {
|
|
163
|
+
const role = data?.role || "";
|
|
164
|
+
const content = data?.content || "";
|
|
165
|
+
return `[${role}] ${content.substring(0, 40)}...`;
|
|
166
|
+
}
|
|
167
|
+
if (event.type === "connection") {
|
|
168
|
+
return data?.status || "";
|
|
169
|
+
}
|
|
170
|
+
if (event.type === "metadata") {
|
|
171
|
+
const model = data?.model || "";
|
|
172
|
+
const tokens = data?.tokens;
|
|
173
|
+
const durationMs = data?.durationMs;
|
|
174
|
+
const parts = [];
|
|
175
|
+
if (model) parts.push(model);
|
|
176
|
+
if (tokens) parts.push(`${tokens.input || 0}\u2192${tokens.output || 0} tokens`);
|
|
177
|
+
if (durationMs) parts.push(`${(durationMs / 1e3).toFixed(1)}s`);
|
|
178
|
+
return parts.join(" | ") || "No metadata";
|
|
179
|
+
}
|
|
180
|
+
if (event.type === "debug") {
|
|
181
|
+
const partType = data?.partType || "unknown";
|
|
182
|
+
return `Unknown part: ${partType}`;
|
|
183
|
+
}
|
|
184
|
+
if (event.type === "question") {
|
|
185
|
+
const questionText = data?.questionText || data?.question?.questions?.[0]?.question || data?.header || "Confirmation required";
|
|
186
|
+
return questionText.substring(0, 50) + (questionText.length > 50 ? "..." : "");
|
|
187
|
+
}
|
|
188
|
+
return "";
|
|
189
|
+
}
|
|
190
|
+
function DebugToggleButton({
|
|
191
|
+
isOpen,
|
|
192
|
+
onToggle
|
|
193
|
+
}) {
|
|
194
|
+
return /* @__PURE__ */ jsxs(
|
|
195
|
+
"button",
|
|
196
|
+
{
|
|
197
|
+
type: "button",
|
|
198
|
+
onClick: onToggle,
|
|
199
|
+
className: cn(
|
|
200
|
+
"flex items-center gap-1 text-xs transition-colors",
|
|
201
|
+
isOpen ? "text-blue-500 hover:text-blue-400" : "text-muted-foreground hover:text-foreground"
|
|
202
|
+
),
|
|
203
|
+
title: "Toggle debug panel",
|
|
204
|
+
children: [
|
|
205
|
+
/* @__PURE__ */ jsx(Code, { className: "w-3 h-3" }),
|
|
206
|
+
/* @__PURE__ */ jsx("span", { children: isOpen ? "Hide Debug" : "Debug" })
|
|
207
|
+
]
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
export {
|
|
212
|
+
DebugPanel,
|
|
213
|
+
DebugToggleButton
|
|
214
|
+
};
|
|
215
|
+
//# sourceMappingURL=DebugPanel.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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-[11px] 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
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { User, Bot } from "lucide-react";
|
|
4
|
+
import Markdown from "react-markdown";
|
|
5
|
+
import remarkGfm from "remark-gfm";
|
|
6
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
7
|
+
function MessageBubble({ message }) {
|
|
8
|
+
const isUser = message.role === "user";
|
|
9
|
+
return /* @__PURE__ */ jsxs(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
className: cn(
|
|
13
|
+
"flex gap-3 py-3",
|
|
14
|
+
isUser ? "flex-row-reverse" : "flex-row"
|
|
15
|
+
),
|
|
16
|
+
children: [
|
|
17
|
+
/* @__PURE__ */ jsx(
|
|
18
|
+
"div",
|
|
19
|
+
{
|
|
20
|
+
className: cn(
|
|
21
|
+
"flex items-center justify-center w-8 h-8 rounded-full shrink-0",
|
|
22
|
+
isUser ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
|
|
23
|
+
),
|
|
24
|
+
children: isUser ? /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Bot, { className: "h-4 w-4" })
|
|
25
|
+
}
|
|
26
|
+
),
|
|
27
|
+
/* @__PURE__ */ jsx(
|
|
28
|
+
"div",
|
|
29
|
+
{
|
|
30
|
+
className: cn(
|
|
31
|
+
"flex-1 min-w-0 px-4 py-2 rounded-lg text-sm",
|
|
32
|
+
isUser ? "bg-primary text-primary-foreground ml-12" : "bg-muted text-foreground mr-12"
|
|
33
|
+
),
|
|
34
|
+
children: isUser ? /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap break-words", children: message.content }) : /* @__PURE__ */ jsx("div", { className: cn(
|
|
35
|
+
"prose prose-sm dark:prose-invert max-w-none break-words",
|
|
36
|
+
// Reset margins for first/last children
|
|
37
|
+
"[&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
|
|
38
|
+
// Paragraph spacing - also handle plain text with whitespace-pre-line
|
|
39
|
+
"[&_p]:my-2 [&_p]:leading-relaxed [&_p]:whitespace-pre-line",
|
|
40
|
+
// List styling
|
|
41
|
+
"[&_ul]:my-2 [&_ul]:pl-4 [&_ol]:my-2 [&_ol]:pl-4",
|
|
42
|
+
"[&_li]:my-0.5 [&_li]:leading-relaxed",
|
|
43
|
+
// Headers
|
|
44
|
+
"[&_h1]:text-base [&_h1]:font-semibold [&_h1]:mt-3 [&_h1]:mb-2",
|
|
45
|
+
"[&_h2]:text-sm [&_h2]:font-semibold [&_h2]:mt-3 [&_h2]:mb-1",
|
|
46
|
+
"[&_h3]:text-sm [&_h3]:font-medium [&_h3]:mt-2 [&_h3]:mb-1",
|
|
47
|
+
// Code blocks
|
|
48
|
+
"[&_pre]:bg-background/50 [&_pre]:rounded [&_pre]:p-2 [&_pre]:my-2 [&_pre]:overflow-x-auto",
|
|
49
|
+
"[&_code]:bg-background/50 [&_code]:px-1 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-xs",
|
|
50
|
+
// Strong/emphasis
|
|
51
|
+
"[&_strong]:font-semibold [&_em]:italic",
|
|
52
|
+
// Blockquotes
|
|
53
|
+
"[&_blockquote]:border-l-2 [&_blockquote]:border-muted-foreground/30 [&_blockquote]:pl-3 [&_blockquote]:italic"
|
|
54
|
+
), children: /* @__PURE__ */ jsx(Markdown, { remarkPlugins: [remarkGfm], children: message.content }) })
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
MessageBubble
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=MessageBubble.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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/50 [&_pre]:rounded [&_pre]:p-2 [&_pre]:my-2 [&_pre]:overflow-x-auto',\n '[&_code]:bg-background/50 [&_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
|
+
"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
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Wrench, AlertTriangle, Loader2, Check, X } from "lucide-react";
|
|
4
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
5
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
6
|
+
const DESTRUCTIVE_PATTERNS = [/^delete/i, /^remove/i, /\.delete$/i, /\.remove$/i];
|
|
7
|
+
function isDestructive(toolName) {
|
|
8
|
+
return DESTRUCTIVE_PATTERNS.some((p) => p.test(toolName));
|
|
9
|
+
}
|
|
10
|
+
function ToolCallConfirmation({
|
|
11
|
+
toolCall,
|
|
12
|
+
onApprove,
|
|
13
|
+
onReject
|
|
14
|
+
}) {
|
|
15
|
+
const destructive = isDestructive(toolCall.toolName);
|
|
16
|
+
if (toolCall.status === "executing") {
|
|
17
|
+
return /* @__PURE__ */ jsx("div", { className: "bg-muted/50 rounded-lg p-3 border animate-pulse", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
18
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-primary" }),
|
|
19
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm", children: [
|
|
20
|
+
"Executing ",
|
|
21
|
+
toolCall.toolName,
|
|
22
|
+
"..."
|
|
23
|
+
] })
|
|
24
|
+
] }) });
|
|
25
|
+
}
|
|
26
|
+
if (toolCall.status === "completed") {
|
|
27
|
+
return /* @__PURE__ */ jsx("div", { className: "bg-emerald-50 dark:bg-emerald-900/20 rounded-lg p-3 border border-emerald-200 dark:border-emerald-800", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
28
|
+
/* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-emerald-600 dark:text-emerald-400" }),
|
|
29
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm text-emerald-800 dark:text-emerald-200", children: [
|
|
30
|
+
toolCall.toolName,
|
|
31
|
+
" completed successfully"
|
|
32
|
+
] })
|
|
33
|
+
] }) });
|
|
34
|
+
}
|
|
35
|
+
if (toolCall.status === "error") {
|
|
36
|
+
return /* @__PURE__ */ jsx("div", { className: "bg-destructive/10 rounded-lg p-3 border border-destructive/20", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
37
|
+
/* @__PURE__ */ jsx(X, { className: "h-4 w-4 text-destructive" }),
|
|
38
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm text-destructive", children: [
|
|
39
|
+
toolCall.toolName,
|
|
40
|
+
" failed: ",
|
|
41
|
+
toolCall.error || "Unknown error"
|
|
42
|
+
] })
|
|
43
|
+
] }) });
|
|
44
|
+
}
|
|
45
|
+
if (toolCall.status === "rejected") {
|
|
46
|
+
return /* @__PURE__ */ jsx("div", { className: "bg-muted/30 rounded-lg p-3 border opacity-60", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
47
|
+
/* @__PURE__ */ jsx(X, { className: "h-4 w-4 text-muted-foreground" }),
|
|
48
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground line-through", children: [
|
|
49
|
+
toolCall.toolName,
|
|
50
|
+
" cancelled"
|
|
51
|
+
] })
|
|
52
|
+
] }) });
|
|
53
|
+
}
|
|
54
|
+
return /* @__PURE__ */ jsxs(
|
|
55
|
+
"div",
|
|
56
|
+
{
|
|
57
|
+
className: cn(
|
|
58
|
+
"rounded-lg p-3 border",
|
|
59
|
+
destructive ? "bg-destructive/5 border-destructive/20" : "bg-muted/50 border-border"
|
|
60
|
+
),
|
|
61
|
+
children: [
|
|
62
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
63
|
+
destructive ? /* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4 text-destructive" }) : /* @__PURE__ */ jsx(Wrench, { className: "h-4 w-4 text-primary" }),
|
|
64
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: destructive ? "Destructive action requested" : "AI wants to execute:" })
|
|
65
|
+
] }),
|
|
66
|
+
/* @__PURE__ */ jsxs("div", { className: "font-mono text-xs bg-background rounded p-2 mb-3 overflow-auto max-h-32", children: [
|
|
67
|
+
/* @__PURE__ */ jsx("div", { className: cn("font-medium", destructive ? "text-destructive" : "text-primary"), children: toolCall.toolName }),
|
|
68
|
+
toolCall.args && Object.keys(toolCall.args).length > 0 && /* @__PURE__ */ jsx("pre", { className: "text-muted-foreground mt-1 whitespace-pre-wrap break-all", children: JSON.stringify(toolCall.args, null, 2) })
|
|
69
|
+
] }),
|
|
70
|
+
destructive && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive mb-3", children: "This action may not be reversible." }),
|
|
71
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
72
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "outline", onClick: onReject, className: "flex-1", children: "Cancel" }),
|
|
73
|
+
/* @__PURE__ */ jsx(
|
|
74
|
+
Button,
|
|
75
|
+
{
|
|
76
|
+
size: "sm",
|
|
77
|
+
variant: destructive ? "destructive" : "default",
|
|
78
|
+
onClick: onApprove,
|
|
79
|
+
className: "flex-1",
|
|
80
|
+
children: destructive ? "Delete" : "Execute"
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
] })
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
export {
|
|
89
|
+
ToolCallConfirmation
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=ToolCallConfirmation.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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-emerald-50 dark:bg-emerald-900/20 rounded-lg p-3 border border-emerald-200 dark:border-emerald-800\">\n <div className=\"flex items-center gap-2\">\n <Check className=\"h-4 w-4 text-emerald-600 dark:text-emerald-400\" />\n <span className=\"text-sm text-emerald-800 dark:text-emerald-200\">\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,yGACb,+BAAC,SAAI,WAAU,2BACb;AAAA,0BAAC,SAAM,WAAU,kDAAiD;AAAA,MAClE,qBAAC,UAAK,WAAU,kDACb;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
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Wrench, Check, X, Loader2 } from "lucide-react";
|
|
4
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
5
|
+
import { humanizeToolName } from "../../utils/toolMatcher.js";
|
|
6
|
+
function ToolCallDisplay({ toolCall }) {
|
|
7
|
+
const displayName = humanizeToolName(toolCall.toolName);
|
|
8
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 py-2 px-3 bg-muted/50 rounded-lg my-2", children: [
|
|
9
|
+
/* @__PURE__ */ jsxs(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
className: cn(
|
|
13
|
+
"flex items-center justify-center w-6 h-6 rounded shrink-0",
|
|
14
|
+
toolCall.status === "completed" && "bg-green-100 text-green-600",
|
|
15
|
+
toolCall.status === "error" && "bg-red-100 text-red-600",
|
|
16
|
+
toolCall.status === "running" && "bg-blue-100 text-blue-600",
|
|
17
|
+
toolCall.status === "pending" && "bg-gray-100 text-gray-600"
|
|
18
|
+
),
|
|
19
|
+
children: [
|
|
20
|
+
toolCall.status === "running" && /* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 animate-spin" }),
|
|
21
|
+
toolCall.status === "completed" && /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" }),
|
|
22
|
+
toolCall.status === "error" && /* @__PURE__ */ jsx(X, { className: "h-3 w-3" }),
|
|
23
|
+
toolCall.status === "pending" && /* @__PURE__ */ jsx(Wrench, { className: "h-3 w-3" })
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
),
|
|
27
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 text-xs", children: [
|
|
28
|
+
/* @__PURE__ */ jsx("div", { className: "font-medium text-foreground", children: displayName }),
|
|
29
|
+
Object.keys(toolCall.args).length > 0 && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground mt-1", children: /* @__PURE__ */ jsxs("code", { className: "bg-muted px-1 rounded", children: [
|
|
30
|
+
JSON.stringify(toolCall.args, null, 0).slice(0, 100),
|
|
31
|
+
JSON.stringify(toolCall.args).length > 100 && "..."
|
|
32
|
+
] }) }),
|
|
33
|
+
toolCall.status === "completed" && toolCall.result !== void 0 && /* @__PURE__ */ jsxs("div", { className: "text-green-600 mt-1", children: [
|
|
34
|
+
"Result: ",
|
|
35
|
+
typeof toolCall.result === "object" ? "Success" : String(toolCall.result)
|
|
36
|
+
] }),
|
|
37
|
+
toolCall.status === "error" && toolCall.error && /* @__PURE__ */ jsxs("div", { className: "text-red-600 mt-1", children: [
|
|
38
|
+
"Error: ",
|
|
39
|
+
toolCall.error
|
|
40
|
+
] })
|
|
41
|
+
] })
|
|
42
|
+
] });
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
ToolCallDisplay
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=ToolCallDisplay.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/frontend/components/CommandPalette/ToolCallDisplay.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Wrench, Check, X, Loader2 } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport type { ToolCall } from '../../types'\nimport { humanizeToolName } from '../../utils/toolMatcher'\n\ninterface ToolCallDisplayProps {\n toolCall: ToolCall\n}\n\nexport function ToolCallDisplay({ toolCall }: ToolCallDisplayProps) {\n const displayName = humanizeToolName(toolCall.toolName)\n\n return (\n <div className=\"flex items-start gap-3 py-2 px-3 bg-muted/50 rounded-lg my-2\">\n <div\n className={cn(\n 'flex items-center justify-center w-6 h-6 rounded shrink-0',\n toolCall.status === 'completed' && 'bg-green-100 text-green-600',\n toolCall.status === 'error' && 'bg-red-100 text-red-600',\n toolCall.status === 'running' && 'bg-blue-100 text-blue-600',\n toolCall.status === 'pending' && 'bg-gray-100 text-gray-600'\n )}\n >\n {toolCall.status === 'running' && <Loader2 className=\"h-3 w-3 animate-spin\" />}\n {toolCall.status === 'completed' && <Check className=\"h-3 w-3\" />}\n {toolCall.status === 'error' && <X className=\"h-3 w-3\" />}\n {toolCall.status === 'pending' && <Wrench className=\"h-3 w-3\" />}\n </div>\n\n <div className=\"flex-1 min-w-0 text-xs\">\n <div className=\"font-medium text-foreground\">{displayName}</div>\n\n {Object.keys(toolCall.args).length > 0 && (\n <div className=\"text-muted-foreground mt-1\">\n <code className=\"bg-muted px-1 rounded\">\n {JSON.stringify(toolCall.args, null, 0).slice(0, 100)}\n {JSON.stringify(toolCall.args).length > 100 && '...'}\n </code>\n </div>\n )}\n\n {toolCall.status === 'completed' && toolCall.result !== undefined && (\n <div className=\"text-green-600 mt-1\">\n Result: {typeof toolCall.result === 'object' ? 'Success' : String(toolCall.result)}\n </div>\n )}\n\n {toolCall.status === 'error' && toolCall.error && (\n <div className=\"text-red-600 mt-1\">Error: {toolCall.error}</div>\n )}\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAiBM,SASoC,KATpC;AAdN,SAAS,QAAQ,OAAO,GAAG,eAAe;AAC1C,SAAS,UAAU;AAEnB,SAAS,wBAAwB;AAM1B,SAAS,gBAAgB,EAAE,SAAS,GAAyB;AAClE,QAAM,cAAc,iBAAiB,SAAS,QAAQ;AAEtD,SACE,qBAAC,SAAI,WAAU,gEACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA,SAAS,WAAW,eAAe;AAAA,UACnC,SAAS,WAAW,WAAW;AAAA,UAC/B,SAAS,WAAW,aAAa;AAAA,UACjC,SAAS,WAAW,aAAa;AAAA,QACnC;AAAA,QAEC;AAAA,mBAAS,WAAW,aAAa,oBAAC,WAAQ,WAAU,wBAAuB;AAAA,UAC3E,SAAS,WAAW,eAAe,oBAAC,SAAM,WAAU,WAAU;AAAA,UAC9D,SAAS,WAAW,WAAW,oBAAC,KAAE,WAAU,WAAU;AAAA,UACtD,SAAS,WAAW,aAAa,oBAAC,UAAO,WAAU,WAAU;AAAA;AAAA;AAAA,IAChE;AAAA,IAEA,qBAAC,SAAI,WAAU,0BACb;AAAA,0BAAC,SAAI,WAAU,+BAA+B,uBAAY;AAAA,MAEzD,OAAO,KAAK,SAAS,IAAI,EAAE,SAAS,KACnC,oBAAC,SAAI,WAAU,8BACb,+BAAC,UAAK,WAAU,yBACb;AAAA,aAAK,UAAU,SAAS,MAAM,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG;AAAA,QACnD,KAAK,UAAU,SAAS,IAAI,EAAE,SAAS,OAAO;AAAA,SACjD,GACF;AAAA,MAGD,SAAS,WAAW,eAAe,SAAS,WAAW,UACtD,qBAAC,SAAI,WAAU,uBAAsB;AAAA;AAAA,QAC1B,OAAO,SAAS,WAAW,WAAW,YAAY,OAAO,SAAS,MAAM;AAAA,SACnF;AAAA,MAGD,SAAS,WAAW,WAAW,SAAS,SACvC,qBAAC,SAAI,WAAU,qBAAoB;AAAA;AAAA,QAAQ,SAAS;AAAA,SAAM;AAAA,OAE9D;AAAA,KACF;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useRef, useEffect } from "react";
|
|
4
|
+
import { Loader2 } from "lucide-react";
|
|
5
|
+
import Markdown from "react-markdown";
|
|
6
|
+
import remarkGfm from "remark-gfm";
|
|
7
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
8
|
+
import { MessageBubble } from "./MessageBubble.js";
|
|
9
|
+
import { ToolCallConfirmation } from "./ToolCallConfirmation.js";
|
|
10
|
+
function ToolChatPage({
|
|
11
|
+
tool,
|
|
12
|
+
messages,
|
|
13
|
+
pendingToolCalls,
|
|
14
|
+
isStreaming,
|
|
15
|
+
isThinking = false,
|
|
16
|
+
onApproveToolCall,
|
|
17
|
+
onRejectToolCall,
|
|
18
|
+
pendingQuestion,
|
|
19
|
+
onAnswerQuestion
|
|
20
|
+
}) {
|
|
21
|
+
const bottomRef = useRef(null);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const timeoutId = setTimeout(() => {
|
|
24
|
+
bottomRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
|
|
25
|
+
}, 100);
|
|
26
|
+
return () => clearTimeout(timeoutId);
|
|
27
|
+
}, [messages, pendingToolCalls, isStreaming, isThinking, pendingQuestion]);
|
|
28
|
+
return /* @__PURE__ */ jsxs("div", { className: "p-3 space-y-3", children: [
|
|
29
|
+
tool && /* @__PURE__ */ jsx("div", { className: "-mx-3 -mt-3 mb-3 px-3 py-2 border-b bg-muted/20", children: /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground line-clamp-2", children: tool.description }) }),
|
|
30
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
31
|
+
messages.map((message) => /* @__PURE__ */ jsx(MessageBubble, { message }, message.id)),
|
|
32
|
+
pendingToolCalls.filter((tc) => tc.status === "pending" || tc.status === "error").map((toolCall) => /* @__PURE__ */ jsx(
|
|
33
|
+
ToolCallConfirmation,
|
|
34
|
+
{
|
|
35
|
+
toolCall,
|
|
36
|
+
onApprove: () => onApproveToolCall(toolCall.id),
|
|
37
|
+
onReject: () => onRejectToolCall(toolCall.id)
|
|
38
|
+
},
|
|
39
|
+
toolCall.id
|
|
40
|
+
)),
|
|
41
|
+
pendingQuestion && pendingQuestion.questions[0] && /* @__PURE__ */ jsxs("div", { className: "p-4 bg-amber-500/10 border border-amber-500/30 rounded-lg space-y-3", children: [
|
|
42
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-amber-600 dark:text-amber-400 text-sm font-medium", children: [
|
|
43
|
+
/* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("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" }) }),
|
|
44
|
+
/* @__PURE__ */ jsx("span", { children: pendingQuestion.questions[0].header || "Confirmation Required" })
|
|
45
|
+
] }),
|
|
46
|
+
/* @__PURE__ */ jsx("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", children: /* @__PURE__ */ jsx(Markdown, { remarkPlugins: [remarkGfm], children: pendingQuestion.questions[0].question }) }),
|
|
47
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-2 flex-wrap", children: pendingQuestion.questions[0].options.map((option, index) => /* @__PURE__ */ jsx(
|
|
48
|
+
Button,
|
|
49
|
+
{
|
|
50
|
+
variant: index === 0 ? "default" : "outline",
|
|
51
|
+
size: "sm",
|
|
52
|
+
onClick: () => onAnswerQuestion?.(index),
|
|
53
|
+
disabled: isStreaming,
|
|
54
|
+
children: option.label
|
|
55
|
+
},
|
|
56
|
+
index
|
|
57
|
+
)) })
|
|
58
|
+
] }),
|
|
59
|
+
isThinking && !pendingQuestion && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 py-3 px-3 bg-muted/50 rounded-lg text-muted-foreground text-sm", children: [
|
|
60
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
61
|
+
/* @__PURE__ */ jsx("span", { children: "Agent is working..." })
|
|
62
|
+
] }),
|
|
63
|
+
isStreaming && !isThinking && !pendingQuestion && messages[messages.length - 1]?.role !== "assistant" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 py-2 text-muted-foreground text-sm", children: [
|
|
64
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
65
|
+
/* @__PURE__ */ jsx("span", { children: "AI is responding..." })
|
|
66
|
+
] }),
|
|
67
|
+
/* @__PURE__ */ jsx("div", { ref: bottomRef })
|
|
68
|
+
] })
|
|
69
|
+
] });
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
ToolChatPage
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=ToolChatPage.js.map
|