@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.
Files changed (193) hide show
  1. package/AGENTS.md +1090 -0
  2. package/README.md +607 -0
  3. package/build.mjs +92 -0
  4. package/dist/di.js +8 -0
  5. package/dist/di.js.map +7 -0
  6. package/dist/frontend/components/CommandPalette/CommandFooter.js +80 -0
  7. package/dist/frontend/components/CommandPalette/CommandFooter.js.map +7 -0
  8. package/dist/frontend/components/CommandPalette/CommandHeader.js +53 -0
  9. package/dist/frontend/components/CommandPalette/CommandHeader.js.map +7 -0
  10. package/dist/frontend/components/CommandPalette/CommandInput.js +29 -0
  11. package/dist/frontend/components/CommandPalette/CommandInput.js.map +7 -0
  12. package/dist/frontend/components/CommandPalette/CommandItem.js +92 -0
  13. package/dist/frontend/components/CommandPalette/CommandItem.js.map +7 -0
  14. package/dist/frontend/components/CommandPalette/CommandPalette.js +244 -0
  15. package/dist/frontend/components/CommandPalette/CommandPalette.js.map +7 -0
  16. package/dist/frontend/components/CommandPalette/CommandPaletteProvider.js +42 -0
  17. package/dist/frontend/components/CommandPalette/CommandPaletteProvider.js.map +7 -0
  18. package/dist/frontend/components/CommandPalette/CommandPaletteWrapper.js +18 -0
  19. package/dist/frontend/components/CommandPalette/CommandPaletteWrapper.js.map +7 -0
  20. package/dist/frontend/components/CommandPalette/DebugPanel.js +215 -0
  21. package/dist/frontend/components/CommandPalette/DebugPanel.js.map +7 -0
  22. package/dist/frontend/components/CommandPalette/MessageBubble.js +64 -0
  23. package/dist/frontend/components/CommandPalette/MessageBubble.js.map +7 -0
  24. package/dist/frontend/components/CommandPalette/ToolCallConfirmation.js +91 -0
  25. package/dist/frontend/components/CommandPalette/ToolCallConfirmation.js.map +7 -0
  26. package/dist/frontend/components/CommandPalette/ToolCallDisplay.js +47 -0
  27. package/dist/frontend/components/CommandPalette/ToolCallDisplay.js.map +7 -0
  28. package/dist/frontend/components/CommandPalette/ToolChatPage.js +74 -0
  29. package/dist/frontend/components/CommandPalette/ToolChatPage.js.map +7 -0
  30. package/dist/frontend/components/CommandPalette/index.js +28 -0
  31. package/dist/frontend/components/CommandPalette/index.js.map +7 -0
  32. package/dist/frontend/constants.js +41 -0
  33. package/dist/frontend/constants.js.map +7 -0
  34. package/dist/frontend/hooks/index.js +13 -0
  35. package/dist/frontend/hooks/index.js.map +7 -0
  36. package/dist/frontend/hooks/useCommandPalette.js +1094 -0
  37. package/dist/frontend/hooks/useCommandPalette.js.map +7 -0
  38. package/dist/frontend/hooks/useMcpTools.js +66 -0
  39. package/dist/frontend/hooks/useMcpTools.js.map +7 -0
  40. package/dist/frontend/hooks/usePageContext.js +48 -0
  41. package/dist/frontend/hooks/usePageContext.js.map +7 -0
  42. package/dist/frontend/hooks/useRecentActions.js +56 -0
  43. package/dist/frontend/hooks/useRecentActions.js.map +7 -0
  44. package/dist/frontend/hooks/useRecentTools.js +55 -0
  45. package/dist/frontend/hooks/useRecentTools.js.map +7 -0
  46. package/dist/frontend/index.js +35 -0
  47. package/dist/frontend/index.js.map +7 -0
  48. package/dist/frontend/types.js +1 -0
  49. package/dist/frontend/types.js.map +7 -0
  50. package/dist/frontend/utils/index.js +7 -0
  51. package/dist/frontend/utils/index.js.map +7 -0
  52. package/dist/frontend/utils/toolMatcher.js +95 -0
  53. package/dist/frontend/utils/toolMatcher.js.map +7 -0
  54. package/dist/index.js +57 -0
  55. package/dist/index.js.map +7 -0
  56. package/dist/modules/ai_assistant/acl.js +14 -0
  57. package/dist/modules/ai_assistant/acl.js.map +7 -0
  58. package/dist/modules/ai_assistant/api/chat/route.js +152 -0
  59. package/dist/modules/ai_assistant/api/chat/route.js.map +7 -0
  60. package/dist/modules/ai_assistant/api/health/route.js +27 -0
  61. package/dist/modules/ai_assistant/api/health/route.js.map +7 -0
  62. package/dist/modules/ai_assistant/api/route/route.js +123 -0
  63. package/dist/modules/ai_assistant/api/route/route.js.map +7 -0
  64. package/dist/modules/ai_assistant/api/settings/route.js +60 -0
  65. package/dist/modules/ai_assistant/api/settings/route.js.map +7 -0
  66. package/dist/modules/ai_assistant/api/tools/execute/route.js +58 -0
  67. package/dist/modules/ai_assistant/api/tools/execute/route.js.map +7 -0
  68. package/dist/modules/ai_assistant/api/tools/route.js +48 -0
  69. package/dist/modules/ai_assistant/api/tools/route.js.map +7 -0
  70. package/dist/modules/ai_assistant/backend/config/ai-assistant/page.js +10 -0
  71. package/dist/modules/ai_assistant/backend/config/ai-assistant/page.js.map +7 -0
  72. package/dist/modules/ai_assistant/backend/config/ai-assistant/page.meta.js +28 -0
  73. package/dist/modules/ai_assistant/backend/config/ai-assistant/page.meta.js.map +7 -0
  74. package/dist/modules/ai_assistant/cli.js +192 -0
  75. package/dist/modules/ai_assistant/cli.js.map +7 -0
  76. package/dist/modules/ai_assistant/di.js +11 -0
  77. package/dist/modules/ai_assistant/di.js.map +7 -0
  78. package/dist/modules/ai_assistant/frontend/components/AiAssistantSettingsPageClient.js +257 -0
  79. package/dist/modules/ai_assistant/frontend/components/AiAssistantSettingsPageClient.js.map +7 -0
  80. package/dist/modules/ai_assistant/index.js +13 -0
  81. package/dist/modules/ai_assistant/index.js.map +7 -0
  82. package/dist/modules/ai_assistant/lib/ai-sdk.js +13 -0
  83. package/dist/modules/ai_assistant/lib/ai-sdk.js.map +7 -0
  84. package/dist/modules/ai_assistant/lib/api-discovery-tools.js +249 -0
  85. package/dist/modules/ai_assistant/lib/api-discovery-tools.js.map +7 -0
  86. package/dist/modules/ai_assistant/lib/api-endpoint-index-config.js +177 -0
  87. package/dist/modules/ai_assistant/lib/api-endpoint-index-config.js.map +7 -0
  88. package/dist/modules/ai_assistant/lib/api-endpoint-index.js +210 -0
  89. package/dist/modules/ai_assistant/lib/api-endpoint-index.js.map +7 -0
  90. package/dist/modules/ai_assistant/lib/auth.js +87 -0
  91. package/dist/modules/ai_assistant/lib/auth.js.map +7 -0
  92. package/dist/modules/ai_assistant/lib/chat-config.js +117 -0
  93. package/dist/modules/ai_assistant/lib/chat-config.js.map +7 -0
  94. package/dist/modules/ai_assistant/lib/client-factory.js +60 -0
  95. package/dist/modules/ai_assistant/lib/client-factory.js.map +7 -0
  96. package/dist/modules/ai_assistant/lib/http-server.js +367 -0
  97. package/dist/modules/ai_assistant/lib/http-server.js.map +7 -0
  98. package/dist/modules/ai_assistant/lib/in-process-client.js +126 -0
  99. package/dist/modules/ai_assistant/lib/in-process-client.js.map +7 -0
  100. package/dist/modules/ai_assistant/lib/mcp-client.js +146 -0
  101. package/dist/modules/ai_assistant/lib/mcp-client.js.map +7 -0
  102. package/dist/modules/ai_assistant/lib/mcp-dev-server.js +283 -0
  103. package/dist/modules/ai_assistant/lib/mcp-dev-server.js.map +7 -0
  104. package/dist/modules/ai_assistant/lib/mcp-server-config.js +160 -0
  105. package/dist/modules/ai_assistant/lib/mcp-server-config.js.map +7 -0
  106. package/dist/modules/ai_assistant/lib/mcp-server.js +156 -0
  107. package/dist/modules/ai_assistant/lib/mcp-server.js.map +7 -0
  108. package/dist/modules/ai_assistant/lib/mcp-tool-adapter.js +44 -0
  109. package/dist/modules/ai_assistant/lib/mcp-tool-adapter.js.map +7 -0
  110. package/dist/modules/ai_assistant/lib/opencode-client.js +247 -0
  111. package/dist/modules/ai_assistant/lib/opencode-client.js.map +7 -0
  112. package/dist/modules/ai_assistant/lib/opencode-handlers.js +398 -0
  113. package/dist/modules/ai_assistant/lib/opencode-handlers.js.map +7 -0
  114. package/dist/modules/ai_assistant/lib/schema-utils.js +94 -0
  115. package/dist/modules/ai_assistant/lib/schema-utils.js.map +7 -0
  116. package/dist/modules/ai_assistant/lib/tool-executor.js +55 -0
  117. package/dist/modules/ai_assistant/lib/tool-executor.js.map +7 -0
  118. package/dist/modules/ai_assistant/lib/tool-index-config.js +125 -0
  119. package/dist/modules/ai_assistant/lib/tool-index-config.js.map +7 -0
  120. package/dist/modules/ai_assistant/lib/tool-loader.js +88 -0
  121. package/dist/modules/ai_assistant/lib/tool-loader.js.map +7 -0
  122. package/dist/modules/ai_assistant/lib/tool-registry.js +65 -0
  123. package/dist/modules/ai_assistant/lib/tool-registry.js.map +7 -0
  124. package/dist/modules/ai_assistant/lib/tool-search.js +192 -0
  125. package/dist/modules/ai_assistant/lib/tool-search.js.map +7 -0
  126. package/dist/modules/ai_assistant/lib/types.js +1 -0
  127. package/dist/modules/ai_assistant/lib/types.js.map +7 -0
  128. package/package.json +108 -0
  129. package/src/di.ts +11 -0
  130. package/src/frontend/components/CommandPalette/CommandFooter.tsx +113 -0
  131. package/src/frontend/components/CommandPalette/CommandHeader.tsx +76 -0
  132. package/src/frontend/components/CommandPalette/CommandInput.tsx +50 -0
  133. package/src/frontend/components/CommandPalette/CommandItem.tsx +111 -0
  134. package/src/frontend/components/CommandPalette/CommandPalette.tsx +276 -0
  135. package/src/frontend/components/CommandPalette/CommandPaletteProvider.tsx +60 -0
  136. package/src/frontend/components/CommandPalette/CommandPaletteWrapper.tsx +21 -0
  137. package/src/frontend/components/CommandPalette/DebugPanel.tsx +257 -0
  138. package/src/frontend/components/CommandPalette/MessageBubble.tsx +73 -0
  139. package/src/frontend/components/CommandPalette/ToolCallConfirmation.tsx +130 -0
  140. package/src/frontend/components/CommandPalette/ToolCallDisplay.tsx +57 -0
  141. package/src/frontend/components/CommandPalette/ToolChatPage.tsx +125 -0
  142. package/src/frontend/components/CommandPalette/index.ts +14 -0
  143. package/src/frontend/constants.ts +35 -0
  144. package/src/frontend/hooks/index.ts +5 -0
  145. package/src/frontend/hooks/useCommandPalette.ts +1389 -0
  146. package/src/frontend/hooks/useMcpTools.ts +73 -0
  147. package/src/frontend/hooks/usePageContext.ts +61 -0
  148. package/src/frontend/hooks/useRecentActions.ts +64 -0
  149. package/src/frontend/hooks/useRecentTools.ts +69 -0
  150. package/src/frontend/index.ts +39 -0
  151. package/src/frontend/types.ts +260 -0
  152. package/src/frontend/utils/index.ts +1 -0
  153. package/src/frontend/utils/toolMatcher.ts +127 -0
  154. package/src/index.ts +92 -0
  155. package/src/modules/ai_assistant/acl.ts +10 -0
  156. package/src/modules/ai_assistant/api/chat/route.ts +213 -0
  157. package/src/modules/ai_assistant/api/health/route.ts +30 -0
  158. package/src/modules/ai_assistant/api/route/route.ts +149 -0
  159. package/src/modules/ai_assistant/api/settings/route.ts +73 -0
  160. package/src/modules/ai_assistant/api/tools/execute/route.ts +71 -0
  161. package/src/modules/ai_assistant/api/tools/route.ts +57 -0
  162. package/src/modules/ai_assistant/backend/config/ai-assistant/page.meta.ts +26 -0
  163. package/src/modules/ai_assistant/backend/config/ai-assistant/page.tsx +12 -0
  164. package/src/modules/ai_assistant/cli.ts +233 -0
  165. package/src/modules/ai_assistant/di.ts +9 -0
  166. package/src/modules/ai_assistant/frontend/components/AiAssistantSettingsPageClient.tsx +418 -0
  167. package/src/modules/ai_assistant/index.ts +11 -0
  168. package/src/modules/ai_assistant/lib/ai-sdk.ts +5 -0
  169. package/src/modules/ai_assistant/lib/api-discovery-tools.ts +334 -0
  170. package/src/modules/ai_assistant/lib/api-endpoint-index-config.ts +243 -0
  171. package/src/modules/ai_assistant/lib/api-endpoint-index.ts +381 -0
  172. package/src/modules/ai_assistant/lib/auth.ts +185 -0
  173. package/src/modules/ai_assistant/lib/chat-config.ts +152 -0
  174. package/src/modules/ai_assistant/lib/client-factory.ts +130 -0
  175. package/src/modules/ai_assistant/lib/http-server.ts +498 -0
  176. package/src/modules/ai_assistant/lib/in-process-client.ts +205 -0
  177. package/src/modules/ai_assistant/lib/mcp-client.ts +221 -0
  178. package/src/modules/ai_assistant/lib/mcp-dev-server.ts +373 -0
  179. package/src/modules/ai_assistant/lib/mcp-server-config.ts +287 -0
  180. package/src/modules/ai_assistant/lib/mcp-server.ts +214 -0
  181. package/src/modules/ai_assistant/lib/mcp-tool-adapter.ts +76 -0
  182. package/src/modules/ai_assistant/lib/opencode-client.ts +426 -0
  183. package/src/modules/ai_assistant/lib/opencode-handlers.ts +676 -0
  184. package/src/modules/ai_assistant/lib/schema-utils.ts +142 -0
  185. package/src/modules/ai_assistant/lib/tool-executor.ts +71 -0
  186. package/src/modules/ai_assistant/lib/tool-index-config.ts +178 -0
  187. package/src/modules/ai_assistant/lib/tool-loader.ts +149 -0
  188. package/src/modules/ai_assistant/lib/tool-registry.ts +114 -0
  189. package/src/modules/ai_assistant/lib/tool-search.ts +308 -0
  190. package/src/modules/ai_assistant/lib/types.ts +147 -0
  191. package/test-schema.ts +37 -0
  192. package/tsconfig.json +10 -0
  193. package/watch.mjs +6 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/ai_assistant/frontend/components/AiAssistantSettingsPageClient.tsx"],
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useState } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { Bot, Loader2, CheckCircle2, XCircle, ChevronDown, ChevronRight, Server, Wrench, AlertTriangle } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n CommandPaletteProvider,\n CommandPalette,\n useCommandPaletteContext,\n} from '../../../../frontend'\n\n// OpenCode health response type\ntype OpenCodeHealthResponse = {\n status: 'ok' | 'error'\n opencode?: {\n healthy: boolean\n version: string\n }\n mcp?: Record<string, { status: string; error?: string }>\n search?: {\n available: boolean\n driver: string | null\n }\n url: string\n message?: string\n}\n\n// Provider config type from settings API\ntype ProviderConfig = {\n id: string\n name: string\n model: string\n defaultModel: string\n envKey: string\n configured: boolean\n}\n\ntype SettingsResponse = {\n provider: ProviderConfig\n availableProviders: ProviderConfig[]\n}\n\n// Tool info type\ntype ToolInfo = {\n name: string\n description: string\n module: string\n inputSchema: Record<string, unknown>\n}\n\n// API fetch functions\nasync function fetchHealth(): Promise<OpenCodeHealthResponse> {\n const res = await fetch('/api/ai_assistant/health')\n if (!res.ok) throw new Error('Failed to fetch health')\n return res.json()\n}\n\nasync function fetchSettings(): Promise<SettingsResponse> {\n const res = await fetch('/api/ai_assistant/settings')\n if (!res.ok) throw new Error('Failed to fetch settings')\n return res.json()\n}\n\nasync function fetchTools(): Promise<{ tools: ToolInfo[] }> {\n const res = await fetch('/api/ai_assistant/tools')\n if (!res.ok) throw new Error('Failed to fetch tools')\n return res.json()\n}\n\nfunction AiAssistantSettingsContent() {\n const [toolsExpanded, setToolsExpanded] = useState(false)\n const { setIsOpen } = useCommandPaletteContext()\n\n // Health query - polls every 10 seconds\n const healthQuery = useQuery({\n queryKey: ['ai-assistant', 'health'],\n queryFn: fetchHealth,\n refetchInterval: 10000,\n staleTime: 5000,\n })\n\n // Settings query - no polling needed (static config)\n const settingsQuery = useQuery({\n queryKey: ['ai-assistant', 'settings'],\n queryFn: fetchSettings,\n staleTime: 60000,\n })\n\n // Tools query - no polling needed\n const toolsQuery = useQuery({\n queryKey: ['ai-assistant', 'tools'],\n queryFn: fetchTools,\n staleTime: 60000,\n })\n\n // Open AI Assistant palette\n const openAiAssistant = () => {\n setIsOpen(true)\n }\n\n const isLoading = healthQuery.isLoading || settingsQuery.isLoading || toolsQuery.isLoading\n\n if (isLoading) {\n return (\n <div className=\"flex items-center gap-2 text-muted-foreground py-8\">\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n Loading settings...\n </div>\n )\n }\n\n const health = healthQuery.data\n const settings = settingsQuery.data\n const tools = toolsQuery.data?.tools || []\n\n // Group tools by module\n const toolsByModule = tools.reduce<Record<string, ToolInfo[]>>((acc, tool) => {\n const module = tool.module || 'other'\n if (!acc[module]) acc[module] = []\n acc[module].push(tool)\n return acc\n }, {})\n\n const provider = settings?.provider\n\n return (\n <div className=\"flex flex-col gap-6\">\n {/* Header */}\n <div className=\"space-y-1\">\n <h1 className=\"text-2xl font-bold flex items-center gap-2\">\n <Bot className=\"h-6 w-6\" />\n AI Assistant Settings\n </h1>\n <p className=\"text-muted-foreground\">\n Configure and monitor the AI assistant\n </p>\n </div>\n\n {/* Test AI Assistant Section */}\n <div className=\"rounded-lg border bg-card p-6\">\n <div className=\"flex items-start justify-between\">\n <div className=\"space-y-1\">\n <h2 className=\"text-lg font-semibold flex items-center gap-2\">\n <Bot className=\"h-5 w-5\" />\n Test AI Assistant\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n Click the button to open the AI Assistant command palette.\n </p>\n </div>\n <Button onClick={openAiAssistant} size=\"lg\" className=\"gap-2\">\n <Bot className=\"h-4 w-4\" />\n Open AI Assistant\n </Button>\n </div>\n </div>\n\n {/* Configuration Section */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-sm font-semibold mb-4 flex items-center gap-2\">\n <Server className=\"h-4 w-4\" />\n Configuration\n </h2>\n <div className=\"bg-muted/50 rounded-md p-4 space-y-2\">\n <div className=\"flex items-center gap-2 text-sm\">\n <span className=\"text-muted-foreground\">Provider:</span>\n <span className=\"font-medium\">{provider?.name || 'Anthropic'}</span>\n {provider?.configured ? (\n <span className=\"flex items-center gap-1 text-emerald-600 dark:text-emerald-400 text-xs\">\n <CheckCircle2 className=\"h-3 w-3\" />\n Configured\n </span>\n ) : (\n <span className=\"flex items-center gap-1 text-amber-600 dark:text-amber-400 text-xs\">\n <XCircle className=\"h-3 w-3\" />\n Not configured\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-2 text-sm\">\n <span className=\"text-muted-foreground\">Model:</span>\n <code className=\"font-mono text-xs bg-background px-1.5 py-0.5 rounded\">{provider?.model || 'claude-haiku-4-5-20251001'}</code>\n </div>\n <div className=\"flex items-center gap-2 text-sm\">\n <span className=\"text-muted-foreground\">Required:</span>\n <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>\n </div>\n </div>\n\n {/* Available Providers */}\n {settings?.availableProviders && settings.availableProviders.length > 1 && (\n <div className=\"mt-4\">\n <p className=\"text-xs text-muted-foreground mb-2\">Available Providers:</p>\n <div className=\"flex flex-wrap gap-2\">\n {settings.availableProviders.map((p) => (\n <div\n key={p.id}\n className={`px-2 py-1 rounded text-xs ${\n p.id === provider?.id\n ? 'bg-primary text-primary-foreground'\n : p.configured\n ? 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400'\n : 'bg-muted text-muted-foreground'\n }`}\n >\n {p.name}\n {p.id === provider?.id && ' (active)'}\n {p.id !== provider?.id && p.configured && ' (ready)'}\n </div>\n ))}\n </div>\n </div>\n )}\n\n <p className=\"text-xs text-muted-foreground mt-3\">\n Set <code className=\"font-mono text-[10px] bg-muted px-1 rounded\">OPENCODE_PROVIDER</code> in .env to change provider (anthropic, openai, google).\n </p>\n </div>\n\n {/* Requirements Section */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-sm font-semibold mb-4 flex items-center gap-2\">\n <AlertTriangle className=\"h-4 w-4\" />\n Requirements\n </h2>\n <div className=\"bg-muted/50 rounded-md p-4 space-y-3\">\n <div className=\"flex items-center gap-2 text-sm\">\n <span className=\"text-muted-foreground\">Full-Text Search:</span>\n {health?.search?.available ? (\n <span className=\"flex items-center gap-1 text-emerald-600 dark:text-emerald-400\">\n <CheckCircle2 className=\"h-3 w-3\" />\n Meilisearch connected\n </span>\n ) : (\n <span className=\"flex items-center gap-1 text-amber-600 dark:text-amber-400\">\n <XCircle className=\"h-3 w-3\" />\n Not available\n </span>\n )}\n </div>\n <p className=\"text-xs text-muted-foreground\">\n A full-text search driver (Meilisearch) is required for API endpoint discovery.\n Endpoints are indexed automatically when the MCP server starts.\n </p>\n </div>\n </div>\n\n {/* OpenCode Connection Section */}\n <div className=\"rounded-lg border bg-card p-6\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-sm font-semibold flex items-center gap-2\">\n <Server className=\"h-4 w-4\" />\n OpenCode Connection\n </h2>\n {healthQuery.isFetching && !healthQuery.isLoading && (\n <Loader2 className=\"h-3 w-3 animate-spin text-muted-foreground\" />\n )}\n </div>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n {/* OpenCode Server Status */}\n <div className={`p-4 rounded-lg border-2 ${\n health?.status === 'ok' && health.opencode?.healthy\n ? 'border-emerald-500/50 bg-emerald-50/50 dark:bg-emerald-900/10'\n : 'border-destructive/50 bg-destructive/5'\n }`}>\n <div className=\"flex items-start justify-between\">\n <div>\n <p className=\"text-sm font-medium\">OpenCode Server</p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {health?.status === 'ok' && health.opencode?.healthy ? (\n <span className=\"flex items-center gap-1 text-emerald-600 dark:text-emerald-400\">\n <CheckCircle2 className=\"h-3 w-3\" />\n Connected\n </span>\n ) : (\n <span className=\"flex items-center gap-1 text-destructive\">\n <XCircle className=\"h-3 w-3\" />\n {health?.message || 'Disconnected'}\n </span>\n )}\n </p>\n {health?.opencode?.version && (\n <p className=\"text-xs text-muted-foreground mt-1\">\n Version: {health.opencode.version}\n </p>\n )}\n <p className=\"text-xs text-muted-foreground mt-1\">\n {health?.url || 'http://localhost:4096'}\n </p>\n </div>\n {health?.status === 'ok' && health.opencode?.healthy && (\n <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\">\n <svg className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </div>\n )}\n </div>\n </div>\n\n {/* MCP Server Status */}\n {health?.mcp && Object.entries(health.mcp).map(([name, mcpStatus]) => (\n <div\n key={name}\n className={`p-4 rounded-lg border-2 ${\n mcpStatus.status === 'connected'\n ? 'border-emerald-500/50 bg-emerald-50/50 dark:bg-emerald-900/10'\n : mcpStatus.status === 'connecting'\n ? 'border-amber-500/50 bg-amber-50/50 dark:bg-amber-900/10'\n : 'border-destructive/50 bg-destructive/5'\n }`}\n >\n <div className=\"flex items-start justify-between\">\n <div>\n <p className=\"text-sm font-medium\">MCP Server</p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {mcpStatus.status === 'connected' ? (\n <span className=\"flex items-center gap-1 text-emerald-600 dark:text-emerald-400\">\n <CheckCircle2 className=\"h-3 w-3\" />\n Connected\n </span>\n ) : mcpStatus.status === 'connecting' ? (\n <span className=\"flex items-center gap-1 text-amber-600 dark:text-amber-400\">\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n Connecting...\n </span>\n ) : (\n <span className=\"flex items-center gap-1 text-destructive\">\n <XCircle className=\"h-3 w-3\" />\n {mcpStatus.error || 'Failed'}\n </span>\n )}\n </p>\n <p className=\"text-xs text-muted-foreground mt-1\">{name}</p>\n <p className=\"text-xs text-muted-foreground mt-1\">localhost:3001</p>\n </div>\n {mcpStatus.status === 'connected' && (\n <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\">\n <svg className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </div>\n )}\n </div>\n </div>\n ))}\n\n {/* Show placeholder if no MCP info */}\n {(!health?.mcp || Object.keys(health.mcp).length === 0) && (\n <div className=\"p-4 rounded-lg border-2 border-border bg-muted/20\">\n <div>\n <p className=\"text-sm font-medium\">MCP Server</p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n <span className=\"flex items-center gap-1\">\n <XCircle className=\"h-3 w-3\" />\n Not connected\n </span>\n </p>\n <p className=\"text-xs text-muted-foreground mt-1\">localhost:3001</p>\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* MCP Tools Section */}\n <div className=\"rounded-lg border bg-card p-6\">\n <button\n onClick={() => setToolsExpanded(!toolsExpanded)}\n className=\"w-full flex items-center justify-between text-left\"\n >\n <h2 className=\"text-sm font-semibold flex items-center gap-2\">\n <Wrench className=\"h-4 w-4\" />\n MCP Tools ({tools.length} tools)\n </h2>\n {toolsExpanded ? (\n <ChevronDown className=\"h-4 w-4 text-muted-foreground\" />\n ) : (\n <ChevronRight className=\"h-4 w-4 text-muted-foreground\" />\n )}\n </button>\n\n {toolsExpanded && (\n <div className=\"mt-4 space-y-4\">\n {Object.entries(toolsByModule).map(([module, moduleTools]) => (\n <div key={module} className=\"space-y-2\">\n <h3 className=\"text-xs font-medium text-muted-foreground uppercase tracking-wider\">\n {module}\n </h3>\n <div className=\"space-y-1\">\n {moduleTools.map((tool) => (\n <div key={tool.name} className=\"pl-2 border-l-2 border-muted py-1\">\n <p className=\"text-sm font-medium\">{tool.name}</p>\n <p className=\"text-xs text-muted-foreground\">{tool.description}</p>\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport function AiAssistantSettingsPageClient() {\n return (\n <CommandPaletteProvider tenantId=\"\" organizationId={null}>\n <AiAssistantSettingsContent />\n <CommandPalette />\n </CommandPaletteProvider>\n )\n}\n\nexport default AiAssistantSettingsPageClient\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,13 @@
1
+ const metadata = {
2
+ name: "ai_assistant",
3
+ title: "AI Assistant",
4
+ version: "0.1.0",
5
+ description: "MCP server for AI assistant integration with multi-tenant support.",
6
+ author: "FreightTech Team"
7
+ };
8
+ import { features } from "./acl.js";
9
+ export {
10
+ features,
11
+ metadata
12
+ };
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/ai_assistant/index.ts"],
4
+ "sourcesContent": ["import type { ModuleInfo } from '@open-mercato/shared/modules/registry'\n\nexport const metadata: ModuleInfo = {\n name: 'ai_assistant',\n title: 'AI Assistant',\n version: '0.1.0',\n description: 'MCP server for AI assistant integration with multi-tenant support.',\n author: 'FreightTech Team',\n}\n\nexport { features } from './acl'\n"],
5
+ "mappings": "AAEO,MAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,aAAa;AAAA,EACb,QAAQ;AACV;AAEA,SAAS,gBAAgB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,13 @@
1
+ import { streamText, generateObject, stepCountIs } from "ai";
2
+ import { createOpenAI } from "@ai-sdk/openai";
3
+ import { createAnthropic } from "@ai-sdk/anthropic";
4
+ import { createGoogleGenerativeAI } from "@ai-sdk/google";
5
+ export {
6
+ createAnthropic,
7
+ createGoogleGenerativeAI,
8
+ createOpenAI,
9
+ generateObject,
10
+ stepCountIs,
11
+ streamText
12
+ };
13
+ //# sourceMappingURL=ai-sdk.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/ai_assistant/lib/ai-sdk.ts"],
4
+ "sourcesContent": ["// Re-export AI SDK functions from the ai-assistant package\nexport { streamText, generateObject, stepCountIs } from 'ai'\nexport { createOpenAI } from '@ai-sdk/openai'\nexport { createAnthropic } from '@ai-sdk/anthropic'\nexport { createGoogleGenerativeAI } from '@ai-sdk/google'\n"],
5
+ "mappings": "AACA,SAAS,YAAY,gBAAgB,mBAAmB;AACxD,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB;AAChC,SAAS,gCAAgC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,249 @@
1
+ import { z } from "zod";
2
+ import { registerMcpTool } from "./tool-registry.js";
3
+ import {
4
+ getApiEndpoints,
5
+ getEndpointByOperationId,
6
+ searchEndpoints
7
+ } from "./api-endpoint-index.js";
8
+ async function loadApiDiscoveryTools() {
9
+ const endpoints = await getApiEndpoints();
10
+ console.error(`[API Discovery] ${endpoints.length} endpoints available for discovery`);
11
+ registerApiDiscoverTool();
12
+ registerApiExecuteTool();
13
+ registerApiSchemaTool();
14
+ return 3;
15
+ }
16
+ function registerApiDiscoverTool() {
17
+ registerMcpTool(
18
+ {
19
+ name: "api_discover",
20
+ description: `Find API endpoints in Open Mercato by keyword or action.
21
+
22
+ CAPABILITIES: This tool searches 400+ endpoints that can CREATE, READ, UPDATE, and DELETE
23
+ data across all modules (customers, products, orders, shipments, invoices, etc.).
24
+
25
+ SEARCH: Uses hybrid search (fulltext + vector) for best results. You can filter by HTTP method.
26
+
27
+ EXAMPLES:
28
+ - "customer endpoints" - Find all customer-related APIs
29
+ - "create order" - Find endpoint to create new orders
30
+ - "delete product" - Find endpoint to delete products (confirm with user before executing!)
31
+ - "update company name" - Find endpoint to modify companies
32
+ - "search customers" - Find search/list endpoints
33
+
34
+ Returns: method, path, description, and operationId for each match.
35
+ Use operationId with api_schema to get detailed parameter info before calling api_execute.`,
36
+ inputSchema: z.object({
37
+ query: z.string().describe('Natural language query to find relevant endpoints (e.g., "customer list")'),
38
+ method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).optional().describe("Filter by HTTP method"),
39
+ limit: z.number().optional().default(10).describe("Max results to return (default: 10)")
40
+ }),
41
+ requiredFeatures: [],
42
+ // Available to all authenticated users
43
+ handler: async (input, ctx) => {
44
+ const { query, method, limit = 10 } = input;
45
+ const searchService = ctx.container?.resolve("searchService");
46
+ const matches = await searchEndpoints(searchService, query, { limit, method });
47
+ if (matches.length === 0) {
48
+ return {
49
+ success: true,
50
+ message: "No matching endpoints found. Try different search terms.",
51
+ endpoints: []
52
+ };
53
+ }
54
+ const results = matches.map((endpoint) => ({
55
+ operationId: endpoint.operationId,
56
+ method: endpoint.method,
57
+ path: endpoint.path,
58
+ description: endpoint.description || endpoint.summary,
59
+ tags: endpoint.tags,
60
+ parameters: endpoint.parameters.map((p) => ({
61
+ name: p.name,
62
+ in: p.in,
63
+ required: p.required,
64
+ type: p.type
65
+ })),
66
+ hasRequestBody: endpoint.requestBodySchema !== null
67
+ }));
68
+ return {
69
+ success: true,
70
+ message: `Found ${results.length} matching endpoint(s)`,
71
+ endpoints: results,
72
+ hint: "Use api_schema to get detailed parameter info, or api_execute to call an endpoint"
73
+ };
74
+ }
75
+ },
76
+ { moduleId: "api" }
77
+ );
78
+ }
79
+ function registerApiExecuteTool() {
80
+ registerMcpTool(
81
+ {
82
+ name: "api_execute",
83
+ description: `Execute an API call to CREATE, READ, UPDATE, or DELETE data in Open Mercato.
84
+
85
+ WARNING: This tool can MODIFY and DELETE data. Be careful with mutations!
86
+
87
+ METHODS:
88
+ - GET: Read/search data (safe, no confirmation needed)
89
+ - POST: Create new records (confirm data with user first)
90
+ - PUT/PATCH: Update existing records (confirm changes with user)
91
+ - DELETE: Remove records permanently (ALWAYS confirm with user before executing!)
92
+
93
+ WORKFLOW:
94
+ 1. First use api_discover to find the right endpoint
95
+ 2. Use api_schema to understand required parameters
96
+ 3. For POST/PUT/PATCH/DELETE: Confirm with user what will be changed
97
+ 4. Execute the call with proper parameters
98
+
99
+ PARAMETERS:
100
+ - method: HTTP method (GET, POST, PUT, PATCH, DELETE)
101
+ - path: API path with parameters replaced (e.g., /customers/companies/123)
102
+ - query: Query parameters as key-value object (for GET requests and filtering)
103
+ - body: Request body for POST/PUT/PATCH (object with required fields)`,
104
+ inputSchema: z.object({
105
+ method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method"),
106
+ path: z.string().describe("API path with parameters replaced (e.g., /customers/123, /orders)"),
107
+ query: z.record(z.string(), z.string()).optional().describe("Query parameters as key-value pairs"),
108
+ body: z.record(z.string(), z.unknown()).optional().describe("Request body for POST/PUT/PATCH requests")
109
+ }),
110
+ requiredFeatures: [],
111
+ // ACL checked at API level
112
+ handler: async (input, ctx) => {
113
+ const { method, path, query, body } = input;
114
+ const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || process.env.NEXT_PUBLIC_APP_URL || process.env.APP_URL || "http://localhost:3000";
115
+ const apiPath = path.startsWith("/api") ? path : `/api${path}`;
116
+ let url = `${baseUrl}${apiPath}`;
117
+ const queryParams = { ...query };
118
+ if (method === "GET") {
119
+ if (ctx.tenantId) queryParams.tenantId = ctx.tenantId;
120
+ if (ctx.organizationId) queryParams.organizationId = ctx.organizationId;
121
+ }
122
+ if (Object.keys(queryParams).length > 0) {
123
+ const separator = url.includes("?") ? "&" : "?";
124
+ url += separator + new URLSearchParams(queryParams).toString();
125
+ }
126
+ let requestBody;
127
+ if (["POST", "PUT", "PATCH"].includes(method)) {
128
+ requestBody = { ...body };
129
+ if (ctx.tenantId) requestBody.tenantId = ctx.tenantId;
130
+ if (ctx.organizationId) requestBody.organizationId = ctx.organizationId;
131
+ }
132
+ const headers = {
133
+ "Content-Type": "application/json"
134
+ };
135
+ if (ctx.apiKeySecret) headers["X-API-Key"] = ctx.apiKeySecret;
136
+ if (ctx.tenantId) headers["X-Tenant-Id"] = ctx.tenantId;
137
+ if (ctx.organizationId) headers["X-Organization-Id"] = ctx.organizationId;
138
+ try {
139
+ const response = await fetch(url, {
140
+ method,
141
+ headers,
142
+ body: requestBody ? JSON.stringify(requestBody) : void 0
143
+ });
144
+ const responseText = await response.text();
145
+ if (!response.ok) {
146
+ return {
147
+ success: false,
148
+ statusCode: response.status,
149
+ error: `API error ${response.status}`,
150
+ details: tryParseJson(responseText)
151
+ };
152
+ }
153
+ return {
154
+ success: true,
155
+ statusCode: response.status,
156
+ data: tryParseJson(responseText)
157
+ };
158
+ } catch (error) {
159
+ return {
160
+ success: false,
161
+ error: error instanceof Error ? error.message : "Request failed"
162
+ };
163
+ }
164
+ }
165
+ },
166
+ { moduleId: "api" }
167
+ );
168
+ }
169
+ function registerApiSchemaTool() {
170
+ registerMcpTool(
171
+ {
172
+ name: "api_schema",
173
+ description: `Get detailed schema for an API endpoint before executing it.
174
+
175
+ IMPORTANT: Always check the schema before calling POST, PUT, PATCH, or DELETE endpoints
176
+ to understand what parameters are required.
177
+
178
+ USAGE:
179
+ - Use the operationId from api_discover results
180
+ - Returns: path parameters, query parameters, and request body schema
181
+ - Shows which fields are required vs optional
182
+ - Includes field types and descriptions
183
+
184
+ This helps you construct the correct api_execute call with all required data.`,
185
+ inputSchema: z.object({
186
+ operationId: z.string().describe("Operation ID from api_discover results")
187
+ }),
188
+ requiredFeatures: [],
189
+ handler: async (input) => {
190
+ const endpoint = await getEndpointByOperationId(input.operationId);
191
+ if (!endpoint) {
192
+ return {
193
+ success: false,
194
+ error: `Endpoint not found: ${input.operationId}`,
195
+ hint: "Use api_discover to find available endpoints"
196
+ };
197
+ }
198
+ return {
199
+ success: true,
200
+ endpoint: {
201
+ operationId: endpoint.operationId,
202
+ method: endpoint.method,
203
+ path: endpoint.path,
204
+ description: endpoint.description,
205
+ tags: endpoint.tags,
206
+ deprecated: endpoint.deprecated,
207
+ requiredFeatures: endpoint.requiredFeatures,
208
+ parameters: endpoint.parameters,
209
+ requestBodySchema: endpoint.requestBodySchema
210
+ },
211
+ usage: buildUsageExample(endpoint)
212
+ };
213
+ }
214
+ },
215
+ { moduleId: "api" }
216
+ );
217
+ }
218
+ function buildUsageExample(endpoint) {
219
+ const pathParams = endpoint.parameters.filter((p) => p.in === "path");
220
+ const queryParams = endpoint.parameters.filter((p) => p.in === "query");
221
+ let example = `api_execute with:
222
+ method: "${endpoint.method}"
223
+ path: "${endpoint.path}"`;
224
+ if (pathParams.length > 0) {
225
+ example += `
226
+ (replace ${pathParams.map((p) => `{${p.name}}`).join(", ")} in path)`;
227
+ }
228
+ if (queryParams.length > 0) {
229
+ const queryExample = queryParams.slice(0, 3).map((p) => `"${p.name}": "..."`).join(", ");
230
+ example += `
231
+ query: { ${queryExample} }`;
232
+ }
233
+ if (endpoint.requestBodySchema) {
234
+ example += `
235
+ body: { ... } (see requestBodySchema above)`;
236
+ }
237
+ return example;
238
+ }
239
+ function tryParseJson(text) {
240
+ try {
241
+ return JSON.parse(text);
242
+ } catch {
243
+ return text;
244
+ }
245
+ }
246
+ export {
247
+ loadApiDiscoveryTools
248
+ };
249
+ //# sourceMappingURL=api-discovery-tools.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/ai_assistant/lib/api-discovery-tools.ts"],
4
+ "sourcesContent": ["/**\n * API Discovery Tools\n *\n * Meta-tools for discovering and executing API endpoints via search.\n * Replaces 400+ individual endpoint tools with 3 flexible tools.\n */\n\nimport { z } from 'zod'\nimport { registerMcpTool } from './tool-registry'\nimport type { McpToolContext } from './types'\nimport {\n getApiEndpoints,\n getEndpointByOperationId,\n searchEndpoints,\n type ApiEndpoint,\n} from './api-endpoint-index'\n\n/**\n * Load API discovery tools into the registry\n */\nexport async function loadApiDiscoveryTools(): Promise<number> {\n // Ensure endpoints are parsed and cached\n const endpoints = await getApiEndpoints()\n console.error(`[API Discovery] ${endpoints.length} endpoints available for discovery`)\n\n // Register the three discovery tools\n registerApiDiscoverTool()\n registerApiExecuteTool()\n registerApiSchemaTool()\n\n return 3\n}\n\n/**\n * api_discover - Find relevant API endpoints based on a query\n */\nfunction registerApiDiscoverTool(): void {\n registerMcpTool(\n {\n name: 'api_discover',\n description: `Find API endpoints in Open Mercato by keyword or action.\n\nCAPABILITIES: This tool searches 400+ endpoints that can CREATE, READ, UPDATE, and DELETE\ndata across all modules (customers, products, orders, shipments, invoices, etc.).\n\nSEARCH: Uses hybrid search (fulltext + vector) for best results. You can filter by HTTP method.\n\nEXAMPLES:\n- \"customer endpoints\" - Find all customer-related APIs\n- \"create order\" - Find endpoint to create new orders\n- \"delete product\" - Find endpoint to delete products (confirm with user before executing!)\n- \"update company name\" - Find endpoint to modify companies\n- \"search customers\" - Find search/list endpoints\n\nReturns: method, path, description, and operationId for each match.\nUse operationId with api_schema to get detailed parameter info before calling api_execute.`,\n inputSchema: z.object({\n query: z\n .string()\n .describe('Natural language query to find relevant endpoints (e.g., \"customer list\")'),\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE'])\n .optional()\n .describe('Filter by HTTP method'),\n limit: z.number().optional().default(10).describe('Max results to return (default: 10)'),\n }),\n requiredFeatures: [], // Available to all authenticated users\n handler: async (input: { query: string; method?: string; limit?: number }, ctx) => {\n const { query, method, limit = 10 } = input\n\n // Search for matching endpoints\n const searchService = ctx.container?.resolve<any>('searchService')\n const matches = await searchEndpoints(searchService, query, { limit, method })\n\n if (matches.length === 0) {\n return {\n success: true,\n message: 'No matching endpoints found. Try different search terms.',\n endpoints: [],\n }\n }\n\n // Format results for LLM consumption\n const results = matches.map((endpoint) => ({\n operationId: endpoint.operationId,\n method: endpoint.method,\n path: endpoint.path,\n description: endpoint.description || endpoint.summary,\n tags: endpoint.tags,\n parameters: endpoint.parameters.map((p) => ({\n name: p.name,\n in: p.in,\n required: p.required,\n type: p.type,\n })),\n hasRequestBody: endpoint.requestBodySchema !== null,\n }))\n\n return {\n success: true,\n message: `Found ${results.length} matching endpoint(s)`,\n endpoints: results,\n hint: 'Use api_schema to get detailed parameter info, or api_execute to call an endpoint',\n }\n },\n },\n { moduleId: 'api' }\n )\n}\n\n/**\n * api_execute - Execute an API endpoint\n */\nfunction registerApiExecuteTool(): void {\n registerMcpTool(\n {\n name: 'api_execute',\n description: `Execute an API call to CREATE, READ, UPDATE, or DELETE data in Open Mercato.\n\nWARNING: This tool can MODIFY and DELETE data. Be careful with mutations!\n\nMETHODS:\n- GET: Read/search data (safe, no confirmation needed)\n- POST: Create new records (confirm data with user first)\n- PUT/PATCH: Update existing records (confirm changes with user)\n- DELETE: Remove records permanently (ALWAYS confirm with user before executing!)\n\nWORKFLOW:\n1. First use api_discover to find the right endpoint\n2. Use api_schema to understand required parameters\n3. For POST/PUT/PATCH/DELETE: Confirm with user what will be changed\n4. Execute the call with proper parameters\n\nPARAMETERS:\n- method: HTTP method (GET, POST, PUT, PATCH, DELETE)\n- path: API path with parameters replaced (e.g., /customers/companies/123)\n- query: Query parameters as key-value object (for GET requests and filtering)\n- body: Request body for POST/PUT/PATCH (object with required fields)`,\n inputSchema: z.object({\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).describe('HTTP method'),\n path: z\n .string()\n .describe('API path with parameters replaced (e.g., /customers/123, /orders)'),\n query: z\n .record(z.string(), z.string())\n .optional()\n .describe('Query parameters as key-value pairs'),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe('Request body for POST/PUT/PATCH requests'),\n }),\n requiredFeatures: [], // ACL checked at API level\n handler: async (\n input: {\n method: string\n path: string\n query?: Record<string, string>\n body?: Record<string, unknown>\n },\n ctx: McpToolContext\n ) => {\n const { method, path, query, body } = input\n\n // Build URL\n const baseUrl =\n process.env.NEXT_PUBLIC_API_BASE_URL ||\n process.env.NEXT_PUBLIC_APP_URL ||\n process.env.APP_URL ||\n 'http://localhost:3000'\n\n // Ensure path starts with /api\n const apiPath = path.startsWith('/api') ? path : `/api${path}`\n let url = `${baseUrl}${apiPath}`\n\n // Add query parameters\n const queryParams = { ...query }\n\n // Add context to query for GET, to body for mutations\n if (method === 'GET') {\n if (ctx.tenantId) queryParams.tenantId = ctx.tenantId\n if (ctx.organizationId) queryParams.organizationId = ctx.organizationId\n }\n\n if (Object.keys(queryParams).length > 0) {\n const separator = url.includes('?') ? '&' : '?'\n url += separator + new URLSearchParams(queryParams).toString()\n }\n\n // Build body with context\n let requestBody: Record<string, unknown> | undefined\n if (['POST', 'PUT', 'PATCH'].includes(method)) {\n requestBody = { ...body }\n if (ctx.tenantId) requestBody.tenantId = ctx.tenantId\n if (ctx.organizationId) requestBody.organizationId = ctx.organizationId\n }\n\n // Build headers\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n if (ctx.apiKeySecret) headers['X-API-Key'] = ctx.apiKeySecret\n if (ctx.tenantId) headers['X-Tenant-Id'] = ctx.tenantId\n if (ctx.organizationId) headers['X-Organization-Id'] = ctx.organizationId\n\n // Execute request\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: requestBody ? JSON.stringify(requestBody) : undefined,\n })\n\n const responseText = await response.text()\n\n if (!response.ok) {\n return {\n success: false,\n statusCode: response.status,\n error: `API error ${response.status}`,\n details: tryParseJson(responseText),\n }\n }\n\n return {\n success: true,\n statusCode: response.status,\n data: tryParseJson(responseText),\n }\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Request failed',\n }\n }\n },\n },\n { moduleId: 'api' }\n )\n}\n\n/**\n * api_schema - Get detailed schema for an endpoint\n */\nfunction registerApiSchemaTool(): void {\n registerMcpTool(\n {\n name: 'api_schema',\n description: `Get detailed schema for an API endpoint before executing it.\n\nIMPORTANT: Always check the schema before calling POST, PUT, PATCH, or DELETE endpoints\nto understand what parameters are required.\n\nUSAGE:\n- Use the operationId from api_discover results\n- Returns: path parameters, query parameters, and request body schema\n- Shows which fields are required vs optional\n- Includes field types and descriptions\n\nThis helps you construct the correct api_execute call with all required data.`,\n inputSchema: z.object({\n operationId: z.string().describe('Operation ID from api_discover results'),\n }),\n requiredFeatures: [],\n handler: async (input: { operationId: string }) => {\n const endpoint = await getEndpointByOperationId(input.operationId)\n\n if (!endpoint) {\n return {\n success: false,\n error: `Endpoint not found: ${input.operationId}`,\n hint: 'Use api_discover to find available endpoints',\n }\n }\n\n return {\n success: true,\n endpoint: {\n operationId: endpoint.operationId,\n method: endpoint.method,\n path: endpoint.path,\n description: endpoint.description,\n tags: endpoint.tags,\n deprecated: endpoint.deprecated,\n requiredFeatures: endpoint.requiredFeatures,\n parameters: endpoint.parameters,\n requestBodySchema: endpoint.requestBodySchema,\n },\n usage: buildUsageExample(endpoint),\n }\n },\n },\n { moduleId: 'api' }\n )\n}\n\n/**\n * Build usage example for an endpoint\n */\nfunction buildUsageExample(endpoint: ApiEndpoint): string {\n const pathParams = endpoint.parameters.filter((p) => p.in === 'path')\n const queryParams = endpoint.parameters.filter((p) => p.in === 'query')\n\n let example = `api_execute with:\\n method: \"${endpoint.method}\"\\n path: \"${endpoint.path}\"`\n\n if (pathParams.length > 0) {\n example += `\\n (replace ${pathParams.map((p) => `{${p.name}}`).join(', ')} in path)`\n }\n\n if (queryParams.length > 0) {\n const queryExample = queryParams\n .slice(0, 3)\n .map((p) => `\"${p.name}\": \"...\"`)\n .join(', ')\n example += `\\n query: { ${queryExample} }`\n }\n\n if (endpoint.requestBodySchema) {\n example += `\\n body: { ... } (see requestBodySchema above)`\n }\n\n return example\n}\n\n/**\n * Try to parse JSON, return original string if fails\n */\nfunction tryParseJson(text: string): unknown {\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,177 @@
1
+ const API_ENDPOINT_ENTITY_ID = "ai_assistant:api_endpoint";
2
+ const GLOBAL_TENANT_ID = "00000000-0000-0000-0000-000000000000";
3
+ const API_ENDPOINT_SEARCH_CONFIG = {
4
+ /** Maximum endpoints to return from search */
5
+ defaultLimit: 20,
6
+ /** Minimum relevance score (0-1) */
7
+ minScore: 0.15,
8
+ /** Strategies to use (in priority order) */
9
+ strategies: ["fulltext", "vector"]
10
+ };
11
+ const apiEndpointEntityConfig = {
12
+ entityId: API_ENDPOINT_ENTITY_ID,
13
+ enabled: true,
14
+ priority: 90,
15
+ // High priority, just below tools
16
+ /**
17
+ * Build searchable content from an API endpoint.
18
+ */
19
+ buildSource: (ctx) => {
20
+ const endpoint = ctx.record;
21
+ const method = endpoint.method || "";
22
+ const path = endpoint.path || "";
23
+ const summary = endpoint.summary || "";
24
+ const description = endpoint.description || "";
25
+ const tags = endpoint.tags || [];
26
+ const operationId = endpoint.operationId || "";
27
+ const normalizedPath = path.replace(/[/{}\[\]]/g, " ").trim();
28
+ const actionWords = getActionWordsForMethod(method);
29
+ const textContent = [
30
+ `${method} ${normalizedPath}`,
31
+ operationId.replace(/[_.-]/g, " "),
32
+ summary,
33
+ description,
34
+ ...actionWords,
35
+ ...tags
36
+ ].filter(Boolean).join(" | ");
37
+ return {
38
+ text: textContent,
39
+ fields: {
40
+ method,
41
+ path,
42
+ operationId,
43
+ summary,
44
+ description,
45
+ tags,
46
+ module: extractModuleFromPath(path),
47
+ deprecated: endpoint.deprecated ?? false,
48
+ requiredFeatures: endpoint.requiredFeatures ?? []
49
+ },
50
+ presenter: {
51
+ title: `${method} ${path}`,
52
+ subtitle: summary || description.slice(0, 100),
53
+ icon: getIconForMethod(method)
54
+ },
55
+ checksumSource: { operationId, method, path, summary }
56
+ };
57
+ },
58
+ /**
59
+ * Format result for display in search UI.
60
+ */
61
+ formatResult: (ctx) => {
62
+ const endpoint = ctx.record;
63
+ return {
64
+ title: `${endpoint.method} ${endpoint.path}`,
65
+ subtitle: (endpoint.summary || endpoint.description || "").slice(0, 100),
66
+ icon: getIconForMethod(endpoint.method)
67
+ };
68
+ },
69
+ /**
70
+ * Field policy for search strategies.
71
+ */
72
+ fieldPolicy: {
73
+ searchable: ["method", "path", "operationId", "summary", "description", "tags", "module"],
74
+ hashOnly: [],
75
+ excluded: ["parameters", "requestBodySchema", "requiredFeatures"]
76
+ }
77
+ };
78
+ function endpointToIndexableRecord(endpoint) {
79
+ const method = endpoint.method;
80
+ const path = endpoint.path;
81
+ const normalizedPath = path.replace(/[/{}\[\]]/g, " ").trim();
82
+ const actionWords = getActionWordsForMethod(method);
83
+ const embeddingText = [
84
+ `${method} ${normalizedPath}`,
85
+ endpoint.operationId.replace(/[_.-]/g, " "),
86
+ endpoint.summary,
87
+ endpoint.description,
88
+ ...actionWords,
89
+ ...endpoint.tags
90
+ ].filter(Boolean).join(" | ");
91
+ const presenter = {
92
+ title: `${method} ${path}`,
93
+ subtitle: (endpoint.summary || endpoint.description || "").slice(0, 100),
94
+ icon: getIconForMethod(method)
95
+ };
96
+ return {
97
+ entityId: API_ENDPOINT_ENTITY_ID,
98
+ recordId: endpoint.operationId,
99
+ tenantId: GLOBAL_TENANT_ID,
100
+ organizationId: null,
101
+ fields: {
102
+ method,
103
+ path,
104
+ operationId: endpoint.operationId,
105
+ summary: endpoint.summary,
106
+ description: endpoint.description,
107
+ tags: endpoint.tags,
108
+ module: extractModuleFromPath(path),
109
+ deprecated: endpoint.deprecated,
110
+ requiredFeatures: endpoint.requiredFeatures
111
+ },
112
+ presenter,
113
+ text: embeddingText,
114
+ checksumSource: {
115
+ operationId: endpoint.operationId,
116
+ method,
117
+ path,
118
+ summary: endpoint.summary
119
+ }
120
+ };
121
+ }
122
+ function getActionWordsForMethod(method) {
123
+ switch (method.toUpperCase()) {
124
+ case "GET":
125
+ return ["read", "fetch", "get", "list", "retrieve", "find", "search", "query"];
126
+ case "POST":
127
+ return ["create", "add", "new", "insert", "submit", "register"];
128
+ case "PUT":
129
+ return ["update", "replace", "modify", "set", "change", "edit"];
130
+ case "PATCH":
131
+ return ["update", "modify", "partial", "change", "edit", "patch"];
132
+ case "DELETE":
133
+ return ["delete", "remove", "destroy", "cancel", "erase"];
134
+ default:
135
+ return [];
136
+ }
137
+ }
138
+ function getIconForMethod(method) {
139
+ switch (method.toUpperCase()) {
140
+ case "GET":
141
+ return "search";
142
+ case "POST":
143
+ return "plus";
144
+ case "PUT":
145
+ case "PATCH":
146
+ return "edit";
147
+ case "DELETE":
148
+ return "trash";
149
+ default:
150
+ return "api";
151
+ }
152
+ }
153
+ function extractModuleFromPath(path) {
154
+ const match = path.match(/^\/([\w-]+)/);
155
+ if (match) {
156
+ return match[1];
157
+ }
158
+ return null;
159
+ }
160
+ function computeEndpointsChecksum(endpoints) {
161
+ const content = endpoints.map((e) => `${e.operationId}:${e.method}:${e.path}`).sort().join("|");
162
+ let hash = 0;
163
+ for (let i = 0; i < content.length; i++) {
164
+ const char = content.charCodeAt(i);
165
+ hash = (hash << 5) - hash + char | 0;
166
+ }
167
+ return hash.toString(16);
168
+ }
169
+ export {
170
+ API_ENDPOINT_ENTITY_ID,
171
+ API_ENDPOINT_SEARCH_CONFIG,
172
+ GLOBAL_TENANT_ID,
173
+ apiEndpointEntityConfig,
174
+ computeEndpointsChecksum,
175
+ endpointToIndexableRecord
176
+ };
177
+ //# sourceMappingURL=api-endpoint-index-config.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/ai_assistant/lib/api-endpoint-index-config.ts"],
4
+ "sourcesContent": ["import type {\n SearchEntityConfig,\n SearchResultPresenter,\n IndexableRecord,\n} from '@open-mercato/search/types'\nimport type { ApiEndpoint } from './api-endpoint-index'\n\n/**\n * Entity ID for API endpoints in the search index.\n * Following the module:entity naming convention.\n */\nexport const API_ENDPOINT_ENTITY_ID = 'ai_assistant:api_endpoint' as const\n\n/**\n * Tenant ID for global endpoints.\n * API endpoints are not tenant-scoped, so we use a special \"system\" UUID.\n * This is the nil UUID (all zeros) reserved for system-wide resources.\n */\nexport const GLOBAL_TENANT_ID = '00000000-0000-0000-0000-000000000000'\n\n/**\n * Default configuration for API endpoint search.\n */\nexport const API_ENDPOINT_SEARCH_CONFIG = {\n /** Maximum endpoints to return from search */\n defaultLimit: 20,\n /** Minimum relevance score (0-1) */\n minScore: 0.15,\n /** Strategies to use (in priority order) */\n strategies: ['fulltext', 'vector'] as const,\n} as const\n\n/**\n * Search entity configuration for API endpoints.\n * This configures how endpoints are indexed and searched.\n */\nexport const apiEndpointEntityConfig: SearchEntityConfig = {\n entityId: API_ENDPOINT_ENTITY_ID,\n enabled: true,\n priority: 90, // High priority, just below tools\n\n /**\n * Build searchable content from an API endpoint.\n */\n buildSource: (ctx) => {\n const endpoint = ctx.record as unknown as ApiEndpoint\n const method = endpoint.method || ''\n const path = endpoint.path || ''\n const summary = endpoint.summary || ''\n const description = endpoint.description || ''\n const tags = endpoint.tags || []\n const operationId = endpoint.operationId || ''\n\n // Normalize path: replace slashes and braces with spaces for better search\n const normalizedPath = path.replace(/[/{}\\[\\]]/g, ' ').trim()\n\n // Build action words from method\n const actionWords = getActionWordsForMethod(method)\n\n // Build text content for embedding and fulltext search\n const textContent = [\n `${method} ${normalizedPath}`,\n operationId.replace(/[_.-]/g, ' '),\n summary,\n description,\n ...actionWords,\n ...tags,\n ]\n .filter(Boolean)\n .join(' | ')\n\n return {\n text: textContent,\n fields: {\n method,\n path,\n operationId,\n summary,\n description,\n tags,\n module: extractModuleFromPath(path),\n deprecated: endpoint.deprecated ?? false,\n requiredFeatures: endpoint.requiredFeatures ?? [],\n },\n presenter: {\n title: `${method} ${path}`,\n subtitle: summary || description.slice(0, 100),\n icon: getIconForMethod(method),\n },\n checksumSource: { operationId, method, path, summary },\n }\n },\n\n /**\n * Format result for display in search UI.\n */\n formatResult: (ctx) => {\n const endpoint = ctx.record as unknown as ApiEndpoint\n return {\n title: `${endpoint.method} ${endpoint.path}`,\n subtitle: (endpoint.summary || endpoint.description || '').slice(0, 100),\n icon: getIconForMethod(endpoint.method),\n }\n },\n\n /**\n * Field policy for search strategies.\n */\n fieldPolicy: {\n searchable: ['method', 'path', 'operationId', 'summary', 'description', 'tags', 'module'],\n hashOnly: [],\n excluded: ['parameters', 'requestBodySchema', 'requiredFeatures'],\n },\n}\n\n/**\n * Convert an API endpoint to an indexable record for search.\n *\n * @param endpoint - The API endpoint to index\n * @returns IndexableRecord ready for search indexing\n */\nexport function endpointToIndexableRecord(endpoint: ApiEndpoint): IndexableRecord {\n const method = endpoint.method\n const path = endpoint.path\n const normalizedPath = path.replace(/[/{}\\[\\]]/g, ' ').trim()\n const actionWords = getActionWordsForMethod(method)\n\n // Build text for vector embedding\n const embeddingText = [\n `${method} ${normalizedPath}`,\n endpoint.operationId.replace(/[_.-]/g, ' '),\n endpoint.summary,\n endpoint.description,\n ...actionWords,\n ...endpoint.tags,\n ]\n .filter(Boolean)\n .join(' | ')\n\n const presenter: SearchResultPresenter = {\n title: `${method} ${path}`,\n subtitle: (endpoint.summary || endpoint.description || '').slice(0, 100),\n icon: getIconForMethod(method),\n }\n\n return {\n entityId: API_ENDPOINT_ENTITY_ID,\n recordId: endpoint.operationId,\n tenantId: GLOBAL_TENANT_ID,\n organizationId: null,\n fields: {\n method,\n path,\n operationId: endpoint.operationId,\n summary: endpoint.summary,\n description: endpoint.description,\n tags: endpoint.tags,\n module: extractModuleFromPath(path),\n deprecated: endpoint.deprecated,\n requiredFeatures: endpoint.requiredFeatures,\n },\n presenter,\n text: embeddingText,\n checksumSource: {\n operationId: endpoint.operationId,\n method,\n path,\n summary: endpoint.summary,\n },\n }\n}\n\n/**\n * Get action words for HTTP method to improve semantic search.\n */\nfunction getActionWordsForMethod(method: string): string[] {\n switch (method.toUpperCase()) {\n case 'GET':\n return ['read', 'fetch', 'get', 'list', 'retrieve', 'find', 'search', 'query']\n case 'POST':\n return ['create', 'add', 'new', 'insert', 'submit', 'register']\n case 'PUT':\n return ['update', 'replace', 'modify', 'set', 'change', 'edit']\n case 'PATCH':\n return ['update', 'modify', 'partial', 'change', 'edit', 'patch']\n case 'DELETE':\n return ['delete', 'remove', 'destroy', 'cancel', 'erase']\n default:\n return []\n }\n}\n\n/**\n * Get icon for HTTP method.\n */\nfunction getIconForMethod(method: string): string {\n switch (method.toUpperCase()) {\n case 'GET':\n return 'search'\n case 'POST':\n return 'plus'\n case 'PUT':\n case 'PATCH':\n return 'edit'\n case 'DELETE':\n return 'trash'\n default:\n return 'api'\n }\n}\n\n/**\n * Extract module name from API path.\n */\nfunction extractModuleFromPath(path: string): string | null {\n // Common module patterns in paths\n const match = path.match(/^\\/([\\w-]+)/)\n if (match) {\n return match[1]\n }\n return null\n}\n\n/**\n * Compute a simple checksum for endpoint definitions.\n * Used to detect changes and avoid unnecessary re-indexing.\n */\nexport function computeEndpointsChecksum(\n endpoints: Array<{ operationId: string; method: string; path: string }>\n): string {\n const content = endpoints\n .map((e) => `${e.operationId}:${e.method}:${e.path}`)\n .sort()\n .join('|')\n\n // Simple hash using string code points\n let hash = 0\n for (let i = 0; i < content.length; i++) {\n const char = content.charCodeAt(i)\n hash = ((hash << 5) - hash + char) | 0\n }\n return hash.toString(16)\n}\n"],
5
+ "mappings": "AAWO,MAAM,yBAAyB;AAO/B,MAAM,mBAAmB;AAKzB,MAAM,6BAA6B;AAAA;AAAA,EAExC,cAAc;AAAA;AAAA,EAEd,UAAU;AAAA;AAAA,EAEV,YAAY,CAAC,YAAY,QAAQ;AACnC;AAMO,MAAM,0BAA8C;AAAA,EACzD,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAKV,aAAa,CAAC,QAAQ;AACpB,UAAM,WAAW,IAAI;AACrB,UAAM,SAAS,SAAS,UAAU;AAClC,UAAM,OAAO,SAAS,QAAQ;AAC9B,UAAM,UAAU,SAAS,WAAW;AACpC,UAAM,cAAc,SAAS,eAAe;AAC5C,UAAM,OAAO,SAAS,QAAQ,CAAC;AAC/B,UAAM,cAAc,SAAS,eAAe;AAG5C,UAAM,iBAAiB,KAAK,QAAQ,cAAc,GAAG,EAAE,KAAK;AAG5D,UAAM,cAAc,wBAAwB,MAAM;AAGlD,UAAM,cAAc;AAAA,MAClB,GAAG,MAAM,IAAI,cAAc;AAAA,MAC3B,YAAY,QAAQ,UAAU,GAAG;AAAA,MACjC;AAAA,MACA;AAAA,MACA,GAAG;AAAA,MACH,GAAG;AAAA,IACL,EACG,OAAO,OAAO,EACd,KAAK,KAAK;AAEb,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ,sBAAsB,IAAI;AAAA,QAClC,YAAY,SAAS,cAAc;AAAA,QACnC,kBAAkB,SAAS,oBAAoB,CAAC;AAAA,MAClD;AAAA,MACA,WAAW;AAAA,QACT,OAAO,GAAG,MAAM,IAAI,IAAI;AAAA,QACxB,UAAU,WAAW,YAAY,MAAM,GAAG,GAAG;AAAA,QAC7C,MAAM,iBAAiB,MAAM;AAAA,MAC/B;AAAA,MACA,gBAAgB,EAAE,aAAa,QAAQ,MAAM,QAAQ;AAAA,IACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,CAAC,QAAQ;AACrB,UAAM,WAAW,IAAI;AACrB,WAAO;AAAA,MACL,OAAO,GAAG,SAAS,MAAM,IAAI,SAAS,IAAI;AAAA,MAC1C,WAAW,SAAS,WAAW,SAAS,eAAe,IAAI,MAAM,GAAG,GAAG;AAAA,MACvE,MAAM,iBAAiB,SAAS,MAAM;AAAA,IACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa;AAAA,IACX,YAAY,CAAC,UAAU,QAAQ,eAAe,WAAW,eAAe,QAAQ,QAAQ;AAAA,IACxF,UAAU,CAAC;AAAA,IACX,UAAU,CAAC,cAAc,qBAAqB,kBAAkB;AAAA,EAClE;AACF;AAQO,SAAS,0BAA0B,UAAwC;AAChF,QAAM,SAAS,SAAS;AACxB,QAAM,OAAO,SAAS;AACtB,QAAM,iBAAiB,KAAK,QAAQ,cAAc,GAAG,EAAE,KAAK;AAC5D,QAAM,cAAc,wBAAwB,MAAM;AAGlD,QAAM,gBAAgB;AAAA,IACpB,GAAG,MAAM,IAAI,cAAc;AAAA,IAC3B,SAAS,YAAY,QAAQ,UAAU,GAAG;AAAA,IAC1C,SAAS;AAAA,IACT,SAAS;AAAA,IACT,GAAG;AAAA,IACH,GAAG,SAAS;AAAA,EACd,EACG,OAAO,OAAO,EACd,KAAK,KAAK;AAEb,QAAM,YAAmC;AAAA,IACvC,OAAO,GAAG,MAAM,IAAI,IAAI;AAAA,IACxB,WAAW,SAAS,WAAW,SAAS,eAAe,IAAI,MAAM,GAAG,GAAG;AAAA,IACvE,MAAM,iBAAiB,MAAM;AAAA,EAC/B;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,UAAU,SAAS;AAAA,IACnB,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA,aAAa,SAAS;AAAA,MACtB,SAAS,SAAS;AAAA,MAClB,aAAa,SAAS;AAAA,MACtB,MAAM,SAAS;AAAA,MACf,QAAQ,sBAAsB,IAAI;AAAA,MAClC,YAAY,SAAS;AAAA,MACrB,kBAAkB,SAAS;AAAA,IAC7B;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,gBAAgB;AAAA,MACd,aAAa,SAAS;AAAA,MACtB;AAAA,MACA;AAAA,MACA,SAAS,SAAS;AAAA,IACpB;AAAA,EACF;AACF;AAKA,SAAS,wBAAwB,QAA0B;AACzD,UAAQ,OAAO,YAAY,GAAG;AAAA,IAC5B,KAAK;AACH,aAAO,CAAC,QAAQ,SAAS,OAAO,QAAQ,YAAY,QAAQ,UAAU,OAAO;AAAA,IAC/E,KAAK;AACH,aAAO,CAAC,UAAU,OAAO,OAAO,UAAU,UAAU,UAAU;AAAA,IAChE,KAAK;AACH,aAAO,CAAC,UAAU,WAAW,UAAU,OAAO,UAAU,MAAM;AAAA,IAChE,KAAK;AACH,aAAO,CAAC,UAAU,UAAU,WAAW,UAAU,QAAQ,OAAO;AAAA,IAClE,KAAK;AACH,aAAO,CAAC,UAAU,UAAU,WAAW,UAAU,OAAO;AAAA,IAC1D;AACE,aAAO,CAAC;AAAA,EACZ;AACF;AAKA,SAAS,iBAAiB,QAAwB;AAChD,UAAQ,OAAO,YAAY,GAAG;AAAA,IAC5B,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAKA,SAAS,sBAAsB,MAA6B;AAE1D,QAAM,QAAQ,KAAK,MAAM,aAAa;AACtC,MAAI,OAAO;AACT,WAAO,MAAM,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAMO,SAAS,yBACd,WACQ;AACR,QAAM,UAAU,UACb,IAAI,CAAC,MAAM,GAAG,EAAE,WAAW,IAAI,EAAE,MAAM,IAAI,EAAE,IAAI,EAAE,EACnD,KAAK,EACL,KAAK,GAAG;AAGX,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,OAAO,QAAQ,WAAW,CAAC;AACjC,YAAS,QAAQ,KAAK,OAAO,OAAQ;AAAA,EACvC;AACA,SAAO,KAAK,SAAS,EAAE;AACzB;",
6
+ "names": []
7
+ }