@burdenoff/microfe-botmanor 2026.813.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.
Files changed (160) hide show
  1. package/README.md +12 -0
  2. package/dist/botlit/BotlitRoutes.js +357 -0
  3. package/dist/botlit/BotlitRoutes.js.map +1 -0
  4. package/dist/botlit/BotmanorRoot.js +12 -0
  5. package/dist/botlit/BotmanorRoot.js.map +1 -0
  6. package/dist/botlit/BotmanorRootInner.js +101 -0
  7. package/dist/botlit/BotmanorRootInner.js.map +1 -0
  8. package/dist/botlit/components/Badge.js +39 -0
  9. package/dist/botlit/components/Badge.js.map +1 -0
  10. package/dist/botlit/components/Button.js +46 -0
  11. package/dist/botlit/components/Button.js.map +1 -0
  12. package/dist/botlit/components/Card.js +31 -0
  13. package/dist/botlit/components/Card.js.map +1 -0
  14. package/dist/botlit/components/ChannelSelectorSheet.js +130 -0
  15. package/dist/botlit/components/ChannelSelectorSheet.js.map +1 -0
  16. package/dist/botlit/components/EmptyState.js +35 -0
  17. package/dist/botlit/components/EmptyState.js.map +1 -0
  18. package/dist/botlit/components/ErrorState.js +33 -0
  19. package/dist/botlit/components/ErrorState.js.map +1 -0
  20. package/dist/botlit/components/Input.js +59 -0
  21. package/dist/botlit/components/Input.js.map +1 -0
  22. package/dist/botlit/components/PageLayout.js +34 -0
  23. package/dist/botlit/components/PageLayout.js.map +1 -0
  24. package/dist/botlit/components/QuotaExhaustedDialog.js +20 -0
  25. package/dist/botlit/components/QuotaExhaustedDialog.js.map +1 -0
  26. package/dist/botlit/components/RouteLoader.js +52 -0
  27. package/dist/botlit/components/RouteLoader.js.map +1 -0
  28. package/dist/botlit/components/VersionHistoryPanel.js +144 -0
  29. package/dist/botlit/components/VersionHistoryPanel.js.map +1 -0
  30. package/dist/botlit/components/WorkspaceRequired.js +70 -0
  31. package/dist/botlit/components/WorkspaceRequired.js.map +1 -0
  32. package/dist/botlit/hooks/index.js +16 -0
  33. package/dist/botlit/hooks/internal/mutationInput.js +16 -0
  34. package/dist/botlit/hooks/internal/mutationInput.js.map +1 -0
  35. package/dist/botlit/hooks/internal/workspaceGateway.js +99 -0
  36. package/dist/botlit/hooks/internal/workspaceGateway.js.map +1 -0
  37. package/dist/botlit/hooks/useA2A.js +184 -0
  38. package/dist/botlit/hooks/useA2A.js.map +1 -0
  39. package/dist/botlit/hooks/useAgents.js +469 -0
  40. package/dist/botlit/hooks/useAgents.js.map +1 -0
  41. package/dist/botlit/hooks/useBots.js +306 -0
  42. package/dist/botlit/hooks/useBots.js.map +1 -0
  43. package/dist/botlit/hooks/useBuckets.js +119 -0
  44. package/dist/botlit/hooks/useBuckets.js.map +1 -0
  45. package/dist/botlit/hooks/useChannels.js +213 -0
  46. package/dist/botlit/hooks/useChannels.js.map +1 -0
  47. package/dist/botlit/hooks/useConversations.js +64 -0
  48. package/dist/botlit/hooks/useConversations.js.map +1 -0
  49. package/dist/botlit/hooks/useExecutions.js +86 -0
  50. package/dist/botlit/hooks/useExecutions.js.map +1 -0
  51. package/dist/botlit/hooks/useKnowledgeBases.js +113 -0
  52. package/dist/botlit/hooks/useKnowledgeBases.js.map +1 -0
  53. package/dist/botlit/hooks/useLLMProviders.js +83 -0
  54. package/dist/botlit/hooks/useLLMProviders.js.map +1 -0
  55. package/dist/botlit/hooks/useMCPServers.js +134 -0
  56. package/dist/botlit/hooks/useMCPServers.js.map +1 -0
  57. package/dist/botlit/hooks/usePolicies.js +120 -0
  58. package/dist/botlit/hooks/usePolicies.js.map +1 -0
  59. package/dist/botlit/hooks/usePromptTemplates.js +161 -0
  60. package/dist/botlit/hooks/usePromptTemplates.js.map +1 -0
  61. package/dist/botlit/hooks/useRetrievalProfiles.js +146 -0
  62. package/dist/botlit/hooks/useRetrievalProfiles.js.map +1 -0
  63. package/dist/botlit/hooks/useSkills.js +132 -0
  64. package/dist/botlit/hooks/useSkills.js.map +1 -0
  65. package/dist/botlit/hooks/useStore.js +167 -0
  66. package/dist/botlit/hooks/useStore.js.map +1 -0
  67. package/dist/botlit/hooks/useUserPlatformConnection.js +172 -0
  68. package/dist/botlit/hooks/useUserPlatformConnection.js.map +1 -0
  69. package/dist/botlit/index.js +11 -0
  70. package/dist/botlit/pages/A2AAgentDetailPage.js +589 -0
  71. package/dist/botlit/pages/A2AAgentDetailPage.js.map +1 -0
  72. package/dist/botlit/pages/A2ARegistryPage.js +240 -0
  73. package/dist/botlit/pages/A2ARegistryPage.js.map +1 -0
  74. package/dist/botlit/pages/AgentBuilderPage.js +486 -0
  75. package/dist/botlit/pages/AgentBuilderPage.js.map +1 -0
  76. package/dist/botlit/pages/AgentDetailPage.js +517 -0
  77. package/dist/botlit/pages/AgentDetailPage.js.map +1 -0
  78. package/dist/botlit/pages/AgentsListPage.js +294 -0
  79. package/dist/botlit/pages/AgentsListPage.js.map +1 -0
  80. package/dist/botlit/pages/BotChannelsTab.js +530 -0
  81. package/dist/botlit/pages/BotChannelsTab.js.map +1 -0
  82. package/dist/botlit/pages/BotDetailPage.js +872 -0
  83. package/dist/botlit/pages/BotDetailPage.js.map +1 -0
  84. package/dist/botlit/pages/BotWorkflowTab.js +229 -0
  85. package/dist/botlit/pages/BotWorkflowTab.js.map +1 -0
  86. package/dist/botlit/pages/BotsListPage.js +313 -0
  87. package/dist/botlit/pages/BotsListPage.js.map +1 -0
  88. package/dist/botlit/pages/BucketsPage.js +604 -0
  89. package/dist/botlit/pages/BucketsPage.js.map +1 -0
  90. package/dist/botlit/pages/ChannelDetailPage.js +955 -0
  91. package/dist/botlit/pages/ChannelDetailPage.js.map +1 -0
  92. package/dist/botlit/pages/ChannelRoutesPage.js +218 -0
  93. package/dist/botlit/pages/ChannelRoutesPage.js.map +1 -0
  94. package/dist/botlit/pages/ChannelsPage.js +304 -0
  95. package/dist/botlit/pages/ChannelsPage.js.map +1 -0
  96. package/dist/botlit/pages/ChatPage.js +247 -0
  97. package/dist/botlit/pages/ChatPage.js.map +1 -0
  98. package/dist/botlit/pages/DashboardPage.js +318 -0
  99. package/dist/botlit/pages/DashboardPage.js.map +1 -0
  100. package/dist/botlit/pages/ExecutionDetailPage.js +313 -0
  101. package/dist/botlit/pages/ExecutionDetailPage.js.map +1 -0
  102. package/dist/botlit/pages/ExecutionsPage.js +294 -0
  103. package/dist/botlit/pages/ExecutionsPage.js.map +1 -0
  104. package/dist/botlit/pages/InstalledPackagesPage.js +619 -0
  105. package/dist/botlit/pages/InstalledPackagesPage.js.map +1 -0
  106. package/dist/botlit/pages/KnowledgeBaseDetailPage.js +473 -0
  107. package/dist/botlit/pages/KnowledgeBaseDetailPage.js.map +1 -0
  108. package/dist/botlit/pages/KnowledgeBasesPage.js +150 -0
  109. package/dist/botlit/pages/KnowledgeBasesPage.js.map +1 -0
  110. package/dist/botlit/pages/MCPServerDetailPage.js +550 -0
  111. package/dist/botlit/pages/MCPServerDetailPage.js.map +1 -0
  112. package/dist/botlit/pages/MCPServersPage.js +321 -0
  113. package/dist/botlit/pages/MCPServersPage.js.map +1 -0
  114. package/dist/botlit/pages/PoliciesPage.js +224 -0
  115. package/dist/botlit/pages/PoliciesPage.js.map +1 -0
  116. package/dist/botlit/pages/PolicyDetailPage.js +861 -0
  117. package/dist/botlit/pages/PolicyDetailPage.js.map +1 -0
  118. package/dist/botlit/pages/PromptStudioPage.js +236 -0
  119. package/dist/botlit/pages/PromptStudioPage.js.map +1 -0
  120. package/dist/botlit/pages/PromptTemplateDetailPage.js +812 -0
  121. package/dist/botlit/pages/PromptTemplateDetailPage.js.map +1 -0
  122. package/dist/botlit/pages/PromptTemplatesPage.js +269 -0
  123. package/dist/botlit/pages/PromptTemplatesPage.js.map +1 -0
  124. package/dist/botlit/pages/RetrievalProfileDetailPage.js +559 -0
  125. package/dist/botlit/pages/RetrievalProfileDetailPage.js.map +1 -0
  126. package/dist/botlit/pages/RetrievalProfilesPage.js +219 -0
  127. package/dist/botlit/pages/RetrievalProfilesPage.js.map +1 -0
  128. package/dist/botlit/pages/SettingsPage.js +655 -0
  129. package/dist/botlit/pages/SettingsPage.js.map +1 -0
  130. package/dist/botlit/pages/SkillDetailPage.js +778 -0
  131. package/dist/botlit/pages/SkillDetailPage.js.map +1 -0
  132. package/dist/botlit/pages/SkillsPage.js +206 -0
  133. package/dist/botlit/pages/SkillsPage.js.map +1 -0
  134. package/dist/botlit/pages/StorePackageDetailPage.js +462 -0
  135. package/dist/botlit/pages/StorePackageDetailPage.js.map +1 -0
  136. package/dist/botlit/pages/StorePage.js +315 -0
  137. package/dist/botlit/pages/StorePage.js.map +1 -0
  138. package/dist/botlit/providers/BotlitProvider.js +93 -0
  139. package/dist/botlit/providers/BotlitProvider.js.map +1 -0
  140. package/dist/botlit/store/botlitStore.js +101 -0
  141. package/dist/botlit/store/botlitStore.js.map +1 -0
  142. package/dist/botlit/utils/cn.js +10 -0
  143. package/dist/botlit/utils/cn.js.map +1 -0
  144. package/dist/botlit/utils/formatters.js +37 -0
  145. package/dist/botlit/utils/formatters.js.map +1 -0
  146. package/dist/botlit/utils/navigation.js +9 -0
  147. package/dist/botlit/utils/navigation.js.map +1 -0
  148. package/dist/botlit/utils/unions.js +14 -0
  149. package/dist/botlit/utils/unions.js.map +1 -0
  150. package/dist/generated/global-operations.js +66 -0
  151. package/dist/generated/global-operations.js.map +1 -0
  152. package/dist/generated/global-types.js +8 -0
  153. package/dist/generated/global-types.js.map +1 -0
  154. package/dist/generated/wspace-operations.js +1591 -0
  155. package/dist/generated/wspace-operations.js.map +1 -0
  156. package/dist/generated/wspace-types.js +12 -0
  157. package/dist/generated/wspace-types.js.map +1 -0
  158. package/dist/index.js +13 -0
  159. package/dist/utils/nativeBridge.js +2 -0
  160. package/package.json +133 -0
