@monster-orange/den 0.4.3 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +348 -0
- package/README.md +12 -11
- package/docs/distributions.md +438 -91
- package/docs/reference.md +8 -3
- 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 +14 -18
- package/src/shared/agents/runtime-search.ts +142 -15
- package/src/shared/agents/runtime.ts +18 -1
- package/src/shared/agents/runtimes.ts +23 -1
- package/src/shared/auth/sudo-vault.ts +131 -11
- package/src/shared/cli-command.ts +186 -0
- package/src/shared/confirm-code.ts +34 -0
- package/src/shared/den-config.ts +64 -3
- package/src/shared/dev-metrics/emit.ts +31 -1
- package/src/shared/edge/config.ts +39 -0
- package/src/shared/edge/render.ts +92 -18
- package/src/shared/edge/runtime.ts +57 -1
- package/src/shared/edge/status.ts +134 -0
- package/src/shared/edge/types.ts +11 -1
- package/src/shared/environment-manager/health.ts +82 -8
- package/src/shared/environment-manager/workspaces.ts +54 -0
- package/src/shared/github-app.ts +94 -0
- package/src/shared/github-device.ts +286 -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/secrets/onepassword.ts +27 -4
- 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/shared/web-owner.ts +91 -0
- package/src/shared/web-session.ts +135 -1
- package/src/ui/cli/agent-ops.ts +210 -19
- package/src/ui/cli/agents-command.ts +50 -21
- package/src/ui/cli/edge-command.ts +16 -3
- package/src/ui/cli/flag-parser.ts +1 -1
- package/src/ui/cli/health-display.ts +4 -1
- package/src/ui/cli/web-command.ts +512 -33
- 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 +118 -28
- package/src/ui/server/device-flows.ts +274 -0
- package/src/ui/server/edge-exposure.ts +16 -4
- package/src/ui/server/github-routes.ts +321 -0
- package/src/ui/server/http-errors.ts +10 -0
- package/src/ui/server/index.ts +540 -33
- package/src/ui/server/login-waits.ts +203 -0
- package/src/ui/server/pair-requests.ts +237 -0
- package/src/ui/server/pair-routes.ts +196 -0
- package/src/ui/server/public/agent-start.js +46 -7
- package/src/ui/server/public/agents-page.js +232 -97
- package/src/ui/server/public/agents-section.js +3 -5
- package/src/ui/server/public/agents.html +12 -28
- package/src/ui/server/public/error-page.js +452 -40
- package/src/ui/server/public/error.html +59 -0
- 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 +89 -21
- package/src/ui/server/public/i18n/ja.js +88 -21
- package/src/ui/server/public/index.html +17 -4
- package/src/ui/server/public/local-dev.html +44 -21
- package/src/ui/server/public/qr.js +317 -0
- package/src/ui/server/public/services.html +21 -5
- package/src/ui/server/public/settings-page.js +10 -2
- package/src/ui/server/public/settings-registry.js +617 -1
- package/src/ui/server/public/settings.html +90 -1
- package/src/ui/server/public/shell.js +151 -33
- package/src/ui/server/public/topbar.js +170 -206
- package/src/ui/server/public/workspace-picker.js +1 -1
- package/src/ui/server/readonly-routes.ts +29 -5
- package/src/ui/server/request-guard.ts +103 -36
- package/src/ui/server/route-classes.ts +116 -4
- 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
|
@@ -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
|
|
|
@@ -27,7 +27,9 @@
|
|
|
27
27
|
"org.title": "Org: {title}",
|
|
28
28
|
"org.titleId": "Org: {title} ({id})",
|
|
29
29
|
"ws.all": "Todos los activos",
|
|
30
|
-
"ws.focus": "
|
|
30
|
+
"ws.focus": "predeterminado de la CLI",
|
|
31
|
+
"ws.focusTip":
|
|
32
|
+
"Los comandos de la CLI se ejecutan aquí si no indicas un espacio de trabajo. Elegir un espacio en la barra superior solo cambia lo que muestran las páginas.",
|
|
31
33
|
"ws.none": "No hay espacios de trabajo activos",
|
|
32
34
|
"ws.manage": "Gestionar espacios de trabajo…",
|
|
33
35
|
"ws.allN": "Todos los activos ({n})",
|
|
@@ -37,8 +39,8 @@
|
|
|
37
39
|
"ws.viewTitle":
|
|
38
40
|
"Vista: lo que muestra cada página ({ws}). Es solo un filtro: no inicia, detiene ni enruta nada.",
|
|
39
41
|
"ws.viewTitleFocus":
|
|
40
|
-
"Vista: lo que muestra cada página ({ws}). Es solo un filtro: no inicia, detiene ni enruta nada, y el
|
|
41
|
-
"ws.setFocus": "
|
|
42
|
+
"Vista: lo que muestra cada página ({ws}). Es solo un filtro: no inicia, detiene ni enruta nada, y el predeterminado de la CLI ({focus}) sigue siendo el destino de los comandos.",
|
|
43
|
+
"ws.setFocus": "Hacer de {ws} el predeterminado de la CLI",
|
|
42
44
|
"ws.setFocusTip":
|
|
43
45
|
"Lo convierte en el destino por defecto de los comandos (escribe workspaces.yml)",
|
|
44
46
|
"ws.viewFailed": "No se pudo cambiar la vista: {msg}",
|
|
@@ -142,26 +144,21 @@
|
|
|
142
144
|
"dock.err": "falló",
|
|
143
145
|
"dock.last": "Última ejecución: {s} ↗",
|
|
144
146
|
"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.",
|
|
147
|
+
"lock.waiting": "Se necesita la contraseña de administrador",
|
|
148
|
+
"lock.needs": "{cmd} necesita tu contraseña de administrador",
|
|
149
|
+
"lock.cmd": "Un comando",
|
|
154
150
|
"lock.cfg":
|
|
155
151
|
"Guardar la contraseña está desactivado: define secrets.provider y secrets.refs.sudo en {file}.",
|
|
156
152
|
"lock.update": "Actualizar la contraseña guardada",
|
|
157
153
|
"lock.saveTo": "Guardar en {s}",
|
|
158
154
|
"lock.pw": "Contraseña de administrador",
|
|
159
|
-
"lock.go": "
|
|
155
|
+
"lock.go": "Continuar",
|
|
160
156
|
"lock.checking": "Comprobando…",
|
|
161
157
|
"lock.note":
|
|
162
|
-
"Den la
|
|
163
|
-
"lock.
|
|
164
|
-
"lock.saveFailed":
|
|
158
|
+
"Den la usa solo para sudo. Los agentes no pueden introducirla.",
|
|
159
|
+
"lock.saved": "Contraseña de administrador guardada para esta sesión",
|
|
160
|
+
"lock.saveFailed":
|
|
161
|
+
"Guardada para esta sesión, pero no se pudo guardar en {s}: {err}",
|
|
165
162
|
"lock.wrong": "Contraseña incorrecta; inténtalo de nuevo",
|
|
166
163
|
"lock.reqFailed": "La solicitud falló: ¿está en marcha el servidor?",
|
|
167
164
|
"v.title": "Ver el registro de cambios",
|
|
@@ -247,19 +244,74 @@
|
|
|
247
244
|
"Este servidor solo responde en sus propias direcciones, así que una página con otro nombre no puede alcanzarlo.",
|
|
248
245
|
"err.421.open": "Abrir en localhost",
|
|
249
246
|
"err.refused.title": "Solicitud rechazada",
|
|
250
|
-
"err.signin.title": "Inicia sesión para usar {name}",
|
|
251
247
|
"err.signin.terminal": "Inicia sesión para usar la terminal",
|
|
252
248
|
"err.signin.agents": "Inicia sesión para iniciar agentes",
|
|
253
249
|
"err.signin.sub": "Este navegador no ha iniciado sesión",
|
|
254
250
|
"err.signin.lead": "Ejecuta {cmd} y abre el enlace.",
|
|
255
251
|
"err.signin.expiredTitle": "El enlace de inicio de sesión caducó",
|
|
256
|
-
"err.signin.expired":
|
|
257
|
-
"Ese enlace de inicio de sesión caducó o ya se usó. Ejecuta {cmd} para obtener uno nuevo.",
|
|
258
252
|
"err.signin.local":
|
|
259
253
|
"Un inicio de sesión pertenece a una sola dirección. Esta página está en {host}: abre la misma página en localhost, donde este navegador tiene la sesión iniciada.",
|
|
260
|
-
"err.signin.why":
|
|
261
|
-
"No hay contraseña: el enlace sale de un archivo que solo tu cuenta de usuario puede leer.",
|
|
262
254
|
"err.signin.copy": "Copiar comando",
|
|
255
|
+
"err.signin.title": "Inicia sesión en {name}",
|
|
256
|
+
"err.signin.where":
|
|
257
|
+
"Estás abriendo {name} desde otro ordenador. {name} corre en {host}, así que necesita saber que eres tú.",
|
|
258
|
+
"err.signin.githubNote":
|
|
259
|
+
"Usa tu cuenta de GitHub. El propietario de este {name} tiene que haber vinculado la suya.",
|
|
260
|
+
"err.signin.githubNoOwner":
|
|
261
|
+
"Iniciar sesión con GitHub necesita un propietario, y este {name} aún no tiene. En {host} (no en este ordenador), ejecuta:",
|
|
262
|
+
"err.signin.githubRefused":
|
|
263
|
+
"@{login} no es el propietario de este {name}. Pide al propietario que te añada, o usa «Aprobar este ordenador».",
|
|
264
|
+
"err.signin.approveOr": "O aprueba este ordenador",
|
|
265
|
+
"err.signin.approve": "Aprueba este ordenador",
|
|
266
|
+
"err.signin.step1": "En {host} (no en este ordenador), ejecuta:",
|
|
267
|
+
"err.signin.step1Or":
|
|
268
|
+
"O abre {name} en el propio {host} y ve a Ajustes › Acceso › Dispositivos en espera.",
|
|
269
|
+
"err.signin.step2":
|
|
270
|
+
"Esta página inicia sesión sola una vez aprobada. El código caduca en 10 minutos.",
|
|
271
|
+
"err.signin.waiting": "Esperando la aprobación…",
|
|
272
|
+
"err.signin.noTerminal":
|
|
273
|
+
"¿No tienes una terminal en {host}? Desde este ordenador, ejecuta:",
|
|
274
|
+
"err.signin.openTerminal": "Abrir Terminal",
|
|
275
|
+
"err.signin.sshNote":
|
|
276
|
+
"Abrir Terminal abre ssh://{target} en tu aplicación de terminal. Necesita acceso SSH a {target}.",
|
|
277
|
+
"err.signin.whyTitle": "¿Por qué?",
|
|
278
|
+
"err.signin.whyText":
|
|
279
|
+
"{name} puede iniciar terminales y agentes en {host}, así que solo deja entrar a quien demuestra ser el propietario. Solo lo haces una vez por ordenador: la sesión se mantiene.",
|
|
280
|
+
"err.signin.other": "Otras formas (el enlace de un solo uso con {cmd})",
|
|
281
|
+
"err.signin.otherStep":
|
|
282
|
+
"En {host} (no en este ordenador), ejecuta esto y abre en este navegador el enlace que imprime:",
|
|
283
|
+
"err.signin.codeExpired": "Este código caducó.",
|
|
284
|
+
"err.signin.codeDenied": "Este ordenador fue rechazado en {host}.",
|
|
285
|
+
"err.signin.codeFailed":
|
|
286
|
+
"{name} no dio un código a esta página. Inténtalo de nuevo.",
|
|
287
|
+
"err.signin.newCode": "Obtener un código nuevo",
|
|
288
|
+
"err.signin.youreIn": "Ya estás dentro.",
|
|
289
|
+
"err.signin.expiredLead":
|
|
290
|
+
"Ese enlace de inicio de sesión caducó o ya se usó. Inicia sesión de nuevo abajo.",
|
|
291
|
+
"err.signin.confirmLead":
|
|
292
|
+
"Introduce el código que web login imprimió en {host}:",
|
|
293
|
+
"err.signin.confirmGo": "Iniciar sesión",
|
|
294
|
+
"err.signin.confirmWrong":
|
|
295
|
+
"Ese código no es correcto. Revisa lo que imprimió web login e inténtalo de nuevo.",
|
|
296
|
+
"err.signin.confirmBusy":
|
|
297
|
+
"Demasiados intentos. Espera un minuto e inténtalo de nuevo.",
|
|
298
|
+
"err.signin.confirmGone":
|
|
299
|
+
"Este enlace ya no funciona. En {host}, ejecuta web login de nuevo para obtener uno nuevo.",
|
|
300
|
+
"err.signin.confirmWhy":
|
|
301
|
+
"El enlace solo no basta: también hace falta el código que se muestra en {host}, así que alguien que vea el enlace no puede iniciar sesión.",
|
|
302
|
+
"err.signin.github": "Iniciar sesión con GitHub",
|
|
303
|
+
"err.signin.githubEnter": "Introduce este código en {url}:",
|
|
304
|
+
"err.signin.githubOpen": "Abrir GitHub",
|
|
305
|
+
"err.signin.githubCopy": "Copiar código",
|
|
306
|
+
"err.signin.githubWaiting": "Esperando a que lo apruebes en GitHub…",
|
|
307
|
+
"err.signin.githubDone": "Sesión iniciada. Cargando…",
|
|
308
|
+
"err.signin.githubExpired": "El código caducó antes de aprobarse.",
|
|
309
|
+
"err.signin.githubDenied": "La solicitud se canceló en GitHub.",
|
|
310
|
+
"err.signin.githubBusy":
|
|
311
|
+
"Hay demasiados inicios de sesión en curso. Vuelve a intentarlo en unos minutos.",
|
|
312
|
+
"err.signin.githubFailed":
|
|
313
|
+
"No se pudo contactar con GitHub. Inténtalo de nuevo.",
|
|
314
|
+
"err.signin.githubAgain": "Empezar de nuevo",
|
|
263
315
|
"err.422.title": "La configuración no es válida",
|
|
264
316
|
"err.422.sub": "La configuración de la distribución no pasa la validación",
|
|
265
317
|
"err.422.lead":
|
|
@@ -289,11 +341,22 @@
|
|
|
289
341
|
"set.graph.density": "Tarjetas",
|
|
290
342
|
"set.graph.panelWidth": "Panel de detalles",
|
|
291
343
|
"set.workspace.editor": "IDE de este espacio de trabajo",
|
|
344
|
+
"set.agents.runtimes": "Runtimes",
|
|
292
345
|
"set.cli.local_dev": "Entorno local",
|
|
293
346
|
"set.cli.cli_tabs": "Pestañas de terminal",
|
|
294
347
|
"set.cli.log_window_lines": "Líneas del panel de registros",
|
|
295
348
|
"set.cli.web_port": "Tu puerto web",
|
|
296
349
|
"set.cli.signin": "Inicio de sesión del navegador",
|
|
350
|
+
"set.cli.sudo": "Contraseña de administrador",
|
|
351
|
+
"set.access.owner": "Propietario",
|
|
352
|
+
"set.access.devices": "Dispositivos vinculados",
|
|
353
|
+
"set.access.waiting": "Dispositivos en espera",
|
|
354
|
+
"set.access.machine_name": "Nombre de la máquina",
|
|
355
|
+
"ident.local": "Local",
|
|
356
|
+
"ident.device": "Sesión iniciada · este dispositivo",
|
|
357
|
+
"ident.toast":
|
|
358
|
+
"Este dispositivo tiene la sesión iniciada en {name} en {host}",
|
|
359
|
+
"set.access.pair": "Emparejar un dispositivo",
|
|
297
360
|
"set.distribution.brand": "Nombre del producto",
|
|
298
361
|
"set.distribution.github_org": "Org de GitHub",
|
|
299
362
|
"set.distribution.orgs": "Etiquetas de org",
|
|
@@ -383,5 +446,10 @@
|
|
|
383
446
|
"ag.rt.fix":
|
|
384
447
|
"Instálalo, o pon su ruta en {key} en {file}, o ejecuta {cmd}.",
|
|
385
448
|
"ag.rt.unknown": "Aquí no hay ningún runtime {id}.",
|
|
449
|
+
"ag.rt.denTools": "Herramientas de Den: próximamente",
|
|
450
|
+
"ag.rt.ownCli":
|
|
451
|
+
"Se ejecuta como su propia CLI en el workspace: las herramientas y los modos de permiso de Den llegarán más adelante.",
|
|
452
|
+
"ag.rt.notInstalled": "no instalado",
|
|
453
|
+
"ag.rt.needsArgv": "la persona no tiene plantilla argv",
|
|
386
454
|
};
|
|
387
455
|
})((window.denMessages = window.denMessages || {}));
|
|
@@ -27,7 +27,9 @@
|
|
|
27
27
|
"org.title": "組織: {title}",
|
|
28
28
|
"org.titleId": "組織: {title} ({id})",
|
|
29
29
|
"ws.all": "すべてのアクティブ",
|
|
30
|
-
"ws.focus": "
|
|
30
|
+
"ws.focus": "CLI の既定",
|
|
31
|
+
"ws.focusTip":
|
|
32
|
+
"ワークスペースを指定しないとき、CLI のコマンドはここで実行されます。上部バーでワークスペースを選んでも、ページの表示が変わるだけです。",
|
|
31
33
|
"ws.none": "アクティブなワークスペースはありません",
|
|
32
34
|
"ws.manage": "ワークスペースを管理…",
|
|
33
35
|
"ws.allN": "すべてのアクティブ ({n})",
|
|
@@ -37,8 +39,8 @@
|
|
|
37
39
|
"ws.viewTitle":
|
|
38
40
|
"表示: すべてのページに表示する範囲 ({ws})。表示の絞り込みだけで、何も起動・停止・ルーティングしません。",
|
|
39
41
|
"ws.viewTitleFocus":
|
|
40
|
-
"表示: すべてのページに表示する範囲 ({ws})
|
|
41
|
-
"ws.setFocus": "{ws}
|
|
42
|
+
"表示: すべてのページに表示する範囲 ({ws})。表示の絞り込みだけで、何も起動・停止・ルーティングしません。コマンドの対象は CLI の既定 ({focus}) のままです。",
|
|
43
|
+
"ws.setFocus": "{ws} を CLI の既定にする",
|
|
42
44
|
"ws.setFocusTip":
|
|
43
45
|
"コマンドの既定の対象にします (workspaces.yml に書き込みます)",
|
|
44
46
|
"ws.viewFailed": "表示を変更できませんでした: {msg}",
|
|
@@ -131,27 +133,21 @@
|
|
|
131
133
|
"dock.err": "失敗",
|
|
132
134
|
"dock.last": "前回の実行: {s} ↗",
|
|
133
135
|
"dock.resize": "ドラッグしてサイズを変更",
|
|
134
|
-
"lock.
|
|
135
|
-
"lock.
|
|
136
|
-
"lock.
|
|
137
|
-
"ロックを解除するとサービスとエージェントの起動・停止・再起動ができます",
|
|
138
|
-
"lock.nopw":
|
|
139
|
-
"パスワード不要の sudo (NOPASSWD): 管理者パスワードは必要ありません",
|
|
140
|
-
"lock.session": "このセッションの間ロックを解除しました",
|
|
141
|
-
"lock.sessionDesc":
|
|
142
|
-
"このセッションの間ロック解除中: どのページでも起動・停止・再起動ができます。",
|
|
136
|
+
"lock.waiting": "管理者パスワードが必要です",
|
|
137
|
+
"lock.needs": "{cmd} に管理者パスワードが必要です",
|
|
138
|
+
"lock.cmd": "コマンド",
|
|
143
139
|
"lock.cfg":
|
|
144
140
|
"パスワードの保存はオフです: {file} で secrets.provider と secrets.refs.sudo を設定してください。",
|
|
145
141
|
"lock.update": "保存したパスワードを更新",
|
|
146
142
|
"lock.saveTo": "{s} に保存",
|
|
147
143
|
"lock.pw": "管理者パスワード",
|
|
148
|
-
"lock.go": "
|
|
144
|
+
"lock.go": "続行",
|
|
149
145
|
"lock.checking": "確認中…",
|
|
150
146
|
"lock.note":
|
|
151
|
-
"Den
|
|
152
|
-
"lock.
|
|
147
|
+
"Den はこれを sudo にだけ使います。エージェントは入力できません。",
|
|
148
|
+
"lock.saved": "このセッションの間、管理者パスワードを保持します",
|
|
153
149
|
"lock.saveFailed":
|
|
154
|
-
"
|
|
150
|
+
"このセッションの間は保持しますが、{s} への保存に失敗しました: {err}",
|
|
155
151
|
"lock.wrong": "パスワードが違います。もう一度お試しください",
|
|
156
152
|
"lock.reqFailed": "リクエストに失敗しました。サーバーは動いていますか?",
|
|
157
153
|
"v.title": "変更履歴を見る",
|
|
@@ -236,19 +232,75 @@
|
|
|
236
232
|
"このサーバーは自身のアドレスでのみ応答するため、別の名前のページからは届きません。",
|
|
237
233
|
"err.421.open": "localhost で開く",
|
|
238
234
|
"err.refused.title": "リクエストが拒否されました",
|
|
239
|
-
"err.signin.title": "{name} を使うにはサインインしてください",
|
|
240
235
|
"err.signin.terminal": "ターミナルを使うにはサインインしてください",
|
|
241
236
|
"err.signin.agents": "エージェントを起動するにはサインインしてください",
|
|
242
237
|
"err.signin.sub": "このブラウザはサインインしていません",
|
|
243
238
|
"err.signin.lead": "{cmd} を実行し、表示されたリンクを開いてください。",
|
|
244
239
|
"err.signin.expiredTitle": "サインインリンクの期限切れ",
|
|
245
|
-
"err.signin.expired":
|
|
246
|
-
"このサインインリンクは期限切れか、使用済みです。{cmd} を実行して新しいリンクを取得してください。",
|
|
247
240
|
"err.signin.local":
|
|
248
241
|
"サインインはアドレスごとです。このページは {host} にあります。サインイン済みの localhost で同じページを開いてください。",
|
|
249
|
-
"err.signin.why":
|
|
250
|
-
"パスワードはありません。リンクは、あなたのユーザーアカウントだけが読めるファイルから作られます。",
|
|
251
242
|
"err.signin.copy": "コマンドをコピー",
|
|
243
|
+
"err.signin.title": "{name} にサインイン",
|
|
244
|
+
"err.signin.where":
|
|
245
|
+
"別のコンピューターから {name} を開いています。{name} は {host} で動いているため、あなた本人であることを確認する必要があります。",
|
|
246
|
+
"err.signin.githubNote":
|
|
247
|
+
"あなたの GitHub アカウントを使います。この {name} のオーナーが自分のアカウントをリンクしている必要があります。",
|
|
248
|
+
"err.signin.githubNoOwner":
|
|
249
|
+
"GitHub でのサインインにはオーナーが必要ですが、この {name} にはまだいません。{host} で(このコンピューターではありません)次を実行してください:",
|
|
250
|
+
"err.signin.githubRefused":
|
|
251
|
+
"@{login} はこの {name} のオーナーではありません。オーナーに追加を依頼するか、「このコンピューターを承認」を使ってください。",
|
|
252
|
+
"err.signin.approveOr": "または、このコンピューターを承認",
|
|
253
|
+
"err.signin.approve": "このコンピューターを承認",
|
|
254
|
+
"err.signin.step1":
|
|
255
|
+
"{host} で(このコンピューターではありません)次を実行します:",
|
|
256
|
+
"err.signin.step1Or":
|
|
257
|
+
"または、{host} 上で {name} を開き、設定 › アクセス › 承認待ちのデバイス に進みます。",
|
|
258
|
+
"err.signin.step2":
|
|
259
|
+
"承認されると、このページは自動でサインインします。コードの有効期限は 10 分です。",
|
|
260
|
+
"err.signin.waiting": "承認を待っています…",
|
|
261
|
+
"err.signin.noTerminal":
|
|
262
|
+
"{host} のターミナルがありませんか?このコンピューターで次を実行します:",
|
|
263
|
+
"err.signin.openTerminal": "ターミナルを開く",
|
|
264
|
+
"err.signin.sshNote":
|
|
265
|
+
"「ターミナルを開く」はターミナルアプリで ssh://{target} を開きます。{target} への SSH アクセスが必要です。",
|
|
266
|
+
"err.signin.whyTitle": "なぜ?",
|
|
267
|
+
"err.signin.whyText":
|
|
268
|
+
"{name} は {host} でターミナルやエージェントを起動できるため、オーナーであることを証明した人だけを通します。これはコンピューターごとに一度だけで、サインインしたままになります。",
|
|
269
|
+
"err.signin.other": "その他の方法({cmd} による一回限りのリンク)",
|
|
270
|
+
"err.signin.otherStep":
|
|
271
|
+
"{host} で(このコンピューターではありません)次を実行し、表示されたリンクをこのブラウザで開きます:",
|
|
272
|
+
"err.signin.codeExpired": "このコードは期限切れです。",
|
|
273
|
+
"err.signin.codeDenied": "このコンピューターは {host} で拒否されました。",
|
|
274
|
+
"err.signin.codeFailed":
|
|
275
|
+
"{name} からコードを取得できませんでした。もう一度お試しください。",
|
|
276
|
+
"err.signin.newCode": "新しいコードを取得",
|
|
277
|
+
"err.signin.youreIn": "サインインしました。",
|
|
278
|
+
"err.signin.expiredLead":
|
|
279
|
+
"このサインインリンクは期限切れか、使用済みです。下から改めてサインインしてください。",
|
|
280
|
+
"err.signin.confirmLead":
|
|
281
|
+
"{host} で web login が表示したコードを入力してください:",
|
|
282
|
+
"err.signin.confirmGo": "サインイン",
|
|
283
|
+
"err.signin.confirmWrong":
|
|
284
|
+
"コードが正しくありません。web login の表示を確認して、もう一度お試しください。",
|
|
285
|
+
"err.signin.confirmBusy":
|
|
286
|
+
"試行回数が多すぎます。1 分待ってからもう一度お試しください。",
|
|
287
|
+
"err.signin.confirmGone":
|
|
288
|
+
"このリンクはもう使えません。{host} で web login をもう一度実行して新しいリンクを取得してください。",
|
|
289
|
+
"err.signin.confirmWhy":
|
|
290
|
+
"リンクだけでは足りません。{host} に表示されたコードも必要なので、他の人がリンクを見てもサインインできません。",
|
|
291
|
+
"err.signin.github": "GitHub でサインイン",
|
|
292
|
+
"err.signin.githubEnter": "{url} でこのコードを入力してください:",
|
|
293
|
+
"err.signin.githubOpen": "GitHub を開く",
|
|
294
|
+
"err.signin.githubCopy": "コードをコピー",
|
|
295
|
+
"err.signin.githubWaiting": "GitHub での承認を待っています…",
|
|
296
|
+
"err.signin.githubDone": "サインインしました。読み込み中…",
|
|
297
|
+
"err.signin.githubExpired": "承認される前にコードの有効期限が切れました。",
|
|
298
|
+
"err.signin.githubDenied": "GitHub でリクエストがキャンセルされました。",
|
|
299
|
+
"err.signin.githubBusy":
|
|
300
|
+
"進行中のサインインが多すぎます。数分後にもう一度お試しください。",
|
|
301
|
+
"err.signin.githubFailed":
|
|
302
|
+
"GitHub に接続できませんでした。もう一度お試しください。",
|
|
303
|
+
"err.signin.githubAgain": "やり直す",
|
|
252
304
|
"err.422.title": "設定が無効です",
|
|
253
305
|
"err.422.sub": "ディストリビューションの設定が検証に失敗しました",
|
|
254
306
|
"err.422.lead":
|
|
@@ -278,11 +330,21 @@
|
|
|
278
330
|
"set.graph.density": "カード",
|
|
279
331
|
"set.graph.panelWidth": "詳細パネル",
|
|
280
332
|
"set.workspace.editor": "このワークスペースの IDE",
|
|
333
|
+
"set.agents.runtimes": "ランタイム",
|
|
281
334
|
"set.cli.local_dev": "ローカル環境",
|
|
282
335
|
"set.cli.cli_tabs": "ターミナルのタブ",
|
|
283
336
|
"set.cli.log_window_lines": "ログ欄の行数",
|
|
284
337
|
"set.cli.web_port": "あなたの web ポート",
|
|
285
338
|
"set.cli.signin": "ブラウザのサインイン",
|
|
339
|
+
"set.cli.sudo": "管理者パスワード",
|
|
340
|
+
"set.access.owner": "オーナー",
|
|
341
|
+
"set.access.devices": "リンク済みデバイス",
|
|
342
|
+
"set.access.waiting": "承認待ちのデバイス",
|
|
343
|
+
"set.access.machine_name": "マシン名",
|
|
344
|
+
"ident.local": "ローカル",
|
|
345
|
+
"ident.device": "サインイン済み · このデバイス",
|
|
346
|
+
"ident.toast": "このデバイスは {host} の {name} にサインインしました",
|
|
347
|
+
"set.access.pair": "デバイスをペアリング",
|
|
286
348
|
"set.distribution.brand": "製品名",
|
|
287
349
|
"set.distribution.github_org": "GitHub の組織",
|
|
288
350
|
"set.distribution.orgs": "組織のラベル",
|
|
@@ -368,5 +430,10 @@
|
|
|
368
430
|
"ag.rt.fix":
|
|
369
431
|
"インストールするか、{file} の {key} にパスを設定するか、{cmd} を実行してください。",
|
|
370
432
|
"ag.rt.unknown": "ランタイム {id} はここにありません。",
|
|
433
|
+
"ag.rt.denTools": "Den ツール: 近日対応",
|
|
434
|
+
"ag.rt.ownCli":
|
|
435
|
+
"ワークスペースで独自の CLI として動きます。Den のツールと権限モードは今後対応します。",
|
|
436
|
+
"ag.rt.notInstalled": "未インストール",
|
|
437
|
+
"ag.rt.needsArgv": "ペルソナに argv テンプレートがありません",
|
|
371
438
|
};
|
|
372
439
|
})((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 = () => {
|