@monster-orange/den 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +273 -0
- package/README.md +9 -9
- package/docs/distributions.md +313 -50
- package/package.json +1 -1
- package/src/shared/agents/catalog-runtime.ts +178 -0
- package/src/shared/agents/catalog.ts +343 -0
- package/src/shared/agents/den-claude.ts +53 -12
- package/src/shared/agents/generic.ts +1 -0
- package/src/shared/agents/runtime-search.ts +543 -0
- package/src/shared/agents/runtime.ts +43 -1
- package/src/shared/agents/runtimes.ts +53 -4
- package/src/shared/auth/sudo-vault.ts +16 -0
- package/src/shared/den-config.ts +92 -2
- package/src/shared/edge/render.ts +31 -0
- package/src/shared/edge/status.ts +134 -0
- package/src/shared/environment-manager/health.ts +82 -8
- package/src/shared/environment-manager/workspaces.ts +54 -0
- package/src/shared/health/not-checked.ts +42 -0
- package/src/shared/health/rollup.ts +4 -0
- package/src/shared/process/spawn-streaming.ts +8 -3
- package/src/shared/sessions/client.ts +5 -1
- package/src/shared/sessions/host.ts +29 -1
- package/src/shared/sessions/protocol.ts +6 -1
- package/src/shared/sessions/types.ts +6 -0
- package/src/shared/stacks/status.ts +24 -0
- package/src/shared/strategies/registry.ts +5 -0
- package/src/shared/types/index.ts +6 -0
- package/src/ui/cli/agent-ops.ts +298 -19
- package/src/ui/cli/agents-command.ts +129 -4
- package/src/ui/cli/edge-command.ts +16 -3
- package/src/ui/cli/health-display.ts +4 -1
- package/src/ui/cli/sessions-command.ts +9 -4
- package/src/ui/cli/web-command.ts +53 -8
- package/src/ui/mcp/scope.ts +23 -3
- package/src/ui/mcp/server.ts +31 -7
- package/src/ui/mcp/tools.ts +327 -20
- package/src/ui/mcp/views.ts +450 -0
- package/src/ui/server/agent-routes.ts +123 -26
- package/src/ui/server/edge-exposure.ts +143 -0
- package/src/ui/server/index.ts +171 -25
- package/src/ui/server/public/agent-start.js +241 -0
- package/src/ui/server/public/agents-page.js +246 -45
- package/src/ui/server/public/agents-section.js +7 -21
- package/src/ui/server/public/agents.html +55 -1
- package/src/ui/server/public/graph-model.js +2 -0
- package/src/ui/server/public/header.js +2 -3
- package/src/ui/server/public/health-rollup.js +20 -8
- package/src/ui/server/public/i18n/es.js +26 -13
- package/src/ui/server/public/i18n/ja.js +25 -13
- package/src/ui/server/public/index.html +17 -4
- package/src/ui/server/public/local-dev.html +62 -22
- package/src/ui/server/public/services.html +21 -5
- package/src/ui/server/public/settings-page.js +3 -2
- package/src/ui/server/public/settings-registry.js +226 -1
- package/src/ui/server/public/settings.html +90 -1
- package/src/ui/server/public/shell.js +67 -22
- package/src/ui/server/public/topbar.js +217 -158
- package/src/ui/server/readonly-routes.ts +29 -5
- package/src/ui/server/request-guard.ts +123 -8
- package/src/ui/server/route-classes.ts +14 -2
- package/src/ui/server/session-routes.ts +9 -1
- package/src/ui/server/sudo-store.ts +170 -6
- package/src/ui/server/ui-assets.ts +2 -0
- package/src/ui/server/workspace-routes.ts +10 -3
|
@@ -7,15 +7,16 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Every call is the server's agent routes (agent-routes.ts), which are the
|
|
9
9
|
* CLI's own operations: nothing here keeps an agent's state. Each action
|
|
10
|
-
* goes through denShell.api() (a refusal is its error toast)
|
|
11
|
-
*
|
|
10
|
+
* goes through denShell.api() (a refusal is its error toast). None asks
|
|
11
|
+
* for the admin password: it is for sudo, and no agent action runs sudo
|
|
12
|
+
* (LK-0). A row with a
|
|
12
13
|
* session has Open (its terminal on the Agents page, AG-4a-term), and the
|
|
13
14
|
* header links to the Agents page for the workspace.
|
|
14
15
|
*
|
|
15
16
|
* The page's table styles (table.svc, .tablewrap, .tbl-*) and the shell's
|
|
16
17
|
* (.den-sec, .den-btn, .den-dot) are reused as they are.
|
|
17
18
|
*/
|
|
18
|
-
import {
|
|
19
|
+
import { fillStartForm } from "/agent-start.js";
|
|
19
20
|
|
|
20
21
|
const t = (key, vars) => window.denShell?.t?.(key, vars) ?? key;
|
|
21
22
|
const esc = (s) =>
|
|
@@ -62,6 +63,8 @@ export function agentsSectionHtml(ws) {
|
|
|
62
63
|
<form class="agent-form" id="agent-start-form" hidden>
|
|
63
64
|
<label>${esc(t("ag.persona"))} <select class="form-sel" name="persona" required></select></label>
|
|
64
65
|
<label>${esc(t("ag.runtime"))} <select class="form-sel" name="runtime"></select></label>
|
|
66
|
+
<p class="agent-form-help" data-persona-help hidden></p>
|
|
67
|
+
<p class="agent-form-ready" data-runtime-ready role="status" hidden></p>
|
|
65
68
|
<button type="submit" class="den-btn sm primary" id="agent-start-go">${esc(t("ag.go"))}</button>
|
|
66
69
|
<button type="button" class="den-btn sm" data-agent-cancel>${esc(t("ag.cancel"))}</button>
|
|
67
70
|
</form>
|
|
@@ -185,22 +188,7 @@ async function refresh(ws) {
|
|
|
185
188
|
}
|
|
186
189
|
|
|
187
190
|
function fillForm(form, data) {
|
|
188
|
-
|
|
189
|
-
ps.innerHTML = (data.personas ?? [])
|
|
190
|
-
.map(
|
|
191
|
-
(p) =>
|
|
192
|
-
`<option value="${esc(p.id)}">${esc(p.id)}${p.role ? ` — ${esc(p.role)}` : ""}</option>`,
|
|
193
|
-
)
|
|
194
|
-
.join("");
|
|
195
|
-
const rs = form.querySelector('select[name="runtime"]');
|
|
196
|
-
rs.innerHTML =
|
|
197
|
-
`<option value="">${esc(t("ag.runtime.auto"))}</option>` +
|
|
198
|
-
(data.runtimes ?? [])
|
|
199
|
-
.map(
|
|
200
|
-
(r) =>
|
|
201
|
-
`<option value="${esc(r.id)}"${r.available ? "" : " disabled"}>${esc(r.id)}${r.available ? "" : ` — ${esc(t("ag.unavailable"))}`}</option>`,
|
|
202
|
-
)
|
|
203
|
-
.join("");
|
|
191
|
+
fillStartForm(form, data, t);
|
|
204
192
|
}
|
|
205
193
|
|
|
206
194
|
async function openForm(sec) {
|
|
@@ -229,7 +217,6 @@ async function openForm(sec) {
|
|
|
229
217
|
}
|
|
230
218
|
|
|
231
219
|
async function act(ws, verb, id, button) {
|
|
232
|
-
if (!requireUnlock()) return;
|
|
233
220
|
button.disabled = true;
|
|
234
221
|
try {
|
|
235
222
|
await api("POST", `${base(ws)}/${encodeURIComponent(id)}/${verb}`);
|
|
@@ -243,7 +230,6 @@ async function act(ws, verb, id, button) {
|
|
|
243
230
|
}
|
|
244
231
|
|
|
245
232
|
async function start(ws, form) {
|
|
246
|
-
if (!requireUnlock()) return;
|
|
247
233
|
const go = form.querySelector("#agent-start-go");
|
|
248
234
|
const persona = form.querySelector('select[name="persona"]').value;
|
|
249
235
|
const runtime = form.querySelector('select[name="runtime"]').value;
|
|
@@ -298,7 +298,17 @@
|
|
|
298
298
|
font-size: 12.5px;
|
|
299
299
|
}
|
|
300
300
|
dialog.ag-dlg {
|
|
301
|
-
|
|
301
|
+
/* The approved mock's Start agent dialog (AG-0.5), measured on
|
|
302
|
+
den-shell.html: .dlg.wide, min(600px, 100%) of content in a
|
|
303
|
+
content-box, so 600 + 2 x 18 padding + 2 x 1 border = 638
|
|
304
|
+
outside at 1440. Here the box is border-box: 638, and never
|
|
305
|
+
wider than the viewport less 16px a side (at 375 the mock's
|
|
306
|
+
box is 381 and overflows; this one is 343). */
|
|
307
|
+
box-sizing: border-box;
|
|
308
|
+
width: min(638px, calc(100vw - 32px));
|
|
309
|
+
max-width: none;
|
|
310
|
+
max-height: calc(100vh - 32px);
|
|
311
|
+
overflow-y: auto;
|
|
302
312
|
background: var(--raised);
|
|
303
313
|
color: var(--text);
|
|
304
314
|
border: 1px solid var(--border-strong);
|
|
@@ -311,8 +321,41 @@
|
|
|
311
321
|
}
|
|
312
322
|
.ag-dlg form {
|
|
313
323
|
display: grid;
|
|
324
|
+
/* AG-10.0: minmax(0, 1fr), so a long option can't widen the form
|
|
325
|
+
past the dialog and push Cancel and Start out of sight. */
|
|
326
|
+
grid-template-columns: minmax(0, 1fr);
|
|
314
327
|
gap: 12px;
|
|
315
328
|
}
|
|
329
|
+
.ag-dlg .help {
|
|
330
|
+
margin: -6px 0 0;
|
|
331
|
+
font: 12.5px/1.45 var(--sans);
|
|
332
|
+
color: var(--muted);
|
|
333
|
+
overflow-wrap: anywhere;
|
|
334
|
+
}
|
|
335
|
+
.ag-dlg .help[hidden],
|
|
336
|
+
.ag-dlg .ready[hidden],
|
|
337
|
+
.ag-dlg .err[hidden] {
|
|
338
|
+
display: none;
|
|
339
|
+
}
|
|
340
|
+
/* AG-0.2: the runtime it will run, or why it can't, before Start
|
|
341
|
+
(the mock's .helpl: 12px, faint, 1.4). */
|
|
342
|
+
.ag-dlg .ready {
|
|
343
|
+
margin: -6px 0 0;
|
|
344
|
+
font: 12px/1.4 var(--sans);
|
|
345
|
+
color: var(--faint);
|
|
346
|
+
overflow-wrap: anywhere;
|
|
347
|
+
}
|
|
348
|
+
.ag-dlg .ready[data-tone="warn"] {
|
|
349
|
+
color: var(--warn);
|
|
350
|
+
}
|
|
351
|
+
.ag-dlg .ready .mono {
|
|
352
|
+
font-family: var(--mono);
|
|
353
|
+
}
|
|
354
|
+
.ag-dlg .err {
|
|
355
|
+
margin: 0;
|
|
356
|
+
font: 12.5px/1.45 var(--sans);
|
|
357
|
+
color: var(--bad);
|
|
358
|
+
}
|
|
316
359
|
.ag-dlg h2 {
|
|
317
360
|
margin: 0;
|
|
318
361
|
font: 600 17px var(--display);
|
|
@@ -325,7 +368,10 @@
|
|
|
325
368
|
text-transform: uppercase;
|
|
326
369
|
letter-spacing: 0.07em;
|
|
327
370
|
}
|
|
371
|
+
.ag-dlg input[type="password"],
|
|
328
372
|
.ag-dlg select {
|
|
373
|
+
width: 100%;
|
|
374
|
+
min-width: 0;
|
|
329
375
|
font: 13px var(--sans);
|
|
330
376
|
text-transform: none;
|
|
331
377
|
letter-spacing: 0;
|
|
@@ -404,10 +450,18 @@
|
|
|
404
450
|
><span id="ag-p-t">Persona</span>
|
|
405
451
|
<select name="persona" id="ag-persona" required></select
|
|
406
452
|
></label>
|
|
453
|
+
<p class="help" id="ag-p-help" data-persona-help hidden></p>
|
|
407
454
|
<label
|
|
408
455
|
><span id="ag-r-t">Runtime</span>
|
|
409
456
|
<select name="runtime" id="ag-runtime"></select
|
|
410
457
|
></label>
|
|
458
|
+
<p
|
|
459
|
+
class="ready"
|
|
460
|
+
id="ag-r-ready"
|
|
461
|
+
data-runtime-ready
|
|
462
|
+
role="status"
|
|
463
|
+
hidden
|
|
464
|
+
></p>
|
|
411
465
|
<div class="btns">
|
|
412
466
|
<button type="button" class="den-btn" id="ag-cancel">Cancel</button>
|
|
413
467
|
<button type="submit" class="den-btn primary" id="ag-go">
|
|
@@ -156,6 +156,7 @@ export function applyHealth(m, results) {
|
|
|
156
156
|
check: h.check ?? null,
|
|
157
157
|
error: h.error ?? null,
|
|
158
158
|
status: h.status ?? null,
|
|
159
|
+
redirect: h.redirect ?? null,
|
|
159
160
|
ms:
|
|
160
161
|
typeof h.ms === "number"
|
|
161
162
|
? h.ms
|
|
@@ -232,6 +233,7 @@ export function repoRollup(m, repo) {
|
|
|
232
233
|
service: s.name,
|
|
233
234
|
ok: s.health.ok,
|
|
234
235
|
isEntrypoint: s.entry,
|
|
236
|
+
redirect: !!s.health.redirect,
|
|
235
237
|
})),
|
|
236
238
|
);
|
|
237
239
|
}
|
|
@@ -30,12 +30,11 @@ const escT = (key, vars) =>
|
|
|
30
30
|
);
|
|
31
31
|
|
|
32
32
|
export {
|
|
33
|
-
|
|
34
|
-
onLockChange,
|
|
33
|
+
askSudo,
|
|
35
34
|
problemCards,
|
|
36
35
|
problemFix,
|
|
37
|
-
requireUnlock,
|
|
38
36
|
setServiceRunner,
|
|
37
|
+
sudoRun,
|
|
39
38
|
takePendingAction,
|
|
40
39
|
} from "./topbar.js";
|
|
41
40
|
export { buildRow } from "./health-fit.js";
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
export const STATE_RANK = { down: 0, degraded: 1, ok: 2, unknown: 3 };
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* @typedef {{ service: string, ok: boolean | null | undefined, isEntrypoint?: boolean, awaiting?: boolean }} HealthSignal
|
|
30
|
+
* @typedef {{ service: string, ok: boolean | null | undefined, isEntrypoint?: boolean, awaiting?: boolean, redirect?: boolean }} HealthSignal
|
|
31
31
|
* @typedef {"down" | "degraded" | "ok" | "unknown"} RepoState
|
|
32
|
-
* @typedef {{ state: RepoState, entry: string | null, down: string[], checked: number, unchecked: number, awaiting: number }} RepoRollup
|
|
32
|
+
* @typedef {{ state: RepoState, entry: string | null, down: string[], checked: number, unchecked: number, awaiting: number, redirected?: number }} RepoRollup
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
35
|
/**
|
|
@@ -60,6 +60,11 @@ export function rollupRepo(repo, signals) {
|
|
|
60
60
|
const answered = signals.filter((s) => !s.awaiting);
|
|
61
61
|
const entry = entrySignal(repo, answered);
|
|
62
62
|
const checked = answered.filter((s) => s.ok === true || s.ok === false);
|
|
63
|
+
// A redirect (ok null, `redirect`) answered: not down, not up, and not
|
|
64
|
+
// "not checked" either; counted on its own.
|
|
65
|
+
const redirected = answered.filter(
|
|
66
|
+
(s) => s.redirect && s.ok !== true && s.ok !== false,
|
|
67
|
+
).length;
|
|
63
68
|
const down = awaiting
|
|
64
69
|
? []
|
|
65
70
|
: checked.filter((s) => s.ok === false).map((s) => s.service);
|
|
@@ -77,8 +82,9 @@ export function rollupRepo(repo, signals) {
|
|
|
77
82
|
entry: entry ? entry.service : null,
|
|
78
83
|
down,
|
|
79
84
|
checked: checked.length,
|
|
80
|
-
unchecked: answered.length - checked.length,
|
|
85
|
+
unchecked: answered.length - checked.length - redirected,
|
|
81
86
|
awaiting,
|
|
87
|
+
...(redirected ? { redirected } : {}),
|
|
82
88
|
};
|
|
83
89
|
}
|
|
84
90
|
|
|
@@ -99,16 +105,22 @@ export function rollupRows(rows) {
|
|
|
99
105
|
|
|
100
106
|
/**
|
|
101
107
|
* "down (web down)", "degraded (mailpit down)", "healthy",
|
|
102
|
-
* "healthy, 25 not checked", "unknown (not
|
|
108
|
+
* "healthy, 25 not checked", "healthy, 1 redirect", "unknown (not
|
|
109
|
+
* checked)", "unknown (1 redirect)".
|
|
103
110
|
* @param {RepoRollup} r
|
|
104
111
|
* @returns {string}
|
|
105
112
|
*/
|
|
106
113
|
export function describeRollup(r) {
|
|
107
|
-
const
|
|
114
|
+
const extra = [
|
|
115
|
+
r.redirected ? `${r.redirected} redirect` : "",
|
|
116
|
+
r.unchecked > 0 ? `${r.unchecked} not checked` : "",
|
|
117
|
+
]
|
|
118
|
+
.filter(Boolean)
|
|
119
|
+
.join(", ");
|
|
108
120
|
if (r.awaiting) return "unknown (still checking)";
|
|
109
|
-
if (r.state === "unknown")
|
|
110
|
-
|
|
111
|
-
|
|
121
|
+
if (r.state === "unknown")
|
|
122
|
+
return r.redirected ? `unknown (${extra})` : "unknown (not checked)";
|
|
123
|
+
if (r.state === "ok") return extra ? `healthy, ${extra}` : "healthy";
|
|
112
124
|
return `${r.state} (${r.down.join(", ")} down)`;
|
|
113
125
|
}
|
|
114
126
|
|
|
@@ -142,26 +142,21 @@
|
|
|
142
142
|
"dock.err": "falló",
|
|
143
143
|
"dock.last": "Última ejecución: {s} ↗",
|
|
144
144
|
"dock.resize": "Arrastra para cambiar el tamaño",
|
|
145
|
-
"lock.
|
|
146
|
-
"lock.
|
|
147
|
-
"lock.
|
|
148
|
-
"Desbloquea para iniciar, detener y reiniciar servicios y agentes",
|
|
149
|
-
"lock.nopw":
|
|
150
|
-
"sudo sin contraseña (NOPASSWD): no hace falta la contraseña de administrador",
|
|
151
|
-
"lock.session": "Desbloqueado durante esta sesión",
|
|
152
|
-
"lock.sessionDesc":
|
|
153
|
-
"Desbloqueado durante esta sesión: iniciar, detener y reiniciar funcionan en todas las páginas.",
|
|
145
|
+
"lock.waiting": "Se necesita la contraseña de administrador",
|
|
146
|
+
"lock.needs": "{cmd} necesita tu contraseña de administrador",
|
|
147
|
+
"lock.cmd": "Un comando",
|
|
154
148
|
"lock.cfg":
|
|
155
149
|
"Guardar la contraseña está desactivado: define secrets.provider y secrets.refs.sudo en {file}.",
|
|
156
150
|
"lock.update": "Actualizar la contraseña guardada",
|
|
157
151
|
"lock.saveTo": "Guardar en {s}",
|
|
158
152
|
"lock.pw": "Contraseña de administrador",
|
|
159
|
-
"lock.go": "
|
|
153
|
+
"lock.go": "Continuar",
|
|
160
154
|
"lock.checking": "Comprobando…",
|
|
161
155
|
"lock.note":
|
|
162
|
-
"Den la
|
|
163
|
-
"lock.
|
|
164
|
-
"lock.saveFailed":
|
|
156
|
+
"Den la usa solo para sudo. Los agentes no pueden introducirla.",
|
|
157
|
+
"lock.saved": "Contraseña de administrador guardada para esta sesión",
|
|
158
|
+
"lock.saveFailed":
|
|
159
|
+
"Guardada para esta sesión, pero no se pudo guardar en {s}: {err}",
|
|
165
160
|
"lock.wrong": "Contraseña incorrecta; inténtalo de nuevo",
|
|
166
161
|
"lock.reqFailed": "La solicitud falló: ¿está en marcha el servidor?",
|
|
167
162
|
"v.title": "Ver el registro de cambios",
|
|
@@ -289,11 +284,13 @@
|
|
|
289
284
|
"set.graph.density": "Tarjetas",
|
|
290
285
|
"set.graph.panelWidth": "Panel de detalles",
|
|
291
286
|
"set.workspace.editor": "IDE de este espacio de trabajo",
|
|
287
|
+
"set.agents.runtimes": "Runtimes",
|
|
292
288
|
"set.cli.local_dev": "Entorno local",
|
|
293
289
|
"set.cli.cli_tabs": "Pestañas de terminal",
|
|
294
290
|
"set.cli.log_window_lines": "Líneas del panel de registros",
|
|
295
291
|
"set.cli.web_port": "Tu puerto web",
|
|
296
292
|
"set.cli.signin": "Inicio de sesión del navegador",
|
|
293
|
+
"set.cli.sudo": "Contraseña de administrador",
|
|
297
294
|
"set.distribution.brand": "Nombre del producto",
|
|
298
295
|
"set.distribution.github_org": "Org de GitHub",
|
|
299
296
|
"set.distribution.orgs": "Etiquetas de org",
|
|
@@ -330,6 +327,7 @@
|
|
|
330
327
|
"ag.persona": "Persona",
|
|
331
328
|
"ag.runtime": "Runtime",
|
|
332
329
|
"ag.runtime.auto": "La de la persona",
|
|
330
|
+
"ag.runtime.default": "{name} (la de la persona)",
|
|
333
331
|
"ag.unavailable": "no disponible",
|
|
334
332
|
"ag.go": "Iniciar",
|
|
335
333
|
"ag.starting": "Iniciando…",
|
|
@@ -372,5 +370,20 @@
|
|
|
372
370
|
"ag.palStart": "Iniciar agente…",
|
|
373
371
|
"ag.cap":
|
|
374
372
|
"Hasta 4 paneles: se cerró el de {id} para hacer sitio (sigue en marcha)",
|
|
373
|
+
"ag.rt.ready": "Inicia {name} {version} desde",
|
|
374
|
+
"ag.rt.readyNoVer": "Inicia {name} desde",
|
|
375
|
+
"ag.rt.notFound": "No se encontró {name}.",
|
|
376
|
+
"ag.rt.searched": "Se buscó en:",
|
|
377
|
+
"ag.rt.more": "y {n} más",
|
|
378
|
+
"ag.rt.nowhere": "ningún directorio",
|
|
379
|
+
"ag.rt.refused": "{name} no puede iniciarse: {why}.",
|
|
380
|
+
"ag.rt.fix":
|
|
381
|
+
"Instálalo, o pon su ruta en {key} en {file}, o ejecuta {cmd}.",
|
|
382
|
+
"ag.rt.unknown": "Aquí no hay ningún runtime {id}.",
|
|
383
|
+
"ag.rt.denTools": "Herramientas de Den: próximamente",
|
|
384
|
+
"ag.rt.ownCli":
|
|
385
|
+
"Se ejecuta como su propia CLI en el workspace: las herramientas y los modos de permiso de Den llegarán más adelante.",
|
|
386
|
+
"ag.rt.notInstalled": "no instalado",
|
|
387
|
+
"ag.rt.needsArgv": "la persona no tiene plantilla argv",
|
|
375
388
|
};
|
|
376
389
|
})((window.denMessages = window.denMessages || {}));
|
|
@@ -131,27 +131,21 @@
|
|
|
131
131
|
"dock.err": "失敗",
|
|
132
132
|
"dock.last": "前回の実行: {s} ↗",
|
|
133
133
|
"dock.resize": "ドラッグしてサイズを変更",
|
|
134
|
-
"lock.
|
|
135
|
-
"lock.
|
|
136
|
-
"lock.
|
|
137
|
-
"ロックを解除するとサービスとエージェントの起動・停止・再起動ができます",
|
|
138
|
-
"lock.nopw":
|
|
139
|
-
"パスワード不要の sudo (NOPASSWD): 管理者パスワードは必要ありません",
|
|
140
|
-
"lock.session": "このセッションの間ロックを解除しました",
|
|
141
|
-
"lock.sessionDesc":
|
|
142
|
-
"このセッションの間ロック解除中: どのページでも起動・停止・再起動ができます。",
|
|
134
|
+
"lock.waiting": "管理者パスワードが必要です",
|
|
135
|
+
"lock.needs": "{cmd} に管理者パスワードが必要です",
|
|
136
|
+
"lock.cmd": "コマンド",
|
|
143
137
|
"lock.cfg":
|
|
144
138
|
"パスワードの保存はオフです: {file} で secrets.provider と secrets.refs.sudo を設定してください。",
|
|
145
139
|
"lock.update": "保存したパスワードを更新",
|
|
146
140
|
"lock.saveTo": "{s} に保存",
|
|
147
141
|
"lock.pw": "管理者パスワード",
|
|
148
|
-
"lock.go": "
|
|
142
|
+
"lock.go": "続行",
|
|
149
143
|
"lock.checking": "確認中…",
|
|
150
144
|
"lock.note":
|
|
151
|
-
"Den
|
|
152
|
-
"lock.
|
|
145
|
+
"Den はこれを sudo にだけ使います。エージェントは入力できません。",
|
|
146
|
+
"lock.saved": "このセッションの間、管理者パスワードを保持します",
|
|
153
147
|
"lock.saveFailed":
|
|
154
|
-
"
|
|
148
|
+
"このセッションの間は保持しますが、{s} への保存に失敗しました: {err}",
|
|
155
149
|
"lock.wrong": "パスワードが違います。もう一度お試しください",
|
|
156
150
|
"lock.reqFailed": "リクエストに失敗しました。サーバーは動いていますか?",
|
|
157
151
|
"v.title": "変更履歴を見る",
|
|
@@ -278,11 +272,13 @@
|
|
|
278
272
|
"set.graph.density": "カード",
|
|
279
273
|
"set.graph.panelWidth": "詳細パネル",
|
|
280
274
|
"set.workspace.editor": "このワークスペースの IDE",
|
|
275
|
+
"set.agents.runtimes": "ランタイム",
|
|
281
276
|
"set.cli.local_dev": "ローカル環境",
|
|
282
277
|
"set.cli.cli_tabs": "ターミナルのタブ",
|
|
283
278
|
"set.cli.log_window_lines": "ログ欄の行数",
|
|
284
279
|
"set.cli.web_port": "あなたの web ポート",
|
|
285
280
|
"set.cli.signin": "ブラウザのサインイン",
|
|
281
|
+
"set.cli.sudo": "管理者パスワード",
|
|
286
282
|
"set.distribution.brand": "製品名",
|
|
287
283
|
"set.distribution.github_org": "GitHub の組織",
|
|
288
284
|
"set.distribution.orgs": "組織のラベル",
|
|
@@ -318,6 +314,7 @@
|
|
|
318
314
|
"ag.persona": "ペルソナ",
|
|
319
315
|
"ag.runtime": "ランタイム",
|
|
320
316
|
"ag.runtime.auto": "ペルソナの既定",
|
|
317
|
+
"ag.runtime.default": "{name}(ペルソナの既定)",
|
|
321
318
|
"ag.unavailable": "利用不可",
|
|
322
319
|
"ag.go": "開始",
|
|
323
320
|
"ag.starting": "開始中…",
|
|
@@ -357,5 +354,20 @@
|
|
|
357
354
|
"ag.palStart": "エージェントを開始…",
|
|
358
355
|
"ag.cap":
|
|
359
356
|
"ペインは最大 4 つです。{id} のペインを閉じました(実行は続きます)",
|
|
357
|
+
"ag.rt.ready": "{name} {version} を起動:",
|
|
358
|
+
"ag.rt.readyNoVer": "{name} を起動:",
|
|
359
|
+
"ag.rt.notFound": "{name} が見つかりません。",
|
|
360
|
+
"ag.rt.searched": "検索した場所:",
|
|
361
|
+
"ag.rt.more": "ほか {n} 件",
|
|
362
|
+
"ag.rt.nowhere": "なし",
|
|
363
|
+
"ag.rt.refused": "{name} を起動できません: {why}。",
|
|
364
|
+
"ag.rt.fix":
|
|
365
|
+
"インストールするか、{file} の {key} にパスを設定するか、{cmd} を実行してください。",
|
|
366
|
+
"ag.rt.unknown": "ランタイム {id} はここにありません。",
|
|
367
|
+
"ag.rt.denTools": "Den ツール: 近日対応",
|
|
368
|
+
"ag.rt.ownCli":
|
|
369
|
+
"ワークスペースで独自の CLI として動きます。Den のツールと権限モードは今後対応します。",
|
|
370
|
+
"ag.rt.notInstalled": "未インストール",
|
|
371
|
+
"ag.rt.needsArgv": "ペルソナに argv テンプレートがありません",
|
|
360
372
|
};
|
|
361
373
|
})((window.denMessages = window.denMessages || {}));
|
|
@@ -1160,6 +1160,7 @@
|
|
|
1160
1160
|
storeOpenLog,
|
|
1161
1161
|
initChangelog,
|
|
1162
1162
|
envReady,
|
|
1163
|
+
sudoRun,
|
|
1163
1164
|
} from "/header.js";
|
|
1164
1165
|
import { ownersLabel } from "/workspace-picker.js";
|
|
1165
1166
|
import {
|
|
@@ -2128,10 +2129,16 @@
|
|
|
2128
2129
|
|
|
2129
2130
|
pane.innerHTML = services
|
|
2130
2131
|
.map((s) => {
|
|
2132
|
+
// The row's own workspace (the first in view that defines it):
|
|
2133
|
+
// its command runs there, not in the focused one.
|
|
2134
|
+
const ws = s.inWorkspaces?.[0];
|
|
2135
|
+
const wsAttr = ws
|
|
2136
|
+
? ` data-workspace="${String(ws).replace(/[&<>"]/g, (c) => `&#${c.charCodeAt(0)};`)}"`
|
|
2137
|
+
: "";
|
|
2131
2138
|
const cmdBtns = s.commands
|
|
2132
2139
|
.map(
|
|
2133
2140
|
(cmd) =>
|
|
2134
|
-
`<button class="cmd-btn" data-repo="${s.repo}" data-service="${s.service}" data-cmd="${cmd}" data-type="exec">${cmd}</button>`,
|
|
2141
|
+
`<button class="cmd-btn" data-repo="${s.repo}" data-service="${s.service}" data-cmd="${cmd}" data-type="exec"${wsAttr}>${cmd}</button>`,
|
|
2135
2142
|
)
|
|
2136
2143
|
.join("");
|
|
2137
2144
|
const logsBtn = s.logs
|
|
@@ -2156,8 +2163,8 @@
|
|
|
2156
2163
|
|
|
2157
2164
|
pane.querySelectorAll(".cmd-btn").forEach((btn) => {
|
|
2158
2165
|
btn.addEventListener("click", () => {
|
|
2159
|
-
const { repo, service, cmd, type } = btn.dataset;
|
|
2160
|
-
if (type === "exec") runExec(repo, service, cmd);
|
|
2166
|
+
const { repo, service, cmd, type, workspace } = btn.dataset;
|
|
2167
|
+
if (type === "exec") runExec(repo, service, cmd, workspace);
|
|
2161
2168
|
else {
|
|
2162
2169
|
const env = document.getElementById("env-sel").value;
|
|
2163
2170
|
storeOpenLog(repo, service, env);
|
|
@@ -2201,7 +2208,7 @@
|
|
|
2201
2208
|
}
|
|
2202
2209
|
|
|
2203
2210
|
// ── Service exec ──────────────────────────────────────────────────────────
|
|
2204
|
-
function runExec(repo, service, cmd) {
|
|
2211
|
+
function runExec(repo, service, cmd, workspace) {
|
|
2205
2212
|
if (execEs) {
|
|
2206
2213
|
execEs.close();
|
|
2207
2214
|
execEs = null;
|
|
@@ -2234,9 +2241,14 @@
|
|
|
2234
2241
|
);
|
|
2235
2242
|
|
|
2236
2243
|
const params = new URLSearchParams({ repo, service, cmd, env });
|
|
2244
|
+
if (workspace) params.set("workspace", workspace);
|
|
2237
2245
|
execEs = new EventSource(`/api/service/exec?${params}`);
|
|
2246
|
+
// LK-0: a command that needs sudo without the password asks, then
|
|
2247
|
+
// runs again.
|
|
2248
|
+
const sudo = sudoRun();
|
|
2238
2249
|
execEs.onmessage = (e) => {
|
|
2239
2250
|
const msg = JSON.parse(e.data);
|
|
2251
|
+
sudo.see(msg);
|
|
2240
2252
|
if (msg.type === "cmd") {
|
|
2241
2253
|
cmdAppendLine(msg.text, "cmd");
|
|
2242
2254
|
execDetachable = !!msg.detached;
|
|
@@ -2261,6 +2273,7 @@
|
|
|
2261
2273
|
.forEach((b) => (b.disabled = false));
|
|
2262
2274
|
execEs?.close();
|
|
2263
2275
|
execEs = null;
|
|
2276
|
+
void sudo.done(() => runExec(repo, service, cmd, workspace));
|
|
2264
2277
|
}
|
|
2265
2278
|
};
|
|
2266
2279
|
execEs.onerror = () => {
|