@monster-orange/den 0.4.11 → 0.4.13

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +169 -0
  2. package/README.md +7 -7
  3. package/docs/distributions.md +212 -12
  4. package/package.json +2 -1
  5. package/src/shared/agents/catalog.ts +77 -0
  6. package/src/shared/agents/default-pack/be-dev.md +1 -0
  7. package/src/shared/agents/default-pack/devops.md +1 -0
  8. package/src/shared/agents/default-pack/fe-dev.md +1 -0
  9. package/src/shared/agents/default-pack/orchestrator.md +3 -1
  10. package/src/shared/agents/default-pack/planner.md +1 -0
  11. package/src/shared/agents/default-pack/reviewer.md +1 -0
  12. package/src/shared/agents/default-pack/tester.md +16 -0
  13. package/src/shared/agents/default-pack/ux-designer.md +1 -0
  14. package/src/shared/agents/den-claude.ts +151 -17
  15. package/src/shared/agents/permissions.ts +108 -0
  16. package/src/shared/agents/persona-store.ts +286 -0
  17. package/src/shared/agents/personas.ts +116 -12
  18. package/src/shared/agents/records.ts +57 -0
  19. package/src/shared/agents/roles.ts +288 -0
  20. package/src/shared/agents/runtime.ts +49 -0
  21. package/src/shared/agents/session-name.ts +110 -0
  22. package/src/shared/agents/transcript-follow.ts +180 -0
  23. package/src/shared/den-config.ts +27 -1
  24. package/src/ui/cli/agent-ops.ts +578 -11
  25. package/src/ui/cli/agents-command.ts +12 -2
  26. package/src/ui/cli/env-probe.ts +4 -1
  27. package/src/ui/mcp/tools.ts +1 -1
  28. package/src/ui/server/agent-paths.ts +52 -0
  29. package/src/ui/server/agent-routes.ts +329 -19
  30. package/src/ui/server/agents-layout-pref.ts +43 -0
  31. package/src/ui/server/editor-open-pref.ts +41 -0
  32. package/src/ui/server/index.ts +22 -0
  33. package/src/ui/server/public/agent-start.js +3 -2
  34. package/src/ui/server/public/agents-page.js +1037 -67
  35. package/src/ui/server/public/agents-section.js +1 -1
  36. package/src/ui/server/public/agents.html +236 -20
  37. package/src/ui/server/public/header.js +2 -0
  38. package/src/ui/server/public/i18n/es.js +139 -0
  39. package/src/ui/server/public/i18n/ja.js +139 -0
  40. package/src/ui/server/public/persona-ui.css +539 -0
  41. package/src/ui/server/public/persona-ui.js +796 -0
  42. package/src/ui/server/public/settings-page.js +4 -9
  43. package/src/ui/server/public/settings-registry.js +66 -0
  44. package/src/ui/server/public/settings.html +1 -0
  45. package/src/ui/server/public/shell.js +137 -0
  46. package/src/ui/server/public/term-input.js +129 -0
  47. package/src/ui/server/public/topbar.js +22 -4
  48. package/src/ui/server/route-classes.ts +29 -0
  49. package/src/ui/server/session-routes.ts +34 -1
  50. package/src/ui/server/ui-assets.ts +8 -0
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Where a file path in an agent's pane opens (AG-4b): ⌘-click (Ctrl-click
3
+ * elsewhere) opens it in this editor by its URL scheme, at the line
4
+ * (vscode://file/…, cursor://file/…, zed://file/…), or, with `none` (the
5
+ * default), copies its absolute path. A person's view preference, stored
6
+ * in the user config as `editor_open` (the `editor` key is already the
7
+ * repo editor's, ↗) and served by /api/settings as `editor_open`. Nothing
8
+ * here runs an editor: the browser hands the URL to the OS.
9
+ */
10
+ import type { UserConfig } from "../../shared/den-config.js";
11
+
12
+ export const EDITOR_OPENS = ["vscode", "cursor", "zed", "none"] as const;
13
+ export type EditorOpen = (typeof EDITOR_OPENS)[number];
14
+ export const EDITOR_OPEN_DEFAULT: EditorOpen = "none";
15
+
16
+ const isEditorOpen = (v: unknown): v is EditorOpen =>
17
+ typeof v === "string" && (EDITOR_OPENS as readonly string[]).includes(v);
18
+
19
+ /** The stored choice, or none when unset or hand-broken. */
20
+ export function editorOpen(user: UserConfig): EditorOpen {
21
+ const v = user.editor_open;
22
+ return isEditorOpen(v) ? v : EDITOR_OPEN_DEFAULT;
23
+ }
24
+
25
+ /**
26
+ * Apply a POSTed `editor_open` to `user` (in place): an editor sets it,
27
+ * null clears it. Anything else: the error to answer with.
28
+ */
29
+ export function patchEditorOpen(
30
+ user: UserConfig,
31
+ v: unknown,
32
+ ): { ok: true } | { ok: false; error: string } {
33
+ if (v !== null && !isEditorOpen(v))
34
+ return {
35
+ ok: false,
36
+ error: `editor_open must be one of ${EDITOR_OPENS.map((e) => `"${e}"`).join(", ")}, or null`,
37
+ };
38
+ if (v === null) delete user.editor_open;
39
+ else user.editor_open = v;
40
+ return { ok: true };
41
+ }
@@ -256,6 +256,8 @@ import {
256
256
  sshTarget,
257
257
  } from "../../shared/cli-command.js";
258
258
  import { graphPrefs, patchStoredGraph } from "./graph-prefs.js";
259
+ import { agentsLayout, patchAgentsLayout } from "./agents-layout-pref.js";
260
+ import { editorOpen, patchEditorOpen } from "./editor-open-pref.js";
259
261
  import { graphPageHtml } from "./graph-page.js";
260
262
  import { mergeShellPrefs, shellPrefs, storedShell } from "./shell-prefs.js";
261
263
  import { distributionSettings, userWebPort } from "./settings-distribution.js";
@@ -4467,6 +4469,10 @@ async function handleRequest(
4467
4469
  // graph: { direction, group, density, panelWidth } (see graph-prefs.ts)
4468
4470
  // appearance: { theme: id | null, mode: system|dark|light } (appearance-prefs.ts)
4469
4471
  // shell: { pins, collapsed, hidden, order, dock, dockHeight } (shell-prefs.ts)
4472
+ // agents_layout: focus | tabs | tile, the Agents tab's layout (AG-4b,
4473
+ // agents-layout-pref.ts; user.yml agents.layout); null clears it
4474
+ // editor_open: vscode | cursor | zed | none, where a path in an agent's
4475
+ // pane opens (AG-4b, editor-open-pref.ts); null clears it (none)
4470
4476
  // language: the UI's language, en | ja | es (ui-language.ts); null or
4471
4477
  // "en" clears it (English is the default)
4472
4478
  // It writes config/local/user.yml only. `distribution` is read-only: what
@@ -4512,6 +4518,8 @@ async function handleRequest(
4512
4518
  graph: graphPrefs(user.graph),
4513
4519
  appearance: appearancePrefs(user.appearance),
4514
4520
  shell: shellPrefs(user.shell),
4521
+ agents_layout: agentsLayout(user),
4522
+ editor_open: editorOpen(user),
4515
4523
  distribution: distributionSettings(getDistRoot()),
4516
4524
  // Set from the command line (`<cli> config`), shown read-only.
4517
4525
  user_web_port: userWebPort(user as Record<string, unknown>),
@@ -4537,8 +4545,20 @@ async function handleRequest(
4537
4545
  shell?: unknown;
4538
4546
  language?: unknown;
4539
4547
  machine_name?: unknown;
4548
+ agents_layout?: unknown;
4549
+ editor_open?: unknown;
4540
4550
  };
4541
4551
  const user = readUserConfig();
4552
+ // AG-4b: the Agents tab's layout, a view preference only.
4553
+ if (body.agents_layout !== undefined) {
4554
+ const l = patchAgentsLayout(user, body.agents_layout);
4555
+ if (!l.ok) return send400(res, l.error);
4556
+ }
4557
+ // AG-4b: where a path link in an agent's pane opens.
4558
+ if (body.editor_open !== undefined) {
4559
+ const e = patchEditorOpen(user, body.editor_open);
4560
+ if (!e.ok) return send400(res, e.error);
4561
+ }
4542
4562
  // SEC-2a: web.machine_name (user.yml); null or "" clears it.
4543
4563
  if (body.machine_name !== undefined) {
4544
4564
  let name: string | null;
@@ -4648,6 +4668,8 @@ async function handleRequest(
4648
4668
  shell: shellPrefs(user.shell),
4649
4669
  language: uiLanguage(user.language),
4650
4670
  machine_name: machineNameSetting(user),
4671
+ agents_layout: agentsLayout(user),
4672
+ editor_open: editorOpen(user),
4651
4673
  });
4652
4674
  } catch (e) {
4653
4675
  return send400(res, `Invalid request: ${(e as Error).message}`);
@@ -37,9 +37,10 @@ export function personaOptions(personas) {
37
37
  .join("");
38
38
  }
39
39
 
40
- /** The help line under the persona select: the picked persona's role. */
40
+ /** The help line under the persona select: the picked persona's description. */
41
41
  export function personaHelp(personas, id) {
42
- return (personas ?? []).find((p) => p.id === id)?.role ?? "";
42
+ const p = (personas ?? []).find((x) => x.id === id);
43
+ return p?.description ?? p?.role ?? "";
43
44
  }
44
45
 
45
46
  /** A runtime's name for people ("Claude Code"); its id when it has none. */