@open-mercato/ai-assistant 0.6.3-develop.3894.1.352abf4240 → 0.6.3

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 (80) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/ai_assistant/__integration__/TC-AI-sharing-06-deep-link.spec.js +87 -0
  3. package/dist/modules/ai_assistant/__integration__/TC-AI-sharing-06-deep-link.spec.js.map +7 -0
  4. package/dist/modules/ai_assistant/__integration__/TC-AI-sharing-07-owner-label.spec.js +119 -0
  5. package/dist/modules/ai_assistant/__integration__/TC-AI-sharing-07-owner-label.spec.js.map +7 -0
  6. package/dist/modules/ai_assistant/acl.js +1 -0
  7. package/dist/modules/ai_assistant/acl.js.map +2 -2
  8. package/dist/modules/ai_assistant/api/ai/chat/route.js +3 -0
  9. package/dist/modules/ai_assistant/api/ai/chat/route.js.map +2 -2
  10. package/dist/modules/ai_assistant/api/ai/conversations/[conversationId]/participants/[userId]/route.js +128 -0
  11. package/dist/modules/ai_assistant/api/ai/conversations/[conversationId]/participants/[userId]/route.js.map +7 -0
  12. package/dist/modules/ai_assistant/api/ai/conversations/[conversationId]/participants/route.js +271 -0
  13. package/dist/modules/ai_assistant/api/ai/conversations/[conversationId]/participants/route.js.map +7 -0
  14. package/dist/modules/ai_assistant/api/ai/conversations/[conversationId]/route.js +9 -1
  15. package/dist/modules/ai_assistant/api/ai/conversations/[conversationId]/route.js.map +2 -2
  16. package/dist/modules/ai_assistant/api/ai/conversations/route.js +4 -1
  17. package/dist/modules/ai_assistant/api/ai/conversations/route.js.map +2 -2
  18. package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.js +5 -1
  19. package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.js.map +2 -2
  20. package/dist/modules/ai_assistant/components/ConversationShareButton.js +5 -0
  21. package/dist/modules/ai_assistant/components/ConversationShareButton.js.map +7 -0
  22. package/dist/modules/ai_assistant/components/ConversationShareDialog.js +5 -0
  23. package/dist/modules/ai_assistant/components/ConversationShareDialog.js.map +7 -0
  24. package/dist/modules/ai_assistant/data/entities.js +3 -0
  25. package/dist/modules/ai_assistant/data/entities.js.map +2 -2
  26. package/dist/modules/ai_assistant/data/repositories/AiChatConversationRepository.js +235 -5
  27. package/dist/modules/ai_assistant/data/repositories/AiChatConversationRepository.js.map +2 -2
  28. package/dist/modules/ai_assistant/events.js +14 -0
  29. package/dist/modules/ai_assistant/events.js.map +2 -2
  30. package/dist/modules/ai_assistant/i18n/de.json +17 -0
  31. package/dist/modules/ai_assistant/i18n/en.json +17 -0
  32. package/dist/modules/ai_assistant/i18n/es.json +17 -0
  33. package/dist/modules/ai_assistant/i18n/pl.json +17 -0
  34. package/dist/modules/ai_assistant/lib/conversation-storage.js +12 -3
  35. package/dist/modules/ai_assistant/lib/conversation-storage.js.map +2 -2
  36. package/dist/modules/ai_assistant/migrations/Migration20260522120000_ai_assistant.js +15 -0
  37. package/dist/modules/ai_assistant/migrations/Migration20260522120000_ai_assistant.js.map +7 -0
  38. package/dist/modules/ai_assistant/notifications.client.js +30 -0
  39. package/dist/modules/ai_assistant/notifications.client.js.map +7 -0
  40. package/dist/modules/ai_assistant/notifications.js +27 -0
  41. package/dist/modules/ai_assistant/notifications.js.map +7 -0
  42. package/dist/modules/ai_assistant/setup.js +2 -1
  43. package/dist/modules/ai_assistant/setup.js.map +2 -2
  44. package/dist/modules/ai_assistant/subscribers/conversation-shared-notify.js +59 -0
  45. package/dist/modules/ai_assistant/subscribers/conversation-shared-notify.js.map +7 -0
  46. package/dist/modules/ai_assistant/widgets/notifications/ConversationSharedRenderer.js +123 -0
  47. package/dist/modules/ai_assistant/widgets/notifications/ConversationSharedRenderer.js.map +7 -0
  48. package/generated/entities/ai_chat_conversation_participant/index.ts +1 -0
  49. package/generated/entity-fields-registry.ts +1 -0
  50. package/package.json +7 -8
  51. package/src/modules/ai_assistant/__integration__/TC-AI-sharing-06-deep-link.spec.ts +117 -0
  52. package/src/modules/ai_assistant/__integration__/TC-AI-sharing-07-owner-label.spec.ts +159 -0
  53. package/src/modules/ai_assistant/__tests__/integration/ai-chat-sharing.test.ts +406 -0
  54. package/src/modules/ai_assistant/acl.ts +1 -0
  55. package/src/modules/ai_assistant/api/ai/chat/route.ts +3 -0
  56. package/src/modules/ai_assistant/api/ai/conversations/[conversationId]/participants/[userId]/route.ts +149 -0
  57. package/src/modules/ai_assistant/api/ai/conversations/[conversationId]/participants/route.ts +314 -0
  58. package/src/modules/ai_assistant/api/ai/conversations/[conversationId]/route.ts +9 -1
  59. package/src/modules/ai_assistant/api/ai/conversations/route.ts +4 -1
  60. package/src/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.tsx +4 -0
  61. package/src/modules/ai_assistant/components/ConversationShareButton.tsx +1 -0
  62. package/src/modules/ai_assistant/components/ConversationShareDialog.tsx +1 -0
  63. package/src/modules/ai_assistant/data/entities.ts +4 -0
  64. package/src/modules/ai_assistant/data/repositories/AiChatConversationRepository.ts +270 -7
  65. package/src/modules/ai_assistant/data/repositories/__tests__/AiChatConversationRepository.test.ts +297 -3
  66. package/src/modules/ai_assistant/events.ts +31 -0
  67. package/src/modules/ai_assistant/i18n/__tests__/conversation-share-translations.test.ts +59 -0
  68. package/src/modules/ai_assistant/i18n/de.json +17 -0
  69. package/src/modules/ai_assistant/i18n/en.json +17 -0
  70. package/src/modules/ai_assistant/i18n/es.json +17 -0
  71. package/src/modules/ai_assistant/i18n/pl.json +17 -0
  72. package/src/modules/ai_assistant/lib/conversation-storage.ts +22 -1
  73. package/src/modules/ai_assistant/migrations/.snapshot-open-mercato.json +25 -0
  74. package/src/modules/ai_assistant/migrations/Migration20260522120000_ai_assistant.ts +15 -0
  75. package/src/modules/ai_assistant/notifications.client.ts +29 -0
  76. package/src/modules/ai_assistant/notifications.ts +25 -0
  77. package/src/modules/ai_assistant/setup.ts +2 -1
  78. package/src/modules/ai_assistant/subscribers/__tests__/conversation-shared-notify.test.ts +116 -0
  79. package/src/modules/ai_assistant/subscribers/conversation-shared-notify.ts +78 -0
  80. package/src/modules/ai_assistant/widgets/notifications/ConversationSharedRenderer.tsx +121 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { Bot, BookOpen, Loader2, Play, RefreshCcw } from 'lucide-react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Alert, AlertDescription, AlertTitle } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from '@open-mercato/ui/primitives/tabs'\nimport { Textarea } from '@open-mercato/ui/primitives/textarea'\nimport { EmptyState } from '@open-mercato/ui/backend/EmptyState'\nimport { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { AiChat, createAiUiPartRegistry, LoopDisabledBanner, useAiShortcuts } from '@open-mercato/ui/ai'\nimport type { AiChatDebugPromptSection, AiChatDebugTool } from '@open-mercato/ui/ai'\n\ntype PlaygroundAgentTool = {\n name: string\n displayName?: string\n isMutation?: boolean\n registered?: boolean\n requiredFeatures?: string[]\n}\n\ntype PlaygroundAgent = {\n id: string\n moduleId: string\n label: string\n description: string\n executionMode: 'chat' | 'object'\n mutationPolicy: string\n allowedTools: string[]\n requiredFeatures: string[]\n acceptedMediaTypes: string[]\n hasOutputSchema: boolean\n systemPrompt?: string\n readOnly?: boolean\n maxSteps?: number | null\n tools?: PlaygroundAgentTool[]\n}\n\ntype AgentsResponse = {\n agents: PlaygroundAgent[]\n total: number\n}\n\ntype RunObjectResponse = {\n object: unknown\n finishReason?: string\n usage?: { inputTokens?: number; outputTokens?: number }\n}\n\ntype RunObjectError = {\n error: string\n code?: string\n issues?: unknown\n}\n\nasync function fetchAgents(): Promise<AgentsResponse> {\n const { result, status } = await apiCallOrThrow<AgentsResponse>(\n '/api/ai_assistant/ai/agents',\n { method: 'GET', credentials: 'include' },\n { errorMessage: 'Failed to load agents' },\n )\n if (!result) throw new Error(`Failed to load agents (${status})`)\n return result\n}\n\nfunction PlaygroundLoading({ message }: { message: string }) {\n return (\n <div\n className=\"flex items-center gap-2 rounded-lg border border-border bg-background p-4 text-sm text-muted-foreground\"\n role=\"status\"\n >\n <Loader2 className=\"size-4 animate-spin\" aria-hidden />\n <span>{message}</span>\n </div>\n )\n}\n\nfunction PlaygroundNoAgents() {\n const t = useT()\n return (\n <EmptyState\n icon={<Bot className=\"size-6\" aria-hidden />}\n title={t(\n 'ai_assistant.playground.empty.title',\n 'No AI agents are registered for your role yet.',\n )}\n description={t(\n 'ai_assistant.playground.empty.description',\n 'Declare agents inside `packages/<module>/src/modules/<module>/ai-agents.ts`, run `yarn generate`, and ensure the caller holds the agent\\'s required features.',\n )}\n >\n <div className=\"mt-2 inline-flex items-center gap-2 text-xs text-muted-foreground\">\n <BookOpen className=\"size-3\" aria-hidden />\n <span>\n {t(\n 'ai_assistant.playground.empty.docLabel',\n 'See packages/ai-assistant/AGENTS.md for the agent definition reference.',\n )}\n </span>\n </div>\n </EmptyState>\n )\n}\n\nfunction AgentDetails({ agent }: { agent: PlaygroundAgent }) {\n const t = useT()\n return (\n <div className=\"rounded-md border border-border bg-muted/30 p-3 text-sm\">\n <div className=\"font-semibold\">{agent.label}</div>\n <p className=\"mt-1 text-xs text-muted-foreground\">{agent.description}</p>\n <dl className=\"mt-3 grid grid-cols-2 gap-2 text-xs\">\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.meta.module', 'Module')}\n </dt>\n <dd className=\"font-mono\">{agent.moduleId}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.meta.executionMode', 'Execution mode')}\n </dt>\n <dd className=\"font-mono\">{agent.executionMode}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.meta.mutationPolicy', 'Mutation policy')}\n </dt>\n <dd className=\"font-mono\">{agent.mutationPolicy}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.meta.tools', 'Allowed tools')}\n </dt>\n <dd className=\"font-mono\">{agent.allowedTools.length}</dd>\n </div>\n </dl>\n </div>\n )\n}\n\nfunction buildDebugTools(agent: PlaygroundAgent): AiChatDebugTool[] {\n if (agent.tools && agent.tools.length > 0) {\n return agent.tools.map((tool) => ({\n name: tool.name,\n displayName: tool.displayName ?? tool.name,\n isMutation: Boolean(tool.isMutation),\n requiredFeatures: tool.requiredFeatures ?? [],\n }))\n }\n return agent.allowedTools.map((toolName) => ({ name: toolName }))\n}\n\nfunction buildDebugPromptSections(agent: PlaygroundAgent): AiChatDebugPromptSection[] {\n const sections: AiChatDebugPromptSection[] = []\n if (agent.systemPrompt) {\n sections.push({ id: 'role', source: 'default', text: agent.systemPrompt })\n }\n const placeholderIds = [\n 'scope',\n 'data',\n 'tools',\n 'attachments',\n 'mutationPolicy',\n 'responseStyle',\n 'overrides',\n ] as const\n for (const id of placeholderIds) {\n sections.push({ id, source: 'placeholder' })\n }\n return sections\n}\n\ntype AgentModelResolution = {\n agentId: string\n providerId: string\n modelId: string\n baseURL: string | null\n source: string\n}\n\ntype SettingsAgentResolutionResponse = {\n agents: AgentModelResolution[]\n}\n\nasync function fetchAgentResolutions(): Promise<SettingsAgentResolutionResponse> {\n const result = await apiCall<SettingsAgentResolutionResponse>('/api/ai_assistant/settings')\n if (!result.ok || !result.result) return { agents: [] }\n return { agents: result.result.agents ?? [] }\n}\n\nasync function fetchLoopOverrideForAgent(\n agentId: string,\n): Promise<{ agentId: string; override: { loopDisabled?: boolean | null } | null }> {\n const result = await apiCall<{ agentId: string; override: { loopDisabled?: boolean | null } | null }>(\n `/api/ai_assistant/ai/agents/${encodeURIComponent(agentId)}/loop-override`,\n { method: 'GET', credentials: 'include' },\n )\n if (!result.ok || !result.result) return { agentId, override: null }\n return result.result\n}\n\nfunction LoopDisabledPlaygroundBanner({ agentId }: { agentId: string }) {\n const { data } = useQuery({\n queryKey: ['ai_assistant', 'loop_override', agentId],\n queryFn: () => fetchLoopOverrideForAgent(agentId),\n staleTime: 30000,\n })\n if (!data?.override?.loopDisabled) return null\n return <LoopDisabledBanner agentId={agentId} />\n}\n\nfunction ModelResolutionPanel({ agentId }: { agentId: string }) {\n const t = useT()\n const { data } = useQuery({\n queryKey: ['ai_assistant', 'settings', 'agents'],\n queryFn: fetchAgentResolutions,\n staleTime: 30000,\n })\n\n const resolution = data?.agents.find((agent) => agent.agentId === agentId)\n if (!resolution) return null\n\n return (\n <dl\n className=\"grid grid-cols-2 gap-x-4 gap-y-1 rounded-md border border-border bg-muted/30 p-3 text-xs sm:grid-cols-4\"\n data-ai-playground-model-resolution={agentId}\n >\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.resolution.provider', 'Provider')}\n </dt>\n <dd className=\"font-mono\" data-ai-playground-resolution-provider>\n {resolution.providerId}\n </dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.resolution.model', 'Model')}\n </dt>\n <dd className=\"font-mono\" data-ai-playground-resolution-model>\n {resolution.modelId}\n </dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.resolution.baseUrl', 'Base URL')}\n </dt>\n <dd className=\"font-mono\" data-ai-playground-resolution-base-url>\n {resolution.baseURL ?? t('ai_assistant.playground.resolution.none', '\u2014')}\n </dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.resolution.source', 'Source')}\n </dt>\n <dd className=\"font-mono\" data-ai-playground-resolution-source>\n {resolution.source}\n </dd>\n </div>\n </dl>\n )\n}\n\ntype PlaygroundUiPartSeed = {\n componentId: string\n pendingActionId?: string\n payload?: unknown\n}\n\nfunction readPlaygroundUiPartSeeds(): PlaygroundUiPartSeed[] {\n if (typeof window === 'undefined') return []\n try {\n const params = new URLSearchParams(window.location.search)\n const componentId = params.get('uiPart')\n if (!componentId) return []\n const pendingActionId = params.get('pendingActionId') ?? undefined\n return [{ componentId, pendingActionId }]\n } catch {\n return []\n }\n}\n\nfunction ChatLane({ agent, debug }: { agent: PlaygroundAgent; debug: boolean }) {\n const t = useT()\n // Scoped registry so repeated mounts do not share state with other pages.\n // Step 5.10: opt in to the LIVE mutation-approval cards so the playground\n // exercises the real cards when the chat response surfaces a pending\n // action (via the `?uiPart=...` debug seed for Playwright).\n const registry = React.useMemo(\n () => createAiUiPartRegistry({ seedLiveApprovalCards: true }),\n [],\n )\n const debugTools = React.useMemo(() => buildDebugTools(agent), [agent])\n const debugPromptSections = React.useMemo(\n () => buildDebugPromptSections(agent),\n [agent],\n )\n const [uiParts, setUiParts] = React.useState<PlaygroundUiPartSeed[]>([])\n\n // Step 5.10: the dispatcher does not yet surface `AiUiPart` entries through\n // the plain-text stream consumed by `useAiChat`. For now the playground\n // reads a `?uiPart=<componentId>&pendingActionId=...` seed from the URL\n // so Playwright + operator debug flows can render the approval cards\n // against a stubbed `/api/ai_assistant/ai/actions/:id` endpoint. When the\n // dispatcher switches to the UIMessageChunk format this effect swaps over\n // to the streamed `uiParts` payload.\n React.useEffect(() => {\n const seeds = readPlaygroundUiPartSeeds()\n if (seeds.length > 0) setUiParts(seeds)\n }, [])\n\n if (agent.executionMode !== 'chat') {\n return (\n <Alert variant=\"info\" data-ai-playground-unsupported=\"chat\">\n <AlertTitle>\n {t(\n 'ai_assistant.playground.chat.notSupportedTitle',\n 'Chat mode is not available for this agent.',\n )}\n </AlertTitle>\n <AlertDescription>\n {t(\n 'ai_assistant.playground.chat.notSupportedBody',\n 'Pick an agent whose execution mode is \"chat\", or switch to the object-mode tab.',\n )}\n </AlertDescription>\n </Alert>\n )\n }\n\n return (\n <div className=\"flex flex-col gap-2\" data-ai-playground-chat={agent.id}>\n <AiChat\n key={agent.id}\n agent={agent.id}\n pageContext={{ source: 'playground', pageId: 'ai_assistant.playground' }}\n debug={debug}\n registry={registry}\n className=\"min-h-96\"\n debugTools={debugTools}\n debugPromptSections={debugPromptSections}\n uiParts={uiParts}\n />\n </div>\n )\n}\n\nfunction ObjectLane({ agent }: { agent: PlaygroundAgent }) {\n const t = useT()\n const [prompt, setPrompt] = React.useState('')\n const [isRunning, setIsRunning] = React.useState(false)\n const [result, setResult] = React.useState<RunObjectResponse | null>(null)\n const [error, setError] = React.useState<RunObjectError | null>(null)\n const [lastRequest, setLastRequest] = React.useState<unknown>(null)\n\n const isSupported = agent.executionMode === 'object'\n const canRun = isSupported && prompt.trim().length > 0 && !isRunning\n\n const runObject = React.useCallback(async () => {\n if (!canRun) return\n const body = {\n agent: agent.id,\n messages: [{ role: 'user' as const, content: prompt }],\n pageContext: { source: 'playground', pageId: 'ai_assistant.playground' },\n }\n setLastRequest(body)\n setIsRunning(true)\n setResult(null)\n setError(null)\n try {\n const { ok, status, result } = await apiCall<RunObjectResponse | RunObjectError>(\n '/api/ai_assistant/ai/run-object',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(body),\n },\n )\n if (!ok) {\n const payload = (result as RunObjectError | null) ?? { error: `HTTP ${status}` }\n setError(payload)\n return\n }\n setResult((result as RunObjectResponse | null) ?? { object: null })\n } catch (err) {\n setError({\n error: err instanceof Error ? err.message : String(err),\n code: 'network_error',\n })\n } finally {\n setIsRunning(false)\n }\n }, [agent.id, canRun, prompt])\n\n const { handleKeyDown } = useAiShortcuts({\n onSubmit: () => {\n void runObject()\n },\n onCancel: () => {\n setError(null)\n },\n })\n\n if (!isSupported) {\n return (\n <Alert variant=\"info\" data-ai-playground-unsupported=\"object\">\n <AlertTitle>\n {t(\n 'ai_assistant.playground.object.notSupportedTitle',\n 'Object mode is not available for this agent.',\n )}\n </AlertTitle>\n <AlertDescription>\n {t(\n 'ai_assistant.playground.object.notSupportedBody',\n 'This agent declares executionMode = \"chat\". Pick an object-mode agent to preview structured output, or switch to the chat tab.',\n )}\n </AlertDescription>\n </Alert>\n )\n }\n\n return (\n <div className=\"flex flex-col gap-3\" data-ai-playground-object>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"ai-playground-object-input\">\n {t('ai_assistant.playground.object.inputLabel', 'Prompt')}\n </Label>\n <Textarea\n id=\"ai-playground-object-input\"\n rows={4}\n value={prompt}\n placeholder={t(\n 'ai_assistant.playground.object.inputPlaceholder',\n 'Describe what the agent should produce...',\n )}\n onChange={(event) => setPrompt(event.target.value)}\n onKeyDown={handleKeyDown}\n className=\"resize-none\"\n aria-label={t('ai_assistant.playground.object.inputLabel', 'Prompt')}\n />\n <div className=\"flex items-center justify-between\">\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'ai_assistant.playground.object.shortcutHint',\n 'Press Cmd/Ctrl+Enter to run.',\n )}\n </p>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void runObject()}\n disabled={!canRun}\n data-ai-playground-object-run\n >\n {isRunning ? (\n <Loader2 className=\"size-4 animate-spin\" aria-hidden />\n ) : (\n <Play className=\"size-4\" aria-hidden />\n )}\n <span>{t('ai_assistant.playground.object.run', 'Run object')}</span>\n </Button>\n </div>\n </div>\n\n {error ? (\n <Alert variant=\"destructive\" data-ai-playground-object-error={error.code ?? 'unknown'}>\n <AlertTitle>\n {t('ai_assistant.playground.object.errorTitle', 'Object run failed')}\n </AlertTitle>\n <AlertDescription>\n {error.code ? <span className=\"mr-2 font-mono text-xs\">{error.code}</span> : null}\n {error.error}\n </AlertDescription>\n </Alert>\n ) : null}\n\n {result ? (\n <section\n className=\"rounded-md border border-border bg-muted/30 p-3\"\n data-ai-playground-object-result\n >\n <h3 className=\"text-sm font-semibold\">\n {t('ai_assistant.playground.object.resultTitle', 'Generated object')}\n </h3>\n <pre className=\"mt-2 max-h-96 overflow-auto rounded bg-background p-2 text-xs font-mono\">\n {JSON.stringify(result.object, null, 2)}\n </pre>\n {result.usage || result.finishReason ? (\n <dl className=\"mt-3 grid grid-cols-3 gap-2 text-xs\">\n {result.finishReason ? (\n <div>\n <dt className=\"text-muted-foreground\">\n {t('ai_assistant.playground.object.finishReason', 'Finish reason')}\n </dt>\n <dd className=\"font-mono\">{result.finishReason}</dd>\n </div>\n ) : null}\n {result.usage?.inputTokens !== undefined ? (\n <div>\n <dt className=\"text-muted-foreground\">\n {t('ai_assistant.playground.object.inputTokens', 'Input tokens')}\n </dt>\n <dd className=\"font-mono\">{result.usage.inputTokens}</dd>\n </div>\n ) : null}\n {result.usage?.outputTokens !== undefined ? (\n <div>\n <dt className=\"text-muted-foreground\">\n {t('ai_assistant.playground.object.outputTokens', 'Output tokens')}\n </dt>\n <dd className=\"font-mono\">{result.usage.outputTokens}</dd>\n </div>\n ) : null}\n </dl>\n ) : null}\n </section>\n ) : null}\n\n {lastRequest && (error || result) ? (\n <details\n className=\"rounded-md border border-border bg-muted/20 p-2 text-xs\"\n data-ai-playground-object-debug\n >\n <summary className=\"cursor-pointer font-semibold\">\n {t('ai_assistant.playground.object.debugTitle', 'Last request payload')}\n </summary>\n <pre className=\"mt-2 max-h-64 overflow-auto whitespace-pre-wrap font-mono\">\n {JSON.stringify(lastRequest, null, 2)}\n </pre>\n </details>\n ) : null}\n </div>\n )\n}\n\nexport function AiPlaygroundPageClient() {\n const t = useT()\n const [selectedAgentId, setSelectedAgentId] = React.useState<string | null>(null)\n const [debugEnabled, setDebugEnabled] = React.useState(false)\n const [tab, setTab] = React.useState<'chat' | 'object'>('chat')\n\n const { data, isLoading, isError, error, refetch, isFetching } = useQuery<AgentsResponse>({\n queryKey: ['ai_assistant', 'playground', 'agents'],\n queryFn: fetchAgents,\n })\n\n const agents = React.useMemo<PlaygroundAgent[]>(() => data?.agents ?? [], [data])\n\n React.useEffect(() => {\n if (!agents.length) {\n if (selectedAgentId !== null) setSelectedAgentId(null)\n return\n }\n if (!selectedAgentId || !agents.some((agent) => agent.id === selectedAgentId)) {\n setSelectedAgentId(agents[0].id)\n }\n }, [agents, selectedAgentId])\n\n const selectedAgent = React.useMemo<PlaygroundAgent | null>(() => {\n if (!selectedAgentId) return null\n return agents.find((agent) => agent.id === selectedAgentId) ?? null\n }, [agents, selectedAgentId])\n\n if (isLoading) {\n return (\n <PlaygroundLoading\n message={t('ai_assistant.playground.loadingAgents', 'Loading AI agents...')}\n />\n )\n }\n\n if (isError) {\n return (\n <Alert variant=\"destructive\" data-ai-playground-error>\n <AlertTitle>\n {t('ai_assistant.playground.loadErrorTitle', 'Failed to load AI agents')}\n </AlertTitle>\n <AlertDescription>\n <span>{error instanceof Error ? error.message : String(error)}</span>\n <div className=\"mt-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n void refetch()\n }}\n >\n <RefreshCcw className=\"size-4\" aria-hidden />\n <span>{t('ai_assistant.playground.retry', 'Retry')}</span>\n </Button>\n </div>\n </AlertDescription>\n </Alert>\n )\n }\n\n if (!agents.length) {\n return <PlaygroundNoAgents />\n }\n\n return (\n <div className=\"flex flex-col gap-4\" data-ai-playground>\n <header className=\"flex flex-col gap-1\">\n <h1 className=\"text-2xl font-bold tracking-tight\">\n {t('ai_assistant.playground.title', 'AI Playground')}\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n {t(\n 'ai_assistant.playground.subtitle',\n 'Exercise every registered AI agent end-to-end. Use the debug panel to inspect request and response payloads, and the object-mode tab to preview structured output.',\n )}\n </p>\n </header>\n\n <section className=\"flex flex-col gap-3 rounded-lg border border-border bg-background p-3\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between\">\n <div className=\"flex flex-col gap-2 sm:flex-1\">\n <Label htmlFor=\"ai-playground-agent-picker\">\n {t('ai_assistant.playground.agentPickerLabel', 'Agent')}\n </Label>\n <select\n id=\"ai-playground-agent-picker\"\n data-ai-playground-agent-picker\n className=\"h-9 rounded-md border border-input bg-background px-3 text-sm\"\n value={selectedAgentId ?? ''}\n onChange={(event) => setSelectedAgentId(event.target.value)}\n >\n {agents.map((agent) => (\n <option key={agent.id} value={agent.id}>\n {agent.label} ({agent.id})\n </option>\n ))}\n </select>\n </div>\n <div className=\"flex items-center gap-3 sm:flex-shrink-0\">\n <Label htmlFor=\"ai-playground-debug\" className=\"text-sm\">\n {t('ai_assistant.playground.debugToggle', 'Debug panel')}\n </Label>\n <Switch\n id=\"ai-playground-debug\"\n checked={debugEnabled}\n onCheckedChange={(next: boolean) => setDebugEnabled(next)}\n aria-label={t('ai_assistant.playground.debugToggle', 'Debug panel')}\n data-ai-playground-debug-toggle\n />\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => {\n void refetch()\n }}\n aria-label={t('ai_assistant.playground.refresh', 'Refresh agents')}\n disabled={isFetching}\n >\n <RefreshCcw className=\"size-4\" aria-hidden />\n </IconButton>\n </div>\n </div>\n {selectedAgent ? <AgentDetails agent={selectedAgent} /> : null}\n {selectedAgent ? <ModelResolutionPanel agentId={selectedAgent.id} /> : null}\n {selectedAgent ? <LoopDisabledPlaygroundBanner agentId={selectedAgent.id} /> : null}\n </section>\n\n {selectedAgent ? (\n <Tabs\n value={tab}\n onValueChange={(next: string) => setTab(next === 'object' ? 'object' : 'chat')}\n >\n <TabsList>\n <TabsTrigger value=\"chat\">\n {t('ai_assistant.playground.tabs.chat', 'Chat')}\n </TabsTrigger>\n <TabsTrigger value=\"object\">\n {t('ai_assistant.playground.tabs.object', 'Object mode')}\n </TabsTrigger>\n </TabsList>\n <TabsContent value=\"chat\">\n <ChatLane agent={selectedAgent} debug={debugEnabled} />\n </TabsContent>\n <TabsContent value=\"object\">\n <ObjectLane agent={selectedAgent} />\n </TabsContent>\n </Tabs>\n ) : null}\n </div>\n )\n}\n\nexport default AiPlaygroundPageClient\n"],
