@burdenoff/microfe-botmanor 2026.1101.3 → 2026.1108.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AiOperationsPanel.js","names":[],"sources":["../../../src/botlit/components/AiOperationsPanel.tsx"],"sourcesContent":["/**\n * AI Operations Panel (BOFF-3839)\n * @module botlit/components\n *\n * The decision-card list at the heart of the supervisor feed. Rendered by the\n * workspace-wide /botmanor/ai page and, narrowed with `filter`, as a slice on\n * the agent and bot detail pages. Accept always confirms first and then\n * applies the recommendation through the existing mutation for the finding\n * type (rebuild index, pause agent) before marking the finding ACCEPTED;\n * findings without a safe one-click action are acknowledged with a deep link\n * to the subject. Dismiss records the signal and suppresses same-day\n * re-fires (fingerprint bucket, enforced server-side).\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { useCallback, useMemo, useState } from 'react';\nimport { useNavigate } from 'react-router';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Check, ShieldAlert, X } from 'lucide-react';\nimport {\n PauseBotmanorAgentForSupervisorDocument,\n RebuildKnowledgeBaseIndexForSupervisorDocument,\n type PauseBotmanorAgentForSupervisorMutation,\n type RebuildKnowledgeBaseIndexForSupervisorMutation,\n} from '../../generated/wspace-operations';\nimport { AiPredictionStatus } from '../../generated/wspace-types';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { cn } from '../utils/cn';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { Badge } from './Badge';\nimport { Button } from './Button';\nimport { Card, CardContent } from './Card';\nimport { EmptyState } from './EmptyState';\nimport { ErrorState } from './ErrorState';\nimport { useWorkspaceClient } from '../hooks/internal/workspaceGateway';\nimport {\n predictionSeverity,\n predictionSubjectName,\n useAiPredictions,\n useSetAiPredictionStatus,\n type AiPredictionRecord,\n type AiPredictionsFilter,\n} from '../hooks/useAiOperations';\n\nconst SEVERITY_VARIANTS: Record<\n string,\n 'default' | 'secondary' | 'warning' | 'destructive' | 'outline'\n> = {\n CRITICAL: 'destructive',\n WARNING: 'warning',\n INFO: 'secondary',\n};\n\nconst SEVERITY_LABEL_KEYS: Record<string, string> = {\n CRITICAL: 'botlit.aiOperations.severity.critical',\n WARNING: 'botlit.aiOperations.severity.warning',\n INFO: 'botlit.aiOperations.severity.info',\n};\n\nconst TYPE_LABEL_KEYS: Record<string, string> = {\n failure_rate_regression: 'botlit.aiOperations.type.failureRateRegression',\n grounding_decay: 'botlit.aiOperations.type.groundingDecay',\n cost_anomaly: 'botlit.aiOperations.type.costAnomaly',\n latency_drift: 'botlit.aiOperations.type.latencyDrift',\n stalled_index: 'botlit.aiOperations.type.stalledIndex',\n idle_agent: 'botlit.aiOperations.type.idleAgent',\n stale_knowledge: 'botlit.aiOperations.type.staleKnowledge',\n};\n\ninterface AcceptAction {\n /** Existing mutation that applies the recommendation. */\n kind: 'rebuild-index' | 'pause-agent';\n /** Dynamic confirmation copy. */\n confirmTitle: string;\n confirmBody: string;\n /** Fallback deep-link target when there is no one-click action. */\n acknowledgeOnly?: false;\n}\n\n/** Maps a finding to its Accept action, or null when Accept is not offered. */\nfunction acceptActionFor(\n record: AiPredictionRecord,\n t: ReturnType<typeof useTr>\n): AcceptAction | null {\n switch (record.predictionType) {\n case 'stalled_index':\n if (record.subjectType !== 'KNOWLEDGE_BASE' || !record.subjectId) return null;\n return {\n kind: 'rebuild-index',\n confirmTitle: t(\n 'botlit.aiOperations.confirm.rebuildTitle',\n 'Rebuild the knowledge base index?'\n ),\n confirmBody: t(\n 'botlit.aiOperations.confirm.rebuildBody',\n 'This rebuilds the index for this knowledge base so agents can retrieve from it again. The finding is marked accepted afterwards.'\n ),\n };\n case 'failure_rate_regression':\n case 'idle_agent':\n if (record.subjectType !== 'AGENT' || !record.subjectId) return null;\n return {\n kind: 'pause-agent',\n confirmTitle: t('botlit.aiOperations.confirm.pauseTitle', 'Pause this agent?'),\n confirmBody: t(\n 'botlit.aiOperations.confirm.pauseBody',\n 'The agent stops answering until a workspace member reactivates it. The finding is marked accepted afterwards.'\n ),\n };\n default:\n return null;\n }\n}\n\n/** Deep link to the subject for findings Accept cannot apply automatically. */\nfunction subjectLinkFor(record: AiPredictionRecord): string | null {\n if (!record.subjectId) return null;\n switch (record.subjectType) {\n case 'AGENT':\n return `/agents/${record.subjectId}`;\n case 'APP':\n return `/bots/${record.subjectId}`;\n case 'KNOWLEDGE_BASE':\n return `/knowledge/${record.subjectId}`;\n default:\n return null;\n }\n}\n\nfunction evidenceSummary(record: AiPredictionRecord): Array<[string, string]> {\n const features = record.features ?? {};\n const entries: Array<[string, string]> = [];\n const push = (key: string, value: unknown): void => {\n if (typeof value === 'number')\n entries.push([key, Number.isInteger(value) ? String(value) : value.toFixed(4)]);\n else if (typeof value === 'string' && value.length > 0 && value.length < 80)\n entries.push([key, value]);\n };\n for (const [key, value] of Object.entries(features).slice(0, 6)) {\n if (key.endsWith('At') || key === 'knowledgeBaseIds' || key === 'agentIds') continue;\n push(key, value);\n }\n return entries.slice(0, 4);\n}\n\ninterface DecisionCardProps {\n record: AiPredictionRecord;\n busy: boolean;\n onAccept: (record: AiPredictionRecord) => void;\n onDismiss: (record: AiPredictionRecord) => void;\n}\n\nconst DecisionCard: FC<DecisionCardProps> = ({ record, busy, onAccept, onDismiss }) => {\n const t = useTr();\n const navigate = useNavigate();\n const severity = predictionSeverity(record);\n const subjectName = predictionSubjectName(record);\n const action = record.status === 'GENERATED' ? acceptActionFor(record, t) : null;\n const subjectLink = subjectLinkFor(record);\n const evidence = evidenceSummary(record);\n const isOpen = record.status === 'GENERATED';\n\n return (\n <Card className={cn('p-5', severity === 'CRITICAL' && 'glow')} data-testid=\"ai-operations-card\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <Badge variant={SEVERITY_VARIANTS[severity] ?? 'secondary'}>\n {t(SEVERITY_LABEL_KEYS[severity] ?? SEVERITY_LABEL_KEYS.INFO, severity.toLowerCase())}\n </Badge>\n <Badge variant=\"outline\">\n {t(\n TYPE_LABEL_KEYS[record.predictionType] ?? 'botlit.aiOperations.type.unknown',\n record.predictionType.replace(/_/g, ' ')\n )}\n </Badge>\n <span className=\"text-sm text-text-secondary\">\n {t('botlit.aiOperations.onSubject', 'on {{name}}', { name: subjectName })}\n </span>\n </div>\n <span className=\"text-xs text-text-tertiary whitespace-nowrap\">\n {formatRelativeTime(record.generatedAt)}\n </span>\n </div>\n\n <p className=\"mt-3 text-sm text-text-primary\">{record.recommendation}</p>\n\n {evidence.length > 0 && (\n <dl className=\"mt-3 grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-4\">\n {evidence.map(([key, value]) => (\n <div key={key}>\n <dt className=\"text-xs text-text-tertiary\">{key}</dt>\n <dd className=\"text-sm text-text-secondary\">{value}</dd>\n </div>\n ))}\n </dl>\n )}\n\n {isOpen && (\n <div className=\"mt-4 flex items-center gap-2\">\n {action ? (\n <Button size=\"sm\" onClick={() => onAccept(record)} disabled={busy}>\n <Check className=\"h-4 w-4\" />\n {t('botlit.aiOperations.actions.accept', 'Accept')}\n </Button>\n ) : (\n subjectLink && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => navigate(subjectLink)}\n disabled={busy}\n >\n <Check className=\"h-4 w-4\" />\n {t('botlit.aiOperations.actions.reviewSubject', 'Review subject')}\n </Button>\n )\n )}\n <Button size=\"sm\" variant=\"outline\" onClick={() => onDismiss(record)} disabled={busy}>\n <X className=\"h-4 w-4\" />\n {t('botlit.aiOperations.actions.dismiss', 'Dismiss')}\n </Button>\n </div>\n )}\n {!isOpen && (\n <div className=\"mt-4\">\n <Badge variant={record.status === 'ACCEPTED' ? 'success' : 'outline'}>\n {record.status}\n </Badge>\n </div>\n )}\n </Card>\n );\n};\n\nexport interface AiOperationsPanelProps {\n /** Narrow the feed to one subject (agent detail / bot detail slices). */\n filter?: AiPredictionsFilter;\n title?: string;\n description?: string;\n className?: string;\n}\n\n/**\n * The decision-card feed. Pure presentation over `useAiPredictions` — the\n * owning page composes it with config and run controls.\n */\nexport const AiOperationsPanel: FC<AiOperationsPanelProps> = ({\n filter,\n title,\n description,\n className,\n}) => {\n const t = useTr();\n const client = useWorkspaceClient();\n const { data: records, loading, error, refetch } = useAiPredictions(filter);\n const [setStatus, setStatusState] = useSetAiPredictionStatus();\n const [pendingAccept, setPendingAccept] = useState<AiPredictionRecord | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n const busy = setStatusState.loading;\n\n const onDismiss = useCallback(\n async (record: AiPredictionRecord) => {\n setActionError(null);\n try {\n await setStatus({ id: record.id, status: AiPredictionStatus.Dismissed });\n await refetch();\n } catch (dismissError) {\n setActionError(dismissError instanceof Error ? dismissError.message : String(dismissError));\n }\n },\n [setStatus, refetch]\n );\n\n const applyAccept = useCallback(async () => {\n const record = pendingAccept;\n if (!record) return;\n setPendingAccept(null);\n setActionError(null);\n const action = acceptActionFor(record, t);\n try {\n if (action?.kind === 'rebuild-index' && record.subjectId) {\n await client.mutate<RebuildKnowledgeBaseIndexForSupervisorMutation>({\n mutation: RebuildKnowledgeBaseIndexForSupervisorDocument,\n variables: { knowledgeBaseId: record.subjectId },\n });\n } else if (action?.kind === 'pause-agent' && record.subjectId) {\n await client.mutate<PauseBotmanorAgentForSupervisorMutation>({\n mutation: PauseBotmanorAgentForSupervisorDocument,\n variables: { id: record.subjectId, input: { status: 'PAUSED' } },\n });\n }\n await setStatus({ id: record.id, status: AiPredictionStatus.Accepted });\n await refetch();\n } catch (acceptError) {\n setActionError(acceptError instanceof Error ? acceptError.message : String(acceptError));\n }\n }, [pendingAccept, client, setStatus, refetch, t]);\n\n const pendingAction = pendingAccept ? acceptActionFor(pendingAccept, t) : null;\n\n const content: ReactNode = useMemo(() => {\n if (error) {\n return (\n <ErrorState\n resource={t('botlit.aiOperations.errorTitle', 'AI operations findings')}\n error={error}\n onRetry={() => void refetch()}\n />\n );\n }\n if (loading && records.length === 0) {\n return (\n <div className=\"space-y-3\" aria-busy=\"true\">\n {[0, 1, 2].map((index) => (\n <Card key={index} className=\"p-5 h-28 animate-pulse bg-bg-subtle\">\n <span className=\"sr-only\">\n {t('botlit.aiOperations.loading', 'Loading findings')}\n </span>\n </Card>\n ))}\n </div>\n );\n }\n if (records.length === 0) {\n return (\n <EmptyState\n icon={<ShieldAlert className=\"h-8 w-8\" />}\n title={t('botlit.aiOperations.emptyTitle', 'No findings')}\n description={t(\n 'botlit.aiOperations.emptyDescription',\n 'The supervisor has not flagged anything. Enable the scheduled review to keep it that way.'\n )}\n />\n );\n }\n return (\n <div className=\"space-y-3\" data-testid=\"ai-operations-feed\">\n {records.map((record) => (\n <DecisionCard\n key={record.id}\n record={record}\n busy={busy}\n onAccept={(target) => setPendingAccept(target)}\n onDismiss={(target) => void onDismiss(target)}\n />\n ))}\n </div>\n );\n }, [error, loading, records, busy, onDismiss, refetch, t]);\n\n return (\n <section className={className} data-testid=\"ai-operations-panel\">\n {(title || description) && (\n <header className=\"mb-4\">\n {title && <h2 className=\"text-lg font-semibold text-text-primary\">{title}</h2>}\n {description && <p className=\"text-sm text-text-secondary\">{description}</p>}\n </header>\n )}\n {actionError && (\n <p className=\"mb-3 text-sm text-status-error-text\" role=\"alert\">\n {actionError}\n </p>\n )}\n {content}\n\n <AlertDialog\n open={pendingAccept != null}\n onOpenChange={(open) => !open && setPendingAccept(null)}\n >\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>{pendingAction?.confirmTitle}</AlertDialogTitle>\n <AlertDialogDescription>{pendingAction?.confirmBody}</AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>\n {t('botlit.aiOperations.actions.cancel', 'Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction onClick={() => void applyAccept()}>\n {t('botlit.aiOperations.actions.confirmAccept', 'Confirm')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </section>\n );\n};\n"],"mappings":"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"}
@@ -54,6 +54,6 @@ var o = ({ children: t, htmlFor: i, required: a, className: o }) => /* @__PURE__
54
54
  ]
55
55
  });
56
56
  //#endregion
57
- export { s as FormField, i as Input, a as Textarea };
57
+ export { s as FormField, i as Input, o as Label, a as Textarea };
58
58
 
59
59
  //# sourceMappingURL=Input.js.map
@@ -15,3 +15,4 @@ import "./useExecutions.js";
15
15
  import "./useBuckets.js";
16
16
  import "./useStore.js";
17
17
  import "./useUserPlatformConnection.js";
18
+ import "./useAiOperations.js";
@@ -1 +1 @@
1
- {"version":3,"file":"mutationInput.js","names":[],"sources":["../../../../src/botlit/hooks/internal/mutationInput.ts"],"sourcesContent":["/**\n * Mutation input primitives\n * @module botlit/hooks/internal\n *\n * GraphQL rejects an input object that carries a field its input type does not\n * declare, so a mutation payload must NEVER be assembled by spreading whatever\n * value the UI happens to be holding. An Apollo result carries `__typename`,\n * `id`, `revision` and the audit columns — no `Update*Input` on\n * wspace-botlit-svc accepts any of them, and sending one fails the whole write.\n *\n * `fieldsOf` records the allow-list once per input type and `buildMutationInput`\n * projects an arbitrary caller payload onto it. The `Record<keyof TInput, true>`\n * shape is what makes this safe over time: when the schema grows a field, the\n * allow-list stops compiling until it is declared here too.\n */\n\n/**\n * Widens one generated input field to the values the gateway really accepts.\n *\n * Two codegen artefacts are corrected here:\n * - Enums are emitted as real TypeScript enums (`Visibility.Private`), which a\n * plain `'PRIVATE'` is not assignable to. Widening them to their string\n * literals lets pages pass the values they already render in `<select>`\n * options without a cast.\n * - The `JSON` scalar is mapped to `Record<string, unknown>`, but a GraphQL\n * JSON scalar accepts arrays just as happily (`variables`, `entitlements`\n * and `exampleInputs` are all JSON arrays in practice).\n *\n * Arrays are widened element-wise, so an enum list such as\n * `Array<BotlitAgentCapability>` accepts `['MCP_TOOLS']`.\n */\ntype WidenValue<TValue> = TValue extends string\n ? `${TValue}`\n : TValue extends readonly (infer TItem)[]\n ? WidenValue<TItem>[]\n : TValue extends Record<string, unknown>\n ? TValue | unknown[]\n : TValue;\n\n/** Generated `*Input` type with its enum and JSON fields widened. */\nexport type GraphQLInput<TInput> = {\n [TKey in keyof TInput]: WidenValue<TInput[TKey]>;\n};\n\n/** The complete, compiler-checked field list of one GraphQL input type. */\nexport interface MutationInputFields<TInput> {\n readonly keys: readonly (keyof TInput)[];\n}\n\n/**\n * Declares the complete field list of a GraphQL input type.\n *\n * Every key of `TInput` must be present, so a schema field added upstream\n * surfaces as a compile error here instead of being silently dropped from\n * every mutation the hook sends.\n */\nexport function fieldsOf<TInput>(shape: Record<keyof TInput, true>): MutationInputFields<TInput> {\n return { keys: Object.keys(shape) as (keyof TInput)[] };\n}\n\n/**\n * Projects `input` onto the declared fields, dropping every key the input type\n * does not declare.\n *\n * `undefined` values are dropped (the caller left the field alone); `null` is\n * preserved because GraphQL treats it as an explicit \"clear this field\".\n */\nexport function buildMutationInput<TInput>(\n input: Partial<GraphQLInput<TInput>>,\n fields: MutationInputFields<TInput>\n): Partial<GraphQLInput<TInput>> {\n // Erased views: `TInput` is unresolved here, so the compiler cannot relate\n // `keyof TInput` to an index of the mapped type. The keys come from\n // `fieldsOf`, so every one of them is a real field of the input type.\n const source = input as Record<string, unknown>;\n const payload: Record<string, unknown> = {};\n\n for (const field of fields.keys) {\n const key = field as string;\n const value = source[key];\n if (value !== undefined) {\n payload[key] = value;\n }\n }\n\n return payload as Partial<GraphQLInput<TInput>>;\n}\n"],"mappings":";AAwDA,SAAgB,EAAiB,GAAgE;AAC/F,QAAO,EAAE,MAAM,OAAO,KAAK,EAAM,EAAsB;;AAUzD,SAAgB,EACd,GACA,GAC+B;CAI/B,IAAM,IAAS,GACT,IAAmC,EAAE;AAE3C,MAAK,IAAM,KAAS,EAAO,MAAM;EAC/B,IAAM,IAAM,GACN,IAAQ,EAAO;AACrB,EAAI,MAAU,KAAA,MACZ,EAAQ,KAAO;;AAInB,QAAO"}
1
+ {"version":3,"file":"mutationInput.js","names":[],"sources":["../../../../src/botlit/hooks/internal/mutationInput.ts"],"sourcesContent":["/**\n * Mutation input primitives\n * @module botlit/hooks/internal\n *\n * GraphQL rejects an input object that carries a field its input type does not\n * declare, so a mutation payload must NEVER be assembled by spreading whatever\n * value the UI happens to be holding. An Apollo result carries `__typename`,\n * `id`, `revision` and the audit columns — no `Update*Input` on\n * wspace-botlit-svc accepts any of them, and sending one fails the whole write.\n *\n * `fieldsOf` records the allow-list once per input type and `buildMutationInput`\n * projects an arbitrary caller payload onto it. The `Record<keyof TInput, true>`\n * shape is what makes this safe over time: when the schema grows a field, the\n * allow-list stops compiling until it is declared here too.\n */\n\n/**\n * Widens one generated input field to the values the gateway really accepts.\n *\n * Two codegen artefacts are corrected here:\n * - Enums are emitted as real TypeScript enums (`Visibility.Private`), which a\n * plain `'PRIVATE'` is not assignable to. Widening them to their string\n * literals lets pages pass the values they already render in `<select>`\n * options without a cast.\n * - The `JSON` scalar is mapped to `Record<string, unknown>`, but a GraphQL\n * JSON scalar accepts arrays just as happily (`variables`, `entitlements`\n * and `exampleInputs` are all JSON arrays in practice).\n *\n * Arrays are widened element-wise, so an enum list such as\n * `Array<BotmanorAgentCapability>` accepts `['MCP_TOOLS']`.\n */\ntype WidenValue<TValue> = TValue extends string\n ? `${TValue}`\n : TValue extends readonly (infer TItem)[]\n ? WidenValue<TItem>[]\n : TValue extends Record<string, unknown>\n ? TValue | unknown[]\n : TValue;\n\n/** Generated `*Input` type with its enum and JSON fields widened. */\nexport type GraphQLInput<TInput> = {\n [TKey in keyof TInput]: WidenValue<TInput[TKey]>;\n};\n\n/** The complete, compiler-checked field list of one GraphQL input type. */\nexport interface MutationInputFields<TInput> {\n readonly keys: readonly (keyof TInput)[];\n}\n\n/**\n * Declares the complete field list of a GraphQL input type.\n *\n * Every key of `TInput` must be present, so a schema field added upstream\n * surfaces as a compile error here instead of being silently dropped from\n * every mutation the hook sends.\n */\nexport function fieldsOf<TInput>(shape: Record<keyof TInput, true>): MutationInputFields<TInput> {\n return { keys: Object.keys(shape) as (keyof TInput)[] };\n}\n\n/**\n * Projects `input` onto the declared fields, dropping every key the input type\n * does not declare.\n *\n * `undefined` values are dropped (the caller left the field alone); `null` is\n * preserved because GraphQL treats it as an explicit \"clear this field\".\n */\nexport function buildMutationInput<TInput>(\n input: Partial<GraphQLInput<TInput>>,\n fields: MutationInputFields<TInput>\n): Partial<GraphQLInput<TInput>> {\n // Erased views: `TInput` is unresolved here, so the compiler cannot relate\n // `keyof TInput` to an index of the mapped type. The keys come from\n // `fieldsOf`, so every one of them is a real field of the input type.\n const source = input as Record<string, unknown>;\n const payload: Record<string, unknown> = {};\n\n for (const field of fields.keys) {\n const key = field as string;\n const value = source[key];\n if (value !== undefined) {\n payload[key] = value;\n }\n }\n\n return payload as Partial<GraphQLInput<TInput>>;\n}\n"],"mappings":";AAwDA,SAAgB,EAAiB,GAAgE;AAC/F,QAAO,EAAE,MAAM,OAAO,KAAK,EAAM,EAAsB;;AAUzD,SAAgB,EACd,GACA,GAC+B;CAI/B,IAAM,IAAS,GACT,IAAmC,EAAE;AAE3C,MAAK,IAAM,KAAS,EAAO,MAAM;EAC/B,IAAM,IAAM,GACN,IAAQ,EAAO;AACrB,EAAI,MAAU,KAAA,MACZ,EAAQ,KAAO;;AAInB,QAAO"}
@@ -5,8 +5,8 @@ import { gql as s } from "@apollo/client";
5
5
  import { useGatewayClient as c } from "@burdenoff/fe-libs/shared/graphql";
6
6
  //#region src/botlit/hooks/useAgents.ts
7
7
  var l = s`
8
- query ListAgents($filters: AgentFilterInput, $pagination: PaginationInput) {
9
- listAgents(filters: $filters, pagination: $pagination) {
8
+ query ListBotmanorAgents($filters: BotmanorAgentFilterInput, $pagination: PaginationInput) {
9
+ listBotmanorAgents(filters: $filters, pagination: $pagination) {
10
10
  id
11
11
  name
12
12
  slug
@@ -207,7 +207,7 @@ function b(t) {
207
207
  query: l,
208
208
  variables: g,
209
209
  fetchPolicy: "network-only"
210
- })).data?.listAgents ?? []);
210
+ })).data?.listBotmanorAgents ?? []);
211
211
  } catch (e) {
212
212
  h(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load agents"));
213
213
  } finally {
@@ -1 +1 @@
1
- {"version":3,"file":"useAgents.js","names":[],"sources":["../../../src/botlit/hooks/useAgents.ts"],"sourcesContent":["import { gql, type ApolloClient } from '@apollo/client';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\n\nimport type { UpdateBotmanorAgentInput } from '../../generated/wspace-types';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport type { BaseFilter } from '../types';\nimport { buildMutationInput, fieldsOf, type GraphQLInput } from './internal/mutationInput';\n\nconst LIST_AGENTS_DOCUMENT = gql`\n query ListAgents($filters: AgentFilterInput, $pagination: PaginationInput) {\n listAgents(filters: $filters, pagination: $pagination) {\n id\n name\n slug\n description\n type\n status\n visibility\n capabilities\n llmModelId\n bucketId\n executionCount\n lastExecutedAt\n specialization\n tagIds\n createdAt\n updatedAt\n createdById\n updatedById\n workspaceId\n }\n }\n`;\n\nconst GET_AGENT_DOCUMENT = gql`\n query GetBotmanorAgent($id: ID!) {\n getBotmanorAgent(id: $id) {\n id\n name\n slug\n description\n type\n status\n visibility\n capabilities\n llmModelId\n bucketId\n currentVersionId\n draftVersionId\n executionCount\n lastExecutedAt\n specialization\n systemPrompt\n temperature\n maxTokens\n maxConcurrentExecutions\n knowledgeBaseIds\n mcpConnectionIds\n workflowIds\n tagIds\n metadata\n createdAt\n updatedAt\n createdById\n updatedById\n workspaceId\n }\n }\n`;\n\nconst CREATE_AGENT_DOCUMENT = gql`\n mutation CreateBotmanorAgent($input: CreateBotmanorAgentInput!) {\n createBotmanorAgent(input: $input) {\n id\n name\n slug\n description\n type\n status\n visibility\n capabilities\n llmModelId\n systemPrompt\n temperature\n maxTokens\n maxConcurrentExecutions\n tagIds\n createdAt\n updatedAt\n workspaceId\n }\n }\n`;\n\nconst UPDATE_AGENT_DOCUMENT = gql`\n mutation UpdateBotmanorAgent($id: ID!, $input: UpdateBotmanorAgentInput!) {\n updateBotmanorAgent(id: $id, input: $input) {\n id\n name\n slug\n description\n type\n status\n visibility\n capabilities\n llmModelId\n systemPrompt\n temperature\n maxTokens\n maxConcurrentExecutions\n knowledgeBaseIds\n mcpConnectionIds\n workflowIds\n tagIds\n metadata\n createdAt\n updatedAt\n updatedById\n workspaceId\n }\n }\n`;\n\nconst DELETE_AGENT_DOCUMENT = gql`\n mutation DeleteBotmanorAgent($id: ID!) {\n deleteBotmanorAgent(id: $id)\n }\n`;\n\n// BOFF-4381: agent version history, publish, and rollback.\nconst LIST_AGENT_VERSIONS_DOCUMENT = gql`\n query ListAgentVersions($agentId: ID!, $pagination: PaginationInput) {\n listAgentVersions(agentId: $agentId, pagination: $pagination) {\n id\n agentId\n version\n status\n changelog\n config\n createdById\n createdAt\n publishedById\n publishedAt\n }\n }\n`;\n\nconst PUBLISH_AGENT_VERSION_DOCUMENT = gql`\n mutation PublishAgentVersion($agentId: ID!, $versionId: ID!, $changelog: String) {\n publishAgentVersion(agentId: $agentId, versionId: $versionId, changelog: $changelog) {\n id\n agentId\n version\n status\n changelog\n publishedById\n publishedAt\n }\n }\n`;\n\nconst ROLLBACK_AGENT_VERSION_DOCUMENT = gql`\n mutation RollbackAgentVersion($agentId: ID!, $targetVersionId: ID!) {\n rollbackAgentVersion(agentId: $agentId, targetVersionId: $targetVersionId) {\n id\n agentId\n version\n status\n changelog\n publishedById\n publishedAt\n }\n }\n`;\n\ntype WorkspaceClient = ApolloClient;\n\nexport interface AgentRecord {\n id: string;\n name: string;\n slug: string;\n description?: string | null;\n type: string;\n status: string;\n visibility?: string | null;\n capabilities?: string[] | null;\n llmModelId?: string | null;\n bucketId?: string | null;\n currentVersionId?: string | null;\n draftVersionId?: string | null;\n executionCount?: number | null;\n lastExecutedAt?: string | null;\n specialization?: string | null;\n systemPrompt?: string | null;\n temperature?: number | null;\n maxTokens?: number | null;\n maxConcurrentExecutions?: number | null;\n knowledgeBaseIds?: string[] | null;\n mcpConnectionIds?: string[] | null;\n workflowIds?: string[] | null;\n tagIds?: string[] | null;\n metadata?: Record<string, unknown> | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n createdById?: string | null;\n updatedById?: string | null;\n workspaceId?: string | null;\n}\n\ninterface ListAgentsData {\n listAgents: AgentRecord[];\n}\n\ninterface GetAgentData {\n getBotmanorAgent: AgentRecord | null;\n}\n\ninterface CreateAgentData {\n createBotmanorAgent: AgentRecord;\n}\n\ninterface UpdateAgentData {\n updateBotmanorAgent: AgentRecord;\n}\n\ninterface DeleteAgentData {\n deleteBotmanorAgent: boolean;\n}\n\nexport interface AgentVersionRecord {\n id: string;\n agentId: string;\n version: string;\n status: 'DRAFT' | 'PUBLISHED' | 'HISTORICAL';\n changelog?: string | null;\n config?: Record<string, unknown> | null;\n createdById?: string | null;\n createdAt?: string | null;\n publishedById?: string | null;\n publishedAt?: string | null;\n}\n\ninterface ListAgentVersionsData {\n listAgentVersions: AgentVersionRecord[];\n}\n\ninterface PublishAgentVersionData {\n publishAgentVersion: AgentVersionRecord;\n}\n\ninterface RollbackAgentVersionData {\n rollbackAgentVersion: AgentVersionRecord;\n}\n\ninterface AgentMutationState<T> {\n data: T | undefined;\n loading: boolean;\n error: Error | undefined;\n}\n\ninterface CreateAgentInput {\n workspaceId: string;\n name: string;\n slug?: string;\n description?: string;\n type: string;\n systemPrompt: string;\n temperature?: number;\n maxTokens?: number;\n capabilities?: string[];\n llmModelId?: string;\n}\n\ninterface UpdateAgentInput {\n agentId: string;\n input: GraphQLInput<UpdateBotmanorAgentInput>;\n}\n\nconst UPDATE_AGENT_FIELDS = fieldsOf<UpdateBotmanorAgentInput>({\n bucketId: true,\n capabilities: true,\n context: true,\n description: true,\n knowledgeBaseIds: true,\n llmModelId: true,\n maxConcurrentExecutions: true,\n maxTokens: true,\n mcpConnectionIds: true,\n metadata: true,\n name: true,\n slug: true,\n specialization: true,\n status: true,\n systemPrompt: true,\n tagIds: true,\n tags: true,\n temperature: true,\n type: true,\n visibility: true,\n workflowIds: true,\n});\n\nfunction getWorkspaceClient(client: unknown): WorkspaceClient {\n return client as WorkspaceClient;\n}\n\nfunction buildAgentFilter(\n workspaceId: string | undefined,\n filter?: BaseFilter\n): Record<string, unknown> | undefined {\n if (!workspaceId && !filter) return undefined;\n\n return {\n workspaceId,\n search: filter?.search,\n status: filter?.status?.[0],\n visibility: filter?.visibility?.[0],\n bucketId: filter?.bucketId,\n };\n}\n\nexport const agentKeys = {\n all: ['agents'] as const,\n lists: () => [...agentKeys.all, 'list'] as const,\n list: (filter?: BaseFilter) => [...agentKeys.lists(), filter] as const,\n details: () => [...agentKeys.all, 'detail'] as const,\n detail: (id: string) => [...agentKeys.details(), id] as const,\n};\n\nexport function useAgents(filter?: BaseFilter) {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const { workspaceId } = useBotlit();\n const [data, setData] = useState<AgentRecord[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n\n const variables = useMemo(\n () => ({\n filters: buildAgentFilter(workspaceId, filter),\n pagination: { limit: 100, offset: 0 },\n }),\n [filter, workspaceId]\n );\n\n const refetch = useCallback(async () => {\n if (!workspaceId) {\n setData([]);\n return;\n }\n\n setLoading(true);\n setError(undefined);\n try {\n const result = await client.query<ListAgentsData>({\n query: LIST_AGENTS_DOCUMENT,\n variables,\n fetchPolicy: 'network-only',\n });\n setData(result.data?.listAgents ?? []);\n } catch (queryError) {\n setError(queryError instanceof Error ? queryError : new Error('Failed to load agents'));\n } finally {\n setLoading(false);\n }\n }, [client, variables, workspaceId]);\n\n useEffect(() => {\n void refetch();\n }, [refetch]);\n\n return { data, loading, error, refetch };\n}\n\nexport function useAgent(agentId: string | undefined) {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [data, setData] = useState<AgentRecord | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n\n const refetch = useCallback(async () => {\n if (!agentId) {\n setData(null);\n return;\n }\n\n setLoading(true);\n setError(undefined);\n try {\n const result = await client.query<GetAgentData>({\n query: GET_AGENT_DOCUMENT,\n variables: { id: agentId },\n fetchPolicy: 'network-only',\n });\n setData(result.data?.getBotmanorAgent ?? null);\n } catch (queryError) {\n setError(queryError instanceof Error ? queryError : new Error('Failed to load agent'));\n } finally {\n setLoading(false);\n }\n }, [agentId, client]);\n\n useEffect(() => {\n void refetch();\n }, [refetch]);\n\n return { data, loading, error, refetch };\n}\n\nexport function useCreateAgent() {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [state, setState] = useState<AgentMutationState<AgentRecord>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const createAgent = useCallback(\n async (input: CreateAgentInput) => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<CreateAgentData>({\n mutation: CREATE_AGENT_DOCUMENT,\n variables: { input },\n });\n\n const createdAgent = result.data?.createBotmanorAgent;\n if (!createdAgent) {\n throw new Error('Failed to create agent');\n }\n\n setState({ data: createdAgent, loading: false, error: undefined });\n return createdAgent;\n } catch (mutationError) {\n const error =\n mutationError instanceof Error ? mutationError : new Error('Failed to create agent');\n setState({ data: undefined, loading: false, error });\n throw error;\n }\n },\n [client]\n );\n\n return [createAgent, state] as const;\n}\n\nexport function useUpdateAgent() {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [state, setState] = useState<AgentMutationState<AgentRecord>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const updateAgent = useCallback(\n async ({ agentId, input }: UpdateAgentInput) => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<UpdateAgentData>({\n mutation: UPDATE_AGENT_DOCUMENT,\n variables: { id: agentId, input: buildMutationInput(input, UPDATE_AGENT_FIELDS) },\n });\n\n const updatedAgent = result.data?.updateBotmanorAgent;\n if (!updatedAgent) {\n throw new Error('Failed to update agent');\n }\n\n setState({ data: updatedAgent, loading: false, error: undefined });\n return updatedAgent;\n } catch (mutationError) {\n const error =\n mutationError instanceof Error ? mutationError : new Error('Failed to update agent');\n setState({ data: undefined, loading: false, error });\n throw error;\n }\n },\n [client]\n );\n\n return [updateAgent, state] as const;\n}\n\nexport function useDeleteAgent() {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [state, setState] = useState<AgentMutationState<boolean>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const deleteAgent = useCallback(\n async (agentId: string) => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<DeleteAgentData>({\n mutation: DELETE_AGENT_DOCUMENT,\n variables: { id: agentId },\n });\n\n const deleted = result.data?.deleteBotmanorAgent ?? false;\n setState({ data: deleted, loading: false, error: undefined });\n return deleted;\n } catch (mutationError) {\n const error =\n mutationError instanceof Error ? mutationError : new Error('Failed to delete agent');\n setState({ data: undefined, loading: false, error });\n throw error;\n }\n },\n [client]\n );\n\n return [deleteAgent, state] as const;\n}\n\n// ============================================================================\n// VERSIONING (BOFF-4381) — version history, publish, rollback\n// ============================================================================\n\nexport function useAgentVersions(agentId: string | undefined) {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [data, setData] = useState<AgentVersionRecord[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n\n const refetch = useCallback(async () => {\n if (!agentId) {\n setData([]);\n return;\n }\n\n setLoading(true);\n setError(undefined);\n try {\n const result = await client.query<ListAgentVersionsData>({\n query: LIST_AGENT_VERSIONS_DOCUMENT,\n variables: { agentId, pagination: { limit: 50, offset: 0 } },\n fetchPolicy: 'network-only',\n });\n const versions = result.data?.listAgentVersions ?? [];\n // Newest first, regardless of what the server returned.\n setData(\n [...versions].sort((a, b) =>\n a.createdAt && b.createdAt ? b.createdAt.localeCompare(a.createdAt) : 0\n )\n );\n } catch (queryError) {\n setError(\n queryError instanceof Error ? queryError : new Error('Failed to load agent versions')\n );\n } finally {\n setLoading(false);\n }\n }, [agentId, client]);\n\n useEffect(() => {\n void refetch();\n }, [refetch]);\n\n return { data, loading, error, refetch };\n}\n\nexport function usePublishAgentVersion() {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [state, setState] = useState<AgentMutationState<AgentVersionRecord>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const publishAgentVersion = useCallback(\n async ({\n agentId,\n versionId,\n changelog,\n }: {\n agentId: string;\n versionId: string;\n changelog?: string;\n }) => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<PublishAgentVersionData>({\n mutation: PUBLISH_AGENT_VERSION_DOCUMENT,\n variables: { agentId, versionId, changelog: changelog?.trim() || undefined },\n });\n\n const published = result.data?.publishAgentVersion;\n if (!published) {\n throw new Error('Failed to publish agent version');\n }\n\n setState({ data: published, loading: false, error: undefined });\n return published;\n } catch (mutationError) {\n const error =\n mutationError instanceof Error\n ? mutationError\n : new Error('Failed to publish agent version');\n setState({ data: undefined, loading: false, error });\n throw error;\n }\n },\n [client]\n );\n\n return [publishAgentVersion, state] as const;\n}\n\nexport function useRollbackAgentVersion() {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [state, setState] = useState<AgentMutationState<AgentVersionRecord>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const rollbackAgentVersion = useCallback(\n async ({ agentId, targetVersionId }: { agentId: string; targetVersionId: string }) => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<RollbackAgentVersionData>({\n mutation: ROLLBACK_AGENT_VERSION_DOCUMENT,\n variables: { agentId, targetVersionId },\n });\n\n const rolledBack = result.data?.rollbackAgentVersion;\n if (!rolledBack) {\n throw new Error('Failed to roll back agent version');\n }\n\n setState({ data: rolledBack, loading: false, error: undefined });\n return rolledBack;\n } catch (mutationError) {\n const error =\n mutationError instanceof Error\n ? mutationError\n : new Error('Failed to roll back agent version');\n setState({ data: undefined, loading: false, error });\n throw error;\n }\n },\n [client]\n );\n\n return [rollbackAgentVersion, state] as const;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useAgents.js","names":[],"sources":["../../../src/botlit/hooks/useAgents.ts"],"sourcesContent":["import { gql, type ApolloClient } from '@apollo/client';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\n\nimport type { UpdateBotmanorAgentInput } from '../../generated/wspace-types';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport type { BaseFilter } from '../types';\nimport { buildMutationInput, fieldsOf, type GraphQLInput } from './internal/mutationInput';\n\nconst LIST_AGENTS_DOCUMENT = gql`\n query ListBotmanorAgents($filters: BotmanorAgentFilterInput, $pagination: PaginationInput) {\n listBotmanorAgents(filters: $filters, pagination: $pagination) {\n id\n name\n slug\n description\n type\n status\n visibility\n capabilities\n llmModelId\n bucketId\n executionCount\n lastExecutedAt\n specialization\n tagIds\n createdAt\n updatedAt\n createdById\n updatedById\n workspaceId\n }\n }\n`;\n\nconst GET_AGENT_DOCUMENT = gql`\n query GetBotmanorAgent($id: ID!) {\n getBotmanorAgent(id: $id) {\n id\n name\n slug\n description\n type\n status\n visibility\n capabilities\n llmModelId\n bucketId\n currentVersionId\n draftVersionId\n executionCount\n lastExecutedAt\n specialization\n systemPrompt\n temperature\n maxTokens\n maxConcurrentExecutions\n knowledgeBaseIds\n mcpConnectionIds\n workflowIds\n tagIds\n metadata\n createdAt\n updatedAt\n createdById\n updatedById\n workspaceId\n }\n }\n`;\n\nconst CREATE_AGENT_DOCUMENT = gql`\n mutation CreateBotmanorAgent($input: CreateBotmanorAgentInput!) {\n createBotmanorAgent(input: $input) {\n id\n name\n slug\n description\n type\n status\n visibility\n capabilities\n llmModelId\n systemPrompt\n temperature\n maxTokens\n maxConcurrentExecutions\n tagIds\n createdAt\n updatedAt\n workspaceId\n }\n }\n`;\n\nconst UPDATE_AGENT_DOCUMENT = gql`\n mutation UpdateBotmanorAgent($id: ID!, $input: UpdateBotmanorAgentInput!) {\n updateBotmanorAgent(id: $id, input: $input) {\n id\n name\n slug\n description\n type\n status\n visibility\n capabilities\n llmModelId\n systemPrompt\n temperature\n maxTokens\n maxConcurrentExecutions\n knowledgeBaseIds\n mcpConnectionIds\n workflowIds\n tagIds\n metadata\n createdAt\n updatedAt\n updatedById\n workspaceId\n }\n }\n`;\n\nconst DELETE_AGENT_DOCUMENT = gql`\n mutation DeleteBotmanorAgent($id: ID!) {\n deleteBotmanorAgent(id: $id)\n }\n`;\n\n// BOFF-4381: agent version history, publish, and rollback.\nconst LIST_AGENT_VERSIONS_DOCUMENT = gql`\n query ListAgentVersions($agentId: ID!, $pagination: PaginationInput) {\n listAgentVersions(agentId: $agentId, pagination: $pagination) {\n id\n agentId\n version\n status\n changelog\n config\n createdById\n createdAt\n publishedById\n publishedAt\n }\n }\n`;\n\nconst PUBLISH_AGENT_VERSION_DOCUMENT = gql`\n mutation PublishAgentVersion($agentId: ID!, $versionId: ID!, $changelog: String) {\n publishAgentVersion(agentId: $agentId, versionId: $versionId, changelog: $changelog) {\n id\n agentId\n version\n status\n changelog\n publishedById\n publishedAt\n }\n }\n`;\n\nconst ROLLBACK_AGENT_VERSION_DOCUMENT = gql`\n mutation RollbackAgentVersion($agentId: ID!, $targetVersionId: ID!) {\n rollbackAgentVersion(agentId: $agentId, targetVersionId: $targetVersionId) {\n id\n agentId\n version\n status\n changelog\n publishedById\n publishedAt\n }\n }\n`;\n\ntype WorkspaceClient = ApolloClient;\n\nexport interface AgentRecord {\n id: string;\n name: string;\n slug: string;\n description?: string | null;\n type: string;\n status: string;\n visibility?: string | null;\n capabilities?: string[] | null;\n llmModelId?: string | null;\n bucketId?: string | null;\n currentVersionId?: string | null;\n draftVersionId?: string | null;\n executionCount?: number | null;\n lastExecutedAt?: string | null;\n specialization?: string | null;\n systemPrompt?: string | null;\n temperature?: number | null;\n maxTokens?: number | null;\n maxConcurrentExecutions?: number | null;\n knowledgeBaseIds?: string[] | null;\n mcpConnectionIds?: string[] | null;\n workflowIds?: string[] | null;\n tagIds?: string[] | null;\n metadata?: Record<string, unknown> | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n createdById?: string | null;\n updatedById?: string | null;\n workspaceId?: string | null;\n}\n\ninterface ListBotmanorAgentsData {\n listBotmanorAgents: AgentRecord[];\n}\n\ninterface GetAgentData {\n getBotmanorAgent: AgentRecord | null;\n}\n\ninterface CreateAgentData {\n createBotmanorAgent: AgentRecord;\n}\n\ninterface UpdateAgentData {\n updateBotmanorAgent: AgentRecord;\n}\n\ninterface DeleteAgentData {\n deleteBotmanorAgent: boolean;\n}\n\nexport interface AgentVersionRecord {\n id: string;\n agentId: string;\n version: string;\n status: 'DRAFT' | 'PUBLISHED' | 'HISTORICAL';\n changelog?: string | null;\n config?: Record<string, unknown> | null;\n createdById?: string | null;\n createdAt?: string | null;\n publishedById?: string | null;\n publishedAt?: string | null;\n}\n\ninterface ListAgentVersionsData {\n listAgentVersions: AgentVersionRecord[];\n}\n\ninterface PublishAgentVersionData {\n publishAgentVersion: AgentVersionRecord;\n}\n\ninterface RollbackAgentVersionData {\n rollbackAgentVersion: AgentVersionRecord;\n}\n\ninterface AgentMutationState<T> {\n data: T | undefined;\n loading: boolean;\n error: Error | undefined;\n}\n\ninterface CreateAgentInput {\n workspaceId: string;\n name: string;\n slug?: string;\n description?: string;\n type: string;\n systemPrompt: string;\n temperature?: number;\n maxTokens?: number;\n capabilities?: string[];\n llmModelId?: string;\n}\n\ninterface UpdateAgentInput {\n agentId: string;\n input: GraphQLInput<UpdateBotmanorAgentInput>;\n}\n\nconst UPDATE_AGENT_FIELDS = fieldsOf<UpdateBotmanorAgentInput>({\n bucketId: true,\n capabilities: true,\n context: true,\n description: true,\n knowledgeBaseIds: true,\n llmModelId: true,\n maxConcurrentExecutions: true,\n maxTokens: true,\n mcpConnectionIds: true,\n metadata: true,\n name: true,\n slug: true,\n specialization: true,\n status: true,\n systemPrompt: true,\n tagIds: true,\n tags: true,\n temperature: true,\n type: true,\n visibility: true,\n workflowIds: true,\n});\n\nfunction getWorkspaceClient(client: unknown): WorkspaceClient {\n return client as WorkspaceClient;\n}\n\nfunction buildAgentFilter(\n workspaceId: string | undefined,\n filter?: BaseFilter\n): Record<string, unknown> | undefined {\n if (!workspaceId && !filter) return undefined;\n\n return {\n workspaceId,\n search: filter?.search,\n status: filter?.status?.[0],\n visibility: filter?.visibility?.[0],\n bucketId: filter?.bucketId,\n };\n}\n\nexport const agentKeys = {\n all: ['agents'] as const,\n lists: () => [...agentKeys.all, 'list'] as const,\n list: (filter?: BaseFilter) => [...agentKeys.lists(), filter] as const,\n details: () => [...agentKeys.all, 'detail'] as const,\n detail: (id: string) => [...agentKeys.details(), id] as const,\n};\n\nexport function useAgents(filter?: BaseFilter) {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const { workspaceId } = useBotlit();\n const [data, setData] = useState<AgentRecord[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n\n const variables = useMemo(\n () => ({\n filters: buildAgentFilter(workspaceId, filter),\n pagination: { limit: 100, offset: 0 },\n }),\n [filter, workspaceId]\n );\n\n const refetch = useCallback(async () => {\n if (!workspaceId) {\n setData([]);\n return;\n }\n\n setLoading(true);\n setError(undefined);\n try {\n const result = await client.query<ListBotmanorAgentsData>({\n query: LIST_AGENTS_DOCUMENT,\n variables,\n fetchPolicy: 'network-only',\n });\n setData(result.data?.listBotmanorAgents ?? []);\n } catch (queryError) {\n setError(queryError instanceof Error ? queryError : new Error('Failed to load agents'));\n } finally {\n setLoading(false);\n }\n }, [client, variables, workspaceId]);\n\n useEffect(() => {\n void refetch();\n }, [refetch]);\n\n return { data, loading, error, refetch };\n}\n\nexport function useAgent(agentId: string | undefined) {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [data, setData] = useState<AgentRecord | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n\n const refetch = useCallback(async () => {\n if (!agentId) {\n setData(null);\n return;\n }\n\n setLoading(true);\n setError(undefined);\n try {\n const result = await client.query<GetAgentData>({\n query: GET_AGENT_DOCUMENT,\n variables: { id: agentId },\n fetchPolicy: 'network-only',\n });\n setData(result.data?.getBotmanorAgent ?? null);\n } catch (queryError) {\n setError(queryError instanceof Error ? queryError : new Error('Failed to load agent'));\n } finally {\n setLoading(false);\n }\n }, [agentId, client]);\n\n useEffect(() => {\n void refetch();\n }, [refetch]);\n\n return { data, loading, error, refetch };\n}\n\nexport function useCreateAgent() {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [state, setState] = useState<AgentMutationState<AgentRecord>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const createAgent = useCallback(\n async (input: CreateAgentInput) => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<CreateAgentData>({\n mutation: CREATE_AGENT_DOCUMENT,\n variables: { input },\n });\n\n const createdAgent = result.data?.createBotmanorAgent;\n if (!createdAgent) {\n throw new Error('Failed to create agent');\n }\n\n setState({ data: createdAgent, loading: false, error: undefined });\n return createdAgent;\n } catch (mutationError) {\n const error =\n mutationError instanceof Error ? mutationError : new Error('Failed to create agent');\n setState({ data: undefined, loading: false, error });\n throw error;\n }\n },\n [client]\n );\n\n return [createAgent, state] as const;\n}\n\nexport function useUpdateAgent() {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [state, setState] = useState<AgentMutationState<AgentRecord>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const updateAgent = useCallback(\n async ({ agentId, input }: UpdateAgentInput) => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<UpdateAgentData>({\n mutation: UPDATE_AGENT_DOCUMENT,\n variables: { id: agentId, input: buildMutationInput(input, UPDATE_AGENT_FIELDS) },\n });\n\n const updatedAgent = result.data?.updateBotmanorAgent;\n if (!updatedAgent) {\n throw new Error('Failed to update agent');\n }\n\n setState({ data: updatedAgent, loading: false, error: undefined });\n return updatedAgent;\n } catch (mutationError) {\n const error =\n mutationError instanceof Error ? mutationError : new Error('Failed to update agent');\n setState({ data: undefined, loading: false, error });\n throw error;\n }\n },\n [client]\n );\n\n return [updateAgent, state] as const;\n}\n\nexport function useDeleteAgent() {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [state, setState] = useState<AgentMutationState<boolean>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const deleteAgent = useCallback(\n async (agentId: string) => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<DeleteAgentData>({\n mutation: DELETE_AGENT_DOCUMENT,\n variables: { id: agentId },\n });\n\n const deleted = result.data?.deleteBotmanorAgent ?? false;\n setState({ data: deleted, loading: false, error: undefined });\n return deleted;\n } catch (mutationError) {\n const error =\n mutationError instanceof Error ? mutationError : new Error('Failed to delete agent');\n setState({ data: undefined, loading: false, error });\n throw error;\n }\n },\n [client]\n );\n\n return [deleteAgent, state] as const;\n}\n\n// ============================================================================\n// VERSIONING (BOFF-4381) — version history, publish, rollback\n// ============================================================================\n\nexport function useAgentVersions(agentId: string | undefined) {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [data, setData] = useState<AgentVersionRecord[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n\n const refetch = useCallback(async () => {\n if (!agentId) {\n setData([]);\n return;\n }\n\n setLoading(true);\n setError(undefined);\n try {\n const result = await client.query<ListAgentVersionsData>({\n query: LIST_AGENT_VERSIONS_DOCUMENT,\n variables: { agentId, pagination: { limit: 50, offset: 0 } },\n fetchPolicy: 'network-only',\n });\n const versions = result.data?.listAgentVersions ?? [];\n // Newest first, regardless of what the server returned.\n setData(\n [...versions].sort((a, b) =>\n a.createdAt && b.createdAt ? b.createdAt.localeCompare(a.createdAt) : 0\n )\n );\n } catch (queryError) {\n setError(\n queryError instanceof Error ? queryError : new Error('Failed to load agent versions')\n );\n } finally {\n setLoading(false);\n }\n }, [agentId, client]);\n\n useEffect(() => {\n void refetch();\n }, [refetch]);\n\n return { data, loading, error, refetch };\n}\n\nexport function usePublishAgentVersion() {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [state, setState] = useState<AgentMutationState<AgentVersionRecord>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const publishAgentVersion = useCallback(\n async ({\n agentId,\n versionId,\n changelog,\n }: {\n agentId: string;\n versionId: string;\n changelog?: string;\n }) => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<PublishAgentVersionData>({\n mutation: PUBLISH_AGENT_VERSION_DOCUMENT,\n variables: { agentId, versionId, changelog: changelog?.trim() || undefined },\n });\n\n const published = result.data?.publishAgentVersion;\n if (!published) {\n throw new Error('Failed to publish agent version');\n }\n\n setState({ data: published, loading: false, error: undefined });\n return published;\n } catch (mutationError) {\n const error =\n mutationError instanceof Error\n ? mutationError\n : new Error('Failed to publish agent version');\n setState({ data: undefined, loading: false, error });\n throw error;\n }\n },\n [client]\n );\n\n return [publishAgentVersion, state] as const;\n}\n\nexport function useRollbackAgentVersion() {\n const client = getWorkspaceClient(useGatewayClient('workspace'));\n const [state, setState] = useState<AgentMutationState<AgentVersionRecord>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const rollbackAgentVersion = useCallback(\n async ({ agentId, targetVersionId }: { agentId: string; targetVersionId: string }) => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<RollbackAgentVersionData>({\n mutation: ROLLBACK_AGENT_VERSION_DOCUMENT,\n variables: { agentId, targetVersionId },\n });\n\n const rolledBack = result.data?.rollbackAgentVersion;\n if (!rolledBack) {\n throw new Error('Failed to roll back agent version');\n }\n\n setState({ data: rolledBack, loading: false, error: undefined });\n return rolledBack;\n } catch (mutationError) {\n const error =\n mutationError instanceof Error\n ? mutationError\n : new Error('Failed to roll back agent version');\n setState({ data: undefined, loading: false, error });\n throw error;\n }\n },\n [client]\n );\n\n return [rollbackAgentVersion, state] as const;\n}\n"],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ import { ConfigureSupervisorDocument as e, GetSupervisorConfigDocument as t, ListAiPredictionsDocument as n, ListSupervisorRunsDocument as r, RunSupervisorNowDocument as i, SetAiPredictionStatusDocument as a } from "../../generated/wspace-operations.js";
2
+ import { useWorkspaceId as o, useWorkspaceMutation as s, useWorkspaceQuery as c } from "./internal/workspaceGateway.js";
3
+ import { useMemo as l } from "react";
4
+ //#region src/botlit/hooks/useAiOperations.ts
5
+ var u = 50, d = [], f = [];
6
+ function p(e) {
7
+ let t = o(), { subjectType: r, subjectId: i, status: a } = e ?? {};
8
+ return c({
9
+ document: n,
10
+ variables: l(() => {
11
+ let e = { sourceProduct: "botmanor" };
12
+ return r && (e.subjectType = r), i && (e.subjectId = i), a && (e.status = a), {
13
+ filter: e,
14
+ pagination: {
15
+ limit: u,
16
+ offset: 0
17
+ }
18
+ };
19
+ }, [
20
+ r,
21
+ i,
22
+ a
23
+ ]),
24
+ enabled: !!t,
25
+ errorMessage: "Failed to load AI operations findings.",
26
+ fallback: d,
27
+ select: (e) => (e?.aiPredictions.items ?? []).map((e) => ({
28
+ id: e.id,
29
+ predictionType: e.predictionType,
30
+ subjectType: e.subjectType ?? null,
31
+ subjectId: e.subjectId ?? null,
32
+ score: e.score,
33
+ confidence: e.confidence,
34
+ recommendation: e.recommendation,
35
+ status: e.status,
36
+ features: e.features ?? null,
37
+ metadata: e.metadata ?? null,
38
+ generatedAt: e.generatedAt
39
+ }))
40
+ });
41
+ }
42
+ function m() {
43
+ return s({
44
+ document: a,
45
+ variables: (e) => ({
46
+ id: e.id,
47
+ status: e.status
48
+ }),
49
+ select: (e) => {
50
+ let t = e?.setAiPredictionStatus;
51
+ return t ? {
52
+ id: t.id,
53
+ status: t.status
54
+ } : void 0;
55
+ },
56
+ errorMessage: "Failed to update the finding."
57
+ });
58
+ }
59
+ function h() {
60
+ return c({
61
+ document: t,
62
+ variables: {},
63
+ enabled: !!o(),
64
+ errorMessage: "Failed to load the supervisor configuration.",
65
+ fallback: void 0,
66
+ select: (e) => {
67
+ let t = e?.supervisorConfig;
68
+ if (t) return {
69
+ enabled: t.enabled,
70
+ cron: t.cron,
71
+ timezone: t.timezone,
72
+ lastRunAt: t.lastRunAt ?? null,
73
+ updatedAt: t.updatedAt
74
+ };
75
+ }
76
+ });
77
+ }
78
+ function g() {
79
+ return s({
80
+ document: e,
81
+ variables: (e) => ({ input: e }),
82
+ select: (e) => {
83
+ let t = e?.configureSupervisor;
84
+ if (t) return {
85
+ enabled: t.enabled,
86
+ cron: t.cron,
87
+ timezone: t.timezone,
88
+ lastRunAt: t.lastRunAt ?? null,
89
+ updatedAt: t.updatedAt
90
+ };
91
+ },
92
+ errorMessage: "Failed to save the supervisor configuration."
93
+ });
94
+ }
95
+ function _() {
96
+ return s({
97
+ document: i,
98
+ variables: () => ({}),
99
+ select: (e) => {
100
+ let t = e?.runSupervisorNow;
101
+ if (!t) return;
102
+ let n = t.run;
103
+ return {
104
+ findings: t.findings,
105
+ run: n ? {
106
+ id: n.id,
107
+ trigger: n.trigger,
108
+ status: n.status,
109
+ findings: n.findings,
110
+ notified: n.notified,
111
+ error: n.error ?? null,
112
+ startedAt: n.startedAt,
113
+ completedAt: n.completedAt ?? null
114
+ } : null
115
+ };
116
+ },
117
+ errorMessage: "Failed to run the supervisor review."
118
+ });
119
+ }
120
+ function v() {
121
+ return c({
122
+ document: r,
123
+ variables: { pagination: {
124
+ limit: 20,
125
+ offset: 0
126
+ } },
127
+ enabled: !!o(),
128
+ errorMessage: "Failed to load the supervisor run history.",
129
+ fallback: f,
130
+ select: (e) => (e?.supervisorRuns.items ?? []).map((e) => ({
131
+ id: e.id,
132
+ trigger: e.trigger,
133
+ status: e.status,
134
+ findings: e.findings,
135
+ notified: e.notified,
136
+ error: e.error ?? null,
137
+ startedAt: e.startedAt,
138
+ completedAt: e.completedAt ?? null
139
+ }))
140
+ });
141
+ }
142
+ function y(e) {
143
+ let t = e.metadata?.severity;
144
+ return typeof t == "string" ? t : "INFO";
145
+ }
146
+ function b(e) {
147
+ let t = e.metadata?.subjectName;
148
+ return typeof t == "string" && t.length > 0 ? t : e.subjectId ?? e.predictionType;
149
+ }
150
+ //#endregion
151
+ export { y as predictionSeverity, b as predictionSubjectName, p as useAiPredictions, g as useConfigureSupervisor, _ as useRunSupervisorNow, m as useSetAiPredictionStatus, h as useSupervisorConfig, v as useSupervisorRuns };
152
+
153
+ //# sourceMappingURL=useAiOperations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAiOperations.js","names":[],"sources":["../../../src/botlit/hooks/useAiOperations.ts"],"sourcesContent":["/**\n * AI Operations hooks (BOFF-3839)\n * @module botlit/hooks\n *\n * Backed by the supervisor surface on wspace-botmanor-svc: the AiPrediction\n * feed (findings as decision cards), the supervisor configuration, run-now\n * and the run history. Read conventions come from `useExecutions`\n * (network-only, explicit error state, caller-driven refetch).\n */\n\nimport { useMemo } from 'react';\nimport {\n ConfigureSupervisorDocument,\n GetSupervisorConfigDocument,\n ListAiPredictionsDocument,\n ListSupervisorRunsDocument,\n RunSupervisorNowDocument,\n SetAiPredictionStatusDocument,\n type ConfigureSupervisorMutation,\n type ConfigureSupervisorMutationVariables,\n type GetSupervisorConfigQuery,\n type ListAiPredictionsQuery,\n type ListSupervisorRunsQuery,\n type RunSupervisorNowMutation,\n type SetAiPredictionStatusMutation,\n type SetAiPredictionStatusMutationVariables,\n} from '../../generated/wspace-operations';\nimport type {\n AiPredictionFilterInput,\n AiPredictionStatus,\n ConfigureSupervisorInput,\n} from '../../generated/wspace-types';\nimport {\n useWorkspaceId,\n useWorkspaceMutation,\n useWorkspaceQuery,\n type QueryResult,\n} from './internal/workspaceGateway';\n\nconst LIST_LIMIT = 50;\n\nexport interface AiPredictionRecord {\n id: string;\n predictionType: string;\n subjectType: string | null;\n subjectId: string | null;\n score: number;\n confidence: number;\n recommendation: string;\n status: string;\n features: Record<string, unknown> | null;\n /** Supervisor metadata: fingerprint, severity, subjectName, runId. */\n metadata: Record<string, unknown> | null;\n generatedAt: string;\n}\n\nexport interface AiPredictionsFilter {\n subjectType?: string;\n subjectId?: string;\n status?: string;\n}\n\nexport interface SupervisorConfigRecord {\n enabled: boolean;\n cron: string;\n timezone: string;\n lastRunAt: string | null;\n updatedAt: string;\n}\n\nexport interface SupervisorRunRecord {\n id: string;\n trigger: string;\n status: string;\n findings: number;\n notified: number;\n error: string | null;\n startedAt: string;\n completedAt: string | null;\n}\n\nconst NO_PREDICTIONS: AiPredictionRecord[] = [];\nconst NO_RUNS: SupervisorRunRecord[] = [];\n\nexport const aiOperationsKeys = {\n all: ['ai-operations'] as const,\n predictions: (filter?: AiPredictionsFilter) =>\n [...aiOperationsKeys.all, 'predictions', filter] as const,\n config: () => [...aiOperationsKeys.all, 'config'] as const,\n runs: () => [...aiOperationsKeys.all, 'runs'] as const,\n};\n\n/** Decision-card feed, optionally narrowed to one subject (agent/app/KB). */\nexport function useAiPredictions(filter?: AiPredictionsFilter): QueryResult<AiPredictionRecord[]> {\n const workspaceId = useWorkspaceId();\n const { subjectType, subjectId, status } = filter ?? {};\n\n const variables = useMemo(() => {\n const gqlFilter: AiPredictionFilterInput = { sourceProduct: 'botmanor' };\n if (subjectType) gqlFilter.subjectType = subjectType;\n if (subjectId) gqlFilter.subjectId = subjectId;\n if (status) gqlFilter.status = status as AiPredictionStatus;\n return { filter: gqlFilter, pagination: { limit: LIST_LIMIT, offset: 0 } };\n }, [subjectType, subjectId, status]);\n\n return useWorkspaceQuery<ListAiPredictionsQuery, AiPredictionRecord[]>({\n document: ListAiPredictionsDocument,\n variables,\n enabled: !!workspaceId,\n errorMessage: 'Failed to load AI operations findings.',\n fallback: NO_PREDICTIONS,\n select: (data) =>\n (data?.aiPredictions.items ?? []).map((item) => ({\n id: item.id,\n predictionType: item.predictionType,\n subjectType: item.subjectType ?? null,\n subjectId: item.subjectId ?? null,\n score: item.score,\n confidence: item.confidence,\n recommendation: item.recommendation,\n status: item.status,\n features: (item.features ?? null) as Record<string, unknown> | null,\n metadata: (item.metadata ?? null) as Record<string, unknown> | null,\n generatedAt: item.generatedAt,\n })),\n });\n}\n\n/** Accept / dismiss one finding. Callers refetch the feed afterwards. */\nexport function useSetAiPredictionStatus(): readonly [\n (input: { id: string; status: AiPredictionStatus }) => Promise<{ id: string; status: string }>,\n { data: { id: string; status: string } | undefined; loading: boolean; error: Error | undefined },\n] {\n return useWorkspaceMutation<\n SetAiPredictionStatusMutation,\n { id: string; status: AiPredictionStatus },\n { id: string; status: string }\n >({\n document: SetAiPredictionStatusDocument,\n variables: (input) =>\n ({ id: input.id, status: input.status }) as SetAiPredictionStatusMutationVariables,\n select: (data) => {\n const row = data?.setAiPredictionStatus;\n return row ? { id: row.id, status: row.status } : undefined;\n },\n errorMessage: 'Failed to update the finding.',\n });\n}\n\nexport function useSupervisorConfig(): QueryResult<SupervisorConfigRecord | undefined> {\n const workspaceId = useWorkspaceId();\n return useWorkspaceQuery<GetSupervisorConfigQuery, SupervisorConfigRecord | undefined>({\n document: GetSupervisorConfigDocument,\n variables: {},\n enabled: !!workspaceId,\n errorMessage: 'Failed to load the supervisor configuration.',\n fallback: undefined,\n select: (data) => {\n const config = data?.supervisorConfig;\n if (!config) return undefined;\n return {\n enabled: config.enabled,\n cron: config.cron,\n timezone: config.timezone,\n lastRunAt: config.lastRunAt ?? null,\n updatedAt: config.updatedAt,\n };\n },\n });\n}\n\nexport function useConfigureSupervisor(): readonly [\n (input: {\n enabled?: boolean;\n cron?: string;\n timezone?: string;\n }) => Promise<SupervisorConfigRecord>,\n { data: SupervisorConfigRecord | undefined; loading: boolean; error: Error | undefined },\n] {\n return useWorkspaceMutation<\n ConfigureSupervisorMutation,\n ConfigureSupervisorInput,\n SupervisorConfigRecord\n >({\n document: ConfigureSupervisorDocument,\n variables: (input) => ({ input }) as ConfigureSupervisorMutationVariables,\n select: (data) => {\n const config = data?.configureSupervisor;\n if (!config) return undefined;\n return {\n enabled: config.enabled,\n cron: config.cron,\n timezone: config.timezone,\n lastRunAt: config.lastRunAt ?? null,\n updatedAt: config.updatedAt,\n };\n },\n errorMessage: 'Failed to save the supervisor configuration.',\n });\n}\n\nexport interface RunSupervisorNowResult {\n run: SupervisorRunRecord | null;\n findings: number;\n}\n\n/** Manual fleet review (the scheduled path is the FluidGrids cron tick). */\nexport function useRunSupervisorNow(): readonly [\n () => Promise<RunSupervisorNowResult>,\n { data: RunSupervisorNowResult | undefined; loading: boolean; error: Error | undefined },\n] {\n return useWorkspaceMutation<RunSupervisorNowMutation, void, RunSupervisorNowResult>({\n document: RunSupervisorNowDocument,\n variables: () => ({}),\n select: (data) => {\n const result = data?.runSupervisorNow;\n if (!result) return undefined;\n const run = result.run;\n return {\n findings: result.findings,\n run: run\n ? {\n id: run.id,\n trigger: run.trigger,\n status: run.status,\n findings: run.findings,\n notified: run.notified,\n error: run.error ?? null,\n startedAt: run.startedAt,\n completedAt: run.completedAt ?? null,\n }\n : null,\n };\n },\n errorMessage: 'Failed to run the supervisor review.',\n });\n}\n\nexport function useSupervisorRuns(): QueryResult<SupervisorRunRecord[]> {\n const workspaceId = useWorkspaceId();\n return useWorkspaceQuery<ListSupervisorRunsQuery, SupervisorRunRecord[]>({\n document: ListSupervisorRunsDocument,\n variables: { pagination: { limit: 20, offset: 0 } },\n enabled: !!workspaceId,\n errorMessage: 'Failed to load the supervisor run history.',\n fallback: NO_RUNS,\n select: (data) =>\n (data?.supervisorRuns.items ?? []).map((run) => ({\n id: run.id,\n trigger: run.trigger,\n status: run.status,\n findings: run.findings,\n notified: run.notified,\n error: run.error ?? null,\n startedAt: run.startedAt,\n completedAt: run.completedAt ?? null,\n })),\n });\n}\n\n/** Severity from supervisor metadata (WARNING/CRITICAL/INFO), defaulting to INFO. */\nexport function predictionSeverity(record: AiPredictionRecord): string {\n const severity = record.metadata?.['severity'];\n return typeof severity === 'string' ? severity : 'INFO';\n}\n\n/** Human name the supervisor recorded for the subject, when present. */\nexport function predictionSubjectName(record: AiPredictionRecord): string {\n const name = record.metadata?.['subjectName'];\n if (typeof name === 'string' && name.length > 0) return name;\n return record.subjectId ?? record.predictionType;\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { useBotlit as e } from "../providers/BotlitProvider.js";
2
2
  import { buildMutationInput as t, fieldsOf as n } from "./internal/mutationInput.js";
3
- import { CreateBotmanorLlmModelDocument as r, CreateBotmanorLlmProviderDocument as i, ListLlmModelsDocument as a, ListLlmProvidersDocument as o, UpdateLlmProviderDocument as s } from "../../generated/wspace-operations.js";
3
+ import { CreateBotmanorLlmModelDocument as r, CreateBotmanorLlmProviderDocument as i, ListBotmanorLlmModelsDocument as a, ListBotmanorLlmProvidersDocument as o, UpdateBotmanorLlmProviderDocument as s } from "../../generated/wspace-operations.js";
4
4
  import { useWorkspaceClient as c, useWorkspaceId as l, useWorkspaceMutation as u } from "./internal/workspaceGateway.js";
5
5
  import { useCallback as d } from "react";
6
6
  import { useQuery as f } from "@tanstack/react-query";
@@ -64,10 +64,10 @@ function v(t, n, r, i, a) {
64
64
  };
65
65
  }
66
66
  function y() {
67
- return v(o, "providers", (e) => e?.listLLMProviders ?? m, m);
67
+ return v(o, "providers", (e) => e?.listBotmanorLLMProviders ?? m, m);
68
68
  }
69
69
  function b(e) {
70
- return v(a, "models", (e) => e?.listLLMModels ?? h, h, e?.providerId);
70
+ return v(a, "models", (e) => e?.listBotmanorLLMModels ?? h, h, e?.providerId);
71
71
  }
72
72
  function x() {
73
73
  let e = l(), [n, r] = u({
@@ -84,7 +84,7 @@ function x() {
84
84
  id: e,
85
85
  input: t(n, _)
86
86
  }),
87
- select: (e) => e?.updateLLMProvider,
87
+ select: (e) => e?.updateBotmanorLLMProvider,
88
88
  errorMessage: "Failed to update the LLM provider"
89
89
  });
90
90
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"useLLMProviders.js","names":[],"sources":["../../../src/botlit/hooks/useLLMProviders.ts"],"sourcesContent":["/**\n * LLM Providers Hooks\n * @module botlit/hooks\n *\n * These go through the shell's workspace gateway client like every other BotManor\n * hook. They deliberately do NOT use the generated `useQuery`/`useMutation`\n * wrappers: `BotmanorRoot` only mounts an `<ApolloProvider>` in standalone mode,\n * so an Apollo React hook throws \"Could not find client in the context\" the\n * moment the MFE is mounted by an app shell — which is every production route.\n */\n\nimport { useCallback, useMemo } from 'react';\nimport type { DocumentNode } from 'graphql';\nimport { useQuery } from '@tanstack/react-query';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport {\n CreateBotmanorLlmProviderDocument,\n CreateBotmanorLlmModelDocument,\n DeleteLlmProviderDocument,\n GetLlmProviderDocument,\n ListLlmModelsDocument,\n ListLlmProvidersDocument,\n TestLlmConnectionDocument,\n UpdateLlmProviderDocument,\n type CreateBotmanorLlmProviderMutation,\n type CreateBotmanorLlmModelMutation,\n type DeleteLlmProviderMutation,\n type GetLlmProviderQuery,\n type ListLlmModelsQuery,\n type ListLlmProvidersQuery,\n type TestLlmConnectionMutation,\n type UpdateLlmProviderMutation,\n} from '../../generated/wspace-operations';\nimport type {\n CreateBotmanorLlmModelInput,\n CreateBotmanorLlmProviderInput,\n UpdateBotlitLlmProviderInput,\n} from '../../generated/wspace-types';\nimport { buildMutationInput, fieldsOf, type GraphQLInput } from './internal/mutationInput';\nimport {\n useWorkspaceId,\n useWorkspaceClient,\n useWorkspaceMutation,\n useWorkspaceQuery,\n type QueryResult,\n} from './internal/workspaceGateway';\n\nconst LIST_LIMIT = 50;\n\nexport interface LLMProviderRecord {\n id: string;\n name: string;\n type: string;\n isActive: boolean;\n apiEndpoint?: string | null;\n credentialsHash?: string | null;\n connectionId?: string | null;\n metadata?: Record<string, unknown> | null;\n createdAt: string;\n updatedAt: string;\n workspaceId: string;\n}\n\nexport interface LLMModelRecord {\n id: string;\n name: string;\n modelId: string;\n providerId: string;\n contextWindow: number;\n maxOutputTokens: number;\n inputPricePerMToken: number;\n outputPricePerMToken: number;\n isActive: boolean;\n supportsStreaming: boolean;\n supportsFunctionCalling: boolean;\n supportsVision: boolean;\n metadata?: Record<string, unknown> | null;\n createdAt: string;\n updatedAt: string;\n}\n\n/** `CreateBotmanorLLMProviderInput` minus the `workspaceId` the hook supplies. */\nexport type ConfigureLLMProviderVariables = Omit<\n GraphQLInput<CreateBotmanorLlmProviderInput>,\n 'workspaceId'\n> & { isActive?: boolean };\n\nconst NO_PROVIDERS: LLMProviderRecord[] = [];\nconst NO_MODELS: LLMModelRecord[] = [];\n\nconst CREATE_PROVIDER_FIELDS = fieldsOf<CreateBotmanorLlmProviderInput>({\n apiEndpoint: true,\n connectionId: true,\n credentials: true,\n metadata: true,\n name: true,\n type: true,\n workspaceId: true,\n});\n\nconst UPDATE_PROVIDER_FIELDS = fieldsOf<UpdateBotlitLlmProviderInput>({\n apiEndpoint: true,\n connectionId: true,\n credentials: true,\n isActive: true,\n metadata: true,\n name: true,\n});\n\nexport const llmProviderKeys = {\n all: ['llmProviders'] as const,\n lists: () => [...llmProviderKeys.all, 'list'] as const,\n details: () => [...llmProviderKeys.all, 'detail'] as const,\n detail: (id: string) => [...llmProviderKeys.details(), id] as const,\n};\n\nfunction useLLMList<TData, TRecord>(\n document: DocumentNode,\n kind: string,\n select: (data: TData | undefined) => TRecord[],\n fallback: TRecord[],\n providerId?: string\n): QueryResult<TRecord[]> {\n const client = useWorkspaceClient();\n const { workspaceId, currentUser } = useBotlit();\n const query = useQuery({\n queryKey: ['botmanor-llm-catalog', workspaceId, currentUser?.id, kind, providerId],\n enabled: Boolean(workspaceId),\n retry: false,\n queryFn: async () => {\n const records: TRecord[] = [];\n for (let offset = 0; offset < 10000; offset += LIST_LIMIT) {\n const result = await client.query<TData>({\n query: document,\n fetchPolicy: 'network-only',\n variables: {\n filters: providerId ? { providerId } : undefined,\n pagination: { limit: LIST_LIMIT, offset },\n },\n });\n if (!result.data) throw new Error('Model catalog unavailable');\n const page = select(result.data);\n if (!Array.isArray(page) || page.length > LIST_LIMIT)\n throw new Error('Model catalog unavailable');\n records.push(...page);\n if (page.length < LIST_LIMIT) return records;\n }\n throw new Error('Model catalog exceeds the supported limit');\n },\n });\n return {\n data: query.data ?? fallback,\n loading: query.isFetching,\n error: query.error ?? undefined,\n refetch: async () => {\n await query.refetch();\n },\n };\n}\n\nexport function useLLMProviders(): QueryResult<LLMProviderRecord[]> {\n return useLLMList<ListLlmProvidersQuery, LLMProviderRecord>(\n ListLlmProvidersDocument,\n 'providers',\n (data) => data?.listLLMProviders ?? NO_PROVIDERS,\n NO_PROVIDERS\n );\n}\n\nexport function useLLMProvider(\n providerId: string | undefined\n): QueryResult<LLMProviderRecord | null> {\n const variables = useMemo(() => ({ id: providerId ?? '' }), [providerId]);\n\n return useWorkspaceQuery<GetLlmProviderQuery, LLMProviderRecord | null>({\n document: GetLlmProviderDocument,\n variables,\n select: (data) => data?.getLLMProvider ?? null,\n fallback: null,\n enabled: Boolean(providerId),\n errorMessage: 'Failed to load LLM provider',\n });\n}\n\nexport function useLLMModels(filters?: { providerId?: string }): QueryResult<LLMModelRecord[]> {\n return useLLMList<ListLlmModelsQuery, LLMModelRecord>(\n ListLlmModelsDocument,\n 'models',\n (data) => data?.listLLMModels ?? NO_MODELS,\n NO_MODELS,\n filters?.providerId\n );\n}\n\n/**\n * Creates a provider, or updates the one whose id the caller passes.\n * `UpdateBotlitLLMProviderInput` has no `type`/`workspaceId`, so the update\n * payload is projected onto the fields that input actually declares.\n */\nexport function useConfigureLLMProvider() {\n const workspaceId = useWorkspaceId();\n\n const [create, createState] = useWorkspaceMutation<\n CreateBotmanorLlmProviderMutation,\n ConfigureLLMProviderVariables,\n LLMProviderRecord\n >({\n document: CreateBotmanorLlmProviderDocument,\n variables: (input) => ({\n input: buildMutationInput({ ...input, workspaceId }, CREATE_PROVIDER_FIELDS),\n }),\n select: (data) => data?.createBotmanorLLMProvider,\n errorMessage: 'Failed to create the LLM provider',\n });\n\n const [update, updateState] = useWorkspaceMutation<\n UpdateLlmProviderMutation,\n { providerId: string; input: ConfigureLLMProviderVariables },\n LLMProviderRecord\n >({\n document: UpdateLlmProviderDocument,\n variables: ({ providerId, input }) => ({\n id: providerId,\n input: buildMutationInput(input, UPDATE_PROVIDER_FIELDS),\n }),\n select: (data) => data?.updateLLMProvider,\n errorMessage: 'Failed to update the LLM provider',\n });\n\n const configureProvider = useCallback(\n async (input: ConfigureLLMProviderVariables, existingId?: string) =>\n existingId ? update({ providerId: existingId, input }) : create(input),\n [create, update]\n );\n\n return {\n configureProvider,\n isConfiguring: createState.loading || updateState.loading,\n error: createState.error ?? updateState.error,\n };\n}\n\nexport function useDeleteLLMProvider() {\n return useWorkspaceMutation<DeleteLlmProviderMutation, string, boolean>({\n document: DeleteLlmProviderDocument,\n variables: (providerId) => ({ id: providerId }),\n select: (data) => data?.deleteLLMProvider,\n errorMessage: 'Failed to delete the LLM provider',\n });\n}\n\nexport function useTestLLMConnection() {\n return useWorkspaceMutation<TestLlmConnectionMutation, string, boolean>({\n document: TestLlmConnectionDocument,\n variables: (providerId) => ({ id: providerId }),\n select: (data) => data?.testLlmConnection,\n errorMessage: 'Failed to test the LLM connection',\n });\n}\n\n/** Register models through the same authenticated workspace gateway as providers. */\nexport function useCreateLLMModel() {\n const [createModel, state] = useWorkspaceMutation<\n CreateBotmanorLlmModelMutation,\n CreateBotmanorLlmModelInput,\n LLMModelRecord\n >({\n document: CreateBotmanorLlmModelDocument,\n variables: (input) => ({\n input: buildMutationInput(\n input,\n fieldsOf<CreateBotmanorLlmModelInput>({\n providerId: true,\n name: true,\n modelId: true,\n contextWindow: true,\n maxOutputTokens: true,\n inputPricePerMToken: true,\n outputPricePerMToken: true,\n supportsStreaming: true,\n supportsFunctionCalling: true,\n supportsVision: true,\n metadata: true,\n })\n ),\n }),\n select: (data) => data?.createBotmanorLLMModel,\n errorMessage: 'Failed to register the model',\n });\n return { createModel, isCreating: state.loading, error: state.error };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useLLMProviders.js","names":[],"sources":["../../../src/botlit/hooks/useLLMProviders.ts"],"sourcesContent":["/**\n * LLM Providers Hooks\n * @module botlit/hooks\n *\n * These go through the shell's workspace gateway client like every other BotManor\n * hook. They deliberately do NOT use the generated `useQuery`/`useMutation`\n * wrappers: `BotmanorRoot` only mounts an `<ApolloProvider>` in standalone mode,\n * so an Apollo React hook throws \"Could not find client in the context\" the\n * moment the MFE is mounted by an app shell — which is every production route.\n */\n\nimport { useCallback, useMemo } from 'react';\nimport type { DocumentNode } from 'graphql';\nimport { useQuery } from '@tanstack/react-query';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport {\n CreateBotmanorLlmProviderDocument,\n CreateBotmanorLlmModelDocument,\n DeleteLlmProviderDocument,\n GetBotmanorLlmProviderDocument,\n ListBotmanorLlmModelsDocument,\n ListBotmanorLlmProvidersDocument,\n TestLlmConnectionDocument,\n UpdateBotmanorLlmProviderDocument,\n type CreateBotmanorLlmProviderMutation,\n type CreateBotmanorLlmModelMutation,\n type DeleteLlmProviderMutation,\n type GetBotmanorLlmProviderQuery,\n type ListBotmanorLlmModelsQuery,\n type ListBotmanorLlmProvidersQuery,\n type TestLlmConnectionMutation,\n type UpdateBotmanorLlmProviderMutation,\n} from '../../generated/wspace-operations';\nimport type {\n CreateBotmanorLlmModelInput,\n CreateBotmanorLlmProviderInput,\n UpdateBotmanorLlmProviderInput,\n} from '../../generated/wspace-types';\nimport { buildMutationInput, fieldsOf, type GraphQLInput } from './internal/mutationInput';\nimport {\n useWorkspaceId,\n useWorkspaceClient,\n useWorkspaceMutation,\n useWorkspaceQuery,\n type QueryResult,\n} from './internal/workspaceGateway';\n\nconst LIST_LIMIT = 50;\n\nexport interface LLMProviderRecord {\n id: string;\n name: string;\n type: string;\n isActive: boolean;\n apiEndpoint?: string | null;\n credentialsHash?: string | null;\n connectionId?: string | null;\n metadata?: Record<string, unknown> | null;\n createdAt: string;\n updatedAt: string;\n workspaceId: string;\n}\n\nexport interface LLMModelRecord {\n id: string;\n name: string;\n modelId: string;\n providerId: string;\n contextWindow: number;\n maxOutputTokens: number;\n inputPricePerMToken: number;\n outputPricePerMToken: number;\n isActive: boolean;\n supportsStreaming: boolean;\n supportsFunctionCalling: boolean;\n supportsVision: boolean;\n metadata?: Record<string, unknown> | null;\n createdAt: string;\n updatedAt: string;\n}\n\n/** `CreateBotmanorLLMProviderInput` minus the `workspaceId` the hook supplies. */\nexport type ConfigureLLMProviderVariables = Omit<\n GraphQLInput<CreateBotmanorLlmProviderInput>,\n 'workspaceId'\n> & { isActive?: boolean };\n\nconst NO_PROVIDERS: LLMProviderRecord[] = [];\nconst NO_MODELS: LLMModelRecord[] = [];\n\nconst CREATE_PROVIDER_FIELDS = fieldsOf<CreateBotmanorLlmProviderInput>({\n apiEndpoint: true,\n connectionId: true,\n credentials: true,\n metadata: true,\n name: true,\n type: true,\n workspaceId: true,\n});\n\nconst UPDATE_PROVIDER_FIELDS = fieldsOf<UpdateBotmanorLlmProviderInput>({\n apiEndpoint: true,\n connectionId: true,\n credentials: true,\n isActive: true,\n metadata: true,\n name: true,\n});\n\nexport const llmProviderKeys = {\n all: ['llmProviders'] as const,\n lists: () => [...llmProviderKeys.all, 'list'] as const,\n details: () => [...llmProviderKeys.all, 'detail'] as const,\n detail: (id: string) => [...llmProviderKeys.details(), id] as const,\n};\n\nfunction useLLMList<TData, TRecord>(\n document: DocumentNode,\n kind: string,\n select: (data: TData | undefined) => TRecord[],\n fallback: TRecord[],\n providerId?: string\n): QueryResult<TRecord[]> {\n const client = useWorkspaceClient();\n const { workspaceId, currentUser } = useBotlit();\n const query = useQuery({\n queryKey: ['botmanor-llm-catalog', workspaceId, currentUser?.id, kind, providerId],\n enabled: Boolean(workspaceId),\n retry: false,\n queryFn: async () => {\n const records: TRecord[] = [];\n for (let offset = 0; offset < 10000; offset += LIST_LIMIT) {\n const result = await client.query<TData>({\n query: document,\n fetchPolicy: 'network-only',\n variables: {\n filters: providerId ? { providerId } : undefined,\n pagination: { limit: LIST_LIMIT, offset },\n },\n });\n if (!result.data) throw new Error('Model catalog unavailable');\n const page = select(result.data);\n if (!Array.isArray(page) || page.length > LIST_LIMIT)\n throw new Error('Model catalog unavailable');\n records.push(...page);\n if (page.length < LIST_LIMIT) return records;\n }\n throw new Error('Model catalog exceeds the supported limit');\n },\n });\n return {\n data: query.data ?? fallback,\n loading: query.isFetching,\n error: query.error ?? undefined,\n refetch: async () => {\n await query.refetch();\n },\n };\n}\n\nexport function useLLMProviders(): QueryResult<LLMProviderRecord[]> {\n return useLLMList<ListBotmanorLlmProvidersQuery, LLMProviderRecord>(\n ListBotmanorLlmProvidersDocument,\n 'providers',\n (data) => data?.listBotmanorLLMProviders ?? NO_PROVIDERS,\n NO_PROVIDERS\n );\n}\n\nexport function useLLMProvider(\n providerId: string | undefined\n): QueryResult<LLMProviderRecord | null> {\n const variables = useMemo(() => ({ id: providerId ?? '' }), [providerId]);\n\n return useWorkspaceQuery<GetBotmanorLlmProviderQuery, LLMProviderRecord | null>({\n document: GetBotmanorLlmProviderDocument,\n variables,\n select: (data) => data?.getBotmanorLLMProvider ?? null,\n fallback: null,\n enabled: Boolean(providerId),\n errorMessage: 'Failed to load LLM provider',\n });\n}\n\nexport function useLLMModels(filters?: { providerId?: string }): QueryResult<LLMModelRecord[]> {\n return useLLMList<ListBotmanorLlmModelsQuery, LLMModelRecord>(\n ListBotmanorLlmModelsDocument,\n 'models',\n (data) => data?.listBotmanorLLMModels ?? NO_MODELS,\n NO_MODELS,\n filters?.providerId\n );\n}\n\n/**\n * Creates a provider, or updates the one whose id the caller passes.\n * `UpdateBotmanorLLMProviderInput` has no `type`/`workspaceId`, so the update\n * payload is projected onto the fields that input actually declares.\n */\nexport function useConfigureLLMProvider() {\n const workspaceId = useWorkspaceId();\n\n const [create, createState] = useWorkspaceMutation<\n CreateBotmanorLlmProviderMutation,\n ConfigureLLMProviderVariables,\n LLMProviderRecord\n >({\n document: CreateBotmanorLlmProviderDocument,\n variables: (input) => ({\n input: buildMutationInput({ ...input, workspaceId }, CREATE_PROVIDER_FIELDS),\n }),\n select: (data) => data?.createBotmanorLLMProvider,\n errorMessage: 'Failed to create the LLM provider',\n });\n\n const [update, updateState] = useWorkspaceMutation<\n UpdateBotmanorLlmProviderMutation,\n { providerId: string; input: ConfigureLLMProviderVariables },\n LLMProviderRecord\n >({\n document: UpdateBotmanorLlmProviderDocument,\n variables: ({ providerId, input }) => ({\n id: providerId,\n input: buildMutationInput(input, UPDATE_PROVIDER_FIELDS),\n }),\n select: (data) => data?.updateBotmanorLLMProvider,\n errorMessage: 'Failed to update the LLM provider',\n });\n\n const configureProvider = useCallback(\n async (input: ConfigureLLMProviderVariables, existingId?: string) =>\n existingId ? update({ providerId: existingId, input }) : create(input),\n [create, update]\n );\n\n return {\n configureProvider,\n isConfiguring: createState.loading || updateState.loading,\n error: createState.error ?? updateState.error,\n };\n}\n\nexport function useDeleteLLMProvider() {\n return useWorkspaceMutation<DeleteLlmProviderMutation, string, boolean>({\n document: DeleteLlmProviderDocument,\n variables: (providerId) => ({ id: providerId }),\n select: (data) => data?.deleteLLMProvider,\n errorMessage: 'Failed to delete the LLM provider',\n });\n}\n\nexport function useTestLLMConnection() {\n return useWorkspaceMutation<TestLlmConnectionMutation, string, boolean>({\n document: TestLlmConnectionDocument,\n variables: (providerId) => ({ id: providerId }),\n select: (data) => data?.testLlmConnection,\n errorMessage: 'Failed to test the LLM connection',\n });\n}\n\n/** Register models through the same authenticated workspace gateway as providers. */\nexport function useCreateLLMModel() {\n const [createModel, state] = useWorkspaceMutation<\n CreateBotmanorLlmModelMutation,\n CreateBotmanorLlmModelInput,\n LLMModelRecord\n >({\n document: CreateBotmanorLlmModelDocument,\n variables: (input) => ({\n input: buildMutationInput(\n input,\n fieldsOf<CreateBotmanorLlmModelInput>({\n providerId: true,\n name: true,\n modelId: true,\n contextWindow: true,\n maxOutputTokens: true,\n inputPricePerMToken: true,\n outputPricePerMToken: true,\n supportsStreaming: true,\n supportsFunctionCalling: true,\n supportsVision: true,\n metadata: true,\n })\n ),\n }),\n select: (data) => data?.createBotmanorLLMModel,\n errorMessage: 'Failed to register the model',\n });\n return { createModel, isCreating: state.loading, error: state.error };\n}\n"],"mappings":";;;;;;;AA+CA,IAAM,IAAa,IAwCb,IAAoC,EAAE,EACtC,IAA8B,EAAE,EAEhC,IAAyB,EAAyC;CACtE,aAAa;CACb,cAAc;CACd,aAAa;CACb,UAAU;CACV,MAAM;CACN,MAAM;CACN,aAAa;CACd,CAAC,EAEI,IAAyB,EAAyC;CACtE,aAAa;CACb,cAAc;CACd,aAAa;CACb,UAAU;CACV,UAAU;CACV,MAAM;CACP,CAAC;AASF,SAAS,EACP,GACA,GACA,GACA,GACA,GACwB;CACxB,IAAM,IAAS,GAAoB,EAC7B,EAAE,gBAAa,mBAAgB,GAAW,EAC1C,IAAQ,EAAS;EACrB,UAAU;GAAC;GAAwB;GAAa,GAAa;GAAI;GAAM;GAAW;EAClF,SAAS,EAAQ;EACjB,OAAO;EACP,SAAS,YAAY;GACnB,IAAM,IAAqB,EAAE;AAC7B,QAAK,IAAI,IAAS,GAAG,IAAS,KAAO,KAAU,GAAY;IACzD,IAAM,IAAS,MAAM,EAAO,MAAa;KACvC,OAAO;KACP,aAAa;KACb,WAAW;MACT,SAAS,IAAa,EAAE,eAAY,GAAG,KAAA;MACvC,YAAY;OAAE,OAAO;OAAY;OAAQ;MAC1C;KACF,CAAC;AACF,QAAI,CAAC,EAAO,KAAM,OAAU,MAAM,4BAA4B;IAC9D,IAAM,IAAO,EAAO,EAAO,KAAK;AAChC,QAAI,CAAC,MAAM,QAAQ,EAAK,IAAI,EAAK,SAAS,EACxC,OAAU,MAAM,4BAA4B;AAE9C,QADA,EAAQ,KAAK,GAAG,EAAK,EACjB,EAAK,SAAS,EAAY,QAAO;;AAEvC,SAAU,MAAM,4CAA4C;;EAE/D,CAAC;AACF,QAAO;EACL,MAAM,EAAM,QAAQ;EACpB,SAAS,EAAM;EACf,OAAO,EAAM,SAAS,KAAA;EACtB,SAAS,YAAY;AACnB,SAAM,EAAM,SAAS;;EAExB;;AAGH,SAAgB,IAAoD;AAClE,QAAO,EACL,GACA,cACC,MAAS,GAAM,4BAA4B,GAC5C,EACD;;AAkBH,SAAgB,EAAa,GAAkE;AAC7F,QAAO,EACL,GACA,WACC,MAAS,GAAM,yBAAyB,GACzC,GACA,GAAS,WACV;;AAQH,SAAgB,IAA0B;CACxC,IAAM,IAAc,GAAgB,EAE9B,CAAC,GAAQ,KAAe,EAI5B;EACA,UAAU;EACV,YAAY,OAAW,EACrB,OAAO,EAAmB;GAAE,GAAG;GAAO;GAAa,EAAE,EAAuB,EAC7E;EACD,SAAS,MAAS,GAAM;EACxB,cAAc;EACf,CAAC,EAEI,CAAC,GAAQ,KAAe,EAI5B;EACA,UAAU;EACV,YAAY,EAAE,eAAY,gBAAa;GACrC,IAAI;GACJ,OAAO,EAAmB,GAAO,EAAuB;GACzD;EACD,SAAS,MAAS,GAAM;EACxB,cAAc;EACf,CAAC;AAQF,QAAO;EACL,mBAPwB,EACxB,OAAO,GAAsC,MAC3C,IAAa,EAAO;GAAE,YAAY;GAAY;GAAO,CAAC,GAAG,EAAO,EAAM,EACxE,CAAC,GAAQ,EAAO,CACjB;EAIC,eAAe,EAAY,WAAW,EAAY;EAClD,OAAO,EAAY,SAAS,EAAY;EACzC;;AAsBH,SAAgB,IAAoB;CAClC,IAAM,CAAC,GAAa,KAAS,EAI3B;EACA,UAAU;EACV,YAAY,OAAW,EACrB,OAAO,EACL,GACA,EAAsC;GACpC,YAAY;GACZ,MAAM;GACN,SAAS;GACT,eAAe;GACf,iBAAiB;GACjB,qBAAqB;GACrB,sBAAsB;GACtB,mBAAmB;GACnB,yBAAyB;GACzB,gBAAgB;GAChB,UAAU;GACX,CAAC,CACH,EACF;EACD,SAAS,MAAS,GAAM;EACxB,cAAc;EACf,CAAC;AACF,QAAO;EAAE;EAAa,YAAY,EAAM;EAAS,OAAO,EAAM;EAAO"}