@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.
- package/dist/components/agents/backup/AgentBackupTab.js +126 -113
- package/dist/components/agents/backup/AgentBackupTab.js.map +1 -1
- package/dist/components/ai/PluginHarnessPicker.js +64 -65
- package/dist/components/ai/PluginHarnessPicker.js.map +1 -1
- package/dist/components/aliases/AliasManager.js +72 -47
- package/dist/components/aliases/AliasManager.js.map +1 -1
- package/dist/components/shared/PluginGate.js +70 -71
- package/dist/components/shared/PluginGate.js.map +1 -1
- package/dist/generated/wspace-operations.js +4 -4
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/hooks/usePluginAvailability.js +59 -83
- package/dist/hooks/usePluginAvailability.js.map +1 -1
- package/dist/pages/AgentDetailsPage.js +486 -508
- package/dist/pages/AgentDetailsPage.js.map +1 -1
- package/dist/pages/VibeDetailsPage.js +457 -457
- package/dist/pages/VibeDetailsPage.js.map +1 -1
- package/dist/pages/ai/AIPage.js +10 -10
- package/dist/pages/ai/AISessionDetailPage.js +4 -4
- package/dist/pages/ai/AgentManagerPage.js +11 -11
- package/dist/pages/ai/AgentManagerPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -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
|
|
4
|
-
import { useCallback as
|
|
5
|
-
import { Check as ne, Loader2 as a,
|
|
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
|
|
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,
|
|
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
|
-
|
|
22
|
+
ce(Array.isArray(e) ? e : e.items ?? []);
|
|
18
23
|
} catch (e) {
|
|
19
|
-
|
|
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
|
|
28
|
-
|
|
29
|
-
let e =
|
|
33
|
+
let fe = async () => {
|
|
34
|
+
A(null);
|
|
35
|
+
let e = ee(x.trim());
|
|
30
36
|
if (e) {
|
|
31
|
-
|
|
37
|
+
A(e);
|
|
32
38
|
return;
|
|
33
39
|
}
|
|
34
|
-
if (!
|
|
35
|
-
|
|
40
|
+
if (!C.trim()) {
|
|
41
|
+
A(m("aliases.commandRequired", "Command is required"));
|
|
36
42
|
return;
|
|
37
43
|
}
|
|
38
|
-
|
|
44
|
+
O(!0);
|
|
39
45
|
try {
|
|
40
46
|
await n(p.id, h, "POST", {
|
|
41
|
-
name:
|
|
42
|
-
command:
|
|
43
|
-
description:
|
|
44
|
-
}),
|
|
47
|
+
name: x.trim(),
|
|
48
|
+
command: C,
|
|
49
|
+
description: T || void 0
|
|
50
|
+
}), S(""), w(""), E(""), await Q();
|
|
45
51
|
} catch (e) {
|
|
46
|
-
|
|
52
|
+
A(e instanceof Error ? e.message : String(e));
|
|
47
53
|
} finally {
|
|
48
|
-
|
|
54
|
+
O(!1);
|
|
49
55
|
}
|
|
50
|
-
},
|
|
56
|
+
}, pe = (e) => {
|
|
51
57
|
j(e.name), N(e.command), F(e.description ?? "");
|
|
52
58
|
}, $ = () => {
|
|
53
59
|
j(null), N(""), F("");
|
|
54
|
-
},
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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:
|
|
105
|
-
onChange: (e) =>
|
|
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:
|
|
111
|
-
onChange: (e) =>
|
|
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:
|
|
118
|
-
onChange: (e) =>
|
|
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
|
-
|
|
148
|
+
k && /* @__PURE__ */ d("div", {
|
|
124
149
|
className: "text-xs text-status-error-text",
|
|
125
|
-
children:
|
|
150
|
+
children: k
|
|
126
151
|
}),
|
|
127
152
|
/* @__PURE__ */ d("div", {
|
|
128
153
|
className: "flex justify-end",
|
|
129
154
|
children: /* @__PURE__ */ f("button", {
|
|
130
|
-
onClick:
|
|
131
|
-
disabled:
|
|
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: [
|
|
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:
|
|
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 =
|
|
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:
|
|
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
|
|
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: () =>
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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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"}
|