@burdenoff/microfe-vibecontrols 2026.601.2 → 2026.601.4

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.
@@ -34,7 +34,7 @@ function v(e) {
34
34
  function y({ agent: _, isOpen: y, onClose: b }) {
35
35
  let [x, S] = u(""), [C, w] = u("claude"), [T, E] = u(o), [D, O] = u([]), k = (e) => {
36
36
  w(e), s(_, e, T).then(E).catch(() => E(T || "default"));
37
- }, [A, j] = u(""), [M, N] = u("sdk"), [P, F] = u(!1), [I, L] = u(null), R = r((e) => e.openSession), z = r((e) => e.activeChatContext), B = r((e) => e.setSessionSdk), V = r((e) => e.setSessionModel), H = r((e) => e.setSessionMode), U = m(), W = e();
37
+ }, [A, j] = u(""), [M, N] = u("sdk"), [P, F] = u(!1), [I, L] = u(null), R = r((e) => e.openSession), z = r((e) => e.bumpSessionsRefresh), B = r((e) => e.activeChatContext), V = r((e) => e.setSessionSdk), H = r((e) => e.setSessionModel), U = r((e) => e.setSessionMode), W = m(), G = e();
38
38
  l(() => {
39
39
  if (!y) return;
40
40
  let e = !1;
@@ -73,7 +73,7 @@ function y({ agent: _, isOpen: y, onClose: b }) {
73
73
  y,
74
74
  C
75
75
  ]);
76
- let G = c(async () => {
76
+ let K = c(async () => {
77
77
  if (x.trim()) {
78
78
  F(!0), L(null);
79
79
  try {
@@ -87,10 +87,10 @@ function y({ agent: _, isOpen: y, onClose: b }) {
87
87
  tags: A.split(",").map((e) => e.trim()).filter(Boolean)
88
88
  },
89
89
  agentId: _.id,
90
- contextLevel: z.contextLevel,
91
- vibeId: z.vibeId
90
+ contextLevel: B.contextLevel,
91
+ vibeId: B.vibeId
92
92
  });
93
- R(e.id, e.name), B(e.id, C), V(e.id, T), H(e.id, M), S(""), w("claude"), E(o), N("sdk"), j(""), b();
93
+ R(e.id, e.name), z(), V(e.id, C), H(e.id, T), U(e.id, M), S(""), w("claude"), E(o), N("sdk"), j(""), b();
94
94
  } catch (e) {
95
95
  L(e instanceof Error ? e.message : "Failed to create session");
96
96
  } finally {
@@ -109,20 +109,21 @@ function y({ agent: _, isOpen: y, onClose: b }) {
109
109
  B,
110
110
  V,
111
111
  H,
112
+ U,
112
113
  b
113
114
  ]);
114
115
  return y ? /* @__PURE__ */ h(f, { children: y && /* @__PURE__ */ g("div", {
115
116
  className: "fixed inset-0 z-50 flex items-center justify-center",
116
117
  children: [/* @__PURE__ */ h(p.div, {
117
118
  className: "absolute inset-0 bg-bg-overlay",
118
- initial: U ? void 0 : { opacity: 0 },
119
+ initial: W ? void 0 : { opacity: 0 },
119
120
  animate: { opacity: 1 },
120
121
  exit: { opacity: 0 },
121
122
  transition: { duration: .2 },
122
123
  onClick: b
123
124
  }), /* @__PURE__ */ g(p.div, {
124
125
  className: "relative w-full max-w-md mx-4 rounded-lg border border-border-default bg-bg-surface shadow-xl",
125
- initial: U ? void 0 : {
126
+ initial: W ? void 0 : {
126
127
  opacity: 0,
127
128
  scale: .95,
128
129
  y: 8
@@ -151,7 +152,7 @@ function y({ agent: _, isOpen: y, onClose: b }) {
151
152
  className: "flex items-center justify-between px-6 py-4 border-b border-border-default",
152
153
  children: [/* @__PURE__ */ h("h3", {
153
154
  className: "text-lg font-semibold text-text-primary",
154
- children: W("vibecontrols.agentManager.dialogs.newSession", "New Session")
155
+ children: G("vibecontrols.agentManager.dialogs.newSession", "New Session")
155
156
  }), /* @__PURE__ */ h("button", {
156
157
  type: "button",
157
158
  onClick: b,
@@ -164,7 +165,7 @@ function y({ agent: _, isOpen: y, onClose: b }) {
164
165
  children: [
165
166
  /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
166
167
  className: "block text-sm font-medium text-text-primary mb-1",
167
- children: W("vibecontrols.agentManager.dialogs.name", "Name")
168
+ children: G("vibecontrols.agentManager.dialogs.name", "Name")
168
169
  }), /* @__PURE__ */ h("input", {
169
170
  "aria-label": "My session",
170
171
  type: "text",
@@ -175,7 +176,7 @@ function y({ agent: _, isOpen: y, onClose: b }) {
175
176
  })] }),
176
177
  /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
177
178
  className: "block text-sm font-medium text-text-primary mb-1",
178
- children: W("vibecontrols.agentManager.dialogs.sdkAndMode", "SDK & Mode")
179
+ children: G("vibecontrols.agentManager.dialogs.sdkAndMode", "SDK & Mode")
179
180
  }), /* @__PURE__ */ h(a, {
180
181
  sdk: C,
181
182
  mode: M,
@@ -185,7 +186,7 @@ function y({ agent: _, isOpen: y, onClose: b }) {
185
186
  })] }),
186
187
  /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
187
188
  className: "block text-sm font-medium text-text-primary mb-1",
188
- children: W("vibecontrols.agentManager.dialogs.model", "Model")
189
+ children: G("vibecontrols.agentManager.dialogs.model", "Model")
189
190
  }), /* @__PURE__ */ h(i, {
190
191
  value: T,
191
192
  onChange: E,
@@ -195,7 +196,7 @@ function y({ agent: _, isOpen: y, onClose: b }) {
195
196
  })] }),
196
197
  /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
197
198
  className: "block text-sm font-medium text-text-primary mb-1",
198
- children: W("vibecontrols.agentManager.dialogs.tagsLabel", "Tags (comma-separated)")
199
+ children: G("vibecontrols.agentManager.dialogs.tagsLabel", "Tags (comma-separated)")
199
200
  }), /* @__PURE__ */ h("input", {
200
201
  "aria-label": "e.g. frontend, bugfix, prototype",
201
202
  type: "text",
@@ -217,13 +218,13 @@ function y({ agent: _, isOpen: y, onClose: b }) {
217
218
  onClick: b,
218
219
  disabled: P,
219
220
  className: "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",
220
- children: W("vibecontrols.agentManager.dialogs.cancel", "Cancel")
221
+ children: G("vibecontrols.agentManager.dialogs.cancel", "Cancel")
221
222
  }), /* @__PURE__ */ h("button", {
222
223
  type: "button",
223
- onClick: G,
224
+ onClick: K,
224
225
  disabled: P || !x.trim(),
225
226
  className: "px-4 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-40 disabled:cursor-not-allowed",
226
- children: P ? W("vibecontrols.agentManager.dialogs.creating", "Creating...") : W("vibecontrols.agentManager.dialogs.create", "Create")
227
+ children: P ? G("vibecontrols.agentManager.dialogs.creating", "Creating...") : G("vibecontrols.agentManager.dialogs.create", "Create")
227
228
  })]
228
229
  })
229
230
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"NewSessionDialog.js","names":[],"sources":["../../../../src/components/agent-manager/dialogs/NewSessionDialog.tsx"],"sourcesContent":["/**\n * New session creation dialog.\n *\n * Modal overlay with fields for session name, SDK, model, and mode.\n * Creates a session via aiApi and opens it as a new tab.\n */\n\nimport { useState, useCallback, useEffect } from 'react';\nimport { X } from 'lucide-react';\nimport { motion, AnimatePresence, useReducedMotion } from 'framer-motion';\nimport { createSession, fetchProviders, type AIProvider, type AgentRef } from '@/services/aiApi';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { ModelSelector } from '../controls/ModelSelector';\nimport { SdkSelector } from '../controls/SdkSelector';\nimport { GENERIC_MODEL_FALLBACK, resolveProviderDefaultModel } from '../modelDefaults';\nimport type { AgentSdkType, ProviderMode } from '@/types/agentManager';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface NewSessionDialogProps {\n agent: AgentRef;\n isOpen: boolean;\n onClose: () => void;\n}\n\nconst SDK_VALUES = new Set<string>([\n 'claude',\n 'codex',\n 'gemini',\n 'opencode',\n 'cursor',\n 'openrouter',\n 'minimax',\n 'ollama',\n 'openai-compat',\n 'goose',\n 'amp',\n 'copilot',\n 'crush',\n 'pi',\n 'aider',\n 'plandex',\n]);\n\nfunction providerSdk(provider: AIProvider): AgentSdkType | null {\n const value = (provider.name || provider.pluginName).replace(/^ai-/, '');\n return SDK_VALUES.has(value) ? (value as AgentSdkType) : null;\n}\n\nexport function NewSessionDialog({ agent, isOpen, onClose }: NewSessionDialogProps) {\n const [name, setName] = useState('');\n const [sdk, setSdk] = useState<AgentSdkType>('claude');\n const [model, setModel] = useState(GENERIC_MODEL_FALLBACK);\n const [providers, setProviders] = useState<AIProvider[]>([]);\n\n // Auto-update default model when SDK changes\n const handleSdkChange = (newSdk: AgentSdkType) => {\n setSdk(newSdk);\n void resolveProviderDefaultModel(agent, newSdk, model)\n .then(setModel)\n .catch(() => setModel(model || GENERIC_MODEL_FALLBACK));\n };\n const [tags, setTags] = useState('');\n const [mode, setMode] = useState<ProviderMode>('sdk');\n const [creating, setCreating] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const openSession = useAgentManagerStore((s) => s.openSession);\n const activeChatContext = useAgentManagerStore((s) => s.activeChatContext);\n const setSessionSdk = useAgentManagerStore((s) => s.setSessionSdk);\n const setSessionModel = useAgentManagerStore((s) => s.setSessionModel);\n const setSessionMode = useAgentManagerStore((s) => s.setSessionMode);\n const shouldReduceMotion = useReducedMotion();\n const tr = useTr();\n\n useEffect(() => {\n if (!isOpen) return;\n\n let cancelled = false;\n void fetchProviders(agent)\n .then((items) => {\n if (!cancelled) setProviders(items);\n })\n .catch(() => {\n if (!cancelled) setProviders([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [agent, isOpen]);\n\n useEffect(() => {\n if (!isOpen || providers.length === 0) return;\n\n const current = providers.find((provider) => providerSdk(provider) === sdk);\n const fallback = providers.find((provider) => provider.isDefault) ?? providers[0];\n const nextProvider = current ?? fallback;\n if (!nextProvider) return;\n\n const nextSdk = providerSdk(nextProvider);\n if (nextSdk && !current) {\n setSdk(nextSdk);\n }\n\n const supportedModes = nextProvider.supportedModes ?? [];\n if (supportedModes.length > 0 && !supportedModes.includes(mode)) {\n setMode(nextProvider.defaultMode ?? nextProvider.currentMode ?? supportedModes[0] ?? 'cli');\n }\n }, [isOpen, mode, providers, sdk]);\n\n useEffect(() => {\n if (!isOpen) return;\n\n let cancelled = false;\n void resolveProviderDefaultModel(agent, sdk, GENERIC_MODEL_FALLBACK)\n .then((nextModel) => {\n if (!cancelled) setModel(nextModel);\n })\n .catch(() => {\n if (!cancelled) setModel((current) => current || GENERIC_MODEL_FALLBACK);\n });\n\n return () => {\n cancelled = true;\n };\n }, [agent, isOpen, sdk]);\n\n const handleCreate = useCallback(async () => {\n if (!name.trim()) return;\n setCreating(true);\n setError(null);\n try {\n const session = await createSession(agent, {\n name: name.trim(),\n agentType: sdk,\n config: {\n model,\n mode,\n // New sessions default to the safe autonomy level; users adjust it\n // per-session via the Autonomy control in the chat toolbar.\n permissionMode: 'acceptEdits',\n tags: tags\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean),\n },\n // Stamp the active \"bucket\" context (agent/vibe) onto the session.\n agentId: agent.id,\n contextLevel: activeChatContext.contextLevel,\n vibeId: activeChatContext.vibeId,\n });\n openSession(session.id, session.name);\n setSessionSdk(session.id, sdk);\n setSessionModel(session.id, model);\n setSessionMode(session.id, mode);\n // Reset form\n setName('');\n setSdk('claude');\n setModel(GENERIC_MODEL_FALLBACK);\n setMode('sdk');\n setTags('');\n onClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to create session');\n } finally {\n setCreating(false);\n }\n }, [\n agent,\n name,\n sdk,\n model,\n mode,\n tags,\n openSession,\n activeChatContext,\n setSessionSdk,\n setSessionModel,\n setSessionMode,\n onClose,\n ]);\n\n if (!isOpen) return null;\n\n return (\n <AnimatePresence>\n {isOpen && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <motion.div\n className=\"absolute inset-0 bg-bg-overlay\"\n initial={shouldReduceMotion ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.2 }}\n onClick={onClose}\n />\n <motion.div\n className=\"relative w-full max-w-md mx-4 rounded-lg border border-border-default bg-bg-surface shadow-xl\"\n initial={shouldReduceMotion ? undefined : { opacity: 0, scale: 0.95, y: 8 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.95, y: 8 }}\n transition={{ duration: 0.2, ease: [0.2, 0, 0, 1] }}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {tr('vibecontrols.agentManager.dialogs.newSession', 'New Session')}\n </h3>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"size-5 text-text-secondary\" />\n </button>\n </div>\n\n {/* Body */}\n <div className=\"px-6 py-4 space-y-4\">\n {/* Name */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.agentManager.dialogs.name', 'Name')}\n </label>\n <input\n aria-label=\"My session\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"My session\"\n className=\"w-full rounded-md border border-border-default bg-bg-primary px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:border-border-strong transition-colors\"\n />\n </div>\n\n {/* SDK + Mode */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.agentManager.dialogs.sdkAndMode', 'SDK & Mode')}\n </label>\n <SdkSelector\n sdk={sdk}\n mode={mode}\n providers={providers}\n onSdkChange={handleSdkChange}\n onModeChange={setMode}\n />\n </div>\n\n {/* Model */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.agentManager.dialogs.model', 'Model')}\n </label>\n <ModelSelector\n value={model}\n onChange={setModel}\n provider={sdk}\n agentId={agent.id}\n profile={agent.profile}\n />\n </div>\n\n {/* Tags */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.agentManager.dialogs.tagsLabel', 'Tags (comma-separated)')}\n </label>\n <input\n aria-label=\"e.g. frontend, bugfix, prototype\"\n type=\"text\"\n value={tags}\n onChange={(e) => setTags(e.target.value)}\n placeholder=\"e.g. frontend, bugfix, prototype\"\n className=\"w-full rounded-md border border-border-default bg-bg-primary px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:border-border-strong transition-colors\"\n />\n </div>\n\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-end gap-3 px-6 py-4 border-t border-border-default bg-bg-sunken rounded-b-lg\">\n <button\n type=\"button\"\n onClick={onClose}\n disabled={creating}\n className=\"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\"\n >\n {tr('vibecontrols.agentManager.dialogs.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleCreate}\n disabled={creating || !name.trim()}\n className=\"px-4 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-40 disabled:cursor-not-allowed\"\n >\n {creating\n ? tr('vibecontrols.agentManager.dialogs.creating', 'Creating...')\n : tr('vibecontrols.agentManager.dialogs.create', 'Create')}\n </button>\n </div>\n </motion.div>\n </div>\n )}\n </AnimatePresence>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"NewSessionDialog.js","names":[],"sources":["../../../../src/components/agent-manager/dialogs/NewSessionDialog.tsx"],"sourcesContent":["/**\n * New session creation dialog.\n *\n * Modal overlay with fields for session name, SDK, model, and mode.\n * Creates a session via aiApi and opens it as a new tab.\n */\n\nimport { useState, useCallback, useEffect } from 'react';\nimport { X } from 'lucide-react';\nimport { motion, AnimatePresence, useReducedMotion } from 'framer-motion';\nimport { createSession, fetchProviders, type AIProvider, type AgentRef } from '@/services/aiApi';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { ModelSelector } from '../controls/ModelSelector';\nimport { SdkSelector } from '../controls/SdkSelector';\nimport { GENERIC_MODEL_FALLBACK, resolveProviderDefaultModel } from '../modelDefaults';\nimport type { AgentSdkType, ProviderMode } from '@/types/agentManager';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface NewSessionDialogProps {\n agent: AgentRef;\n isOpen: boolean;\n onClose: () => void;\n}\n\nconst SDK_VALUES = new Set<string>([\n 'claude',\n 'codex',\n 'gemini',\n 'opencode',\n 'cursor',\n 'openrouter',\n 'minimax',\n 'ollama',\n 'openai-compat',\n 'goose',\n 'amp',\n 'copilot',\n 'crush',\n 'pi',\n 'aider',\n 'plandex',\n]);\n\nfunction providerSdk(provider: AIProvider): AgentSdkType | null {\n const value = (provider.name || provider.pluginName).replace(/^ai-/, '');\n return SDK_VALUES.has(value) ? (value as AgentSdkType) : null;\n}\n\nexport function NewSessionDialog({ agent, isOpen, onClose }: NewSessionDialogProps) {\n const [name, setName] = useState('');\n const [sdk, setSdk] = useState<AgentSdkType>('claude');\n const [model, setModel] = useState(GENERIC_MODEL_FALLBACK);\n const [providers, setProviders] = useState<AIProvider[]>([]);\n\n // Auto-update default model when SDK changes\n const handleSdkChange = (newSdk: AgentSdkType) => {\n setSdk(newSdk);\n void resolveProviderDefaultModel(agent, newSdk, model)\n .then(setModel)\n .catch(() => setModel(model || GENERIC_MODEL_FALLBACK));\n };\n const [tags, setTags] = useState('');\n const [mode, setMode] = useState<ProviderMode>('sdk');\n const [creating, setCreating] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const openSession = useAgentManagerStore((s) => s.openSession);\n const bumpSessionsRefresh = useAgentManagerStore((s) => s.bumpSessionsRefresh);\n const activeChatContext = useAgentManagerStore((s) => s.activeChatContext);\n const setSessionSdk = useAgentManagerStore((s) => s.setSessionSdk);\n const setSessionModel = useAgentManagerStore((s) => s.setSessionModel);\n const setSessionMode = useAgentManagerStore((s) => s.setSessionMode);\n const shouldReduceMotion = useReducedMotion();\n const tr = useTr();\n\n useEffect(() => {\n if (!isOpen) return;\n\n let cancelled = false;\n void fetchProviders(agent)\n .then((items) => {\n if (!cancelled) setProviders(items);\n })\n .catch(() => {\n if (!cancelled) setProviders([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [agent, isOpen]);\n\n useEffect(() => {\n if (!isOpen || providers.length === 0) return;\n\n const current = providers.find((provider) => providerSdk(provider) === sdk);\n const fallback = providers.find((provider) => provider.isDefault) ?? providers[0];\n const nextProvider = current ?? fallback;\n if (!nextProvider) return;\n\n const nextSdk = providerSdk(nextProvider);\n if (nextSdk && !current) {\n setSdk(nextSdk);\n }\n\n const supportedModes = nextProvider.supportedModes ?? [];\n if (supportedModes.length > 0 && !supportedModes.includes(mode)) {\n setMode(nextProvider.defaultMode ?? nextProvider.currentMode ?? supportedModes[0] ?? 'cli');\n }\n }, [isOpen, mode, providers, sdk]);\n\n useEffect(() => {\n if (!isOpen) return;\n\n let cancelled = false;\n void resolveProviderDefaultModel(agent, sdk, GENERIC_MODEL_FALLBACK)\n .then((nextModel) => {\n if (!cancelled) setModel(nextModel);\n })\n .catch(() => {\n if (!cancelled) setModel((current) => current || GENERIC_MODEL_FALLBACK);\n });\n\n return () => {\n cancelled = true;\n };\n }, [agent, isOpen, sdk]);\n\n const handleCreate = useCallback(async () => {\n if (!name.trim()) return;\n setCreating(true);\n setError(null);\n try {\n const session = await createSession(agent, {\n name: name.trim(),\n agentType: sdk,\n config: {\n model,\n mode,\n // New sessions default to the safe autonomy level; users adjust it\n // per-session via the Autonomy control in the chat toolbar.\n permissionMode: 'acceptEdits',\n tags: tags\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean),\n },\n // Stamp the active \"bucket\" context (agent/vibe) onto the session.\n agentId: agent.id,\n contextLevel: activeChatContext.contextLevel,\n vibeId: activeChatContext.vibeId,\n });\n openSession(session.id, session.name);\n bumpSessionsRefresh();\n setSessionSdk(session.id, sdk);\n setSessionModel(session.id, model);\n setSessionMode(session.id, mode);\n // Reset form\n setName('');\n setSdk('claude');\n setModel(GENERIC_MODEL_FALLBACK);\n setMode('sdk');\n setTags('');\n onClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to create session');\n } finally {\n setCreating(false);\n }\n }, [\n agent,\n name,\n sdk,\n model,\n mode,\n tags,\n openSession,\n bumpSessionsRefresh,\n activeChatContext,\n setSessionSdk,\n setSessionModel,\n setSessionMode,\n onClose,\n ]);\n\n if (!isOpen) return null;\n\n return (\n <AnimatePresence>\n {isOpen && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <motion.div\n className=\"absolute inset-0 bg-bg-overlay\"\n initial={shouldReduceMotion ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.2 }}\n onClick={onClose}\n />\n <motion.div\n className=\"relative w-full max-w-md mx-4 rounded-lg border border-border-default bg-bg-surface shadow-xl\"\n initial={shouldReduceMotion ? undefined : { opacity: 0, scale: 0.95, y: 8 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.95, y: 8 }}\n transition={{ duration: 0.2, ease: [0.2, 0, 0, 1] }}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {tr('vibecontrols.agentManager.dialogs.newSession', 'New Session')}\n </h3>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"size-5 text-text-secondary\" />\n </button>\n </div>\n\n {/* Body */}\n <div className=\"px-6 py-4 space-y-4\">\n {/* Name */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.agentManager.dialogs.name', 'Name')}\n </label>\n <input\n aria-label=\"My session\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"My session\"\n className=\"w-full rounded-md border border-border-default bg-bg-primary px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:border-border-strong transition-colors\"\n />\n </div>\n\n {/* SDK + Mode */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.agentManager.dialogs.sdkAndMode', 'SDK & Mode')}\n </label>\n <SdkSelector\n sdk={sdk}\n mode={mode}\n providers={providers}\n onSdkChange={handleSdkChange}\n onModeChange={setMode}\n />\n </div>\n\n {/* Model */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.agentManager.dialogs.model', 'Model')}\n </label>\n <ModelSelector\n value={model}\n onChange={setModel}\n provider={sdk}\n agentId={agent.id}\n profile={agent.profile}\n />\n </div>\n\n {/* Tags */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.agentManager.dialogs.tagsLabel', 'Tags (comma-separated)')}\n </label>\n <input\n aria-label=\"e.g. frontend, bugfix, prototype\"\n type=\"text\"\n value={tags}\n onChange={(e) => setTags(e.target.value)}\n placeholder=\"e.g. frontend, bugfix, prototype\"\n className=\"w-full rounded-md border border-border-default bg-bg-primary px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:border-border-strong transition-colors\"\n />\n </div>\n\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-end gap-3 px-6 py-4 border-t border-border-default bg-bg-sunken rounded-b-lg\">\n <button\n type=\"button\"\n onClick={onClose}\n disabled={creating}\n className=\"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\"\n >\n {tr('vibecontrols.agentManager.dialogs.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleCreate}\n disabled={creating || !name.trim()}\n className=\"px-4 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-40 disabled:cursor-not-allowed\"\n >\n {creating\n ? tr('vibecontrols.agentManager.dialogs.creating', 'Creating...')\n : tr('vibecontrols.agentManager.dialogs.create', 'Create')}\n </button>\n </div>\n </motion.div>\n </div>\n )}\n </AnimatePresence>\n );\n}\n"],"mappings":"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"}
@@ -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