@burdenoff/microfe-botmanor 2026.1027.2 → 2026.1028.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.
- package/dist/botlit/BotlitRoutes.js +142 -132
- package/dist/botlit/BotlitRoutes.js.map +1 -1
- package/dist/botlit/components/AgentApprovalPanel.js +144 -126
- package/dist/botlit/components/AgentApprovalPanel.js.map +1 -1
- package/dist/botlit/components/ModelRegistrationPanel.js +4 -4
- package/dist/botlit/components/RetentionStatusPanel.js +95 -0
- package/dist/botlit/components/RetentionStatusPanel.js.map +1 -0
- package/dist/botlit/components/VersionHistoryPanel.js +92 -83
- package/dist/botlit/components/VersionHistoryPanel.js.map +1 -1
- package/dist/botlit/hooks/index.js +1 -0
- package/dist/botlit/hooks/useRetention.js +31 -0
- package/dist/botlit/hooks/useRetention.js.map +1 -0
- package/dist/botlit/pages/A2AAgentDetailPage.js +212 -203
- package/dist/botlit/pages/A2AAgentDetailPage.js.map +1 -1
- package/dist/botlit/pages/A2ARegistryPage.js +129 -117
- package/dist/botlit/pages/A2ARegistryPage.js.map +1 -1
- package/dist/botlit/pages/AgentApprovalsPage.js +122 -110
- package/dist/botlit/pages/AgentApprovalsPage.js.map +1 -1
- package/dist/botlit/pages/AgentBuilderPage.js +18 -18
- package/dist/botlit/pages/AgentDetailPage.js +298 -273
- package/dist/botlit/pages/AgentDetailPage.js.map +1 -1
- package/dist/botlit/pages/AgentsListPage.js +145 -121
- package/dist/botlit/pages/AgentsListPage.js.map +1 -1
- package/dist/botlit/pages/BotChannelsTab.js +238 -226
- package/dist/botlit/pages/BotChannelsTab.js.map +1 -1
- package/dist/botlit/pages/BotDetailPage.js +307 -288
- package/dist/botlit/pages/BotDetailPage.js.map +1 -1
- package/dist/botlit/pages/BotWorkflowTab.js +125 -116
- package/dist/botlit/pages/BotWorkflowTab.js.map +1 -1
- package/dist/botlit/pages/BotsListPage.js +159 -144
- package/dist/botlit/pages/BotsListPage.js.map +1 -1
- package/dist/botlit/pages/BucketsPage.js +279 -258
- package/dist/botlit/pages/BucketsPage.js.map +1 -1
- package/dist/botlit/pages/ChannelDetailPage.js +346 -328
- package/dist/botlit/pages/ChannelDetailPage.js.map +1 -1
- package/dist/botlit/pages/ChannelRoutesPage.js +10 -10
- package/dist/botlit/pages/ChannelsPage.js +163 -148
- package/dist/botlit/pages/ChannelsPage.js.map +1 -1
- package/dist/botlit/pages/DashboardPage.js +129 -114
- package/dist/botlit/pages/DashboardPage.js.map +1 -1
- package/dist/botlit/pages/ExecutionDetailPage.js +145 -139
- package/dist/botlit/pages/ExecutionDetailPage.js.map +1 -1
- package/dist/botlit/pages/ExecutionsPage.js +14 -14
- package/dist/botlit/pages/InstalledPackagesPage.js +245 -227
- package/dist/botlit/pages/InstalledPackagesPage.js.map +1 -1
- package/dist/botlit/pages/KnowledgeBaseDetailPage.js +168 -156
- package/dist/botlit/pages/KnowledgeBaseDetailPage.js.map +1 -1
- package/dist/botlit/pages/KnowledgeBasesPage.js +91 -79
- package/dist/botlit/pages/KnowledgeBasesPage.js.map +1 -1
- package/dist/botlit/pages/MCPServerDetailPage.js +200 -188
- package/dist/botlit/pages/MCPServerDetailPage.js.map +1 -1
- package/dist/botlit/pages/MCPServersPage.js +170 -155
- package/dist/botlit/pages/MCPServersPage.js.map +1 -1
- package/dist/botlit/pages/PoliciesPage.js +115 -104
- package/dist/botlit/pages/PoliciesPage.js.map +1 -1
- package/dist/botlit/pages/PolicyDetailPage.js +368 -324
- package/dist/botlit/pages/PolicyDetailPage.js.map +1 -1
- package/dist/botlit/pages/PromptStudioPage.js +106 -97
- package/dist/botlit/pages/PromptStudioPage.js.map +1 -1
- package/dist/botlit/pages/PromptTemplateDetailPage.js +359 -347
- package/dist/botlit/pages/PromptTemplateDetailPage.js.map +1 -1
- package/dist/botlit/pages/PromptTemplatesPage.js +127 -112
- package/dist/botlit/pages/PromptTemplatesPage.js.map +1 -1
- package/dist/botlit/pages/RetrievalProfileDetailPage.js +219 -210
- package/dist/botlit/pages/RetrievalProfileDetailPage.js.map +1 -1
- package/dist/botlit/pages/RetrievalProfilesPage.js +112 -103
- package/dist/botlit/pages/RetrievalProfilesPage.js.map +1 -1
- package/dist/botlit/pages/SettingsPage.js +264 -252
- package/dist/botlit/pages/SettingsPage.js.map +1 -1
- package/dist/botlit/pages/SkillDetailPage.js +235 -226
- package/dist/botlit/pages/SkillDetailPage.js.map +1 -1
- package/dist/botlit/pages/SkillsPage.js +115 -106
- package/dist/botlit/pages/SkillsPage.js.map +1 -1
- package/dist/botlit/pages/StorePackageDetailPage.js +194 -188
- package/dist/botlit/pages/StorePackageDetailPage.js.map +1 -1
- package/dist/botlit/pages/StorePage.js +161 -155
- package/dist/botlit/pages/StorePage.js.map +1 -1
- package/dist/botlit/permissions/PermissionRequired.js +45 -0
- package/dist/botlit/permissions/PermissionRequired.js.map +1 -0
- package/dist/botlit/permissions/botmanorPermissions.js +72 -0
- package/dist/botlit/permissions/botmanorPermissions.js.map +1 -0
- package/dist/botlit/permissions/index.js +3 -0
- package/dist/botlit/permissions/useBotmanorPermissions.js +19 -0
- package/dist/botlit/permissions/useBotmanorPermissions.js.map +1 -0
- package/dist/botlit/utils/policyConfig.js +67 -42
- package/dist/botlit/utils/policyConfig.js.map +1 -1
- package/dist/generated/global-types.js.map +1 -1
- package/dist/generated/wspace-operations.js +90 -54
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RetentionStatusPanel.js","names":[],"sources":["../../../src/botlit/components/RetentionStatusPanel.tsx"],"sourcesContent":["/**\n * Retention status panel (BOFF-9661)\n * @module botlit/components\n *\n * Shows the retention periods in force for the workspace (the shortest of its\n * ACTIVE retention policies), the end-of-term erasure grace period and the\n * most recent retention passes, and lets a policy editor run a pass now.\n */\n\nimport type { FC } from 'react';\nimport { toast } from 'sonner';\nimport { Archive, RefreshCw } from 'lucide-react';\nimport { Card, CardHeader, CardTitle, CardContent, CardDescription } from './Card';\nimport { Button } from './Button';\nimport { Badge } from './Badge';\nimport { useApplyRetention, useRetentionStatus } from '../hooks';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { BOTMANOR_PERMISSIONS, BotmanorPermissionGate } from '../permissions';\n\nfunction describePeriod(days: number | null | undefined, zeroLabel: string): string {\n if (days === null || days === undefined) return 'Kept for the life of the workspace';\n if (days === 0) return zeroLabel;\n return `${days} day${days === 1 ? '' : 's'}`;\n}\n\nexport const RetentionStatusPanel: FC = () => {\n const { data: status, loading, error, refetch } = useRetentionStatus();\n const { apply, loading: applying } = useApplyRetention();\n\n const handleApply = async () => {\n try {\n const run = await apply();\n if (run.status === 'COMPLETED') {\n toast.success(\n `Retention applied: ${run.executionsPurged} run payloads and ${run.a2aMessagesPurged} agent messages erased`\n );\n } else {\n toast.error(run.errorMessage ?? 'The retention pass failed');\n }\n } catch (applyError) {\n toast.error(applyError instanceof Error ? applyError.message : 'Failed to apply retention');\n }\n await refetch();\n };\n\n if (error) {\n return null;\n }\n\n const lastRun = status?.recentRuns[0];\n\n return (\n <Card data-testid=\"retention-status-panel\">\n <CardHeader className=\"pb-2\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Archive size={18} />\n Data retention\n </CardTitle>\n <CardDescription>\n Active retention policies are enforced every hour. When a workspace is deleted, its\n BotManor data is erased after{' '}\n {status ? `${status.endOfTermErasureGraceDays} days` : 'the grace period'}.\n </CardDescription>\n </div>\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.POLICY_UPDATE}>\n <Button\n variant=\"outline\"\n size=\"sm\"\n leftIcon={<RefreshCw size={14} />}\n onClick={() => void handleApply()}\n isLoading={applying}\n disabled={loading || !status || status.activePolicyCount === 0}\n >\n Apply now\n </Button>\n </BotmanorPermissionGate>\n </div>\n </CardHeader>\n <CardContent>\n {loading && !status ? (\n <div className=\"h-16 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\" />\n ) : status ? (\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">Run inputs and outputs</p>\n <p className=\"font-medium\" data-testid=\"retention-execution-days\">\n {describePeriod(status.executionDataRetentionDays, 'Erased when the run ends')}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Assistant conversations</p>\n <p className=\"font-medium\" data-testid=\"retention-conversation-days\">\n {describePeriod(status.conversationRetentionDays, 'Erased when the run ends')}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Last pass</p>\n {lastRun ? (\n <p className=\"font-medium flex flex-wrap items-center gap-2\">\n <span>{formatRelativeTime(lastRun.finishedAt)}</span>\n <Badge variant={lastRun.status === 'COMPLETED' ? 'success' : 'destructive'}>\n {lastRun.status === 'COMPLETED'\n ? `${lastRun.executionsPurged + lastRun.a2aMessagesPurged} erased`\n : 'Failed'}\n </Badge>\n </p>\n ) : (\n <p className=\"font-medium\">\n {status.activePolicyCount === 0 ? 'No active retention policy' : 'Not run yet'}\n </p>\n )}\n </div>\n </div>\n ) : null}\n </CardContent>\n </Card>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAmBA,SAAS,EAAe,GAAiC,GAA2B;AAGlF,QAFI,KAAS,OAAmC,uCAC5C,MAAS,IAAU,IAChB,GAAG,EAAK,MAAM,MAAS,IAAI,KAAK;;AAGzC,IAAa,UAAiC;CAC5C,IAAM,EAAE,MAAM,GAAQ,YAAS,UAAO,eAAY,GAAoB,EAChE,EAAE,UAAO,SAAS,MAAa,GAAmB,EAElD,IAAc,YAAY;AAC9B,MAAI;GACF,IAAM,IAAM,MAAM,GAAO;AACzB,GAAI,EAAI,WAAW,cACjB,EAAM,QACJ,sBAAsB,EAAI,iBAAiB,oBAAoB,EAAI,kBAAkB,wBACtF,GAED,EAAM,MAAM,EAAI,gBAAgB,4BAA4B;WAEvD,GAAY;AACnB,KAAM,MAAM,aAAsB,QAAQ,EAAW,UAAU,4BAA4B;;AAE7F,QAAM,GAAS;;AAGjB,KAAI,EACF,QAAO;CAGT,IAAM,IAAU,GAAQ,WAAW;AAEnC,QACE,kBAAC,GAAD;EAAM,eAAY;YAAlB,CACE,kBAAC,GAAD;GAAY,WAAU;aACpB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,GAAD;KAAW,WAAU;eAArB,CACE,kBAAC,GAAD,EAAS,MAAM,IAAM,CAAA,EAAA,iBAEX;QACZ,kBAAC,GAAD,EAAA,UAAA;KAAiB;KAEe;KAC7B,IAAS,GAAG,EAAO,0BAA0B,SAAS;KAAmB;KAC1D,EAAA,CAAA,CACd,EAAA,CAAA,EACN,kBAAC,GAAD;KAAwB,YAAY,EAAqB;eACvD,kBAAC,GAAD;MACE,SAAQ;MACR,MAAK;MACL,UAAU,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA;MACjC,eAAe,KAAK,GAAa;MACjC,WAAW;MACX,UAAU,KAAW,CAAC,KAAU,EAAO,sBAAsB;gBAC9D;MAEQ,CAAA;KACc,CAAA,CACrB;;GACK,CAAA,EACb,kBAAC,GAAD,EAAA,UACG,KAAW,CAAC,IACX,kBAAC,OAAD,EAAK,WAAU,+DAAgE,CAAA,GAC7E,IACF,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;eAAsB;KAA0B,CAAA,EAC7D,kBAAC,KAAD;KAAG,WAAU;KAAc,eAAY;eACpC,EAAe,EAAO,4BAA4B,2BAA2B;KAC5E,CAAA,CACA,EAAA,CAAA;IACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;eAAsB;KAA2B,CAAA,EAC9D,kBAAC,KAAD;KAAG,WAAU;KAAc,eAAY;eACpC,EAAe,EAAO,2BAA2B,2BAA2B;KAC3E,CAAA,CACA,EAAA,CAAA;IACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;eAAsB;KAAa,CAAA,EAC/C,IACC,kBAAC,KAAD;KAAG,WAAU;eAAb,CACE,kBAAC,QAAD,EAAA,UAAO,EAAmB,EAAQ,WAAW,EAAQ,CAAA,EACrD,kBAAC,GAAD;MAAO,SAAS,EAAQ,WAAW,cAAc,YAAY;gBAC1D,EAAQ,WAAW,cAChB,GAAG,EAAQ,mBAAmB,EAAQ,kBAAkB,WACxD;MACE,CAAA,CACN;SAEJ,kBAAC,KAAD;KAAG,WAAU;eACV,EAAO,sBAAsB,IAAI,+BAA+B;KAC/D,CAAA,CAEF,EAAA,CAAA;IACF;OACJ,MACQ,CAAA,CACT"}
|
|
@@ -1,141 +1,150 @@
|
|
|
1
1
|
import { useTr as e } from "../../shared/hooks/useTr.js";
|
|
2
2
|
import { useAgentVersions as t, usePublishAgentVersion as n, useRollbackAgentVersion as r } from "../hooks/useAgents.js";
|
|
3
3
|
import { formatRelativeTime as i } from "../utils/formatters.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
4
|
+
import { BOTMANOR_PERMISSIONS as a } from "../permissions/botmanorPermissions.js";
|
|
5
|
+
import { BotmanorPermissionGate as o } from "../permissions/useBotmanorPermissions.js";
|
|
6
|
+
import { Button as s } from "./Button.js";
|
|
7
|
+
import "../permissions/index.js";
|
|
8
|
+
import { Card as c, CardContent as l, CardDescription as u, CardHeader as d, CardTitle as f } from "./Card.js";
|
|
9
|
+
import { Badge as p } from "./Badge.js";
|
|
10
|
+
import { useState as m } from "react";
|
|
11
|
+
import { AlertDialog as h, AlertDialogAction as g, AlertDialogCancel as _, AlertDialogContent as v, AlertDialogDescription as y, AlertDialogFooter as b, AlertDialogHeader as x, AlertDialogTitle as S, Dialog as ee, DialogContent as C, DialogDescription as w, DialogFooter as T, DialogHeader as E, DialogTitle as D, Textarea as O } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
import { jsx as k, jsxs as A } from "react/jsx-runtime";
|
|
13
|
+
import { CheckCircle2 as j, History as M, Rocket as N, RotateCcw as P } from "lucide-react";
|
|
14
|
+
import { toast as F } from "sonner";
|
|
12
15
|
//#region src/botlit/components/VersionHistoryPanel.tsx
|
|
13
|
-
function
|
|
16
|
+
function I(e) {
|
|
14
17
|
return e === "DRAFT" ? "secondary" : e === "PUBLISHED" ? "success" : "outline";
|
|
15
18
|
}
|
|
16
|
-
var
|
|
17
|
-
let
|
|
18
|
-
if (
|
|
19
|
-
let e = await
|
|
20
|
-
agentId:
|
|
21
|
-
versionId:
|
|
22
|
-
changelog:
|
|
19
|
+
var L = ({ agentId: L, draftVersionId: R, currentVersionId: te, onChanged: z }) => {
|
|
20
|
+
let B = e(), { data: V, loading: H, refetch: U } = t(L), [W, G] = n(), [K, q] = r(), [J, Y] = m(!1), [X, Z] = m(""), [Q, $] = m(null), ne = async () => {
|
|
21
|
+
if (R) try {
|
|
22
|
+
let e = await W({
|
|
23
|
+
agentId: L,
|
|
24
|
+
versionId: R,
|
|
25
|
+
changelog: X
|
|
23
26
|
});
|
|
24
|
-
|
|
27
|
+
F.success(`${B("botlit.agentDetail.versions.publishSuccessPrefix", "Published version")} ${e.version}`), Y(!1), Z(""), await U(), z?.();
|
|
25
28
|
} catch (e) {
|
|
26
|
-
|
|
29
|
+
F.error(e instanceof Error ? e.message : B("botlit.agentDetail.versions.publishError", "Failed to publish version"));
|
|
27
30
|
}
|
|
28
|
-
},
|
|
29
|
-
if (
|
|
30
|
-
let e = await
|
|
31
|
-
agentId:
|
|
32
|
-
targetVersionId:
|
|
31
|
+
}, re = async () => {
|
|
32
|
+
if (Q) try {
|
|
33
|
+
let e = await K({
|
|
34
|
+
agentId: L,
|
|
35
|
+
targetVersionId: Q.id
|
|
33
36
|
});
|
|
34
|
-
|
|
37
|
+
F.success(`${B("botlit.agentDetail.versions.rollbackSuccessPrefix", "Rolled back to version")} ${Q.version} (${B("botlit.agentDetail.versions.rollbackSuccessSuffix", "now")} ${e.version})`), $(null), await U(), z?.();
|
|
35
38
|
} catch (e) {
|
|
36
|
-
|
|
39
|
+
F.error(e instanceof Error ? e.message : B("botlit.agentDetail.versions.rollbackError", "Failed to roll back agent version"));
|
|
37
40
|
}
|
|
38
41
|
};
|
|
39
|
-
return /* @__PURE__ */
|
|
42
|
+
return /* @__PURE__ */ A("div", {
|
|
40
43
|
className: "space-y-6",
|
|
41
44
|
children: [
|
|
42
|
-
/* @__PURE__ */
|
|
45
|
+
/* @__PURE__ */ A(c, { children: [/* @__PURE__ */ A(d, {
|
|
43
46
|
className: "flex flex-row items-start justify-between gap-4",
|
|
44
|
-
children: [/* @__PURE__ */
|
|
47
|
+
children: [/* @__PURE__ */ A("div", { children: [/* @__PURE__ */ A(f, {
|
|
45
48
|
className: "flex items-center gap-2",
|
|
46
|
-
children: [/* @__PURE__ */
|
|
47
|
-
}), /* @__PURE__ */
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
children: [/* @__PURE__ */ k(M, { size: 18 }), B("botlit.agentDetail.versions.title", "Version History")]
|
|
50
|
+
}), /* @__PURE__ */ k(u, { 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.") })] }), R && /* @__PURE__ */ k(o, {
|
|
51
|
+
permission: a.AGENT_PUBLISH,
|
|
52
|
+
children: /* @__PURE__ */ k(s, {
|
|
53
|
+
leftIcon: /* @__PURE__ */ k(N, { size: 16 }),
|
|
54
|
+
onClick: () => Y(!0),
|
|
55
|
+
children: B("botlit.agentDetail.versions.publishDraft", "Publish Draft")
|
|
56
|
+
})
|
|
51
57
|
})]
|
|
52
|
-
}), /* @__PURE__ */
|
|
58
|
+
}), /* @__PURE__ */ k(l, { children: H ? /* @__PURE__ */ k("div", { className: "h-32 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }) : V.length === 0 ? /* @__PURE__ */ k("p", {
|
|
53
59
|
className: "text-text-secondary",
|
|
54
|
-
children:
|
|
55
|
-
}) : /* @__PURE__ */
|
|
60
|
+
children: B("botlit.agentDetail.versions.empty", "No version history yet.")
|
|
61
|
+
}) : /* @__PURE__ */ k("ul", {
|
|
56
62
|
className: "space-y-3",
|
|
57
|
-
children:
|
|
58
|
-
let t = e.id ===
|
|
59
|
-
return /* @__PURE__ */
|
|
63
|
+
children: V.map((e) => {
|
|
64
|
+
let t = e.id === te, n = e.status !== "DRAFT" && !t;
|
|
65
|
+
return /* @__PURE__ */ A("li", {
|
|
60
66
|
className: "flex items-start justify-between gap-4 p-4 border border-border-subtle rounded-lg",
|
|
61
|
-
children: [/* @__PURE__ */
|
|
67
|
+
children: [/* @__PURE__ */ A("div", {
|
|
62
68
|
className: "space-y-1 min-w-0",
|
|
63
69
|
children: [
|
|
64
|
-
/* @__PURE__ */
|
|
70
|
+
/* @__PURE__ */ A("div", {
|
|
65
71
|
className: "flex items-center gap-2 flex-wrap",
|
|
66
72
|
children: [
|
|
67
|
-
/* @__PURE__ */
|
|
73
|
+
/* @__PURE__ */ A("span", {
|
|
68
74
|
className: "font-mono font-medium",
|
|
69
75
|
children: ["v", e.version]
|
|
70
76
|
}),
|
|
71
|
-
/* @__PURE__ */
|
|
72
|
-
variant:
|
|
77
|
+
/* @__PURE__ */ k(p, {
|
|
78
|
+
variant: I(e.status),
|
|
73
79
|
children: e.status
|
|
74
80
|
}),
|
|
75
|
-
t && /* @__PURE__ */
|
|
81
|
+
t && /* @__PURE__ */ A(p, {
|
|
76
82
|
variant: "outline",
|
|
77
83
|
className: "flex items-center gap-1",
|
|
78
|
-
children: [/* @__PURE__ */
|
|
84
|
+
children: [/* @__PURE__ */ k(j, { size: 12 }), B("botlit.agentDetail.versions.liveNow", "Live now")]
|
|
79
85
|
})
|
|
80
86
|
]
|
|
81
87
|
}),
|
|
82
|
-
/* @__PURE__ */
|
|
88
|
+
/* @__PURE__ */ k("p", {
|
|
83
89
|
className: "text-sm text-text-secondary break-words",
|
|
84
|
-
children: e.changelog ||
|
|
90
|
+
children: e.changelog || B("botlit.agentDetail.versions.noChangelog", "No description")
|
|
85
91
|
}),
|
|
86
|
-
/* @__PURE__ */
|
|
92
|
+
/* @__PURE__ */ k("p", {
|
|
87
93
|
className: "text-xs text-text-secondary",
|
|
88
|
-
children: e.status === "DRAFT" ? `${
|
|
94
|
+
children: e.status === "DRAFT" ? `${B("botlit.agentDetail.versions.updated", "Updated")} ${i(e.createdAt)}` : `${B("botlit.agentDetail.versions.published", "Published")} ${i(e.publishedAt ?? e.createdAt)}`
|
|
89
95
|
})
|
|
90
96
|
]
|
|
91
|
-
}), n && /* @__PURE__ */
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
}), n && /* @__PURE__ */ k(o, {
|
|
98
|
+
permission: a.AGENT_ROLLBACK,
|
|
99
|
+
children: /* @__PURE__ */ k(s, {
|
|
100
|
+
variant: "outline",
|
|
101
|
+
size: "sm",
|
|
102
|
+
leftIcon: /* @__PURE__ */ k(P, { size: 14 }),
|
|
103
|
+
onClick: () => $(e),
|
|
104
|
+
children: B("botlit.agentDetail.versions.rollback", "Roll back")
|
|
105
|
+
})
|
|
97
106
|
})]
|
|
98
107
|
}, e.id);
|
|
99
108
|
})
|
|
100
109
|
}) })] }),
|
|
101
|
-
/* @__PURE__ */
|
|
102
|
-
open:
|
|
103
|
-
onOpenChange:
|
|
104
|
-
children: /* @__PURE__ */
|
|
105
|
-
/* @__PURE__ */
|
|
106
|
-
/* @__PURE__ */ O
|
|
107
|
-
value:
|
|
108
|
-
onChange: (e) =>
|
|
109
|
-
placeholder:
|
|
110
|
+
/* @__PURE__ */ k(ee, {
|
|
111
|
+
open: J,
|
|
112
|
+
onOpenChange: Y,
|
|
113
|
+
children: /* @__PURE__ */ A(C, { children: [
|
|
114
|
+
/* @__PURE__ */ A(E, { children: [/* @__PURE__ */ k(D, { children: B("botlit.agentDetail.versions.publishDialog.title", "Publish this version") }), /* @__PURE__ */ k(w, { 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.") })] }),
|
|
115
|
+
/* @__PURE__ */ k(O, {
|
|
116
|
+
value: X,
|
|
117
|
+
onChange: (e) => Z(e.target.value),
|
|
118
|
+
placeholder: B("botlit.agentDetail.versions.publishDialog.placeholder", "e.g. Tightened the system prompt and switched to gpt-4o"),
|
|
110
119
|
rows: 4
|
|
111
120
|
}),
|
|
112
|
-
/* @__PURE__ */
|
|
121
|
+
/* @__PURE__ */ A(T, { children: [/* @__PURE__ */ k(s, {
|
|
113
122
|
variant: "outline",
|
|
114
|
-
onClick: () =>
|
|
115
|
-
children:
|
|
116
|
-
}), /* @__PURE__ */
|
|
117
|
-
isLoading:
|
|
118
|
-
onClick: () => void
|
|
119
|
-
children:
|
|
123
|
+
onClick: () => Y(!1),
|
|
124
|
+
children: B("botlit.common.cancel", "Cancel")
|
|
125
|
+
}), /* @__PURE__ */ k(s, {
|
|
126
|
+
isLoading: G.loading,
|
|
127
|
+
onClick: () => void ne(),
|
|
128
|
+
children: B("botlit.agentDetail.versions.publishDialog.confirm", "Publish")
|
|
120
129
|
})] })
|
|
121
130
|
] })
|
|
122
131
|
}),
|
|
123
|
-
/* @__PURE__ */
|
|
124
|
-
open:
|
|
125
|
-
onOpenChange: (e) => !e &&
|
|
126
|
-
children: /* @__PURE__ */
|
|
127
|
-
onClick: () =>
|
|
128
|
-
children:
|
|
129
|
-
}), /* @__PURE__ */
|
|
130
|
-
disabled:
|
|
131
|
-
onClick: () => void
|
|
132
|
-
children:
|
|
132
|
+
/* @__PURE__ */ k(h, {
|
|
133
|
+
open: Q !== null,
|
|
134
|
+
onOpenChange: (e) => !e && $(null),
|
|
135
|
+
children: /* @__PURE__ */ A(v, { children: [/* @__PURE__ */ A(x, { children: [/* @__PURE__ */ k(S, { children: B("botlit.agentDetail.versions.rollbackDialog.title", "Roll back to this version?") }), /* @__PURE__ */ k(y, { 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__ */ A(b, { children: [/* @__PURE__ */ k(_, {
|
|
136
|
+
onClick: () => $(null),
|
|
137
|
+
children: B("botlit.common.cancel", "Cancel")
|
|
138
|
+
}), /* @__PURE__ */ k(g, {
|
|
139
|
+
disabled: q.loading,
|
|
140
|
+
onClick: () => void re(),
|
|
141
|
+
children: B("botlit.agentDetail.versions.rollbackDialog.confirm", "Roll back")
|
|
133
142
|
})] })] })
|
|
134
143
|
})
|
|
135
144
|
]
|
|
136
145
|
});
|
|
137
146
|
};
|
|
138
147
|
//#endregion
|
|
139
|
-
export {
|
|
148
|
+
export { L as VersionHistoryPanel };
|
|
140
149
|
|
|
141
150
|
//# sourceMappingURL=VersionHistoryPanel.js.map
|
|
@@ -1 +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 { useTr } from '../../shared/hooks/useTr';\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 = useTr();\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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"}
|
|
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 { useTr } from '../../shared/hooks/useTr';\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';\nimport { BOTMANOR_PERMISSIONS, BotmanorPermissionGate } from '../permissions';\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 = useTr();\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 <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.AGENT_PUBLISH}>\n <Button leftIcon={<Rocket size={16} />} onClick={() => setPublishOpen(true)}>\n {t('botlit.agentDetail.versions.publishDraft', 'Publish Draft')}\n </Button>\n </BotmanorPermissionGate>\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 <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.AGENT_ROLLBACK}>\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 </BotmanorPermissionGate>\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,31 @@
|
|
|
1
|
+
import { ApplyBotmanorRetentionDocument as e, BotmanorRetentionStatusDocument as t } from "../../generated/wspace-operations.js";
|
|
2
|
+
import { useWorkspaceId as n, useWorkspaceMutation as r, useWorkspaceQuery as i } from "./internal/workspaceGateway.js";
|
|
3
|
+
//#region src/botlit/hooks/useRetention.ts
|
|
4
|
+
var a = {};
|
|
5
|
+
function o() {
|
|
6
|
+
return i({
|
|
7
|
+
document: t,
|
|
8
|
+
variables: a,
|
|
9
|
+
select: (e) => e?.botmanorRetentionStatus ?? null,
|
|
10
|
+
fallback: null,
|
|
11
|
+
enabled: !!n(),
|
|
12
|
+
errorMessage: "Failed to load retention status"
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function s() {
|
|
16
|
+
let [t, n] = r({
|
|
17
|
+
document: e,
|
|
18
|
+
variables: () => ({}),
|
|
19
|
+
select: (e) => e?.applyBotmanorRetention,
|
|
20
|
+
errorMessage: "Failed to apply retention"
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
apply: t,
|
|
24
|
+
loading: n.loading,
|
|
25
|
+
error: n.error
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { s as useApplyRetention, o as useRetentionStatus };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=useRetention.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRetention.js","names":[],"sources":["../../../src/botlit/hooks/useRetention.ts"],"sourcesContent":["/**\n * Retention hooks (BOFF-9661)\n * @module botlit/hooks\n *\n * Reads the retention settings in force for the workspace and its recent\n * retention passes, and runs a pass on demand. Retention itself is enforced\n * hourly by wspace-botmanor-svc; `applyBotmanorRetention` only runs it now.\n */\n\nimport {\n ApplyBotmanorRetentionDocument,\n BotmanorRetentionStatusDocument,\n type ApplyBotmanorRetentionMutation,\n type BotmanorRetentionStatusQuery,\n} from '../../generated/wspace-operations';\nimport {\n useWorkspaceId,\n useWorkspaceMutation,\n useWorkspaceQuery,\n type QueryResult,\n} from './internal/workspaceGateway';\n\nconst NO_VARIABLES: Record<string, unknown> = {};\n\nexport interface RetentionRunRecord {\n id: string;\n trigger: string;\n status: string;\n executionDataRetentionDays?: number | null;\n conversationRetentionDays?: number | null;\n executionsPurged: number;\n a2aMessagesPurged: number;\n errorMessage?: string | null;\n startedAt: string;\n finishedAt: string;\n}\n\nexport interface RetentionStatusRecord {\n executionDataRetentionDays?: number | null;\n conversationRetentionDays?: number | null;\n activePolicyCount: number;\n endOfTermErasureGraceDays: number;\n recentRuns: RetentionRunRecord[];\n}\n\nexport function useRetentionStatus(): QueryResult<RetentionStatusRecord | null> {\n const workspaceId = useWorkspaceId();\n return useWorkspaceQuery<BotmanorRetentionStatusQuery, RetentionStatusRecord | null>({\n document: BotmanorRetentionStatusDocument,\n // No arguments: the workspace comes from the gateway-verified token.\n variables: NO_VARIABLES,\n select: (data) => data?.botmanorRetentionStatus ?? null,\n fallback: null,\n enabled: Boolean(workspaceId),\n errorMessage: 'Failed to load retention status',\n });\n}\n\nexport function useApplyRetention() {\n const [apply, state] = useWorkspaceMutation<\n ApplyBotmanorRetentionMutation,\n void,\n RetentionRunRecord\n >({\n document: ApplyBotmanorRetentionDocument,\n variables: () => ({}),\n select: (data) => data?.applyBotmanorRetention,\n errorMessage: 'Failed to apply retention',\n });\n return { apply, loading: state.loading, error: state.error };\n}\n"],"mappings":";;;AAsBA,IAAM,IAAwC,EAAE;AAuBhD,SAAgB,IAAgE;AAE9E,QAAO,EAA8E;EACnF,UAAU;EAEV,WAAW;EACX,SAAS,MAAS,GAAM,2BAA2B;EACnD,UAAU;EACV,SAAS,EAPS,GAAgB;EAQlC,cAAc;EACf,CAAC;;AAGJ,SAAgB,IAAoB;CAClC,IAAM,CAAC,GAAO,KAAS,EAIrB;EACA,UAAU;EACV,kBAAkB,EAAE;EACpB,SAAS,MAAS,GAAM;EACxB,cAAc;EACf,CAAC;AACF,QAAO;EAAE;EAAO,SAAS,EAAM;EAAS,OAAO,EAAM;EAAO"}
|