@@ -0,0 +1,144 @@
1
+ import { useAgentVersions as e, usePublishAgentVersion as t, useRollbackAgentVersion as n } from "../hooks/useAgents.js";
2
+ import { formatRelativeTime as r } from "../utils/formatters.js";
3
+ import { Card as i, CardContent as a, CardDescription as o, CardHeader as s, CardTitle as c } from "./Card.js";
4
+ import { Button as l } from "./Button.js";
5
+ import { Badge as u } from "./Badge.js";
6
+ import { useState as d } from "react";
7
+ import { AlertDialog as f, AlertDialogAction as p, AlertDialogCancel as m, AlertDialogContent as h, AlertDialogDescription as g, AlertDialogFooter as _, AlertDialogHeader as v, AlertDialogTitle as y, Dialog as b, DialogContent as x, DialogDescription as S, DialogFooter as C, DialogHeader as w, DialogTitle as T, Textarea as E } from "@burdenoff/fe-libs/ui";
8
+ import { jsx as D, jsxs as O } from "react/jsx-runtime";
9
+ import { CheckCircle2 as k, History as A, Rocket as j, RotateCcw as M } from "lucide-react";
10
+ import { useI18n as N } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
11
+ import { toast as P } from "sonner";
12
+ //#region src/botlit/components/VersionHistoryPanel.tsx
13
+ function F(e) {
14
+ return e === "DRAFT" ? "secondary" : e === "PUBLISHED" ? "success" : "outline";
15
+ }
16
+ var I = ({ agentId: I, draftVersionId: L, currentVersionId: ee, onChanged: R }) => {
17
+ let { t: z } = N(), B = (e, t) => {
18
+ let n = z(e);
19
+ return n === e ? t : n;
20
+ }, { data: V, loading: H, refetch: U } = e(I), [W, G] = t(), [K, q] = n(), [J, Y] = d(!1), [X, Z] = d(""), [Q, $] = d(null), te = async () => {
21
+ if (L) try {
22
+ let e = await W({
23
+ agentId: I,
24
+ versionId: L,
25
+ changelog: X
26
+ });
27
+ P.success(`${B("botlit.agentDetail.versions.publishSuccessPrefix", "Published version")} ${e.version}`), Y(!1), Z(""), await U(), R?.();
28
+ } catch (e) {
29
+ P.error(e instanceof Error ? e.message : B("botlit.agentDetail.versions.publishError", "Failed to publish version"));
30
+ }
31
+ }, ne = async () => {
32
+ if (Q) try {
33
+ let e = await K({
34
+ agentId: I,
35
+ targetVersionId: Q.id
36
+ });
37
+ P.success(`${B("botlit.agentDetail.versions.rollbackSuccessPrefix", "Rolled back to version")} ${Q.version} (${B("botlit.agentDetail.versions.rollbackSuccessSuffix", "now")} ${e.version})`), $(null), await U(), R?.();
38
+ } catch (e) {
39
+ P.error(e instanceof Error ? e.message : B("botlit.agentDetail.versions.rollbackError", "Failed to roll back agent version"));
40
+ }
41
+ };
42
+ return /* @__PURE__ */ O("div", {
43
+ className: "space-y-6",
44
+ children: [
45
+ /* @__PURE__ */ O(i, { children: [/* @__PURE__ */ O(s, {
46
+ className: "flex flex-row items-start justify-between gap-4",
47
+ children: [/* @__PURE__ */ O("div", { children: [/* @__PURE__ */ O(c, {
48
+ className: "flex items-center gap-2",
49
+ children: [/* @__PURE__ */ D(A, { size: 18 }), B("botlit.agentDetail.versions.title", "Version History")]
50
+ }), /* @__PURE__ */ D(o, { children: B("botlit.agentDetail.versions.description", "Every published configuration change, with a diff-able changelog. Publish the current draft or roll back to any prior version.") })] }), L && /* @__PURE__ */ D(l, {
51
+ leftIcon: /* @__PURE__ */ D(j, { size: 16 }),
52
+ onClick: () => Y(!0),
53
+ children: B("botlit.agentDetail.versions.publishDraft", "Publish Draft")
54
+ })]
55
+ }), /* @__PURE__ */ D(a, { children: H ? /* @__PURE__ */ D("div", { className: "h-32 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }) : V.length === 0 ? /* @__PURE__ */ D("p", {
56
+ className: "text-text-secondary",
57
+ children: B("botlit.agentDetail.versions.empty", "No version history yet.")
58
+ }) : /* @__PURE__ */ D("ul", {
59
+ className: "space-y-3",
60
+ children: V.map((e) => {
61
+ let t = e.id === ee, n = e.status !== "DRAFT" && !t;
62
+ return /* @__PURE__ */ O("li", {
63
+ className: "flex items-start justify-between gap-4 p-4 border border-border-subtle rounded-lg",
64
+ children: [/* @__PURE__ */ O("div", {
65
+ className: "space-y-1 min-w-0",
66
+ children: [
67
+ /* @__PURE__ */ O("div", {
68
+ className: "flex items-center gap-2 flex-wrap",
69
+ children: [
70
+ /* @__PURE__ */ O("span", {
71
+ className: "font-mono font-medium",
72
+ children: ["v", e.version]
73
+ }),
74
+ /* @__PURE__ */ D(u, {
75
+ variant: F(e.status),
76
+ children: e.status
77
+ }),
78
+ t && /* @__PURE__ */ O(u, {
79
+ variant: "outline",
80
+ className: "flex items-center gap-1",
81
+ children: [/* @__PURE__ */ D(k, { size: 12 }), B("botlit.agentDetail.versions.liveNow", "Live now")]
82
+ })
83
+ ]
84
+ }),
85
+ /* @__PURE__ */ D("p", {
86
+ className: "text-sm text-text-secondary break-words",
87
+ children: e.changelog || B("botlit.agentDetail.versions.noChangelog", "No description")
88
+ }),
89
+ /* @__PURE__ */ D("p", {
90
+ className: "text-xs text-text-secondary",
91
+ children: e.status === "DRAFT" ? `${B("botlit.agentDetail.versions.updated", "Updated")} ${r(e.createdAt)}` : `${B("botlit.agentDetail.versions.published", "Published")} ${r(e.publishedAt ?? e.createdAt)}`
92
+ })
93
+ ]
94
+ }), n && /* @__PURE__ */ D(l, {
95
+ variant: "outline",
96
+ size: "sm",
97
+ leftIcon: /* @__PURE__ */ D(M, { size: 14 }),
98
+ onClick: () => $(e),
99
+ children: B("botlit.agentDetail.versions.rollback", "Roll back")
100
+ })]
101
+ }, e.id);
102
+ })
103
+ }) })] }),
104
+ /* @__PURE__ */ D(b, {
105
+ open: J,
106
+ onOpenChange: Y,
107
+ children: /* @__PURE__ */ O(x, { children: [
108
+ /* @__PURE__ */ O(w, { children: [/* @__PURE__ */ D(T, { children: B("botlit.agentDetail.versions.publishDialog.title", "Publish this version") }), /* @__PURE__ */ D(S, { children: B("botlit.agentDetail.versions.publishDialog.description", "This makes the draft's prompt, model, tools, and policy settings live for the agent. Describe what changed.") })] }),
109
+ /* @__PURE__ */ D(E, {
110
+ value: X,
111
+ onChange: (e) => Z(e.target.value),
112
+ placeholder: B("botlit.agentDetail.versions.publishDialog.placeholder", "e.g. Tightened the system prompt and switched to gpt-4o"),
113
+ rows: 4
114
+ }),
115
+ /* @__PURE__ */ O(C, { children: [/* @__PURE__ */ D(l, {
116
+ variant: "outline",
117
+ onClick: () => Y(!1),
118
+ children: B("botlit.common.cancel", "Cancel")
119
+ }), /* @__PURE__ */ D(l, {
120
+ isLoading: G.loading,
121
+ onClick: () => void te(),
122
+ children: B("botlit.agentDetail.versions.publishDialog.confirm", "Publish")
123
+ })] })
124
+ ] })
125
+ }),
126
+ /* @__PURE__ */ D(f, {
127
+ open: Q !== null,
128
+ onOpenChange: (e) => !e && $(null),
129
+ children: /* @__PURE__ */ O(h, { children: [/* @__PURE__ */ O(v, { children: [/* @__PURE__ */ D(y, { children: B("botlit.agentDetail.versions.rollbackDialog.title", "Roll back to this version?") }), /* @__PURE__ */ D(g, { children: Q && `${B("botlit.agentDetail.versions.rollbackDialog.descriptionPrefix", "This immediately restores the agent to version")} ${Q.version}${B("botlit.agentDetail.versions.rollbackDialog.descriptionSuffix", ". The current live config is kept in history and can be restored the same way.")}` })] }), /* @__PURE__ */ O(_, { children: [/* @__PURE__ */ D(m, {
130
+ onClick: () => $(null),
131
+ children: B("botlit.common.cancel", "Cancel")
132
+ }), /* @__PURE__ */ D(p, {
133
+ disabled: q.loading,
134
+ onClick: () => void ne(),
135
+ children: B("botlit.agentDetail.versions.rollbackDialog.confirm", "Roll back")
136
+ })] })] })
137
+ })
138
+ ]
139
+ });
140
+ };
141
+ //#endregion
142
+ export { I as VersionHistoryPanel };
143
+
144
+ //# sourceMappingURL=VersionHistoryPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VersionHistoryPanel.js","names":[],"sources":["../../../src/botlit/components/VersionHistoryPanel.tsx"],"sourcesContent":["/**\n * Version History Panel (BOFF-4381)\n * @module botlit/components\n *\n * Real, discoverable UI for agent versioning: shows the full version\n * history (draft/published/historical), lets a workspace admin publish the\n * current draft with a changelog, and roll back to any prior published\n * version with a confirmation step.\n */\n\nimport { useState, type FC } from 'react';\nimport { History, Rocket, RotateCcw, CheckCircle2 } from 'lucide-react';\nimport { toast } from 'sonner';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from './Card';\nimport { Button } from './Button';\nimport { Badge } from './Badge';\nimport {\n useAgentVersions,\n usePublishAgentVersion,\n useRollbackAgentVersion,\n type AgentVersionRecord,\n} from '../hooks/useAgents';\nimport { formatRelativeTime } from '../utils/formatters';\n\ninterface VersionHistoryPanelProps {\n agentId: string;\n /** The agent's current draft version id (if any) — enables the Publish action. */\n draftVersionId?: string | null;\n /** The agent's current live (published) version id — hidden from the rollback list. */\n currentVersionId?: string | null;\n /** Called after a successful publish or rollback so the caller can refetch the agent itself. */\n onChanged?: () => void;\n}\n\nfunction versionStatusVariant(\n status: AgentVersionRecord['status']\n): 'secondary' | 'success' | 'outline' {\n if (status === 'DRAFT') return 'secondary';\n if (status === 'PUBLISHED') return 'success';\n return 'outline';\n}\n\nexport const VersionHistoryPanel: FC<VersionHistoryPanelProps> = ({\n agentId,\n draftVersionId,\n currentVersionId,\n onChanged,\n}) => {\n const { t: translate } = useI18n();\n const t = (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n\n const { data: versions, loading, refetch } = useAgentVersions(agentId);\n const [publishAgentVersion, publishState] = usePublishAgentVersion();\n const [rollbackAgentVersion, rollbackState] = useRollbackAgentVersion();\n\n const [publishOpen, setPublishOpen] = useState(false);\n const [changelogDraft, setChangelogDraft] = useState('');\n const [rollbackTarget, setRollbackTarget] = useState<AgentVersionRecord | null>(null);\n\n const handlePublish = async (): Promise<void> => {\n if (!draftVersionId) return;\n try {\n const published = await publishAgentVersion({\n agentId,\n versionId: draftVersionId,\n changelog: changelogDraft,\n });\n toast.success(\n `${t('botlit.agentDetail.versions.publishSuccessPrefix', 'Published version')} ${published.version}`\n );\n setPublishOpen(false);\n setChangelogDraft('');\n await refetch();\n onChanged?.();\n } catch (err: unknown) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.agentDetail.versions.publishError', 'Failed to publish version')\n );\n }\n };\n\n const handleRollback = async (): Promise<void> => {\n if (!rollbackTarget) return;\n try {\n const restored = await rollbackAgentVersion({ agentId, targetVersionId: rollbackTarget.id });\n toast.success(\n `${t('botlit.agentDetail.versions.rollbackSuccessPrefix', 'Rolled back to version')} ${rollbackTarget.version} (${t('botlit.agentDetail.versions.rollbackSuccessSuffix', 'now')} ${restored.version})`\n );\n setRollbackTarget(null);\n await refetch();\n onChanged?.();\n } catch (err: unknown) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.agentDetail.versions.rollbackError', 'Failed to roll back agent version')\n );\n }\n };\n\n return (\n <div className=\"space-y-6\">\n <Card>\n <CardHeader className=\"flex flex-row items-start justify-between gap-4\">\n <div>\n <CardTitle className=\"flex items-center gap-2\">\n <History size={18} />\n {t('botlit.agentDetail.versions.title', 'Version History')}\n </CardTitle>\n <CardDescription>\n {t(\n 'botlit.agentDetail.versions.description',\n 'Every published configuration change, with a diff-able changelog. Publish the current draft or roll back to any prior version.'\n )}\n </CardDescription>\n </div>\n {draftVersionId && (\n <Button leftIcon={<Rocket size={16} />} onClick={() => setPublishOpen(true)}>\n {t('botlit.agentDetail.versions.publishDraft', 'Publish Draft')}\n </Button>\n )}\n </CardHeader>\n <CardContent>\n {loading ? (\n <div className=\"h-32 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\" />\n ) : versions.length === 0 ? (\n <p className=\"text-text-secondary\">\n {t('botlit.agentDetail.versions.empty', 'No version history yet.')}\n </p>\n ) : (\n <ul className=\"space-y-3\">\n {versions.map((version) => {\n const isCurrent = version.id === currentVersionId;\n const canRollback = version.status !== 'DRAFT' && !isCurrent;\n return (\n <li\n key={version.id}\n className=\"flex items-start justify-between gap-4 p-4 border border-border-subtle rounded-lg\"\n >\n <div className=\"space-y-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-mono font-medium\">v{version.version}</span>\n <Badge variant={versionStatusVariant(version.status)}>\n {version.status}\n </Badge>\n {isCurrent && (\n <Badge variant=\"outline\" className=\"flex items-center gap-1\">\n <CheckCircle2 size={12} />\n {t('botlit.agentDetail.versions.liveNow', 'Live now')}\n </Badge>\n )}\n </div>\n <p className=\"text-sm text-text-secondary break-words\">\n {version.changelog ||\n t('botlit.agentDetail.versions.noChangelog', 'No description')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {version.status === 'DRAFT'\n ? `${t('botlit.agentDetail.versions.updated', 'Updated')} ${formatRelativeTime(version.createdAt)}`\n : `${t('botlit.agentDetail.versions.published', 'Published')} ${formatRelativeTime(version.publishedAt ?? version.createdAt)}`}\n </p>\n </div>\n {canRollback && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n leftIcon={<RotateCcw size={14} />}\n onClick={() => setRollbackTarget(version)}\n >\n {t('botlit.agentDetail.versions.rollback', 'Roll back')}\n </Button>\n )}\n </li>\n );\n })}\n </ul>\n )}\n </CardContent>\n </Card>\n\n {/* Publish dialog */}\n <Dialog open={publishOpen} onOpenChange={setPublishOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {t('botlit.agentDetail.versions.publishDialog.title', 'Publish this version')}\n </DialogTitle>\n <DialogDescription>\n {t(\n 'botlit.agentDetail.versions.publishDialog.description',\n \"This makes the draft's prompt, model, tools, and policy settings live for the agent. Describe what changed.\"\n )}\n </DialogDescription>\n </DialogHeader>\n <Textarea\n value={changelogDraft}\n onChange={(e) => setChangelogDraft(e.target.value)}\n placeholder={t(\n 'botlit.agentDetail.versions.publishDialog.placeholder',\n 'e.g. Tightened the system prompt and switched to gpt-4o'\n )}\n rows={4}\n />\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setPublishOpen(false)}>\n {t('botlit.common.cancel', 'Cancel')}\n </Button>\n <Button isLoading={publishState.loading} onClick={() => void handlePublish()}>\n {t('botlit.agentDetail.versions.publishDialog.confirm', 'Publish')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n {/* Rollback confirmation */}\n <AlertDialog\n open={rollbackTarget !== null}\n onOpenChange={(open) => !open && setRollbackTarget(null)}\n >\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {t('botlit.agentDetail.versions.rollbackDialog.title', 'Roll back to this version?')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {rollbackTarget &&\n `${t('botlit.agentDetail.versions.rollbackDialog.descriptionPrefix', 'This immediately restores the agent to version')} ${rollbackTarget.version}${t('botlit.agentDetail.versions.rollbackDialog.descriptionSuffix', '. The current live config is kept in history and can be restored the same way.')}`}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel onClick={() => setRollbackTarget(null)}>\n {t('botlit.common.cancel', 'Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n disabled={rollbackState.loading}\n onClick={() => void handleRollback()}\n >\n {t('botlit.agentDetail.versions.rollbackDialog.confirm', 'Roll back')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import { joinPath as e } from "../utils/navigation.js";
2
+ import { EmphasisPanel as t, IllustratedEmptyState as n, NextSteps as r, PagePurpose as i } from "@burdenoff/fe-libs/ui";
3
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
4
+ import { Bot as s, MessagesSquare as c, Sparkles as l } from "lucide-react";
5
+ //#region src/botlit/components/WorkspaceRequired.tsx
6
+ var u = ({ basePath: u, navigate: d }) => {
7
+ let f = (t) => {
8
+ d?.(e(u, t));
9
+ };
10
+ return /* @__PURE__ */ o("div", {
11
+ className: "mx-auto flex h-full min-h-[60vh] w-full max-w-2xl flex-col justify-center gap-6 px-4 py-10",
12
+ children: [
13
+ /* @__PURE__ */ a(i, {
14
+ icon: /* @__PURE__ */ a(s, {
15
+ className: "size-4",
16
+ "aria-hidden": "true"
17
+ }),
18
+ children: "Botlit is where you build and run AI agents — you give an agent a prompt, a model, the knowledge it may read and the tools it may call, then publish it to a channel such as web chat, Slack or an API so your team and customers can talk to it."
19
+ }),
20
+ /* @__PURE__ */ a(t, {
21
+ className: "p-6",
22
+ children: /* @__PURE__ */ a(n, {
23
+ illustration: "onboarding",
24
+ title: "Pick a workspace to start building",
25
+ description: "Agents, knowledge bases and channels live inside a workspace so they stay scoped to the right team. Select or create an active workspace from the shell to load your Botlit workspace."
26
+ })
27
+ }),
28
+ /* @__PURE__ */ a(r, {
29
+ storageKey: "botlit-get-started",
30
+ title: "Once your workspace is active",
31
+ steps: [
32
+ {
33
+ id: "open-agents",
34
+ label: "Open your agents",
35
+ description: "Browse, search and manage every agent in this workspace.",
36
+ icon: /* @__PURE__ */ a(s, {
37
+ className: "size-4",
38
+ "aria-hidden": "true"
39
+ }),
40
+ onClick: () => f("agents")
41
+ },
42
+ {
43
+ id: "build-agent",
44
+ label: "Build an agent",
45
+ description: "Pick a model, write the prompt and wire up the tools it may call.",
46
+ icon: /* @__PURE__ */ a(l, {
47
+ className: "size-4",
48
+ "aria-hidden": "true"
49
+ }),
50
+ onClick: () => f("agents/new")
51
+ },
52
+ {
53
+ id: "connect-channel",
54
+ label: "Connect a channel",
55
+ description: "Publish an agent to web chat, Slack or an API so people can reach it.",
56
+ icon: /* @__PURE__ */ a(c, {
57
+ className: "size-4",
58
+ "aria-hidden": "true"
59
+ }),
60
+ onClick: () => f("channels")
61
+ }
62
+ ]
63
+ })
64
+ ]
65
+ });
66
+ };
67
+ //#endregion
68
+ export { u as WorkspaceRequired };
69
+
70
+ //# sourceMappingURL=WorkspaceRequired.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkspaceRequired.js","names":[],"sources":["../../../src/botlit/components/WorkspaceRequired.tsx"],"sourcesContent":["/**\n * Workspace Required Gate\n * @module botlit/components\n */\n\nimport type { FC } from 'react';\nimport { Bot, MessagesSquare, Sparkles } from 'lucide-react';\nimport {\n EmphasisPanel,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { joinPath } from '../utils/navigation';\n\n/**\n * Shown when Botlit is mounted without an active workspace.\n *\n * Every Botlit query is workspace-scoped and every write is rejected without\n * `x-workspace-id`, so the module genuinely cannot run — but a single muted\n * sentence in a tall empty region reads as a broken page. This uses the shared\n * guidance pattern (purpose → illustrated zero state → next steps) so the user\n * is told what Botlit is for and what to do next, and the steps land on real\n * routes the moment a workspace becomes active.\n */\nexport interface WorkspaceRequiredProps {\n /** Absolute path Botlit is mounted at in the host shell, e.g. `/botlit`. */\n basePath: string;\n /** Host shell navigation. Absent in standalone/dev mounts. */\n navigate?: (path: string) => void;\n}\n\nexport const WorkspaceRequired: FC<WorkspaceRequiredProps> = ({ basePath, navigate }) => {\n const go = (relativePath: string) => {\n navigate?.(joinPath(basePath, relativePath));\n };\n\n return (\n <div className=\"mx-auto flex h-full min-h-[60vh] w-full max-w-2xl flex-col justify-center gap-6 px-4 py-10\">\n {/* The 'story': plain-language purpose of this module for a first-time user. */}\n <PagePurpose icon={<Bot className=\"size-4\" aria-hidden=\"true\" />}>\n Botlit is where you build and run AI agents — you give an agent a prompt, a model, the\n knowledge it may read and the tools it may call, then publish it to a channel such as web\n chat, Slack or an API so your team and customers can talk to it.\n </PagePurpose>\n\n {/* The single emphasis zone for this screen: the get-started callout. */}\n <EmphasisPanel className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"onboarding\"\n title=\"Pick a workspace to start building\"\n description=\"Agents, knowledge bases and channels live inside a workspace so they stay scoped to the right team. Select or create an active workspace from the shell to load your Botlit workspace.\"\n />\n </EmphasisPanel>\n\n {/* Dismissable, reopenable next-step guidance wired to real routes. */}\n <NextSteps\n storageKey=\"botlit-get-started\"\n title=\"Once your workspace is active\"\n steps={[\n {\n id: 'open-agents',\n label: 'Open your agents',\n description: 'Browse, search and manage every agent in this workspace.',\n icon: <Bot className=\"size-4\" aria-hidden=\"true\" />,\n onClick: () => go('agents'),\n },\n {\n id: 'build-agent',\n label: 'Build an agent',\n description: 'Pick a model, write the prompt and wire up the tools it may call.',\n icon: <Sparkles className=\"size-4\" aria-hidden=\"true\" />,\n onClick: () => go('agents/new'),\n },\n {\n id: 'connect-channel',\n label: 'Connect a channel',\n description: 'Publish an agent to web chat, Slack or an API so people can reach it.',\n icon: <MessagesSquare className=\"size-4\" aria-hidden=\"true\" />,\n onClick: () => go('channels'),\n },\n ]}\n />\n </div>\n );\n};\n"],"mappings":";;;;;AAgCA,IAAa,KAAiD,EAAE,aAAU,kBAAe;CACvF,IAAM,KAAM,MAAyB;AACnC,MAAW,EAAS,GAAU,EAAa,CAAC;;AAG9C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEE,kBAAC,GAAD;IAAa,MAAM,kBAAC,GAAD;KAAK,WAAU;KAAS,eAAY;KAAS,CAAA;cAAE;IAIpD,CAAA;GAGd,kBAAC,GAAD;IAAe,WAAU;cACvB,kBAAC,GAAD;KACE,cAAa;KACb,OAAM;KACN,aAAY;KACZ,CAAA;IACY,CAAA;GAGhB,kBAAC,GAAD;IACE,YAAW;IACX,OAAM;IACN,OAAO;KACL;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,MAAM,kBAAC,GAAD;OAAK,WAAU;OAAS,eAAY;OAAS,CAAA;MACnD,eAAe,EAAG,SAAS;MAC5B;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,MAAM,kBAAC,GAAD;OAAU,WAAU;OAAS,eAAY;OAAS,CAAA;MACxD,eAAe,EAAG,aAAa;MAChC;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,MAAM,kBAAC,GAAD;OAAgB,WAAU;OAAS,eAAY;OAAS,CAAA;MAC9D,eAAe,EAAG,WAAW;MAC9B;KACF;IACD,CAAA;GACE"}
@@ -0,0 +1,16 @@
1
+ import "./useBots.js";
2
+ import "./useAgents.js";
3
+ import "./useKnowledgeBases.js";
4
+ import "./useConversations.js";
5
+ import "./useLLMProviders.js";
6
+ import "./useMCPServers.js";
7
+ import "./useA2A.js";
8
+ import "./useRetrievalProfiles.js";
9
+ import "./useChannels.js";
10
+ import "./usePolicies.js";
11
+ import "./useSkills.js";
12
+ import "./usePromptTemplates.js";
13
+ import "./useExecutions.js";
14
+ import "./useBuckets.js";
15
+ import "./useStore.js";
16
+ import "./useUserPlatformConnection.js";
@@ -0,0 +1,16 @@
1
+ //#region src/botlit/hooks/internal/mutationInput.ts
2
+ function e(e) {
3
+ return { keys: Object.keys(e) };
4
+ }
5
+ function t(e, t) {
6
+ let n = e, r = {};
7
+ for (let e of t.keys) {
8
+ let t = e, i = n[t];
9
+ i !== void 0 && (r[t] = i);
10
+ }
11
+ return r;
12
+ }
13
+ //#endregion
14
+ export { t as buildMutationInput, e as fieldsOf };
15
+
16
+ //# sourceMappingURL=mutationInput.js.map
@@ -0,0 +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"}
@@ -0,0 +1,99 @@
1
+ import { useBotlit as e } from "../../providers/BotlitProvider.js";
2
+ import { useCallback as t, useEffect as n, useLayoutEffect as r, useRef as i, useState as a } from "react";
3
+ import { useGatewayClient as o } from "@burdenoff/fe-libs/shared/graphql";
4
+ //#region src/botlit/hooks/internal/workspaceGateway.ts
5
+ function s() {
6
+ return o("workspace");
7
+ }
8
+ function c() {
9
+ return e().workspaceId;
10
+ }
11
+ function l(e, t) {
12
+ return e instanceof Error ? e : Error(t);
13
+ }
14
+ function u(e) {
15
+ let t = i(e);
16
+ return r(() => {
17
+ t.current = e;
18
+ }, [e]), t;
19
+ }
20
+ function d(e) {
21
+ let { document: r, variables: i, enabled: o, errorMessage: c } = e, d = s(), f = u(e.select), p = u(e.fallback), [m, h] = a(e.fallback), [g, _] = a(!1), [v, y] = a(), b = t(async () => {
22
+ if (!o) {
23
+ h(p.current), y(void 0);
24
+ return;
25
+ }
26
+ _(!0), y(void 0);
27
+ try {
28
+ let e = await d.query({
29
+ query: r,
30
+ variables: i,
31
+ fetchPolicy: "network-only"
32
+ });
33
+ h(f.current(e.data ?? void 0));
34
+ } catch (e) {
35
+ h(p.current), y(l(e, c));
36
+ } finally {
37
+ _(!1);
38
+ }
39
+ }, [
40
+ d,
41
+ r,
42
+ i,
43
+ o,
44
+ c,
45
+ p,
46
+ f
47
+ ]);
48
+ return n(() => {
49
+ b();
50
+ }, [b]), {
51
+ data: m,
52
+ loading: g,
53
+ error: v,
54
+ refetch: b
55
+ };
56
+ }
57
+ function f(e) {
58
+ let { document: n, errorMessage: r } = e, i = s(), o = u(e.variables), c = u(e.select), [d, f] = a({
59
+ data: void 0,
60
+ loading: !1,
61
+ error: void 0
62
+ });
63
+ return [t(async (e) => {
64
+ f({
65
+ data: void 0,
66
+ loading: !0,
67
+ error: void 0
68
+ });
69
+ try {
70
+ let t = await i.mutate({
71
+ mutation: n,
72
+ variables: o.current(e)
73
+ }), a = c.current(t.data ?? void 0);
74
+ if (a === void 0) throw Error(r);
75
+ return f({
76
+ data: a,
77
+ loading: !1,
78
+ error: void 0
79
+ }), a;
80
+ } catch (e) {
81
+ let t = l(e, r);
82
+ throw f({
83
+ data: void 0,
84
+ loading: !1,
85
+ error: t
86
+ }), t;
87
+ }
88
+ }, [
89
+ i,
90
+ n,
91
+ r,
92
+ c,
93
+ o
94
+ ]), d];
95
+ }
96
+ //#endregion
97
+ export { c as useWorkspaceId, f as useWorkspaceMutation, d as useWorkspaceQuery };
98
+
99
+ //# sourceMappingURL=workspaceGateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceGateway.js","names":[],"sources":["../../../../src/botlit/hooks/internal/workspaceGateway.ts"],"sourcesContent":["/**\n * Workspace gateway hook primitives\n * @module botlit/hooks/internal\n *\n * Every Botlit hook talks to the workspace public gateway through the Apollo\n * client the shell installs (`useGatewayClient('workspace')`) — never through a\n * client of its own. These primitives capture the exact shape used by the\n * reference hooks (`useAgents`, `useBots`): `network-only` reads, an explicit\n * `Error` in state rather than a thrown promise, and a `refetch` the caller can\n * run after a mutation.\n */\n\nimport type { ApolloClient, DocumentNode } from '@apollo/client';\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { useGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { useBotlit } from '../../providers/BotlitProvider';\n\nexport type WorkspaceClient = ApolloClient;\n\n/** Apollo client for the workspace gateway, provided by the host shell. */\nexport function useWorkspaceClient(): WorkspaceClient {\n return useGatewayClient('workspace');\n}\n\n/** Current workspace id from the Botlit context (undefined until the shell resolves it). */\nexport function useWorkspaceId(): string | undefined {\n return useBotlit().workspaceId;\n}\n\nexport interface QueryResult<T> {\n data: T;\n loading: boolean;\n /** Set only when the request FAILED. An empty `data` with no `error` means \"no records yet\". */\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\nexport interface MutationState<T> {\n data: T | undefined;\n loading: boolean;\n error: Error | undefined;\n}\n\nfunction toError(cause: unknown, fallbackMessage: string): Error {\n if (cause instanceof Error) return cause;\n return new Error(fallbackMessage);\n}\n\n/** Keeps a mutable ref pointing at the latest value without re-running effects. */\nfunction useLatest<T>(value: T): { readonly current: T } {\n const ref = useRef(value);\n useLayoutEffect(() => {\n ref.current = value;\n }, [value]);\n return ref;\n}\n\nexport interface WorkspaceQueryOptions<TData, TResult> {\n /** Generated GraphQL document (see `src/generated/wspace-operations.ts`). */\n document: DocumentNode;\n /** Must be referentially stable — memoize at the call site. */\n variables: Record<string, unknown> | undefined;\n /** Projects the raw payload onto the record shape the UI consumes. */\n select: (data: TData | undefined) => TResult;\n /** Value held while disabled or before the first successful read. */\n fallback: TResult;\n /** When false the request is skipped (e.g. no workspace id / no entity id yet). */\n enabled: boolean;\n /** Used when the thrown value is not an Error. */\n errorMessage: string;\n}\n\n/**\n * Reads from the workspace gateway and keeps `{ data, loading, error, refetch }`\n * in sync. `error` is reserved for real failures so callers can tell an empty\n * collection apart from a failed request.\n */\nexport function useWorkspaceQuery<TData, TResult>(\n options: WorkspaceQueryOptions<TData, TResult>\n): QueryResult<TResult> {\n const { document, variables, enabled, errorMessage } = options;\n const client = useWorkspaceClient();\n const selectRef = useLatest(options.select);\n const fallbackRef = useLatest(options.fallback);\n\n const [data, setData] = useState<TResult>(options.fallback);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n\n const refetch = useCallback(async () => {\n if (!enabled) {\n setData(fallbackRef.current);\n setError(undefined);\n return;\n }\n\n setLoading(true);\n setError(undefined);\n try {\n const result = await client.query<TData>({\n query: document,\n variables,\n fetchPolicy: 'network-only',\n });\n setData(selectRef.current(result.data ?? undefined));\n } catch (queryError) {\n setData(fallbackRef.current);\n setError(toError(queryError, errorMessage));\n } finally {\n setLoading(false);\n }\n // fallbackRef/selectRef are stable refs by construction\n }, [client, document, variables, enabled, errorMessage, fallbackRef, selectRef]);\n\n useEffect(() => {\n void refetch();\n }, [refetch]);\n\n return { data, loading, error, refetch };\n}\n\nexport interface WorkspaceMutationOptions<TData, TInput, TResult> {\n /** Generated GraphQL document (see `src/generated/wspace-operations.ts`). */\n document: DocumentNode;\n /** Maps the caller's input onto GraphQL variables. */\n variables: (input: TInput) => Record<string, unknown>;\n /** Projects the raw payload onto the record shape the UI consumes. */\n select: (data: TData | undefined) => TResult | undefined;\n /** Thrown (and stored) when the payload is missing or the request fails. */\n errorMessage: string;\n}\n\n/**\n * Writes to the workspace gateway. Returns the `[mutate, state]` tuple used by\n * the reference hooks. `mutate` REJECTS on failure so callers cannot mistake a\n * failed write for a successful one.\n */\nexport function useWorkspaceMutation<TData, TInput, TResult>(\n options: WorkspaceMutationOptions<TData, TInput, TResult>\n): readonly [(input: TInput) => Promise<TResult>, MutationState<TResult>] {\n const { document, errorMessage } = options;\n const client = useWorkspaceClient();\n const variablesRef = useLatest(options.variables);\n const selectRef = useLatest(options.select);\n\n const [state, setState] = useState<MutationState<TResult>>({\n data: undefined,\n loading: false,\n error: undefined,\n });\n\n const mutate = useCallback(\n async (input: TInput): Promise<TResult> => {\n setState({ data: undefined, loading: true, error: undefined });\n try {\n const result = await client.mutate<TData>({\n mutation: document,\n variables: variablesRef.current(input),\n });\n const selected = selectRef.current(result.data ?? undefined);\n if (selected === undefined) {\n throw new Error(errorMessage);\n }\n setState({ data: selected, loading: false, error: undefined });\n return selected;\n } catch (mutationError) {\n const failure = toError(mutationError, errorMessage);\n setState({ data: undefined, loading: false, error: failure });\n throw failure;\n }\n },\n [client, document, errorMessage, selectRef, variablesRef]\n );\n\n return [mutate, state] as const;\n}\n"],"mappings":";;;;AAqBA,SAAgB,IAAsC;AACpD,QAAO,EAAiB,YAAY;;AAItC,SAAgB,IAAqC;AACnD,QAAO,GAAW,CAAC;;AAiBrB,SAAS,EAAQ,GAAgB,GAAgC;AAE/D,QADI,aAAiB,QAAc,IACxB,MAAM,EAAgB;;AAInC,SAAS,EAAa,GAAmC;CACvD,IAAM,IAAM,EAAO,EAAM;AAIzB,QAHA,QAAsB;AACpB,IAAI,UAAU;IACb,CAAC,EAAM,CAAC,EACJ;;AAuBT,SAAgB,EACd,GACsB;CACtB,IAAM,EAAE,aAAU,cAAW,YAAS,oBAAiB,GACjD,IAAS,GAAoB,EAC7B,IAAY,EAAU,EAAQ,OAAO,EACrC,IAAc,EAAU,EAAQ,SAAS,EAEzC,CAAC,GAAM,KAAW,EAAkB,EAAQ,SAAS,EACrD,CAAC,GAAS,KAAc,EAAS,GAAM,EACvC,CAAC,GAAO,KAAY,GAA6B,EAEjD,IAAU,EAAY,YAAY;AACtC,MAAI,CAAC,GAAS;AAEZ,GADA,EAAQ,EAAY,QAAQ,EAC5B,EAAS,KAAA,EAAU;AACnB;;AAIF,EADA,EAAW,GAAK,EAChB,EAAS,KAAA,EAAU;AACnB,MAAI;GACF,IAAM,IAAS,MAAM,EAAO,MAAa;IACvC,OAAO;IACP;IACA,aAAa;IACd,CAAC;AACF,KAAQ,EAAU,QAAQ,EAAO,QAAQ,KAAA,EAAU,CAAC;WAC7C,GAAY;AAEnB,GADA,EAAQ,EAAY,QAAQ,EAC5B,EAAS,EAAQ,GAAY,EAAa,CAAC;YACnC;AACR,KAAW,GAAM;;IAGlB;EAAC;EAAQ;EAAU;EAAW;EAAS;EAAc;EAAa;EAAU,CAAC;AAMhF,QAJA,QAAgB;AACT,KAAS;IACb,CAAC,EAAQ,CAAC,EAEN;EAAE;EAAM;EAAS;EAAO;EAAS;;AAmB1C,SAAgB,EACd,GACwE;CACxE,IAAM,EAAE,aAAU,oBAAiB,GAC7B,IAAS,GAAoB,EAC7B,IAAe,EAAU,EAAQ,UAAU,EAC3C,IAAY,EAAU,EAAQ,OAAO,EAErC,CAAC,GAAO,KAAY,EAAiC;EACzD,MAAM,KAAA;EACN,SAAS;EACT,OAAO,KAAA;EACR,CAAC;AAyBF,QAAO,CAvBQ,EACb,OAAO,MAAoC;AACzC,IAAS;GAAE,MAAM,KAAA;GAAW,SAAS;GAAM,OAAO,KAAA;GAAW,CAAC;AAC9D,MAAI;GACF,IAAM,IAAS,MAAM,EAAO,OAAc;IACxC,UAAU;IACV,WAAW,EAAa,QAAQ,EAAM;IACvC,CAAC,EACI,IAAW,EAAU,QAAQ,EAAO,QAAQ,KAAA,EAAU;AAC5D,OAAI,MAAa,KAAA,EACf,OAAU,MAAM,EAAa;AAG/B,UADA,EAAS;IAAE,MAAM;IAAU,SAAS;IAAO,OAAO,KAAA;IAAW,CAAC,EACvD;WACA,GAAe;GACtB,IAAM,IAAU,EAAQ,GAAe,EAAa;AAEpD,SADA,EAAS;IAAE,MAAM,KAAA;IAAW,SAAS;IAAO,OAAO;IAAS,CAAC,EACvD;;IAGV;EAAC;EAAQ;EAAU;EAAc;EAAW;EAAa,CAC1D,EAEe,EAAM"}
@@ -0,0 +1,184 @@
1
+ import { buildMutationInput as e, fieldsOf as t } from "./internal/mutationInput.js";
2
+ import { CreateA2ARegistryEntryDocument as n, DeleteA2ARegistryEntryDocument as r, GetA2ARegistryEntryDocument as i, ListA2ARegistryEntriesDocument as a, UpdateA2ARegistryEntryDocument as o } from "../../generated/wspace-operations.js";
3
+ import { useWorkspaceId as s, useWorkspaceMutation as c, useWorkspaceQuery as l } from "./internal/workspaceGateway.js";
4
+ import { useCallback as u, useMemo as d } from "react";
5
+ //#region src/botlit/hooks/useA2A.ts
6
+ var f = 100, p = t({
7
+ agentCard: !0,
8
+ bucketId: !0,
9
+ description: !0,
10
+ entitlements: !0,
11
+ metadata: !0,
12
+ name: !0,
13
+ status: !0,
14
+ tags: !0,
15
+ trustLevel: !0,
16
+ visibility: !0,
17
+ wellKnownUrl: !0,
18
+ workspaceId: !0
19
+ }), m = t({
20
+ agentCard: !0,
21
+ bucketId: !0,
22
+ description: !0,
23
+ entitlements: !0,
24
+ metadata: !0,
25
+ name: !0,
26
+ status: !0,
27
+ tags: !0,
28
+ trustLevel: !0,
29
+ visibility: !0,
30
+ wellKnownUrl: !0
31
+ }), h = [];
32
+ function g(e) {
33
+ return typeof e == "object" && e && !Array.isArray(e) ? e : {};
34
+ }
35
+ function _(e, t = "") {
36
+ return typeof e == "string" ? e : t;
37
+ }
38
+ function v(e) {
39
+ return e === !0;
40
+ }
41
+ function y(e) {
42
+ return Array.isArray(e) ? e.filter((e) => typeof e == "string") : [];
43
+ }
44
+ function b(e) {
45
+ return Array.isArray(e) ? e.map(g) : [];
46
+ }
47
+ function x(e) {
48
+ let t = g(e), n = g(t.capabilities), r = g(t.authentication);
49
+ return {
50
+ url: _(t.url),
51
+ version: _(t.version),
52
+ providerOrganization: _(g(t.provider).organization),
53
+ documentationUrl: _(t.documentationUrl),
54
+ capabilities: {
55
+ streaming: v(n.streaming),
56
+ pushNotifications: v(n.pushNotifications),
57
+ stateTransitionHistory: v(n.stateTransitionHistory)
58
+ },
59
+ authenticationSchemes: y(r.schemes),
60
+ defaultInputModes: y(t.defaultInputModes),
61
+ defaultOutputModes: y(t.defaultOutputModes),
62
+ skills: b(t.skills).map((e, t) => ({
63
+ id: _(e.id, `skill-${t}`),
64
+ name: _(e.name),
65
+ description: _(e.description),
66
+ tags: y(e.tags),
67
+ examples: y(e.examples)
68
+ }))
69
+ };
70
+ }
71
+ function S(e) {
72
+ return b(e).map((e, t) => {
73
+ let n = e.maxHops;
74
+ return {
75
+ id: _(e.id, `entitlement-${t}`),
76
+ sourceType: _(e.sourceType, "unknown"),
77
+ sourceId: _(e.sourceId),
78
+ allowedSkills: y(e.allowedSkills),
79
+ disallowedSkills: y(e.disallowedSkills),
80
+ maxHops: typeof n == "number" ? n : void 0
81
+ };
82
+ });
83
+ }
84
+ function C(e) {
85
+ let t = e.agentCard?.skills;
86
+ return Array.isArray(t) ? t.length : 0;
87
+ }
88
+ function w(e) {
89
+ let t = [];
90
+ if (!e) return {
91
+ valid: !1,
92
+ errors: ["An agent card is required"]
93
+ };
94
+ for (let n of [
95
+ "name",
96
+ "description",
97
+ "url",
98
+ "version"
99
+ ]) (typeof e[n] != "string" || e[n].trim() === "") && t.push(`Agent card is missing "${n}"`);
100
+ return (!Array.isArray(e.skills) || e.skills.length === 0) && t.push("Agent card must advertise at least one skill"), {
101
+ valid: t.length === 0,
102
+ errors: t
103
+ };
104
+ }
105
+ function T(e) {
106
+ return e?.listA2ARegistryEntries ?? h;
107
+ }
108
+ function E(e) {
109
+ let t = s(), n = e?.search?.trim().toLowerCase() ?? "", r = e?.status?.[0], i = e?.visibility?.[0], o = e?.trustLevel?.[0], c = e?.bucketId;
110
+ return l({
111
+ document: a,
112
+ variables: d(() => ({
113
+ filters: {
114
+ workspaceId: t,
115
+ status: r,
116
+ visibility: i,
117
+ trustLevel: o,
118
+ bucketId: c
119
+ },
120
+ pagination: {
121
+ limit: f,
122
+ offset: 0
123
+ }
124
+ }), [
125
+ t,
126
+ r,
127
+ i,
128
+ o,
129
+ c
130
+ ]),
131
+ select: u((e) => {
132
+ let t = T(e);
133
+ return n ? t.filter((e) => e.name.toLowerCase().includes(n) || (e.description ?? "").toLowerCase().includes(n)) : t;
134
+ }, [n]),
135
+ fallback: h,
136
+ enabled: !!t,
137
+ errorMessage: "Failed to load the A2A registry"
138
+ });
139
+ }
140
+ function D(e) {
141
+ return l({
142
+ document: i,
143
+ variables: d(() => ({ id: e ?? "" }), [e]),
144
+ select: (e) => e?.getA2ARegistryEntry ?? null,
145
+ fallback: null,
146
+ enabled: !!e,
147
+ errorMessage: "Failed to load A2A agent"
148
+ });
149
+ }
150
+ function O() {
151
+ let t = s();
152
+ return c({
153
+ document: n,
154
+ variables: u((n) => ({ input: e({
155
+ ...n,
156
+ workspaceId: t
157
+ }, p) }), [t]),
158
+ select: (e) => e?.createA2ARegistryEntry,
159
+ errorMessage: "Failed to register A2A agent"
160
+ });
161
+ }
162
+ function k() {
163
+ return c({
164
+ document: o,
165
+ variables: ({ agentId: t, input: n }) => ({
166
+ id: t,
167
+ input: e(n, m)
168
+ }),
169
+ select: (e) => e?.updateA2ARegistryEntry,
170
+ errorMessage: "Failed to update A2A agent"
171
+ });
172
+ }
173
+ function A() {
174
+ return c({
175
+ document: r,
176
+ variables: (e) => ({ id: e }),
177
+ select: (e) => e?.deleteA2ARegistryEntry,
178
+ errorMessage: "Failed to remove A2A agent"
179
+ });
180
+ }
181
+ //#endregion
182
+ export { C as a2aAgentSkillCount, x as readAgentCard, S as readEntitlements, D as useA2AAgent, E as useA2AAgents, A as useDeleteA2AAgent, O as useRegisterA2AAgent, k as useUpdateA2AAgent, w as validateAgentCard };
183
+
184
+ //# sourceMappingURL=useA2A.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useA2A.js","names":[],"sources":["../../../src/botlit/hooks/useA2A.ts"],"sourcesContent":["/**\n * A2A Registry Hooks\n * @module botlit/hooks\n *\n * Backed by the live `listA2ARegistryEntries` / `getA2ARegistryEntry`\n * operations and the create/update/delete mutations on wspace-botlit-svc.\n */\n\nimport { useCallback, useMemo } from 'react';\nimport {\n CreateA2ARegistryEntryDocument,\n DeleteA2ARegistryEntryDocument,\n GetA2ARegistryEntryDocument,\n ListA2ARegistryEntriesDocument,\n UpdateA2ARegistryEntryDocument,\n type CreateA2ARegistryEntryMutation,\n type DeleteA2ARegistryEntryMutation,\n type GetA2ARegistryEntryQuery,\n type ListA2ARegistryEntriesQuery,\n type UpdateA2ARegistryEntryMutation,\n} from '../../generated/wspace-operations';\nimport type {\n CreateA2ARegistryEntryInput,\n UpdateA2ARegistryEntryInput,\n} from '../../generated/wspace-types';\nimport type { A2AAgentFilter } from '../types';\nimport { buildMutationInput, fieldsOf, type GraphQLInput } from './internal/mutationInput';\nimport {\n useWorkspaceId,\n useWorkspaceMutation,\n useWorkspaceQuery,\n type QueryResult,\n} from './internal/workspaceGateway';\n\nconst LIST_LIMIT = 100;\n\nexport interface A2AAgentRecord {\n id: string;\n name: string;\n status: string;\n visibility: string;\n trustLevel: string;\n /** A2A agent card (the `/.well-known/agent.json` document). */\n agentCard: Record<string, unknown>;\n entitlements: Record<string, unknown> | unknown[];\n description?: string | null;\n wellKnownUrl?: string | null;\n bucketId?: string | null;\n metadata?: Record<string, unknown> | null;\n revision: number;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n createdById: string;\n updatedById: string;\n workspaceId: string;\n}\n\n/** `CreateA2ARegistryEntryInput` minus the `workspaceId` the hook supplies. */\nexport type RegisterA2AAgentVariables = Omit<\n GraphQLInput<CreateA2ARegistryEntryInput>,\n 'workspaceId'\n>;\n\nexport interface UpdateA2AAgentVariables {\n agentId: string;\n input: GraphQLInput<UpdateA2ARegistryEntryInput>;\n}\n\nconst REGISTER_AGENT_FIELDS = fieldsOf<CreateA2ARegistryEntryInput>({\n agentCard: true,\n bucketId: true,\n description: true,\n entitlements: true,\n metadata: true,\n name: true,\n status: true,\n tags: true,\n trustLevel: true,\n visibility: true,\n wellKnownUrl: true,\n workspaceId: true,\n});\n\nconst UPDATE_AGENT_FIELDS = fieldsOf<UpdateA2ARegistryEntryInput>({\n agentCard: true,\n bucketId: true,\n description: true,\n entitlements: true,\n metadata: true,\n name: true,\n status: true,\n tags: true,\n trustLevel: true,\n visibility: true,\n wellKnownUrl: true,\n});\n\nexport interface AgentCardValidation {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * The agent-card fields the UI renders. `agentCard` is a free-form `JSON`\n * column on the service, so every field is read defensively — a card that is\n * missing `capabilities`, or that stores `skills` as an object instead of an\n * array, must render as \"not supported\"/\"none\" rather than throw.\n */\nexport interface A2AAgentCardView {\n url: string;\n version: string;\n providerOrganization: string;\n documentationUrl: string;\n capabilities: {\n streaming: boolean;\n pushNotifications: boolean;\n stateTransitionHistory: boolean;\n };\n authenticationSchemes: string[];\n defaultInputModes: string[];\n defaultOutputModes: string[];\n skills: A2AAgentCardSkill[];\n}\n\nexport interface A2AAgentCardSkill {\n id: string;\n name: string;\n description: string;\n tags: string[];\n examples: string[];\n}\n\n/** One row of the `entitlements` JSON, normalised for rendering. */\nexport interface A2AEntitlementView {\n id: string;\n sourceType: string;\n sourceId: string;\n allowedSkills: string[];\n disallowedSkills: string[];\n maxHops?: number;\n}\n\nconst NO_AGENTS: A2AAgentRecord[] = [];\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction asString(value: unknown, fallback = ''): string {\n return typeof value === 'string' ? value : fallback;\n}\n\nfunction asBoolean(value: unknown): boolean {\n return value === true;\n}\n\nfunction asStringArray(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((entry): entry is string => typeof entry === 'string')\n : [];\n}\n\nfunction asObjectArray(value: unknown): Record<string, unknown>[] {\n return Array.isArray(value) ? value.map(asRecord) : [];\n}\n\n/** Reads the renderable view of an A2A agent card out of its JSON document. */\nexport function readAgentCard(card: Record<string, unknown> | undefined): A2AAgentCardView {\n const source = asRecord(card);\n const capabilities = asRecord(source.capabilities);\n const authentication = asRecord(source.authentication);\n\n return {\n url: asString(source.url),\n version: asString(source.version),\n providerOrganization: asString(asRecord(source.provider).organization),\n documentationUrl: asString(source.documentationUrl),\n capabilities: {\n streaming: asBoolean(capabilities.streaming),\n pushNotifications: asBoolean(capabilities.pushNotifications),\n stateTransitionHistory: asBoolean(capabilities.stateTransitionHistory),\n },\n authenticationSchemes: asStringArray(authentication.schemes),\n defaultInputModes: asStringArray(source.defaultInputModes),\n defaultOutputModes: asStringArray(source.defaultOutputModes),\n skills: asObjectArray(source.skills).map((skill, index) => ({\n id: asString(skill.id, `skill-${index}`),\n name: asString(skill.name),\n description: asString(skill.description),\n tags: asStringArray(skill.tags),\n examples: asStringArray(skill.examples),\n })),\n };\n}\n\n/** Reads the entitlement rows out of the `entitlements` JSON column. */\nexport function readEntitlements(\n entitlements: Record<string, unknown> | unknown[] | null | undefined\n): A2AEntitlementView[] {\n return asObjectArray(entitlements).map((entitlement, index) => {\n const maxHops = entitlement.maxHops;\n return {\n id: asString(entitlement.id, `entitlement-${index}`),\n sourceType: asString(entitlement.sourceType, 'unknown'),\n sourceId: asString(entitlement.sourceId),\n allowedSkills: asStringArray(entitlement.allowedSkills),\n disallowedSkills: asStringArray(entitlement.disallowedSkills),\n maxHops: typeof maxHops === 'number' ? maxHops : undefined,\n };\n });\n}\n\n/** Number of skills the registered agent card advertises. */\nexport function a2aAgentSkillCount(agent: Pick<A2AAgentRecord, 'agentCard'>): number {\n const skills = agent.agentCard?.skills;\n return Array.isArray(skills) ? skills.length : 0;\n}\n\n/**\n * Structural check of an A2A agent card before it is registered. This validates\n * the document the caller supplies — it does NOT contact the remote agent.\n */\nexport function validateAgentCard(card: Record<string, unknown> | undefined): AgentCardValidation {\n const errors: string[] = [];\n if (!card) {\n return { valid: false, errors: ['An agent card is required'] };\n }\n for (const field of ['name', 'description', 'url', 'version'] as const) {\n if (typeof card[field] !== 'string' || (card[field] as string).trim() === '') {\n errors.push(`Agent card is missing \"${field}\"`);\n }\n }\n if (!Array.isArray(card.skills) || card.skills.length === 0) {\n errors.push('Agent card must advertise at least one skill');\n }\n return { valid: errors.length === 0, errors };\n}\n\nfunction selectAgents(data: ListA2ARegistryEntriesQuery | undefined): A2AAgentRecord[] {\n return data?.listA2ARegistryEntries ?? NO_AGENTS;\n}\n\nexport const a2aKeys = {\n all: ['a2a'] as const,\n lists: () => [...a2aKeys.all, 'list'] as const,\n list: (filter?: A2AAgentFilter) => [...a2aKeys.lists(), filter] as const,\n details: () => [...a2aKeys.all, 'detail'] as const,\n detail: (id: string) => [...a2aKeys.details(), id] as const,\n};\n\nexport function useA2AAgents(filter?: A2AAgentFilter): QueryResult<A2AAgentRecord[]> {\n const workspaceId = useWorkspaceId();\n const search = filter?.search?.trim().toLowerCase() ?? '';\n const status = filter?.status?.[0];\n const visibility = filter?.visibility?.[0];\n const trustLevel = filter?.trustLevel?.[0];\n const bucketId = filter?.bucketId;\n\n const variables = useMemo(\n () => ({\n // A2ARegistryEntryFilterInput has no free-text field — search is client-side.\n filters: { workspaceId, status, visibility, trustLevel, bucketId },\n pagination: { limit: LIST_LIMIT, offset: 0 },\n }),\n [workspaceId, status, visibility, trustLevel, bucketId]\n );\n\n const select = useCallback(\n (data: ListA2ARegistryEntriesQuery | undefined): A2AAgentRecord[] => {\n const rows = selectAgents(data);\n if (!search) return rows;\n return rows.filter(\n (row) =>\n row.name.toLowerCase().includes(search) ||\n (row.description ?? '').toLowerCase().includes(search)\n );\n },\n [search]\n );\n\n return useWorkspaceQuery<ListA2ARegistryEntriesQuery, A2AAgentRecord[]>({\n document: ListA2ARegistryEntriesDocument,\n variables,\n select,\n fallback: NO_AGENTS,\n enabled: Boolean(workspaceId),\n errorMessage: 'Failed to load the A2A registry',\n });\n}\n\nexport function useA2AAgent(agentId: string | undefined): QueryResult<A2AAgentRecord | null> {\n const variables = useMemo(() => ({ id: agentId ?? '' }), [agentId]);\n\n return useWorkspaceQuery<GetA2ARegistryEntryQuery, A2AAgentRecord | null>({\n document: GetA2ARegistryEntryDocument,\n variables,\n select: (data) => data?.getA2ARegistryEntry ?? null,\n fallback: null,\n enabled: Boolean(agentId),\n errorMessage: 'Failed to load A2A agent',\n });\n}\n\nexport function useRegisterA2AAgent() {\n const workspaceId = useWorkspaceId();\n\n const variables = useCallback(\n (input: RegisterA2AAgentVariables) => ({\n input: buildMutationInput({ ...input, workspaceId }, REGISTER_AGENT_FIELDS),\n }),\n [workspaceId]\n );\n\n return useWorkspaceMutation<\n CreateA2ARegistryEntryMutation,\n RegisterA2AAgentVariables,\n A2AAgentRecord\n >({\n document: CreateA2ARegistryEntryDocument,\n variables,\n select: (data) => data?.createA2ARegistryEntry,\n errorMessage: 'Failed to register A2A agent',\n });\n}\n\nexport function useUpdateA2AAgent() {\n return useWorkspaceMutation<\n UpdateA2ARegistryEntryMutation,\n UpdateA2AAgentVariables,\n A2AAgentRecord\n >({\n document: UpdateA2ARegistryEntryDocument,\n variables: ({ agentId, input }) => ({\n id: agentId,\n input: buildMutationInput(input, UPDATE_AGENT_FIELDS),\n }),\n select: (data) => data?.updateA2ARegistryEntry,\n errorMessage: 'Failed to update A2A agent',\n });\n}\n\nexport function useDeleteA2AAgent() {\n return useWorkspaceMutation<DeleteA2ARegistryEntryMutation, string, boolean>({\n document: DeleteA2ARegistryEntryDocument,\n variables: (agentId) => ({ id: agentId }),\n select: (data) => data?.deleteA2ARegistryEntry,\n errorMessage: 'Failed to remove A2A agent',\n });\n}\n\n/**\n * Validates an agent card locally before registration. There is no server-side\n * validation operation, so this deliberately reports only what can be checked\n * from the document itself.\n */\nexport function useValidateA2AAgent() {\n const validate = useCallback(\n async (card: Record<string, unknown> | undefined): Promise<AgentCardValidation> =>\n validateAgentCard(card),\n []\n );\n\n return [validate, { loading: false, error: undefined }] as const;\n}\n"],"mappings":"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"}