5
- "mappings": ";AAwEI,SAIE,KAJF;AAtEJ,YAAY,WAAW;AACvB,SAAS,gBAAgB;AACzB,SAAS,KAAK,UAAU,SAAS,MAAM,kBAAkB;AACzD,SAAS,YAAY;AACrB,SAAS,OAAO,kBAAkB,kBAAkB;AACpD,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,aAAa;AACtB,SAAS,cAAc;AACvB,SAAS,MAAM,UAAU,aAAa,mBAAmB;AACzD,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,SAAS,sBAAsB;AACxC,SAAS,QAAQ,wBAAwB,oBAAoB,sBAAsB;AA6CnF,eAAe,cAAuC;AACpD,QAAM,EAAE,QAAQ,OAAO,IAAI,MAAM;AAAA,IAC/B;AAAA,IACA,EAAE,QAAQ,OAAO,aAAa,UAAU;AAAA,IACxC,EAAE,cAAc,wBAAwB;AAAA,EAC1C;AACA,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,0BAA0B,MAAM,GAAG;AAChE,SAAO;AACT;AAEA,SAAS,kBAAkB,EAAE,QAAQ,GAAwB;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,MAAK;AAAA,MAEL;AAAA,4BAAC,WAAQ,WAAU,uBAAsB,eAAW,MAAC;AAAA,QACrD,oBAAC,UAAM,mBAAQ;AAAA;AAAA;AAAA,EACjB;AAEJ;AAEA,SAAS,qBAAqB;AAC5B,QAAM,IAAI,KAAK;AACf,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,oBAAC,OAAI,WAAU,UAAS,eAAW,MAAC;AAAA,MAC1C,OAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,MACA,aAAa;AAAA,QACX;AAAA,QACA;AAAA,MACF;AAAA,MAEA,+BAAC,SAAI,WAAU,qEACb;AAAA,4BAAC,YAAS,WAAU,UAAS,eAAW,MAAC;AAAA,QACzC,oBAAC,UACE;AAAA,UACC;AAAA,UACA;AAAA,QACF,GACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,aAAa,EAAE,MAAM,GAA+B;AAC3D,QAAM,IAAI,KAAK;AACf,SACE,qBAAC,SAAI,WAAU,2DACb;AAAA,wBAAC,SAAI,WAAU,iBAAiB,gBAAM,OAAM;AAAA,IAC5C,oBAAC,OAAE,WAAU,sCAAsC,gBAAM,aAAY;AAAA,IACrE,qBAAC,QAAG,WAAU,uCACZ;AAAA,2BAAC,SACC;AAAA,4BAAC,QAAG,WAAU,qCACX,YAAE,uCAAuC,QAAQ,GACpD;AAAA,QACA,oBAAC,QAAG,WAAU,aAAa,gBAAM,UAAS;AAAA,SAC5C;AAAA,MACA,qBAAC,SACC;AAAA,4BAAC,QAAG,WAAU,qCACX,YAAE,8CAA8C,gBAAgB,GACnE;AAAA,QACA,oBAAC,QAAG,WAAU,aAAa,gBAAM,eAAc;AAAA,SACjD;AAAA,MACA,qBAAC,SACC;AAAA,4BAAC,QAAG,WAAU,qCACX,YAAE,+CAA+C,iBAAiB,GACrE;AAAA,QACA,oBAAC,QAAG,WAAU,aAAa,gBAAM,gBAAe;AAAA,SAClD;AAAA,MACA,qBAAC,SACC;AAAA,4BAAC,QAAG,WAAU,qCACX,YAAE,sCAAsC,eAAe,GAC1D;AAAA,QACA,oBAAC,QAAG,WAAU,aAAa,gBAAM,aAAa,QAAO;AAAA,SACvD;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,SAAS,gBAAgB,OAA2C;AAClE,MAAI,MAAM,SAAS,MAAM,MAAM,SAAS,GAAG;AACzC,WAAO,MAAM,MAAM,IAAI,CAAC,UAAU;AAAA,MAChC,MAAM,KAAK;AAAA,MACX,aAAa,KAAK,eAAe,KAAK;AAAA,MACtC,YAAY,QAAQ,KAAK,UAAU;AAAA,MACnC,kBAAkB,KAAK,oBAAoB,CAAC;AAAA,IAC9C,EAAE;AAAA,EACJ;AACA,SAAO,MAAM,aAAa,IAAI,CAAC,cAAc,EAAE,MAAM,SAAS,EAAE;AAClE;AAEA,SAAS,yBAAyB,OAAoD;AACpF,QAAM,WAAuC,CAAC;AAC9C,MAAI,MAAM,cAAc;AACtB,aAAS,KAAK,EAAE,IAAI,QAAQ,QAAQ,WAAW,MAAM,MAAM,aAAa,CAAC;AAAA,EAC3E;AACA,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,aAAW,MAAM,gBAAgB;AAC/B,aAAS,KAAK,EAAE,IAAI,QAAQ,cAAc,CAAC;AAAA,EAC7C;AACA,SAAO;AACT;AAcA,eAAe,wBAAkE;AAC/E,QAAM,SAAS,MAAM,QAAyC,4BAA4B;AAC1F,MAAI,CAAC,OAAO,MAAM,CAAC,OAAO,OAAQ,QAAO,EAAE,QAAQ,CAAC,EAAE;AACtD,SAAO,EAAE,QAAQ,OAAO,OAAO,UAAU,CAAC,EAAE;AAC9C;AAEA,eAAe,0BACb,SACkF;AAClF,QAAM,SAAS,MAAM;AAAA,IACnB,+BAA+B,mBAAmB,OAAO,CAAC;AAAA,IAC1D,EAAE,QAAQ,OAAO,aAAa,UAAU;AAAA,EAC1C;AACA,MAAI,CAAC,OAAO,MAAM,CAAC,OAAO,OAAQ,QAAO,EAAE,SAAS,UAAU,KAAK;AACnE,SAAO,OAAO;AAChB;AAEA,SAAS,6BAA6B,EAAE,QAAQ,GAAwB;AACtE,QAAM,EAAE,KAAK,IAAI,SAAS;AAAA,IACxB,UAAU,CAAC,gBAAgB,iBAAiB,OAAO;AAAA,IACnD,SAAS,MAAM,0BAA0B,OAAO;AAAA,IAChD,WAAW;AAAA,EACb,CAAC;AACD,MAAI,CAAC,MAAM,UAAU,aAAc,QAAO;AAC1C,SAAO,oBAAC,sBAAmB,SAAkB;AAC/C;AAEA,SAAS,qBAAqB,EAAE,QAAQ,GAAwB;AAC9D,QAAM,IAAI,KAAK;AACf,QAAM,EAAE,KAAK,IAAI,SAAS;AAAA,IACxB,UAAU,CAAC,gBAAgB,YAAY,QAAQ;AAAA,IAC/C,SAAS;AAAA,IACT,WAAW;AAAA,EACb,CAAC;AAED,QAAM,aAAa,MAAM,OAAO,KAAK,CAAC,UAAU,MAAM,YAAY,OAAO;AACzE,MAAI,CAAC,WAAY,QAAO;AAExB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,uCAAqC;AAAA,MAErC;AAAA,6BAAC,SACC;AAAA,8BAAC,QAAG,WAAU,qCACX,YAAE,+CAA+C,UAAU,GAC9D;AAAA,UACA,oBAAC,QAAG,WAAU,aAAY,0CAAsC,MAC7D,qBAAW,YACd;AAAA,WACF;AAAA,QACA,qBAAC,SACC;AAAA,8BAAC,QAAG,WAAU,qCACX,YAAE,4CAA4C,OAAO,GACxD;AAAA,UACA,oBAAC,QAAG,WAAU,aAAY,uCAAmC,MAC1D,qBAAW,SACd;AAAA,WACF;AAAA,QACA,qBAAC,SACC;AAAA,8BAAC,QAAG,WAAU,qCACX,YAAE,8CAA8C,UAAU,GAC7D;AAAA,UACA,oBAAC,QAAG,WAAU,aAAY,0CAAsC,MAC7D,qBAAW,WAAW,EAAE,2CAA2C,QAAG,GACzE;AAAA,WACF;AAAA,QACA,qBAAC,SACC;AAAA,8BAAC,QAAG,WAAU,qCACX,YAAE,6CAA6C,QAAQ,GAC1D;AAAA,UACA,oBAAC,QAAG,WAAU,aAAY,wCAAoC,MAC3D,qBAAW,QACd;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAQA,SAAS,4BAAoD;AAC3D,MAAI,OAAO,WAAW,YAAa,QAAO,CAAC;AAC3C,MAAI;AACF,UAAM,SAAS,IAAI,gBAAgB,OAAO,SAAS,MAAM;AACzD,UAAM,cAAc,OAAO,IAAI,QAAQ;AACvC,QAAI,CAAC,YAAa,QAAO,CAAC;AAC1B,UAAM,kBAAkB,OAAO,IAAI,iBAAiB,KAAK;AACzD,WAAO,CAAC,EAAE,aAAa,gBAAgB,CAAC;AAAA,EAC1C,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,SAAS,EAAE,OAAO,MAAM,GAA+C;AAC9E,QAAM,IAAI,KAAK;AAKf,QAAM,WAAW,MAAM;AAAA,IACrB,MAAM,uBAAuB,EAAE,uBAAuB,KAAK,CAAC;AAAA,IAC5D,CAAC;AAAA,EACH;AACA,QAAM,aAAa,MAAM,QAAQ,MAAM,gBAAgB,KAAK,GAAG,CAAC,KAAK,CAAC;AACtE,QAAM,sBAAsB,MAAM;AAAA,IAChC,MAAM,yBAAyB,KAAK;AAAA,IACpC,CAAC,KAAK;AAAA,EACR;AACA,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAiC,CAAC,CAAC;AASvE,QAAM,UAAU,MAAM;AACpB,UAAM,QAAQ,0BAA0B;AACxC,QAAI,MAAM,SAAS,EAAG,YAAW,KAAK;AAAA,EACxC,GAAG,CAAC,CAAC;AAEL,MAAI,MAAM,kBAAkB,QAAQ;AAClC,WACE,qBAAC,SAAM,SAAQ,QAAO,kCAA+B,QACnD;AAAA,0BAAC,cACE;AAAA,QACC;AAAA,QACA;AAAA,MACF,GACF;AAAA,MACA,oBAAC,oBACE;AAAA,QACC;AAAA,QACA;AAAA,MACF,GACF;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,oBAAC,SAAI,WAAU,uBAAsB,2BAAyB,MAAM,IAClE;AAAA,IAAC;AAAA;AAAA,MAEC,OAAO,MAAM;AAAA,MACb,aAAa,EAAE,QAAQ,cAAc,QAAQ,0BAA0B;AAAA,MACvE;AAAA,MACA;AAAA,MACA,WAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IARK,MAAM;AAAA,EASb,GACF;AAEJ;AAEA,SAAS,WAAW,EAAE,MAAM,GAA+B;AACzD,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAC7C,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,KAAK;AACtD,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAmC,IAAI;AACzE,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAgC,IAAI;AACpE,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAkB,IAAI;AAElE,QAAM,cAAc,MAAM,kBAAkB;AAC5C,QAAM,SAAS,eAAe,OAAO,KAAK,EAAE,SAAS,KAAK,CAAC;AAE3D,QAAM,YAAY,MAAM,YAAY,YAAY;AAC9C,QAAI,CAAC,OAAQ;AACb,UAAM,OAAO;AAAA,MACX,OAAO,MAAM;AAAA,MACb,UAAU,CAAC,EAAE,MAAM,QAAiB,SAAS,OAAO,CAAC;AAAA,MACrD,aAAa,EAAE,QAAQ,cAAc,QAAQ,0BAA0B;AAAA,IACzE;AACA,mBAAe,IAAI;AACnB,iBAAa,IAAI;AACjB,cAAU,IAAI;AACd,aAAS,IAAI;AACb,QAAI;AACF,YAAM,EAAE,IAAI,QAAQ,QAAAA,QAAO,IAAI,MAAM;AAAA,QACnC;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,aAAa;AAAA,UACb,MAAM,KAAK,UAAU,IAAI;AAAA,QAC3B;AAAA,MACF;AACA,UAAI,CAAC,IAAI;AACP,cAAM,UAAWA,WAAoC,EAAE,OAAO,QAAQ,MAAM,GAAG;AAC/E,iBAAS,OAAO;AAChB;AAAA,MACF;AACA,gBAAWA,WAAuC,EAAE,QAAQ,KAAK,CAAC;AAAA,IACpE,SAAS,KAAK;AACZ,eAAS;AAAA,QACP,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,QACtD,MAAM;AAAA,MACR,CAAC;AAAA,IACH,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAM,IAAI,QAAQ,MAAM,CAAC;AAE7B,QAAM,EAAE,cAAc,IAAI,eAAe;AAAA,IACvC,UAAU,MAAM;AACd,WAAK,UAAU;AAAA,IACjB;AAAA,IACA,UAAU,MAAM;AACd,eAAS,IAAI;AAAA,IACf;AAAA,EACF,CAAC;AAED,MAAI,CAAC,aAAa;AAChB,WACE,qBAAC,SAAM,SAAQ,QAAO,kCAA+B,UACnD;AAAA,0BAAC,cACE;AAAA,QACC;AAAA,QACA;AAAA,MACF,GACF;AAAA,MACA,oBAAC,oBACE;AAAA,QACC;AAAA,QACA;AAAA,MACF,GACF;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAU,uBAAsB,6BAAyB,MAC5D;AAAA,yBAAC,SAAI,WAAU,uBACb;AAAA,0BAAC,SAAM,SAAQ,8BACZ,YAAE,6CAA6C,QAAQ,GAC1D;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,IAAG;AAAA,UACH,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa;AAAA,YACX;AAAA,YACA;AAAA,UACF;AAAA,UACA,UAAU,CAAC,UAAU,UAAU,MAAM,OAAO,KAAK;AAAA,UACjD,WAAW;AAAA,UACX,WAAU;AAAA,UACV,cAAY,EAAE,6CAA6C,QAAQ;AAAA;AAAA,MACrE;AAAA,MACA,qBAAC,SAAI,WAAU,qCACb;AAAA,4BAAC,OAAE,WAAU,iCACV;AAAA,UACC;AAAA,UACA;AAAA,QACF,GACF;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,SAAS,MAAM,KAAK,UAAU;AAAA,YAC9B,UAAU,CAAC;AAAA,YACX,iCAA6B;AAAA,YAE5B;AAAA,0BACC,oBAAC,WAAQ,WAAU,uBAAsB,eAAW,MAAC,IAErD,oBAAC,QAAK,WAAU,UAAS,eAAW,MAAC;AAAA,cAEvC,oBAAC,UAAM,YAAE,sCAAsC,YAAY,GAAE;AAAA;AAAA;AAAA,QAC/D;AAAA,SACF;AAAA,OACF;AAAA,IAEC,QACC,qBAAC,SAAM,SAAQ,eAAc,mCAAiC,MAAM,QAAQ,WAC1E;AAAA,0BAAC,cACE,YAAE,6CAA6C,mBAAmB,GACrE;AAAA,MACA,qBAAC,oBACE;AAAA,cAAM,OAAO,oBAAC,UAAK,WAAU,0BAA0B,gBAAM,MAAK,IAAU;AAAA,QAC5E,MAAM;AAAA,SACT;AAAA,OACF,IACE;AAAA,IAEH,SACC;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,oCAAgC;AAAA,QAEhC;AAAA,8BAAC,QAAG,WAAU,yBACX,YAAE,8CAA8C,kBAAkB,GACrE;AAAA,UACA,oBAAC,SAAI,WAAU,2EACZ,eAAK,UAAU,OAAO,QAAQ,MAAM,CAAC,GACxC;AAAA,UACC,OAAO,SAAS,OAAO,eACtB,qBAAC,QAAG,WAAU,uCACX;AAAA,mBAAO,eACN,qBAAC,SACC;AAAA,kCAAC,QAAG,WAAU,yBACX,YAAE,+CAA+C,eAAe,GACnE;AAAA,cACA,oBAAC,QAAG,WAAU,aAAa,iBAAO,cAAa;AAAA,eACjD,IACE;AAAA,YACH,OAAO,OAAO,gBAAgB,SAC7B,qBAAC,SACC;AAAA,kCAAC,QAAG,WAAU,yBACX,YAAE,8CAA8C,cAAc,GACjE;AAAA,cACA,oBAAC,QAAG,WAAU,aAAa,iBAAO,MAAM,aAAY;AAAA,eACtD,IACE;AAAA,YACH,OAAO,OAAO,iBAAiB,SAC9B,qBAAC,SACC;AAAA,kCAAC,QAAG,WAAU,yBACX,YAAE,+CAA+C,eAAe,GACnE;AAAA,cACA,oBAAC,QAAG,WAAU,aAAa,iBAAO,MAAM,cAAa;AAAA,eACvD,IACE;AAAA,aACN,IACE;AAAA;AAAA;AAAA,IACN,IACE;AAAA,IAEH,gBAAgB,SAAS,UACxB;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,mCAA+B;AAAA,QAE/B;AAAA,8BAAC,aAAQ,WAAU,gCAChB,YAAE,6CAA6C,sBAAsB,GACxE;AAAA,UACA,oBAAC,SAAI,WAAU,6DACZ,eAAK,UAAU,aAAa,MAAM,CAAC,GACtC;AAAA;AAAA;AAAA,IACF,IACE;AAAA,KACN;AAEJ;AAEO,SAAS,yBAAyB;AACvC,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,MAAM,SAAwB,IAAI;AAChF,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAS,KAAK;AAC5D,QAAM,CAAC,KAAK,MAAM,IAAI,MAAM,SAA4B,MAAM;AAE9D,QAAM,EAAE,MAAM,WAAW,SAAS,OAAO,SAAS,WAAW,IAAI,SAAyB;AAAA,IACxF,UAAU,CAAC,gBAAgB,cAAc,QAAQ;AAAA,IACjD,SAAS;AAAA,EACX,CAAC;AAED,QAAM,SAAS,MAAM,QAA2B,MAAM,MAAM,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AAEhF,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,OAAO,QAAQ;AAClB,UAAI,oBAAoB,KAAM,oBAAmB,IAAI;AACrD;AAAA,IACF;AACA,QAAI,CAAC,mBAAmB,CAAC,OAAO,KAAK,CAAC,UAAU,MAAM,OAAO,eAAe,GAAG;AAC7E,yBAAmB,OAAO,CAAC,EAAE,EAAE;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,QAAQ,eAAe,CAAC;AAE5B,QAAM,gBAAgB,MAAM,QAAgC,MAAM;AAChE,QAAI,CAAC,gBAAiB,QAAO;AAC7B,WAAO,OAAO,KAAK,CAAC,UAAU,MAAM,OAAO,eAAe,KAAK;AAAA,EACjE,GAAG,CAAC,QAAQ,eAAe,CAAC;AAE5B,MAAI,WAAW;AACb,WACE;AAAA,MAAC;AAAA;AAAA,QACC,SAAS,EAAE,yCAAyC,sBAAsB;AAAA;AAAA,IAC5E;AAAA,EAEJ;AAEA,MAAI,SAAS;AACX,WACE,qBAAC,SAAM,SAAQ,eAAc,4BAAwB,MACnD;AAAA,0BAAC,cACE,YAAE,0CAA0C,0BAA0B,GACzE;AAAA,MACA,qBAAC,oBACC;AAAA,4BAAC,UAAM,2BAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAE;AAAA,QAC9D,oBAAC,SAAI,WAAU,QACb;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,SAAS,MAAM;AACb,mBAAK,QAAQ;AAAA,YACf;AAAA,YAEA;AAAA,kCAAC,cAAW,WAAU,UAAS,eAAW,MAAC;AAAA,cAC3C,oBAAC,UAAM,YAAE,iCAAiC,OAAO,GAAE;AAAA;AAAA;AAAA,QACrD,GACF;AAAA,SACF;AAAA,OACF;AAAA,EAEJ;AAEA,MAAI,CAAC,OAAO,QAAQ;AAClB,WAAO,oBAAC,sBAAmB;AAAA,EAC7B;AAEA,SACE,qBAAC,SAAI,WAAU,uBAAsB,sBAAkB,MACrD;AAAA,yBAAC,YAAO,WAAU,uBAChB;AAAA,0BAAC,QAAG,WAAU,qCACX,YAAE,iCAAiC,eAAe,GACrD;AAAA,MACA,oBAAC,OAAE,WAAU,iCACV;AAAA,QACC;AAAA,QACA;AAAA,MACF,GACF;AAAA,OACF;AAAA,IAEA,qBAAC,aAAQ,WAAU,yEACjB;AAAA,2BAAC,SAAI,WAAU,mEACb;AAAA,6BAAC,SAAI,WAAU,iCACb;AAAA,8BAAC,SAAM,SAAQ,8BACZ,YAAE,4CAA4C,OAAO,GACxD;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,IAAG;AAAA,cACH,mCAA+B;AAAA,cAC/B,WAAU;AAAA,cACV,OAAO,mBAAmB;AAAA,cAC1B,UAAU,CAAC,UAAU,mBAAmB,MAAM,OAAO,KAAK;AAAA,cAEzD,iBAAO,IAAI,CAAC,UACX,qBAAC,YAAsB,OAAO,MAAM,IACjC;AAAA,sBAAM;AAAA,gBAAM;AAAA,gBAAG,MAAM;AAAA,gBAAG;AAAA,mBADd,MAAM,EAEnB,CACD;AAAA;AAAA,UACH;AAAA,WACF;AAAA,QACA,qBAAC,SAAI,WAAU,4CACb;AAAA,8BAAC,SAAM,SAAQ,uBAAsB,WAAU,WAC5C,YAAE,uCAAuC,aAAa,GACzD;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,IAAG;AAAA,cACH,SAAS;AAAA,cACT,iBAAiB,CAAC,SAAkB,gBAAgB,IAAI;AAAA,cACxD,cAAY,EAAE,uCAAuC,aAAa;AAAA,cAClE,mCAA+B;AAAA;AAAA,UACjC;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM;AACb,qBAAK,QAAQ;AAAA,cACf;AAAA,cACA,cAAY,EAAE,mCAAmC,gBAAgB;AAAA,cACjE,UAAU;AAAA,cAEV,8BAAC,cAAW,WAAU,UAAS,eAAW,MAAC;AAAA;AAAA,UAC7C;AAAA,WACF;AAAA,SACF;AAAA,MACC,gBAAgB,oBAAC,gBAAa,OAAO,eAAe,IAAK;AAAA,MACzD,gBAAgB,oBAAC,wBAAqB,SAAS,cAAc,IAAI,IAAK;AAAA,MACtE,gBAAgB,oBAAC,gCAA6B,SAAS,cAAc,IAAI,IAAK;AAAA,OACjF;AAAA,IAEC,gBACC;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QACP,eAAe,CAAC,SAAiB,OAAO,SAAS,WAAW,WAAW,MAAM;AAAA,QAE7E;AAAA,+BAAC,YACC;AAAA,gCAAC,eAAY,OAAM,QAChB,YAAE,qCAAqC,MAAM,GAChD;AAAA,YACA,oBAAC,eAAY,OAAM,UAChB,YAAE,uCAAuC,aAAa,GACzD;AAAA,aACF;AAAA,UACA,oBAAC,eAAY,OAAM,QACjB,8BAAC,YAAS,OAAO,eAAe,OAAO,cAAc,GACvD;AAAA,UACA,oBAAC,eAAY,OAAM,UACjB,8BAAC,cAAW,OAAO,eAAe,GACpC;AAAA;AAAA;AAAA,IACF,IACE;AAAA,KACN;AAEJ;AAEA,IAAO,iCAAQ;",
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { Bot, BookOpen, Loader2, Play, RefreshCcw } from 'lucide-react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Alert, AlertDescription, AlertTitle } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from '@open-mercato/ui/primitives/tabs'\nimport { Textarea } from '@open-mercato/ui/primitives/textarea'\nimport { EmptyState } from '@open-mercato/ui/backend/EmptyState'\nimport { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { AiChat, createAiUiPartRegistry, LoopDisabledBanner, useAiShortcuts } from '@open-mercato/ui/ai'\nimport type { AiChatDebugPromptSection, AiChatDebugTool } from '@open-mercato/ui/ai'\nimport { ConversationShareButton } from '../../../../components/ConversationShareButton'\n\ntype PlaygroundAgentTool = {\n name: string\n displayName?: string\n isMutation?: boolean\n registered?: boolean\n requiredFeatures?: string[]\n}\n\ntype PlaygroundAgent = {\n id: string\n moduleId: string\n label: string\n description: string\n executionMode: 'chat' | 'object'\n mutationPolicy: string\n allowedTools: string[]\n requiredFeatures: string[]\n acceptedMediaTypes: string[]\n hasOutputSchema: boolean\n systemPrompt?: string\n readOnly?: boolean\n maxSteps?: number | null\n tools?: PlaygroundAgentTool[]\n}\n\ntype AgentsResponse = {\n agents: PlaygroundAgent[]\n total: number\n}\n\ntype RunObjectResponse = {\n object: unknown\n finishReason?: string\n usage?: { inputTokens?: number; outputTokens?: number }\n}\n\ntype RunObjectError = {\n error: string\n code?: string\n issues?: unknown\n}\n\nasync function fetchAgents(): Promise<AgentsResponse> {\n const { result, status } = await apiCallOrThrow<AgentsResponse>(\n '/api/ai_assistant/ai/agents',\n { method: 'GET', credentials: 'include' },\n { errorMessage: 'Failed to load agents' },\n )\n if (!result) throw new Error(`Failed to load agents (${status})`)\n return result\n}\n\nfunction PlaygroundLoading({ message }: { message: string }) {\n return (\n <div\n className=\"flex items-center gap-2 rounded-lg border border-border bg-background p-4 text-sm text-muted-foreground\"\n role=\"status\"\n >\n <Loader2 className=\"size-4 animate-spin\" aria-hidden />\n <span>{message}</span>\n </div>\n )\n}\n\nfunction PlaygroundNoAgents() {\n const t = useT()\n return (\n <EmptyState\n icon={<Bot className=\"size-6\" aria-hidden />}\n title={t(\n 'ai_assistant.playground.empty.title',\n 'No AI agents are registered for your role yet.',\n )}\n description={t(\n 'ai_assistant.playground.empty.description',\n 'Declare agents inside `packages/<module>/src/modules/<module>/ai-agents.ts`, run `yarn generate`, and ensure the caller holds the agent\\'s required features.',\n )}\n >\n <div className=\"mt-2 inline-flex items-center gap-2 text-xs text-muted-foreground\">\n <BookOpen className=\"size-3\" aria-hidden />\n <span>\n {t(\n 'ai_assistant.playground.empty.docLabel',\n 'See packages/ai-assistant/AGENTS.md for the agent definition reference.',\n )}\n </span>\n </div>\n </EmptyState>\n )\n}\n\nfunction AgentDetails({ agent }: { agent: PlaygroundAgent }) {\n const t = useT()\n return (\n <div className=\"rounded-md border border-border bg-muted/30 p-3 text-sm\">\n <div className=\"font-semibold\">{agent.label}</div>\n <p className=\"mt-1 text-xs text-muted-foreground\">{agent.description}</p>\n <dl className=\"mt-3 grid grid-cols-2 gap-2 text-xs\">\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.meta.module', 'Module')}\n </dt>\n <dd className=\"font-mono\">{agent.moduleId}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.meta.executionMode', 'Execution mode')}\n </dt>\n <dd className=\"font-mono\">{agent.executionMode}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.meta.mutationPolicy', 'Mutation policy')}\n </dt>\n <dd className=\"font-mono\">{agent.mutationPolicy}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.meta.tools', 'Allowed tools')}\n </dt>\n <dd className=\"font-mono\">{agent.allowedTools.length}</dd>\n </div>\n </dl>\n </div>\n )\n}\n\nfunction buildDebugTools(agent: PlaygroundAgent): AiChatDebugTool[] {\n if (agent.tools && agent.tools.length > 0) {\n return agent.tools.map((tool) => ({\n name: tool.name,\n displayName: tool.displayName ?? tool.name,\n isMutation: Boolean(tool.isMutation),\n requiredFeatures: tool.requiredFeatures ?? [],\n }))\n }\n return agent.allowedTools.map((toolName) => ({ name: toolName }))\n}\n\nfunction buildDebugPromptSections(agent: PlaygroundAgent): AiChatDebugPromptSection[] {\n const sections: AiChatDebugPromptSection[] = []\n if (agent.systemPrompt) {\n sections.push({ id: 'role', source: 'default', text: agent.systemPrompt })\n }\n const placeholderIds = [\n 'scope',\n 'data',\n 'tools',\n 'attachments',\n 'mutationPolicy',\n 'responseStyle',\n 'overrides',\n ] as const\n for (const id of placeholderIds) {\n sections.push({ id, source: 'placeholder' })\n }\n return sections\n}\n\ntype AgentModelResolution = {\n agentId: string\n providerId: string\n modelId: string\n baseURL: string | null\n source: string\n}\n\ntype SettingsAgentResolutionResponse = {\n agents: AgentModelResolution[]\n}\n\nasync function fetchAgentResolutions(): Promise<SettingsAgentResolutionResponse> {\n const result = await apiCall<SettingsAgentResolutionResponse>('/api/ai_assistant/settings')\n if (!result.ok || !result.result) return { agents: [] }\n return { agents: result.result.agents ?? [] }\n}\n\nasync function fetchLoopOverrideForAgent(\n agentId: string,\n): Promise<{ agentId: string; override: { loopDisabled?: boolean | null } | null }> {\n const result = await apiCall<{ agentId: string; override: { loopDisabled?: boolean | null } | null }>(\n `/api/ai_assistant/ai/agents/${encodeURIComponent(agentId)}/loop-override`,\n { method: 'GET', credentials: 'include' },\n )\n if (!result.ok || !result.result) return { agentId, override: null }\n return result.result\n}\n\nfunction LoopDisabledPlaygroundBanner({ agentId }: { agentId: string }) {\n const { data } = useQuery({\n queryKey: ['ai_assistant', 'loop_override', agentId],\n queryFn: () => fetchLoopOverrideForAgent(agentId),\n staleTime: 30000,\n })\n if (!data?.override?.loopDisabled) return null\n return <LoopDisabledBanner agentId={agentId} />\n}\n\nfunction ModelResolutionPanel({ agentId }: { agentId: string }) {\n const t = useT()\n const { data } = useQuery({\n queryKey: ['ai_assistant', 'settings', 'agents'],\n queryFn: fetchAgentResolutions,\n staleTime: 30000,\n })\n\n const resolution = data?.agents.find((agent) => agent.agentId === agentId)\n if (!resolution) return null\n\n return (\n <dl\n className=\"grid grid-cols-2 gap-x-4 gap-y-1 rounded-md border border-border bg-muted/30 p-3 text-xs sm:grid-cols-4\"\n data-ai-playground-model-resolution={agentId}\n >\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.resolution.provider', 'Provider')}\n </dt>\n <dd className=\"font-mono\" data-ai-playground-resolution-provider>\n {resolution.providerId}\n </dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.resolution.model', 'Model')}\n </dt>\n <dd className=\"font-mono\" data-ai-playground-resolution-model>\n {resolution.modelId}\n </dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.resolution.baseUrl', 'Base URL')}\n </dt>\n <dd className=\"font-mono\" data-ai-playground-resolution-base-url>\n {resolution.baseURL ?? t('ai_assistant.playground.resolution.none', '\u2014')}\n </dd>\n </div>\n <div>\n <dt className=\"font-medium text-muted-foreground\">\n {t('ai_assistant.playground.resolution.source', 'Source')}\n </dt>\n <dd className=\"font-mono\" data-ai-playground-resolution-source>\n {resolution.source}\n </dd>\n </div>\n </dl>\n )\n}\n\ntype PlaygroundUiPartSeed = {\n componentId: string\n pendingActionId?: string\n payload?: unknown\n}\n\nfunction readPlaygroundUiPartSeeds(): PlaygroundUiPartSeed[] {\n if (typeof window === 'undefined') return []\n try {\n const params = new URLSearchParams(window.location.search)\n const componentId = params.get('uiPart')\n if (!componentId) return []\n const pendingActionId = params.get('pendingActionId') ?? undefined\n return [{ componentId, pendingActionId }]\n } catch {\n return []\n }\n}\n\nfunction ChatLane({ agent, debug }: { agent: PlaygroundAgent; debug: boolean }) {\n const t = useT()\n // Scoped registry so repeated mounts do not share state with other pages.\n // Step 5.10: opt in to the LIVE mutation-approval cards so the playground\n // exercises the real cards when the chat response surfaces a pending\n // action (via the `?uiPart=...` debug seed for Playwright).\n const registry = React.useMemo(\n () => createAiUiPartRegistry({ seedLiveApprovalCards: true }),\n [],\n )\n const debugTools = React.useMemo(() => buildDebugTools(agent), [agent])\n const debugPromptSections = React.useMemo(\n () => buildDebugPromptSections(agent),\n [agent],\n )\n const [uiParts, setUiParts] = React.useState<PlaygroundUiPartSeed[]>([])\n const [conversationId, setConversationId] = React.useState<string | null>(null)\n\n // Step 5.10: the dispatcher does not yet surface `AiUiPart` entries through\n // the plain-text stream consumed by `useAiChat`. For now the playground\n // reads a `?uiPart=<componentId>&pendingActionId=...` seed from the URL\n // so Playwright + operator debug flows can render the approval cards\n // against a stubbed `/api/ai_assistant/ai/actions/:id` endpoint. When the\n // dispatcher switches to the UIMessageChunk format this effect swaps over\n // to the streamed `uiParts` payload.\n React.useEffect(() => {\n const seeds = readPlaygroundUiPartSeeds()\n if (seeds.length > 0) setUiParts(seeds)\n }, [])\n\n if (agent.executionMode !== 'chat') {\n return (\n <Alert variant=\"info\" data-ai-playground-unsupported=\"chat\">\n <AlertTitle>\n {t(\n 'ai_assistant.playground.chat.notSupportedTitle',\n 'Chat mode is not available for this agent.',\n )}\n </AlertTitle>\n <AlertDescription>\n {t(\n 'ai_assistant.playground.chat.notSupportedBody',\n 'Pick an agent whose execution mode is \"chat\", or switch to the object-mode tab.',\n )}\n </AlertDescription>\n </Alert>\n )\n }\n\n return (\n <div className=\"flex flex-col gap-2\" data-ai-playground-chat={agent.id}>\n <AiChat\n key={agent.id}\n agent={agent.id}\n pageContext={{ source: 'playground', pageId: 'ai_assistant.playground' }}\n debug={debug}\n registry={registry}\n className=\"min-h-96\"\n debugTools={debugTools}\n debugPromptSections={debugPromptSections}\n uiParts={uiParts}\n onConversationIdChange={setConversationId}\n headerActions={conversationId ? <ConversationShareButton conversationId={conversationId} /> : null}\n />\n </div>\n )\n}\n\nfunction ObjectLane({ agent }: { agent: PlaygroundAgent }) {\n const t = useT()\n const [prompt, setPrompt] = React.useState('')\n const [isRunning, setIsRunning] = React.useState(false)\n const [result, setResult] = React.useState<RunObjectResponse | null>(null)\n const [error, setError] = React.useState<RunObjectError | null>(null)\n const [lastRequest, setLastRequest] = React.useState<unknown>(null)\n\n const isSupported = agent.executionMode === 'object'\n const canRun = isSupported && prompt.trim().length > 0 && !isRunning\n\n const runObject = React.useCallback(async () => {\n if (!canRun) return\n const body = {\n agent: agent.id,\n messages: [{ role: 'user' as const, content: prompt }],\n pageContext: { source: 'playground', pageId: 'ai_assistant.playground' },\n }\n setLastRequest(body)\n setIsRunning(true)\n setResult(null)\n setError(null)\n try {\n const { ok, status, result } = await apiCall<RunObjectResponse | RunObjectError>(\n '/api/ai_assistant/ai/run-object',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(body),\n },\n )\n if (!ok) {\n const payload = (result as RunObjectError | null) ?? { error: `HTTP ${status}` }\n setError(payload)\n return\n }\n setResult((result as RunObjectResponse | null) ?? { object: null })\n } catch (err) {\n setError({\n error: err instanceof Error ? err.message : String(err),\n code: 'network_error',\n })\n } finally {\n setIsRunning(false)\n }\n }, [agent.id, canRun, prompt])\n\n const { handleKeyDown } = useAiShortcuts({\n onSubmit: () => {\n void runObject()\n },\n onCancel: () => {\n setError(null)\n },\n })\n\n if (!isSupported) {\n return (\n <Alert variant=\"info\" data-ai-playground-unsupported=\"object\">\n <AlertTitle>\n {t(\n 'ai_assistant.playground.object.notSupportedTitle',\n 'Object mode is not available for this agent.',\n )}\n </AlertTitle>\n <AlertDescription>\n {t(\n 'ai_assistant.playground.object.notSupportedBody',\n 'This agent declares executionMode = \"chat\". Pick an object-mode agent to preview structured output, or switch to the chat tab.',\n )}\n </AlertDescription>\n </Alert>\n )\n }\n\n return (\n <div className=\"flex flex-col gap-3\" data-ai-playground-object>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"ai-playground-object-input\">\n {t('ai_assistant.playground.object.inputLabel', 'Prompt')}\n </Label>\n <Textarea\n id=\"ai-playground-object-input\"\n rows={4}\n value={prompt}\n placeholder={t(\n 'ai_assistant.playground.object.inputPlaceholder',\n 'Describe what the agent should produce...',\n )}\n onChange={(event) => setPrompt(event.target.value)}\n onKeyDown={handleKeyDown}\n className=\"resize-none\"\n aria-label={t('ai_assistant.playground.object.inputLabel', 'Prompt')}\n />\n <div className=\"flex items-center justify-between\">\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'ai_assistant.playground.object.shortcutHint',\n 'Press Cmd/Ctrl+Enter to run.',\n )}\n </p>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void runObject()}\n disabled={!canRun}\n data-ai-playground-object-run\n >\n {isRunning ? (\n <Loader2 className=\"size-4 animate-spin\" aria-hidden />\n ) : (\n <Play className=\"size-4\" aria-hidden />\n )}\n <span>{t('ai_assistant.playground.object.run', 'Run object')}</span>\n </Button>\n </div>\n </div>\n\n {error ? (\n <Alert variant=\"destructive\" data-ai-playground-object-error={error.code ?? 'unknown'}>\n <AlertTitle>\n {t('ai_assistant.playground.object.errorTitle', 'Object run failed')}\n </AlertTitle>\n <AlertDescription>\n {error.code ? <span className=\"mr-2 font-mono text-xs\">{error.code}</span> : null}\n {error.error}\n </AlertDescription>\n </Alert>\n ) : null}\n\n {result ? (\n <section\n className=\"rounded-md border border-border bg-muted/30 p-3\"\n data-ai-playground-object-result\n >\n <h3 className=\"text-sm font-semibold\">\n {t('ai_assistant.playground.object.resultTitle', 'Generated object')}\n </h3>\n <pre className=\"mt-2 max-h-96 overflow-auto rounded bg-background p-2 text-xs font-mono\">\n {JSON.stringify(result.object, null, 2)}\n </pre>\n {result.usage || result.finishReason ? (\n <dl className=\"mt-3 grid grid-cols-3 gap-2 text-xs\">\n {result.finishReason ? (\n <div>\n <dt className=\"text-muted-foreground\">\n {t('ai_assistant.playground.object.finishReason', 'Finish reason')}\n </dt>\n <dd className=\"font-mono\">{result.finishReason}</dd>\n </div>\n ) : null}\n {result.usage?.inputTokens !== undefined ? (\n <div>\n <dt className=\"text-muted-foreground\">\n {t('ai_assistant.playground.object.inputTokens', 'Input tokens')}\n </dt>\n <dd className=\"font-mono\">{result.usage.inputTokens}</dd>\n </div>\n ) : null}\n {result.usage?.outputTokens !== undefined ? (\n <div>\n <dt className=\"text-muted-foreground\">\n {t('ai_assistant.playground.object.outputTokens', 'Output tokens')}\n </dt>\n <dd className=\"font-mono\">{result.usage.outputTokens}</dd>\n </div>\n ) : null}\n </dl>\n ) : null}\n </section>\n ) : null}\n\n {lastRequest && (error || result) ? (\n <details\n className=\"rounded-md border border-border bg-muted/20 p-2 text-xs\"\n data-ai-playground-object-debug\n >\n <summary className=\"cursor-pointer font-semibold\">\n {t('ai_assistant.playground.object.debugTitle', 'Last request payload')}\n </summary>\n <pre className=\"mt-2 max-h-64 overflow-auto whitespace-pre-wrap font-mono\">\n {JSON.stringify(lastRequest, null, 2)}\n </pre>\n </details>\n ) : null}\n </div>\n )\n}\n\nexport function AiPlaygroundPageClient() {\n const t = useT()\n const [selectedAgentId, setSelectedAgentId] = React.useState<string | null>(null)\n const [debugEnabled, setDebugEnabled] = React.useState(false)\n const [tab, setTab] = React.useState<'chat' | 'object'>('chat')\n\n const { data, isLoading, isError, error, refetch, isFetching } = useQuery<AgentsResponse>({\n queryKey: ['ai_assistant', 'playground', 'agents'],\n queryFn: fetchAgents,\n })\n\n const agents = React.useMemo<PlaygroundAgent[]>(() => data?.agents ?? [], [data])\n\n React.useEffect(() => {\n if (!agents.length) {\n if (selectedAgentId !== null) setSelectedAgentId(null)\n return\n }\n if (!selectedAgentId || !agents.some((agent) => agent.id === selectedAgentId)) {\n setSelectedAgentId(agents[0].id)\n }\n }, [agents, selectedAgentId])\n\n const selectedAgent = React.useMemo<PlaygroundAgent | null>(() => {\n if (!selectedAgentId) return null\n return agents.find((agent) => agent.id === selectedAgentId) ?? null\n }, [agents, selectedAgentId])\n\n if (isLoading) {\n return (\n <PlaygroundLoading\n message={t('ai_assistant.playground.loadingAgents', 'Loading AI agents...')}\n />\n )\n }\n\n if (isError) {\n return (\n <Alert variant=\"destructive\" data-ai-playground-error>\n <AlertTitle>\n {t('ai_assistant.playground.loadErrorTitle', 'Failed to load AI agents')}\n </AlertTitle>\n <AlertDescription>\n <span>{error instanceof Error ? error.message : String(error)}</span>\n <div className=\"mt-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n void refetch()\n }}\n >\n <RefreshCcw className=\"size-4\" aria-hidden />\n <span>{t('ai_assistant.playground.retry', 'Retry')}</span>\n </Button>\n </div>\n </AlertDescription>\n </Alert>\n )\n }\n\n if (!agents.length) {\n return <PlaygroundNoAgents />\n }\n\n return (\n <div className=\"flex flex-col gap-4\" data-ai-playground>\n <header className=\"flex flex-col gap-1\">\n <h1 className=\"text-2xl font-bold tracking-tight\">\n {t('ai_assistant.playground.title', 'AI Playground')}\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n {t(\n 'ai_assistant.playground.subtitle',\n 'Exercise every registered AI agent end-to-end. Use the debug panel to inspect request and response payloads, and the object-mode tab to preview structured output.',\n )}\n </p>\n </header>\n\n <section className=\"flex flex-col gap-3 rounded-lg border border-border bg-background p-3\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between\">\n <div className=\"flex flex-col gap-2 sm:flex-1\">\n <Label htmlFor=\"ai-playground-agent-picker\">\n {t('ai_assistant.playground.agentPickerLabel', 'Agent')}\n </Label>\n <select\n id=\"ai-playground-agent-picker\"\n data-ai-playground-agent-picker\n className=\"h-9 rounded-md border border-input bg-background px-3 text-sm\"\n value={selectedAgentId ?? ''}\n onChange={(event) => setSelectedAgentId(event.target.value)}\n >\n {agents.map((agent) => (\n <option key={agent.id} value={agent.id}>\n {agent.label} ({agent.id})\n </option>\n ))}\n </select>\n </div>\n <div className=\"flex items-center gap-3 sm:flex-shrink-0\">\n <Label htmlFor=\"ai-playground-debug\" className=\"text-sm\">\n {t('ai_assistant.playground.debugToggle', 'Debug panel')}\n </Label>\n <Switch\n id=\"ai-playground-debug\"\n checked={debugEnabled}\n onCheckedChange={(next: boolean) => setDebugEnabled(next)}\n aria-label={t('ai_assistant.playground.debugToggle', 'Debug panel')}\n data-ai-playground-debug-toggle\n />\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => {\n void refetch()\n }}\n aria-label={t('ai_assistant.playground.refresh', 'Refresh agents')}\n disabled={isFetching}\n >\n <RefreshCcw className=\"size-4\" aria-hidden />\n </IconButton>\n </div>\n </div>\n {selectedAgent ? <AgentDetails agent={selectedAgent} /> : null}\n {selectedAgent ? <ModelResolutionPanel agentId={selectedAgent.id} /> : null}\n {selectedAgent ? <LoopDisabledPlaygroundBanner agentId={selectedAgent.id} /> : null}\n </section>\n\n {selectedAgent ? (\n <Tabs\n value={tab}\n onValueChange={(next: string) => setTab(next === 'object' ? 'object' : 'chat')}\n >\n <TabsList>\n <TabsTrigger value=\"chat\">\n {t('ai_assistant.playground.tabs.chat', 'Chat')}\n </TabsTrigger>\n <TabsTrigger value=\"object\">\n {t('ai_assistant.playground.tabs.object', 'Object mode')}\n </TabsTrigger>\n </TabsList>\n <TabsContent value=\"chat\">\n <ChatLane agent={selectedAgent} debug={debugEnabled} />\n </TabsContent>\n <TabsContent value=\"object\">\n <ObjectLane agent={selectedAgent} />\n </TabsContent>\n </Tabs>\n ) : null}\n </div>\n )\n}\n\nexport default AiPlaygroundPageClient\n"],
5
+ "mappings": "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",
6
6
  "names": ["result"]
