@monster-orange/den 0.4.10 → 0.4.12
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 +92 -0
- package/README.md +7 -7
- package/docs/distributions.md +67 -3
- package/package.json +2 -1
- package/src/shared/agents/catalog.ts +77 -0
- package/src/shared/agents/den-claude.ts +36 -8
- package/src/shared/agents/records.ts +29 -0
- package/src/shared/agents/runtime.ts +8 -0
- package/src/shared/agents/session-name.ts +110 -0
- package/src/shared/agents/transcript-follow.ts +180 -0
- package/src/shared/den-config.ts +7 -0
- package/src/ui/cli/agent-ops.ts +49 -0
- package/src/ui/server/agent-paths.ts +52 -0
- package/src/ui/server/agent-routes.ts +76 -5
- package/src/ui/server/agents-layout-pref.ts +43 -0
- package/src/ui/server/editor-open-pref.ts +41 -0
- package/src/ui/server/index.ts +22 -0
- package/src/ui/server/public/agents-page.js +539 -20
- package/src/ui/server/public/agents-section.js +1 -1
- package/src/ui/server/public/agents.html +178 -5
- package/src/ui/server/public/header.js +30 -19
- package/src/ui/server/public/i18n/es.js +23 -5
- package/src/ui/server/public/i18n/ja.js +23 -5
- package/src/ui/server/public/local-dev.html +1 -1
- package/src/ui/server/public/settings-registry.js +44 -0
- package/src/ui/server/public/shell.js +34 -20
- package/src/ui/server/public/term-input.js +129 -0
- package/src/ui/server/public/topbar.js +22 -4
- package/src/ui/server/public/workspace-picker.js +9 -6
- package/src/ui/server/route-classes.ts +11 -0
- package/src/ui/server/session-routes.ts +17 -0
- package/src/ui/server/ui-assets.ts +5 -0
|
@@ -138,7 +138,7 @@ function rowHtml(r) {
|
|
|
138
138
|
? ` <span class="tbl-muted">· ${esc(r.model)}</span>`
|
|
139
139
|
: "";
|
|
140
140
|
return `<tr class="agent" data-agent="${esc(r.agent)}" data-state="${esc(r.state)}">
|
|
141
|
-
<th scope="row"
|
|
141
|
+
<th scope="row">${r.displayName ? `<span class="repo-name">${esc(r.displayName)}</span> <span class="tbl-muted">${esc(r.agent)}</span>` : `<span class="repo-name">${esc(r.agent)}</span>`}${persona}</th>
|
|
142
142
|
<td class="tbl-mono">${esc(r.runtime ?? "—")}${model}</td>
|
|
143
143
|
<td>${stateCell(r.state)}</td>
|
|
144
144
|
<td class="tbl-mono tbl-muted agent-cwd" title="${esc(r.cwd ?? "")}">${esc(r.cwd ?? "—")}</td>
|
|
@@ -50,13 +50,26 @@
|
|
|
50
50
|
flex-direction: column;
|
|
51
51
|
overflow: hidden;
|
|
52
52
|
}
|
|
53
|
+
/* AG-4b: the main area is a column that fills the window between
|
|
54
|
+
the top bar and the runs dock (the body is the viewport's height,
|
|
55
|
+
the shell's column puts the dock at its foot); the list and the
|
|
56
|
+
panes take what is left, 14px above the dock. No 100vh guess. */
|
|
57
|
+
html body.den-has-shell {
|
|
58
|
+
height: 100%;
|
|
59
|
+
min-height: 0;
|
|
60
|
+
}
|
|
53
61
|
html body.den-has-shell > #den-content {
|
|
54
62
|
overflow: auto;
|
|
55
63
|
min-width: 0;
|
|
56
|
-
|
|
64
|
+
min-height: 0;
|
|
65
|
+
padding: 20px 24px 14px 24px;
|
|
57
66
|
font: 14px/1.45 var(--sans);
|
|
58
67
|
color: var(--text);
|
|
59
|
-
display:
|
|
68
|
+
display: flex;
|
|
69
|
+
flex-direction: column;
|
|
70
|
+
}
|
|
71
|
+
#den-content > .ph {
|
|
72
|
+
flex: none;
|
|
60
73
|
}
|
|
61
74
|
#den-content :focus-visible {
|
|
62
75
|
outline: 2px solid var(--accent);
|
|
@@ -94,9 +107,38 @@
|
|
|
94
107
|
.agx {
|
|
95
108
|
display: grid;
|
|
96
109
|
grid-template-columns: 300px minmax(0, 1fr);
|
|
110
|
+
grid-template-rows: minmax(0, 1fr);
|
|
97
111
|
gap: 14px;
|
|
98
|
-
|
|
99
|
-
height:
|
|
112
|
+
flex: 1;
|
|
113
|
+
min-height: 0;
|
|
114
|
+
}
|
|
115
|
+
/* The layout switch (AG-4b), the prototype's .seg. */
|
|
116
|
+
.seg {
|
|
117
|
+
display: inline-flex;
|
|
118
|
+
border: 1px solid var(--border);
|
|
119
|
+
border-radius: var(--radius-button);
|
|
120
|
+
overflow: hidden;
|
|
121
|
+
flex-wrap: wrap;
|
|
122
|
+
}
|
|
123
|
+
.seg button {
|
|
124
|
+
background: none;
|
|
125
|
+
border: 0;
|
|
126
|
+
padding: 6px 12px;
|
|
127
|
+
cursor: pointer;
|
|
128
|
+
color: var(--muted);
|
|
129
|
+
font: inherit;
|
|
130
|
+
}
|
|
131
|
+
.seg button[aria-pressed="true"] {
|
|
132
|
+
background: color-mix(in srgb, var(--accent) 16%, transparent);
|
|
133
|
+
color: var(--text);
|
|
134
|
+
font-weight: 500;
|
|
135
|
+
}
|
|
136
|
+
.agl .aghint {
|
|
137
|
+
padding: 10px 12px;
|
|
138
|
+
font-size: 12px;
|
|
139
|
+
color: var(--faint);
|
|
140
|
+
border-top: 1px solid var(--border);
|
|
141
|
+
margin-top: 6px;
|
|
100
142
|
}
|
|
101
143
|
.agl {
|
|
102
144
|
border: 1px solid var(--border);
|
|
@@ -245,6 +287,98 @@
|
|
|
245
287
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
246
288
|
grid-auto-rows: minmax(0, 1fr);
|
|
247
289
|
}
|
|
290
|
+
.agp.tabs {
|
|
291
|
+
grid-template-columns: minmax(0, 1fr);
|
|
292
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
293
|
+
gap: 0;
|
|
294
|
+
}
|
|
295
|
+
.agp > .pane[hidden] {
|
|
296
|
+
display: none;
|
|
297
|
+
}
|
|
298
|
+
.agp.tabs > .pane {
|
|
299
|
+
border-top-left-radius: 0;
|
|
300
|
+
}
|
|
301
|
+
/* The tab strip (the prototype's .agtabs): name, persona · workspace. */
|
|
302
|
+
.agtabs {
|
|
303
|
+
display: flex;
|
|
304
|
+
gap: 2px;
|
|
305
|
+
border-bottom: 1px solid var(--border);
|
|
306
|
+
overflow-x: auto;
|
|
307
|
+
min-width: 0;
|
|
308
|
+
}
|
|
309
|
+
.agtab-w {
|
|
310
|
+
position: relative;
|
|
311
|
+
display: inline-flex;
|
|
312
|
+
flex: none;
|
|
313
|
+
max-width: 280px;
|
|
314
|
+
}
|
|
315
|
+
.agtab {
|
|
316
|
+
display: inline-flex;
|
|
317
|
+
align-items: center;
|
|
318
|
+
gap: 6px;
|
|
319
|
+
min-width: 0;
|
|
320
|
+
border: 1px solid transparent;
|
|
321
|
+
border-bottom: 0;
|
|
322
|
+
background: none;
|
|
323
|
+
padding: 6px 28px 6px 10px;
|
|
324
|
+
border-radius: var(--radius-button) var(--radius-button) 0 0;
|
|
325
|
+
cursor: pointer;
|
|
326
|
+
color: var(--muted);
|
|
327
|
+
white-space: nowrap;
|
|
328
|
+
font: 13px var(--sans);
|
|
329
|
+
}
|
|
330
|
+
.agtab[hidden] {
|
|
331
|
+
display: none;
|
|
332
|
+
}
|
|
333
|
+
.agtab[aria-selected="true"] {
|
|
334
|
+
background: var(--surface);
|
|
335
|
+
border-color: var(--border);
|
|
336
|
+
color: var(--text);
|
|
337
|
+
margin-bottom: -1px;
|
|
338
|
+
}
|
|
339
|
+
.agtab .den-dot {
|
|
340
|
+
margin: 0;
|
|
341
|
+
}
|
|
342
|
+
.agtab .tn {
|
|
343
|
+
overflow: hidden;
|
|
344
|
+
text-overflow: ellipsis;
|
|
345
|
+
}
|
|
346
|
+
.agtab .tm {
|
|
347
|
+
color: var(--faint);
|
|
348
|
+
font-size: 11px;
|
|
349
|
+
overflow: hidden;
|
|
350
|
+
text-overflow: ellipsis;
|
|
351
|
+
}
|
|
352
|
+
.agtab-x {
|
|
353
|
+
position: absolute;
|
|
354
|
+
top: 0;
|
|
355
|
+
bottom: 0;
|
|
356
|
+
right: 4px;
|
|
357
|
+
display: flex;
|
|
358
|
+
align-items: center;
|
|
359
|
+
padding: 0 4px;
|
|
360
|
+
border: 0;
|
|
361
|
+
background: none;
|
|
362
|
+
cursor: pointer;
|
|
363
|
+
font: 13px var(--sans);
|
|
364
|
+
color: var(--faint);
|
|
365
|
+
}
|
|
366
|
+
.agtab-x:hover {
|
|
367
|
+
color: var(--bad);
|
|
368
|
+
}
|
|
369
|
+
.agtab-in {
|
|
370
|
+
font: 13px var(--sans);
|
|
371
|
+
width: 200px;
|
|
372
|
+
margin: 3px 28px 3px 6px;
|
|
373
|
+
padding: 2px 6px;
|
|
374
|
+
border: 1px solid var(--accent);
|
|
375
|
+
border-radius: var(--radius-button);
|
|
376
|
+
background: var(--bg);
|
|
377
|
+
color: var(--text);
|
|
378
|
+
}
|
|
379
|
+
.den-sr[hidden] {
|
|
380
|
+
display: none;
|
|
381
|
+
}
|
|
248
382
|
.pane {
|
|
249
383
|
display: grid;
|
|
250
384
|
grid-template-rows: auto minmax(0, 1fr);
|
|
@@ -292,6 +426,9 @@
|
|
|
292
426
|
gap: 6px;
|
|
293
427
|
flex: none;
|
|
294
428
|
}
|
|
429
|
+
.pane .bar2 .x [hidden] {
|
|
430
|
+
display: none;
|
|
431
|
+
}
|
|
295
432
|
/* The body: mono 12px/1.5 (xterm draws inside it). */
|
|
296
433
|
.pane .term {
|
|
297
434
|
min-height: 0;
|
|
@@ -301,6 +438,15 @@
|
|
|
301
438
|
color: var(--text);
|
|
302
439
|
overflow: hidden;
|
|
303
440
|
}
|
|
441
|
+
.pane .term {
|
|
442
|
+
display: grid;
|
|
443
|
+
grid-template: minmax(0, 1fr) / minmax(0, 1fr);
|
|
444
|
+
}
|
|
445
|
+
.pane .term .tbox {
|
|
446
|
+
min-height: 0;
|
|
447
|
+
min-width: 0;
|
|
448
|
+
overflow: hidden;
|
|
449
|
+
}
|
|
304
450
|
.pane .term .xterm {
|
|
305
451
|
height: 100%;
|
|
306
452
|
}
|
|
@@ -430,7 +576,8 @@
|
|
|
430
576
|
@media (max-width: 860px) {
|
|
431
577
|
.agx {
|
|
432
578
|
grid-template-columns: minmax(0, 1fr);
|
|
433
|
-
|
|
579
|
+
grid-template-rows: none;
|
|
580
|
+
flex: none;
|
|
434
581
|
}
|
|
435
582
|
.ph .act {
|
|
436
583
|
flex-wrap: wrap;
|
|
@@ -465,6 +612,32 @@
|
|
|
465
612
|
</div>
|
|
466
613
|
</div>
|
|
467
614
|
<div class="act">
|
|
615
|
+
<div class="seg" role="group" aria-label="Layout" data-layouts>
|
|
616
|
+
<button
|
|
617
|
+
type="button"
|
|
618
|
+
data-layout="focus"
|
|
619
|
+
aria-pressed="true"
|
|
620
|
+
aria-keyshortcuts="Control+Shift+1"
|
|
621
|
+
>
|
|
622
|
+
Focus
|
|
623
|
+
</button>
|
|
624
|
+
<button
|
|
625
|
+
type="button"
|
|
626
|
+
data-layout="tabs"
|
|
627
|
+
aria-pressed="false"
|
|
628
|
+
aria-keyshortcuts="Control+Shift+2"
|
|
629
|
+
>
|
|
630
|
+
Tabs
|
|
631
|
+
</button>
|
|
632
|
+
<button
|
|
633
|
+
type="button"
|
|
634
|
+
data-layout="tile"
|
|
635
|
+
aria-pressed="false"
|
|
636
|
+
aria-keyshortcuts="Control+Shift+3"
|
|
637
|
+
>
|
|
638
|
+
Tile
|
|
639
|
+
</button>
|
|
640
|
+
</div>
|
|
468
641
|
<button type="button" class="den-btn" id="ag-clear" hidden>
|
|
469
642
|
Clear stopped
|
|
470
643
|
</button>
|
|
@@ -792,10 +792,11 @@ export function groupReposByApplication(repos, apps) {
|
|
|
792
792
|
|
|
793
793
|
/**
|
|
794
794
|
* Feed the shell's Workspace part (shell.js #ws-pill, a menu): "All active"
|
|
795
|
-
* and each active workspace, the focused one marked. Choosing
|
|
796
|
-
*
|
|
797
|
-
*
|
|
798
|
-
*
|
|
795
|
+
* and each active workspace, the focused one marked. Choosing a workspace
|
|
796
|
+
* makes it the CLI default (POST /api/workspaces `focus`, workspaces.yml)
|
|
797
|
+
* and sets the view (POST /api/scope, a preference) for every page: one
|
|
798
|
+
* "current workspace" (Ward's decision, 0.4.11). "All active" sets only the
|
|
799
|
+
* view; the CLI default stays.
|
|
799
800
|
*
|
|
800
801
|
* The arguments are dev.17's (an env select, an onSwitch callback) and are
|
|
801
802
|
* no longer used: the view applies to every env.
|
|
@@ -822,7 +823,6 @@ async function _renderScopeMenu() {
|
|
|
822
823
|
sh.setWorkspaces({
|
|
823
824
|
...buildScopeMenuModel(pageScope(scope, data), data, t),
|
|
824
825
|
onSelect: _switchScope,
|
|
825
|
-
onFocus: _setFocus,
|
|
826
826
|
});
|
|
827
827
|
} catch {
|
|
828
828
|
sh.setWorkspaces(null);
|
|
@@ -852,25 +852,36 @@ function pageScope(scope, data) {
|
|
|
852
852
|
}
|
|
853
853
|
|
|
854
854
|
/**
|
|
855
|
-
*
|
|
856
|
-
*
|
|
857
|
-
*
|
|
858
|
-
*
|
|
855
|
+
* A choice replaces ?ws= (All active drops it, a workspace sets it) on the
|
|
856
|
+
* Graph and Agents pages, and on any page whose URL names a workspace
|
|
857
|
+
* (Workspaces' detail pane), so the reload shows the choice rather than
|
|
858
|
+
* the old ?ws=. The history entry is replaced, not pushed: Back does not
|
|
859
|
+
* return to a view the picker has left.
|
|
859
860
|
*/
|
|
860
861
|
function followScopeInUrl(value) {
|
|
861
|
-
if (!WS_URL_PAGES.has(location.pathname)) return;
|
|
862
862
|
const u = new URL(location.href);
|
|
863
|
+
if (!WS_URL_PAGES.has(location.pathname) && !u.searchParams.has("ws")) return;
|
|
863
864
|
if (value === "all") u.searchParams.delete("ws");
|
|
864
865
|
else u.searchParams.set("ws", value);
|
|
865
866
|
history.replaceState(history.state, "", u.pathname + u.search + u.hash);
|
|
866
867
|
}
|
|
867
868
|
|
|
868
869
|
/**
|
|
869
|
-
* A
|
|
870
|
-
*
|
|
871
|
-
*
|
|
870
|
+
* A workspace: first the CLI default (workspaces.yml), then the view. When
|
|
871
|
+
* the CLI default can't be set, nothing changes and the error shows. "All
|
|
872
|
+
* active": the view only. POST /api/scope stores the view (user.yml
|
|
873
|
+
* `view`), then the page reloads to show it whole. The workspace already
|
|
874
|
+
* in view (`inView`): the CLI default only, the view untouched. No
|
|
875
|
+
* service, container, daemon or route changes.
|
|
872
876
|
*/
|
|
873
|
-
async function _switchScope(value) {
|
|
877
|
+
async function _switchScope(value, focus, inView) {
|
|
878
|
+
if (value !== "all" && value !== focus && !(await _setFocus(value))) return;
|
|
879
|
+
if (inView) {
|
|
880
|
+
// A ?ws= page shows the pick after the reload, not its old ?ws=.
|
|
881
|
+
followScopeInUrl(value);
|
|
882
|
+
location.reload();
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
874
885
|
try {
|
|
875
886
|
await window.denShell.api("POST", "/api/scope", { scope: value });
|
|
876
887
|
} catch (err) {
|
|
@@ -885,9 +896,9 @@ async function _switchScope(value) {
|
|
|
885
896
|
}
|
|
886
897
|
|
|
887
898
|
/**
|
|
888
|
-
*
|
|
889
|
-
* `focus`, which writes workspaces.yml and retargets the
|
|
890
|
-
*
|
|
899
|
+
* Make `name` the CLI default: Local Dev's focus action (POST
|
|
900
|
+
* /api/workspaces `focus`, which writes workspaces.yml and retargets the
|
|
901
|
+
* CLI). False, with the error shown, when it couldn't.
|
|
891
902
|
*/
|
|
892
903
|
async function _setFocus(name) {
|
|
893
904
|
try {
|
|
@@ -900,9 +911,9 @@ async function _setFocus(name) {
|
|
|
900
911
|
err.message = t("ws.focusFailed", { msg: err.message });
|
|
901
912
|
window.denShell.errorToast(err);
|
|
902
913
|
} else window.denShell?.toast?.(t("ws.focusFailed", { msg: err.message }));
|
|
903
|
-
return;
|
|
914
|
+
return false;
|
|
904
915
|
}
|
|
905
|
-
|
|
916
|
+
return true;
|
|
906
917
|
}
|
|
907
918
|
|
|
908
919
|
// ── Health: the status chip and drawer (topbar.js, R6 and R15) ─────────────
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
"ws.all": "Todos los activos",
|
|
30
30
|
"ws.focus": "predeterminado de la CLI",
|
|
31
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
|
|
32
|
+
"Los comandos de la CLI se ejecutan aquí si no indicas un espacio de trabajo. Elegir un espacio en la barra superior también lo convierte en el predeterminado de la CLI.",
|
|
33
|
+
"ws.pickTip":
|
|
34
|
+
"Elegir un espacio de trabajo aquí también lo convierte en el predeterminado de la CLI, así que los comandos de __DEN_CLI__ se ejecutan allí.",
|
|
33
35
|
"ws.none": "No hay espacios de trabajo activos",
|
|
34
36
|
"ws.manage": "Gestionar espacios de trabajo…",
|
|
35
37
|
"ws.allN": "Todos los activos ({n})",
|
|
@@ -39,10 +41,7 @@
|
|
|
39
41
|
"ws.viewTitle":
|
|
40
42
|
"Vista: lo que muestra cada página ({ws}). Es solo un filtro: no inicia, detiene ni enruta nada.",
|
|
41
43
|
"ws.viewTitleFocus":
|
|
42
|
-
"Vista: lo que muestra cada página ({ws}).
|
|
43
|
-
"ws.setFocus": "Hacer de {ws} el predeterminado de la CLI",
|
|
44
|
-
"ws.setFocusTip":
|
|
45
|
-
"Lo convierte en el destino por defecto de los comandos (escribe workspaces.yml)",
|
|
44
|
+
"Vista: lo que muestra cada página ({ws}). No inicia, detiene ni enruta nada. Predeterminado de la CLI: {focus}.",
|
|
46
45
|
"ws.viewFailed": "No se pudo cambiar la vista: {msg}",
|
|
47
46
|
"ws.focusFailed": "No se pudo poner el foco: {msg}",
|
|
48
47
|
"org.n": "{n} espacios de trabajo",
|
|
@@ -328,6 +327,7 @@
|
|
|
328
327
|
"set.language": "Idioma",
|
|
329
328
|
"set.appearance.org-theme": "Tema predeterminado de la org",
|
|
330
329
|
"set.editor": "IDE predeterminado",
|
|
330
|
+
"set.editor.open": "Abrir enlaces de archivo en",
|
|
331
331
|
"set.editor_overrides": "IDE por lenguaje",
|
|
332
332
|
"set.terminal": "Terminal predeterminada",
|
|
333
333
|
"set.shell.pages": "Páginas",
|
|
@@ -342,6 +342,7 @@
|
|
|
342
342
|
"set.graph.panelWidth": "Panel de detalles",
|
|
343
343
|
"set.workspace.editor": "IDE de este espacio de trabajo",
|
|
344
344
|
"set.agents.runtimes": "Runtimes",
|
|
345
|
+
"set.agents.layout": "Disposición de la pestaña Agentes",
|
|
345
346
|
"set.cli.local_dev": "Entorno local",
|
|
346
347
|
"set.cli.cli_tabs": "Pestañas de terminal",
|
|
347
348
|
"set.cli.log_window_lines": "Líneas del panel de registros",
|
|
@@ -476,6 +477,23 @@
|
|
|
476
477
|
"ag.palStart": "Iniciar agente…",
|
|
477
478
|
"ag.cap":
|
|
478
479
|
"Hasta 4 paneles: se cerró el de {id} para hacer sitio (sigue en marcha)",
|
|
480
|
+
"ag.layout": "Disposición",
|
|
481
|
+
"ag.l.focus": "Enfoque",
|
|
482
|
+
"ag.l.tabs": "Pestañas",
|
|
483
|
+
"ag.l.tile": "Mosaico",
|
|
484
|
+
"ag.l.tip": "{name} ({key})",
|
|
485
|
+
"ag.hint.keys":
|
|
486
|
+
"⌃⇧1 / ⌃⇧2 / ⌃⇧3 cambian la disposición. ⌘ y clic (Ctrl y clic) abre un enlace o una ruta.",
|
|
487
|
+
"ag.pal.layout": "Disposición: {name}",
|
|
488
|
+
"ag.copied": "Copiado",
|
|
489
|
+
"ag.tabs": "Sesiones abiertas",
|
|
490
|
+
"ag.hint.focus":
|
|
491
|
+
"Un clic muestra una sesión. Mayús o ⌘ y clic la añade al lado.",
|
|
492
|
+
"ag.hint.tabs":
|
|
493
|
+
"Un clic abre una sesión en una pestaña. Doble clic en una pestaña para cambiarle el nombre.",
|
|
494
|
+
"ag.hint.tile": "Un clic añade una sesión al mosaico, hasta 4.",
|
|
495
|
+
"ag.renameTip": "Doble clic para cambiar el nombre",
|
|
496
|
+
"ag.renameName": "Cambiar el nombre de {id}",
|
|
479
497
|
"ag.rt.ready": "Inicia {name} {version} desde",
|
|
480
498
|
"ag.rt.readyNoVer": "Inicia {name} desde",
|
|
481
499
|
"ag.rt.notFound": "No se encontró {name}.",
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
"ws.all": "すべてのアクティブ",
|
|
30
30
|
"ws.focus": "CLI の既定",
|
|
31
31
|
"ws.focusTip":
|
|
32
|
-
"
|
|
32
|
+
"ワークスペースを指定しないと CLI のコマンドはここで実行されます。上部バーでワークスペースを選ぶと、それが CLI の既定にもなります。",
|
|
33
|
+
"ws.pickTip":
|
|
34
|
+
"ここでワークスペースを選ぶと CLI の既定にもなり、__DEN_CLI__ のコマンドはそこで実行されます。",
|
|
33
35
|
"ws.none": "アクティブなワークスペースはありません",
|
|
34
36
|
"ws.manage": "ワークスペースを管理…",
|
|
35
37
|
"ws.allN": "すべてのアクティブ ({n})",
|
|
@@ -39,10 +41,7 @@
|
|
|
39
41
|
"ws.viewTitle":
|
|
40
42
|
"表示: すべてのページに表示する範囲 ({ws})。表示の絞り込みだけで、何も起動・停止・ルーティングしません。",
|
|
41
43
|
"ws.viewTitleFocus":
|
|
42
|
-
"表示:
|
|
43
|
-
"ws.setFocus": "{ws} を CLI の既定にする",
|
|
44
|
-
"ws.setFocusTip":
|
|
45
|
-
"コマンドの既定の対象にします (workspaces.yml に書き込みます)",
|
|
44
|
+
"表示: 各ページに出るもの ({ws})。起動・停止・ルーティングは行いません。CLI の既定: {focus}。",
|
|
46
45
|
"ws.viewFailed": "表示を変更できませんでした: {msg}",
|
|
47
46
|
"ws.focusFailed": "フォーカスを設定できませんでした: {msg}",
|
|
48
47
|
"org.n": "{n} 個のワークスペース",
|
|
@@ -317,6 +316,7 @@
|
|
|
317
316
|
"set.language": "言語",
|
|
318
317
|
"set.appearance.org-theme": "組織の既定テーマ",
|
|
319
318
|
"set.editor": "既定の IDE",
|
|
319
|
+
"set.editor.open": "ファイルリンクを開くエディター",
|
|
320
320
|
"set.editor_overrides": "言語ごとの IDE",
|
|
321
321
|
"set.terminal": "既定のターミナル",
|
|
322
322
|
"set.shell.pages": "ページ",
|
|
@@ -331,6 +331,7 @@
|
|
|
331
331
|
"set.graph.panelWidth": "詳細パネル",
|
|
332
332
|
"set.workspace.editor": "このワークスペースの IDE",
|
|
333
333
|
"set.agents.runtimes": "ランタイム",
|
|
334
|
+
"set.agents.layout": "エージェントタブのレイアウト",
|
|
334
335
|
"set.cli.local_dev": "ローカル環境",
|
|
335
336
|
"set.cli.cli_tabs": "ターミナルのタブ",
|
|
336
337
|
"set.cli.log_window_lines": "ログ欄の行数",
|
|
@@ -456,6 +457,23 @@
|
|
|
456
457
|
"ag.palStart": "エージェントを開始…",
|
|
457
458
|
"ag.cap":
|
|
458
459
|
"ペインは最大 4 つです。{id} のペインを閉じました(実行は続きます)",
|
|
460
|
+
"ag.layout": "レイアウト",
|
|
461
|
+
"ag.l.focus": "フォーカス",
|
|
462
|
+
"ag.l.tabs": "タブ",
|
|
463
|
+
"ag.l.tile": "タイル",
|
|
464
|
+
"ag.l.tip": "{name}({key})",
|
|
465
|
+
"ag.hint.keys":
|
|
466
|
+
"⌃⇧1 / ⌃⇧2 / ⌃⇧3 でレイアウトを切り替えます。⌘ クリック(Ctrl クリック)でリンクやパスを開きます。",
|
|
467
|
+
"ag.pal.layout": "レイアウト: {name}",
|
|
468
|
+
"ag.copied": "コピーしました",
|
|
469
|
+
"ag.tabs": "開いているセッション",
|
|
470
|
+
"ag.hint.focus":
|
|
471
|
+
"クリックで 1 つのセッションを表示します。Shift か ⌘ を押しながらクリックすると横に追加します。",
|
|
472
|
+
"ag.hint.tabs":
|
|
473
|
+
"クリックでセッションをタブで開きます。タブをダブルクリックすると名前を変えられます。",
|
|
474
|
+
"ag.hint.tile": "クリックでセッションをタイルに追加します(最大 4)。",
|
|
475
|
+
"ag.renameTip": "ダブルクリックで名前を変更",
|
|
476
|
+
"ag.renameName": "{id} の名前を変更",
|
|
459
477
|
"ag.rt.ready": "{name} {version} を起動:",
|
|
460
478
|
"ag.rt.readyNoVer": "{name} を起動:",
|
|
461
479
|
"ag.rt.notFound": "{name} が見つかりません。",
|
|
@@ -1613,7 +1613,7 @@
|
|
|
1613
1613
|
? `<button class="danger" data-action="delete">Delete</button>`
|
|
1614
1614
|
: "";
|
|
1615
1615
|
return `<div class="ws-item ${n === activeWs ? "active" : ""}" data-name="${escHtml(n)}" data-action="select">
|
|
1616
|
-
<span>${escHtml(n)}${isWsActive(n) ? ' <span style="font-size:10px;color:var(--muted)">(active)</span>' : ""}${n === focusName() ? ` <span class="ws-cli-default" title="${escHtml(wsT("ws.focusTip", "CLI commands run here when you don't name a workspace. Picking a workspace in the top bar
|
|
1616
|
+
<span>${escHtml(n)}${isWsActive(n) ? ' <span style="font-size:10px;color:var(--muted)">(active)</span>' : ""}${n === focusName() ? ` <span class="ws-cli-default" title="${escHtml(wsT("ws.focusTip", "CLI commands run here when you don't name a workspace. Picking a workspace in the top bar also makes it the CLI default."))}">${escHtml(wsT("ws.focus", "CLI default"))}</span>` : ""}</span>
|
|
1617
1617
|
<span class="ws-item-right">
|
|
1618
1618
|
<button class="ws-term-btn" title="Open in terminal" data-open-term="${escHtml(dirPath)}">>_</button>
|
|
1619
1619
|
<button class="ws-open-btn" title="Open in editor" data-open-path="${escHtml(wsData.codeWorkspacePaths?.[n] || dirPath)}">↗</button>
|
|
@@ -628,6 +628,33 @@ export const DEN_SETTINGS = [
|
|
|
628
628
|
read: (ctx) => effective(ctx.data.editors, ctx.data.editor),
|
|
629
629
|
write: (v, ctx) => ctx.post({ editor: v || null }),
|
|
630
630
|
},
|
|
631
|
+
{
|
|
632
|
+
id: "editor.open",
|
|
633
|
+
category: "editor",
|
|
634
|
+
label: "Open file links in",
|
|
635
|
+
description:
|
|
636
|
+
"⌘-click (Ctrl-click on Windows and Linux) on a file path in an agent's pane opens it here, at the line. None copies the path instead.",
|
|
637
|
+
keywords: [
|
|
638
|
+
"editor",
|
|
639
|
+
"link",
|
|
640
|
+
"path",
|
|
641
|
+
"file",
|
|
642
|
+
"agents",
|
|
643
|
+
"vscode",
|
|
644
|
+
"cursor",
|
|
645
|
+
"zed",
|
|
646
|
+
],
|
|
647
|
+
scope: "user",
|
|
648
|
+
control: seg([
|
|
649
|
+
{ value: "vscode", label: "VS Code" },
|
|
650
|
+
{ value: "cursor", label: "Cursor" },
|
|
651
|
+
{ value: "zed", label: "Zed" },
|
|
652
|
+
{ value: "none", label: "None (copy)" },
|
|
653
|
+
]),
|
|
654
|
+
keys: ["editor_open"],
|
|
655
|
+
read: (ctx) => ctx.data.editor_open ?? "none",
|
|
656
|
+
write: (v, ctx) => ctx.post({ editor_open: v }),
|
|
657
|
+
},
|
|
631
658
|
{
|
|
632
659
|
id: "editor_overrides",
|
|
633
660
|
category: "editor",
|
|
@@ -813,6 +840,23 @@ export const DEN_SETTINGS = [
|
|
|
813
840
|
},
|
|
814
841
|
|
|
815
842
|
// ── Agents ─────────────────────────────────────────────────────────────
|
|
843
|
+
{
|
|
844
|
+
id: "agents.layout",
|
|
845
|
+
category: "agents",
|
|
846
|
+
label: "Agents tab layout",
|
|
847
|
+
description:
|
|
848
|
+
"Focus shows one agent, Tabs shows one with a tab for each, Tile shows up to four in a grid. The Agents tab's switch, ⌃⇧1, ⌃⇧2, ⌃⇧3 and ⌘K set it too.",
|
|
849
|
+
keywords: ["agents", "layout", "focus", "tabs", "tile", "grid", "panes"],
|
|
850
|
+
scope: "user",
|
|
851
|
+
control: seg([
|
|
852
|
+
{ value: "focus", label: "Focus" },
|
|
853
|
+
{ value: "tabs", label: "Tabs" },
|
|
854
|
+
{ value: "tile", label: "Tile" },
|
|
855
|
+
]),
|
|
856
|
+
keys: ["agents_layout"],
|
|
857
|
+
read: (ctx) => ctx.data.agents_layout ?? "focus",
|
|
858
|
+
write: (v, ctx) => ctx.post({ agents_layout: v }),
|
|
859
|
+
},
|
|
816
860
|
{
|
|
817
861
|
id: "agents.runtimes",
|
|
818
862
|
category: "agents",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
* setOrgs([{ id, title, workspaces? }], currentId, onSelect?)
|
|
63
63
|
* two or more: the Org ▾ menu; a pick
|
|
64
64
|
* calls onSelect(id), fires `den:org`
|
|
65
|
-
* setWorkspaces({ label, title, items,
|
|
65
|
+
* setWorkspaces({ label, title, items, focus, onSelect })
|
|
66
66
|
* the Workspace ▾ menu (header.js)
|
|
67
67
|
* syncEnv() repaint Env ▾ from #env-sel
|
|
68
68
|
* registerCommand({ id, label, keywords?, kind?, run })
|
|
@@ -134,7 +134,9 @@
|
|
|
134
134
|
"ws.all": "All active",
|
|
135
135
|
"ws.focus": "CLI default",
|
|
136
136
|
"ws.focusTip":
|
|
137
|
-
"CLI commands run here when you don't name a workspace. Picking a workspace in the top bar
|
|
137
|
+
"CLI commands run here when you don't name a workspace. Picking a workspace in the top bar also makes it the CLI default.",
|
|
138
|
+
"ws.pickTip":
|
|
139
|
+
"Picking a workspace here also makes it the CLI default, so __DEN_CLI__ commands run there.",
|
|
138
140
|
"ws.none": "No active workspaces",
|
|
139
141
|
"ws.manage": "Manage workspaces…",
|
|
140
142
|
"ws.allN": "All active ({n})",
|
|
@@ -144,10 +146,7 @@
|
|
|
144
146
|
"ws.viewTitle":
|
|
145
147
|
"View: what every page shows ({ws}). A view filter only: it starts, stops and routes nothing.",
|
|
146
148
|
"ws.viewTitleFocus":
|
|
147
|
-
"View: what every page shows ({ws}).
|
|
148
|
-
"ws.setFocus": "Make {ws} the CLI default",
|
|
149
|
-
"ws.setFocusTip":
|
|
150
|
-
"CLI commands run in it when you don't name a workspace (writes workspaces.yml)",
|
|
149
|
+
"View: what every page shows ({ws}). It starts, stops and routes nothing. CLI default: {focus}.",
|
|
151
150
|
"ws.viewFailed": "Could not change the view: {msg}",
|
|
152
151
|
"ws.focusFailed": "Could not change the CLI default: {msg}",
|
|
153
152
|
// A count's singular is its .one (0.3.0-dev.40: en had none, so the org
|
|
@@ -439,6 +438,7 @@
|
|
|
439
438
|
"set.language": "Language",
|
|
440
439
|
"set.appearance.org-theme": "Org default theme",
|
|
441
440
|
"set.editor": "Default IDE",
|
|
441
|
+
"set.editor.open": "Open file links in",
|
|
442
442
|
"set.editor_overrides": "Per-language IDE",
|
|
443
443
|
"set.terminal": "Default terminal",
|
|
444
444
|
"set.shell.pages": "Pages",
|
|
@@ -453,6 +453,7 @@
|
|
|
453
453
|
"set.graph.panelWidth": "Details panel",
|
|
454
454
|
"set.workspace.editor": "IDE for this workspace",
|
|
455
455
|
"set.agents.runtimes": "Runtimes",
|
|
456
|
+
"set.agents.layout": "Agents tab layout",
|
|
456
457
|
"set.cli.local_dev": "Local environment",
|
|
457
458
|
"set.cli.cli_tabs": "Terminal tabs",
|
|
458
459
|
"set.cli.log_window_lines": "Log pane lines",
|
|
@@ -586,6 +587,24 @@
|
|
|
586
587
|
"ag.pal": "Agents › {ws} / {name}",
|
|
587
588
|
"ag.palStart": "Start agent…",
|
|
588
589
|
"ag.cap": "Up to 4 panes: {id}'s closed to make room (it keeps running)",
|
|
590
|
+
// AG-4b: the Agents tab's layouts and named tabs.
|
|
591
|
+
"ag.layout": "Layout",
|
|
592
|
+
"ag.l.focus": "Focus",
|
|
593
|
+
"ag.l.tabs": "Tabs",
|
|
594
|
+
"ag.l.tile": "Tile",
|
|
595
|
+
"ag.l.tip": "{name} ({key})",
|
|
596
|
+
"ag.hint.keys":
|
|
597
|
+
"⌃⇧1 / ⌃⇧2 / ⌃⇧3 switch layout. ⌘-click (Ctrl-click) opens a link or path.",
|
|
598
|
+
"ag.pal.layout": "Layout: {name}",
|
|
599
|
+
"ag.copied": "Copied",
|
|
600
|
+
"ag.tabs": "Open sessions",
|
|
601
|
+
"ag.hint.focus":
|
|
602
|
+
"Click shows one session. Shift- or ⌘-click adds it alongside.",
|
|
603
|
+
"ag.hint.tabs":
|
|
604
|
+
"Click opens a session as a tab. Double-click a tab to rename it.",
|
|
605
|
+
"ag.hint.tile": "Click adds a session as a tile, up to 4.",
|
|
606
|
+
"ag.renameTip": "Double-click to rename",
|
|
607
|
+
"ag.renameName": "Rename {id}",
|
|
589
608
|
"ag.rt.ready": "Starts {name} {version} from",
|
|
590
609
|
"ag.rt.readyNoVer": "Starts {name} from",
|
|
591
610
|
"ag.rt.notFound": "{name} not found.",
|
|
@@ -1722,8 +1741,9 @@
|
|
|
1722
1741
|
/**
|
|
1723
1742
|
* The Workspace part: { label, title, items: [{ value, label, checked,
|
|
1724
1743
|
* focused, title? }], onSelect(value) }. "All active" and the active
|
|
1725
|
-
* workspaces, the focused one
|
|
1726
|
-
*
|
|
1744
|
+
* workspaces, the focused one (model.focus, the CLI default) marked; then
|
|
1745
|
+
* a link to manage them. onSelect(value, focus): choosing a workspace
|
|
1746
|
+
* also makes it the CLI default (header.js).
|
|
1727
1747
|
*/
|
|
1728
1748
|
function setWorkspaces(model) {
|
|
1729
1749
|
var btn = document.getElementById("ws-pill");
|
|
@@ -1748,22 +1768,16 @@
|
|
|
1748
1768
|
tag: it.focused ? t("ws.focus") : null,
|
|
1749
1769
|
title: it.title || null,
|
|
1750
1770
|
onSelect: function () {
|
|
1751
|
-
if (
|
|
1752
|
-
|
|
1771
|
+
if (typeof model.onSelect !== "function") return;
|
|
1772
|
+
// The workspace in view still becomes the CLI default when it
|
|
1773
|
+
// isn't one; picking what is both already does nothing.
|
|
1774
|
+
if (it.checked && (it.value === "all" || it.value === model.focus))
|
|
1775
|
+
return;
|
|
1776
|
+
model.onSelect(it.value, model.focus || null, !!it.checked);
|
|
1753
1777
|
},
|
|
1754
1778
|
});
|
|
1755
1779
|
});
|
|
1756
1780
|
items.push({ hr: true });
|
|
1757
|
-
// Focus is a separate action (it writes workspaces.yml and retargets
|
|
1758
|
-
// the CLI); picking a view above never moves it.
|
|
1759
|
-
if (model.focusable && typeof model.onFocus === "function")
|
|
1760
|
-
items.push({
|
|
1761
|
-
label: t("ws.setFocus", { ws: model.focusable }),
|
|
1762
|
-
title: t("ws.setFocusTip"),
|
|
1763
|
-
onSelect: function () {
|
|
1764
|
-
model.onFocus(model.focusable);
|
|
1765
|
-
},
|
|
1766
|
-
});
|
|
1767
1781
|
items.push({ label: t("ws.manage"), href: navHref("local-dev") });
|
|
1768
1782
|
scopeMenus.ws = { label: t("k.ws"), items: items };
|
|
1769
1783
|
}
|