@burdenoff/microfe-vibecontrols 2026.601.3 → 2026.601.5
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/components/agents/AgentMaintenanceTab.js +373 -0
- package/dist/components/agents/AgentMaintenanceTab.js.map +1 -0
- package/dist/components/shared/ConfirmDialog.js +34 -27
- package/dist/components/shared/ConfirmDialog.js.map +1 -1
- package/dist/generated/wspace-operations.js +1782 -1565
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.js.map +1 -1
- package/dist/index.js +10 -10
- package/dist/pages/AgentDetailsPage.js +1059 -932
- package/dist/pages/AgentDetailsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { useAgentCommandsQuery as e, useAgentSelfUpdateMutation as t, useAgentUpdateCheckLazyQuery as n, useAgentUpdateStatusQuery as r, useNukeVibecontrolsAgentMutation as i, useRunAgentCommandMutation as a, useSetAgentAutoUpdateMutation as o } from "../../generated/wspace-operations.js";
|
|
2
|
+
import { useTr as ee } from "../../shared/hooks/useTr.js";
|
|
3
|
+
import { ConfirmDialog as s } from "../shared/ConfirmDialog.js";
|
|
4
|
+
import { useCallback as c, useMemo as te, useState as l } from "react";
|
|
5
|
+
import { AlertTriangle as ne, ArrowUpCircle as u, Loader2 as d, RefreshCw as f, Terminal as p, Trash2 as re } from "lucide-react";
|
|
6
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
7
|
+
import { Checkbox as g } from "@burdenoff/fe-libs/ui";
|
|
8
|
+
//#region src/components/agents/AgentMaintenanceTab.tsx
|
|
9
|
+
function _(e) {
|
|
10
|
+
return e && typeof e == "object" && !Array.isArray(e) ? e : null;
|
|
11
|
+
}
|
|
12
|
+
function v(e, t) {
|
|
13
|
+
let n = e?.[t];
|
|
14
|
+
return typeof n == "string" ? n : null;
|
|
15
|
+
}
|
|
16
|
+
function y(e, t) {
|
|
17
|
+
let n = e?.[t];
|
|
18
|
+
return typeof n == "boolean" ? n : null;
|
|
19
|
+
}
|
|
20
|
+
var b = "rounded-lg border border-border-default bg-bg-surface p-4 sm:p-5", x = "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50", S = "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md bg-bg-sunken text-text-primary hover:bg-bg-elevated transition-colors disabled:opacity-50", ie = "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md bg-status-error-bg text-text-inverse hover:opacity-80 transition-colors disabled:opacity-50";
|
|
21
|
+
function C({ agentId: C, agentVersion: w, onAfterDestructiveNuke: T }) {
|
|
22
|
+
let E = ee(), [D, O] = l(null), k = c((e, t, n = !1) => {
|
|
23
|
+
O({
|
|
24
|
+
title: e,
|
|
25
|
+
body: t,
|
|
26
|
+
error: n
|
|
27
|
+
});
|
|
28
|
+
}, []), { data: ae, refetch: A } = r({
|
|
29
|
+
variables: { agentId: C },
|
|
30
|
+
fetchPolicy: "cache-and-network"
|
|
31
|
+
}), [oe, { data: se, loading: j }] = n({ fetchPolicy: "network-only" }), [M, { loading: N }] = t(), [P, { loading: ce }] = o(), F = _(ae?.agentUpdateStatus?.data), I = _(F?.lastCheck), L = _(se?.agentUpdateCheck?.data), le = y(F, "enabled") ?? !0, ue = v(L, "latest") ?? v(I, "latest") ?? null, de = y(L, "hasUpdate") ?? y(I, "hasUpdate") ?? !1, [R, fe] = l(""), pe = c(async () => {
|
|
32
|
+
O(null);
|
|
33
|
+
try {
|
|
34
|
+
let e = await oe({ variables: { agentId: C } }), t = _(e.data?.agentUpdateCheck?.data);
|
|
35
|
+
e.data?.agentUpdateCheck?.error ? k(E("agentDetails.maintenance.update", "Update"), e.data.agentUpdateCheck.error, !0) : y(t, "hasUpdate") ? k(E("agentDetails.maintenance.update", "Update"), `Update available: ${v(t, "current")} → ${v(t, "latest")}`) : k(E("agentDetails.maintenance.update", "Update"), `Up to date (${v(t, "current") ?? w ?? "?"}).`);
|
|
36
|
+
} catch (e) {
|
|
37
|
+
k("Update", e instanceof Error ? e.message : String(e), !0);
|
|
38
|
+
}
|
|
39
|
+
}, [
|
|
40
|
+
C,
|
|
41
|
+
oe,
|
|
42
|
+
k,
|
|
43
|
+
E,
|
|
44
|
+
w
|
|
45
|
+
]), z = c(async (e) => {
|
|
46
|
+
O(null);
|
|
47
|
+
try {
|
|
48
|
+
let t = (await M({ variables: {
|
|
49
|
+
agentId: C,
|
|
50
|
+
version: e || null
|
|
51
|
+
} })).data?.agentSelfUpdate, n = _(t?.data);
|
|
52
|
+
t?.error || y(n, "ok") === !1 ? k("Update", v(n, "error") ?? t?.error ?? "Update failed", !0) : k("Update", `Updated → ${v(n, "current") ?? e ?? "latest"} (restart: ${v(n, "restart") ?? "n/a"}).`), await A();
|
|
53
|
+
} catch (e) {
|
|
54
|
+
k("Update", e instanceof Error ? e.message : String(e), !0);
|
|
55
|
+
}
|
|
56
|
+
}, [
|
|
57
|
+
C,
|
|
58
|
+
M,
|
|
59
|
+
k,
|
|
60
|
+
A
|
|
61
|
+
]), me = c(async (e) => {
|
|
62
|
+
try {
|
|
63
|
+
await P({ variables: {
|
|
64
|
+
agentId: C,
|
|
65
|
+
enabled: e
|
|
66
|
+
} }), await A();
|
|
67
|
+
} catch (e) {
|
|
68
|
+
k("Autoupdate", e instanceof Error ? e.message : String(e), !0);
|
|
69
|
+
}
|
|
70
|
+
}, [
|
|
71
|
+
C,
|
|
72
|
+
P,
|
|
73
|
+
A,
|
|
74
|
+
k
|
|
75
|
+
]), { data: B, loading: V, refetch: he } = e({
|
|
76
|
+
variables: { agentId: C },
|
|
77
|
+
fetchPolicy: "cache-and-network"
|
|
78
|
+
}), [ge, { loading: H }] = a(), U = te(() => {
|
|
79
|
+
let e = _(B?.agentCommands?.data)?.commands;
|
|
80
|
+
return Array.isArray(e) ? e : [];
|
|
81
|
+
}, [B]), [W, _e] = l(""), [G, ve] = l(""), [K, q] = l(null), J = U.find((e) => e.name === W), ye = c(() => [W, ...G.trim().length > 0 ? G.trim().split(/\s+/) : []], [W, G]), Y = c(async (e) => {
|
|
82
|
+
O(null);
|
|
83
|
+
try {
|
|
84
|
+
let t = (await ge({ variables: {
|
|
85
|
+
agentId: C,
|
|
86
|
+
argv: e
|
|
87
|
+
} })).data?.runAgentCommand, n = _(t?.data), r = v(n, "stdout") ?? "", i = v(n, "stderr") ?? "", a = n?.exitCode, o = (r || "") + (i ? `\n[stderr]\n${i}` : "") + `\n[exit ${a ?? "?"}]`;
|
|
88
|
+
k(`vibe ${e.join(" ")}`, o.trim() || t?.error || "(no output)", !y(n, "ok"));
|
|
89
|
+
} catch (e) {
|
|
90
|
+
k("Command", e instanceof Error ? e.message : String(e), !0);
|
|
91
|
+
}
|
|
92
|
+
}, [
|
|
93
|
+
C,
|
|
94
|
+
ge,
|
|
95
|
+
k
|
|
96
|
+
]), be = c(() => {
|
|
97
|
+
if (!W) return;
|
|
98
|
+
let e = ye();
|
|
99
|
+
J?.destructive ? q(e) : Y(e);
|
|
100
|
+
}, [
|
|
101
|
+
W,
|
|
102
|
+
ye,
|
|
103
|
+
J,
|
|
104
|
+
Y
|
|
105
|
+
]), [xe, { loading: X }] = i(), [Z, Se] = l(!0), [Q, $] = l(null), Ce = c(async (e) => {
|
|
106
|
+
O(null);
|
|
107
|
+
try {
|
|
108
|
+
let t = (await xe({ variables: {
|
|
109
|
+
agentId: C,
|
|
110
|
+
all: e.all,
|
|
111
|
+
removeConfig: e.removeConfig,
|
|
112
|
+
dryRun: Z
|
|
113
|
+
} })).data?.nukeVibecontrolsAgent, n = _(t?.data), r = v(n, "stdout") ?? "", i = v(n, "stderr") ?? "", a = y(n, "ok") === !0 && !t?.error;
|
|
114
|
+
k(`vibe nuke${e.all ? " --all" : ""}${Z ? " --dry-run" : ""}`, (r + (i ? `\n[stderr]\n${i}` : "")).trim() || t?.error || "(no output)", !a && !!t?.error), a && !Z && await T?.();
|
|
115
|
+
} catch (e) {
|
|
116
|
+
k("Nuke", e instanceof Error ? e.message : String(e), !0);
|
|
117
|
+
}
|
|
118
|
+
}, [
|
|
119
|
+
C,
|
|
120
|
+
xe,
|
|
121
|
+
Z,
|
|
122
|
+
T,
|
|
123
|
+
k
|
|
124
|
+
]);
|
|
125
|
+
return /* @__PURE__ */ h("div", {
|
|
126
|
+
className: "space-y-5",
|
|
127
|
+
children: [
|
|
128
|
+
/* @__PURE__ */ h("section", {
|
|
129
|
+
className: b,
|
|
130
|
+
children: [
|
|
131
|
+
/* @__PURE__ */ h("div", {
|
|
132
|
+
className: "flex items-center gap-2 mb-3",
|
|
133
|
+
children: [/* @__PURE__ */ m(u, { className: "size-5 text-text-secondary" }), /* @__PURE__ */ m("h3", {
|
|
134
|
+
className: "text-base font-semibold text-text-primary",
|
|
135
|
+
children: E("agentDetails.maintenance.updateTitle", "Agent version & updates")
|
|
136
|
+
})]
|
|
137
|
+
}),
|
|
138
|
+
/* @__PURE__ */ h("div", {
|
|
139
|
+
className: "grid grid-cols-2 gap-3 text-sm mb-4",
|
|
140
|
+
children: [/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("div", {
|
|
141
|
+
className: "text-text-muted",
|
|
142
|
+
children: E("agentDetails.maintenance.current", "Current")
|
|
143
|
+
}), /* @__PURE__ */ m("div", {
|
|
144
|
+
className: "font-mono text-text-primary",
|
|
145
|
+
children: w ?? "—"
|
|
146
|
+
})] }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("div", {
|
|
147
|
+
className: "text-text-muted",
|
|
148
|
+
children: E("agentDetails.maintenance.latest", "Latest")
|
|
149
|
+
}), /* @__PURE__ */ h("div", {
|
|
150
|
+
className: "font-mono text-text-primary",
|
|
151
|
+
children: [ue ?? "—", de ? /* @__PURE__ */ m("span", {
|
|
152
|
+
className: "ml-2 text-xs text-status-warning-text",
|
|
153
|
+
children: E("agentDetails.maintenance.updateAvailable", "update available")
|
|
154
|
+
}) : null]
|
|
155
|
+
})] })]
|
|
156
|
+
}),
|
|
157
|
+
/* @__PURE__ */ h("div", {
|
|
158
|
+
className: "flex flex-wrap items-center gap-2 mb-4",
|
|
159
|
+
children: [/* @__PURE__ */ h("button", {
|
|
160
|
+
type: "button",
|
|
161
|
+
onClick: pe,
|
|
162
|
+
disabled: j,
|
|
163
|
+
className: S,
|
|
164
|
+
children: [j ? /* @__PURE__ */ m(d, { className: "size-4 animate-spin" }) : /* @__PURE__ */ m(f, { className: "size-4" }), E("agentDetails.maintenance.check", "Check for updates")]
|
|
165
|
+
}), /* @__PURE__ */ h("button", {
|
|
166
|
+
type: "button",
|
|
167
|
+
onClick: () => z(),
|
|
168
|
+
disabled: N,
|
|
169
|
+
className: x,
|
|
170
|
+
children: [N ? /* @__PURE__ */ m(d, { className: "size-4 animate-spin" }) : /* @__PURE__ */ m(u, { className: "size-4" }), E("agentDetails.maintenance.updateLatest", "Update to latest")]
|
|
171
|
+
})]
|
|
172
|
+
}),
|
|
173
|
+
/* @__PURE__ */ h("div", {
|
|
174
|
+
className: "flex flex-wrap items-center gap-2 mb-4",
|
|
175
|
+
children: [/* @__PURE__ */ m("input", {
|
|
176
|
+
type: "text",
|
|
177
|
+
value: R,
|
|
178
|
+
onChange: (e) => fe(e.target.value),
|
|
179
|
+
placeholder: E("agentDetails.maintenance.versionPlaceholder", "e.g. 2026.601.21"),
|
|
180
|
+
className: "px-3 py-2 text-sm rounded-md bg-bg-sunken border border-border-default text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 font-mono w-44"
|
|
181
|
+
}), /* @__PURE__ */ m("button", {
|
|
182
|
+
type: "button",
|
|
183
|
+
onClick: () => z(R.trim()),
|
|
184
|
+
disabled: N || R.trim().length === 0,
|
|
185
|
+
className: S,
|
|
186
|
+
children: E("agentDetails.maintenance.updateVersion", "Update to version")
|
|
187
|
+
})]
|
|
188
|
+
}),
|
|
189
|
+
/* @__PURE__ */ h("label", {
|
|
190
|
+
className: "flex items-center gap-3 cursor-pointer",
|
|
191
|
+
children: [/* @__PURE__ */ m(g, {
|
|
192
|
+
checked: le,
|
|
193
|
+
disabled: ce,
|
|
194
|
+
onCheckedChange: (e) => me(e === !0)
|
|
195
|
+
}), /* @__PURE__ */ m("span", {
|
|
196
|
+
className: "text-sm text-text-primary",
|
|
197
|
+
children: E("agentDetails.maintenance.autoUpdate", "Automatically install updates when idle (daily background check)")
|
|
198
|
+
})]
|
|
199
|
+
})
|
|
200
|
+
]
|
|
201
|
+
}),
|
|
202
|
+
/* @__PURE__ */ h("section", {
|
|
203
|
+
className: b,
|
|
204
|
+
children: [
|
|
205
|
+
/* @__PURE__ */ h("div", {
|
|
206
|
+
className: "flex items-center justify-between gap-2 mb-3",
|
|
207
|
+
children: [/* @__PURE__ */ h("div", {
|
|
208
|
+
className: "flex items-center gap-2",
|
|
209
|
+
children: [/* @__PURE__ */ m(p, { className: "size-5 text-text-secondary" }), /* @__PURE__ */ m("h3", {
|
|
210
|
+
className: "text-base font-semibold text-text-primary",
|
|
211
|
+
children: E("agentDetails.maintenance.commandsTitle", "Run a command")
|
|
212
|
+
})]
|
|
213
|
+
}), /* @__PURE__ */ m("button", {
|
|
214
|
+
type: "button",
|
|
215
|
+
onClick: () => he(),
|
|
216
|
+
disabled: V,
|
|
217
|
+
className: "text-text-muted hover:text-text-primary",
|
|
218
|
+
"aria-label": E("agentDetails.maintenance.refresh", "Refresh"),
|
|
219
|
+
children: /* @__PURE__ */ m(f, { className: `size-4 ${V ? "animate-spin" : ""}` })
|
|
220
|
+
})]
|
|
221
|
+
}),
|
|
222
|
+
/* @__PURE__ */ m("p", {
|
|
223
|
+
className: "text-xs text-text-muted mb-3",
|
|
224
|
+
children: E("agentDetails.maintenance.commandsHint", "Every agent command can be run here. Destructive commands ask for confirmation.")
|
|
225
|
+
}),
|
|
226
|
+
/* @__PURE__ */ h("div", {
|
|
227
|
+
className: "flex flex-wrap items-end gap-2 mb-3",
|
|
228
|
+
children: [
|
|
229
|
+
/* @__PURE__ */ h("div", {
|
|
230
|
+
className: "flex flex-col gap-1",
|
|
231
|
+
children: [/* @__PURE__ */ m("span", {
|
|
232
|
+
className: "text-xs text-text-muted",
|
|
233
|
+
children: E("agentDetails.maintenance.command", "Command")
|
|
234
|
+
}), /* @__PURE__ */ h("select", {
|
|
235
|
+
value: W,
|
|
236
|
+
onChange: (e) => _e(e.target.value),
|
|
237
|
+
className: "px-3 py-2 text-sm rounded-md bg-bg-sunken border border-border-default text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 min-w-44",
|
|
238
|
+
children: [/* @__PURE__ */ m("option", {
|
|
239
|
+
value: "",
|
|
240
|
+
children: V ? E("agentDetails.maintenance.loading", "Loading…") : E("agentDetails.maintenance.selectCommand", "Select a command…")
|
|
241
|
+
}), U.map((e) => /* @__PURE__ */ h("option", {
|
|
242
|
+
value: e.name,
|
|
243
|
+
children: [e.name, e.destructive ? " ⚠" : ""]
|
|
244
|
+
}, e.name))]
|
|
245
|
+
})]
|
|
246
|
+
}),
|
|
247
|
+
/* @__PURE__ */ h("div", {
|
|
248
|
+
className: "flex flex-col gap-1 flex-1 min-w-44",
|
|
249
|
+
children: [/* @__PURE__ */ m("span", {
|
|
250
|
+
className: "text-xs text-text-muted",
|
|
251
|
+
children: E("agentDetails.maintenance.args", "Arguments (optional)")
|
|
252
|
+
}), /* @__PURE__ */ m("input", {
|
|
253
|
+
type: "text",
|
|
254
|
+
value: G,
|
|
255
|
+
onChange: (e) => ve(e.target.value),
|
|
256
|
+
placeholder: "--json --tail 50",
|
|
257
|
+
className: "px-3 py-2 text-sm rounded-md bg-bg-sunken border border-border-default text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 font-mono w-full"
|
|
258
|
+
})]
|
|
259
|
+
}),
|
|
260
|
+
/* @__PURE__ */ h("button", {
|
|
261
|
+
type: "button",
|
|
262
|
+
onClick: be,
|
|
263
|
+
disabled: H || !W,
|
|
264
|
+
className: x,
|
|
265
|
+
children: [H ? /* @__PURE__ */ m(d, { className: "size-4 animate-spin" }) : /* @__PURE__ */ m(p, { className: "size-4" }), E("agentDetails.maintenance.run", "Run")]
|
|
266
|
+
})
|
|
267
|
+
]
|
|
268
|
+
}),
|
|
269
|
+
J?.description ? /* @__PURE__ */ m("p", {
|
|
270
|
+
className: "text-xs text-text-muted",
|
|
271
|
+
children: J.description
|
|
272
|
+
}) : null
|
|
273
|
+
]
|
|
274
|
+
}),
|
|
275
|
+
/* @__PURE__ */ h("section", {
|
|
276
|
+
className: `${b} border-status-error-bg/40`,
|
|
277
|
+
children: [
|
|
278
|
+
/* @__PURE__ */ h("div", {
|
|
279
|
+
className: "flex items-center gap-2 mb-3",
|
|
280
|
+
children: [/* @__PURE__ */ m(ne, { className: "size-5 text-status-error-text" }), /* @__PURE__ */ m("h3", {
|
|
281
|
+
className: "text-base font-semibold text-text-primary",
|
|
282
|
+
children: E("agentDetails.maintenance.dangerTitle", "Danger zone")
|
|
283
|
+
})]
|
|
284
|
+
}),
|
|
285
|
+
/* @__PURE__ */ h("label", {
|
|
286
|
+
className: "flex items-center gap-3 cursor-pointer mb-3",
|
|
287
|
+
children: [/* @__PURE__ */ m(g, {
|
|
288
|
+
checked: Z,
|
|
289
|
+
onCheckedChange: (e) => Se(e === !0)
|
|
290
|
+
}), /* @__PURE__ */ m("span", {
|
|
291
|
+
className: "text-sm text-text-primary",
|
|
292
|
+
children: E("agentDetails.maintenance.dryRun", "Dry run (preview only — nothing is deleted)")
|
|
293
|
+
})]
|
|
294
|
+
}),
|
|
295
|
+
/* @__PURE__ */ h("div", {
|
|
296
|
+
className: "flex flex-wrap gap-2",
|
|
297
|
+
children: [/* @__PURE__ */ h("button", {
|
|
298
|
+
type: "button",
|
|
299
|
+
onClick: () => $({
|
|
300
|
+
all: !1,
|
|
301
|
+
removeConfig: !1
|
|
302
|
+
}),
|
|
303
|
+
disabled: X,
|
|
304
|
+
className: S,
|
|
305
|
+
children: [X ? /* @__PURE__ */ m(d, { className: "size-4 animate-spin" }) : /* @__PURE__ */ m(re, { className: "size-4" }), E("agentDetails.maintenance.nukeState", "Nuke state")]
|
|
306
|
+
}), /* @__PURE__ */ h("button", {
|
|
307
|
+
type: "button",
|
|
308
|
+
onClick: () => $({
|
|
309
|
+
all: !0,
|
|
310
|
+
removeConfig: !0
|
|
311
|
+
}),
|
|
312
|
+
disabled: X,
|
|
313
|
+
className: ie,
|
|
314
|
+
children: [/* @__PURE__ */ m(re, { className: "size-4" }), E("agentDetails.maintenance.nukeAll", "Nuke everything (--all)")]
|
|
315
|
+
})]
|
|
316
|
+
}),
|
|
317
|
+
/* @__PURE__ */ m("p", {
|
|
318
|
+
className: "text-xs text-text-muted mt-2",
|
|
319
|
+
children: E("agentDetails.maintenance.nukeHint", "“Nuke state” wipes this agent’s data + tracked binaries. “Nuke everything” also removes all VibeControls plugins, secrets, and config across every profile on the host.")
|
|
320
|
+
})
|
|
321
|
+
]
|
|
322
|
+
}),
|
|
323
|
+
D ? /* @__PURE__ */ h("section", {
|
|
324
|
+
className: b,
|
|
325
|
+
children: [/* @__PURE__ */ h("div", {
|
|
326
|
+
className: "flex items-center justify-between mb-2",
|
|
327
|
+
children: [/* @__PURE__ */ m("h4", {
|
|
328
|
+
className: "text-sm font-semibold text-text-primary",
|
|
329
|
+
children: D.title
|
|
330
|
+
}), /* @__PURE__ */ m("button", {
|
|
331
|
+
type: "button",
|
|
332
|
+
onClick: () => O(null),
|
|
333
|
+
className: "text-xs text-text-muted hover:text-text-primary",
|
|
334
|
+
children: E("agentDetails.maintenance.dismiss", "Dismiss")
|
|
335
|
+
})]
|
|
336
|
+
}), /* @__PURE__ */ m("pre", {
|
|
337
|
+
className: `text-xs whitespace-pre-wrap break-words max-h-96 overflow-auto rounded-md p-3 ${D.error ? "bg-status-error-bg-subtle text-status-error-text" : "bg-bg-sunken text-text-primary"}`,
|
|
338
|
+
children: D.body
|
|
339
|
+
})]
|
|
340
|
+
}) : null,
|
|
341
|
+
/* @__PURE__ */ m(s, {
|
|
342
|
+
isOpen: K !== null,
|
|
343
|
+
onClose: () => q(null),
|
|
344
|
+
onConfirm: () => {
|
|
345
|
+
let e = K;
|
|
346
|
+
q(null), e && Y(e);
|
|
347
|
+
},
|
|
348
|
+
title: E("agentDetails.maintenance.confirmCommandTitle", "Run destructive command?"),
|
|
349
|
+
message: E("agentDetails.maintenance.confirmCommandMsg", "This command can change or destroy agent state: {{cmd}}", { cmd: (K ?? []).join(" ") }),
|
|
350
|
+
confirmLabel: E("agentDetails.maintenance.run", "Run"),
|
|
351
|
+
variant: "danger",
|
|
352
|
+
isLoading: H
|
|
353
|
+
}),
|
|
354
|
+
/* @__PURE__ */ m(s, {
|
|
355
|
+
isOpen: Q !== null,
|
|
356
|
+
onClose: () => $(null),
|
|
357
|
+
onConfirm: () => {
|
|
358
|
+
let e = Q;
|
|
359
|
+
$(null), e && Ce(e);
|
|
360
|
+
},
|
|
361
|
+
title: Z ? E("agentDetails.maintenance.confirmNukeDryTitle", "Preview nuke?") : E("agentDetails.maintenance.confirmNukeTitle", "Nuke agent?"),
|
|
362
|
+
message: Q?.all ? E("agentDetails.maintenance.confirmNukeAllMsg", "This wipes ALL state, plugins, secrets and config on the host.") : E("agentDetails.maintenance.confirmNukeStateMsg", "This wipes this agent’s state and tracked binaries."),
|
|
363
|
+
confirmLabel: Z ? E("agentDetails.maintenance.preview", "Preview") : E("agentDetails.maintenance.nuke", "Nuke"),
|
|
364
|
+
variant: "danger",
|
|
365
|
+
isLoading: X
|
|
366
|
+
})
|
|
367
|
+
]
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
//#endregion
|
|
371
|
+
export { C as AgentMaintenanceTab };
|
|
372
|
+
|
|
373
|
+
//# sourceMappingURL=AgentMaintenanceTab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentMaintenanceTab.js","names":[],"sources":["../../../src/components/agents/AgentMaintenanceTab.tsx"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\nimport { ArrowUpCircle, Loader2, RefreshCw, Terminal, Trash2, AlertTriangle } from 'lucide-react';\nimport { Checkbox } from '@burdenoff/fe-libs/ui';\n\nimport {\n useAgentUpdateStatusQuery,\n useAgentUpdateCheckLazyQuery,\n useAgentSelfUpdateMutation,\n useSetAgentAutoUpdateMutation,\n useAgentCommandsQuery,\n useRunAgentCommandMutation,\n useNukeVibecontrolsAgentMutation,\n} from '@/generated/wspace-operations';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { ConfirmDialog } from '../shared/ConfirmDialog';\n\ntype Json = Record<string, unknown> | null | undefined;\n\nfunction asRecord(v: unknown): Record<string, unknown> | null {\n return v && typeof v === 'object' && !Array.isArray(v) ? (v as Record<string, unknown>) : null;\n}\nfunction jstr(obj: Json, key: string): string | null {\n const v = obj?.[key];\n return typeof v === 'string' ? v : null;\n}\nfunction jbool(obj: Json, key: string): boolean | null {\n const v = obj?.[key];\n return typeof v === 'boolean' ? v : null;\n}\n\ninterface CommandInfo {\n name: string;\n description: string;\n destructive?: boolean;\n options?: Array<{ flags: string; description: string }>;\n}\n\ninterface AgentMaintenanceTabProps {\n agentId: string;\n agentVersion?: string | null;\n onAfterDestructiveNuke?: () => void | Promise<void>;\n}\n\nconst SECTION = 'rounded-lg border border-border-default bg-bg-surface p-4 sm:p-5';\nconst BTN_PRIMARY =\n 'inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50';\nconst BTN_NEUTRAL =\n 'inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md bg-bg-sunken text-text-primary hover:bg-bg-elevated transition-colors disabled:opacity-50';\nconst BTN_DANGER =\n 'inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md bg-status-error-bg text-text-inverse hover:opacity-80 transition-colors disabled:opacity-50';\n\nexport function AgentMaintenanceTab({\n agentId,\n agentVersion,\n onAfterDestructiveNuke,\n}: AgentMaintenanceTabProps) {\n const tr = useTr();\n\n // ── Output + toast plumbing (component-local) ───────────────────────────\n const [output, setOutput] = useState<{ title: string; body: string; error?: boolean } | null>(\n null\n );\n const showOutput = useCallback((title: string, body: string, error = false) => {\n setOutput({ title, body, error });\n }, []);\n\n // ── Update / autoupdate ─────────────────────────────────────────────────\n const { data: statusData, refetch: refetchStatus } = useAgentUpdateStatusQuery({\n variables: { agentId },\n fetchPolicy: 'cache-and-network',\n });\n const [checkUpdate, { data: checkData, loading: checking }] = useAgentUpdateCheckLazyQuery({\n fetchPolicy: 'network-only',\n });\n const [selfUpdate, { loading: updating }] = useAgentSelfUpdateMutation();\n const [setAutoUpdate, { loading: togglingAuto }] = useSetAgentAutoUpdateMutation();\n\n const status = asRecord(statusData?.agentUpdateStatus?.data);\n const lastCheck = asRecord(status?.lastCheck);\n const checkResult = asRecord(checkData?.agentUpdateCheck?.data);\n const autoUpdateEnabled = jbool(status, 'enabled') ?? true;\n const latestVersion = jstr(checkResult, 'latest') ?? jstr(lastCheck, 'latest') ?? null;\n const hasUpdate = jbool(checkResult, 'hasUpdate') ?? jbool(lastCheck, 'hasUpdate') ?? false;\n\n const [versionInput, setVersionInput] = useState('');\n\n const handleCheck = useCallback(async () => {\n setOutput(null);\n try {\n const res = await checkUpdate({ variables: { agentId } });\n const d = asRecord(res.data?.agentUpdateCheck?.data);\n if (res.data?.agentUpdateCheck?.error) {\n showOutput(\n tr('agentDetails.maintenance.update', 'Update'),\n res.data.agentUpdateCheck.error,\n true\n );\n } else if (jbool(d, 'hasUpdate')) {\n showOutput(\n tr('agentDetails.maintenance.update', 'Update'),\n `Update available: ${jstr(d, 'current')} → ${jstr(d, 'latest')}`\n );\n } else {\n showOutput(\n tr('agentDetails.maintenance.update', 'Update'),\n `Up to date (${jstr(d, 'current') ?? agentVersion ?? '?'}).`\n );\n }\n } catch (err) {\n showOutput('Update', err instanceof Error ? err.message : String(err), true);\n }\n }, [agentId, checkUpdate, showOutput, tr, agentVersion]);\n\n const runSelfUpdate = useCallback(\n async (version?: string) => {\n setOutput(null);\n try {\n const res = await selfUpdate({ variables: { agentId, version: version || null } });\n const proxy = res.data?.agentSelfUpdate;\n const d = asRecord(proxy?.data);\n if (proxy?.error || jbool(d, 'ok') === false) {\n showOutput(\n 'Update',\n (jstr(d, 'error') ?? proxy?.error ?? 'Update failed') as string,\n true\n );\n } else {\n showOutput(\n 'Update',\n `Updated → ${jstr(d, 'current') ?? version ?? 'latest'} (restart: ${jstr(d, 'restart') ?? 'n/a'}).`\n );\n }\n await refetchStatus();\n } catch (err) {\n showOutput('Update', err instanceof Error ? err.message : String(err), true);\n }\n },\n [agentId, selfUpdate, showOutput, refetchStatus]\n );\n\n const toggleAutoUpdate = useCallback(\n async (enabled: boolean) => {\n try {\n await setAutoUpdate({ variables: { agentId, enabled } });\n await refetchStatus();\n } catch (err) {\n showOutput('Autoupdate', err instanceof Error ? err.message : String(err), true);\n }\n },\n [agentId, setAutoUpdate, refetchStatus, showOutput]\n );\n\n // ── Command runner ──────────────────────────────────────────────────────\n const {\n data: cmdData,\n loading: cmdsLoading,\n refetch: refetchCmds,\n } = useAgentCommandsQuery({\n variables: { agentId },\n fetchPolicy: 'cache-and-network',\n });\n const [runCommand, { loading: running }] = useRunAgentCommandMutation();\n\n const commands = useMemo<CommandInfo[]>(() => {\n const raw = asRecord(cmdData?.agentCommands?.data)?.commands;\n return Array.isArray(raw) ? (raw as CommandInfo[]) : [];\n }, [cmdData]);\n\n const [selectedCommand, setSelectedCommand] = useState('');\n const [argsInput, setArgsInput] = useState('');\n const [pendingCommand, setPendingCommand] = useState<string[] | null>(null);\n\n const selectedMeta = commands.find((c) => c.name === selectedCommand);\n\n const buildArgv = useCallback((): string[] => {\n const extra = argsInput.trim().length > 0 ? argsInput.trim().split(/\\s+/) : [];\n return [selectedCommand, ...extra];\n }, [selectedCommand, argsInput]);\n\n const executeCommand = useCallback(\n async (argv: string[]) => {\n setOutput(null);\n try {\n const res = await runCommand({ variables: { agentId, argv } });\n const proxy = res.data?.runAgentCommand;\n const d = asRecord(proxy?.data);\n const stdout = jstr(d, 'stdout') ?? '';\n const stderr = jstr(d, 'stderr') ?? '';\n const exit = d?.exitCode;\n const body =\n (stdout ? stdout : '') +\n (stderr ? `\\n[stderr]\\n${stderr}` : '') +\n `\\n[exit ${exit ?? '?'}]`;\n showOutput(\n `vibe ${argv.join(' ')}`,\n body.trim() || proxy?.error || '(no output)',\n !jbool(d, 'ok')\n );\n } catch (err) {\n showOutput('Command', err instanceof Error ? err.message : String(err), true);\n }\n },\n [agentId, runCommand, showOutput]\n );\n\n const handleRunClick = useCallback(() => {\n if (!selectedCommand) return;\n const argv = buildArgv();\n if (selectedMeta?.destructive) {\n setPendingCommand(argv);\n } else {\n void executeCommand(argv);\n }\n }, [selectedCommand, buildArgv, selectedMeta, executeCommand]);\n\n // ── Nuke ────────────────────────────────────────────────────────────────\n const [nuke, { loading: nuking }] = useNukeVibecontrolsAgentMutation();\n const [nukeDryRun, setNukeDryRun] = useState(true);\n const [pendingNuke, setPendingNuke] = useState<{ all: boolean; removeConfig: boolean } | null>(\n null\n );\n\n const runNuke = useCallback(\n async (opts: { all: boolean; removeConfig: boolean }) => {\n setOutput(null);\n try {\n const res = await nuke({\n variables: {\n agentId,\n all: opts.all,\n removeConfig: opts.removeConfig,\n dryRun: nukeDryRun,\n },\n });\n const proxy = res.data?.nukeVibecontrolsAgent;\n const d = asRecord(proxy?.data);\n const stdout = jstr(d, 'stdout') ?? '';\n const stderr = jstr(d, 'stderr') ?? '';\n const ok = jbool(d, 'ok') === true && !proxy?.error;\n showOutput(\n `vibe nuke${opts.all ? ' --all' : ''}${nukeDryRun ? ' --dry-run' : ''}`,\n (stdout + (stderr ? `\\n[stderr]\\n${stderr}` : '')).trim() ||\n proxy?.error ||\n '(no output)',\n !ok && !!proxy?.error\n );\n if (ok && !nukeDryRun) {\n await onAfterDestructiveNuke?.();\n }\n } catch (err) {\n showOutput('Nuke', err instanceof Error ? err.message : String(err), true);\n }\n },\n [agentId, nuke, nukeDryRun, onAfterDestructiveNuke, showOutput]\n );\n\n return (\n <div className=\"space-y-5\">\n {/* ── Agent update ────────────────────────────────────────────── */}\n <section className={SECTION}>\n <div className=\"flex items-center gap-2 mb-3\">\n <ArrowUpCircle className=\"size-5 text-text-secondary\" />\n <h3 className=\"text-base font-semibold text-text-primary\">\n {tr('agentDetails.maintenance.updateTitle', 'Agent version & updates')}\n </h3>\n </div>\n <div className=\"grid grid-cols-2 gap-3 text-sm mb-4\">\n <div>\n <div className=\"text-text-muted\">\n {tr('agentDetails.maintenance.current', 'Current')}\n </div>\n <div className=\"font-mono text-text-primary\">{agentVersion ?? '—'}</div>\n </div>\n <div>\n <div className=\"text-text-muted\">{tr('agentDetails.maintenance.latest', 'Latest')}</div>\n <div className=\"font-mono text-text-primary\">\n {latestVersion ?? '—'}\n {hasUpdate ? (\n <span className=\"ml-2 text-xs text-status-warning-text\">\n {tr('agentDetails.maintenance.updateAvailable', 'update available')}\n </span>\n ) : null}\n </div>\n </div>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2 mb-4\">\n <button type=\"button\" onClick={handleCheck} disabled={checking} className={BTN_NEUTRAL}>\n {checking ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <RefreshCw className=\"size-4\" />\n )}\n {tr('agentDetails.maintenance.check', 'Check for updates')}\n </button>\n <button\n type=\"button\"\n onClick={() => runSelfUpdate()}\n disabled={updating}\n className={BTN_PRIMARY}\n >\n {updating ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <ArrowUpCircle className=\"size-4\" />\n )}\n {tr('agentDetails.maintenance.updateLatest', 'Update to latest')}\n </button>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2 mb-4\">\n <input\n type=\"text\"\n value={versionInput}\n onChange={(e) => setVersionInput(e.target.value)}\n placeholder={tr('agentDetails.maintenance.versionPlaceholder', 'e.g. 2026.601.21')}\n className=\"px-3 py-2 text-sm rounded-md bg-bg-sunken border border-border-default text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 font-mono w-44\"\n />\n <button\n type=\"button\"\n onClick={() => runSelfUpdate(versionInput.trim())}\n disabled={updating || versionInput.trim().length === 0}\n className={BTN_NEUTRAL}\n >\n {tr('agentDetails.maintenance.updateVersion', 'Update to version')}\n </button>\n </div>\n\n <label className=\"flex items-center gap-3 cursor-pointer\">\n <Checkbox\n checked={autoUpdateEnabled}\n disabled={togglingAuto}\n onCheckedChange={(c) => toggleAutoUpdate(c === true)}\n />\n <span className=\"text-sm text-text-primary\">\n {tr(\n 'agentDetails.maintenance.autoUpdate',\n 'Automatically install updates when idle (daily background check)'\n )}\n </span>\n </label>\n </section>\n\n {/* ── Command runner ──────────────────────────────────────────── */}\n <section className={SECTION}>\n <div className=\"flex items-center justify-between gap-2 mb-3\">\n <div className=\"flex items-center gap-2\">\n <Terminal className=\"size-5 text-text-secondary\" />\n <h3 className=\"text-base font-semibold text-text-primary\">\n {tr('agentDetails.maintenance.commandsTitle', 'Run a command')}\n </h3>\n </div>\n <button\n type=\"button\"\n onClick={() => refetchCmds()}\n disabled={cmdsLoading}\n className=\"text-text-muted hover:text-text-primary\"\n aria-label={tr('agentDetails.maintenance.refresh', 'Refresh')}\n >\n <RefreshCw className={`size-4 ${cmdsLoading ? 'animate-spin' : ''}`} />\n </button>\n </div>\n <p className=\"text-xs text-text-muted mb-3\">\n {tr(\n 'agentDetails.maintenance.commandsHint',\n 'Every agent command can be run here. Destructive commands ask for confirmation.'\n )}\n </p>\n <div className=\"flex flex-wrap items-end gap-2 mb-3\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-text-muted\">\n {tr('agentDetails.maintenance.command', 'Command')}\n </span>\n <select\n value={selectedCommand}\n onChange={(e) => setSelectedCommand(e.target.value)}\n className=\"px-3 py-2 text-sm rounded-md bg-bg-sunken border border-border-default text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 min-w-44\"\n >\n <option value=\"\">\n {cmdsLoading\n ? tr('agentDetails.maintenance.loading', 'Loading…')\n : tr('agentDetails.maintenance.selectCommand', 'Select a command…')}\n </option>\n {commands.map((c) => (\n <option key={c.name} value={c.name}>\n {c.name}\n {c.destructive ? ' ⚠' : ''}\n </option>\n ))}\n </select>\n </div>\n <div className=\"flex flex-col gap-1 flex-1 min-w-44\">\n <span className=\"text-xs text-text-muted\">\n {tr('agentDetails.maintenance.args', 'Arguments (optional)')}\n </span>\n <input\n type=\"text\"\n value={argsInput}\n onChange={(e) => setArgsInput(e.target.value)}\n placeholder=\"--json --tail 50\"\n className=\"px-3 py-2 text-sm rounded-md bg-bg-sunken border border-border-default text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 font-mono w-full\"\n />\n </div>\n <button\n type=\"button\"\n onClick={handleRunClick}\n disabled={running || !selectedCommand}\n className={BTN_PRIMARY}\n >\n {running ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Terminal className=\"size-4\" />\n )}\n {tr('agentDetails.maintenance.run', 'Run')}\n </button>\n </div>\n {selectedMeta?.description ? (\n <p className=\"text-xs text-text-muted\">{selectedMeta.description}</p>\n ) : null}\n </section>\n\n {/* ── Danger zone (nuke) ──────────────────────────────────────── */}\n <section className={`${SECTION} border-status-error-bg/40`}>\n <div className=\"flex items-center gap-2 mb-3\">\n <AlertTriangle className=\"size-5 text-status-error-text\" />\n <h3 className=\"text-base font-semibold text-text-primary\">\n {tr('agentDetails.maintenance.dangerTitle', 'Danger zone')}\n </h3>\n </div>\n <label className=\"flex items-center gap-3 cursor-pointer mb-3\">\n <Checkbox checked={nukeDryRun} onCheckedChange={(c) => setNukeDryRun(c === true)} />\n <span className=\"text-sm text-text-primary\">\n {tr('agentDetails.maintenance.dryRun', 'Dry run (preview only — nothing is deleted)')}\n </span>\n </label>\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => setPendingNuke({ all: false, removeConfig: false })}\n disabled={nuking}\n className={BTN_NEUTRAL}\n >\n {nuking ? <Loader2 className=\"size-4 animate-spin\" /> : <Trash2 className=\"size-4\" />}\n {tr('agentDetails.maintenance.nukeState', 'Nuke state')}\n </button>\n <button\n type=\"button\"\n onClick={() => setPendingNuke({ all: true, removeConfig: true })}\n disabled={nuking}\n className={BTN_DANGER}\n >\n <Trash2 className=\"size-4\" />\n {tr('agentDetails.maintenance.nukeAll', 'Nuke everything (--all)')}\n </button>\n </div>\n <p className=\"text-xs text-text-muted mt-2\">\n {tr(\n 'agentDetails.maintenance.nukeHint',\n '“Nuke state” wipes this agent’s data + tracked binaries. “Nuke everything” also removes all VibeControls plugins, secrets, and config across every profile on the host.'\n )}\n </p>\n </section>\n\n {/* ── Output pane ─────────────────────────────────────────────── */}\n {output ? (\n <section className={SECTION}>\n <div className=\"flex items-center justify-between mb-2\">\n <h4 className=\"text-sm font-semibold text-text-primary\">{output.title}</h4>\n <button\n type=\"button\"\n onClick={() => setOutput(null)}\n className=\"text-xs text-text-muted hover:text-text-primary\"\n >\n {tr('agentDetails.maintenance.dismiss', 'Dismiss')}\n </button>\n </div>\n <pre\n className={`text-xs whitespace-pre-wrap break-words max-h-96 overflow-auto rounded-md p-3 ${\n output.error\n ? 'bg-status-error-bg-subtle text-status-error-text'\n : 'bg-bg-sunken text-text-primary'\n }`}\n >\n {output.body}\n </pre>\n </section>\n ) : null}\n\n {/* ── Confirms ────────────────────────────────────────────────── */}\n <ConfirmDialog\n isOpen={pendingCommand !== null}\n onClose={() => setPendingCommand(null)}\n onConfirm={() => {\n const argv = pendingCommand;\n setPendingCommand(null);\n if (argv) void executeCommand(argv);\n }}\n title={tr('agentDetails.maintenance.confirmCommandTitle', 'Run destructive command?')}\n message={tr(\n 'agentDetails.maintenance.confirmCommandMsg',\n 'This command can change or destroy agent state: {{cmd}}',\n { cmd: (pendingCommand ?? []).join(' ') }\n )}\n confirmLabel={tr('agentDetails.maintenance.run', 'Run')}\n variant=\"danger\"\n isLoading={running}\n />\n <ConfirmDialog\n isOpen={pendingNuke !== null}\n onClose={() => setPendingNuke(null)}\n onConfirm={() => {\n const opts = pendingNuke;\n setPendingNuke(null);\n if (opts) void runNuke(opts);\n }}\n title={\n nukeDryRun\n ? tr('agentDetails.maintenance.confirmNukeDryTitle', 'Preview nuke?')\n : tr('agentDetails.maintenance.confirmNukeTitle', 'Nuke agent?')\n }\n message={\n pendingNuke?.all\n ? tr(\n 'agentDetails.maintenance.confirmNukeAllMsg',\n 'This wipes ALL state, plugins, secrets and config on the host.'\n )\n : tr(\n 'agentDetails.maintenance.confirmNukeStateMsg',\n 'This wipes this agent’s state and tracked binaries.'\n )\n }\n confirmLabel={\n nukeDryRun\n ? tr('agentDetails.maintenance.preview', 'Preview')\n : tr('agentDetails.maintenance.nuke', 'Nuke')\n }\n variant=\"danger\"\n isLoading={nuking}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -17,8 +17,8 @@ var u = {
|
|
|
17
17
|
confirmBtn: "bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover"
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
|
-
function d({ isOpen: d, onClose: f, onConfirm: p, title: m, message: h, confirmLabel: g, cancelLabel: _, variant: v = "default", isLoading: y = !1 }) {
|
|
21
|
-
let
|
|
20
|
+
function d({ isOpen: d, onClose: f, onConfirm: p, title: m, message: h, confirmLabel: g, cancelLabel: _, variant: v = "default", isLoading: y = !1, children: b }) {
|
|
21
|
+
let x = e(), S = g ?? x("vibecontrols.shared.confirmDialog.confirm", "Confirm"), C = _ ?? x("vibecontrols.shared.confirmDialog.cancel", "Cancel"), w = u[v];
|
|
22
22
|
return /* @__PURE__ */ n(i, {
|
|
23
23
|
open: d,
|
|
24
24
|
onOpenChange: (e) => {
|
|
@@ -26,32 +26,39 @@ function d({ isOpen: d, onClose: f, onConfirm: p, title: m, message: h, confirmL
|
|
|
26
26
|
},
|
|
27
27
|
children: /* @__PURE__ */ r(a, {
|
|
28
28
|
className: "sm:max-w-md",
|
|
29
|
-
children: [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
29
|
+
children: [
|
|
30
|
+
/* @__PURE__ */ n(c, { children: /* @__PURE__ */ r("div", {
|
|
31
|
+
className: "flex items-start gap-3",
|
|
32
|
+
children: [/* @__PURE__ */ n("div", {
|
|
33
|
+
className: `flex-shrink-0 size-10 rounded-full flex items-center justify-center ${w.iconWrap}`,
|
|
34
|
+
"aria-hidden": "true",
|
|
35
|
+
children: /* @__PURE__ */ n(t, { className: "size-5" })
|
|
36
|
+
}), /* @__PURE__ */ r("div", {
|
|
37
|
+
className: "flex-1 min-w-0",
|
|
38
|
+
children: [/* @__PURE__ */ n(l, { children: m }), /* @__PURE__ */ n(o, {
|
|
39
|
+
className: "mt-1",
|
|
40
|
+
children: h
|
|
41
|
+
})]
|
|
40
42
|
})]
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
}) }),
|
|
44
|
+
b ? /* @__PURE__ */ n("div", {
|
|
45
|
+
className: "px-1 pt-1",
|
|
46
|
+
children: b
|
|
47
|
+
}) : null,
|
|
48
|
+
/* @__PURE__ */ r(s, { children: [/* @__PURE__ */ n("button", {
|
|
49
|
+
type: "button",
|
|
50
|
+
onClick: f,
|
|
51
|
+
disabled: y,
|
|
52
|
+
className: "min-h-11 px-4 py-2 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-md hover:bg-bg-elevated transition-colors disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40",
|
|
53
|
+
children: C
|
|
54
|
+
}), /* @__PURE__ */ n("button", {
|
|
55
|
+
type: "button",
|
|
56
|
+
onClick: p,
|
|
57
|
+
disabled: y,
|
|
58
|
+
className: `min-h-11 px-4 py-2 text-sm font-medium rounded-md transition-colors disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 ${w.confirmBtn}`,
|
|
59
|
+
children: y ? x("vibecontrols.shared.confirmDialog.processing", "Processing...") : S
|
|
60
|
+
})] })
|
|
61
|
+
]
|
|
55
62
|
})
|
|
56
63
|
});
|
|
57
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmDialog.js","names":[],"sources":["../../../src/components/shared/ConfirmDialog.tsx"],"sourcesContent":["import { AlertTriangle } from 'lucide-react';\nimport {\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface ConfirmDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onConfirm: () => void;\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: 'danger' | 'warning' | 'default';\n isLoading?: boolean;\n}\n\nconst VARIANT_STYLES: Record<\n NonNullable<ConfirmDialogProps['variant']>,\n { iconWrap: string; confirmBtn: string }\n> = {\n danger: {\n iconWrap: 'bg-status-error-bg-subtle text-status-error-text',\n confirmBtn: 'bg-status-error-bg text-text-inverse hover:bg-status-error-text-hover',\n },\n warning: {\n iconWrap: 'bg-status-warning-bg-subtle text-status-warning-text',\n confirmBtn: 'bg-status-warning-bg text-text-primary hover:bg-status-warning-text-hover',\n },\n default: {\n iconWrap: 'bg-action-primary-bg text-action-primary-text',\n confirmBtn: 'bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover',\n },\n};\n\nexport function ConfirmDialog({\n isOpen,\n onClose,\n onConfirm,\n title,\n message,\n confirmLabel,\n cancelLabel,\n variant = 'default',\n isLoading = false,\n}: ConfirmDialogProps) {\n const tr = useTr();\n const resolvedConfirmLabel =\n confirmLabel ?? tr('vibecontrols.shared.confirmDialog.confirm', 'Confirm');\n const resolvedCancelLabel =\n cancelLabel ?? tr('vibecontrols.shared.confirmDialog.cancel', 'Cancel');\n const styles = VARIANT_STYLES[variant];\n\n return (\n <ResponsiveDialog\n open={isOpen}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <ResponsiveDialogHeader>\n <div className=\"flex items-start gap-3\">\n <div\n className={`flex-shrink-0 size-10 rounded-full flex items-center justify-center ${styles.iconWrap}`}\n aria-hidden=\"true\"\n >\n <AlertTriangle className=\"size-5\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <ResponsiveDialogTitle>{title}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription className=\"mt-1\">{message}</ResponsiveDialogDescription>\n </div>\n </div>\n </ResponsiveDialogHeader>\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={isLoading}\n className=\"min-h-11 px-4 py-2 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-md hover:bg-bg-elevated transition-colors disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40\"\n >\n {resolvedCancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n disabled={isLoading}\n className={`min-h-11 px-4 py-2 text-sm font-medium rounded-md transition-colors disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 ${styles.confirmBtn}`}\n >\n {isLoading\n ? tr('vibecontrols.shared.confirmDialog.processing', 'Processing...')\n : resolvedConfirmLabel}\n </button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"ConfirmDialog.js","names":[],"sources":["../../../src/components/shared/ConfirmDialog.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { AlertTriangle } from 'lucide-react';\nimport {\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface ConfirmDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onConfirm: () => void;\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: 'danger' | 'warning' | 'default';\n isLoading?: boolean;\n /** Optional extra content rendered between the message and the footer\n * (e.g. an opt-in checkbox). */\n children?: ReactNode;\n}\n\nconst VARIANT_STYLES: Record<\n NonNullable<ConfirmDialogProps['variant']>,\n { iconWrap: string; confirmBtn: string }\n> = {\n danger: {\n iconWrap: 'bg-status-error-bg-subtle text-status-error-text',\n confirmBtn: 'bg-status-error-bg text-text-inverse hover:bg-status-error-text-hover',\n },\n warning: {\n iconWrap: 'bg-status-warning-bg-subtle text-status-warning-text',\n confirmBtn: 'bg-status-warning-bg text-text-primary hover:bg-status-warning-text-hover',\n },\n default: {\n iconWrap: 'bg-action-primary-bg text-action-primary-text',\n confirmBtn: 'bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover',\n },\n};\n\nexport function ConfirmDialog({\n isOpen,\n onClose,\n onConfirm,\n title,\n message,\n confirmLabel,\n cancelLabel,\n variant = 'default',\n isLoading = false,\n children,\n}: ConfirmDialogProps) {\n const tr = useTr();\n const resolvedConfirmLabel =\n confirmLabel ?? tr('vibecontrols.shared.confirmDialog.confirm', 'Confirm');\n const resolvedCancelLabel =\n cancelLabel ?? tr('vibecontrols.shared.confirmDialog.cancel', 'Cancel');\n const styles = VARIANT_STYLES[variant];\n\n return (\n <ResponsiveDialog\n open={isOpen}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <ResponsiveDialogHeader>\n <div className=\"flex items-start gap-3\">\n <div\n className={`flex-shrink-0 size-10 rounded-full flex items-center justify-center ${styles.iconWrap}`}\n aria-hidden=\"true\"\n >\n <AlertTriangle className=\"size-5\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <ResponsiveDialogTitle>{title}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription className=\"mt-1\">{message}</ResponsiveDialogDescription>\n </div>\n </div>\n </ResponsiveDialogHeader>\n {children ? <div className=\"px-1 pt-1\">{children}</div> : null}\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={isLoading}\n className=\"min-h-11 px-4 py-2 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-md hover:bg-bg-elevated transition-colors disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40\"\n >\n {resolvedCancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n disabled={isLoading}\n className={`min-h-11 px-4 py-2 text-sm font-medium rounded-md transition-colors disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 ${styles.confirmBtn}`}\n >\n {isLoading\n ? tr('vibecontrols.shared.confirmDialog.processing', 'Processing...')\n : resolvedConfirmLabel}\n </button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":";;;;;AA2BA,IAAM,IAGF;CACF,QAAQ;EACN,UAAU;EACV,YAAY;EACb;CACD,SAAS;EACP,UAAU;EACV,YAAY;EACb;CACD,SAAS;EACP,UAAU;EACV,YAAY;EACb;CACF;AAED,SAAgB,EAAc,EAC5B,WACA,YACA,cACA,UACA,YACA,iBACA,gBACA,aAAU,WACV,eAAY,IACZ,eACqB;CACrB,IAAM,IAAK,GAAO,EACZ,IACJ,KAAgB,EAAG,6CAA6C,UAAU,EACtE,IACJ,KAAe,EAAG,4CAA4C,SAAS,EACnE,IAAS,EAAe;AAE9B,QACE,kBAAC,GAAD;EACE,MAAM;EACN,eAAe,MAAS;AACtB,GAAK,KAAM,GAAS;;YAGtB,kBAAC,GAAD;GAAyB,WAAU;aAAnC;IACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MACE,WAAW,uEAAuE,EAAO;MACzF,eAAY;gBAEZ,kBAAC,GAAD,EAAe,WAAU,UAAW,CAAA;MAChC,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAA,UAAwB,GAA8B,CAAA,EACtD,kBAAC,GAAD;OAA6B,WAAU;iBAAQ;OAAsC,CAAA,CACjF;QACF;QACiB,CAAA;IACxB,IAAW,kBAAC,OAAD;KAAK,WAAU;KAAa;KAAe,CAAA,GAAG;IAC1D,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,UAAU;KACV,WAAU;eAET;KACM,CAAA,EACT,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,UAAU;KACV,WAAW,2JAA2J,EAAO;eAE5K,IACG,EAAG,gDAAgD,gBAAgB,GACnE;KACG,CAAA,CACc,EAAA,CAAA;IACD;;EACT,CAAA"}
|