7
7
  }
@@ -0,0 +1,5 @@
1
+ import { ConversationShareButton } from "@open-mercato/ui/ai";
2
+ export {
3
+ ConversationShareButton
4
+ };
5
+ //# sourceMappingURL=ConversationShareButton.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/ai_assistant/components/ConversationShareButton.tsx"],
4
+ "sourcesContent": ["export { ConversationShareButton } from '@open-mercato/ui/ai'\n"],
5
+ "mappings": "AAAA,SAAS,+BAA+B;",
6
+ "names": []
7
+ }
@@ -0,0 +1,5 @@
1
+ import { ConversationShareDialog } from "@open-mercato/ui/ai";
2
+ export {
3
+ ConversationShareDialog
4
+ };
5
+ //# sourceMappingURL=ConversationShareDialog.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/ai_assistant/components/ConversationShareDialog.tsx"],
4
+ "sourcesContent": ["export { ConversationShareDialog } from '@open-mercato/ui/ai'\n"],
5
+ "mappings": "AAAA,SAAS,+BAA+B;",
6
+ "names": []
7
+ }
@@ -616,6 +616,9 @@ __decorateClass([
616
616
  __decorateClass([
617
617
  Property({ name: "last_read_at", type: Date, nullable: true })
618
618
  ], AiChatConversationParticipant.prototype, "lastReadAt", 2);
619
+ __decorateClass([
620
+ Property({ name: "deleted_at", type: Date, nullable: true })
621
+ ], AiChatConversationParticipant.prototype, "deletedAt", 2);
619
622
  __decorateClass([
620
623
  Property({ name: "created_at", type: Date, onCreate: () => /* @__PURE__ */ new Date() })
621
624
  ], AiChatConversationParticipant.prototype, "createdAt", 2);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/ai_assistant/data/entities.ts"],
4
- "sourcesContent": ["import { OptionalProps } from '@mikro-orm/core'\nimport {\n Entity,\n Index,\n PrimaryKey,\n Property,\n} from '@mikro-orm/decorators/legacy'\nimport type {\n AiPendingActionExecutionResult,\n AiPendingActionFailedRecord,\n AiPendingActionFieldDiff,\n AiPendingActionQueueMode,\n AiPendingActionRecordDiff,\n AiPendingActionStatus,\n} from '../lib/pending-action-types'\n\n/**\n * Versioned additive prompt-override for a registered AI agent (Step 5.3).\n *\n * Each write creates a new row with `version = latest + 1`. Rows are never\n * updated in place \u2014 history is preserved so operators can roll back by\n * reading an earlier `version`. Column set is tenant/org-scoped per the\n * standard Open Mercato RBAC contract.\n *\n * `sections` holds additive text keyed by prompt section id. The runtime\n * composes the final `systemPrompt` via `composeSystemPromptWithOverride`\n * (see `lib/prompt-override-merge.ts`), which NEVER replaces a built-in\n * section \u2014 overrides are append-only by contract.\n */\n@Entity({ tableName: 'ai_agent_prompt_overrides' })\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_org_agent_version_uq',\n expression:\n 'create unique index \"ai_agent_prompt_overrides_tenant_org_agent_version_uq\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\", \"version\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_agent_version_null_org_uq',\n expression:\n 'create unique index \"ai_agent_prompt_overrides_tenant_agent_version_null_org_uq\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"agent_id\", \"version\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_agent_idx',\n properties: ['tenantId', 'agentId'],\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_org_agent_version_idx',\n expression:\n 'create index \"ai_agent_prompt_overrides_tenant_org_agent_version_idx\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\", \"version\" desc)',\n})\nexport class AiAgentPromptOverride {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId' | 'createdByUserId' | 'notes'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'version', type: 'int' })\n version!: number\n\n @Property({ name: 'sections', type: 'jsonb' })\n sections!: Record<string, string>\n\n @Property({ name: 'notes', type: 'text', nullable: true })\n notes?: string | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Persistent mutation-approval gate row backing the Phase 3 WS-C contract\n * (spec \u00A78 `AiPendingAction` + \u00A79 confirm/cancel flow, Step 5.5).\n *\n * One row is created by `prepareMutation` (Step 5.6) whenever the runtime\n * intercepts an `isMutation: true` tool call from a non-read-only agent.\n * The row stores the normalized tool input, a precomputed `fieldDiff` (or\n * per-record batch diff in `records[]`), the target record version, an\n * `idempotencyKey` that dedupes double-submits within the TTL, and a\n * `status` that walks the state machine defined in\n * {@link AI_PENDING_ACTION_ALLOWED_TRANSITIONS}.\n *\n * The cleanup worker (Step 5.12) sweeps `status='pending' AND expiresAt < now`\n * rows and transitions them to `expired`. The confirm route (Step 5.8)\n * walks `pending \u2192 confirmed \u2192 executing \u2192 (failed | terminal success)`.\n * Reads always flow through `findOneWithDecryption` /\n * `findWithDecryption`, even though no column is GDPR-flagged today, so\n * future encrypted columns (e.g. `normalizedInput`) are handled.\n */\n@Entity({ tableName: 'ai_pending_actions' })\n@Index({\n name: 'ai_pending_actions_tenant_org_idempotency_uq',\n expression:\n 'create unique index \"ai_pending_actions_tenant_org_idempotency_uq\" on \"ai_pending_actions\" (\"tenant_id\", \"organization_id\", \"idempotency_key\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_pending_actions_tenant_idem_null_org_uq',\n expression:\n 'create unique index \"ai_pending_actions_tenant_idem_null_org_uq\" on \"ai_pending_actions\" (\"tenant_id\", \"idempotency_key\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_pending_actions_tenant_org_status_expires_idx',\n properties: ['tenantId', 'organizationId', 'status', 'expiresAt'],\n})\n@Index({\n name: 'ai_pending_actions_tenant_org_agent_status_idx',\n properties: ['tenantId', 'organizationId', 'agentId', 'status'],\n})\nexport class AiPendingAction {\n [OptionalProps]?:\n | 'createdAt'\n | 'organizationId'\n | 'conversationId'\n | 'targetEntityType'\n | 'targetRecordId'\n | 'fieldDiff'\n | 'records'\n | 'failedRecords'\n | 'sideEffectsSummary'\n | 'recordVersion'\n | 'attachmentIds'\n | 'executionResult'\n | 'resolvedAt'\n | 'resolvedByUserId'\n | 'queueMode'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'tool_name', type: 'text' })\n toolName!: string\n\n @Property({ name: 'conversation_id', type: 'text', nullable: true })\n conversationId?: string | null\n\n @Property({ name: 'target_entity_type', type: 'text', nullable: true })\n targetEntityType?: string | null\n\n @Property({ name: 'target_record_id', type: 'text', nullable: true })\n targetRecordId?: string | null\n\n @Property({ name: 'normalized_input', type: 'jsonb' })\n normalizedInput!: Record<string, unknown>\n\n @Property({ name: 'field_diff', type: 'jsonb', default: [] })\n fieldDiff: AiPendingActionFieldDiff[] = []\n\n @Property({ name: 'records', type: 'jsonb', nullable: true })\n records?: AiPendingActionRecordDiff[] | null\n\n @Property({ name: 'failed_records', type: 'jsonb', nullable: true })\n failedRecords?: AiPendingActionFailedRecord[] | null\n\n @Property({ name: 'side_effects_summary', type: 'text', nullable: true })\n sideEffectsSummary?: string | null\n\n @Property({ name: 'record_version', type: 'text', nullable: true })\n recordVersion?: string | null\n\n @Property({ name: 'attachment_ids', type: 'jsonb', default: [] })\n attachmentIds: string[] = []\n\n @Property({ name: 'idempotency_key', type: 'text' })\n idempotencyKey!: string\n\n @Property({ name: 'created_by_user_id', type: 'uuid' })\n createdByUserId!: string\n\n @Property({ name: 'status', type: 'text' })\n status!: AiPendingActionStatus\n\n @Property({ name: 'queue_mode', type: 'text', default: 'inline' })\n queueMode: AiPendingActionQueueMode = 'inline'\n\n @Property({ name: 'execution_result', type: 'jsonb', nullable: true })\n executionResult?: AiPendingActionExecutionResult | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'resolved_at', type: Date, nullable: true })\n resolvedAt?: Date | null\n\n @Property({ name: 'resolved_by_user_id', type: 'uuid', nullable: true })\n resolvedByUserId?: string | null\n}\n\n/**\n * Per-tenant runtime override row that controls which provider, model, and\n * base URL the AI runtime uses for a given agent (or all agents when\n * `agent_id` is null).\n *\n * Resolution at query time: a non-null `agent_id` row takes precedence over\n * a null `agent_id` (tenant-wide) row for the same `(tenant_id,\n * organization_id)` scope. All value columns are nullable \u2014 an admin can\n * override just the provider, just the model, or any subset. A null value\n * means \"inherit from the next source in the factory resolution chain.\"\n *\n * Soft-delete via `deleted_at` so the unique partial index and audit trail\n * remain intact across upsert operations.\n *\n * Phase 4a of spec `2026-04-27-ai-agents-provider-model-baseurl-overrides`.\n */\n@Entity({ tableName: 'ai_agent_runtime_overrides' })\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_org_agent_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_org_agent_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\") where \"deleted_at\" is null and \"organization_id\" is not null and \"agent_id\" is not null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_agent_null_org_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"agent_id\") where \"deleted_at\" is null and \"organization_id\" is null and \"agent_id\" is not null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_null_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_null_agent_null_org_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\") where \"deleted_at\" is null and \"organization_id\" is null and \"agent_id\" is null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_org_null_agent_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_org_null_agent_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"organization_id\") where \"deleted_at\" is null and \"organization_id\" is not null and \"agent_id\" is null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_idx',\n properties: ['tenantId'],\n})\nexport class AiAgentRuntimeOverride {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'agentId'\n | 'providerId'\n | 'modelId'\n | 'baseUrl'\n | 'allowedOverrideProviders'\n | 'allowedOverrideModelsByProvider'\n | 'updatedByUserId'\n | 'deletedAt'\n | 'loopDisabled'\n | 'loopMaxSteps'\n | 'loopMaxToolCalls'\n | 'loopMaxWallClockMs'\n | 'loopMaxTokens'\n | 'loopStopWhenJson'\n | 'loopActiveToolsJson'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'string', columnType: 'varchar(128)', nullable: true })\n agentId?: string | null\n\n @Property({ name: 'provider_id', type: 'string', columnType: 'varchar(64)', nullable: true })\n providerId?: string | null\n\n @Property({ name: 'model_id', type: 'string', columnType: 'varchar(256)', nullable: true })\n modelId?: string | null\n\n @Property({ name: 'base_url', type: 'string', columnType: 'varchar(2048)', nullable: true })\n baseUrl?: string | null\n\n @Property({ name: 'allowed_override_providers', type: 'jsonb', nullable: true })\n allowedOverrideProviders?: string[] | null\n\n @Property({ name: 'allowed_override_models_by_provider', type: 'jsonb', default: '{}' })\n allowedOverrideModelsByProvider: Record<string, string[]> = {}\n\n @Property({ name: 'updated_by_user_id', type: 'uuid', nullable: true })\n updatedByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n\n /**\n * Kill switch \u2014 when `true`, runtime forces `stopWhen: stepCountIs(1)` and\n * ignores all other loop config. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_disabled', type: 'boolean', nullable: true })\n loopDisabled?: boolean | null\n\n /**\n * Override `loop.maxSteps`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_steps', type: 'int', nullable: true })\n loopMaxSteps?: number | null\n\n /**\n * Override `loop.budget.maxToolCalls`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_tool_calls', type: 'int', nullable: true })\n loopMaxToolCalls?: number | null\n\n /**\n * Override `loop.budget.maxWallClockMs`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_wall_clock_ms', type: 'int', nullable: true })\n loopMaxWallClockMs?: number | null\n\n /**\n * Override `loop.budget.maxTokens`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_tokens', type: 'int', nullable: true })\n loopMaxTokens?: number | null\n\n /**\n * Override `loop.stopWhen`. JSON-safe variants only (`stepCount`,\n * `hasToolCall`); validator rejects `kind: 'custom'`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_stop_when_json', type: 'jsonb', nullable: true })\n loopStopWhenJson?: unknown | null\n\n /**\n * Override `loop.activeTools` (must be subset of `agent.allowedTools`).\n * Phase 3 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_active_tools_json', type: 'jsonb', nullable: true })\n loopActiveToolsJson?: unknown | null\n}\n\n/**\n * Append-only event log for token usage per step (chat) or per turn (object).\n *\n * One row is created by `recordTokenUsage` (Phase 6.3) for every completed\n * AI SDK step. Indexed for the three read patterns: daily rollup, per-agent\n * report, and session drill-down.\n *\n * Retention: rows older than `AI_TOKEN_USAGE_EVENTS_RETENTION_DAYS` (default\n * 90) are swept by the `ai-token-usage-prune` worker (Phase 6.4).\n *\n * Phase 6.0 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n@Entity({ tableName: 'ai_token_usage_events' })\n@Index({\n name: 'ai_token_usage_events_tenant_created_idx',\n properties: ['tenantId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_agent_created_idx',\n properties: ['tenantId', 'agentId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_model_created_idx',\n properties: ['tenantId', 'modelId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_session_turn_step_idx',\n properties: ['tenantId', 'sessionId', 'turnId', 'stepIndex'],\n})\nexport class AiTokenUsageEvent {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'cachedInputTokens'\n | 'reasoningTokens'\n | 'finishReason'\n | 'loopAbortReason'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'user_id', type: 'uuid' })\n userId!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'module_id', type: 'text' })\n moduleId!: string\n\n @Property({ name: 'session_id', type: 'uuid' })\n sessionId!: string\n\n @Property({ name: 'turn_id', type: 'uuid' })\n turnId!: string\n\n @Property({ name: 'step_index', type: 'int' })\n stepIndex!: number\n\n @Property({ name: 'provider_id', type: 'text' })\n providerId!: string\n\n @Property({ name: 'model_id', type: 'text' })\n modelId!: string\n\n @Property({ name: 'input_tokens', type: 'int' })\n inputTokens!: number\n\n @Property({ name: 'output_tokens', type: 'int' })\n outputTokens!: number\n\n @Property({ name: 'cached_input_tokens', type: 'int', nullable: true })\n cachedInputTokens?: number | null\n\n @Property({ name: 'reasoning_tokens', type: 'int', nullable: true })\n reasoningTokens?: number | null\n\n @Property({ name: 'finish_reason', type: 'text', nullable: true })\n finishReason?: string | null\n\n @Property({ name: 'loop_abort_reason', type: 'text', nullable: true })\n loopAbortReason?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Materialized daily rollup of token usage per `(tenant, day, agent, model)`.\n *\n * Updated incrementally by UPSERT on every `recordTokenUsage` call so the\n * rollup is always current even when the prune worker is behind. A daily\n * reconciliation worker (Phase 6.4) recomputes `session_count` from the events\n * table to correct any drift caused by event delivery delays or outages.\n *\n * `session_count` is maintained via a per-row LATERAL exists check at write\n * time (first event in a `(tenant, day, agent, model, session)` window\n * increments the counter). This counter may drift if events arrive out of\n * order; the daily worker corrects it.\n *\n * Phase 6.1 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n@Entity({ tableName: 'ai_token_usage_daily' })\n@Index({\n name: 'ai_token_usage_daily_tenant_day_agent_model_org_uq',\n expression:\n 'create unique index \"ai_token_usage_daily_tenant_day_agent_model_org_uq\" on \"ai_token_usage_daily\" (\"tenant_id\", \"day\", \"agent_id\", \"model_id\", \"organization_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_token_usage_daily_tenant_day_agent_model_null_org_uq',\n expression:\n 'create unique index \"ai_token_usage_daily_tenant_day_agent_model_null_org_uq\" on \"ai_token_usage_daily\" (\"tenant_id\", \"day\", \"agent_id\", \"model_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_token_usage_daily_tenant_day_idx',\n properties: ['tenantId', 'day'],\n})\nexport class AiTokenUsageDaily {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'day', type: 'string', columnType: 'date' })\n day!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'model_id', type: 'text' })\n modelId!: string\n\n @Property({ name: 'provider_id', type: 'text' })\n providerId!: string\n\n @Property({ name: 'input_tokens', type: 'string', columnType: 'bigint' })\n inputTokens!: string\n\n @Property({ name: 'output_tokens', type: 'string', columnType: 'bigint' })\n outputTokens!: string\n\n @Property({ name: 'cached_input_tokens', type: 'string', columnType: 'bigint' })\n cachedInputTokens!: string\n\n @Property({ name: 'reasoning_tokens', type: 'string', columnType: 'bigint' })\n reasoningTokens!: string\n\n @Property({ name: 'step_count', type: 'string', columnType: 'bigint' })\n stepCount!: string\n\n @Property({ name: 'turn_count', type: 'string', columnType: 'bigint' })\n turnCount!: string\n\n @Property({ name: 'session_count', type: 'string', columnType: 'bigint' })\n sessionCount!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Tenant-scoped override of an agent's declared `mutationPolicy` (Step 5.4).\n *\n * Unlike {@link AiAgentPromptOverride}, this surface is NOT versioned \u2014 it is\n * a single-value policy switch per `(tenantId, organizationId, agentId)`. The\n * runtime enforces the override as a DOWNGRADE only: the effective policy\n * equals the MOST RESTRICTIVE of `{ code-declared, override }`. Escalation is\n * a code-level change and is rejected at the route layer.\n *\n * Hierarchy (most restrictive \u2192 least): `read-only` < `destructive-confirm-required`\n * < `confirm-required`. The route never allows an override to widen the\n * code-declared policy.\n */\n/**\n * Tenant-scoped allowlist clipping which providers and models the runtime is\n * permitted to use within the env-driven allowlist (Phase 1780-6 of spec\n * `2026-04-27-ai-agents-provider-model-baseurl-overrides`).\n *\n * Effective constraint chain (outer \u2192 inner): `OM_AI_AVAILABLE_*` env vars \u2192\n * this tenant allowlist \u2192 per-tenant runtime overrides \u2192 per-request overrides.\n * The tenant allowlist may NEVER widen the env allowlist; the runtime\n * intersects the two and surfaces the intersection through the settings GET\n * response so the UI never offers a value the runtime would refuse.\n *\n * `allowedProviders === null` means \"inherit env\" (no tenant-level restriction\n * beyond what the env imposes). `allowedModelsByProvider` keys are provider\n * ids; a missing key means \"inherit env\" for that provider; an empty array\n * means \"no models permitted for this provider\" (effectively disabling it).\n */\n@Entity({ tableName: 'ai_tenant_model_allowlists' })\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_org_uq',\n expression:\n 'create unique index \"ai_tenant_model_allowlists_tenant_org_uq\" on \"ai_tenant_model_allowlists\" (\"tenant_id\", \"organization_id\") where \"deleted_at\" is null and \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_null_org_uq',\n expression:\n 'create unique index \"ai_tenant_model_allowlists_tenant_null_org_uq\" on \"ai_tenant_model_allowlists\" (\"tenant_id\") where \"deleted_at\" is null and \"organization_id\" is null',\n})\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_idx',\n properties: ['tenantId'],\n})\nexport class AiTenantModelAllowlist {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'allowedProviders'\n | 'allowedModelsByProvider'\n | 'updatedByUserId'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'allowed_providers', type: 'jsonb', nullable: true })\n allowedProviders?: string[] | null\n\n @Property({ name: 'allowed_models_by_provider', type: 'jsonb', default: '{}' })\n allowedModelsByProvider: Record<string, string[]> = {}\n\n @Property({ name: 'updated_by_user_id', type: 'uuid', nullable: true })\n updatedByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'ai_agent_mutation_policy_overrides' })\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_org_agent_uq',\n expression:\n 'create unique index \"ai_agent_mutation_policy_overrides_tenant_org_agent_uq\" on \"ai_agent_mutation_policy_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_mutation_policy_overrides_tenant_agent_null_org_uq\" on \"ai_agent_mutation_policy_overrides\" (\"tenant_id\", \"agent_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_agent_idx',\n properties: ['tenantId', 'agentId'],\n})\nexport class AiAgentMutationPolicyOverride {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId' | 'createdByUserId' | 'notes'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'mutation_policy', type: 'text' })\n mutationPolicy!: string\n\n @Property({ name: 'notes', type: 'text', nullable: true })\n notes?: string | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Tenant-scoped durable record of a typed AI chat session.\n *\n * Owner-only MVP per spec `2026-05-05-ai-chat-server-side-conversation-storage`.\n * The `participants` table prepares for future sharing without a schema\n * rewrite \u2014 the owner row is always written in the same transaction as the\n * conversation row (see `AiChatConversationRepository.createOrGet`).\n *\n * `conversationId` is the stable, client-visible identifier. It is unique\n * within `(tenant_id, organization_id)` so an idempotent `createOrGet` can\n * accept a client-generated UUID. Pending mutation approvals already store\n * the same id in `AiPendingAction.conversationId` \u2014 the chat-history schema\n * deliberately matches that contract so a future foreign key can be added\n * without churn.\n *\n * `imported_from_local_at` flags conversations that the UI lazily migrated\n * from `localStorage`. The flag is informational only; once a row exists it\n * is always the source of truth for that conversation.\n */\n@Entity({ tableName: 'ai_chat_conversations' })\n@Index({\n name: 'ai_chat_conversations_tenant_org_conv_uq',\n expression:\n 'create unique index \"ai_chat_conversations_tenant_org_conv_uq\" on \"ai_chat_conversations\" (\"tenant_id\", \"organization_id\", \"conversation_id\") where \"organization_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_conversations_tenant_conv_null_org_uq',\n expression:\n 'create unique index \"ai_chat_conversations_tenant_conv_null_org_uq\" on \"ai_chat_conversations\" (\"tenant_id\", \"conversation_id\") where \"organization_id\" is null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_conversations_tenant_org_owner_agent_idx',\n properties: ['tenantId', 'organizationId', 'ownerUserId', 'agentId', 'status', 'lastMessageAt'],\n})\n@Index({\n name: 'ai_chat_conversations_tenant_org_deleted_idx',\n properties: ['tenantId', 'organizationId', 'deletedAt'],\n})\nexport class AiChatConversation {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'title'\n | 'status'\n | 'visibility'\n | 'pageContext'\n | 'lastMessageAt'\n | 'importedFromLocalAt'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'owner_user_id', type: 'uuid' })\n ownerUserId!: string\n\n @Property({ name: 'title', type: 'text', nullable: true })\n title?: string | null\n\n @Property({ name: 'status', type: 'text', default: 'open' })\n status: 'open' | 'closed' = 'open'\n\n @Property({ name: 'visibility', type: 'text', default: 'private' })\n visibility: 'private' | 'shared' | 'organization' = 'private'\n\n @Property({ name: 'page_context', type: 'jsonb', nullable: true })\n pageContext?: Record<string, unknown> | null\n\n @Property({ name: 'last_message_at', type: Date, nullable: true })\n lastMessageAt?: Date | null\n\n @Property({ name: 'imported_from_local_at', type: Date, nullable: true })\n importedFromLocalAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n/**\n * Membership row for an `AiChatConversation`.\n *\n * MVP always writes exactly one row per conversation with `role = 'owner'`,\n * written transactionally alongside the conversation. Sharing extensions\n * append additional rows with `role IN ('viewer', 'commenter', ...)`. The\n * access predicate is \"is the caller an undeleted participant\" \u2014 see\n * `AiChatConversationRepository.assertAccessible`.\n *\n * `last_read_at` is reserved for future unread/share UX and is unused in MVP.\n */\n@Entity({ tableName: 'ai_chat_conversation_participants' })\n@Index({\n name: 'ai_chat_conv_participants_tenant_org_conv_user_uq',\n expression:\n 'create unique index \"ai_chat_conv_participants_tenant_org_conv_user_uq\" on \"ai_chat_conversation_participants\" (\"tenant_id\", \"organization_id\", \"conversation_id\", \"user_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_chat_conv_participants_tenant_conv_user_null_org_uq',\n expression:\n 'create unique index \"ai_chat_conv_participants_tenant_conv_user_null_org_uq\" on \"ai_chat_conversation_participants\" (\"tenant_id\", \"conversation_id\", \"user_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_chat_conv_participants_tenant_org_user_conv_idx',\n properties: ['tenantId', 'organizationId', 'userId', 'conversationId'],\n})\nexport class AiChatConversationParticipant {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'role'\n | 'lastReadAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'user_id', type: 'uuid' })\n userId!: string\n\n @Property({ name: 'role', type: 'text', default: 'owner' })\n role: 'owner' | 'viewer' | 'commenter' = 'owner'\n\n @Property({ name: 'last_read_at', type: Date, nullable: true })\n lastReadAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Append-only message row for an `AiChatConversation`.\n *\n * `client_message_id` is the idempotency key for retries and lazy imports\n * from `localStorage`. The partial unique index allows a non-null\n * `clientMessageId` to dedupe within the conversation while leaving\n * server-only rows (assistant turns persisted from the streaming dispatcher)\n * free of the constraint.\n *\n * `ui_parts` stores the serializable subset of `AiChatMessageUiPart[]` so the\n * chat surface can re-render record cards, mutation-preview cards, etc.\n * across reloads. Attachment previews (`data:` URLs and transient blob\n * URLs) MUST NOT be persisted here \u2014 the UI strips them before upload.\n */\n@Entity({ tableName: 'ai_chat_messages' })\n@Index({\n name: 'ai_chat_messages_tenant_org_conv_client_id_uq',\n expression:\n 'create unique index \"ai_chat_messages_tenant_org_conv_client_id_uq\" on \"ai_chat_messages\" (\"tenant_id\", \"organization_id\", \"conversation_id\", \"client_message_id\") where \"organization_id\" is not null and \"client_message_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_messages_tenant_conv_client_id_null_org_uq',\n expression:\n 'create unique index \"ai_chat_messages_tenant_conv_client_id_null_org_uq\" on \"ai_chat_messages\" (\"tenant_id\", \"conversation_id\", \"client_message_id\") where \"organization_id\" is null and \"client_message_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_messages_tenant_org_conv_created_idx',\n properties: ['tenantId', 'organizationId', 'conversationId', 'createdAt'],\n})\n@Index({\n name: 'ai_chat_messages_tenant_org_deleted_idx',\n properties: ['tenantId', 'organizationId', 'deletedAt'],\n})\nexport class AiChatMessage {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'clientMessageId'\n | 'uiParts'\n | 'attachmentIds'\n | 'filesMetadata'\n | 'model'\n | 'metadata'\n | 'createdByUserId'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'client_message_id', type: 'text', nullable: true })\n clientMessageId?: string | null\n\n @Property({ name: 'role', type: 'text' })\n role!: 'user' | 'assistant' | 'system'\n\n @Property({ name: 'content', type: 'text' })\n content!: string\n\n @Property({ name: 'ui_parts', type: 'jsonb', nullable: true })\n uiParts?: unknown[] | null\n\n @Property({ name: 'attachment_ids', type: 'jsonb', nullable: true })\n attachmentIds?: string[] | null\n\n @Property({ name: 'files_metadata', type: 'jsonb', nullable: true })\n filesMetadata?: Array<Record<string, unknown>> | null\n\n @Property({ name: 'model', type: 'text', nullable: true })\n model?: string | null\n\n @Property({ name: 'metadata', type: 'jsonb', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { OptionalProps } from '@mikro-orm/core'\nimport {\n Entity,\n Index,\n PrimaryKey,\n Property,\n} from '@mikro-orm/decorators/legacy'\nimport type {\n AiPendingActionExecutionResult,\n AiPendingActionFailedRecord,\n AiPendingActionFieldDiff,\n AiPendingActionQueueMode,\n AiPendingActionRecordDiff,\n AiPendingActionStatus,\n} from '../lib/pending-action-types'\n\n/**\n * Versioned additive prompt-override for a registered AI agent (Step 5.3).\n *\n * Each write creates a new row with `version = latest + 1`. Rows are never\n * updated in place \u2014 history is preserved so operators can roll back by\n * reading an earlier `version`. Column set is tenant/org-scoped per the\n * standard Open Mercato RBAC contract.\n *\n * `sections` holds additive text keyed by prompt section id. The runtime\n * composes the final `systemPrompt` via `composeSystemPromptWithOverride`\n * (see `lib/prompt-override-merge.ts`), which NEVER replaces a built-in\n * section \u2014 overrides are append-only by contract.\n */\n@Entity({ tableName: 'ai_agent_prompt_overrides' })\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_org_agent_version_uq',\n expression:\n 'create unique index \"ai_agent_prompt_overrides_tenant_org_agent_version_uq\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\", \"version\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_agent_version_null_org_uq',\n expression:\n 'create unique index \"ai_agent_prompt_overrides_tenant_agent_version_null_org_uq\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"agent_id\", \"version\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_agent_idx',\n properties: ['tenantId', 'agentId'],\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_org_agent_version_idx',\n expression:\n 'create index \"ai_agent_prompt_overrides_tenant_org_agent_version_idx\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\", \"version\" desc)',\n})\nexport class AiAgentPromptOverride {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId' | 'createdByUserId' | 'notes'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'version', type: 'int' })\n version!: number\n\n @Property({ name: 'sections', type: 'jsonb' })\n sections!: Record<string, string>\n\n @Property({ name: 'notes', type: 'text', nullable: true })\n notes?: string | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Persistent mutation-approval gate row backing the Phase 3 WS-C contract\n * (spec \u00A78 `AiPendingAction` + \u00A79 confirm/cancel flow, Step 5.5).\n *\n * One row is created by `prepareMutation` (Step 5.6) whenever the runtime\n * intercepts an `isMutation: true` tool call from a non-read-only agent.\n * The row stores the normalized tool input, a precomputed `fieldDiff` (or\n * per-record batch diff in `records[]`), the target record version, an\n * `idempotencyKey` that dedupes double-submits within the TTL, and a\n * `status` that walks the state machine defined in\n * {@link AI_PENDING_ACTION_ALLOWED_TRANSITIONS}.\n *\n * The cleanup worker (Step 5.12) sweeps `status='pending' AND expiresAt < now`\n * rows and transitions them to `expired`. The confirm route (Step 5.8)\n * walks `pending \u2192 confirmed \u2192 executing \u2192 (failed | terminal success)`.\n * Reads always flow through `findOneWithDecryption` /\n * `findWithDecryption`, even though no column is GDPR-flagged today, so\n * future encrypted columns (e.g. `normalizedInput`) are handled.\n */\n@Entity({ tableName: 'ai_pending_actions' })\n@Index({\n name: 'ai_pending_actions_tenant_org_idempotency_uq',\n expression:\n 'create unique index \"ai_pending_actions_tenant_org_idempotency_uq\" on \"ai_pending_actions\" (\"tenant_id\", \"organization_id\", \"idempotency_key\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_pending_actions_tenant_idem_null_org_uq',\n expression:\n 'create unique index \"ai_pending_actions_tenant_idem_null_org_uq\" on \"ai_pending_actions\" (\"tenant_id\", \"idempotency_key\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_pending_actions_tenant_org_status_expires_idx',\n properties: ['tenantId', 'organizationId', 'status', 'expiresAt'],\n})\n@Index({\n name: 'ai_pending_actions_tenant_org_agent_status_idx',\n properties: ['tenantId', 'organizationId', 'agentId', 'status'],\n})\nexport class AiPendingAction {\n [OptionalProps]?:\n | 'createdAt'\n | 'organizationId'\n | 'conversationId'\n | 'targetEntityType'\n | 'targetRecordId'\n | 'fieldDiff'\n | 'records'\n | 'failedRecords'\n | 'sideEffectsSummary'\n | 'recordVersion'\n | 'attachmentIds'\n | 'executionResult'\n | 'resolvedAt'\n | 'resolvedByUserId'\n | 'queueMode'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'tool_name', type: 'text' })\n toolName!: string\n\n @Property({ name: 'conversation_id', type: 'text', nullable: true })\n conversationId?: string | null\n\n @Property({ name: 'target_entity_type', type: 'text', nullable: true })\n targetEntityType?: string | null\n\n @Property({ name: 'target_record_id', type: 'text', nullable: true })\n targetRecordId?: string | null\n\n @Property({ name: 'normalized_input', type: 'jsonb' })\n normalizedInput!: Record<string, unknown>\n\n @Property({ name: 'field_diff', type: 'jsonb', default: [] })\n fieldDiff: AiPendingActionFieldDiff[] = []\n\n @Property({ name: 'records', type: 'jsonb', nullable: true })\n records?: AiPendingActionRecordDiff[] | null\n\n @Property({ name: 'failed_records', type: 'jsonb', nullable: true })\n failedRecords?: AiPendingActionFailedRecord[] | null\n\n @Property({ name: 'side_effects_summary', type: 'text', nullable: true })\n sideEffectsSummary?: string | null\n\n @Property({ name: 'record_version', type: 'text', nullable: true })\n recordVersion?: string | null\n\n @Property({ name: 'attachment_ids', type: 'jsonb', default: [] })\n attachmentIds: string[] = []\n\n @Property({ name: 'idempotency_key', type: 'text' })\n idempotencyKey!: string\n\n @Property({ name: 'created_by_user_id', type: 'uuid' })\n createdByUserId!: string\n\n @Property({ name: 'status', type: 'text' })\n status!: AiPendingActionStatus\n\n @Property({ name: 'queue_mode', type: 'text', default: 'inline' })\n queueMode: AiPendingActionQueueMode = 'inline'\n\n @Property({ name: 'execution_result', type: 'jsonb', nullable: true })\n executionResult?: AiPendingActionExecutionResult | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'resolved_at', type: Date, nullable: true })\n resolvedAt?: Date | null\n\n @Property({ name: 'resolved_by_user_id', type: 'uuid', nullable: true })\n resolvedByUserId?: string | null\n}\n\n/**\n * Per-tenant runtime override row that controls which provider, model, and\n * base URL the AI runtime uses for a given agent (or all agents when\n * `agent_id` is null).\n *\n * Resolution at query time: a non-null `agent_id` row takes precedence over\n * a null `agent_id` (tenant-wide) row for the same `(tenant_id,\n * organization_id)` scope. All value columns are nullable \u2014 an admin can\n * override just the provider, just the model, or any subset. A null value\n * means \"inherit from the next source in the factory resolution chain.\"\n *\n * Soft-delete via `deleted_at` so the unique partial index and audit trail\n * remain intact across upsert operations.\n *\n * Phase 4a of spec `2026-04-27-ai-agents-provider-model-baseurl-overrides`.\n */\n@Entity({ tableName: 'ai_agent_runtime_overrides' })\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_org_agent_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_org_agent_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\") where \"deleted_at\" is null and \"organization_id\" is not null and \"agent_id\" is not null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_agent_null_org_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"agent_id\") where \"deleted_at\" is null and \"organization_id\" is null and \"agent_id\" is not null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_null_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_null_agent_null_org_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\") where \"deleted_at\" is null and \"organization_id\" is null and \"agent_id\" is null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_org_null_agent_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_org_null_agent_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"organization_id\") where \"deleted_at\" is null and \"organization_id\" is not null and \"agent_id\" is null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_idx',\n properties: ['tenantId'],\n})\nexport class AiAgentRuntimeOverride {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'agentId'\n | 'providerId'\n | 'modelId'\n | 'baseUrl'\n | 'allowedOverrideProviders'\n | 'allowedOverrideModelsByProvider'\n | 'updatedByUserId'\n | 'deletedAt'\n | 'loopDisabled'\n | 'loopMaxSteps'\n | 'loopMaxToolCalls'\n | 'loopMaxWallClockMs'\n | 'loopMaxTokens'\n | 'loopStopWhenJson'\n | 'loopActiveToolsJson'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'string', columnType: 'varchar(128)', nullable: true })\n agentId?: string | null\n\n @Property({ name: 'provider_id', type: 'string', columnType: 'varchar(64)', nullable: true })\n providerId?: string | null\n\n @Property({ name: 'model_id', type: 'string', columnType: 'varchar(256)', nullable: true })\n modelId?: string | null\n\n @Property({ name: 'base_url', type: 'string', columnType: 'varchar(2048)', nullable: true })\n baseUrl?: string | null\n\n @Property({ name: 'allowed_override_providers', type: 'jsonb', nullable: true })\n allowedOverrideProviders?: string[] | null\n\n @Property({ name: 'allowed_override_models_by_provider', type: 'jsonb', default: '{}' })\n allowedOverrideModelsByProvider: Record<string, string[]> = {}\n\n @Property({ name: 'updated_by_user_id', type: 'uuid', nullable: true })\n updatedByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n\n /**\n * Kill switch \u2014 when `true`, runtime forces `stopWhen: stepCountIs(1)` and\n * ignores all other loop config. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_disabled', type: 'boolean', nullable: true })\n loopDisabled?: boolean | null\n\n /**\n * Override `loop.maxSteps`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_steps', type: 'int', nullable: true })\n loopMaxSteps?: number | null\n\n /**\n * Override `loop.budget.maxToolCalls`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_tool_calls', type: 'int', nullable: true })\n loopMaxToolCalls?: number | null\n\n /**\n * Override `loop.budget.maxWallClockMs`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_wall_clock_ms', type: 'int', nullable: true })\n loopMaxWallClockMs?: number | null\n\n /**\n * Override `loop.budget.maxTokens`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_tokens', type: 'int', nullable: true })\n loopMaxTokens?: number | null\n\n /**\n * Override `loop.stopWhen`. JSON-safe variants only (`stepCount`,\n * `hasToolCall`); validator rejects `kind: 'custom'`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_stop_when_json', type: 'jsonb', nullable: true })\n loopStopWhenJson?: unknown | null\n\n /**\n * Override `loop.activeTools` (must be subset of `agent.allowedTools`).\n * Phase 3 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_active_tools_json', type: 'jsonb', nullable: true })\n loopActiveToolsJson?: unknown | null\n}\n\n/**\n * Append-only event log for token usage per step (chat) or per turn (object).\n *\n * One row is created by `recordTokenUsage` (Phase 6.3) for every completed\n * AI SDK step. Indexed for the three read patterns: daily rollup, per-agent\n * report, and session drill-down.\n *\n * Retention: rows older than `AI_TOKEN_USAGE_EVENTS_RETENTION_DAYS` (default\n * 90) are swept by the `ai-token-usage-prune` worker (Phase 6.4).\n *\n * Phase 6.0 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n@Entity({ tableName: 'ai_token_usage_events' })\n@Index({\n name: 'ai_token_usage_events_tenant_created_idx',\n properties: ['tenantId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_agent_created_idx',\n properties: ['tenantId', 'agentId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_model_created_idx',\n properties: ['tenantId', 'modelId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_session_turn_step_idx',\n properties: ['tenantId', 'sessionId', 'turnId', 'stepIndex'],\n})\nexport class AiTokenUsageEvent {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'cachedInputTokens'\n | 'reasoningTokens'\n | 'finishReason'\n | 'loopAbortReason'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'user_id', type: 'uuid' })\n userId!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'module_id', type: 'text' })\n moduleId!: string\n\n @Property({ name: 'session_id', type: 'uuid' })\n sessionId!: string\n\n @Property({ name: 'turn_id', type: 'uuid' })\n turnId!: string\n\n @Property({ name: 'step_index', type: 'int' })\n stepIndex!: number\n\n @Property({ name: 'provider_id', type: 'text' })\n providerId!: string\n\n @Property({ name: 'model_id', type: 'text' })\n modelId!: string\n\n @Property({ name: 'input_tokens', type: 'int' })\n inputTokens!: number\n\n @Property({ name: 'output_tokens', type: 'int' })\n outputTokens!: number\n\n @Property({ name: 'cached_input_tokens', type: 'int', nullable: true })\n cachedInputTokens?: number | null\n\n @Property({ name: 'reasoning_tokens', type: 'int', nullable: true })\n reasoningTokens?: number | null\n\n @Property({ name: 'finish_reason', type: 'text', nullable: true })\n finishReason?: string | null\n\n @Property({ name: 'loop_abort_reason', type: 'text', nullable: true })\n loopAbortReason?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Materialized daily rollup of token usage per `(tenant, day, agent, model)`.\n *\n * Updated incrementally by UPSERT on every `recordTokenUsage` call so the\n * rollup is always current even when the prune worker is behind. A daily\n * reconciliation worker (Phase 6.4) recomputes `session_count` from the events\n * table to correct any drift caused by event delivery delays or outages.\n *\n * `session_count` is maintained via a per-row LATERAL exists check at write\n * time (first event in a `(tenant, day, agent, model, session)` window\n * increments the counter). This counter may drift if events arrive out of\n * order; the daily worker corrects it.\n *\n * Phase 6.1 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n@Entity({ tableName: 'ai_token_usage_daily' })\n@Index({\n name: 'ai_token_usage_daily_tenant_day_agent_model_org_uq',\n expression:\n 'create unique index \"ai_token_usage_daily_tenant_day_agent_model_org_uq\" on \"ai_token_usage_daily\" (\"tenant_id\", \"day\", \"agent_id\", \"model_id\", \"organization_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_token_usage_daily_tenant_day_agent_model_null_org_uq',\n expression:\n 'create unique index \"ai_token_usage_daily_tenant_day_agent_model_null_org_uq\" on \"ai_token_usage_daily\" (\"tenant_id\", \"day\", \"agent_id\", \"model_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_token_usage_daily_tenant_day_idx',\n properties: ['tenantId', 'day'],\n})\nexport class AiTokenUsageDaily {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'day', type: 'string', columnType: 'date' })\n day!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'model_id', type: 'text' })\n modelId!: string\n\n @Property({ name: 'provider_id', type: 'text' })\n providerId!: string\n\n @Property({ name: 'input_tokens', type: 'string', columnType: 'bigint' })\n inputTokens!: string\n\n @Property({ name: 'output_tokens', type: 'string', columnType: 'bigint' })\n outputTokens!: string\n\n @Property({ name: 'cached_input_tokens', type: 'string', columnType: 'bigint' })\n cachedInputTokens!: string\n\n @Property({ name: 'reasoning_tokens', type: 'string', columnType: 'bigint' })\n reasoningTokens!: string\n\n @Property({ name: 'step_count', type: 'string', columnType: 'bigint' })\n stepCount!: string\n\n @Property({ name: 'turn_count', type: 'string', columnType: 'bigint' })\n turnCount!: string\n\n @Property({ name: 'session_count', type: 'string', columnType: 'bigint' })\n sessionCount!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Tenant-scoped override of an agent's declared `mutationPolicy` (Step 5.4).\n *\n * Unlike {@link AiAgentPromptOverride}, this surface is NOT versioned \u2014 it is\n * a single-value policy switch per `(tenantId, organizationId, agentId)`. The\n * runtime enforces the override as a DOWNGRADE only: the effective policy\n * equals the MOST RESTRICTIVE of `{ code-declared, override }`. Escalation is\n * a code-level change and is rejected at the route layer.\n *\n * Hierarchy (most restrictive \u2192 least): `read-only` < `destructive-confirm-required`\n * < `confirm-required`. The route never allows an override to widen the\n * code-declared policy.\n */\n/**\n * Tenant-scoped allowlist clipping which providers and models the runtime is\n * permitted to use within the env-driven allowlist (Phase 1780-6 of spec\n * `2026-04-27-ai-agents-provider-model-baseurl-overrides`).\n *\n * Effective constraint chain (outer \u2192 inner): `OM_AI_AVAILABLE_*` env vars \u2192\n * this tenant allowlist \u2192 per-tenant runtime overrides \u2192 per-request overrides.\n * The tenant allowlist may NEVER widen the env allowlist; the runtime\n * intersects the two and surfaces the intersection through the settings GET\n * response so the UI never offers a value the runtime would refuse.\n *\n * `allowedProviders === null` means \"inherit env\" (no tenant-level restriction\n * beyond what the env imposes). `allowedModelsByProvider` keys are provider\n * ids; a missing key means \"inherit env\" for that provider; an empty array\n * means \"no models permitted for this provider\" (effectively disabling it).\n */\n@Entity({ tableName: 'ai_tenant_model_allowlists' })\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_org_uq',\n expression:\n 'create unique index \"ai_tenant_model_allowlists_tenant_org_uq\" on \"ai_tenant_model_allowlists\" (\"tenant_id\", \"organization_id\") where \"deleted_at\" is null and \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_null_org_uq',\n expression:\n 'create unique index \"ai_tenant_model_allowlists_tenant_null_org_uq\" on \"ai_tenant_model_allowlists\" (\"tenant_id\") where \"deleted_at\" is null and \"organization_id\" is null',\n})\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_idx',\n properties: ['tenantId'],\n})\nexport class AiTenantModelAllowlist {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'allowedProviders'\n | 'allowedModelsByProvider'\n | 'updatedByUserId'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'allowed_providers', type: 'jsonb', nullable: true })\n allowedProviders?: string[] | null\n\n @Property({ name: 'allowed_models_by_provider', type: 'jsonb', default: '{}' })\n allowedModelsByProvider: Record<string, string[]> = {}\n\n @Property({ name: 'updated_by_user_id', type: 'uuid', nullable: true })\n updatedByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'ai_agent_mutation_policy_overrides' })\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_org_agent_uq',\n expression:\n 'create unique index \"ai_agent_mutation_policy_overrides_tenant_org_agent_uq\" on \"ai_agent_mutation_policy_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_mutation_policy_overrides_tenant_agent_null_org_uq\" on \"ai_agent_mutation_policy_overrides\" (\"tenant_id\", \"agent_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_agent_idx',\n properties: ['tenantId', 'agentId'],\n})\nexport class AiAgentMutationPolicyOverride {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId' | 'createdByUserId' | 'notes'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'mutation_policy', type: 'text' })\n mutationPolicy!: string\n\n @Property({ name: 'notes', type: 'text', nullable: true })\n notes?: string | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Tenant-scoped durable record of a typed AI chat session.\n *\n * Owner-only MVP per spec `2026-05-05-ai-chat-server-side-conversation-storage`.\n * The `participants` table prepares for future sharing without a schema\n * rewrite \u2014 the owner row is always written in the same transaction as the\n * conversation row (see `AiChatConversationRepository.createOrGet`).\n *\n * `conversationId` is the stable, client-visible identifier. It is unique\n * within `(tenant_id, organization_id)` so an idempotent `createOrGet` can\n * accept a client-generated UUID. Pending mutation approvals already store\n * the same id in `AiPendingAction.conversationId` \u2014 the chat-history schema\n * deliberately matches that contract so a future foreign key can be added\n * without churn.\n *\n * `imported_from_local_at` flags conversations that the UI lazily migrated\n * from `localStorage`. The flag is informational only; once a row exists it\n * is always the source of truth for that conversation.\n */\n@Entity({ tableName: 'ai_chat_conversations' })\n@Index({\n name: 'ai_chat_conversations_tenant_org_conv_uq',\n expression:\n 'create unique index \"ai_chat_conversations_tenant_org_conv_uq\" on \"ai_chat_conversations\" (\"tenant_id\", \"organization_id\", \"conversation_id\") where \"organization_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_conversations_tenant_conv_null_org_uq',\n expression:\n 'create unique index \"ai_chat_conversations_tenant_conv_null_org_uq\" on \"ai_chat_conversations\" (\"tenant_id\", \"conversation_id\") where \"organization_id\" is null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_conversations_tenant_org_owner_agent_idx',\n properties: ['tenantId', 'organizationId', 'ownerUserId', 'agentId', 'status', 'lastMessageAt'],\n})\n@Index({\n name: 'ai_chat_conversations_tenant_org_deleted_idx',\n properties: ['tenantId', 'organizationId', 'deletedAt'],\n})\nexport class AiChatConversation {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'title'\n | 'status'\n | 'visibility'\n | 'pageContext'\n | 'lastMessageAt'\n | 'importedFromLocalAt'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'owner_user_id', type: 'uuid' })\n ownerUserId!: string\n\n @Property({ name: 'title', type: 'text', nullable: true })\n title?: string | null\n\n @Property({ name: 'status', type: 'text', default: 'open' })\n status: 'open' | 'closed' = 'open'\n\n @Property({ name: 'visibility', type: 'text', default: 'private' })\n visibility: 'private' | 'shared' | 'organization' = 'private'\n\n @Property({ name: 'page_context', type: 'jsonb', nullable: true })\n pageContext?: Record<string, unknown> | null\n\n @Property({ name: 'last_message_at', type: Date, nullable: true })\n lastMessageAt?: Date | null\n\n @Property({ name: 'imported_from_local_at', type: Date, nullable: true })\n importedFromLocalAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n/**\n * Membership row for an `AiChatConversation`.\n *\n * MVP always writes exactly one row per conversation with `role = 'owner'`,\n * written transactionally alongside the conversation. Sharing extensions\n * append additional rows with `role IN ('viewer', 'commenter', ...)`. The\n * access predicate is \"is the caller an undeleted participant\" \u2014 see\n * `AiChatConversationRepository.assertAccessible`.\n *\n * `last_read_at` is reserved for future unread/share UX and is unused in MVP.\n */\n@Entity({ tableName: 'ai_chat_conversation_participants' })\n@Index({\n name: 'ai_chat_conv_participants_tenant_org_conv_user_uq',\n expression:\n 'create unique index \"ai_chat_conv_participants_tenant_org_conv_user_uq\" on \"ai_chat_conversation_participants\" (\"tenant_id\", \"organization_id\", \"conversation_id\", \"user_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_chat_conv_participants_tenant_conv_user_null_org_uq',\n expression:\n 'create unique index \"ai_chat_conv_participants_tenant_conv_user_null_org_uq\" on \"ai_chat_conversation_participants\" (\"tenant_id\", \"conversation_id\", \"user_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_chat_conv_participants_tenant_org_user_conv_idx',\n properties: ['tenantId', 'organizationId', 'userId', 'conversationId'],\n})\nexport class AiChatConversationParticipant {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'role'\n | 'lastReadAt'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'user_id', type: 'uuid' })\n userId!: string\n\n @Property({ name: 'role', type: 'text', default: 'owner' })\n role: 'owner' | 'viewer' | 'commenter' = 'owner'\n\n @Property({ name: 'last_read_at', type: Date, nullable: true })\n lastReadAt?: Date | null\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Append-only message row for an `AiChatConversation`.\n *\n * `client_message_id` is the idempotency key for retries and lazy imports\n * from `localStorage`. The partial unique index allows a non-null\n * `clientMessageId` to dedupe within the conversation while leaving\n * server-only rows (assistant turns persisted from the streaming dispatcher)\n * free of the constraint.\n *\n * `ui_parts` stores the serializable subset of `AiChatMessageUiPart[]` so the\n * chat surface can re-render record cards, mutation-preview cards, etc.\n * across reloads. Attachment previews (`data:` URLs and transient blob\n * URLs) MUST NOT be persisted here \u2014 the UI strips them before upload.\n */\n@Entity({ tableName: 'ai_chat_messages' })\n@Index({\n name: 'ai_chat_messages_tenant_org_conv_client_id_uq',\n expression:\n 'create unique index \"ai_chat_messages_tenant_org_conv_client_id_uq\" on \"ai_chat_messages\" (\"tenant_id\", \"organization_id\", \"conversation_id\", \"client_message_id\") where \"organization_id\" is not null and \"client_message_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_messages_tenant_conv_client_id_null_org_uq',\n expression:\n 'create unique index \"ai_chat_messages_tenant_conv_client_id_null_org_uq\" on \"ai_chat_messages\" (\"tenant_id\", \"conversation_id\", \"client_message_id\") where \"organization_id\" is null and \"client_message_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_messages_tenant_org_conv_created_idx',\n properties: ['tenantId', 'organizationId', 'conversationId', 'createdAt'],\n})\n@Index({\n name: 'ai_chat_messages_tenant_org_deleted_idx',\n properties: ['tenantId', 'organizationId', 'deletedAt'],\n})\nexport class AiChatMessage {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'clientMessageId'\n | 'uiParts'\n | 'attachmentIds'\n | 'filesMetadata'\n | 'model'\n | 'metadata'\n | 'createdByUserId'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'client_message_id', type: 'text', nullable: true })\n clientMessageId?: string | null\n\n @Property({ name: 'role', type: 'text' })\n role!: 'user' | 'assistant' | 'system'\n\n @Property({ name: 'content', type: 'text' })\n content!: string\n\n @Property({ name: 'ui_parts', type: 'jsonb', nullable: true })\n uiParts?: unknown[] | null\n\n @Property({ name: 'attachment_ids', type: 'jsonb', nullable: true })\n attachmentIds?: string[] | null\n\n @Property({ name: 'files_metadata', type: 'jsonb', nullable: true })\n filesMetadata?: Array<Record<string, unknown>> | null\n\n @Property({ name: 'model', type: 'text', nullable: true })\n model?: string | null\n\n @Property({ name: 'metadata', type: 'jsonb', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }