@monster-orange/den 0.4.14 โ 0.4.16
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 +194 -0
- package/README.md +7 -7
- package/docs/distributions.md +226 -19
- package/package.json +1 -1
- package/src/shared/actor-token.ts +12 -0
- package/src/shared/agents/conversations.ts +155 -8
- package/src/shared/agents/den-claude.ts +25 -3
- package/src/shared/agents/records.ts +37 -0
- package/src/shared/agents/runtime.ts +11 -1
- package/src/shared/claim-code.ts +163 -0
- package/src/shared/cli-command.ts +31 -0
- package/src/shared/den-config.ts +12 -0
- package/src/shared/environment-manager/workspaces.ts +20 -0
- package/src/shared/github-app.ts +7 -0
- package/src/shared/web-session.ts +64 -5
- package/src/ui/cli/agent-ops.ts +372 -23
- package/src/ui/cli/agents-command.ts +71 -4
- package/src/ui/cli/doctor-command.ts +29 -3
- package/src/ui/cli/doctor-onboard.ts +26 -0
- package/src/ui/cli/flag-parser.ts +9 -1
- package/src/ui/cli/index.ts +29 -3
- package/src/ui/cli/onboard-command.ts +180 -0
- package/src/ui/cli/onboard-reads.ts +613 -0
- package/src/ui/cli/repo-command.ts +156 -10
- package/src/ui/cli/web-command.ts +92 -1
- package/src/ui/mcp/api.ts +14 -2
- package/src/ui/mcp/server.ts +12 -2
- package/src/ui/mcp/tools.ts +368 -1
- package/src/ui/server/agent-routes.ts +91 -7
- package/src/ui/server/approval-routes.ts +390 -0
- package/src/ui/server/approvals.ts +416 -0
- package/src/ui/server/github-routes.ts +13 -5
- package/src/ui/server/held-actions.ts +203 -0
- package/src/ui/server/http-helpers.ts +35 -0
- package/src/ui/server/index.ts +308 -21
- package/src/ui/server/lifecycle-exec.ts +70 -0
- package/src/ui/server/onboard-routes.ts +132 -0
- package/src/ui/server/pair-routes.ts +7 -4
- package/src/ui/server/public/agents-page.js +378 -30
- package/src/ui/server/public/agents.html +1 -0
- package/src/ui/server/public/error-page.js +97 -18
- package/src/ui/server/public/error.html +18 -0
- package/src/ui/server/public/header.js +1 -1
- package/src/ui/server/public/i18n/es.js +65 -5
- package/src/ui/server/public/i18n/ja.js +67 -5
- package/src/ui/server/public/index.html +1 -1
- package/src/ui/server/public/local-dev.html +5 -4
- package/src/ui/server/public/persona-ui.css +32 -0
- package/src/ui/server/public/release.html +0 -1
- package/src/ui/server/public/settings-registry.js +3 -1
- package/src/ui/server/public/settings.html +9 -1
- package/src/ui/server/public/shell.js +348 -5
- package/src/ui/server/request-guard.ts +2 -0
- package/src/ui/server/route-classes.ts +34 -1
- package/src/ui/server/session-routes.ts +14 -3
- package/src/ui/server/workspace-routes.ts +21 -10
- package/themes/den/den-theme.json +6 -6
|
@@ -139,7 +139,7 @@ function withCmd(text, cmd) {
|
|
|
139
139
|
function withHost(t, key, vars) {
|
|
140
140
|
const marks = {};
|
|
141
141
|
const v = { ...vars };
|
|
142
|
-
for (const k of ["host", "target"])
|
|
142
|
+
for (const k of ["host", "target", "user"])
|
|
143
143
|
if (k in v) {
|
|
144
144
|
marks[k] = v[k];
|
|
145
145
|
v[k] = `\u0001${k}\u0001`;
|
|
@@ -203,6 +203,20 @@ export function countdownText(ms) {
|
|
|
203
203
|
* Where a signed-in page goes: the page that was asked for. On /signin,
|
|
204
204
|
* its same-origin `next` (else `/`); anywhere else, the same URL.
|
|
205
205
|
*/
|
|
206
|
+
/**
|
|
207
|
+
* 0.4.15: keep a sign-in's approval key (web-session.ts) in this origin's
|
|
208
|
+
* localStorage, where shell.js sends it from. It comes in the sign-in's
|
|
209
|
+
* own answer only.
|
|
210
|
+
*/
|
|
211
|
+
function keepApproveKey(b) {
|
|
212
|
+
if (!b || typeof b.approveKey !== "string") return;
|
|
213
|
+
try {
|
|
214
|
+
localStorage.setItem("den.approveKey", b.approveKey);
|
|
215
|
+
} catch {
|
|
216
|
+
/* storage blocked: this browser signs in again to approve */
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
206
220
|
export function landingAfterSignIn(loc) {
|
|
207
221
|
if (loc.pathname !== "/signin") return loc.pathname + loc.search + loc.hash;
|
|
208
222
|
const n = new URLSearchParams(loc.search).get("next") || "/";
|
|
@@ -212,30 +226,84 @@ export function landingAfterSignIn(loc) {
|
|
|
212
226
|
}
|
|
213
227
|
|
|
214
228
|
/**
|
|
215
|
-
* Sign in with GitHub (SEC-2a):
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
229
|
+
* Sign in with GitHub (SEC-2a): shown only when a client id is configured.
|
|
230
|
+
* The server runs GitHub's device flow; the page shows the code and
|
|
231
|
+
* github.com/login/device, polls the server, and goes on once the owner
|
|
232
|
+
* approved it (the server sets the cookie). Another account is refused by
|
|
233
|
+
* name.
|
|
234
|
+
*
|
|
235
|
+
* SEC-2a-UX: the same three steps in every state (link the owner on the
|
|
236
|
+
* machine, enter the code on GitHub, come back and press the button).
|
|
237
|
+
* Once an owner is linked, step 1 is done and names it, and the button
|
|
238
|
+
* follows the steps. Below them: only the owner's account signs in this
|
|
239
|
+
* way, and Learn more.
|
|
220
240
|
*/
|
|
221
241
|
function githubBlock(s, t) {
|
|
222
242
|
const g = s.github;
|
|
223
243
|
if (!g || s.localhost || g.state === "no_client_id") return "";
|
|
224
244
|
const host = s.machine || "";
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
);
|
|
245
|
+
const ready = g.state === "ready";
|
|
246
|
+
const step1 = withHost(t, "err.signin.ghStep1", {
|
|
247
|
+
host,
|
|
248
|
+
cmd: "\u0000",
|
|
249
|
+
}).replace("\u0000", `<code class="mono">${esc(g.owner)}</code>`);
|
|
231
250
|
return (
|
|
232
|
-
`<div id="den-gh"
|
|
233
|
-
`<
|
|
234
|
-
|
|
235
|
-
|
|
251
|
+
`<div id="den-gh">` +
|
|
252
|
+
`<ol class="den-steps" id="den-gh-steps">` +
|
|
253
|
+
`<li id="den-gh-step1"${ready ? ' class="done"' : ""}><p>${step1}</p>` +
|
|
254
|
+
(ready && g.ownerLogin
|
|
255
|
+
? `<p class="den-gh-owner" id="den-gh-owner">${esc(t("err.signin.ghOwner", { login: g.ownerLogin }))}</p>`
|
|
256
|
+
: "") +
|
|
257
|
+
`</li>` +
|
|
258
|
+
`<li id="den-gh-step2"><p>${esc(t("err.signin.ghStep2"))}</p></li>` +
|
|
259
|
+
`<li id="den-gh-step3"><p>${esc(t("err.signin.ghStep3"))}</p></li>` +
|
|
260
|
+
`</ol>` +
|
|
261
|
+
(ready
|
|
262
|
+
? `<div class="acts" style="margin-top:0">` +
|
|
263
|
+
`<button type="button" class="btn primary" id="den-gh-start">${esc(t("err.signin.github"))}</button>` +
|
|
264
|
+
`</div><div id="den-gh-flow" aria-live="polite"></div>`
|
|
265
|
+
: "") +
|
|
266
|
+
`<p class="den-gh-note" id="den-gh-only">${esc(t("err.signin.ghOnly"))}` +
|
|
267
|
+
(g.learnMore
|
|
268
|
+
? ` <a id="den-gh-learn" href="${esc(g.learnMore)}" target="_blank" rel="noopener noreferrer">${esc(t("err.signin.ghLearn"))}</a>`
|
|
269
|
+
: "") +
|
|
270
|
+
`</p></div>`
|
|
236
271
|
);
|
|
237
272
|
}
|
|
238
273
|
|
|
274
|
+
/** How often, and how long, the page watches for an owner (SEC-2a-UX). */
|
|
275
|
+
export const OWNER_POLL_MS = 5000;
|
|
276
|
+
const OWNER_WATCH_MS = 30 * 60 * 1000;
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* SEC-2a-UX: with no owner linked yet, watch the session probe; once the
|
|
280
|
+
* owner is linked on the machine, step 1 shows done and Sign in with
|
|
281
|
+
* GitHub appears, with no reload.
|
|
282
|
+
*/
|
|
283
|
+
function watchOwner(root, t, s, pollMs = OWNER_POLL_MS) {
|
|
284
|
+
if (s.github?.state !== "no_owner" || !root.querySelector("#den-gh")) return;
|
|
285
|
+
const until = Date.now() + OWNER_WATCH_MS;
|
|
286
|
+
const tick = () => {
|
|
287
|
+
if (Date.now() > until || !root.querySelector("#den-gh")) return;
|
|
288
|
+
fetch("/api/session", { cache: "no-store", credentials: "same-origin" })
|
|
289
|
+
.then((r) => r.json().catch(() => ({})))
|
|
290
|
+
.then((b) => {
|
|
291
|
+
const g = b?.github;
|
|
292
|
+
if (g?.state === "ready" && g.ownerLogin) {
|
|
293
|
+
s.github = { ...s.github, state: "ready", ownerLogin: g.ownerLogin };
|
|
294
|
+
const old = root.querySelector("#den-gh");
|
|
295
|
+
if (!old) return;
|
|
296
|
+
old.outerHTML = githubBlock(s, t);
|
|
297
|
+
wireGithub(root, t, s);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
setTimeout(tick, pollMs);
|
|
301
|
+
})
|
|
302
|
+
.catch(() => setTimeout(tick, pollMs));
|
|
303
|
+
};
|
|
304
|
+
setTimeout(tick, pollMs);
|
|
305
|
+
}
|
|
306
|
+
|
|
239
307
|
/** The device flow on the page: start, show the code, poll, go on. */
|
|
240
308
|
function wireGithub(root, t, s) {
|
|
241
309
|
const start = root.querySelector("#den-gh-start");
|
|
@@ -263,6 +331,7 @@ function wireGithub(root, t, s) {
|
|
|
263
331
|
return;
|
|
264
332
|
}
|
|
265
333
|
if (b.state === "ok") {
|
|
334
|
+
keepApproveKey(b);
|
|
266
335
|
show(
|
|
267
336
|
`<p class="lead" style="margin-top:12px">${esc(t("err.signin.githubDone"))}</p>`,
|
|
268
337
|
);
|
|
@@ -351,6 +420,9 @@ function wirePair(root, t, s) {
|
|
|
351
420
|
if (!box) return;
|
|
352
421
|
const host = s.machine || "";
|
|
353
422
|
const target = s.ssh?.target || "";
|
|
423
|
+
// SEC-2a-UX: the account to log in as, so the SSH app doesn't guess one.
|
|
424
|
+
const user = s.ssh?.user || "";
|
|
425
|
+
const login = user ? `${user}@${target}` : target;
|
|
354
426
|
let poll = null;
|
|
355
427
|
let tick = null;
|
|
356
428
|
let gen = 0;
|
|
@@ -376,7 +448,7 @@ function wirePair(root, t, s) {
|
|
|
376
448
|
const show = (b) => {
|
|
377
449
|
const term =
|
|
378
450
|
s.ssh?.name && target
|
|
379
|
-
? `<a class="btn" id="den-pair-term" href="ssh://${esc(
|
|
451
|
+
? `<a class="btn" id="den-pair-term" href="ssh://${esc(login)}">${esc(t("err.signin.openTerminal"))}</a>`
|
|
380
452
|
: "";
|
|
381
453
|
box.innerHTML =
|
|
382
454
|
`<ol class="den-steps">` +
|
|
@@ -389,7 +461,11 @@ function wirePair(root, t, s) {
|
|
|
389
461
|
`<p>${withHost(t, "err.signin.noTerminal", { host })}</p>` +
|
|
390
462
|
cmdLine("den-pair-ssh", b.ssh, t, term) +
|
|
391
463
|
(term
|
|
392
|
-
? `<p class="den-pair-note"
|
|
464
|
+
? `<p class="den-pair-note" id="den-pair-note">${
|
|
465
|
+
user
|
|
466
|
+
? withHost(t, "err.signin.sshUserNote", { host, user })
|
|
467
|
+
: withHost(t, "err.signin.sshNote", { target })
|
|
468
|
+
}</p>`
|
|
393
469
|
: "");
|
|
394
470
|
wireCopy(box, t);
|
|
395
471
|
};
|
|
@@ -432,6 +508,7 @@ function wirePair(root, t, s) {
|
|
|
432
508
|
return;
|
|
433
509
|
}
|
|
434
510
|
if (p.state === "ok") {
|
|
511
|
+
keepApproveKey(p);
|
|
435
512
|
stop();
|
|
436
513
|
box.innerHTML = `<p class="lead" id="den-pair-in">${esc(t("err.signin.youreIn"))}</p>`;
|
|
437
514
|
location.replace(landingAfterSignIn(location));
|
|
@@ -524,6 +601,7 @@ function mountSignedOut(root, sh, d) {
|
|
|
524
601
|
.then((b) => {
|
|
525
602
|
go.disabled = false;
|
|
526
603
|
if (b.ok) {
|
|
604
|
+
keepApproveKey(b);
|
|
527
605
|
err.textContent = "";
|
|
528
606
|
form.innerHTML = `<p class="lead" id="den-confirm-in">${esc(t("err.signin.youreIn"))}</p>`;
|
|
529
607
|
location.replace(typeof b.next === "string" ? b.next : "/");
|
|
@@ -580,6 +658,7 @@ function mountSignedOut(root, sh, d) {
|
|
|
580
658
|
`</div>`;
|
|
581
659
|
wireCopy(root, t);
|
|
582
660
|
wireGithub(root, t, s);
|
|
661
|
+
watchOwner(root, t, s, window.__denOwnerPollMs || OWNER_POLL_MS);
|
|
583
662
|
wirePair(root, t, s);
|
|
584
663
|
if (s.expired) return;
|
|
585
664
|
let tried = false;
|
|
@@ -265,6 +265,24 @@
|
|
|
265
265
|
color: var(--text);
|
|
266
266
|
font-weight: 600;
|
|
267
267
|
}
|
|
268
|
+
/* SEC-2a-UX: a step already done (the owner is linked). */
|
|
269
|
+
ol.den-steps li.done::marker {
|
|
270
|
+
content: "\2713 ";
|
|
271
|
+
color: var(--ok, var(--text));
|
|
272
|
+
}
|
|
273
|
+
ol.den-steps li.done > p:first-child {
|
|
274
|
+
color: var(--muted);
|
|
275
|
+
}
|
|
276
|
+
ol.den-steps code {
|
|
277
|
+
overflow-wrap: anywhere;
|
|
278
|
+
}
|
|
279
|
+
p.den-gh-note {
|
|
280
|
+
margin-top: 8px;
|
|
281
|
+
}
|
|
282
|
+
p.den-gh-owner {
|
|
283
|
+
color: var(--text);
|
|
284
|
+
font-weight: 600;
|
|
285
|
+
}
|
|
268
286
|
details.den-other {
|
|
269
287
|
margin: 0 0 16px;
|
|
270
288
|
}
|
|
@@ -251,7 +251,7 @@ function _injectChangelogStyles() {
|
|
|
251
251
|
padding: 5px 16px; border-radius: 5px; font-size: 12px;
|
|
252
252
|
font-weight: 600; cursor: pointer;
|
|
253
253
|
}
|
|
254
|
-
.cl-got-it:hover {
|
|
254
|
+
.cl-got-it:hover { filter: brightness(0.92); }
|
|
255
255
|
`;
|
|
256
256
|
document.head.appendChild(style);
|
|
257
257
|
|
|
@@ -254,12 +254,18 @@
|
|
|
254
254
|
"err.signin.title": "Inicia sesiรณn en {name}",
|
|
255
255
|
"err.signin.where":
|
|
256
256
|
"Estรกs abriendo {name} desde otro ordenador. {name} corre en {host}, asรญ que necesita saber que eres tรบ.",
|
|
257
|
-
"err.signin.
|
|
258
|
-
"
|
|
259
|
-
"err.signin.
|
|
260
|
-
"
|
|
257
|
+
"err.signin.ghStep1":
|
|
258
|
+
"En {host}, ejecuta {cmd}, o usa Ajustes โบ Acceso allรญ.",
|
|
259
|
+
"err.signin.ghStep2":
|
|
260
|
+
"Muestra un cรณdigo. Introdรบcelo en github.com/login/device y apruรฉbalo.",
|
|
261
|
+
"err.signin.ghStep3":
|
|
262
|
+
"Despuรฉs vuelve aquรญ y pulsa Iniciar sesiรณn con GitHub, con la misma cuenta de GitHub.",
|
|
263
|
+
"err.signin.ghOwner": "Propietario: @{login}",
|
|
264
|
+
"err.signin.ghOnly":
|
|
265
|
+
"Solo la cuenta de GitHub del propietario puede iniciar sesiรณn asรญ. Para cualquier otra persona, usa ยซAprueba este ordenadorยป.",
|
|
266
|
+
"err.signin.ghLearn": "Mรกs informaciรณn",
|
|
261
267
|
"err.signin.githubRefused":
|
|
262
|
-
"@{login} no es el propietario de este {name}.
|
|
268
|
+
"@{login} no es el propietario de este {name}. Solo la cuenta del propietario puede usar Iniciar sesiรณn con GitHub. Usa ยซAprueba este ordenadorยป en su lugar.",
|
|
263
269
|
"err.signin.approveOr": "O aprueba este ordenador",
|
|
264
270
|
"err.signin.approve": "Aprueba este ordenador",
|
|
265
271
|
"err.signin.step1": "En {host} (no en este ordenador), ejecuta:",
|
|
@@ -271,6 +277,8 @@
|
|
|
271
277
|
"err.signin.noTerminal":
|
|
272
278
|
"ยฟNo tienes una terminal en {host}? Desde este ordenador, ejecuta:",
|
|
273
279
|
"err.signin.openTerminal": "Abrir Terminal",
|
|
280
|
+
"err.signin.sshUserNote":
|
|
281
|
+
"Inicia sesiรณn con tu cuenta de {host} ({user}) y su contraseรฑa, o con una clave SSH.",
|
|
274
282
|
"err.signin.sshNote":
|
|
275
283
|
"Abrir Terminal abre ssh://{target} en tu aplicaciรณn de terminal. Necesita acceso SSH a {target}.",
|
|
276
284
|
"err.signin.whyTitle": "ยฟPor quรฉ?",
|
|
@@ -459,6 +467,11 @@
|
|
|
459
467
|
"ag.new.name": "Nombre (opcional)",
|
|
460
468
|
"ag.new.as": "Se inicia como {id}",
|
|
461
469
|
"ag.new.openRunning": "Abrir el que estรก en ejecuciรณn",
|
|
470
|
+
"ag.new.isRunning": "{id} ya estรก en ejecuciรณn",
|
|
471
|
+
"ag.new.openIt": "Abrirlo",
|
|
472
|
+
"ag.new.isStopped": "{id} estรก detenido",
|
|
473
|
+
"ag.new.resumeIt": "Reanudarlo",
|
|
474
|
+
"ag.new.orNext": "o Iniciar crea {id}",
|
|
462
475
|
"ag.new.taskPh":
|
|
463
476
|
"p. ej., Toma la historia del estado vacรญo. Sigue el diseรฑo y aรฑade una prueba.",
|
|
464
477
|
"ag.new.adv": "Avanzado: modelo y permisos",
|
|
@@ -482,12 +495,58 @@
|
|
|
482
495
|
"ag.bring.agent": "Agente {id}",
|
|
483
496
|
"ag.bring.note":
|
|
484
497
|
"La continรบa en la carpeta donde se ejecutรณ, con las herramientas y protecciones de Den desde ahora. Sigue en ejecuciรณn si cierras el panel. Ciรฉrrala antes en cualquier otro terminal: Den solo la ve abierta si se escribiรณ en el รบltimo minuto.",
|
|
498
|
+
"ag.keep.model": "Mantiene {m} de la conversaciรณn.",
|
|
499
|
+
"ag.keep.modelNew": "Usa {m} a partir de ahora.",
|
|
500
|
+
"ag.keep.from":
|
|
501
|
+
"A partir de ahora trabaja como {p}: su rol, sus permisos ({mode}), las herramientas y protecciones de Den. Su historial se mantiene.",
|
|
502
|
+
"ag.keep.lost":
|
|
503
|
+
"No tendrรก: {s}. Den ejecuta los agentes solo con las herramientas de Den.",
|
|
504
|
+
"ag.keep.opt": "Mantener {m}",
|
|
505
|
+
"ag.keep.optNone": "Mantener el modelo que usa",
|
|
506
|
+
"ag.keep.advNote":
|
|
507
|
+
"El modelo que usa se mantiene salvo que elijas otro aquรญ. Los permisos vienen de la persona.",
|
|
508
|
+
"ag.pc.item": "Cambiar personaโฆ",
|
|
509
|
+
"ag.pc.title": "Cambiar la persona de {id}",
|
|
510
|
+
"ag.pc.note":
|
|
511
|
+
"Den lo detiene y reanuda la misma conversaciรณn con la nueva persona. Su id, nombre, carpeta y pestaรฑa se mantienen.",
|
|
512
|
+
"ag.pc.go": "Cambiar persona",
|
|
513
|
+
"ag.pc.going": "Cambiandoโฆ",
|
|
514
|
+
"ag.pc.current": "actual",
|
|
515
|
+
"ag.pc.busy":
|
|
516
|
+
"Estรก trabajando. ยฟCambiar despuรฉs de este turno o detenerlo ahora?",
|
|
517
|
+
"ag.pc.after": "Despuรฉs de este turno",
|
|
518
|
+
"ag.pc.now": "Detenerlo ahora",
|
|
519
|
+
"ag.pc.done": "{id} ahora es {p}",
|
|
520
|
+
"ag.pc.pending": "{id} pasarรก a ser {p} cuando termine este turno",
|
|
521
|
+
"ag.more": "Mรกs para {id}",
|
|
485
522
|
"ag.bring.go": "Traer",
|
|
486
523
|
"ag.bring.going": "Trayendoโฆ",
|
|
487
524
|
"ag.bring.done": "Traรญda como {id}",
|
|
488
525
|
"ag.bring.now": "ahora mismo",
|
|
489
526
|
"ag.bring.min": "hace {n} min",
|
|
490
527
|
"ag.bring.h": "hace {n} h",
|
|
528
|
+
"ap.title": "{agent} quiere:",
|
|
529
|
+
"ap.agent": "El agente {name}",
|
|
530
|
+
"ap.noAgent": "Algo en esta mรกquina (sin identidad de agente)",
|
|
531
|
+
"ap.noAgentWarn": "Si no le pediste esto a un agente, deniรฉgalo.",
|
|
532
|
+
"ap.signin.title": "Algo espera tu aprobaciรณn.",
|
|
533
|
+
"ap.signin": "Inicia sesiรณn para verlo: ejecuta {cmd} y abre el enlace.",
|
|
534
|
+
"ap.do.workspace_create": 'Crear el espacio "{name}"',
|
|
535
|
+
"ap.do.repo_add":
|
|
536
|
+
'Aรฑadir el repositorio de {path} al espacio "{workspace}"',
|
|
537
|
+
"ap.do.repo_add.new":
|
|
538
|
+
'Aรฑadir el repositorio de {path} a un espacio nuevo "{workspace}"',
|
|
539
|
+
"ap.do.service_try": "Iniciar {service}",
|
|
540
|
+
"ap.says": "El agente dice:",
|
|
541
|
+
"ap.review": "Revisar",
|
|
542
|
+
"ap.hide": "Ocultar detalles",
|
|
543
|
+
"ap.later": "Mรกs tarde",
|
|
544
|
+
"ap.deny": "Denegar",
|
|
545
|
+
"ap.allow": "Permitir",
|
|
546
|
+
"ap.waits": "Nada cambia hasta que lo permitas. Espera hasta las {time}.",
|
|
547
|
+
"ap.more": "{n} mรกs en espera",
|
|
548
|
+
"ap.failed": "Se ejecutรณ y fallรณ: {error}",
|
|
549
|
+
"ap.done": "Hecho: {what}",
|
|
491
550
|
"ag.new.note":
|
|
492
551
|
"Se inicia en la carpeta del espacio de trabajo. Sigue en ejecuciรณn si cierras el panel.",
|
|
493
552
|
"ag.new.started": "{p} iniciado en {w}",
|
|
@@ -608,6 +667,7 @@
|
|
|
608
667
|
"Su token fue revocado (web logout --all): detenlo y reanรบdalo, o inรญcialo de nuevo, para darle uno nuevo",
|
|
609
668
|
"ag.ended":
|
|
610
669
|
"Esta sesiรณn ha terminado. Su registro se queda hasta que se reanude o se elimine.",
|
|
670
|
+
"ag.switched": "Cambiado a {p}",
|
|
611
671
|
"ag.exitedLine": "[la sesiรณn terminรณ{code}]",
|
|
612
672
|
"ag.lost": "[desconectado: {why}]",
|
|
613
673
|
"ag.reconnect": "Reconectar",
|
|
@@ -242,12 +242,18 @@
|
|
|
242
242
|
"err.signin.title": "{name} ใซใตใคใณใคใณ",
|
|
243
243
|
"err.signin.where":
|
|
244
244
|
"ๅฅใฎใณใณใใฅใผใฟใผใใ {name} ใ้ใใฆใใพใใ{name} ใฏ {host} ใงๅใใฆใใใใใใใชใๆฌไบบใงใใใใจใ็ขบ่ชใใๅฟ
่ฆใใใใพใใ",
|
|
245
|
-
"err.signin.
|
|
246
|
-
"
|
|
247
|
-
"err.signin.
|
|
248
|
-
"
|
|
245
|
+
"err.signin.ghStep1":
|
|
246
|
+
"{host} ใง {cmd} ใๅฎ่กใใใใใใกใใง ่จญๅฎ โบ ใขใฏใปใน ใไฝฟใใพใใ",
|
|
247
|
+
"err.signin.ghStep2":
|
|
248
|
+
"ใณใผใใ่กจ็คบใใใพใใgithub.com/login/device ใงๅ
ฅๅใใฆๆฟ่ชใใพใใ",
|
|
249
|
+
"err.signin.ghStep3":
|
|
250
|
+
"ใใใซๆปใใๅใ GitHub ใขใซใฆใณใใงใGitHub ใงใตใคใณใคใณใใๆผใใพใใ",
|
|
251
|
+
"err.signin.ghOwner": "ใชใผใใผ: @{login}",
|
|
252
|
+
"err.signin.ghOnly":
|
|
253
|
+
"ใใฎๆนๆณใงใตใคใณใคใณใงใใใฎใฏใชใผใใผใฎ GitHub ใขใซใฆใณใใ ใใงใใใใไปฅๅคใฎไบบใฏใใใฎใณใณใใฅใผใฟใผใๆฟ่ชใใไฝฟใฃใฆใใ ใใใ",
|
|
254
|
+
"err.signin.ghLearn": "่ฉณใใ่ฆใ",
|
|
249
255
|
"err.signin.githubRefused":
|
|
250
|
-
"@{login} ใฏใใฎ {name}
|
|
256
|
+
"@{login} ใฏใใฎ {name} ใฎใชใผใใผใงใฏใใใพใใใGitHub ใงใตใคใณใคใณใไฝฟใใใฎใฏใชใผใใผใฎใขใซใฆใณใใ ใใงใใไปฃใใใซใใใฎใณใณใใฅใผใฟใผใๆฟ่ชใใไฝฟใฃใฆใใ ใใใ",
|
|
251
257
|
"err.signin.approveOr": "ใพใใฏใใใฎใณใณใใฅใผใฟใผใๆฟ่ช",
|
|
252
258
|
"err.signin.approve": "ใใฎใณใณใใฅใผใฟใผใๆฟ่ช",
|
|
253
259
|
"err.signin.step1":
|
|
@@ -260,6 +266,8 @@
|
|
|
260
266
|
"err.signin.noTerminal":
|
|
261
267
|
"{host} ใฎใฟใผใใใซใใใใพใใใ?ใใฎใณใณใใฅใผใฟใผใงๆฌกใๅฎ่กใใพใ:",
|
|
262
268
|
"err.signin.openTerminal": "ใฟใผใใใซใ้ใ",
|
|
269
|
+
"err.signin.sshUserNote":
|
|
270
|
+
"{host} ใฎใขใซใฆใณใ({user})ใจใใฎใในใฏใผใใใพใใฏ SSH ใญใผใงใญใฐใคใณใใพใใ",
|
|
263
271
|
"err.signin.sshNote":
|
|
264
272
|
"ใใฟใผใใใซใ้ใใใฏใฟใผใใใซใขใใชใง ssh://{target} ใ้ใใพใใ{target} ใธใฎ SSH ใขใฏใปในใๅฟ
่ฆใงใใ",
|
|
265
273
|
"err.signin.whyTitle": "ใชใ?",
|
|
@@ -442,6 +450,11 @@
|
|
|
442
450
|
"ag.new.name": "ๅๅ๏ผไปปๆ๏ผ",
|
|
443
451
|
"ag.new.as": "{id} ใจใใฆ้ๅงใใพใ",
|
|
444
452
|
"ag.new.openRunning": "ๅฎ่กไธญใฎใใฎใ้ใ",
|
|
453
|
+
"ag.new.isRunning": "{id} ใฏใใงใซๅฎ่กไธญใงใ",
|
|
454
|
+
"ag.new.openIt": "้ใ",
|
|
455
|
+
"ag.new.isStopped": "{id} ใฏๅๆญขใใฆใใพใ",
|
|
456
|
+
"ag.new.resumeIt": "ๅ้ใใ",
|
|
457
|
+
"ag.new.orNext": "ใพใใฏ้ๅงใง {id} ใไฝๆใใพใ",
|
|
445
458
|
"ag.new.taskPh":
|
|
446
459
|
"ไพ: ็ฉบใฎ็ถๆ
ใฎในใใผใชใผใๆ
ๅฝใใใถใคใณใซๅใใใใในใใ่ฟฝๅ ใใใ",
|
|
447
460
|
"ag.new.adv": "่ฉณ็ดฐ่จญๅฎ: ใขใใซใจๆจฉ้",
|
|
@@ -466,12 +479,60 @@
|
|
|
466
479
|
"ag.bring.agent": "ใจใผใธใงใณใ {id}",
|
|
467
480
|
"ag.bring.note":
|
|
468
481
|
"ๅฎ่กใใฆใใใใฉใซใใผใง็ถใใพใใใใใใใฏ Den ใฎใใผใซใจใฌใผใใ้ฉ็จใใใพใใใใคใณใ้ใใฆใๅฎ่กใฏ็ถใใพใใๅ
ใซใปใใฎใฟใผใใใซใง้ใใฆใใ ใใใDen ใ้ใใฆใใใจๅคๆญใงใใใฎใฏใ็ด่ฟ 1 ๅไปฅๅ
ใซๆธใ่พผใพใใไผ่ฉฑใ ใใงใใ",
|
|
482
|
+
"ag.keep.model": "ไผ่ฉฑใฎ {m} ใใใฎใพใพไฝฟใใพใใ",
|
|
483
|
+
"ag.keep.modelNew": "ใใใใใฏ {m} ใงๅใใพใใ",
|
|
484
|
+
"ag.keep.from":
|
|
485
|
+
"ใใใใใฏ {p} ใจใใฆๅใใพใ: ใใฎๅฝนๅฒใๆจฉ้({mode})ใDen ใฎใใผใซใจใฌใผใใๅฑฅๆญดใฏใใฎใพใพๆฎใใพใใ",
|
|
486
|
+
"ag.keep.lost":
|
|
487
|
+
"ไฝฟใใชใใชใใใฎ: {s}ใDen ใฏใจใผใธใงใณใใ Den ใฎใใผใซใ ใใงๅใใใพใใ",
|
|
488
|
+
"ag.keep.opt": "{m} ใฎใพใพ",
|
|
489
|
+
"ag.keep.optNone": "ไปใฎใขใใซใฎใพใพ",
|
|
490
|
+
"ag.keep.advNote":
|
|
491
|
+
"ใใใงๅฅใฎใขใใซใ้ธใฐใชใ้ใใไปใฎใขใใซใฎใพใพใงใใๆจฉ้ใฏใใซใฝใใใๆฅใพใใ",
|
|
492
|
+
"ag.pc.item": "ใใซใฝใใๅคๆดโฆ",
|
|
493
|
+
"ag.pc.title": "{id} ใฎใใซใฝใใๅคๆด",
|
|
494
|
+
"ag.pc.note":
|
|
495
|
+
"Den ใฏใใฃใใๅๆญขใใๅใไผ่ฉฑใๆฐใใใใซใฝใใงๅ้ใใพใใIDใๅๅใใใฉใซใใผใใฟใใฏใใฎใพใพใงใใ",
|
|
496
|
+
"ag.pc.go": "ใใซใฝใใๅคๆด",
|
|
497
|
+
"ag.pc.going": "ๅคๆดไธญโฆ",
|
|
498
|
+
"ag.pc.current": "็พๅจ",
|
|
499
|
+
"ag.pc.busy":
|
|
500
|
+
"ไฝๆฅญไธญใงใใใใฎใฟใผใณใฎๅพใซๅคๆดใใพใใใใใใจใไปใใๅๆญขใใพใใ?",
|
|
501
|
+
"ag.pc.after": "ใใฎใฟใผใณใฎๅพ",
|
|
502
|
+
"ag.pc.now": "ไปใใๅๆญข",
|
|
503
|
+
"ag.pc.done": "{id} ใฏ {p} ใซใชใใพใใ",
|
|
504
|
+
"ag.pc.pending": "ใใฎใฟใผใณใ็ตใใใจ {id} ใฏ {p} ใซใชใใพใ",
|
|
505
|
+
"ag.more": "{id} ใฎใใฎไปใฎๆไฝ",
|
|
469
506
|
"ag.bring.go": "ๅใ่พผใ",
|
|
470
507
|
"ag.bring.going": "ๅใ่พผใฟไธญโฆ",
|
|
471
508
|
"ag.bring.done": "{id} ใจใใฆๅใ่พผใฟใพใใ",
|
|
472
509
|
"ag.bring.now": "ใใฃใไป",
|
|
473
510
|
"ag.bring.min": "{n} ๅๅ",
|
|
474
511
|
"ag.bring.h": "{n} ๆ้ๅ",
|
|
512
|
+
"ap.title": "{agent}ใๆฌกใฎใใจใๆฑใใฆใใพใ:",
|
|
513
|
+
"ap.agent": "ใจใผใธใงใณใ {name} ",
|
|
514
|
+
"ap.noAgent": "ใใฎใใทใณไธใฎไฝใ๏ผใจใผใธใงใณใใฎ่ญๅฅใชใ๏ผ",
|
|
515
|
+
"ap.noAgentWarn":
|
|
516
|
+
"ใจใผใธใงใณใใซใใใ้ ผใใงใใชใใใฐใๆๅฆใใฆใใ ใใใ",
|
|
517
|
+
"ap.signin.title": "ๆฟ่ชใๅพ
ใฃใฆใใใใฎใใใใพใใ",
|
|
518
|
+
"ap.signin":
|
|
519
|
+
"ใตใคใณใคใณใใใจ่กจ็คบใใใพใ: {cmd} ใๅฎ่กใใฆใชใณใฏใ้ใใฆใใ ใใใ",
|
|
520
|
+
"ap.do.workspace_create": "ใฏใผใฏในใใผในใ{name}ใใไฝๆ",
|
|
521
|
+
"ap.do.repo_add":
|
|
522
|
+
"{path} ใฎใชใใธใใชใใฏใผใฏในใใผในใ{workspace}ใใซ่ฟฝๅ ",
|
|
523
|
+
"ap.do.repo_add.new":
|
|
524
|
+
"{path} ใฎใชใใธใใชใๆฐใใใฏใผใฏในใใผในใ{workspace}ใใซ่ฟฝๅ ",
|
|
525
|
+
"ap.do.service_try": "{service} ใ่ตทๅ",
|
|
526
|
+
"ap.says": "ใจใผใธใงใณใใฎใณใกใณใ:",
|
|
527
|
+
"ap.review": "็ขบ่ช",
|
|
528
|
+
"ap.hide": "่ฉณ็ดฐใ้ ใ",
|
|
529
|
+
"ap.later": "ใใจใง",
|
|
530
|
+
"ap.deny": "ๆๅฆ",
|
|
531
|
+
"ap.allow": "่จฑๅฏ",
|
|
532
|
+
"ap.waits": "่จฑๅฏใใใพใงไฝใๅคใใใพใใใ{time} ใพใงๅพ
ใกใพใใ",
|
|
533
|
+
"ap.more": "ใปใใซ {n} ไปถใๅพ
ๆฉไธญ",
|
|
534
|
+
"ap.failed": "ๅฎ่กใใพใใใๅคฑๆใใพใใ: {error}",
|
|
535
|
+
"ap.done": "ๅฎไบ: {what}",
|
|
475
536
|
"ag.new.note":
|
|
476
537
|
"ใฏใผใฏในใใผในใฎใใฉใซใใผใง้ๅงใใพใใใใคใณใ้ใใฆใๅฎ่กใฏ็ถใใพใใ",
|
|
477
538
|
"ag.new.started": "{w} ใง {p} ใ้ๅงใใพใใ",
|
|
@@ -590,6 +651,7 @@
|
|
|
590
651
|
"ag.revokedTip":
|
|
591
652
|
"ใใผใฏใณใๅคฑๅนใใพใใ๏ผweb logout --all๏ผใๆฐใใใใผใฏใณใๆธกใใซใฏๅๆญขใใฆๅ้ใใใใใใไธๅบฆ้ๅงใใฆใใ ใใ",
|
|
592
653
|
"ag.ended": "ใใฎใปใใทใงใณใฏ็ตไบใใพใใใ่จ้ฒใฏๅ้ใๅ้คใพใงๆฎใใพใใ",
|
|
654
|
+
"ag.switched": "{p} ใซๅใๆฟใใพใใ",
|
|
593
655
|
"ag.exitedLine": "[ใปใใทใงใณใ็ตไบใใพใใ{code}]",
|
|
594
656
|
"ag.lost": "[ๅๆญ: {why}]",
|
|
595
657
|
"ag.reconnect": "ๅๆฅ็ถ",
|
|
@@ -344,7 +344,7 @@
|
|
|
344
344
|
cursor: pointer;
|
|
345
345
|
}
|
|
346
346
|
.new-ws-form button:hover {
|
|
347
|
-
|
|
347
|
+
filter: brightness(0.92);
|
|
348
348
|
}
|
|
349
349
|
/* โโ Content โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */
|
|
350
350
|
.content {
|
|
@@ -552,7 +552,7 @@
|
|
|
552
552
|
cursor: pointer;
|
|
553
553
|
}
|
|
554
554
|
.add-btn:hover {
|
|
555
|
-
|
|
555
|
+
filter: brightness(0.92);
|
|
556
556
|
}
|
|
557
557
|
.form-msg {
|
|
558
558
|
font-size: 11px;
|
|
@@ -688,8 +688,9 @@
|
|
|
688
688
|
.add-svc-row.selected {
|
|
689
689
|
background: color-mix(in srgb, var(--accent) 9%, transparent);
|
|
690
690
|
}
|
|
691
|
+
/* Already in the workspace: readable (WCAG AA), not dimmed. */
|
|
691
692
|
.add-svc-row.already {
|
|
692
|
-
|
|
693
|
+
color: var(--muted);
|
|
693
694
|
}
|
|
694
695
|
.add-svc-row-info {
|
|
695
696
|
flex: 1;
|
|
@@ -839,7 +840,7 @@
|
|
|
839
840
|
cursor: pointer;
|
|
840
841
|
}
|
|
841
842
|
.add-svc-submit:hover {
|
|
842
|
-
|
|
843
|
+
filter: brightness(0.92);
|
|
843
844
|
}
|
|
844
845
|
.add-svc-submit:disabled {
|
|
845
846
|
opacity: 0.45;
|
|
@@ -181,6 +181,17 @@ dialog.pe-dlg::backdrop {
|
|
|
181
181
|
.helpl.warn {
|
|
182
182
|
color: var(--warn);
|
|
183
183
|
}
|
|
184
|
+
/* AG-17.1c, AG-18: what a persona changes, under the list. */
|
|
185
|
+
.den-keep {
|
|
186
|
+
margin: 8px 0 0;
|
|
187
|
+
padding-left: 18px;
|
|
188
|
+
font-size: 12px;
|
|
189
|
+
line-height: 1.45;
|
|
190
|
+
color: var(--muted);
|
|
191
|
+
}
|
|
192
|
+
.den-keep li + li {
|
|
193
|
+
margin-top: 2px;
|
|
194
|
+
}
|
|
184
195
|
.faint {
|
|
185
196
|
color: var(--faint);
|
|
186
197
|
}
|
|
@@ -561,3 +572,24 @@ dialog.pe-dlg::backdrop {
|
|
|
561
572
|
.pr[aria-disabled="true"]:hover {
|
|
562
573
|
background: none;
|
|
563
574
|
}
|
|
575
|
+
|
|
576
|
+
/* ON-3's approval dialog (shell.js, every page): the Start dialog's frame,
|
|
577
|
+
the request in the body text's size and weight, and Review's lines in
|
|
578
|
+
the mono box the persona Details use. */
|
|
579
|
+
.den-ap-dlg .den-ap-what {
|
|
580
|
+
color: var(--text);
|
|
581
|
+
font: 600 14.5px/1.45 var(--sans);
|
|
582
|
+
overflow-wrap: anywhere;
|
|
583
|
+
}
|
|
584
|
+
.den-ap-dlg .den-ap-det {
|
|
585
|
+
margin: 0;
|
|
586
|
+
max-height: 260px;
|
|
587
|
+
overflow: auto;
|
|
588
|
+
padding: 10px 12px;
|
|
589
|
+
border: 1px solid var(--border);
|
|
590
|
+
border-radius: var(--radius-button, 6px);
|
|
591
|
+
background: var(--surface, var(--raised));
|
|
592
|
+
font: 12px/1.5 var(--mono);
|
|
593
|
+
white-space: pre-wrap;
|
|
594
|
+
overflow-wrap: anywhere;
|
|
595
|
+
}
|
|
@@ -160,7 +160,9 @@ export function deviceLine(d, now = Date.now()) {
|
|
|
160
160
|
? `signed in with GitHub${d.login ? ` (@${d.login})` : ""}`
|
|
161
161
|
: d.via === "code"
|
|
162
162
|
? "approved with a code"
|
|
163
|
-
:
|
|
163
|
+
: d.via === "claim"
|
|
164
|
+
? "claimed with a setup link"
|
|
165
|
+
: "signed in with a one-time link";
|
|
164
166
|
const name = d.name || "Unknown browser";
|
|
165
167
|
const from = d.client || d.host;
|
|
166
168
|
return {
|
|
@@ -340,10 +340,18 @@
|
|
|
340
340
|
.set-radio:hover {
|
|
341
341
|
background: var(--sunken);
|
|
342
342
|
}
|
|
343
|
+
/* Not installed: the option stays readable (WCAG AA); only its
|
|
344
|
+
radio dims. */
|
|
343
345
|
.set-radio.off {
|
|
344
|
-
|
|
346
|
+
color: var(--muted);
|
|
345
347
|
cursor: default;
|
|
346
348
|
}
|
|
349
|
+
.set-radio.off:hover {
|
|
350
|
+
background: none;
|
|
351
|
+
}
|
|
352
|
+
.set-radio.off input {
|
|
353
|
+
opacity: 0.5;
|
|
354
|
+
}
|
|
347
355
|
.set-radio input {
|
|
348
356
|
accent-color: var(--accent);
|
|
349
357
|
margin: 0;
|