@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
|
@@ -24,8 +24,10 @@
|
|
|
24
24
|
* running: a new session, in the same cwd, continuing the last run;
|
|
25
25
|
* when that session was never prompted, a fresh start under the
|
|
26
26
|
* same conversation id (there is nothing to continue).
|
|
27
|
-
* doctor (AG-0.3) each runtime
|
|
28
|
-
*
|
|
27
|
+
* doctor (AG-0.3, AG-0.5) each runtime of the catalog, installed
|
|
28
|
+
* first: its status, the CLI it runs and where that came from
|
|
29
|
+
* (workspace or user.yml setting, login shell, PATH, install
|
|
30
|
+
* directory, interactive shell), its
|
|
29
31
|
* version (its version command, once, under a timeout), the
|
|
30
32
|
* directories searched (names only, never an env value), and the
|
|
31
33
|
* fix when it is missing. Exit 1 when the default runtime is
|
|
@@ -88,16 +90,20 @@ export const AGENTS_HELP = {
|
|
|
88
90
|
" a session never prompted starts fresh under the same conversation id",
|
|
89
91
|
"{cli} agents personas [--json]",
|
|
90
92
|
" Den's default pack, then agents.persona_packs (a later pack wins by id)",
|
|
91
|
-
"{cli} agents doctor [--json]",
|
|
92
|
-
" each runtime: status, the CLI it runs and where it came
|
|
93
|
-
" the directories searched, and the fix; exit 1 when the
|
|
93
|
+
"{cli} agents doctor [-w <ws>] [--json]",
|
|
94
|
+
" each runtime, installed first: status, the CLI it runs and where it came",
|
|
95
|
+
" from, its version, the directories searched, and the fix; exit 1 when the",
|
|
96
|
+
" default is missing. -w: as that workspace's agents find them",
|
|
94
97
|
"",
|
|
95
|
-
"Runtimes: den-claude (default; Claude Code's claude)
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
98
|
+
"Runtimes: den-claude (default; Claude Code's claude), codex (OpenAI's Codex",
|
|
99
|
+
"CLI), gemini (Google's Gemini CLI), grok (xAI's Grok Build), and generic (the",
|
|
100
|
+
"persona's argv template). codex, gemini and grok run as their own CLI in the",
|
|
101
|
+
"workspace, without Den's tools yet. Attach with `{cli} sessions attach <ws>:<id>`.",
|
|
102
|
+
"A runtime's CLI is found as your terminal finds it: <ws>.agents.runtimes.<id>.bin",
|
|
103
|
+
"in config/local/workspaces.yml, then agents.runtimes.<id>.bin in",
|
|
104
|
+
"config/local/user.yml (absolute paths), then the login shell's PATH, this PATH,",
|
|
105
|
+
"its install directories (~/.local/bin, /opt/homebrew/bin, /usr/local/bin, npm's",
|
|
106
|
+
"global bin, the vendor's own), and last the interactive shell's PATH.",
|
|
101
107
|
"An agent's env is PATH, HOME, USER, LOGNAME, SHELL, TERM, COLORTERM, LANG,",
|
|
102
108
|
"LC_*, TZ and TMPDIR, plus what its runtime declares: nothing else of yours.",
|
|
103
109
|
],
|
|
@@ -273,10 +279,12 @@ export interface AgentsDoctorDeps {
|
|
|
273
279
|
}
|
|
274
280
|
|
|
275
281
|
const SOURCE_WORD: Record<string, string> = {
|
|
282
|
+
workspace: "the workspace's agents.runtimes setting",
|
|
276
283
|
setting: "agents.runtimes setting",
|
|
277
284
|
"login-shell": "login shell PATH",
|
|
278
285
|
PATH: "PATH",
|
|
279
286
|
"well-known": "install directory",
|
|
287
|
+
"interactive-shell": "interactive shell PATH",
|
|
280
288
|
};
|
|
281
289
|
|
|
282
290
|
/** `agents doctor`'s lines for one runtime (names and paths, never env values). */
|
|
@@ -284,9 +292,11 @@ export function doctorLines(
|
|
|
284
292
|
r: RuntimeChoice,
|
|
285
293
|
cli: string,
|
|
286
294
|
userConfig: string,
|
|
295
|
+
/** Directory lists already printed (a repeat is counted, not listed). */
|
|
296
|
+
printed: string[] = [],
|
|
287
297
|
): string[] {
|
|
288
298
|
const lines = [
|
|
289
|
-
`${r.id}${r.label ? ` (${r.label})` : ""}${r.default ? " [default]" : ""}`,
|
|
299
|
+
`${r.id}${r.label ? ` (${r.label}${r.vendor ? `, ${r.vendor}` : ""})` : ""}${r.default ? " [default]" : ""}${r.denTools === false ? " [Den tools: coming]" : ""}`,
|
|
290
300
|
r.available
|
|
291
301
|
? " status ✓ available"
|
|
292
302
|
: ` status ✗ unavailable: ${r.why ?? "unknown"}`,
|
|
@@ -298,11 +308,19 @@ export function doctorLines(
|
|
|
298
308
|
if (r.available && r.setting)
|
|
299
309
|
lines.push(` version ${r.version ?? "unknown"}`);
|
|
300
310
|
if (!r.setting) lines.push(" path none to find (the persona's argv)");
|
|
301
|
-
else if (r.searched?.length)
|
|
302
|
-
r.searched.
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
311
|
+
else if (r.searched?.length) {
|
|
312
|
+
const key = r.searched.join("\0");
|
|
313
|
+
if (printed.includes(key))
|
|
314
|
+
lines.push(
|
|
315
|
+
` searched the same ${r.searched.length} ${r.searched.length === 1 ? "directory" : "directories"} as above`,
|
|
316
|
+
);
|
|
317
|
+
else {
|
|
318
|
+
printed.push(key);
|
|
319
|
+
r.searched.forEach((dir, i) =>
|
|
320
|
+
lines.push(` ${i === 0 ? "searched " : " "}${dir}`),
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
} else if (r.source !== "setting") lines.push(" searched (no directories)");
|
|
306
324
|
if (!r.available && r.setting)
|
|
307
325
|
lines.push(
|
|
308
326
|
` fix install ${r.label ?? r.id}, or set ${r.setting} to its absolute path in ${userConfig}`,
|
|
@@ -317,25 +335,34 @@ async function doctor(
|
|
|
317
335
|
deps: AgentsDoctorDeps,
|
|
318
336
|
): Promise<number> {
|
|
319
337
|
const where = "agents doctor";
|
|
320
|
-
const p = parseArgs(where, args, { "--json": false });
|
|
338
|
+
const p = parseArgs(where, args, { "--workspace": true, "--json": false });
|
|
321
339
|
noExtra(where, p);
|
|
340
|
+
const ws = workspaceFlag(where, p);
|
|
341
|
+
if (ws && !d.workspaceExists(ws))
|
|
342
|
+
throw new UsageError(`${where}: workspace "${ws}" does not exist`);
|
|
322
343
|
await (deps.loginPath ?? (() => initLoginPath({ env: d.env })))();
|
|
323
|
-
const rts = await listRuntimes(d);
|
|
344
|
+
const rts = await listRuntimes(d, ws);
|
|
324
345
|
const def = rts.find((r) => r.default);
|
|
325
346
|
const code = def?.available ? 0 : 1;
|
|
326
347
|
if (p.flags["--json"]) {
|
|
327
348
|
d.out(
|
|
328
349
|
JSON.stringify(
|
|
329
|
-
{
|
|
350
|
+
{
|
|
351
|
+
runtimes: rts,
|
|
352
|
+
...(ws ? { workspace: ws } : {}),
|
|
353
|
+
userConfig: d.userConfigFile(),
|
|
354
|
+
},
|
|
330
355
|
null,
|
|
331
356
|
2,
|
|
332
357
|
),
|
|
333
358
|
);
|
|
334
359
|
return code;
|
|
335
360
|
}
|
|
361
|
+
const printed: string[] = [];
|
|
336
362
|
rts.forEach((r, i) => {
|
|
337
363
|
if (i) d.out("");
|
|
338
|
-
for (const l of doctorLines(r, d.cli, d.userConfigFile()))
|
|
364
|
+
for (const l of doctorLines(r, d.cli, d.userConfigFile(), printed))
|
|
365
|
+
d.out(l);
|
|
339
366
|
});
|
|
340
367
|
d.out("");
|
|
341
368
|
d.out(
|
|
@@ -369,6 +396,8 @@ export async function cmdAgents(
|
|
|
369
396
|
case "personas":
|
|
370
397
|
return await listPersonas(rest, d);
|
|
371
398
|
case "doctor":
|
|
399
|
+
// -w checks the workspace exists, and reads its runtime paths.
|
|
400
|
+
await loadAgentWorkspaces(deps);
|
|
372
401
|
return await doctor(rest, d, deps);
|
|
373
402
|
default:
|
|
374
403
|
throw new UsageError(`unknown agents command "${sub}"`);
|
|
@@ -25,7 +25,11 @@ import {
|
|
|
25
25
|
routerUrls,
|
|
26
26
|
type IncludedRouter,
|
|
27
27
|
} from "../../shared/edge/included.js";
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
edgeRoutes,
|
|
30
|
+
edgeStatus,
|
|
31
|
+
withHttpsServing,
|
|
32
|
+
} from "../../shared/edge/status.js";
|
|
29
33
|
import { tlsYaml } from "../../shared/edge/tls.js";
|
|
30
34
|
import { rejoinRunningStacks } from "../../shared/stacks/status.js";
|
|
31
35
|
|
|
@@ -102,7 +106,7 @@ export async function cmdEdge(args: string[]): Promise<void> {
|
|
|
102
106
|
return;
|
|
103
107
|
}
|
|
104
108
|
case "status": {
|
|
105
|
-
const st = edgeStatus(cfg);
|
|
109
|
+
const st = await withHttpsServing(edgeStatus(cfg), cfg);
|
|
106
110
|
console.log(chalk.bold(`${readBrand().name} edge — ${st.org}`));
|
|
107
111
|
console.log(` container ${st.container}: ${st.state}`);
|
|
108
112
|
console.log(` ports ${published}`);
|
|
@@ -116,7 +120,16 @@ export async function cmdEdge(args: string[]): Promise<void> {
|
|
|
116
120
|
// browser trust (BOOT-1), so this machine's trust is moot.
|
|
117
121
|
` CA ${caDir(cfg)} — ${!st.ports ? "not needed: fronted" : st.caTrusted === null ? "unknown" : st.caTrusted ? "trusted" : "NOT trusted"}`,
|
|
118
122
|
);
|
|
119
|
-
if (st.
|
|
123
|
+
if (st.certIssuedByDen)
|
|
124
|
+
console.log(` cert ${st.certNames.join(", ")}`);
|
|
125
|
+
else if (st.https.certs === "distribution")
|
|
126
|
+
console.log(
|
|
127
|
+
" cert the distribution's (tls: files): not minted by Den",
|
|
128
|
+
);
|
|
129
|
+
// MCP-2.5: whether HTTPS is actually serving, not only configured.
|
|
130
|
+
console.log(
|
|
131
|
+
` https ${st.https.serving === null ? "not probed" : st.https.serving ? "serving" : "NOT serving"} — ${st.https.detail}`,
|
|
132
|
+
);
|
|
120
133
|
return;
|
|
121
134
|
}
|
|
122
135
|
default:
|
|
@@ -179,7 +179,7 @@ function validateFlagScopes(parsed: ParsedCliArgs): void {
|
|
|
179
179
|
*/
|
|
180
180
|
export const SUBCOMMAND_OWN_HELP: Readonly<Record<string, readonly string[]>> =
|
|
181
181
|
{
|
|
182
|
-
web: ["token", "login", "sessions", "logout"],
|
|
182
|
+
web: ["token", "login", "sessions", "logout", "owner", "approve"],
|
|
183
183
|
mcp: ["connect", "disconnect", "clients", "config"],
|
|
184
184
|
};
|
|
185
185
|
|
|
@@ -77,11 +77,14 @@ export function formatRollupLabel(r: RepoRollup): string {
|
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
79
|
* Why, for a repo row: the down services ("mailpit down"), and how many
|
|
80
|
-
* services aren't checked ("25 not checked")
|
|
80
|
+
* services aren't checked ("25 not checked"), and how many answered with a
|
|
81
|
+
* redirect ("1 redirect": answering, so neither down nor unchecked).
|
|
82
|
+
* Unchecked never means down.
|
|
81
83
|
*/
|
|
82
84
|
export function rollupReasonText(r: RepoRollup): string {
|
|
83
85
|
return [
|
|
84
86
|
r.down.length ? `${r.down.join(", ")} down` : "",
|
|
87
|
+
r.redirected ? `${r.redirected} redirect` : "",
|
|
85
88
|
r.unchecked ? `${r.unchecked} not checked` : "",
|
|
86
89
|
]
|
|
87
90
|
.filter(Boolean)
|