@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,418 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { useState } from 'react'
|
|
5
|
+
import { useQuery } from '@tanstack/react-query'
|
|
6
|
+
import { Bot, Loader2, CheckCircle2, XCircle, ChevronDown, ChevronRight, Server, Wrench, AlertTriangle } from 'lucide-react'
|
|
7
|
+
import { Button } from '@open-mercato/ui/primitives/button'
|
|
8
|
+
import {
|
|
9
|
+
CommandPaletteProvider,
|
|
10
|
+
CommandPalette,
|
|
11
|
+
useCommandPaletteContext,
|
|
12
|
+
} from '../../../../frontend'
|
|
13
|
+
|
|
14
|
+
// OpenCode health response type
|
|
15
|
+
type OpenCodeHealthResponse = {
|
|
16
|
+
status: 'ok' | 'error'
|
|
17
|
+
opencode?: {
|
|
18
|
+
healthy: boolean
|
|
19
|
+
version: string
|
|
20
|
+
}
|
|
21
|
+
mcp?: Record<string, { status: string; error?: string }>
|
|
22
|
+
search?: {
|
|
23
|
+
available: boolean
|
|
24
|
+
driver: string | null
|
|
25
|
+
}
|
|
26
|
+
url: string
|
|
27
|
+
message?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Provider config type from settings API
|
|
31
|
+
type ProviderConfig = {
|
|
32
|
+
id: string
|
|
33
|
+
name: string
|
|
34
|
+
model: string
|
|
35
|
+
defaultModel: string
|
|
36
|
+
envKey: string
|
|
37
|
+
configured: boolean
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type SettingsResponse = {
|
|
41
|
+
provider: ProviderConfig
|
|
42
|
+
availableProviders: ProviderConfig[]
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Tool info type
|
|
46
|
+
type ToolInfo = {
|
|
47
|
+
name: string
|
|
48
|
+
description: string
|
|
49
|
+
module: string
|
|
50
|
+
inputSchema: Record<string, unknown>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// API fetch functions
|
|
54
|
+
async function fetchHealth(): Promise<OpenCodeHealthResponse> {
|
|
55
|
+
const res = await fetch('/api/ai_assistant/health')
|
|
56
|
+
if (!res.ok) throw new Error('Failed to fetch health')
|
|
57
|
+
return res.json()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function fetchSettings(): Promise<SettingsResponse> {
|
|
61
|
+
const res = await fetch('/api/ai_assistant/settings')
|
|
62
|
+
if (!res.ok) throw new Error('Failed to fetch settings')
|
|
63
|
+
return res.json()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function fetchTools(): Promise<{ tools: ToolInfo[] }> {
|
|
67
|
+
const res = await fetch('/api/ai_assistant/tools')
|
|
68
|
+
if (!res.ok) throw new Error('Failed to fetch tools')
|
|
69
|
+
return res.json()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function AiAssistantSettingsContent() {
|
|
73
|
+
const [toolsExpanded, setToolsExpanded] = useState(false)
|
|
74
|
+
const { setIsOpen } = useCommandPaletteContext()
|
|
75
|
+
|
|
76
|
+
// Health query - polls every 10 seconds
|
|
77
|
+
const healthQuery = useQuery({
|
|
78
|
+
queryKey: ['ai-assistant', 'health'],
|
|
79
|
+
queryFn: fetchHealth,
|
|
80
|
+
refetchInterval: 10000,
|
|
81
|
+
staleTime: 5000,
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// Settings query - no polling needed (static config)
|
|
85
|
+
const settingsQuery = useQuery({
|
|
86
|
+
queryKey: ['ai-assistant', 'settings'],
|
|
87
|
+
queryFn: fetchSettings,
|
|
88
|
+
staleTime: 60000,
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
// Tools query - no polling needed
|
|
92
|
+
const toolsQuery = useQuery({
|
|
93
|
+
queryKey: ['ai-assistant', 'tools'],
|
|
94
|
+
queryFn: fetchTools,
|
|
95
|
+
staleTime: 60000,
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
// Open AI Assistant palette
|
|
99
|
+
const openAiAssistant = () => {
|
|
100
|
+
setIsOpen(true)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const isLoading = healthQuery.isLoading || settingsQuery.isLoading || toolsQuery.isLoading
|
|
104
|
+
|
|
105
|
+
if (isLoading) {
|
|
106
|
+
return (
|
|
107
|
+
<div className="flex items-center gap-2 text-muted-foreground py-8">
|
|
108
|
+
<Loader2 className="h-4 w-4 animate-spin" />
|
|
109
|
+
Loading settings...
|
|
110
|
+
</div>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const health = healthQuery.data
|
|
115
|
+
const settings = settingsQuery.data
|
|
116
|
+
const tools = toolsQuery.data?.tools || []
|
|
117
|
+
|
|
118
|
+
// Group tools by module
|
|
119
|
+
const toolsByModule = tools.reduce<Record<string, ToolInfo[]>>((acc, tool) => {
|
|
120
|
+
const module = tool.module || 'other'
|
|
121
|
+
if (!acc[module]) acc[module] = []
|
|
122
|
+
acc[module].push(tool)
|
|
123
|
+
return acc
|
|
124
|
+
}, {})
|
|
125
|
+
|
|
126
|
+
const provider = settings?.provider
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<div className="flex flex-col gap-6">
|
|
130
|
+
{/* Header */}
|
|
131
|
+
<div className="space-y-1">
|
|
132
|
+
<h1 className="text-2xl font-bold flex items-center gap-2">
|
|
133
|
+
<Bot className="h-6 w-6" />
|
|
134
|
+
AI Assistant Settings
|
|
135
|
+
</h1>
|
|
136
|
+
<p className="text-muted-foreground">
|
|
137
|
+
Configure and monitor the AI assistant
|
|
138
|
+
</p>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
{/* Test AI Assistant Section */}
|
|
142
|
+
<div className="rounded-lg border bg-card p-6">
|
|
143
|
+
<div className="flex items-start justify-between">
|
|
144
|
+
<div className="space-y-1">
|
|
145
|
+
<h2 className="text-lg font-semibold flex items-center gap-2">
|
|
146
|
+
<Bot className="h-5 w-5" />
|
|
147
|
+
Test AI Assistant
|
|
148
|
+
</h2>
|
|
149
|
+
<p className="text-sm text-muted-foreground">
|
|
150
|
+
Click the button to open the AI Assistant command palette.
|
|
151
|
+
</p>
|
|
152
|
+
</div>
|
|
153
|
+
<Button onClick={openAiAssistant} size="lg" className="gap-2">
|
|
154
|
+
<Bot className="h-4 w-4" />
|
|
155
|
+
Open AI Assistant
|
|
156
|
+
</Button>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
{/* Configuration Section */}
|
|
161
|
+
<div className="rounded-lg border bg-card p-6">
|
|
162
|
+
<h2 className="text-sm font-semibold mb-4 flex items-center gap-2">
|
|
163
|
+
<Server className="h-4 w-4" />
|
|
164
|
+
Configuration
|
|
165
|
+
</h2>
|
|
166
|
+
<div className="bg-muted/50 rounded-md p-4 space-y-2">
|
|
167
|
+
<div className="flex items-center gap-2 text-sm">
|
|
168
|
+
<span className="text-muted-foreground">Provider:</span>
|
|
169
|
+
<span className="font-medium">{provider?.name || 'Anthropic'}</span>
|
|
170
|
+
{provider?.configured ? (
|
|
171
|
+
<span className="flex items-center gap-1 text-emerald-600 dark:text-emerald-400 text-xs">
|
|
172
|
+
<CheckCircle2 className="h-3 w-3" />
|
|
173
|
+
Configured
|
|
174
|
+
</span>
|
|
175
|
+
) : (
|
|
176
|
+
<span className="flex items-center gap-1 text-amber-600 dark:text-amber-400 text-xs">
|
|
177
|
+
<XCircle className="h-3 w-3" />
|
|
178
|
+
Not configured
|
|
179
|
+
</span>
|
|
180
|
+
)}
|
|
181
|
+
</div>
|
|
182
|
+
<div className="flex items-center gap-2 text-sm">
|
|
183
|
+
<span className="text-muted-foreground">Model:</span>
|
|
184
|
+
<code className="font-mono text-xs bg-background px-1.5 py-0.5 rounded">{provider?.model || 'claude-haiku-4-5-20251001'}</code>
|
|
185
|
+
</div>
|
|
186
|
+
<div className="flex items-center gap-2 text-sm">
|
|
187
|
+
<span className="text-muted-foreground">Required:</span>
|
|
188
|
+
<span>Set <code className="font-mono text-xs bg-background px-1.5 py-0.5 rounded">{provider?.envKey || 'OPENCODE_ANTHROPIC_API_KEY'}</code> in .env</span>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
{/* Available Providers */}
|
|
193
|
+
{settings?.availableProviders && settings.availableProviders.length > 1 && (
|
|
194
|
+
<div className="mt-4">
|
|
195
|
+
<p className="text-xs text-muted-foreground mb-2">Available Providers:</p>
|
|
196
|
+
<div className="flex flex-wrap gap-2">
|
|
197
|
+
{settings.availableProviders.map((p) => (
|
|
198
|
+
<div
|
|
199
|
+
key={p.id}
|
|
200
|
+
className={`px-2 py-1 rounded text-xs ${
|
|
201
|
+
p.id === provider?.id
|
|
202
|
+
? 'bg-primary text-primary-foreground'
|
|
203
|
+
: p.configured
|
|
204
|
+
? 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400'
|
|
205
|
+
: 'bg-muted text-muted-foreground'
|
|
206
|
+
}`}
|
|
207
|
+
>
|
|
208
|
+
{p.name}
|
|
209
|
+
{p.id === provider?.id && ' (active)'}
|
|
210
|
+
{p.id !== provider?.id && p.configured && ' (ready)'}
|
|
211
|
+
</div>
|
|
212
|
+
))}
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
)}
|
|
216
|
+
|
|
217
|
+
<p className="text-xs text-muted-foreground mt-3">
|
|
218
|
+
Set <code className="font-mono text-[10px] bg-muted px-1 rounded">OPENCODE_PROVIDER</code> in .env to change provider (anthropic, openai, google).
|
|
219
|
+
</p>
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
{/* Requirements Section */}
|
|
223
|
+
<div className="rounded-lg border bg-card p-6">
|
|
224
|
+
<h2 className="text-sm font-semibold mb-4 flex items-center gap-2">
|
|
225
|
+
<AlertTriangle className="h-4 w-4" />
|
|
226
|
+
Requirements
|
|
227
|
+
</h2>
|
|
228
|
+
<div className="bg-muted/50 rounded-md p-4 space-y-3">
|
|
229
|
+
<div className="flex items-center gap-2 text-sm">
|
|
230
|
+
<span className="text-muted-foreground">Full-Text Search:</span>
|
|
231
|
+
{health?.search?.available ? (
|
|
232
|
+
<span className="flex items-center gap-1 text-emerald-600 dark:text-emerald-400">
|
|
233
|
+
<CheckCircle2 className="h-3 w-3" />
|
|
234
|
+
Meilisearch connected
|
|
235
|
+
</span>
|
|
236
|
+
) : (
|
|
237
|
+
<span className="flex items-center gap-1 text-amber-600 dark:text-amber-400">
|
|
238
|
+
<XCircle className="h-3 w-3" />
|
|
239
|
+
Not available
|
|
240
|
+
</span>
|
|
241
|
+
)}
|
|
242
|
+
</div>
|
|
243
|
+
<p className="text-xs text-muted-foreground">
|
|
244
|
+
A full-text search driver (Meilisearch) is required for API endpoint discovery.
|
|
245
|
+
Endpoints are indexed automatically when the MCP server starts.
|
|
246
|
+
</p>
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
|
|
250
|
+
{/* OpenCode Connection Section */}
|
|
251
|
+
<div className="rounded-lg border bg-card p-6">
|
|
252
|
+
<div className="flex items-center justify-between mb-4">
|
|
253
|
+
<h2 className="text-sm font-semibold flex items-center gap-2">
|
|
254
|
+
<Server className="h-4 w-4" />
|
|
255
|
+
OpenCode Connection
|
|
256
|
+
</h2>
|
|
257
|
+
{healthQuery.isFetching && !healthQuery.isLoading && (
|
|
258
|
+
<Loader2 className="h-3 w-3 animate-spin text-muted-foreground" />
|
|
259
|
+
)}
|
|
260
|
+
</div>
|
|
261
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
262
|
+
{/* OpenCode Server Status */}
|
|
263
|
+
<div className={`p-4 rounded-lg border-2 ${
|
|
264
|
+
health?.status === 'ok' && health.opencode?.healthy
|
|
265
|
+
? 'border-emerald-500/50 bg-emerald-50/50 dark:bg-emerald-900/10'
|
|
266
|
+
: 'border-destructive/50 bg-destructive/5'
|
|
267
|
+
}`}>
|
|
268
|
+
<div className="flex items-start justify-between">
|
|
269
|
+
<div>
|
|
270
|
+
<p className="text-sm font-medium">OpenCode Server</p>
|
|
271
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
272
|
+
{health?.status === 'ok' && health.opencode?.healthy ? (
|
|
273
|
+
<span className="flex items-center gap-1 text-emerald-600 dark:text-emerald-400">
|
|
274
|
+
<CheckCircle2 className="h-3 w-3" />
|
|
275
|
+
Connected
|
|
276
|
+
</span>
|
|
277
|
+
) : (
|
|
278
|
+
<span className="flex items-center gap-1 text-destructive">
|
|
279
|
+
<XCircle className="h-3 w-3" />
|
|
280
|
+
{health?.message || 'Disconnected'}
|
|
281
|
+
</span>
|
|
282
|
+
)}
|
|
283
|
+
</p>
|
|
284
|
+
{health?.opencode?.version && (
|
|
285
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
286
|
+
Version: {health.opencode.version}
|
|
287
|
+
</p>
|
|
288
|
+
)}
|
|
289
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
290
|
+
{health?.url || 'http://localhost:4096'}
|
|
291
|
+
</p>
|
|
292
|
+
</div>
|
|
293
|
+
{health?.status === 'ok' && health.opencode?.healthy && (
|
|
294
|
+
<div className="flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-emerald-600 dark:bg-emerald-900/40 dark:text-emerald-400">
|
|
295
|
+
<svg className="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}>
|
|
296
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
|
|
297
|
+
</svg>
|
|
298
|
+
</div>
|
|
299
|
+
)}
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
{/* MCP Server Status */}
|
|
304
|
+
{health?.mcp && Object.entries(health.mcp).map(([name, mcpStatus]) => (
|
|
305
|
+
<div
|
|
306
|
+
key={name}
|
|
307
|
+
className={`p-4 rounded-lg border-2 ${
|
|
308
|
+
mcpStatus.status === 'connected'
|
|
309
|
+
? 'border-emerald-500/50 bg-emerald-50/50 dark:bg-emerald-900/10'
|
|
310
|
+
: mcpStatus.status === 'connecting'
|
|
311
|
+
? 'border-amber-500/50 bg-amber-50/50 dark:bg-amber-900/10'
|
|
312
|
+
: 'border-destructive/50 bg-destructive/5'
|
|
313
|
+
}`}
|
|
314
|
+
>
|
|
315
|
+
<div className="flex items-start justify-between">
|
|
316
|
+
<div>
|
|
317
|
+
<p className="text-sm font-medium">MCP Server</p>
|
|
318
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
319
|
+
{mcpStatus.status === 'connected' ? (
|
|
320
|
+
<span className="flex items-center gap-1 text-emerald-600 dark:text-emerald-400">
|
|
321
|
+
<CheckCircle2 className="h-3 w-3" />
|
|
322
|
+
Connected
|
|
323
|
+
</span>
|
|
324
|
+
) : mcpStatus.status === 'connecting' ? (
|
|
325
|
+
<span className="flex items-center gap-1 text-amber-600 dark:text-amber-400">
|
|
326
|
+
<Loader2 className="h-3 w-3 animate-spin" />
|
|
327
|
+
Connecting...
|
|
328
|
+
</span>
|
|
329
|
+
) : (
|
|
330
|
+
<span className="flex items-center gap-1 text-destructive">
|
|
331
|
+
<XCircle className="h-3 w-3" />
|
|
332
|
+
{mcpStatus.error || 'Failed'}
|
|
333
|
+
</span>
|
|
334
|
+
)}
|
|
335
|
+
</p>
|
|
336
|
+
<p className="text-xs text-muted-foreground mt-1">{name}</p>
|
|
337
|
+
<p className="text-xs text-muted-foreground mt-1">localhost:3001</p>
|
|
338
|
+
</div>
|
|
339
|
+
{mcpStatus.status === 'connected' && (
|
|
340
|
+
<div className="flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-emerald-600 dark:bg-emerald-900/40 dark:text-emerald-400">
|
|
341
|
+
<svg className="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}>
|
|
342
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
|
|
343
|
+
</svg>
|
|
344
|
+
</div>
|
|
345
|
+
)}
|
|
346
|
+
</div>
|
|
347
|
+
</div>
|
|
348
|
+
))}
|
|
349
|
+
|
|
350
|
+
{/* Show placeholder if no MCP info */}
|
|
351
|
+
{(!health?.mcp || Object.keys(health.mcp).length === 0) && (
|
|
352
|
+
<div className="p-4 rounded-lg border-2 border-border bg-muted/20">
|
|
353
|
+
<div>
|
|
354
|
+
<p className="text-sm font-medium">MCP Server</p>
|
|
355
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
356
|
+
<span className="flex items-center gap-1">
|
|
357
|
+
<XCircle className="h-3 w-3" />
|
|
358
|
+
Not connected
|
|
359
|
+
</span>
|
|
360
|
+
</p>
|
|
361
|
+
<p className="text-xs text-muted-foreground mt-1">localhost:3001</p>
|
|
362
|
+
</div>
|
|
363
|
+
</div>
|
|
364
|
+
)}
|
|
365
|
+
</div>
|
|
366
|
+
</div>
|
|
367
|
+
|
|
368
|
+
{/* MCP Tools Section */}
|
|
369
|
+
<div className="rounded-lg border bg-card p-6">
|
|
370
|
+
<button
|
|
371
|
+
onClick={() => setToolsExpanded(!toolsExpanded)}
|
|
372
|
+
className="w-full flex items-center justify-between text-left"
|
|
373
|
+
>
|
|
374
|
+
<h2 className="text-sm font-semibold flex items-center gap-2">
|
|
375
|
+
<Wrench className="h-4 w-4" />
|
|
376
|
+
MCP Tools ({tools.length} tools)
|
|
377
|
+
</h2>
|
|
378
|
+
{toolsExpanded ? (
|
|
379
|
+
<ChevronDown className="h-4 w-4 text-muted-foreground" />
|
|
380
|
+
) : (
|
|
381
|
+
<ChevronRight className="h-4 w-4 text-muted-foreground" />
|
|
382
|
+
)}
|
|
383
|
+
</button>
|
|
384
|
+
|
|
385
|
+
{toolsExpanded && (
|
|
386
|
+
<div className="mt-4 space-y-4">
|
|
387
|
+
{Object.entries(toolsByModule).map(([module, moduleTools]) => (
|
|
388
|
+
<div key={module} className="space-y-2">
|
|
389
|
+
<h3 className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
|
390
|
+
{module}
|
|
391
|
+
</h3>
|
|
392
|
+
<div className="space-y-1">
|
|
393
|
+
{moduleTools.map((tool) => (
|
|
394
|
+
<div key={tool.name} className="pl-2 border-l-2 border-muted py-1">
|
|
395
|
+
<p className="text-sm font-medium">{tool.name}</p>
|
|
396
|
+
<p className="text-xs text-muted-foreground">{tool.description}</p>
|
|
397
|
+
</div>
|
|
398
|
+
))}
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
401
|
+
))}
|
|
402
|
+
</div>
|
|
403
|
+
)}
|
|
404
|
+
</div>
|
|
405
|
+
</div>
|
|
406
|
+
)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export function AiAssistantSettingsPageClient() {
|
|
410
|
+
return (
|
|
411
|
+
<CommandPaletteProvider tenantId="" organizationId={null}>
|
|
412
|
+
<AiAssistantSettingsContent />
|
|
413
|
+
<CommandPalette />
|
|
414
|
+
</CommandPaletteProvider>
|
|
415
|
+
)
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export default AiAssistantSettingsPageClient
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ModuleInfo } from '@open-mercato/shared/modules/registry'
|
|
2
|
+
|
|
3
|
+
export const metadata: ModuleInfo = {
|
|
4
|
+
name: 'ai_assistant',
|
|
5
|
+
title: 'AI Assistant',
|
|
6
|
+
version: '0.1.0',
|
|
7
|
+
description: 'MCP server for AI assistant integration with multi-tenant support.',
|
|
8
|
+
author: 'FreightTech Team',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { features } from './acl'
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Re-export AI SDK functions from the ai-assistant package
|
|
2
|
+
export { streamText, generateObject, stepCountIs } from 'ai'
|
|
3
|
+
export { createOpenAI } from '@ai-sdk/openai'
|
|
4
|
+
export { createAnthropic } from '@ai-sdk/anthropic'
|
|
5
|
+
export { createGoogleGenerativeAI } from '@ai-sdk/google'
|