@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,130 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Wrench, AlertTriangle, Loader2, Check, X } from 'lucide-react'
|
|
5
|
+
import { cn } from '@open-mercato/shared/lib/utils'
|
|
6
|
+
import { Button } from '@open-mercato/ui/primitives/button'
|
|
7
|
+
import type { PendingToolCall } from '../../types'
|
|
8
|
+
|
|
9
|
+
interface ToolCallConfirmationProps {
|
|
10
|
+
toolCall: PendingToolCall
|
|
11
|
+
onApprove: () => void
|
|
12
|
+
onReject: () => void
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const DESTRUCTIVE_PATTERNS = [/^delete/i, /^remove/i, /\.delete$/i, /\.remove$/i]
|
|
16
|
+
|
|
17
|
+
function isDestructive(toolName: string): boolean {
|
|
18
|
+
return DESTRUCTIVE_PATTERNS.some((p) => p.test(toolName))
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function ToolCallConfirmation({
|
|
22
|
+
toolCall,
|
|
23
|
+
onApprove,
|
|
24
|
+
onReject,
|
|
25
|
+
}: ToolCallConfirmationProps) {
|
|
26
|
+
const destructive = isDestructive(toolCall.toolName)
|
|
27
|
+
|
|
28
|
+
// Show different UI based on status
|
|
29
|
+
if (toolCall.status === 'executing') {
|
|
30
|
+
return (
|
|
31
|
+
<div className="bg-muted/50 rounded-lg p-3 border animate-pulse">
|
|
32
|
+
<div className="flex items-center gap-2">
|
|
33
|
+
<Loader2 className="h-4 w-4 animate-spin text-primary" />
|
|
34
|
+
<span className="text-sm">Executing {toolCall.toolName}...</span>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (toolCall.status === 'completed') {
|
|
41
|
+
return (
|
|
42
|
+
<div className="bg-emerald-50 dark:bg-emerald-900/20 rounded-lg p-3 border border-emerald-200 dark:border-emerald-800">
|
|
43
|
+
<div className="flex items-center gap-2">
|
|
44
|
+
<Check className="h-4 w-4 text-emerald-600 dark:text-emerald-400" />
|
|
45
|
+
<span className="text-sm text-emerald-800 dark:text-emerald-200">
|
|
46
|
+
{toolCall.toolName} completed successfully
|
|
47
|
+
</span>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (toolCall.status === 'error') {
|
|
54
|
+
return (
|
|
55
|
+
<div className="bg-destructive/10 rounded-lg p-3 border border-destructive/20">
|
|
56
|
+
<div className="flex items-center gap-2">
|
|
57
|
+
<X className="h-4 w-4 text-destructive" />
|
|
58
|
+
<span className="text-sm text-destructive">
|
|
59
|
+
{toolCall.toolName} failed: {toolCall.error || 'Unknown error'}
|
|
60
|
+
</span>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (toolCall.status === 'rejected') {
|
|
67
|
+
return (
|
|
68
|
+
<div className="bg-muted/30 rounded-lg p-3 border opacity-60">
|
|
69
|
+
<div className="flex items-center gap-2">
|
|
70
|
+
<X className="h-4 w-4 text-muted-foreground" />
|
|
71
|
+
<span className="text-sm text-muted-foreground line-through">
|
|
72
|
+
{toolCall.toolName} cancelled
|
|
73
|
+
</span>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Pending state - show confirmation UI
|
|
80
|
+
return (
|
|
81
|
+
<div
|
|
82
|
+
className={cn(
|
|
83
|
+
'rounded-lg p-3 border',
|
|
84
|
+
destructive
|
|
85
|
+
? 'bg-destructive/5 border-destructive/20'
|
|
86
|
+
: 'bg-muted/50 border-border'
|
|
87
|
+
)}
|
|
88
|
+
>
|
|
89
|
+
<div className="flex items-center gap-2 mb-2">
|
|
90
|
+
{destructive ? (
|
|
91
|
+
<AlertTriangle className="h-4 w-4 text-destructive" />
|
|
92
|
+
) : (
|
|
93
|
+
<Wrench className="h-4 w-4 text-primary" />
|
|
94
|
+
)}
|
|
95
|
+
<span className="font-medium text-sm">
|
|
96
|
+
{destructive ? 'Destructive action requested' : 'AI wants to execute:'}
|
|
97
|
+
</span>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<div className="font-mono text-xs bg-background rounded p-2 mb-3 overflow-auto max-h-32">
|
|
101
|
+
<div className={cn('font-medium', destructive ? 'text-destructive' : 'text-primary')}>
|
|
102
|
+
{toolCall.toolName}
|
|
103
|
+
</div>
|
|
104
|
+
{toolCall.args && Object.keys(toolCall.args).length > 0 && (
|
|
105
|
+
<pre className="text-muted-foreground mt-1 whitespace-pre-wrap break-all">
|
|
106
|
+
{JSON.stringify(toolCall.args, null, 2)}
|
|
107
|
+
</pre>
|
|
108
|
+
)}
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
{destructive && (
|
|
112
|
+
<p className="text-xs text-destructive mb-3">This action may not be reversible.</p>
|
|
113
|
+
)}
|
|
114
|
+
|
|
115
|
+
<div className="flex gap-2">
|
|
116
|
+
<Button size="sm" variant="outline" onClick={onReject} className="flex-1">
|
|
117
|
+
Cancel
|
|
118
|
+
</Button>
|
|
119
|
+
<Button
|
|
120
|
+
size="sm"
|
|
121
|
+
variant={destructive ? 'destructive' : 'default'}
|
|
122
|
+
onClick={onApprove}
|
|
123
|
+
className="flex-1"
|
|
124
|
+
>
|
|
125
|
+
{destructive ? 'Delete' : 'Execute'}
|
|
126
|
+
</Button>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Wrench, Check, X, Loader2 } from 'lucide-react'
|
|
5
|
+
import { cn } from '@open-mercato/shared/lib/utils'
|
|
6
|
+
import type { ToolCall } from '../../types'
|
|
7
|
+
import { humanizeToolName } from '../../utils/toolMatcher'
|
|
8
|
+
|
|
9
|
+
interface ToolCallDisplayProps {
|
|
10
|
+
toolCall: ToolCall
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function ToolCallDisplay({ toolCall }: ToolCallDisplayProps) {
|
|
14
|
+
const displayName = humanizeToolName(toolCall.toolName)
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div className="flex items-start gap-3 py-2 px-3 bg-muted/50 rounded-lg my-2">
|
|
18
|
+
<div
|
|
19
|
+
className={cn(
|
|
20
|
+
'flex items-center justify-center w-6 h-6 rounded shrink-0',
|
|
21
|
+
toolCall.status === 'completed' && 'bg-green-100 text-green-600',
|
|
22
|
+
toolCall.status === 'error' && 'bg-red-100 text-red-600',
|
|
23
|
+
toolCall.status === 'running' && 'bg-blue-100 text-blue-600',
|
|
24
|
+
toolCall.status === 'pending' && 'bg-gray-100 text-gray-600'
|
|
25
|
+
)}
|
|
26
|
+
>
|
|
27
|
+
{toolCall.status === 'running' && <Loader2 className="h-3 w-3 animate-spin" />}
|
|
28
|
+
{toolCall.status === 'completed' && <Check className="h-3 w-3" />}
|
|
29
|
+
{toolCall.status === 'error' && <X className="h-3 w-3" />}
|
|
30
|
+
{toolCall.status === 'pending' && <Wrench className="h-3 w-3" />}
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div className="flex-1 min-w-0 text-xs">
|
|
34
|
+
<div className="font-medium text-foreground">{displayName}</div>
|
|
35
|
+
|
|
36
|
+
{Object.keys(toolCall.args).length > 0 && (
|
|
37
|
+
<div className="text-muted-foreground mt-1">
|
|
38
|
+
<code className="bg-muted px-1 rounded">
|
|
39
|
+
{JSON.stringify(toolCall.args, null, 0).slice(0, 100)}
|
|
40
|
+
{JSON.stringify(toolCall.args).length > 100 && '...'}
|
|
41
|
+
</code>
|
|
42
|
+
</div>
|
|
43
|
+
)}
|
|
44
|
+
|
|
45
|
+
{toolCall.status === 'completed' && toolCall.result !== undefined && (
|
|
46
|
+
<div className="text-green-600 mt-1">
|
|
47
|
+
Result: {typeof toolCall.result === 'object' ? 'Success' : String(toolCall.result)}
|
|
48
|
+
</div>
|
|
49
|
+
)}
|
|
50
|
+
|
|
51
|
+
{toolCall.status === 'error' && toolCall.error && (
|
|
52
|
+
<div className="text-red-600 mt-1">Error: {toolCall.error}</div>
|
|
53
|
+
)}
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { useRef, useEffect } from 'react'
|
|
5
|
+
import { Loader2 } from 'lucide-react'
|
|
6
|
+
import Markdown from 'react-markdown'
|
|
7
|
+
import remarkGfm from 'remark-gfm'
|
|
8
|
+
import { Button } from '@open-mercato/ui/primitives/button'
|
|
9
|
+
import type { ToolInfo, ChatMessage, PendingToolCall, OpenCodeQuestion } from '../../types'
|
|
10
|
+
import { MessageBubble } from './MessageBubble'
|
|
11
|
+
import { ToolCallConfirmation } from './ToolCallConfirmation'
|
|
12
|
+
|
|
13
|
+
interface ToolChatPageProps {
|
|
14
|
+
tool: ToolInfo | null // Can be null for general chat
|
|
15
|
+
messages: ChatMessage[]
|
|
16
|
+
pendingToolCalls: PendingToolCall[]
|
|
17
|
+
isStreaming: boolean
|
|
18
|
+
isThinking?: boolean
|
|
19
|
+
onApproveToolCall: (toolCallId: string) => Promise<void>
|
|
20
|
+
onRejectToolCall: (toolCallId: string) => void
|
|
21
|
+
pendingQuestion?: OpenCodeQuestion | null
|
|
22
|
+
onAnswerQuestion?: (answer: number) => Promise<void>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function ToolChatPage({
|
|
26
|
+
tool,
|
|
27
|
+
messages,
|
|
28
|
+
pendingToolCalls,
|
|
29
|
+
isStreaming,
|
|
30
|
+
isThinking = false,
|
|
31
|
+
onApproveToolCall,
|
|
32
|
+
onRejectToolCall,
|
|
33
|
+
pendingQuestion,
|
|
34
|
+
onAnswerQuestion,
|
|
35
|
+
}: ToolChatPageProps) {
|
|
36
|
+
const bottomRef = useRef<HTMLDivElement>(null)
|
|
37
|
+
|
|
38
|
+
// Auto-scroll to bottom on new messages (debounced)
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const timeoutId = setTimeout(() => {
|
|
41
|
+
bottomRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })
|
|
42
|
+
}, 100)
|
|
43
|
+
|
|
44
|
+
return () => clearTimeout(timeoutId)
|
|
45
|
+
}, [messages, pendingToolCalls, isStreaming, isThinking, pendingQuestion])
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div className="p-3 space-y-3">
|
|
49
|
+
{/* Tool description header - only shown if tool is selected */}
|
|
50
|
+
{tool && (
|
|
51
|
+
<div className="-mx-3 -mt-3 mb-3 px-3 py-2 border-b bg-muted/20">
|
|
52
|
+
<p className="text-xs text-muted-foreground line-clamp-2">{tool.description}</p>
|
|
53
|
+
</div>
|
|
54
|
+
)}
|
|
55
|
+
|
|
56
|
+
{/* Chat messages */}
|
|
57
|
+
<div className="space-y-3">
|
|
58
|
+
{messages.map((message) => (
|
|
59
|
+
<MessageBubble key={message.id} message={message} />
|
|
60
|
+
))}
|
|
61
|
+
|
|
62
|
+
{/* Only show tool calls that require user action (pending dangerous tools or errors) */}
|
|
63
|
+
{pendingToolCalls
|
|
64
|
+
.filter((tc) => tc.status === 'pending' || tc.status === 'error')
|
|
65
|
+
.map((toolCall) => (
|
|
66
|
+
<ToolCallConfirmation
|
|
67
|
+
key={toolCall.id}
|
|
68
|
+
toolCall={toolCall}
|
|
69
|
+
onApprove={() => onApproveToolCall(toolCall.id)}
|
|
70
|
+
onReject={() => onRejectToolCall(toolCall.id)}
|
|
71
|
+
/>
|
|
72
|
+
))}
|
|
73
|
+
|
|
74
|
+
{/* OpenCode confirmation question */}
|
|
75
|
+
{pendingQuestion && pendingQuestion.questions[0] && (
|
|
76
|
+
<div className="p-4 bg-amber-500/10 border border-amber-500/30 rounded-lg space-y-3">
|
|
77
|
+
<div className="flex items-center gap-2 text-amber-600 dark:text-amber-400 text-sm font-medium">
|
|
78
|
+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
79
|
+
<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" />
|
|
80
|
+
</svg>
|
|
81
|
+
<span>{pendingQuestion.questions[0].header || 'Confirmation Required'}</span>
|
|
82
|
+
</div>
|
|
83
|
+
<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">
|
|
84
|
+
<Markdown remarkPlugins={[remarkGfm]}>
|
|
85
|
+
{pendingQuestion.questions[0].question}
|
|
86
|
+
</Markdown>
|
|
87
|
+
</div>
|
|
88
|
+
<div className="flex gap-2 flex-wrap">
|
|
89
|
+
{pendingQuestion.questions[0].options.map((option, index) => (
|
|
90
|
+
<Button
|
|
91
|
+
key={index}
|
|
92
|
+
variant={index === 0 ? 'default' : 'outline'}
|
|
93
|
+
size="sm"
|
|
94
|
+
onClick={() => onAnswerQuestion?.(index)}
|
|
95
|
+
disabled={isStreaming}
|
|
96
|
+
>
|
|
97
|
+
{option.label}
|
|
98
|
+
</Button>
|
|
99
|
+
))}
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
)}
|
|
103
|
+
|
|
104
|
+
{/* Thinking indicator - OpenCode is processing */}
|
|
105
|
+
{isThinking && !pendingQuestion && (
|
|
106
|
+
<div className="flex items-center gap-2 py-3 px-3 bg-muted/50 rounded-lg text-muted-foreground text-sm">
|
|
107
|
+
<Loader2 className="h-4 w-4 animate-spin" />
|
|
108
|
+
<span>Agent is working...</span>
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
|
|
112
|
+
{/* Streaming indicator - fallback for non-thinking streaming */}
|
|
113
|
+
{isStreaming && !isThinking && !pendingQuestion && messages[messages.length - 1]?.role !== 'assistant' && (
|
|
114
|
+
<div className="flex items-center gap-2 py-2 text-muted-foreground text-sm">
|
|
115
|
+
<Loader2 className="h-4 w-4 animate-spin" />
|
|
116
|
+
<span>AI is responding...</span>
|
|
117
|
+
</div>
|
|
118
|
+
)}
|
|
119
|
+
|
|
120
|
+
{/* Scroll anchor */}
|
|
121
|
+
<div ref={bottomRef} />
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
)
|
|
125
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { CommandPalette } from './CommandPalette'
|
|
2
|
+
export { CommandPaletteProvider, useCommandPaletteContext } from './CommandPaletteProvider'
|
|
3
|
+
export { CommandPaletteWrapper } from './CommandPaletteWrapper'
|
|
4
|
+
export { CommandInput } from './CommandInput'
|
|
5
|
+
export { CommandItem } from './CommandItem'
|
|
6
|
+
export { MessageBubble } from './MessageBubble'
|
|
7
|
+
export { ToolCallDisplay } from './ToolCallDisplay'
|
|
8
|
+
|
|
9
|
+
// Raycast-style components
|
|
10
|
+
export { CommandHeader } from './CommandHeader'
|
|
11
|
+
export { CommandFooter } from './CommandFooter'
|
|
12
|
+
export { ToolChatPage } from './ToolChatPage'
|
|
13
|
+
export { ToolCallConfirmation } from './ToolCallConfirmation'
|
|
14
|
+
export { DebugPanel } from './DebugPanel'
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const COMMAND_PALETTE_SHORTCUT = {
|
|
2
|
+
key: 'k',
|
|
3
|
+
meta: true, // Cmd on Mac, Ctrl on Windows/Linux
|
|
4
|
+
} as const
|
|
5
|
+
|
|
6
|
+
export const RECENT_ACTIONS_KEY = 'om:command-palette:recent-actions'
|
|
7
|
+
export const MAX_RECENT_ACTIONS = 10
|
|
8
|
+
|
|
9
|
+
export const NATURAL_LANGUAGE_PATTERNS = [
|
|
10
|
+
/^(what|how|why|when|where|who|can you|please|help|show me|find|search|list|create|update|delete)/i,
|
|
11
|
+
/\?$/,
|
|
12
|
+
/^(i want|i need|i'd like)/i,
|
|
13
|
+
] as const
|
|
14
|
+
|
|
15
|
+
export const MODULE_ICONS: Record<string, string> = {
|
|
16
|
+
customers: 'users',
|
|
17
|
+
catalog: 'package',
|
|
18
|
+
sales: 'shopping-cart',
|
|
19
|
+
search: 'search',
|
|
20
|
+
auth: 'lock',
|
|
21
|
+
dictionaries: 'book',
|
|
22
|
+
directory: 'folder',
|
|
23
|
+
currencies: 'dollar-sign',
|
|
24
|
+
feature_toggles: 'toggle-left',
|
|
25
|
+
} as const
|
|
26
|
+
|
|
27
|
+
export const ACTION_ICONS: Record<string, string> = {
|
|
28
|
+
create: 'plus',
|
|
29
|
+
update: 'edit',
|
|
30
|
+
delete: 'trash',
|
|
31
|
+
search: 'search',
|
|
32
|
+
query: 'search',
|
|
33
|
+
get: 'eye',
|
|
34
|
+
list: 'list',
|
|
35
|
+
} as const
|