@burdenoff/microfe-botmanor 2026.1027.2 → 2026.1027.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/VersionHistoryPanel.js +92 -83
- package/dist/botlit/components/VersionHistoryPanel.js.map +1 -1
- 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 +113 -104
- package/dist/botlit/pages/PoliciesPage.js.map +1 -1
- package/dist/botlit/pages/PolicyDetailPage.js +145 -133
- 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/package.json +1 -1
|
@@ -1,233 +1,251 @@
|
|
|
1
1
|
import { useTr as e } from "../../shared/hooks/useTr.js";
|
|
2
2
|
import { useBotlit as t } from "../providers/BotlitProvider.js";
|
|
3
3
|
import { formatRelativeTime as n } from "../utils/formatters.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
4
|
+
import { BOTMANOR_PERMISSIONS as r } from "../permissions/botmanorPermissions.js";
|
|
5
|
+
import { BotmanorPermissionGate as i } from "../permissions/useBotmanorPermissions.js";
|
|
6
|
+
import { Button as a } from "./Button.js";
|
|
7
|
+
import "../permissions/index.js";
|
|
8
|
+
import { Card as o, CardContent as s, CardDescription as c, CardHeader as l, CardTitle as u } from "./Card.js";
|
|
9
|
+
import { Badge as d } from "./Badge.js";
|
|
10
|
+
import { useAgentApprovalActions as f, useAgentApprovalRequests as p, useAgentApprovalSettings as m } from "../hooks/useAgentApprovals.js";
|
|
11
|
+
import { useState as h } from "react";
|
|
12
|
+
import { Dialog as g, DialogContent as _, DialogDescription as v, DialogFooter as y, DialogHeader as b, DialogTitle as x, Textarea as S } from "@burdenoff/fe-libs/ui";
|
|
13
|
+
import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
14
|
+
import { AlertTriangle as E, CheckCircle2 as D, Send as O, ShieldCheck as k, XCircle as A } from "lucide-react";
|
|
15
|
+
import { toast as j } from "sonner";
|
|
13
16
|
//#region src/botlit/components/AgentApprovalPanel.tsx
|
|
14
|
-
function
|
|
17
|
+
function M(e) {
|
|
15
18
|
return e === "PENDING" ? "warning" : e === "APPROVED" ? "success" : e === "REJECTED" ? "destructive" : "outline";
|
|
16
19
|
}
|
|
17
|
-
var
|
|
18
|
-
let
|
|
20
|
+
var N = ({ kind: t, loading: n, onClose: r, onConfirm: i }) => {
|
|
21
|
+
let o = e(), [s, c] = h(""), l = t === "reject", u = {
|
|
19
22
|
request: {
|
|
20
|
-
title:
|
|
21
|
-
description:
|
|
22
|
-
confirm:
|
|
23
|
+
title: o("botlit.agentApproval.dialog.request.title", "Request activation"),
|
|
24
|
+
description: o("botlit.agentApproval.dialog.request.description", "A reviewer will check the agent's current prompt, model, tools and limits before it goes live. Changing the agent afterwards makes this request stale."),
|
|
25
|
+
confirm: o("botlit.agentApproval.dialog.request.confirm", "Submit for review")
|
|
23
26
|
},
|
|
24
27
|
approve: {
|
|
25
|
-
title:
|
|
26
|
-
description:
|
|
27
|
-
confirm:
|
|
28
|
+
title: o("botlit.agentApproval.dialog.approve.title", "Approve and go live"),
|
|
29
|
+
description: o("botlit.agentApproval.dialog.approve.description", "Approving publishes the agent's draft and makes it ACTIVE immediately."),
|
|
30
|
+
confirm: o("botlit.agentApproval.dialog.approve.confirm", "Approve")
|
|
28
31
|
},
|
|
29
32
|
reject: {
|
|
30
|
-
title:
|
|
31
|
-
description:
|
|
32
|
-
confirm:
|
|
33
|
+
title: o("botlit.agentApproval.dialog.reject.title", "Reject activation"),
|
|
34
|
+
description: o("botlit.agentApproval.dialog.reject.description", "Tell the requester what needs to change. The agent stays as it is."),
|
|
35
|
+
confirm: o("botlit.agentApproval.dialog.reject.confirm", "Reject")
|
|
33
36
|
}
|
|
34
37
|
}, d = t ? u[t] : null;
|
|
35
|
-
return /* @__PURE__ */
|
|
38
|
+
return /* @__PURE__ */ w(g, {
|
|
36
39
|
open: t !== null,
|
|
37
40
|
onOpenChange: (e) => {
|
|
38
|
-
e || (
|
|
41
|
+
e || (c(""), r());
|
|
39
42
|
},
|
|
40
|
-
children: /* @__PURE__ */
|
|
41
|
-
/* @__PURE__ */
|
|
42
|
-
/* @__PURE__ */ S
|
|
43
|
-
"aria-label": t === "request" ?
|
|
44
|
-
value:
|
|
43
|
+
children: /* @__PURE__ */ T(_, { children: [
|
|
44
|
+
/* @__PURE__ */ T(b, { children: [/* @__PURE__ */ w(x, { children: d?.title }), /* @__PURE__ */ w(v, { children: d?.description })] }),
|
|
45
|
+
/* @__PURE__ */ w(S, {
|
|
46
|
+
"aria-label": t === "request" ? o("botlit.agentApproval.dialog.noteLabel", "Note for the reviewer") : o("botlit.agentApproval.dialog.reasonLabel", "Reason"),
|
|
47
|
+
value: s,
|
|
45
48
|
maxLength: 2e3,
|
|
46
|
-
onChange: (e) =>
|
|
47
|
-
placeholder: t === "request" ?
|
|
49
|
+
onChange: (e) => c(e.target.value),
|
|
50
|
+
placeholder: t === "request" ? o("botlit.agentApproval.dialog.notePlaceholder", "What changed and why (optional)") : l ? o("botlit.agentApproval.dialog.reasonRequiredPlaceholder", "Reason (required)") : o("botlit.agentApproval.dialog.reasonPlaceholder", "Reason (optional)"),
|
|
48
51
|
rows: 4
|
|
49
52
|
}),
|
|
50
|
-
/* @__PURE__ */
|
|
53
|
+
/* @__PURE__ */ T(y, { children: [/* @__PURE__ */ w(a, {
|
|
51
54
|
variant: "outline",
|
|
52
55
|
onClick: () => {
|
|
53
|
-
|
|
56
|
+
c(""), r();
|
|
54
57
|
},
|
|
55
|
-
children:
|
|
56
|
-
}), /* @__PURE__ */
|
|
58
|
+
children: o("botlit.common.cancel", "Cancel")
|
|
59
|
+
}), /* @__PURE__ */ w(a, {
|
|
57
60
|
variant: t === "reject" ? "destructive" : "default",
|
|
58
61
|
isLoading: n,
|
|
59
|
-
disabled: l &&
|
|
62
|
+
disabled: l && s.trim().length === 0,
|
|
60
63
|
onClick: async () => {
|
|
61
|
-
await i(
|
|
64
|
+
await i(s), c("");
|
|
62
65
|
},
|
|
63
66
|
children: d?.confirm
|
|
64
67
|
})] })
|
|
65
68
|
] })
|
|
66
69
|
});
|
|
67
|
-
},
|
|
68
|
-
let
|
|
69
|
-
if (
|
|
70
|
-
|
|
70
|
+
}, P = ({ agentId: g, agentStatus: _, onChanged: v }) => {
|
|
71
|
+
let y = e(), { currentUser: b } = t(), x = m(), S = p({ agentId: g }), { run: P, pending: F } = f(), [I, L] = h(null), R = x.data?.requireActivationApproval === !0, z = S.data.find((e) => e.status === "PENDING") ?? null, B = S.data.filter((e) => e.status !== "PENDING").slice(0, 10), V = z !== null && z.requestedById === b?.id, H = (e) => e && e === b?.id ? y("botlit.agentApproval.you", "you") : e ?? "—", U = async (e) => {
|
|
72
|
+
if (I) try {
|
|
73
|
+
I.kind === "request" ? (await P({
|
|
71
74
|
kind: "request",
|
|
72
|
-
agentId:
|
|
75
|
+
agentId: g,
|
|
73
76
|
note: e
|
|
74
|
-
}),
|
|
77
|
+
}), j.success(y("botlit.agentApproval.toast.requested", "Activation requested"))) : I.kind === "approve" && I.request ? (await P({
|
|
75
78
|
kind: "approve",
|
|
76
|
-
id:
|
|
79
|
+
id: I.request.id,
|
|
77
80
|
reason: e
|
|
78
|
-
}),
|
|
81
|
+
}), j.success(y("botlit.agentApproval.toast.approved", "Approved — the agent is live")), v?.()) : I.kind === "reject" && I.request && (await P({
|
|
79
82
|
kind: "reject",
|
|
80
|
-
id:
|
|
83
|
+
id: I.request.id,
|
|
81
84
|
reason: e
|
|
82
|
-
}),
|
|
85
|
+
}), j.success(y("botlit.agentApproval.toast.rejected", "Activation rejected"))), L(null), await S.refetch();
|
|
83
86
|
} catch (e) {
|
|
84
|
-
|
|
87
|
+
j.error(e instanceof Error ? e.message : y("botlit.agentApproval.toast.error", "Approval action failed"));
|
|
85
88
|
}
|
|
86
|
-
},
|
|
89
|
+
}, W = async (e) => {
|
|
87
90
|
try {
|
|
88
|
-
await
|
|
91
|
+
await P({
|
|
89
92
|
kind: "cancel",
|
|
90
93
|
id: e.id
|
|
91
|
-
}),
|
|
94
|
+
}), j.success(y("botlit.agentApproval.toast.cancelled", "Request cancelled")), await S.refetch();
|
|
92
95
|
} catch (e) {
|
|
93
|
-
|
|
96
|
+
j.error(e instanceof Error ? e.message : y("botlit.agentApproval.toast.error", "Approval action failed"));
|
|
94
97
|
}
|
|
95
98
|
};
|
|
96
|
-
return /* @__PURE__ */
|
|
99
|
+
return /* @__PURE__ */ T(o, {
|
|
97
100
|
"data-testid": "agent-approval-panel",
|
|
98
101
|
children: [
|
|
99
|
-
/* @__PURE__ */
|
|
102
|
+
/* @__PURE__ */ T(l, {
|
|
100
103
|
className: "flex flex-row items-start justify-between gap-4",
|
|
101
|
-
children: [/* @__PURE__ */
|
|
104
|
+
children: [/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ T(u, {
|
|
102
105
|
className: "flex items-center gap-2",
|
|
103
106
|
children: [
|
|
104
|
-
/* @__PURE__ */
|
|
105
|
-
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
-
variant:
|
|
108
|
-
children:
|
|
107
|
+
/* @__PURE__ */ w(k, { size: 18 }),
|
|
108
|
+
y("botlit.agentApproval.title", "Activation approval"),
|
|
109
|
+
/* @__PURE__ */ w(d, {
|
|
110
|
+
variant: R ? "warning" : "outline",
|
|
111
|
+
children: R ? y("botlit.agentApproval.required", "Required in this workspace") : y("botlit.agentApproval.optional", "Optional")
|
|
109
112
|
})
|
|
110
113
|
]
|
|
111
|
-
}), /* @__PURE__ */
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
}), /* @__PURE__ */ w(c, { children: R ? y("botlit.agentApproval.descriptionRequired", "This workspace requires a reviewer to approve an agent before it goes live or before a new version is published.") : y("botlit.agentApproval.descriptionOptional", "You can ask a reviewer to check this agent before it goes live. A workspace admin can make review mandatory on the Approvals page.") })] }), !z && _ !== "ARCHIVED" && /* @__PURE__ */ w(i, {
|
|
115
|
+
permission: r.AGENT_UPDATE,
|
|
116
|
+
children: /* @__PURE__ */ w(a, {
|
|
117
|
+
leftIcon: /* @__PURE__ */ w(O, { size: 16 }),
|
|
118
|
+
onClick: () => L({ kind: "request" }),
|
|
119
|
+
children: y("botlit.agentApproval.requestAction", "Request activation")
|
|
120
|
+
})
|
|
115
121
|
})]
|
|
116
122
|
}),
|
|
117
|
-
/* @__PURE__ */
|
|
123
|
+
/* @__PURE__ */ T(s, {
|
|
118
124
|
className: "space-y-4",
|
|
119
125
|
children: [
|
|
120
|
-
|
|
121
|
-
|
|
126
|
+
S.loading && S.data.length === 0 ? /* @__PURE__ */ w("div", { className: "h-20 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }) : null,
|
|
127
|
+
z && /* @__PURE__ */ T("div", {
|
|
122
128
|
className: "p-4 border border-status-warning-border bg-bg-sunken rounded-lg space-y-2",
|
|
123
129
|
"data-testid": "agent-approval-pending",
|
|
124
130
|
children: [
|
|
125
|
-
/* @__PURE__ */
|
|
131
|
+
/* @__PURE__ */ T("div", {
|
|
126
132
|
className: "flex items-center gap-2 flex-wrap",
|
|
127
|
-
children: [/* @__PURE__ */
|
|
133
|
+
children: [/* @__PURE__ */ w(d, {
|
|
128
134
|
variant: "warning",
|
|
129
|
-
children:
|
|
130
|
-
}), /* @__PURE__ */
|
|
135
|
+
children: z.status
|
|
136
|
+
}), /* @__PURE__ */ T("span", {
|
|
131
137
|
className: "text-sm text-text-secondary",
|
|
132
138
|
children: [
|
|
133
|
-
|
|
139
|
+
y("botlit.agentApproval.requestedBy", "Requested by"),
|
|
134
140
|
" ",
|
|
135
|
-
|
|
141
|
+
H(z.requestedById),
|
|
136
142
|
" ",
|
|
137
|
-
n(
|
|
143
|
+
n(z.createdAt)
|
|
138
144
|
]
|
|
139
145
|
})]
|
|
140
146
|
}),
|
|
141
|
-
|
|
147
|
+
z.requestNote && /* @__PURE__ */ w("p", {
|
|
142
148
|
className: "text-sm break-words",
|
|
143
|
-
children:
|
|
149
|
+
children: z.requestNote
|
|
144
150
|
}),
|
|
145
|
-
|
|
151
|
+
z.isStale && /* @__PURE__ */ T("p", {
|
|
146
152
|
className: "flex items-center gap-2 text-sm text-status-warning-text",
|
|
147
|
-
children: [/* @__PURE__ */
|
|
153
|
+
children: [/* @__PURE__ */ w(E, { size: 14 }), y("botlit.agentApproval.stale", "The agent changed after this request. Submit a new request so the reviewer sees the current configuration.")]
|
|
148
154
|
}),
|
|
149
|
-
/* @__PURE__ */
|
|
155
|
+
/* @__PURE__ */ w("div", {
|
|
150
156
|
className: "flex gap-2 flex-wrap",
|
|
151
|
-
children:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
children:
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
157
|
+
children: V ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(i, {
|
|
158
|
+
permission: r.AGENT_UPDATE,
|
|
159
|
+
children: /* @__PURE__ */ w(a, {
|
|
160
|
+
variant: "outline",
|
|
161
|
+
size: "sm",
|
|
162
|
+
isLoading: F === "cancel",
|
|
163
|
+
onClick: () => void W(z),
|
|
164
|
+
children: y("botlit.agentApproval.cancelAction", "Cancel request")
|
|
165
|
+
})
|
|
166
|
+
}), z.isStale && /* @__PURE__ */ w(i, {
|
|
167
|
+
permission: r.AGENT_UPDATE,
|
|
168
|
+
children: /* @__PURE__ */ w(a, {
|
|
169
|
+
size: "sm",
|
|
170
|
+
onClick: () => L({ kind: "request" }),
|
|
171
|
+
children: y("botlit.agentApproval.resubmitAction", "Submit new request")
|
|
172
|
+
})
|
|
173
|
+
})] }) : /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(i, {
|
|
174
|
+
permission: r.AGENT_APPROVE,
|
|
175
|
+
children: /* @__PURE__ */ w(a, {
|
|
176
|
+
size: "sm",
|
|
177
|
+
leftIcon: /* @__PURE__ */ w(D, { size: 14 }),
|
|
178
|
+
disabled: z.isStale,
|
|
179
|
+
onClick: () => L({
|
|
180
|
+
kind: "approve",
|
|
181
|
+
request: z
|
|
182
|
+
}),
|
|
183
|
+
children: y("botlit.agentApproval.approveAction", "Approve")
|
|
184
|
+
})
|
|
185
|
+
}), /* @__PURE__ */ w(i, {
|
|
186
|
+
permission: r.AGENT_APPROVE,
|
|
187
|
+
children: /* @__PURE__ */ w(a, {
|
|
188
|
+
size: "sm",
|
|
189
|
+
variant: "destructive",
|
|
190
|
+
leftIcon: /* @__PURE__ */ w(A, { size: 14 }),
|
|
191
|
+
onClick: () => L({
|
|
192
|
+
kind: "reject",
|
|
193
|
+
request: z
|
|
194
|
+
}),
|
|
195
|
+
children: y("botlit.agentApproval.rejectAction", "Reject")
|
|
196
|
+
})
|
|
179
197
|
})] })
|
|
180
198
|
})
|
|
181
199
|
]
|
|
182
200
|
}),
|
|
183
|
-
|
|
201
|
+
B.length > 0 && /* @__PURE__ */ T("div", {
|
|
184
202
|
className: "space-y-2",
|
|
185
|
-
children: [/* @__PURE__ */
|
|
203
|
+
children: [/* @__PURE__ */ w("p", {
|
|
186
204
|
className: "text-sm font-medium",
|
|
187
|
-
children:
|
|
188
|
-
}), /* @__PURE__ */
|
|
205
|
+
children: y("botlit.agentApproval.history", "Decision history")
|
|
206
|
+
}), /* @__PURE__ */ w("ul", {
|
|
189
207
|
className: "space-y-2",
|
|
190
208
|
"data-testid": "agent-approval-history",
|
|
191
|
-
children:
|
|
209
|
+
children: B.map((e) => /* @__PURE__ */ T("li", {
|
|
192
210
|
className: "p-3 border border-border-subtle rounded-lg text-sm space-y-1",
|
|
193
|
-
children: [/* @__PURE__ */
|
|
211
|
+
children: [/* @__PURE__ */ T("div", {
|
|
194
212
|
className: "flex items-center gap-2 flex-wrap",
|
|
195
|
-
children: [/* @__PURE__ */
|
|
196
|
-
variant:
|
|
213
|
+
children: [/* @__PURE__ */ w(d, {
|
|
214
|
+
variant: M(e.status),
|
|
197
215
|
children: e.status
|
|
198
|
-
}), /* @__PURE__ */
|
|
216
|
+
}), /* @__PURE__ */ T("span", {
|
|
199
217
|
className: "text-text-secondary",
|
|
200
218
|
children: [
|
|
201
|
-
|
|
219
|
+
y("botlit.agentApproval.decidedBy", "by"),
|
|
202
220
|
" ",
|
|
203
|
-
|
|
221
|
+
H(e.reviewerId),
|
|
204
222
|
" ",
|
|
205
223
|
e.decidedAt ? n(e.decidedAt) : ""
|
|
206
224
|
]
|
|
207
225
|
})]
|
|
208
|
-
}), e.decisionReason && /* @__PURE__ */
|
|
226
|
+
}), e.decisionReason && /* @__PURE__ */ w("p", {
|
|
209
227
|
className: "break-words",
|
|
210
228
|
children: e.decisionReason
|
|
211
229
|
})]
|
|
212
230
|
}, e.id))
|
|
213
231
|
})]
|
|
214
232
|
}),
|
|
215
|
-
!
|
|
233
|
+
!z && B.length === 0 && !S.loading && /* @__PURE__ */ w("p", {
|
|
216
234
|
className: "text-sm text-text-secondary",
|
|
217
|
-
children:
|
|
235
|
+
children: y("botlit.agentApproval.empty", "No activation requests for this agent yet.")
|
|
218
236
|
})
|
|
219
237
|
]
|
|
220
238
|
}),
|
|
221
|
-
/* @__PURE__ */
|
|
222
|
-
kind:
|
|
223
|
-
loading:
|
|
224
|
-
onClose: () =>
|
|
225
|
-
onConfirm:
|
|
239
|
+
/* @__PURE__ */ w(N, {
|
|
240
|
+
kind: I?.kind ?? null,
|
|
241
|
+
loading: F !== null,
|
|
242
|
+
onClose: () => L(null),
|
|
243
|
+
onConfirm: U
|
|
226
244
|
})
|
|
227
245
|
]
|
|
228
246
|
});
|
|
229
247
|
};
|
|
230
248
|
//#endregion
|
|
231
|
-
export {
|
|
249
|
+
export { P as AgentApprovalPanel, N as ApprovalDecisionDialog, M as approvalStatusVariant };
|
|
232
250
|
|
|
233
251
|
//# sourceMappingURL=AgentApprovalPanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentApprovalPanel.js","names":[],"sources":["../../../src/botlit/components/AgentApprovalPanel.tsx"],"sourcesContent":["/**\n * Agent Activation Approval Panel (BOFF-9682)\n * @module botlit/components\n *\n * Reviewer gate on the agent detail page. Builders request activation (the\n * request pins the agent's current config); reviewers with\n * `botmanor-agent:approve` approve it, which publishes the draft and takes the\n * agent live, or reject it with a reason. The requester cannot decide their\n * own request, and a request whose agent changed afterwards is flagged stale\n * and cannot be approved.\n */\n\nimport { useState, type FC } from 'react';\nimport { AlertTriangle, CheckCircle2, ShieldCheck, Send, XCircle } from 'lucide-react';\nimport { toast } from 'sonner';\nimport {\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, CardDescription, CardHeader, CardTitle } from './Card';\nimport { Button } from './Button';\nimport { Badge } from './Badge';\nimport {\n useAgentApprovalActions,\n useAgentApprovalRequests,\n useAgentApprovalSettings,\n type AgentApprovalRequestRecord,\n type AgentApprovalStatus,\n} from '../hooks/useAgentApprovals';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { formatRelativeTime } from '../utils/formatters';\n\nexport function approvalStatusVariant(\n status: AgentApprovalStatus\n): 'warning' | 'success' | 'destructive' | 'outline' {\n if (status === 'PENDING') return 'warning';\n if (status === 'APPROVED') return 'success';\n if (status === 'REJECTED') return 'destructive';\n return 'outline';\n}\n\ntype DecisionKind = 'request' | 'approve' | 'reject';\n\ninterface DecisionDialogProps {\n kind: DecisionKind | null;\n loading: boolean;\n onClose: () => void;\n onConfirm: (text: string) => Promise<void>;\n}\n\n/** Note / reason dialog shared by the detail panel and the approvals page. */\nexport const ApprovalDecisionDialog: FC<DecisionDialogProps> = ({\n kind,\n loading,\n onClose,\n onConfirm,\n}) => {\n const t = useTr();\n const [text, setText] = useState('');\n const reasonRequired = kind === 'reject';\n\n const copy: Record<DecisionKind, { title: string; description: string; confirm: string }> = {\n request: {\n title: t('botlit.agentApproval.dialog.request.title', 'Request activation'),\n description: t(\n 'botlit.agentApproval.dialog.request.description',\n \"A reviewer will check the agent's current prompt, model, tools and limits before it goes live. Changing the agent afterwards makes this request stale.\"\n ),\n confirm: t('botlit.agentApproval.dialog.request.confirm', 'Submit for review'),\n },\n approve: {\n title: t('botlit.agentApproval.dialog.approve.title', 'Approve and go live'),\n description: t(\n 'botlit.agentApproval.dialog.approve.description',\n \"Approving publishes the agent's draft and makes it ACTIVE immediately.\"\n ),\n confirm: t('botlit.agentApproval.dialog.approve.confirm', 'Approve'),\n },\n reject: {\n title: t('botlit.agentApproval.dialog.reject.title', 'Reject activation'),\n description: t(\n 'botlit.agentApproval.dialog.reject.description',\n 'Tell the requester what needs to change. The agent stays as it is.'\n ),\n confirm: t('botlit.agentApproval.dialog.reject.confirm', 'Reject'),\n },\n };\n const current = kind ? copy[kind] : null;\n\n return (\n <Dialog\n open={kind !== null}\n onOpenChange={(open) => {\n if (!open) {\n setText('');\n onClose();\n }\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{current?.title}</DialogTitle>\n <DialogDescription>{current?.description}</DialogDescription>\n </DialogHeader>\n <Textarea\n aria-label={\n kind === 'request'\n ? t('botlit.agentApproval.dialog.noteLabel', 'Note for the reviewer')\n : t('botlit.agentApproval.dialog.reasonLabel', 'Reason')\n }\n value={text}\n maxLength={2000}\n onChange={(event) => setText(event.target.value)}\n placeholder={\n kind === 'request'\n ? t('botlit.agentApproval.dialog.notePlaceholder', 'What changed and why (optional)')\n : reasonRequired\n ? t('botlit.agentApproval.dialog.reasonRequiredPlaceholder', 'Reason (required)')\n : t('botlit.agentApproval.dialog.reasonPlaceholder', 'Reason (optional)')\n }\n rows={4}\n />\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => {\n setText('');\n onClose();\n }}\n >\n {t('botlit.common.cancel', 'Cancel')}\n </Button>\n <Button\n variant={kind === 'reject' ? 'destructive' : 'default'}\n isLoading={loading}\n disabled={reasonRequired && text.trim().length === 0}\n onClick={async () => {\n await onConfirm(text);\n setText('');\n }}\n >\n {current?.confirm}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n};\n\ninterface AgentApprovalPanelProps {\n agentId: string;\n agentStatus: string;\n /** Called after a decision that changes the agent so the page can refetch it. */\n onChanged?: () => void;\n}\n\nexport const AgentApprovalPanel: FC<AgentApprovalPanelProps> = ({\n agentId,\n agentStatus,\n onChanged,\n}) => {\n const t = useTr();\n const { currentUser } = useBotlit();\n const settings = useAgentApprovalSettings();\n const requests = useAgentApprovalRequests({ agentId });\n const { run, pending } = useAgentApprovalActions();\n const [dialog, setDialog] = useState<{\n kind: DecisionKind;\n request?: AgentApprovalRequestRecord;\n } | null>(null);\n\n const required = settings.data?.requireActivationApproval === true;\n const open = requests.data.find((request) => request.status === 'PENDING') ?? null;\n const history = requests.data.filter((request) => request.status !== 'PENDING').slice(0, 10);\n const isRequester = open !== null && open.requestedById === currentUser?.id;\n\n const who = (id?: string | null): string =>\n id && id === currentUser?.id ? t('botlit.agentApproval.you', 'you') : (id ?? '—');\n\n const confirm = async (text: string): Promise<void> => {\n if (!dialog) return;\n try {\n if (dialog.kind === 'request') {\n await run({ kind: 'request', agentId, note: text });\n toast.success(t('botlit.agentApproval.toast.requested', 'Activation requested'));\n } else if (dialog.kind === 'approve' && dialog.request) {\n await run({ kind: 'approve', id: dialog.request.id, reason: text });\n toast.success(t('botlit.agentApproval.toast.approved', 'Approved — the agent is live'));\n onChanged?.();\n } else if (dialog.kind === 'reject' && dialog.request) {\n await run({ kind: 'reject', id: dialog.request.id, reason: text });\n toast.success(t('botlit.agentApproval.toast.rejected', 'Activation rejected'));\n }\n setDialog(null);\n await requests.refetch();\n } catch (err: unknown) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.agentApproval.toast.error', 'Approval action failed')\n );\n }\n };\n\n const cancel = async (request: AgentApprovalRequestRecord): Promise<void> => {\n try {\n await run({ kind: 'cancel', id: request.id });\n toast.success(t('botlit.agentApproval.toast.cancelled', 'Request cancelled'));\n await requests.refetch();\n } catch (err: unknown) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.agentApproval.toast.error', 'Approval action failed')\n );\n }\n };\n\n return (\n <Card data-testid=\"agent-approval-panel\">\n <CardHeader className=\"flex flex-row items-start justify-between gap-4\">\n <div>\n <CardTitle className=\"flex items-center gap-2\">\n <ShieldCheck size={18} />\n {t('botlit.agentApproval.title', 'Activation approval')}\n <Badge variant={required ? 'warning' : 'outline'}>\n {required\n ? t('botlit.agentApproval.required', 'Required in this workspace')\n : t('botlit.agentApproval.optional', 'Optional')}\n </Badge>\n </CardTitle>\n <CardDescription>\n {required\n ? t(\n 'botlit.agentApproval.descriptionRequired',\n 'This workspace requires a reviewer to approve an agent before it goes live or before a new version is published.'\n )\n : t(\n 'botlit.agentApproval.descriptionOptional',\n 'You can ask a reviewer to check this agent before it goes live. A workspace admin can make review mandatory on the Approvals page.'\n )}\n </CardDescription>\n </div>\n {!open && agentStatus !== 'ARCHIVED' && (\n <Button leftIcon={<Send size={16} />} onClick={() => setDialog({ kind: 'request' })}>\n {t('botlit.agentApproval.requestAction', 'Request activation')}\n </Button>\n )}\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {requests.loading && requests.data.length === 0 ? (\n <div className=\"h-20 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\" />\n ) : null}\n\n {open && (\n <div\n className=\"p-4 border border-status-warning-border bg-bg-sunken rounded-lg space-y-2\"\n data-testid=\"agent-approval-pending\"\n >\n <div className=\"flex items-center gap-2 flex-wrap\">\n <Badge variant=\"warning\">{open.status}</Badge>\n <span className=\"text-sm text-text-secondary\">\n {t('botlit.agentApproval.requestedBy', 'Requested by')} {who(open.requestedById)}{' '}\n {formatRelativeTime(open.createdAt)}\n </span>\n </div>\n {open.requestNote && <p className=\"text-sm break-words\">{open.requestNote}</p>}\n {open.isStale && (\n <p className=\"flex items-center gap-2 text-sm text-status-warning-text\">\n <AlertTriangle size={14} />\n {t(\n 'botlit.agentApproval.stale',\n 'The agent changed after this request. Submit a new request so the reviewer sees the current configuration.'\n )}\n </p>\n )}\n <div className=\"flex gap-2 flex-wrap\">\n {isRequester ? (\n <>\n <Button\n variant=\"outline\"\n size=\"sm\"\n isLoading={pending === 'cancel'}\n onClick={() => void cancel(open)}\n >\n {t('botlit.agentApproval.cancelAction', 'Cancel request')}\n </Button>\n {open.isStale && (\n <Button size=\"sm\" onClick={() => setDialog({ kind: 'request' })}>\n {t('botlit.agentApproval.resubmitAction', 'Submit new request')}\n </Button>\n )}\n </>\n ) : (\n <>\n <Button\n size=\"sm\"\n leftIcon={<CheckCircle2 size={14} />}\n disabled={open.isStale}\n onClick={() => setDialog({ kind: 'approve', request: open })}\n >\n {t('botlit.agentApproval.approveAction', 'Approve')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n leftIcon={<XCircle size={14} />}\n onClick={() => setDialog({ kind: 'reject', request: open })}\n >\n {t('botlit.agentApproval.rejectAction', 'Reject')}\n </Button>\n </>\n )}\n </div>\n </div>\n )}\n\n {history.length > 0 && (\n <div className=\"space-y-2\">\n <p className=\"text-sm font-medium\">\n {t('botlit.agentApproval.history', 'Decision history')}\n </p>\n <ul className=\"space-y-2\" data-testid=\"agent-approval-history\">\n {history.map((request) => (\n <li\n key={request.id}\n className=\"p-3 border border-border-subtle rounded-lg text-sm space-y-1\"\n >\n <div className=\"flex items-center gap-2 flex-wrap\">\n <Badge variant={approvalStatusVariant(request.status)}>{request.status}</Badge>\n <span className=\"text-text-secondary\">\n {t('botlit.agentApproval.decidedBy', 'by')} {who(request.reviewerId)}{' '}\n {request.decidedAt ? formatRelativeTime(request.decidedAt) : ''}\n </span>\n </div>\n {request.decisionReason && (\n <p className=\"break-words\">{request.decisionReason}</p>\n )}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {!open && history.length === 0 && !requests.loading && (\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.agentApproval.empty', 'No activation requests for this agent yet.')}\n </p>\n )}\n </CardContent>\n\n <ApprovalDecisionDialog\n kind={dialog?.kind ?? null}\n loading={pending !== null}\n onClose={() => setDialog(null)}\n onConfirm={confirm}\n />\n </Card>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AgentApprovalPanel.js","names":[],"sources":["../../../src/botlit/components/AgentApprovalPanel.tsx"],"sourcesContent":["/**\n * Agent Activation Approval Panel (BOFF-9682)\n * @module botlit/components\n *\n * Reviewer gate on the agent detail page. Builders request activation (the\n * request pins the agent's current config); reviewers with\n * `botmanor-agent:approve` approve it, which publishes the draft and takes the\n * agent live, or reject it with a reason. The requester cannot decide their\n * own request, and a request whose agent changed afterwards is flagged stale\n * and cannot be approved.\n */\n\nimport { useState, type FC } from 'react';\nimport { AlertTriangle, CheckCircle2, ShieldCheck, Send, XCircle } from 'lucide-react';\nimport { toast } from 'sonner';\nimport {\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, CardDescription, CardHeader, CardTitle } from './Card';\nimport { Button } from './Button';\nimport { Badge } from './Badge';\nimport {\n useAgentApprovalActions,\n useAgentApprovalRequests,\n useAgentApprovalSettings,\n type AgentApprovalRequestRecord,\n type AgentApprovalStatus,\n} from '../hooks/useAgentApprovals';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { BOTMANOR_PERMISSIONS, BotmanorPermissionGate } from '../permissions';\n\nexport function approvalStatusVariant(\n status: AgentApprovalStatus\n): 'warning' | 'success' | 'destructive' | 'outline' {\n if (status === 'PENDING') return 'warning';\n if (status === 'APPROVED') return 'success';\n if (status === 'REJECTED') return 'destructive';\n return 'outline';\n}\n\ntype DecisionKind = 'request' | 'approve' | 'reject';\n\ninterface DecisionDialogProps {\n kind: DecisionKind | null;\n loading: boolean;\n onClose: () => void;\n onConfirm: (text: string) => Promise<void>;\n}\n\n/** Note / reason dialog shared by the detail panel and the approvals page. */\nexport const ApprovalDecisionDialog: FC<DecisionDialogProps> = ({\n kind,\n loading,\n onClose,\n onConfirm,\n}) => {\n const t = useTr();\n const [text, setText] = useState('');\n const reasonRequired = kind === 'reject';\n\n const copy: Record<DecisionKind, { title: string; description: string; confirm: string }> = {\n request: {\n title: t('botlit.agentApproval.dialog.request.title', 'Request activation'),\n description: t(\n 'botlit.agentApproval.dialog.request.description',\n \"A reviewer will check the agent's current prompt, model, tools and limits before it goes live. Changing the agent afterwards makes this request stale.\"\n ),\n confirm: t('botlit.agentApproval.dialog.request.confirm', 'Submit for review'),\n },\n approve: {\n title: t('botlit.agentApproval.dialog.approve.title', 'Approve and go live'),\n description: t(\n 'botlit.agentApproval.dialog.approve.description',\n \"Approving publishes the agent's draft and makes it ACTIVE immediately.\"\n ),\n confirm: t('botlit.agentApproval.dialog.approve.confirm', 'Approve'),\n },\n reject: {\n title: t('botlit.agentApproval.dialog.reject.title', 'Reject activation'),\n description: t(\n 'botlit.agentApproval.dialog.reject.description',\n 'Tell the requester what needs to change. The agent stays as it is.'\n ),\n confirm: t('botlit.agentApproval.dialog.reject.confirm', 'Reject'),\n },\n };\n const current = kind ? copy[kind] : null;\n\n return (\n <Dialog\n open={kind !== null}\n onOpenChange={(open) => {\n if (!open) {\n setText('');\n onClose();\n }\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{current?.title}</DialogTitle>\n <DialogDescription>{current?.description}</DialogDescription>\n </DialogHeader>\n <Textarea\n aria-label={\n kind === 'request'\n ? t('botlit.agentApproval.dialog.noteLabel', 'Note for the reviewer')\n : t('botlit.agentApproval.dialog.reasonLabel', 'Reason')\n }\n value={text}\n maxLength={2000}\n onChange={(event) => setText(event.target.value)}\n placeholder={\n kind === 'request'\n ? t('botlit.agentApproval.dialog.notePlaceholder', 'What changed and why (optional)')\n : reasonRequired\n ? t('botlit.agentApproval.dialog.reasonRequiredPlaceholder', 'Reason (required)')\n : t('botlit.agentApproval.dialog.reasonPlaceholder', 'Reason (optional)')\n }\n rows={4}\n />\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => {\n setText('');\n onClose();\n }}\n >\n {t('botlit.common.cancel', 'Cancel')}\n </Button>\n <Button\n variant={kind === 'reject' ? 'destructive' : 'default'}\n isLoading={loading}\n disabled={reasonRequired && text.trim().length === 0}\n onClick={async () => {\n await onConfirm(text);\n setText('');\n }}\n >\n {current?.confirm}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n};\n\ninterface AgentApprovalPanelProps {\n agentId: string;\n agentStatus: string;\n /** Called after a decision that changes the agent so the page can refetch it. */\n onChanged?: () => void;\n}\n\nexport const AgentApprovalPanel: FC<AgentApprovalPanelProps> = ({\n agentId,\n agentStatus,\n onChanged,\n}) => {\n const t = useTr();\n const { currentUser } = useBotlit();\n const settings = useAgentApprovalSettings();\n const requests = useAgentApprovalRequests({ agentId });\n const { run, pending } = useAgentApprovalActions();\n const [dialog, setDialog] = useState<{\n kind: DecisionKind;\n request?: AgentApprovalRequestRecord;\n } | null>(null);\n\n const required = settings.data?.requireActivationApproval === true;\n const open = requests.data.find((request) => request.status === 'PENDING') ?? null;\n const history = requests.data.filter((request) => request.status !== 'PENDING').slice(0, 10);\n const isRequester = open !== null && open.requestedById === currentUser?.id;\n\n const who = (id?: string | null): string =>\n id && id === currentUser?.id ? t('botlit.agentApproval.you', 'you') : (id ?? '—');\n\n const confirm = async (text: string): Promise<void> => {\n if (!dialog) return;\n try {\n if (dialog.kind === 'request') {\n await run({ kind: 'request', agentId, note: text });\n toast.success(t('botlit.agentApproval.toast.requested', 'Activation requested'));\n } else if (dialog.kind === 'approve' && dialog.request) {\n await run({ kind: 'approve', id: dialog.request.id, reason: text });\n toast.success(t('botlit.agentApproval.toast.approved', 'Approved — the agent is live'));\n onChanged?.();\n } else if (dialog.kind === 'reject' && dialog.request) {\n await run({ kind: 'reject', id: dialog.request.id, reason: text });\n toast.success(t('botlit.agentApproval.toast.rejected', 'Activation rejected'));\n }\n setDialog(null);\n await requests.refetch();\n } catch (err: unknown) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.agentApproval.toast.error', 'Approval action failed')\n );\n }\n };\n\n const cancel = async (request: AgentApprovalRequestRecord): Promise<void> => {\n try {\n await run({ kind: 'cancel', id: request.id });\n toast.success(t('botlit.agentApproval.toast.cancelled', 'Request cancelled'));\n await requests.refetch();\n } catch (err: unknown) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.agentApproval.toast.error', 'Approval action failed')\n );\n }\n };\n\n return (\n <Card data-testid=\"agent-approval-panel\">\n <CardHeader className=\"flex flex-row items-start justify-between gap-4\">\n <div>\n <CardTitle className=\"flex items-center gap-2\">\n <ShieldCheck size={18} />\n {t('botlit.agentApproval.title', 'Activation approval')}\n <Badge variant={required ? 'warning' : 'outline'}>\n {required\n ? t('botlit.agentApproval.required', 'Required in this workspace')\n : t('botlit.agentApproval.optional', 'Optional')}\n </Badge>\n </CardTitle>\n <CardDescription>\n {required\n ? t(\n 'botlit.agentApproval.descriptionRequired',\n 'This workspace requires a reviewer to approve an agent before it goes live or before a new version is published.'\n )\n : t(\n 'botlit.agentApproval.descriptionOptional',\n 'You can ask a reviewer to check this agent before it goes live. A workspace admin can make review mandatory on the Approvals page.'\n )}\n </CardDescription>\n </div>\n {!open && agentStatus !== 'ARCHIVED' && (\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.AGENT_UPDATE}>\n <Button leftIcon={<Send size={16} />} onClick={() => setDialog({ kind: 'request' })}>\n {t('botlit.agentApproval.requestAction', 'Request activation')}\n </Button>\n </BotmanorPermissionGate>\n )}\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {requests.loading && requests.data.length === 0 ? (\n <div className=\"h-20 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\" />\n ) : null}\n\n {open && (\n <div\n className=\"p-4 border border-status-warning-border bg-bg-sunken rounded-lg space-y-2\"\n data-testid=\"agent-approval-pending\"\n >\n <div className=\"flex items-center gap-2 flex-wrap\">\n <Badge variant=\"warning\">{open.status}</Badge>\n <span className=\"text-sm text-text-secondary\">\n {t('botlit.agentApproval.requestedBy', 'Requested by')} {who(open.requestedById)}{' '}\n {formatRelativeTime(open.createdAt)}\n </span>\n </div>\n {open.requestNote && <p className=\"text-sm break-words\">{open.requestNote}</p>}\n {open.isStale && (\n <p className=\"flex items-center gap-2 text-sm text-status-warning-text\">\n <AlertTriangle size={14} />\n {t(\n 'botlit.agentApproval.stale',\n 'The agent changed after this request. Submit a new request so the reviewer sees the current configuration.'\n )}\n </p>\n )}\n <div className=\"flex gap-2 flex-wrap\">\n {isRequester ? (\n <>\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.AGENT_UPDATE}>\n <Button\n variant=\"outline\"\n size=\"sm\"\n isLoading={pending === 'cancel'}\n onClick={() => void cancel(open)}\n >\n {t('botlit.agentApproval.cancelAction', 'Cancel request')}\n </Button>\n </BotmanorPermissionGate>\n {open.isStale && (\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.AGENT_UPDATE}>\n <Button size=\"sm\" onClick={() => setDialog({ kind: 'request' })}>\n {t('botlit.agentApproval.resubmitAction', 'Submit new request')}\n </Button>\n </BotmanorPermissionGate>\n )}\n </>\n ) : (\n <>\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.AGENT_APPROVE}>\n <Button\n size=\"sm\"\n leftIcon={<CheckCircle2 size={14} />}\n disabled={open.isStale}\n onClick={() => setDialog({ kind: 'approve', request: open })}\n >\n {t('botlit.agentApproval.approveAction', 'Approve')}\n </Button>\n </BotmanorPermissionGate>\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.AGENT_APPROVE}>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n leftIcon={<XCircle size={14} />}\n onClick={() => setDialog({ kind: 'reject', request: open })}\n >\n {t('botlit.agentApproval.rejectAction', 'Reject')}\n </Button>\n </BotmanorPermissionGate>\n </>\n )}\n </div>\n </div>\n )}\n\n {history.length > 0 && (\n <div className=\"space-y-2\">\n <p className=\"text-sm font-medium\">\n {t('botlit.agentApproval.history', 'Decision history')}\n </p>\n <ul className=\"space-y-2\" data-testid=\"agent-approval-history\">\n {history.map((request) => (\n <li\n key={request.id}\n className=\"p-3 border border-border-subtle rounded-lg text-sm space-y-1\"\n >\n <div className=\"flex items-center gap-2 flex-wrap\">\n <Badge variant={approvalStatusVariant(request.status)}>{request.status}</Badge>\n <span className=\"text-text-secondary\">\n {t('botlit.agentApproval.decidedBy', 'by')} {who(request.reviewerId)}{' '}\n {request.decidedAt ? formatRelativeTime(request.decidedAt) : ''}\n </span>\n </div>\n {request.decisionReason && (\n <p className=\"break-words\">{request.decisionReason}</p>\n )}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {!open && history.length === 0 && !requests.loading && (\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.agentApproval.empty', 'No activation requests for this agent yet.')}\n </p>\n )}\n </CardContent>\n\n <ApprovalDecisionDialog\n kind={dialog?.kind ?? null}\n loading={pending !== null}\n onClose={() => setDialog(null)}\n onConfirm={confirm}\n />\n </Card>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAuCA,SAAgB,EACd,GACmD;AAInD,QAHI,MAAW,YAAkB,YAC7B,MAAW,aAAmB,YAC9B,MAAW,aAAmB,gBAC3B;;AAaT,IAAa,KAAmD,EAC9D,SACA,YACA,YACA,mBACI;CACJ,IAAM,IAAI,GAAO,EACX,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,IAAiB,MAAS,UAE1B,IAAsF;EAC1F,SAAS;GACP,OAAO,EAAE,6CAA6C,qBAAqB;GAC3E,aAAa,EACX,mDACA,yJACD;GACD,SAAS,EAAE,+CAA+C,oBAAoB;GAC/E;EACD,SAAS;GACP,OAAO,EAAE,6CAA6C,sBAAsB;GAC5E,aAAa,EACX,mDACA,yEACD;GACD,SAAS,EAAE,+CAA+C,UAAU;GACrE;EACD,QAAQ;GACN,OAAO,EAAE,4CAA4C,oBAAoB;GACzE,aAAa,EACX,kDACA,qEACD;GACD,SAAS,EAAE,8CAA8C,SAAS;GACnE;EACF,EACK,IAAU,IAAO,EAAK,KAAQ;AAEpC,QACE,kBAAC,GAAD;EACE,MAAM,MAAS;EACf,eAAe,MAAS;AACtB,GAAK,MACH,EAAQ,GAAG,EACX,GAAS;;YAIb,kBAAC,GAAD,EAAA,UAAA;GACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAc,GAAS,OAAoB,CAAA,EAC3C,kBAAC,GAAD,EAAA,UAAoB,GAAS,aAAgC,CAAA,CAChD,EAAA,CAAA;GACf,kBAAC,GAAD;IACE,cACE,MAAS,YACL,EAAE,yCAAyC,wBAAwB,GACnE,EAAE,2CAA2C,SAAS;IAE5D,OAAO;IACP,WAAW;IACX,WAAW,MAAU,EAAQ,EAAM,OAAO,MAAM;IAChD,aACE,MAAS,YACL,EAAE,+CAA+C,kCAAkC,GACnF,IACE,EAAE,yDAAyD,oBAAoB,GAC/E,EAAE,iDAAiD,oBAAoB;IAE/E,MAAM;IACN,CAAA;GACF,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;IACE,SAAQ;IACR,eAAe;AAEb,KADA,EAAQ,GAAG,EACX,GAAS;;cAGV,EAAE,wBAAwB,SAAS;IAC7B,CAAA,EACT,kBAAC,GAAD;IACE,SAAS,MAAS,WAAW,gBAAgB;IAC7C,WAAW;IACX,UAAU,KAAkB,EAAK,MAAM,CAAC,WAAW;IACnD,SAAS,YAAY;AAEnB,KADA,MAAM,EAAU,EAAK,EACrB,EAAQ,GAAG;;cAGZ,GAAS;IACH,CAAA,CACI,EAAA,CAAA;GACD,EAAA,CAAA;EACT,CAAA;GAWA,KAAmD,EAC9D,YACA,gBACA,mBACI;CACJ,IAAM,IAAI,GAAO,EACX,EAAE,mBAAgB,GAAW,EAC7B,IAAW,GAA0B,EACrC,IAAW,EAAyB,EAAE,YAAS,CAAC,EAChD,EAAE,QAAK,eAAY,GAAyB,EAC5C,CAAC,GAAQ,KAAa,EAGlB,KAAK,EAET,IAAW,EAAS,MAAM,8BAA8B,IACxD,IAAO,EAAS,KAAK,MAAM,MAAY,EAAQ,WAAW,UAAU,IAAI,MACxE,IAAU,EAAS,KAAK,QAAQ,MAAY,EAAQ,WAAW,UAAU,CAAC,MAAM,GAAG,GAAG,EACtF,IAAc,MAAS,QAAQ,EAAK,kBAAkB,GAAa,IAEnE,KAAO,MACX,KAAM,MAAO,GAAa,KAAK,EAAE,4BAA4B,MAAM,GAAI,KAAM,KAEzE,IAAU,OAAO,MAAgC;AAChD,QACL,KAAI;AAaF,GAZI,EAAO,SAAS,aAClB,MAAM,EAAI;IAAE,MAAM;IAAW;IAAS,MAAM;IAAM,CAAC,EACnD,EAAM,QAAQ,EAAE,wCAAwC,uBAAuB,CAAC,IACvE,EAAO,SAAS,aAAa,EAAO,WAC7C,MAAM,EAAI;IAAE,MAAM;IAAW,IAAI,EAAO,QAAQ;IAAI,QAAQ;IAAM,CAAC,EACnE,EAAM,QAAQ,EAAE,uCAAuC,+BAA+B,CAAC,EACvF,KAAa,IACJ,EAAO,SAAS,YAAY,EAAO,YAC5C,MAAM,EAAI;IAAE,MAAM;IAAU,IAAI,EAAO,QAAQ;IAAI,QAAQ;IAAM,CAAC,EAClE,EAAM,QAAQ,EAAE,uCAAuC,sBAAsB,CAAC,GAEhF,EAAU,KAAK,EACf,MAAM,EAAS,SAAS;WACjB,GAAc;AACrB,KAAM,MACJ,aAAe,QACX,EAAI,UACJ,EAAE,oCAAoC,yBAAyB,CACpE;;IAIC,IAAS,OAAO,MAAuD;AAC3E,MAAI;AAGF,GAFA,MAAM,EAAI;IAAE,MAAM;IAAU,IAAI,EAAQ;IAAI,CAAC,EAC7C,EAAM,QAAQ,EAAE,wCAAwC,oBAAoB,CAAC,EAC7E,MAAM,EAAS,SAAS;WACjB,GAAc;AACrB,KAAM,MACJ,aAAe,QACX,EAAI,UACJ,EAAE,oCAAoC,yBAAyB,CACpE;;;AAIL,QACE,kBAAC,GAAD;EAAM,eAAY;YAAlB;GACE,kBAAC,GAAD;IAAY,WAAU;cAAtB,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,GAAD;KAAW,WAAU;eAArB;MACE,kBAAC,GAAD,EAAa,MAAM,IAAM,CAAA;MACxB,EAAE,8BAA8B,sBAAsB;MACvD,kBAAC,GAAD;OAAO,SAAS,IAAW,YAAY;iBACpC,IACG,EAAE,iCAAiC,6BAA6B,GAChE,EAAE,iCAAiC,WAAW;OAC5C,CAAA;MACE;QACZ,kBAAC,GAAD,EAAA,UACG,IACG,EACE,4CACA,mHACD,GACD,EACE,4CACA,qIACD,EACW,CAAA,CACd,EAAA,CAAA,EACL,CAAC,KAAQ,MAAgB,cACxB,kBAAC,GAAD;KAAwB,YAAY,EAAqB;eACvD,kBAAC,GAAD;MAAQ,UAAU,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA;MAAE,eAAe,EAAU,EAAE,MAAM,WAAW,CAAC;gBAChF,EAAE,sCAAsC,qBAAqB;MACvD,CAAA;KACc,CAAA,CAEhB;;GACb,kBAAC,GAAD;IAAa,WAAU;cAAvB;KACG,EAAS,WAAW,EAAS,KAAK,WAAW,IAC5C,kBAAC,OAAD,EAAK,WAAU,+DAAgE,CAAA,GAC7E;KAEH,KACC,kBAAC,OAAD;MACE,WAAU;MACV,eAAY;gBAFd;OAIE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SAAO,SAAQ;mBAAW,EAAK;SAAe,CAAA,EAC9C,kBAAC,QAAD;SAAM,WAAU;mBAAhB;UACG,EAAE,oCAAoC,eAAe;UAAC;UAAE,EAAI,EAAK,cAAc;UAAE;UACjF,EAAmB,EAAK,UAAU;UAC9B;WACH;;OACL,EAAK,eAAe,kBAAC,KAAD;QAAG,WAAU;kBAAuB,EAAK;QAAgB,CAAA;OAC7E,EAAK,WACJ,kBAAC,KAAD;QAAG,WAAU;kBAAb,CACE,kBAAC,GAAD,EAAe,MAAM,IAAM,CAAA,EAC1B,EACC,8BACA,6GACD,CACC;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBACZ,IACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;SAAwB,YAAY,EAAqB;mBACvD,kBAAC,GAAD;UACE,SAAQ;UACR,MAAK;UACL,WAAW,MAAY;UACvB,eAAe,KAAK,EAAO,EAAK;oBAE/B,EAAE,qCAAqC,iBAAiB;UAClD,CAAA;SACc,CAAA,EACxB,EAAK,WACJ,kBAAC,GAAD;SAAwB,YAAY,EAAqB;mBACvD,kBAAC,GAAD;UAAQ,MAAK;UAAK,eAAe,EAAU,EAAE,MAAM,WAAW,CAAC;oBAC5D,EAAE,uCAAuC,qBAAqB;UACxD,CAAA;SACc,CAAA,CAE1B,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;SAAwB,YAAY,EAAqB;mBACvD,kBAAC,GAAD;UACE,MAAK;UACL,UAAU,kBAAC,GAAD,EAAc,MAAM,IAAM,CAAA;UACpC,UAAU,EAAK;UACf,eAAe,EAAU;WAAE,MAAM;WAAW,SAAS;WAAM,CAAC;oBAE3D,EAAE,sCAAsC,UAAU;UAC5C,CAAA;SACc,CAAA,EACzB,kBAAC,GAAD;SAAwB,YAAY,EAAqB;mBACvD,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,UAAU,kBAAC,GAAD,EAAS,MAAM,IAAM,CAAA;UAC/B,eAAe,EAAU;WAAE,MAAM;WAAU,SAAS;WAAM,CAAC;oBAE1D,EAAE,qCAAqC,SAAS;UAC1C,CAAA;SACc,CAAA,CACxB,EAAA,CAAA;QAED,CAAA;OACF;;KAGP,EAAQ,SAAS,KAChB,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAE,gCAAgC,mBAAmB;OACpD,CAAA,EACJ,kBAAC,MAAD;OAAI,WAAU;OAAY,eAAY;iBACnC,EAAQ,KAAK,MACZ,kBAAC,MAAD;QAEE,WAAU;kBAFZ,CAIE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAS,EAAsB,EAAQ,OAAO;oBAAG,EAAQ;UAAe,CAAA,EAC/E,kBAAC,QAAD;UAAM,WAAU;oBAAhB;WACG,EAAE,kCAAkC,KAAK;WAAC;WAAE,EAAI,EAAQ,WAAW;WAAE;WACrE,EAAQ,YAAY,EAAmB,EAAQ,UAAU,GAAG;WACxD;YACH;YACL,EAAQ,kBACP,kBAAC,KAAD;SAAG,WAAU;mBAAe,EAAQ;SAAmB,CAAA,CAEtD;UAbE,EAAQ,GAaV,CACL;OACC,CAAA,CACD;;KAGP,CAAC,KAAQ,EAAQ,WAAW,KAAK,CAAC,EAAS,WAC1C,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAE,8BAA8B,6CAA6C;MAC5E,CAAA;KAEM;;GAEd,kBAAC,GAAD;IACE,MAAM,GAAQ,QAAQ;IACtB,SAAS,MAAY;IACrB,eAAe,EAAU,KAAK;IAC9B,WAAW;IACX,CAAA;GACG"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCreateLLMModel as e } from "../hooks/useLLMProviders.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { Button as t } from "./Button.js";
|
|
3
|
+
import { Card as n, CardContent as r, CardHeader as i, CardTitle as a } from "./Card.js";
|
|
4
4
|
import { FormField as o, Input as s } from "./Input.js";
|
|
5
5
|
import { useState as c } from "react";
|
|
6
6
|
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
@@ -12,7 +12,7 @@ function f({ providers: f, onCreated: p }) {
|
|
|
12
12
|
"AZURE_OPENAI",
|
|
13
13
|
"CUSTOM"
|
|
14
14
|
].includes(F?.type ?? ""), L = P.some((e) => e.id === g) && !!(v.trim() && b.trim()) && Number.isSafeInteger(Number(E)) && Number(E) > 0 && (S !== "embedding" || I && Number.isInteger(Number(w)) && Number(w) > 0 && Number(w) <= 16e3) && (S === "embedding" || Number.isSafeInteger(Number(O)) && Number(O) > 0) && (S === "embedding" ? [A] : [A, M]).every((e) => e.trim() !== "" && Number.isFinite(Number(e)) && Number(e) >= 0);
|
|
15
|
-
return /* @__PURE__ */ u(
|
|
15
|
+
return /* @__PURE__ */ u(n, { children: [/* @__PURE__ */ l(i, { children: /* @__PURE__ */ l(a, { children: "Register model" }) }), /* @__PURE__ */ u(r, {
|
|
16
16
|
className: "space-y-4",
|
|
17
17
|
children: [
|
|
18
18
|
/* @__PURE__ */ l("p", {
|
|
@@ -138,7 +138,7 @@ function f({ providers: f, onCreated: p }) {
|
|
|
138
138
|
onChange: (e) => N(e.target.value)
|
|
139
139
|
})
|
|
140
140
|
}),
|
|
141
|
-
/* @__PURE__ */ l(
|
|
141
|
+
/* @__PURE__ */ l(t, {
|
|
142
142
|
disabled: !L,
|
|
143
143
|
isLoading: h,
|
|
144
144
|
onClick: async () => {
|