@burdenoff/microfe-vibecontrols 2026.526.1 → 2026.526.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.
@@ -1,57 +1,63 @@
1
1
  import { useTr as e } from "../../shared/hooks/useTr.js";
2
2
  import { agentAiGet as t, agentAiMutate as n } from "../../services/aiApi.js";
3
- import { validateAliasName as r } from "./aliasReservedNames.js";
4
- import { useCallback as ee, useEffect as te, useState as i } from "react";
5
- import { Check as ne, Loader2 as a, Pencil as re, Play as o, Plus as s, Terminal as ie, Trash2 as c, X as l } from "lucide-react";
3
+ import { validateAliasName as ee } from "./aliasReservedNames.js";
4
+ import { useCallback as r, useEffect as te, useState as i } from "react";
5
+ import { Check as ne, Loader2 as a, PackageOpen as re, Pencil as ie, Play as o, Plus as s, Terminal as ae, Trash2 as c, X as l } from "lucide-react";
6
6
  import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
7
7
  //#region src/components/aliases/AliasManager.tsx
8
+ function oe(e) {
9
+ if (!e) return !1;
10
+ let t = e.toLowerCase();
11
+ return t.includes("not installed on the agent") || t.includes("not_found") || t.includes(" 404");
12
+ }
8
13
  var p = 80;
9
- function ae(e, t = p) {
14
+ function se(e, t = p) {
10
15
  return e ? e.length > t ? `${e.slice(0, t)}…` : e : "";
11
16
  }
12
17
  function m({ agent: p }) {
13
- let m = e(), h = `/api/profiles/${encodeURIComponent(p.profile ?? "default")}/aliases`, [g, oe] = i([]), [se, _] = i(!0), [v, y] = i(null), [b, x] = i(""), [S, C] = i(""), [w, T] = i(""), [E, D] = i(!1), [O, k] = i(null), [A, j] = i(null), [M, N] = i(""), [P, F] = i(""), [I, L] = i(!1), [R, z] = i(null), [B, V] = i(""), [H, U] = i(null), [W, G] = i(!1), [K, q] = i(null), [J, Y] = i(null), [X, Z] = i(!1), Q = ee(async () => {
14
- _(!0), y(null);
18
+ let m = e(), h = `/api/profiles/${encodeURIComponent(p.profile ?? "default")}/aliases`, [g, ce] = i([]), [le, _] = i(!0), [v, y] = i(null), [ue, b] = i(!1), [x, S] = i(""), [C, w] = i(""), [T, E] = i(""), [D, O] = i(!1), [k, A] = i(null), [de, j] = i(null), [M, N] = i(""), [P, F] = i(""), [I, L] = i(!1), [R, z] = i(null), [B, V] = i(""), [H, U] = i(null), [W, G] = i(!1), [K, q] = i(null), [J, Y] = i(null), [X, Z] = i(!1), Q = r(async () => {
19
+ _(!0), y(null), b(!1);
15
20
  try {
16
21
  let e = await t(p.id, h);
17
- oe(Array.isArray(e) ? e : e.items ?? []);
22
+ ce(Array.isArray(e) ? e : e.items ?? []);
18
23
  } catch (e) {
19
- y(e instanceof Error ? e.message : String(e));
24
+ let t = e instanceof Error ? e.message : String(e);
25
+ oe(t) ? b(!0) : y(t);
20
26
  } finally {
21
27
  _(!1);
22
28
  }
23
- }, [p.id]);
29
+ }, [p.id, h]);
24
30
  te(() => {
25
31
  Q();
26
32
  }, [Q]);
27
- let ce = async () => {
28
- k(null);
29
- let e = r(b.trim());
33
+ let fe = async () => {
34
+ A(null);
35
+ let e = ee(x.trim());
30
36
  if (e) {
31
- k(e);
37
+ A(e);
32
38
  return;
33
39
  }
34
- if (!S.trim()) {
35
- k(m("aliases.commandRequired", "Command is required"));
40
+ if (!C.trim()) {
41
+ A(m("aliases.commandRequired", "Command is required"));
36
42
  return;
37
43
  }
38
- D(!0);
44
+ O(!0);
39
45
  try {
40
46
  await n(p.id, h, "POST", {
41
- name: b.trim(),
42
- command: S,
43
- description: w || void 0
44
- }), x(""), C(""), T(""), await Q();
47
+ name: x.trim(),
48
+ command: C,
49
+ description: T || void 0
50
+ }), S(""), w(""), E(""), await Q();
45
51
  } catch (e) {
46
- k(e instanceof Error ? e.message : String(e));
52
+ A(e instanceof Error ? e.message : String(e));
47
53
  } finally {
48
- D(!1);
54
+ O(!1);
49
55
  }
50
- }, le = (e) => {
56
+ }, pe = (e) => {
51
57
  j(e.name), N(e.command), F(e.description ?? "");
52
58
  }, $ = () => {
53
59
  j(null), N(""), F("");
54
- }, ue = async (e) => {
60
+ }, me = async (e) => {
55
61
  L(!0);
56
62
  try {
57
63
  await n(p.id, `${h}/${encodeURIComponent(e.name)}`, "PUT", {
@@ -63,7 +69,7 @@ function m({ agent: p }) {
63
69
  } finally {
64
70
  L(!1);
65
71
  }
66
- }, de = async () => {
72
+ }, he = async () => {
67
73
  if (J) {
68
74
  Z(!0);
69
75
  try {
@@ -74,7 +80,7 @@ function m({ agent: p }) {
74
80
  Z(!1);
75
81
  }
76
82
  }
77
- }, fe = async () => {
83
+ }, ge = async () => {
78
84
  if (R) {
79
85
  G(!0), q(null), U(null);
80
86
  try {
@@ -87,7 +93,26 @@ function m({ agent: p }) {
87
93
  }
88
94
  }
89
95
  };
90
- return /* @__PURE__ */ f("div", {
96
+ return ue ? /* @__PURE__ */ f("div", {
97
+ className: "rounded-lg border border-border-default bg-bg-surface p-8 text-center space-y-3",
98
+ children: [
99
+ /* @__PURE__ */ d(re, { className: "w-8 h-8 mx-auto text-text-muted" }),
100
+ /* @__PURE__ */ d("h3", {
101
+ className: "text-base font-medium text-text-primary",
102
+ children: m("aliases.pluginMissingTitle", "Aliases plugin not installed")
103
+ }),
104
+ /* @__PURE__ */ d("p", {
105
+ className: "text-sm text-text-secondary max-w-md mx-auto",
106
+ children: m("aliases.pluginMissingBody", "This agent doesn't have the aliases plugin installed yet. Install @vibecontrols/vibe-plugin-aliases from the Plugins tab to enable per-agent shell aliases.")
107
+ }),
108
+ /* @__PURE__ */ d("button", {
109
+ type: "button",
110
+ onClick: Q,
111
+ className: "inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-text-secondary border border-border-default rounded-md hover:bg-bg-sunken transition-colors",
112
+ children: m("aliases.retry", "Retry")
113
+ })
114
+ ]
115
+ }) : /* @__PURE__ */ f("div", {
91
116
  className: "space-y-4",
92
117
  children: [
93
118
  /* @__PURE__ */ f("div", {
@@ -101,43 +126,43 @@ function m({ agent: p }) {
101
126
  className: "grid grid-cols-1 sm:grid-cols-2 gap-3",
102
127
  children: [/* @__PURE__ */ d("input", {
103
128
  type: "text",
104
- value: b,
105
- onChange: (e) => x(e.target.value),
129
+ value: x,
130
+ onChange: (e) => S(e.target.value),
106
131
  placeholder: m("aliases.namePlaceholder", "Name (a-z, 0-9, _, -)"),
107
132
  className: "px-3 py-2 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg font-mono"
108
133
  }), /* @__PURE__ */ d("input", {
109
134
  type: "text",
110
- value: w,
111
- onChange: (e) => T(e.target.value),
135
+ value: T,
136
+ onChange: (e) => E(e.target.value),
112
137
  placeholder: m("aliases.descriptionPlaceholder", "Description (optional)"),
113
138
  className: "px-3 py-2 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
114
139
  })]
115
140
  }),
116
141
  /* @__PURE__ */ d("textarea", {
117
- value: S,
118
- onChange: (e) => C(e.target.value),
142
+ value: C,
143
+ onChange: (e) => w(e.target.value),
119
144
  placeholder: m("aliases.commandPlaceholder", "Command (e.g. git status)"),
120
145
  rows: 3,
121
146
  className: "w-full px-3 py-2 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg font-mono"
122
147
  }),
123
- O && /* @__PURE__ */ d("div", {
148
+ k && /* @__PURE__ */ d("div", {
124
149
  className: "text-xs text-status-error-text",
125
- children: O
150
+ children: k
126
151
  }),
127
152
  /* @__PURE__ */ d("div", {
128
153
  className: "flex justify-end",
129
154
  children: /* @__PURE__ */ f("button", {
130
- onClick: ce,
131
- disabled: E || !b.trim() || !S.trim(),
155
+ onClick: fe,
156
+ disabled: D || !x.trim() || !C.trim(),
132
157
  className: "inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50",
133
- children: [E ? /* @__PURE__ */ d(a, { className: "w-4 h-4 animate-spin" }) : /* @__PURE__ */ d(s, { className: "w-4 h-4" }), m("aliases.create", "Create")]
158
+ children: [D ? /* @__PURE__ */ d(a, { className: "w-4 h-4 animate-spin" }) : /* @__PURE__ */ d(s, { className: "w-4 h-4" }), m("aliases.create", "Create")]
134
159
  })
135
160
  })
136
161
  ]
137
162
  }),
138
163
  /* @__PURE__ */ d("div", {
139
164
  className: "rounded-lg border border-border-default overflow-hidden",
140
- children: se ? /* @__PURE__ */ d("div", {
165
+ children: le ? /* @__PURE__ */ d("div", {
141
166
  className: "p-8 text-center text-text-secondary",
142
167
  children: /* @__PURE__ */ d(a, { className: "w-5 h-5 animate-spin mx-auto" })
143
168
  }) : v ? /* @__PURE__ */ d("div", {
@@ -173,7 +198,7 @@ function m({ agent: p }) {
173
198
  })
174
199
  ] })
175
200
  }), /* @__PURE__ */ d("tbody", { children: g.map((e) => {
176
- let t = A === e.name;
201
+ let t = de === e.name;
177
202
  return /* @__PURE__ */ f("tr", {
178
203
  className: "border-t border-border-default",
179
204
  children: [
@@ -191,7 +216,7 @@ function m({ agent: p }) {
191
216
  }) : /* @__PURE__ */ d("code", {
192
217
  className: "text-xs text-text-primary",
193
218
  title: e.command,
194
- children: ae(e.command)
219
+ children: se(e.command)
195
220
  })
196
221
  }),
197
222
  /* @__PURE__ */ d("td", {
@@ -214,7 +239,7 @@ function m({ agent: p }) {
214
239
  children: /* @__PURE__ */ d("div", {
215
240
  className: "flex items-center justify-end gap-1",
216
241
  children: t ? /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("button", {
217
- onClick: () => void ue(e),
242
+ onClick: () => void me(e),
218
243
  disabled: I,
219
244
  className: "p-1.5 rounded hover:bg-bg-sunken text-status-success-text",
220
245
  title: m("aliases.save", "Save"),
@@ -234,10 +259,10 @@ function m({ agent: p }) {
234
259
  children: /* @__PURE__ */ d(o, { className: "w-4 h-4" })
235
260
  }),
236
261
  /* @__PURE__ */ d("button", {
237
- onClick: () => le(e),
262
+ onClick: () => pe(e),
238
263
  className: "p-1.5 rounded hover:bg-bg-sunken text-text-secondary",
239
264
  title: m("aliases.edit", "Edit"),
240
- children: /* @__PURE__ */ d(re, { className: "w-4 h-4" })
265
+ children: /* @__PURE__ */ d(ie, { className: "w-4 h-4" })
241
266
  }),
242
267
  /* @__PURE__ */ d("button", {
243
268
  onClick: () => Y(e),
@@ -263,7 +288,7 @@ function m({ agent: p }) {
263
288
  children: [/* @__PURE__ */ f("h2", {
264
289
  className: "text-lg font-semibold text-text-primary flex items-center gap-2",
265
290
  children: [
266
- /* @__PURE__ */ d(ie, { className: "w-5 h-5" }),
291
+ /* @__PURE__ */ d(ae, { className: "w-5 h-5" }),
267
292
  m("aliases.runTitle", "Run alias"),
268
293
  ": ",
269
294
  /* @__PURE__ */ d("code", { children: R.name })
@@ -332,7 +357,7 @@ function m({ agent: p }) {
332
357
  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",
333
358
  children: m("common.close", "Close")
334
359
  }), /* @__PURE__ */ f("button", {
335
- onClick: () => void fe(),
360
+ onClick: () => void ge(),
336
361
  disabled: W,
337
362
  className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover disabled:opacity-50",
338
363
  children: [W ? /* @__PURE__ */ d(a, { className: "w-4 h-4 animate-spin" }) : /* @__PURE__ */ d(o, { className: "w-4 h-4" }), m("aliases.run", "Run")]
@@ -368,7 +393,7 @@ function m({ agent: p }) {
368
393
  className: "px-3 py-1.5 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary hover:bg-bg-elevated",
369
394
  children: m("common.cancel", "Cancel")
370
395
  }), /* @__PURE__ */ f("button", {
371
- onClick: () => void de(),
396
+ onClick: () => void he(),
372
397
  disabled: X,
373
398
  className: "inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-status-error-text bg-status-error-bg rounded-md hover:opacity-80 disabled:opacity-50",
374
399
  children: [X ? /* @__PURE__ */ d(a, { className: "w-4 h-4 animate-spin" }) : /* @__PURE__ */ d(c, { className: "w-4 h-4" }), m("aliases.delete", "Delete")]
@@ -1 +1 @@
1
- {"version":3,"file":"AliasManager.js","names":[],"sources":["../../../src/components/aliases/AliasManager.tsx"],"sourcesContent":["/**\n * AliasManager — per-agent CRUDL for shell aliases exposed by\n * vibecontrols-agent under `/api/aliases/*`.\n *\n * Pairs with the agent's Phase A4 ship.\n *\n * Endpoints (proxied through wspace-vibecontrols-svc → agent):\n * GET /api/aliases → { items: Alias[] }\n * GET /api/aliases/:name → Alias\n * POST /api/aliases → Alias\n * PUT /api/aliases/:name → Alias\n * DELETE /api/aliases/:name\n * POST /api/aliases/:name/execute → { exit_code, stdout, stderr }\n */\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { Plus, Trash2, Play, Pencil, Check, X, Loader2, Terminal } from 'lucide-react';\nimport { agentAiGet, agentAiMutate } from '@/services/aiApi';\nimport { useTr } from '@/shared/hooks/useTr';\nimport { validateAliasName } from './aliasReservedNames';\n\ninterface Alias {\n name: string;\n command: string;\n description?: string | null;\n updatedAt?: string | null;\n createdAt?: string | null;\n}\n\ninterface AliasListResponse {\n items?: Alias[];\n}\n\ninterface AliasExecuteResult {\n exit_code: number;\n stdout: string;\n stderr: string;\n}\n\ninterface AliasManagerProps {\n agent: { id: string; profile?: string };\n}\n\nconst TRUNCATE = 80;\n\nfunction truncate(str: string, n = TRUNCATE): string {\n if (!str) return '';\n return str.length > n ? `${str.slice(0, n)}…` : str;\n}\n\nexport function AliasManager({ agent }: AliasManagerProps) {\n const tr = useTr();\n // Canonical agent URL hierarchy: agent → profile → plugins/data.\n // The aliases plugin lives under `/api/profiles/<profile>/aliases/*`.\n // No client-side rewrites — every consumer constructs the canonical\n // path inline so the URL the agent sees is the URL the FE wrote.\n const profile = encodeURIComponent(agent.profile ?? 'default');\n const aliasesBase = `/api/profiles/${profile}/aliases`;\n const [aliases, setAliases] = useState<Alias[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // Add-new form\n const [newName, setNewName] = useState('');\n const [newCommand, setNewCommand] = useState('');\n const [newDescription, setNewDescription] = useState('');\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<string | null>(null);\n\n // Edit row\n const [editingName, setEditingName] = useState<string | null>(null);\n const [editCommand, setEditCommand] = useState('');\n const [editDescription, setEditDescription] = useState('');\n const [savingEdit, setSavingEdit] = useState(false);\n\n // Run modal\n const [runTarget, setRunTarget] = useState<Alias | null>(null);\n const [runArgs, setRunArgs] = useState('');\n const [runResult, setRunResult] = useState<AliasExecuteResult | null>(null);\n const [runRunning, setRunRunning] = useState(false);\n const [runError, setRunError] = useState<string | null>(null);\n\n // Delete confirm\n const [deleteTarget, setDeleteTarget] = useState<Alias | null>(null);\n const [deleting, setDeleting] = useState(false);\n\n const refresh = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const data = await agentAiGet<AliasListResponse | Alias[]>(agent.id, aliasesBase);\n const items = Array.isArray(data) ? data : (data.items ?? []);\n setAliases(items);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setLoading(false);\n }\n }, [agent.id]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n // ── Create ────────────────────────────────────────────────────────\n const handleCreate = async () => {\n setCreateError(null);\n const nameErr = validateAliasName(newName.trim());\n if (nameErr) {\n setCreateError(nameErr);\n return;\n }\n if (!newCommand.trim()) {\n setCreateError(tr('aliases.commandRequired', 'Command is required'));\n return;\n }\n setCreating(true);\n try {\n await agentAiMutate(agent.id, aliasesBase, 'POST', {\n name: newName.trim(),\n command: newCommand,\n description: newDescription || undefined,\n });\n setNewName('');\n setNewCommand('');\n setNewDescription('');\n await refresh();\n } catch (e) {\n setCreateError(e instanceof Error ? e.message : String(e));\n } finally {\n setCreating(false);\n }\n };\n\n // ── Edit ──────────────────────────────────────────────────────────\n const startEdit = (alias: Alias) => {\n setEditingName(alias.name);\n setEditCommand(alias.command);\n setEditDescription(alias.description ?? '');\n };\n\n const cancelEdit = () => {\n setEditingName(null);\n setEditCommand('');\n setEditDescription('');\n };\n\n const saveEdit = async (alias: Alias) => {\n setSavingEdit(true);\n try {\n await agentAiMutate(agent.id, `${aliasesBase}/${encodeURIComponent(alias.name)}`, 'PUT', {\n command: editCommand,\n description: editDescription || undefined,\n });\n cancelEdit();\n await refresh();\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setSavingEdit(false);\n }\n };\n\n // ── Delete ────────────────────────────────────────────────────────\n const confirmDelete = async () => {\n if (!deleteTarget) return;\n setDeleting(true);\n try {\n await agentAiMutate(\n agent.id,\n `${aliasesBase}/${encodeURIComponent(deleteTarget.name)}`,\n 'DELETE'\n );\n setDeleteTarget(null);\n await refresh();\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setDeleting(false);\n }\n };\n\n // ── Run ───────────────────────────────────────────────────────────\n const runAlias = async () => {\n if (!runTarget) return;\n setRunRunning(true);\n setRunError(null);\n setRunResult(null);\n try {\n const args = runArgs.split(/\\s+/).filter(Boolean);\n const result = await agentAiMutate<AliasExecuteResult>(\n agent.id,\n `${aliasesBase}/${encodeURIComponent(runTarget.name)}/execute`,\n 'POST',\n { args }\n );\n setRunResult(result);\n } catch (e) {\n setRunError(e instanceof Error ? e.message : String(e));\n } finally {\n setRunRunning(false);\n }\n };\n\n return (\n <div className=\"space-y-4\">\n {/* Add new alias form */}\n <div className=\"rounded-lg border border-border-default bg-bg-sunken p-4 space-y-3\">\n <h3 className=\"text-sm font-medium text-text-primary flex items-center gap-2\">\n <Plus className=\"w-4 h-4\" />\n {tr('aliases.createTitle', 'New alias')}\n </h3>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n <input\n type=\"text\"\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n placeholder={tr('aliases.namePlaceholder', 'Name (a-z, 0-9, _, -)')}\n className=\"px-3 py-2 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg font-mono\"\n />\n <input\n type=\"text\"\n value={newDescription}\n onChange={(e) => setNewDescription(e.target.value)}\n placeholder={tr('aliases.descriptionPlaceholder', 'Description (optional)')}\n className=\"px-3 py-2 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n <textarea\n value={newCommand}\n onChange={(e) => setNewCommand(e.target.value)}\n placeholder={tr('aliases.commandPlaceholder', 'Command (e.g. git status)')}\n rows={3}\n className=\"w-full px-3 py-2 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg font-mono\"\n />\n {createError && <div className=\"text-xs text-status-error-text\">{createError}</div>}\n <div className=\"flex justify-end\">\n <button\n onClick={handleCreate}\n disabled={creating || !newName.trim() || !newCommand.trim()}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {creating ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Plus className=\"w-4 h-4\" />}\n {tr('aliases.create', 'Create')}\n </button>\n </div>\n </div>\n\n {/* List */}\n <div className=\"rounded-lg border border-border-default overflow-hidden\">\n {loading ? (\n <div className=\"p-8 text-center text-text-secondary\">\n <Loader2 className=\"w-5 h-5 animate-spin mx-auto\" />\n </div>\n ) : error ? (\n <div className=\"p-4 text-sm text-status-error-text\">{error}</div>\n ) : aliases.length === 0 ? (\n <div className=\"p-8 text-center text-sm text-text-secondary\">\n {tr('aliases.empty', 'No aliases yet. Create one above.')}\n </div>\n ) : (\n <table className=\"w-full text-sm\">\n <thead className=\"bg-bg-sunken text-text-secondary\">\n <tr>\n <th className=\"text-left px-3 py-2 font-medium\">{tr('aliases.colName', 'Name')}</th>\n <th className=\"text-left px-3 py-2 font-medium\">\n {tr('aliases.colCommand', 'Command')}\n </th>\n <th className=\"text-left px-3 py-2 font-medium\">\n {tr('aliases.colDescription', 'Description')}\n </th>\n <th className=\"text-left px-3 py-2 font-medium\">\n {tr('aliases.colUpdatedAt', 'Updated')}\n </th>\n <th className=\"text-right px-3 py-2 font-medium\">\n {tr('aliases.colActions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody>\n {aliases.map((alias) => {\n const isEditing = editingName === alias.name;\n return (\n <tr key={alias.name} className=\"border-t border-border-default\">\n <td className=\"px-3 py-2 font-mono text-text-primary align-top\">\n {alias.name}\n </td>\n <td className=\"px-3 py-2 align-top\">\n {isEditing ? (\n <textarea\n value={editCommand}\n onChange={(e) => setEditCommand(e.target.value)}\n rows={2}\n className=\"w-full px-2 py-1 text-xs bg-bg-surface border border-border-default rounded text-text-primary font-mono\"\n />\n ) : (\n <code className=\"text-xs text-text-primary\" title={alias.command}>\n {truncate(alias.command)}\n </code>\n )}\n </td>\n <td className=\"px-3 py-2 align-top\">\n {isEditing ? (\n <input\n value={editDescription}\n onChange={(e) => setEditDescription(e.target.value)}\n className=\"w-full px-2 py-1 text-xs bg-bg-surface border border-border-default rounded text-text-primary\"\n />\n ) : (\n <span className=\"text-xs text-text-secondary\">\n {alias.description ?? '—'}\n </span>\n )}\n </td>\n <td className=\"px-3 py-2 text-xs text-text-secondary align-top\">\n {alias.updatedAt ? new Date(alias.updatedAt).toLocaleString() : '—'}\n </td>\n <td className=\"px-3 py-2 align-top\">\n <div className=\"flex items-center justify-end gap-1\">\n {isEditing ? (\n <>\n <button\n onClick={() => void saveEdit(alias)}\n disabled={savingEdit}\n className=\"p-1.5 rounded hover:bg-bg-sunken text-status-success-text\"\n title={tr('aliases.save', 'Save')}\n >\n {savingEdit ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Check className=\"w-4 h-4\" />\n )}\n </button>\n <button\n onClick={cancelEdit}\n className=\"p-1.5 rounded hover:bg-bg-sunken text-text-secondary\"\n title={tr('common.cancel', 'Cancel')}\n >\n <X className=\"w-4 h-4\" />\n </button>\n </>\n ) : (\n <>\n <button\n onClick={() => {\n setRunTarget(alias);\n setRunArgs('');\n setRunResult(null);\n setRunError(null);\n }}\n className=\"p-1.5 rounded hover:bg-bg-sunken text-action-primary-bg\"\n title={tr('aliases.run', 'Run')}\n >\n <Play className=\"w-4 h-4\" />\n </button>\n <button\n onClick={() => startEdit(alias)}\n className=\"p-1.5 rounded hover:bg-bg-sunken text-text-secondary\"\n title={tr('aliases.edit', 'Edit')}\n >\n <Pencil className=\"w-4 h-4\" />\n </button>\n <button\n onClick={() => setDeleteTarget(alias)}\n className=\"p-1.5 rounded hover:bg-bg-sunken text-status-error-text\"\n title={tr('aliases.delete', 'Delete')}\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </>\n )}\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n )}\n </div>\n\n {/* Run modal */}\n {runTarget && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-overlay\">\n <div className=\"w-full max-w-2xl bg-bg-surface rounded-lg shadow-xl max-h-[90vh] flex flex-col\">\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <h2 className=\"text-lg font-semibold text-text-primary flex items-center gap-2\">\n <Terminal className=\"w-5 h-5\" />\n {tr('aliases.runTitle', 'Run alias')}: <code>{runTarget.name}</code>\n </h2>\n <button onClick={() => setRunTarget(null)} className=\"p-1 rounded hover:bg-bg-sunken\">\n <X className=\"w-5 h-5 text-text-secondary\" />\n </button>\n </div>\n <div className=\"flex-1 overflow-y-auto p-6 space-y-3\">\n <div className=\"text-xs text-text-secondary font-mono break-all\">\n $ {runTarget.command}\n </div>\n <input\n type=\"text\"\n value={runArgs}\n onChange={(e) => setRunArgs(e.target.value)}\n placeholder={tr('aliases.argsPlaceholder', 'Args (space-separated, optional)')}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary font-mono\"\n />\n {runError && <div className=\"text-sm text-status-error-text\">{runError}</div>}\n {runResult && (\n <div className=\"space-y-2\">\n <div className=\"text-xs text-text-secondary\">\n {tr('aliases.exitCode', 'Exit code')}:{' '}\n <span\n className={\n runResult.exit_code === 0\n ? 'text-status-success-text font-mono'\n : 'text-status-error-text font-mono'\n }\n >\n {runResult.exit_code}\n </span>\n </div>\n {runResult.stdout && (\n <div>\n <div className=\"text-xs text-text-secondary mb-1\">stdout</div>\n <pre className=\"text-xs bg-bg-sunken p-3 rounded font-mono whitespace-pre-wrap break-all max-h-64 overflow-y-auto text-text-primary\">\n {runResult.stdout}\n </pre>\n </div>\n )}\n {runResult.stderr && (\n <div>\n <div className=\"text-xs text-text-secondary mb-1\">stderr</div>\n <pre className=\"text-xs bg-bg-sunken p-3 rounded font-mono whitespace-pre-wrap break-all max-h-64 overflow-y-auto text-status-error-text\">\n {runResult.stderr}\n </pre>\n </div>\n )}\n </div>\n )}\n </div>\n <div className=\"flex items-center justify-end gap-3 px-6 py-4 border-t border-border-default bg-bg-sunken\">\n <button\n onClick={() => setRunTarget(null)}\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\"\n >\n {tr('common.close', 'Close')}\n </button>\n <button\n onClick={() => void runAlias()}\n disabled={runRunning}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n {runRunning ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Play className=\"w-4 h-4\" />\n )}\n {tr('aliases.run', 'Run')}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Delete confirm */}\n {deleteTarget && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-overlay\">\n <div className=\"w-full max-w-md bg-bg-surface rounded-lg shadow-xl p-6 space-y-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('aliases.deleteTitle', 'Delete alias?')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr('aliases.deleteConfirm', 'This permanently removes the alias from this profile.')}{' '}\n <code className=\"font-mono text-text-primary\">{deleteTarget.name}</code>\n </p>\n <div className=\"flex justify-end gap-3\">\n <button\n onClick={() => setDeleteTarget(null)}\n className=\"px-3 py-1.5 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary hover:bg-bg-elevated\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n onClick={() => void confirmDelete()}\n disabled={deleting}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-status-error-text bg-status-error-bg rounded-md hover:opacity-80 disabled:opacity-50\"\n >\n {deleting ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Trash2 className=\"w-4 h-4\" />\n )}\n {tr('aliases.delete', 'Delete')}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AliasManager.js","names":[],"sources":["../../../src/components/aliases/AliasManager.tsx"],"sourcesContent":["/**\n * AliasManager — per-agent CRUDL for shell aliases exposed by\n * vibecontrols-agent under `/api/aliases/*`.\n *\n * Pairs with the agent's Phase A4 ship.\n *\n * Endpoints (proxied through wspace-vibecontrols-svc → agent):\n * GET /api/aliases → { items: Alias[] }\n * GET /api/aliases/:name → Alias\n * POST /api/aliases → Alias\n * PUT /api/aliases/:name → Alias\n * DELETE /api/aliases/:name\n * POST /api/aliases/:name/execute → { exit_code, stdout, stderr }\n */\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { Plus, Trash2, Play, Pencil, Check, X, Loader2, Terminal, PackageOpen } from 'lucide-react';\nimport { agentAiGet, agentAiMutate } from '@/services/aiApi';\nimport { useTr } from '@/shared/hooks/useTr';\nimport { validateAliasName } from './aliasReservedNames';\n\n/**\n * Detect the signatures that mean \"the aliases plugin isn't installed on\n * this agent.\" The agent answers 404 with body `NOT_FOUND` when no plugin\n * is mounted at `/api/profiles/<profile>/aliases`; the svc proxy\n * sanitizes that to the \"feature is not installed\" string (see aiApi\n * `sanitizeError`). We also catch the underlying error text directly so\n * we don't depend on `sanitizeError` keeping that exact phrasing.\n *\n * Reviewer follow-up: deliberately NOT matching Apollo's default\n * `Unexpected error.` mask here. It would catch today's\n * `WorkspaceRequiredError`-from-`agentAiGet` symptom AND legitimate\n * future errors (auth failures, timeouts, etc.) once the plugin ships,\n * masking them as \"plugin not installed\" — a worse UX than the honest\n * raw error. The right cure for the workspace-context surface lives at\n * the svc resolver (translate to a typed GraphQL error code the FE can\n * pivot on) and the aiApi sanitizer; tracked in BOFF-2613.\n */\nfunction isAliasesPluginUnavailable(msg: string): boolean {\n if (!msg) return false;\n const m = msg.toLowerCase();\n return m.includes('not installed on the agent') || m.includes('not_found') || m.includes(' 404');\n}\n\ninterface Alias {\n name: string;\n command: string;\n description?: string | null;\n updatedAt?: string | null;\n createdAt?: string | null;\n}\n\ninterface AliasListResponse {\n items?: Alias[];\n}\n\ninterface AliasExecuteResult {\n exit_code: number;\n stdout: string;\n stderr: string;\n}\n\ninterface AliasManagerProps {\n agent: { id: string; profile?: string };\n}\n\nconst TRUNCATE = 80;\n\nfunction truncate(str: string, n = TRUNCATE): string {\n if (!str) return '';\n return str.length > n ? `${str.slice(0, n)}…` : str;\n}\n\nexport function AliasManager({ agent }: AliasManagerProps) {\n const tr = useTr();\n // Canonical agent URL hierarchy: agent → profile → plugins/data.\n // The aliases plugin lives under `/api/profiles/<profile>/aliases/*`.\n // No client-side rewrites — every consumer constructs the canonical\n // path inline so the URL the agent sees is the URL the FE wrote.\n const profile = encodeURIComponent(agent.profile ?? 'default');\n const aliasesBase = `/api/profiles/${profile}/aliases`;\n const [aliases, setAliases] = useState<Alias[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n // Distinguish \"the agent doesn't have this plugin installed\" from a generic\n // error so we can show a clean empty-state with an actionable hint instead\n // of a scary stack-trace fragment. [BOFF-2613]\n const [pluginUnavailable, setPluginUnavailable] = useState(false);\n\n // Add-new form\n const [newName, setNewName] = useState('');\n const [newCommand, setNewCommand] = useState('');\n const [newDescription, setNewDescription] = useState('');\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<string | null>(null);\n\n // Edit row\n const [editingName, setEditingName] = useState<string | null>(null);\n const [editCommand, setEditCommand] = useState('');\n const [editDescription, setEditDescription] = useState('');\n const [savingEdit, setSavingEdit] = useState(false);\n\n // Run modal\n const [runTarget, setRunTarget] = useState<Alias | null>(null);\n const [runArgs, setRunArgs] = useState('');\n const [runResult, setRunResult] = useState<AliasExecuteResult | null>(null);\n const [runRunning, setRunRunning] = useState(false);\n const [runError, setRunError] = useState<string | null>(null);\n\n // Delete confirm\n const [deleteTarget, setDeleteTarget] = useState<Alias | null>(null);\n const [deleting, setDeleting] = useState(false);\n\n const refresh = useCallback(async () => {\n setLoading(true);\n setError(null);\n setPluginUnavailable(false);\n try {\n const data = await agentAiGet<AliasListResponse | Alias[]>(agent.id, aliasesBase);\n const items = Array.isArray(data) ? data : (data.items ?? []);\n setAliases(items);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n if (isAliasesPluginUnavailable(msg)) {\n // Plugin not installed on this agent (or upstream context-required\n // error that we treat the same way for this tab) — show empty-state\n // instead of a scary error banner. [BOFF-2613]\n setPluginUnavailable(true);\n } else {\n setError(msg);\n }\n } finally {\n setLoading(false);\n }\n }, [agent.id, aliasesBase]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n // ── Create ────────────────────────────────────────────────────────\n const handleCreate = async () => {\n setCreateError(null);\n const nameErr = validateAliasName(newName.trim());\n if (nameErr) {\n setCreateError(nameErr);\n return;\n }\n if (!newCommand.trim()) {\n setCreateError(tr('aliases.commandRequired', 'Command is required'));\n return;\n }\n setCreating(true);\n try {\n await agentAiMutate(agent.id, aliasesBase, 'POST', {\n name: newName.trim(),\n command: newCommand,\n description: newDescription || undefined,\n });\n setNewName('');\n setNewCommand('');\n setNewDescription('');\n await refresh();\n } catch (e) {\n setCreateError(e instanceof Error ? e.message : String(e));\n } finally {\n setCreating(false);\n }\n };\n\n // ── Edit ──────────────────────────────────────────────────────────\n const startEdit = (alias: Alias) => {\n setEditingName(alias.name);\n setEditCommand(alias.command);\n setEditDescription(alias.description ?? '');\n };\n\n const cancelEdit = () => {\n setEditingName(null);\n setEditCommand('');\n setEditDescription('');\n };\n\n const saveEdit = async (alias: Alias) => {\n setSavingEdit(true);\n try {\n await agentAiMutate(agent.id, `${aliasesBase}/${encodeURIComponent(alias.name)}`, 'PUT', {\n command: editCommand,\n description: editDescription || undefined,\n });\n cancelEdit();\n await refresh();\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setSavingEdit(false);\n }\n };\n\n // ── Delete ────────────────────────────────────────────────────────\n const confirmDelete = async () => {\n if (!deleteTarget) return;\n setDeleting(true);\n try {\n await agentAiMutate(\n agent.id,\n `${aliasesBase}/${encodeURIComponent(deleteTarget.name)}`,\n 'DELETE'\n );\n setDeleteTarget(null);\n await refresh();\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setDeleting(false);\n }\n };\n\n // ── Run ───────────────────────────────────────────────────────────\n const runAlias = async () => {\n if (!runTarget) return;\n setRunRunning(true);\n setRunError(null);\n setRunResult(null);\n try {\n const args = runArgs.split(/\\s+/).filter(Boolean);\n const result = await agentAiMutate<AliasExecuteResult>(\n agent.id,\n `${aliasesBase}/${encodeURIComponent(runTarget.name)}/execute`,\n 'POST',\n { args }\n );\n setRunResult(result);\n } catch (e) {\n setRunError(e instanceof Error ? e.message : String(e));\n } finally {\n setRunRunning(false);\n }\n };\n\n if (pluginUnavailable) {\n // The aliases plugin isn't installed on this agent. Show a clean,\n // actionable empty-state instead of the form + the raw error string.\n // [BOFF-2613]\n return (\n <div className=\"rounded-lg border border-border-default bg-bg-surface p-8 text-center space-y-3\">\n <PackageOpen className=\"w-8 h-8 mx-auto text-text-muted\" />\n <h3 className=\"text-base font-medium text-text-primary\">\n {tr('aliases.pluginMissingTitle', 'Aliases plugin not installed')}\n </h3>\n <p className=\"text-sm text-text-secondary max-w-md mx-auto\">\n {tr(\n 'aliases.pluginMissingBody',\n \"This agent doesn't have the aliases plugin installed yet. Install @vibecontrols/vibe-plugin-aliases from the Plugins tab to enable per-agent shell aliases.\"\n )}\n </p>\n <button\n type=\"button\"\n onClick={refresh}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-text-secondary border border-border-default rounded-md hover:bg-bg-sunken transition-colors\"\n >\n {tr('aliases.retry', 'Retry')}\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4\">\n {/* Add new alias form */}\n <div className=\"rounded-lg border border-border-default bg-bg-sunken p-4 space-y-3\">\n <h3 className=\"text-sm font-medium text-text-primary flex items-center gap-2\">\n <Plus className=\"w-4 h-4\" />\n {tr('aliases.createTitle', 'New alias')}\n </h3>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n <input\n type=\"text\"\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n placeholder={tr('aliases.namePlaceholder', 'Name (a-z, 0-9, _, -)')}\n className=\"px-3 py-2 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg font-mono\"\n />\n <input\n type=\"text\"\n value={newDescription}\n onChange={(e) => setNewDescription(e.target.value)}\n placeholder={tr('aliases.descriptionPlaceholder', 'Description (optional)')}\n className=\"px-3 py-2 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n <textarea\n value={newCommand}\n onChange={(e) => setNewCommand(e.target.value)}\n placeholder={tr('aliases.commandPlaceholder', 'Command (e.g. git status)')}\n rows={3}\n className=\"w-full px-3 py-2 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg font-mono\"\n />\n {createError && <div className=\"text-xs text-status-error-text\">{createError}</div>}\n <div className=\"flex justify-end\">\n <button\n onClick={handleCreate}\n disabled={creating || !newName.trim() || !newCommand.trim()}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {creating ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Plus className=\"w-4 h-4\" />}\n {tr('aliases.create', 'Create')}\n </button>\n </div>\n </div>\n\n {/* List */}\n <div className=\"rounded-lg border border-border-default overflow-hidden\">\n {loading ? (\n <div className=\"p-8 text-center text-text-secondary\">\n <Loader2 className=\"w-5 h-5 animate-spin mx-auto\" />\n </div>\n ) : error ? (\n <div className=\"p-4 text-sm text-status-error-text\">{error}</div>\n ) : aliases.length === 0 ? (\n <div className=\"p-8 text-center text-sm text-text-secondary\">\n {tr('aliases.empty', 'No aliases yet. Create one above.')}\n </div>\n ) : (\n <table className=\"w-full text-sm\">\n <thead className=\"bg-bg-sunken text-text-secondary\">\n <tr>\n <th className=\"text-left px-3 py-2 font-medium\">{tr('aliases.colName', 'Name')}</th>\n <th className=\"text-left px-3 py-2 font-medium\">\n {tr('aliases.colCommand', 'Command')}\n </th>\n <th className=\"text-left px-3 py-2 font-medium\">\n {tr('aliases.colDescription', 'Description')}\n </th>\n <th className=\"text-left px-3 py-2 font-medium\">\n {tr('aliases.colUpdatedAt', 'Updated')}\n </th>\n <th className=\"text-right px-3 py-2 font-medium\">\n {tr('aliases.colActions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody>\n {aliases.map((alias) => {\n const isEditing = editingName === alias.name;\n return (\n <tr key={alias.name} className=\"border-t border-border-default\">\n <td className=\"px-3 py-2 font-mono text-text-primary align-top\">\n {alias.name}\n </td>\n <td className=\"px-3 py-2 align-top\">\n {isEditing ? (\n <textarea\n value={editCommand}\n onChange={(e) => setEditCommand(e.target.value)}\n rows={2}\n className=\"w-full px-2 py-1 text-xs bg-bg-surface border border-border-default rounded text-text-primary font-mono\"\n />\n ) : (\n <code className=\"text-xs text-text-primary\" title={alias.command}>\n {truncate(alias.command)}\n </code>\n )}\n </td>\n <td className=\"px-3 py-2 align-top\">\n {isEditing ? (\n <input\n value={editDescription}\n onChange={(e) => setEditDescription(e.target.value)}\n className=\"w-full px-2 py-1 text-xs bg-bg-surface border border-border-default rounded text-text-primary\"\n />\n ) : (\n <span className=\"text-xs text-text-secondary\">\n {alias.description ?? '—'}\n </span>\n )}\n </td>\n <td className=\"px-3 py-2 text-xs text-text-secondary align-top\">\n {alias.updatedAt ? new Date(alias.updatedAt).toLocaleString() : '—'}\n </td>\n <td className=\"px-3 py-2 align-top\">\n <div className=\"flex items-center justify-end gap-1\">\n {isEditing ? (\n <>\n <button\n onClick={() => void saveEdit(alias)}\n disabled={savingEdit}\n className=\"p-1.5 rounded hover:bg-bg-sunken text-status-success-text\"\n title={tr('aliases.save', 'Save')}\n >\n {savingEdit ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Check className=\"w-4 h-4\" />\n )}\n </button>\n <button\n onClick={cancelEdit}\n className=\"p-1.5 rounded hover:bg-bg-sunken text-text-secondary\"\n title={tr('common.cancel', 'Cancel')}\n >\n <X className=\"w-4 h-4\" />\n </button>\n </>\n ) : (\n <>\n <button\n onClick={() => {\n setRunTarget(alias);\n setRunArgs('');\n setRunResult(null);\n setRunError(null);\n }}\n className=\"p-1.5 rounded hover:bg-bg-sunken text-action-primary-bg\"\n title={tr('aliases.run', 'Run')}\n >\n <Play className=\"w-4 h-4\" />\n </button>\n <button\n onClick={() => startEdit(alias)}\n className=\"p-1.5 rounded hover:bg-bg-sunken text-text-secondary\"\n title={tr('aliases.edit', 'Edit')}\n >\n <Pencil className=\"w-4 h-4\" />\n </button>\n <button\n onClick={() => setDeleteTarget(alias)}\n className=\"p-1.5 rounded hover:bg-bg-sunken text-status-error-text\"\n title={tr('aliases.delete', 'Delete')}\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </>\n )}\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n )}\n </div>\n\n {/* Run modal */}\n {runTarget && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-overlay\">\n <div className=\"w-full max-w-2xl bg-bg-surface rounded-lg shadow-xl max-h-[90vh] flex flex-col\">\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <h2 className=\"text-lg font-semibold text-text-primary flex items-center gap-2\">\n <Terminal className=\"w-5 h-5\" />\n {tr('aliases.runTitle', 'Run alias')}: <code>{runTarget.name}</code>\n </h2>\n <button onClick={() => setRunTarget(null)} className=\"p-1 rounded hover:bg-bg-sunken\">\n <X className=\"w-5 h-5 text-text-secondary\" />\n </button>\n </div>\n <div className=\"flex-1 overflow-y-auto p-6 space-y-3\">\n <div className=\"text-xs text-text-secondary font-mono break-all\">\n $ {runTarget.command}\n </div>\n <input\n type=\"text\"\n value={runArgs}\n onChange={(e) => setRunArgs(e.target.value)}\n placeholder={tr('aliases.argsPlaceholder', 'Args (space-separated, optional)')}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary font-mono\"\n />\n {runError && <div className=\"text-sm text-status-error-text\">{runError}</div>}\n {runResult && (\n <div className=\"space-y-2\">\n <div className=\"text-xs text-text-secondary\">\n {tr('aliases.exitCode', 'Exit code')}:{' '}\n <span\n className={\n runResult.exit_code === 0\n ? 'text-status-success-text font-mono'\n : 'text-status-error-text font-mono'\n }\n >\n {runResult.exit_code}\n </span>\n </div>\n {runResult.stdout && (\n <div>\n <div className=\"text-xs text-text-secondary mb-1\">stdout</div>\n <pre className=\"text-xs bg-bg-sunken p-3 rounded font-mono whitespace-pre-wrap break-all max-h-64 overflow-y-auto text-text-primary\">\n {runResult.stdout}\n </pre>\n </div>\n )}\n {runResult.stderr && (\n <div>\n <div className=\"text-xs text-text-secondary mb-1\">stderr</div>\n <pre className=\"text-xs bg-bg-sunken p-3 rounded font-mono whitespace-pre-wrap break-all max-h-64 overflow-y-auto text-status-error-text\">\n {runResult.stderr}\n </pre>\n </div>\n )}\n </div>\n )}\n </div>\n <div className=\"flex items-center justify-end gap-3 px-6 py-4 border-t border-border-default bg-bg-sunken\">\n <button\n onClick={() => setRunTarget(null)}\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\"\n >\n {tr('common.close', 'Close')}\n </button>\n <button\n onClick={() => void runAlias()}\n disabled={runRunning}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n {runRunning ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Play className=\"w-4 h-4\" />\n )}\n {tr('aliases.run', 'Run')}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Delete confirm */}\n {deleteTarget && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-overlay\">\n <div className=\"w-full max-w-md bg-bg-surface rounded-lg shadow-xl p-6 space-y-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('aliases.deleteTitle', 'Delete alias?')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr('aliases.deleteConfirm', 'This permanently removes the alias from this profile.')}{' '}\n <code className=\"font-mono text-text-primary\">{deleteTarget.name}</code>\n </p>\n <div className=\"flex justify-end gap-3\">\n <button\n onClick={() => setDeleteTarget(null)}\n className=\"px-3 py-1.5 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary hover:bg-bg-elevated\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n onClick={() => void confirmDelete()}\n disabled={deleting}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-status-error-text bg-status-error-bg rounded-md hover:opacity-80 disabled:opacity-50\"\n >\n {deleting ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Trash2 className=\"w-4 h-4\" />\n )}\n {tr('aliases.delete', 'Delete')}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}