proteum 2.3.0 → 2.4.2
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/AGENTS.md +8 -3
- package/README.md +20 -15
- package/agents/project/AGENTS.md +16 -10
- package/agents/project/DOCUMENTATION.md +1326 -0
- package/agents/project/app-root/AGENTS.md +2 -2
- package/agents/project/diagnostics.md +10 -9
- package/agents/project/optimizations.md +1 -1
- package/agents/project/root/AGENTS.md +15 -8
- package/agents/project/server/services/AGENTS.md +1 -0
- package/agents/project/tests/AGENTS.md +1 -0
- package/cli/commands/db.ts +160 -0
- package/cli/commands/dev.ts +148 -25
- package/cli/commands/diagnose.ts +2 -0
- package/cli/commands/explain.ts +38 -9
- package/cli/commands/mcp.ts +126 -9
- package/cli/commands/orient.ts +44 -17
- package/cli/commands/runtime.ts +100 -17
- package/cli/mcp/router.ts +1028 -0
- package/cli/presentation/commands.ts +56 -25
- package/cli/presentation/help.ts +1 -1
- package/cli/runtime/commands.ts +163 -21
- package/cli/runtime/devSessions.ts +328 -2
- package/cli/runtime/mcpDaemon.ts +288 -0
- package/cli/runtime/ports.ts +151 -0
- package/cli/utils/agents.ts +94 -17
- package/cli/utils/appRoots.ts +232 -0
- package/common/dev/database.ts +226 -0
- package/common/dev/diagnostics.ts +1 -1
- package/common/dev/inspection.ts +8 -1
- package/common/dev/mcpPayloads.ts +456 -17
- package/common/dev/mcpServer.ts +51 -0
- package/docs/agent-routing.md +32 -21
- package/docs/dev-commands.md +1 -1
- package/docs/dev-sessions.md +3 -1
- package/docs/diagnostics.md +21 -20
- package/docs/mcp.md +114 -50
- package/docs/migrate-from-2.1.3.md +3 -5
- package/docs/request-tracing.md +3 -3
- package/package.json +10 -3
- package/server/app/devDiagnostics.ts +92 -0
- package/server/app/devMcp.ts +55 -0
- package/server/services/prisma/mariadb.ts +7 -3
- package/server/services/router/http/index.ts +25 -0
- package/server/services/router/request/ip.test.cjs +0 -1
- package/tests/agents-utils.test.cjs +58 -3
- package/tests/cli-mcp-command.test.cjs +327 -0
- package/tests/codex-mcp-usage.test.cjs +307 -0
- package/tests/dev-sessions.test.cjs +113 -0
- package/tests/dev-transpile-watch.test.cjs +0 -1
- package/tests/eslint-rules.test.cjs +0 -1
- package/tests/inspection.test.cjs +0 -1
- package/tests/mcp.test.cjs +769 -2
- package/tests/router-cache-config.test.cjs +0 -1
- package/vitest.config.mjs +9 -0
- package/cli/mcp/provider.ts +0 -365
- package/cli/mcp/stdio.ts +0 -16
|
@@ -21,6 +21,7 @@ export const proteumCommandNames = [
|
|
|
21
21
|
'orient',
|
|
22
22
|
'diagnose',
|
|
23
23
|
'perf',
|
|
24
|
+
'db',
|
|
24
25
|
'runtime',
|
|
25
26
|
'mcp',
|
|
26
27
|
'trace',
|
|
@@ -59,7 +60,7 @@ export const proteumRecommendedFlow: TRow[] = [
|
|
|
59
60
|
export const proteumCommandGroups: Array<{ title: string; names: TProteumCommandName[] }> = [
|
|
60
61
|
{ title: 'Daily workflow', names: ['dev', 'refresh', 'build'] },
|
|
61
62
|
{ title: 'Quality gates', names: ['typecheck', 'lint', 'check', 'e2e'] },
|
|
62
|
-
{ title: 'Manifest and contracts', names: ['connect', 'doctor', 'explain', 'orient', 'diagnose', 'perf', 'runtime', 'mcp', 'trace', 'command', 'session', 'verify'] },
|
|
63
|
+
{ title: 'Manifest and contracts', names: ['connect', 'doctor', 'explain', 'orient', 'diagnose', 'perf', 'db', 'runtime', 'mcp', 'trace', 'command', 'session', 'verify'] },
|
|
63
64
|
{ title: 'Project scaffolding', names: ['init', 'configure', 'create', 'migrate'] },
|
|
64
65
|
];
|
|
65
66
|
|
|
@@ -128,7 +129,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
128
129
|
notes: [
|
|
129
130
|
'This command is interactive. It asks whether the current Proteum app belongs to a monorepo and, if so, which ancestor path should receive the reusable root instruction files.',
|
|
130
131
|
'Standalone mode writes tracked instruction files into the current Proteum app root.',
|
|
131
|
-
'Monorepo mode writes reusable root documents such as `AGENTS.md`, `CODING_STYLE.md`, `diagnostics.md`, and `optimizations.md` into the chosen monorepo root, then writes only app-root and area instruction files into the current Proteum app root.',
|
|
132
|
+
'Monorepo mode writes reusable root documents such as `AGENTS.md`, `DOCUMENTATION.md`, `CODING_STYLE.md`, `diagnostics.md`, and `optimizations.md` into the chosen monorepo root, then writes only app-root and area instruction files into the current Proteum app root.',
|
|
132
133
|
'Every managed instruction file contains a `# Proteum Instructions` section with the full embedded Proteum project instruction corpus.',
|
|
133
134
|
'Existing content outside `# Proteum Instructions` is preserved. Directories and foreign symlinks are replaced only after confirmation.',
|
|
134
135
|
],
|
|
@@ -170,11 +171,14 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
170
171
|
{ description: 'Start the app on its configured router port', command: 'proteum dev' },
|
|
171
172
|
{
|
|
172
173
|
description: 'Start a worktree or sibling checkout without changing your shell directory',
|
|
173
|
-
command: 'proteum dev --cwd /path/to/platform-worktree --port 3101
|
|
174
|
+
command: 'proteum dev --cwd /path/to/platform-worktree --port 3101',
|
|
174
175
|
},
|
|
175
|
-
{ description: 'Replace the tracked dev session on another port', command: 'proteum dev --port 3101 --replace-existing' },
|
|
176
176
|
{
|
|
177
177
|
description: 'Start a tracked dev session with an explicit session file for an agent task',
|
|
178
|
+
command: 'proteum dev --port 3101 --session-file var/run/proteum/dev/agents/task.json',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
description: 'Restart the exact tracked session file from the current task',
|
|
178
182
|
command: 'proteum dev --port 3101 --session-file var/run/proteum/dev/agents/task.json --replace-existing',
|
|
179
183
|
},
|
|
180
184
|
{
|
|
@@ -193,8 +197,9 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
193
197
|
notes: [
|
|
194
198
|
'Use `--cwd` when the target Proteum app lives in another worktree or checkout and you do not want to `cd` first.',
|
|
195
199
|
'Proteum writes a machine-readable dev session file under `var/run/proteum/dev/<port>.json` by default; override it with `--session-file` when an agent needs a stable path.',
|
|
200
|
+
'Before registering a new session, Proteum removes stale same-worktree session files and fails fast if another live tracked session remains.',
|
|
196
201
|
'Before the dev loop starts, Proteum ensures tracked instruction files contain the current managed `# Proteum Instructions` section.',
|
|
197
|
-
'Use `--replace-existing` when
|
|
202
|
+
'Use `--replace-existing` only when retrying the exact requested session file.',
|
|
198
203
|
'`proteum dev list` inspects tracked sessions for the current app root. Add `--stale` to show only orphaned or dead sessions.',
|
|
199
204
|
'`proteum dev stop` targets the current session file by default. Add `--all` to stop every tracked session for the current app root.',
|
|
200
205
|
'`proteum dev` clears the interactive terminal once at startup, then shows `CTRL+R` reload and `CTRL+C` shutdown hotkeys in the session banner.',
|
|
@@ -359,11 +364,15 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
359
364
|
examples: [
|
|
360
365
|
{ description: 'Show the default compact agent summary', command: 'proteum explain' },
|
|
361
366
|
{
|
|
362
|
-
description: '
|
|
367
|
+
description: 'Summarize generated routes, controllers, and commands together',
|
|
363
368
|
command: 'proteum explain --routes --controllers --commands',
|
|
364
369
|
},
|
|
365
370
|
{
|
|
366
|
-
description: '
|
|
371
|
+
description: 'Emit selected route/controller/command arrays only when needed',
|
|
372
|
+
command: 'proteum explain --routes --controllers --commands --full',
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
description: 'Summarize configured connected projects and imported controllers',
|
|
367
376
|
command: 'proteum explain --connected --controllers',
|
|
368
377
|
},
|
|
369
378
|
{ description: 'Resolve the most likely manifest owner for a path or file', command: 'proteum explain owner /api/Auth/CurrentUser' },
|
|
@@ -371,7 +380,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
371
380
|
],
|
|
372
381
|
notes: [
|
|
373
382
|
'Default output is compact `proteum-agent-v1` JSON because the CLI is optimized for agents.',
|
|
374
|
-
'
|
|
383
|
+
'Explicit section flags summarize those sections by default; add `--full` or use `--manifest` for raw manifest arrays.',
|
|
375
384
|
'Legacy positional section selection remains supported, for example `proteum explain routes services`.',
|
|
376
385
|
'`proteum explain owner <query>` ranks matching routes, controllers, services, commands, layouts, and diagnostics from the manifest.',
|
|
377
386
|
'Connected projects are emitted from explicit `proteum.config.ts` `connect.<Namespace>.*` values plus the resolved connected contract.',
|
|
@@ -391,7 +400,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
391
400
|
{ description: 'Use a running dev server when the local manifest is unavailable', command: 'proteum orient /domains --port 3101' },
|
|
392
401
|
],
|
|
393
402
|
notes: [
|
|
394
|
-
'Default output is compact `proteum-agent-v1` JSON with `mustRead`, conditional docs, owner matches, and next commands.',
|
|
403
|
+
'Default output is compact `proteum-agent-v1` JSON with `mustRead`, triggered instruction files, conditional docs, owner matches, and next commands.',
|
|
395
404
|
'Use it before reading source when the query might map to generated code, connected imports, framework-owned files, or area instructions.',
|
|
396
405
|
'When `--port` or `--url` is provided, Proteum can read the manifest from a running dev server instead of only from disk.',
|
|
397
406
|
],
|
|
@@ -444,6 +453,26 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
444
453
|
],
|
|
445
454
|
status: 'experimental',
|
|
446
455
|
},
|
|
456
|
+
db: {
|
|
457
|
+
name: 'db',
|
|
458
|
+
category: 'Manifest and contracts',
|
|
459
|
+
summary: 'Run one capped read-only database diagnostic query against a running Proteum dev server.',
|
|
460
|
+
usage: 'proteum db [query] <sql> [--limit <rows>] [--timeout <ms>] [--port <port>|--url <baseUrl>] [--full]',
|
|
461
|
+
bestFor:
|
|
462
|
+
'Inspecting live MySQL or MariaDB state during diagnosis without giving agents a write-capable SQL execution surface.',
|
|
463
|
+
examples: [
|
|
464
|
+
{ description: 'Run a small SELECT diagnostic', command: 'proteum db query "SELECT id, email FROM User LIMIT 5"' },
|
|
465
|
+
{ description: 'Inspect table metadata', command: 'proteum db "SHOW TABLES"' },
|
|
466
|
+
{ description: 'Explain a query plan', command: 'proteum db query "EXPLAIN SELECT * FROM User WHERE id = 1"' },
|
|
467
|
+
],
|
|
468
|
+
notes: [
|
|
469
|
+
'Only SELECT, SHOW, and EXPLAIN statements are allowed.',
|
|
470
|
+
'The dev runtime executes the query with the app DATABASE_URL and returns rows, columns, elapsedMs, and cap metadata.',
|
|
471
|
+
'Multi-statement SQL, EXPLAIN ANALYZE, locking reads, LOAD_FILE, SELECT INTO OUTFILE, sleep, and benchmark functions are rejected.',
|
|
472
|
+
'Default output is compact `proteum-agent-v1` JSON with capped rows; use `--full` for the raw dev endpoint payload.',
|
|
473
|
+
],
|
|
474
|
+
status: 'experimental',
|
|
475
|
+
},
|
|
447
476
|
runtime: {
|
|
448
477
|
name: 'runtime',
|
|
449
478
|
category: 'Manifest and contracts',
|
|
@@ -457,6 +486,10 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
457
486
|
],
|
|
458
487
|
notes: [
|
|
459
488
|
'Default output is compact `proteum-agent-v1` JSON with the selected session, health, and next command.',
|
|
489
|
+
'When no tracked session exists, the configured router and HMR ports are inspected before suggesting Start Dev.',
|
|
490
|
+
'If the same app already responds on the configured port, the next action uses or repairs that runtime instead of starting a second server.',
|
|
491
|
+
'The selected live session includes its dev-hosted MCP URL when available.',
|
|
492
|
+
'Use this command instead of curling page routes to identify port ownership.',
|
|
460
493
|
'Use `--full` to include every tracked session field.',
|
|
461
494
|
],
|
|
462
495
|
status: 'experimental',
|
|
@@ -464,26 +497,24 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
464
497
|
mcp: {
|
|
465
498
|
name: 'mcp',
|
|
466
499
|
category: 'Manifest and contracts',
|
|
467
|
-
summary: 'Start
|
|
468
|
-
usage: 'proteum mcp [
|
|
500
|
+
summary: 'Start or attach to the machine-scope MCP router for live Proteum dev projects.',
|
|
501
|
+
usage: 'proteum mcp [status|stop] [--stdio|--daemon] [--port <port>]',
|
|
469
502
|
bestFor:
|
|
470
|
-
'
|
|
503
|
+
'Registering a single MCP server in an LLM and keeping one managed machine daemon available while dev servers run.',
|
|
471
504
|
examples: [
|
|
472
|
-
{ description: 'Start the
|
|
473
|
-
{
|
|
474
|
-
|
|
475
|
-
command: 'proteum mcp --url http://localhost:3101',
|
|
476
|
-
},
|
|
477
|
-
{
|
|
478
|
-
description: 'Resolve runtime data from an explicit tracked session file',
|
|
479
|
-
command: 'proteum mcp --session-file var/run/proteum/dev/agents/task.json',
|
|
480
|
-
},
|
|
505
|
+
{ description: 'Start or reuse the managed machine MCP daemon from a terminal', command: 'proteum mcp' },
|
|
506
|
+
{ description: 'Force stdio MCP transport for an MCP client', command: 'proteum mcp --stdio' },
|
|
507
|
+
{ description: 'Inspect the managed machine MCP daemon', command: 'proteum mcp status' },
|
|
481
508
|
],
|
|
482
509
|
notes: [
|
|
483
|
-
'`proteum
|
|
484
|
-
'
|
|
485
|
-
'
|
|
486
|
-
'
|
|
510
|
+
'`proteum dev` ensures one managed machine MCP daemon is running before the app dev loop starts.',
|
|
511
|
+
'`proteum mcp` is a router, not an app dev server. It discovers live `proteum dev` sessions from the machine registry and can resolve offline app candidates from `cwd`.',
|
|
512
|
+
'Agents should call MCP `workflow_start` with `cwd` or a known `projectId`; use `project_resolve { cwd }` when routing is ambiguous or no live dev server exists yet.',
|
|
513
|
+
'When an offline app candidate is returned, start exactly one `proteum dev` from that app root before runtime diagnose, trace, or perf reads.',
|
|
514
|
+
'After an MCP read succeeds, agents should not run the equivalent CLI command or broad owner search for the same runtime state.',
|
|
515
|
+
'App runtime data still comes from the selected dev-hosted `/__proteum/mcp` endpoint.',
|
|
516
|
+
'Only one managed machine MCP daemon may run at a time; stale daemon records are cleaned automatically.',
|
|
517
|
+
'MCP remains read-only and optimized for compact `proteum-mcp-v1` payloads.',
|
|
487
518
|
],
|
|
488
519
|
status: 'experimental',
|
|
489
520
|
},
|
package/cli/presentation/help.ts
CHANGED
|
@@ -174,7 +174,7 @@ export const renderCommandHelp = async ({
|
|
|
174
174
|
const notes = [...(command.notes ?? [])];
|
|
175
175
|
|
|
176
176
|
if (commandName === 'init') notes.push(getInitAvailabilityNote(initAvailable));
|
|
177
|
-
if (commandName !== 'init' && !isLikelyProteumAppRoot(workdir)) {
|
|
177
|
+
if (commandName !== 'init' && commandName !== 'mcp' && !isLikelyProteumAppRoot(workdir)) {
|
|
178
178
|
notes.push(
|
|
179
179
|
'This command expects to run inside a Proteum app root. The current directory does not contain the usual `client/` and `server/` folders.',
|
|
180
180
|
);
|
package/cli/runtime/commands.ts
CHANGED
|
@@ -1,8 +1,72 @@
|
|
|
1
1
|
import { Builtins, Cli, Option } from 'clipanion';
|
|
2
|
+
import path from 'path';
|
|
2
3
|
|
|
3
|
-
import
|
|
4
|
+
import cli, { type TArgsObject } from '../context';
|
|
4
5
|
import { applyLegacyBooleanArgs, assertNoLegacyArgs } from './argv';
|
|
5
6
|
import { buildUsage, ProteumCommand, runCommandModule } from './command';
|
|
7
|
+
import { createStartDevCommand, quoteShellPath, resolveProteumAppRootContext } from '../utils/appRoots';
|
|
8
|
+
import { printJson } from '../utils/agentOutput';
|
|
9
|
+
|
|
10
|
+
const createRunInAppCommand = ({
|
|
11
|
+
appRoot,
|
|
12
|
+
baseRoot,
|
|
13
|
+
command,
|
|
14
|
+
}: {
|
|
15
|
+
appRoot: string;
|
|
16
|
+
baseRoot: string;
|
|
17
|
+
command: string;
|
|
18
|
+
}) => {
|
|
19
|
+
const relativeAppRoot = path.relative(baseRoot, appRoot) || '.';
|
|
20
|
+
if (relativeAppRoot === '.') return command;
|
|
21
|
+
return `cd ${quoteShellPath(relativeAppRoot)} && ${command}`;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const printNonAppRootResponse = ({
|
|
25
|
+
commandName,
|
|
26
|
+
cwd,
|
|
27
|
+
}: {
|
|
28
|
+
commandName: 'dev' | 'runtime';
|
|
29
|
+
cwd: string;
|
|
30
|
+
}) => {
|
|
31
|
+
const context = resolveProteumAppRootContext(cwd);
|
|
32
|
+
const appCandidates = context.appCandidates;
|
|
33
|
+
const commandLabel = commandName === 'dev' ? 'Dev' : 'Runtime Status';
|
|
34
|
+
|
|
35
|
+
printJson({
|
|
36
|
+
ok: false,
|
|
37
|
+
format: 'proteum-agent-v1',
|
|
38
|
+
summary:
|
|
39
|
+
appCandidates.length > 0
|
|
40
|
+
? `${cwd} is a Proteum workspace wrapper or nested directory, not an app root. Found ${appCandidates.length} app candidate${appCandidates.length === 1 ? '' : 's'}.`
|
|
41
|
+
: `${cwd} is not a Proteum app root.`,
|
|
42
|
+
data: {
|
|
43
|
+
cwd: context.cwd,
|
|
44
|
+
appCandidates,
|
|
45
|
+
},
|
|
46
|
+
nextActions: appCandidates.map((candidate) => ({
|
|
47
|
+
label: `${commandLabel}: ${candidate.relativeAppRoot || candidate.appRoot}`,
|
|
48
|
+
command:
|
|
49
|
+
commandName === 'dev'
|
|
50
|
+
? createStartDevCommand({
|
|
51
|
+
appRoot: candidate.appRoot,
|
|
52
|
+
baseRoot: context.cwd,
|
|
53
|
+
port: candidate.manifest?.routerPort,
|
|
54
|
+
})
|
|
55
|
+
: createRunInAppCommand({
|
|
56
|
+
appRoot: candidate.appRoot,
|
|
57
|
+
baseRoot: context.cwd,
|
|
58
|
+
command: 'npx proteum runtime status',
|
|
59
|
+
}),
|
|
60
|
+
reason:
|
|
61
|
+
commandName === 'dev'
|
|
62
|
+
? 'Start Proteum dev from the app root, not the workspace wrapper.'
|
|
63
|
+
: 'Inspect tracked runtime sessions from the app root, not the workspace wrapper.',
|
|
64
|
+
})),
|
|
65
|
+
});
|
|
66
|
+
process.exitCode = 1;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const isCurrentWorkdirProteumAppRoot = () => resolveProteumAppRootContext(String(cli.args.workdir || process.cwd())).isAppRoot;
|
|
6
70
|
|
|
7
71
|
class InitCommand extends ProteumCommand {
|
|
8
72
|
public static paths = [['init']];
|
|
@@ -154,6 +218,10 @@ class DevCommand extends ProteumCommand {
|
|
|
154
218
|
all: this.all,
|
|
155
219
|
stale: this.stale,
|
|
156
220
|
});
|
|
221
|
+
if (!isCurrentWorkdirProteumAppRoot()) {
|
|
222
|
+
printNonAppRootResponse({ commandName: 'dev', cwd: String(cli.args.workdir || process.cwd()) });
|
|
223
|
+
return 1;
|
|
224
|
+
}
|
|
157
225
|
await runCommandModule(() => import('../commands/dev'));
|
|
158
226
|
}
|
|
159
227
|
}
|
|
@@ -371,18 +439,18 @@ class ExplainCommand extends ProteumCommand {
|
|
|
371
439
|
public full = Option.Boolean('--full', false, { description: 'Print the full selected machine-readable detail.' });
|
|
372
440
|
public human = Option.Boolean('--human', false, { description: 'Print the legacy human-readable report.' });
|
|
373
441
|
public manifest = Option.Boolean('--manifest', false, { description: 'Print the full generated manifest.' });
|
|
374
|
-
public all = Option.Boolean('--all', false, { description: '
|
|
375
|
-
public app = Option.Boolean('--app', false, { description: '
|
|
376
|
-
public conventions = Option.Boolean('--conventions', false, { description: '
|
|
377
|
-
public env = Option.Boolean('--env', false, { description: '
|
|
378
|
-
public connected = Option.Boolean('--connected', false, { description: '
|
|
379
|
-
public services = Option.Boolean('--services', false, { description: '
|
|
380
|
-
public controllers = Option.Boolean('--controllers', false, { description: '
|
|
381
|
-
public commands = Option.Boolean('--commands', false, { description: '
|
|
382
|
-
public routes = Option.Boolean('--routes', false, { description: '
|
|
383
|
-
public layouts = Option.Boolean('--layouts', false, { description: '
|
|
442
|
+
public all = Option.Boolean('--all', false, { description: 'Summarize every explain section; add --full for raw arrays.' });
|
|
443
|
+
public app = Option.Boolean('--app', false, { description: 'Summarize the app section; add --full for raw detail.' });
|
|
444
|
+
public conventions = Option.Boolean('--conventions', false, { description: 'Summarize the conventions section; add --full for raw detail.' });
|
|
445
|
+
public env = Option.Boolean('--env', false, { description: 'Summarize the env section; add --full for raw detail.' });
|
|
446
|
+
public connected = Option.Boolean('--connected', false, { description: 'Summarize the connected-projects section; add --full for raw detail.' });
|
|
447
|
+
public services = Option.Boolean('--services', false, { description: 'Summarize the services section; add --full for raw detail.' });
|
|
448
|
+
public controllers = Option.Boolean('--controllers', false, { description: 'Summarize the controllers section; add --full for raw detail.' });
|
|
449
|
+
public commands = Option.Boolean('--commands', false, { description: 'Summarize the commands section; add --full for raw detail.' });
|
|
450
|
+
public routes = Option.Boolean('--routes', false, { description: 'Summarize the routes section; add --full for raw detail.' });
|
|
451
|
+
public layouts = Option.Boolean('--layouts', false, { description: 'Summarize the layouts section; add --full for raw detail.' });
|
|
384
452
|
public diagnostics = Option.Boolean('--diagnostics', false, {
|
|
385
|
-
description: '
|
|
453
|
+
description: 'Summarize the diagnostics section; add --full for raw detail.',
|
|
386
454
|
});
|
|
387
455
|
public args = Option.Rest();
|
|
388
456
|
|
|
@@ -627,12 +695,47 @@ class PerfCommand extends ProteumCommand {
|
|
|
627
695
|
}
|
|
628
696
|
}
|
|
629
697
|
|
|
698
|
+
class DbCommand extends ProteumCommand {
|
|
699
|
+
public static paths = [['db']];
|
|
700
|
+
|
|
701
|
+
public static usage = buildUsage('db');
|
|
702
|
+
|
|
703
|
+
public port = Option.String('--port', { description: 'Target an existing dev server on the given port.' });
|
|
704
|
+
public url = Option.String('--url', { description: 'Target an existing dev server at the given base URL.' });
|
|
705
|
+
public limit = Option.String('--limit', { description: 'Maximum number of result rows to return, up to 500.' });
|
|
706
|
+
public timeout = Option.String('--timeout', { description: 'Database query timeout in milliseconds, up to 30000.' });
|
|
707
|
+
public json = Option.Boolean('--json', false, { description: 'Compatibility flag; compact JSON is the default output.' });
|
|
708
|
+
public full = Option.Boolean('--full', false, { description: 'Print the full database query payload.' });
|
|
709
|
+
public args = Option.Rest();
|
|
710
|
+
|
|
711
|
+
public async execute() {
|
|
712
|
+
const [first = '', ...restArgs] = this.args;
|
|
713
|
+
const sql = first === 'query' ? restArgs.join(' ').trim() : [first, ...restArgs].join(' ').trim();
|
|
714
|
+
|
|
715
|
+
this.setCliArgs({
|
|
716
|
+
action: 'query',
|
|
717
|
+
full: this.full,
|
|
718
|
+
json: this.json,
|
|
719
|
+
limit: this.limit ?? '',
|
|
720
|
+
port: this.port ?? '',
|
|
721
|
+
sql,
|
|
722
|
+
timeout: this.timeout ?? '',
|
|
723
|
+
url: this.url ?? '',
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
await runCommandModule(() => import('../commands/db'));
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
630
730
|
class RuntimeCommand extends ProteumCommand {
|
|
631
731
|
public static paths = [['runtime']];
|
|
632
732
|
|
|
633
733
|
public static usage = buildUsage('runtime');
|
|
634
734
|
|
|
635
735
|
public full = Option.Boolean('--full', false, { description: 'Print full tracked-session and health detail.' });
|
|
736
|
+
public manifest = Option.Boolean('--manifest', false, {
|
|
737
|
+
description: 'Unsupported compatibility guard. Use `proteum explain --manifest` instead.',
|
|
738
|
+
});
|
|
636
739
|
public sessionFile = Option.String('--session-file', {
|
|
637
740
|
description: 'Inspect one explicit dev session file instead of the app registry.',
|
|
638
741
|
});
|
|
@@ -644,9 +747,35 @@ class RuntimeCommand extends ProteumCommand {
|
|
|
644
747
|
this.setCliArgs({
|
|
645
748
|
action,
|
|
646
749
|
full: this.full,
|
|
750
|
+
manifest: this.manifest,
|
|
647
751
|
sessionFile: this.sessionFile ?? '',
|
|
648
752
|
});
|
|
649
753
|
|
|
754
|
+
if (this.manifest) {
|
|
755
|
+
printJson({
|
|
756
|
+
ok: false,
|
|
757
|
+
format: 'proteum-agent-v1',
|
|
758
|
+
summary: '`proteum runtime status --manifest` is not supported. Use `proteum explain --manifest` from the app root.',
|
|
759
|
+
data: {
|
|
760
|
+
command: 'proteum runtime status --manifest',
|
|
761
|
+
},
|
|
762
|
+
nextActions: [
|
|
763
|
+
{
|
|
764
|
+
label: 'Explain Manifest',
|
|
765
|
+
command: 'npx proteum explain --manifest',
|
|
766
|
+
reason: 'The generated manifest belongs to the explain command, not runtime status.',
|
|
767
|
+
},
|
|
768
|
+
],
|
|
769
|
+
});
|
|
770
|
+
process.exitCode = 1;
|
|
771
|
+
return 1;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
if (!isCurrentWorkdirProteumAppRoot()) {
|
|
775
|
+
printNonAppRootResponse({ commandName: 'runtime', cwd: String(cli.args.workdir || process.cwd()) });
|
|
776
|
+
return 1;
|
|
777
|
+
}
|
|
778
|
+
|
|
650
779
|
await runCommandModule(() => import('../commands/runtime'));
|
|
651
780
|
}
|
|
652
781
|
}
|
|
@@ -656,19 +785,30 @@ class McpCommand extends ProteumCommand {
|
|
|
656
785
|
|
|
657
786
|
public static usage = buildUsage('mcp');
|
|
658
787
|
|
|
659
|
-
public
|
|
660
|
-
|
|
661
|
-
description: 'Inspect one explicit dev session file when resolving runtime data.',
|
|
788
|
+
public daemon = Option.Boolean('--daemon', false, {
|
|
789
|
+
description: 'Run the managed machine-scope MCP daemon over local HTTP.',
|
|
662
790
|
});
|
|
663
|
-
public
|
|
664
|
-
|
|
791
|
+
public stdio = Option.Boolean('--stdio', false, {
|
|
792
|
+
description: 'Force stdio MCP transport for an MCP client.',
|
|
793
|
+
});
|
|
794
|
+
public port = Option.String('--port', {
|
|
795
|
+
description: 'Port for the managed machine MCP daemon.',
|
|
796
|
+
});
|
|
797
|
+
public json = Option.Boolean('--json', false, {
|
|
798
|
+
description: 'Print machine-readable daemon status output.',
|
|
799
|
+
});
|
|
800
|
+
public args = Option.Rest();
|
|
665
801
|
|
|
666
802
|
public async execute() {
|
|
667
|
-
|
|
803
|
+
const [action = 'start', ...restArgs] = this.args;
|
|
804
|
+
|
|
805
|
+
assertNoLegacyArgs('mcp', restArgs);
|
|
668
806
|
this.setCliArgs({
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
807
|
+
action,
|
|
808
|
+
daemon: this.daemon,
|
|
809
|
+
stdio: this.stdio,
|
|
810
|
+
port: this.port ?? '',
|
|
811
|
+
json: this.json,
|
|
672
812
|
});
|
|
673
813
|
|
|
674
814
|
await runCommandModule(() => import('../commands/mcp'));
|
|
@@ -751,6 +891,7 @@ export const registeredCommands = {
|
|
|
751
891
|
orient: OrientCommand,
|
|
752
892
|
diagnose: DiagnoseCommand,
|
|
753
893
|
perf: PerfCommand,
|
|
894
|
+
db: DbCommand,
|
|
754
895
|
runtime: RuntimeCommand,
|
|
755
896
|
mcp: McpCommand,
|
|
756
897
|
trace: TraceCommand,
|
|
@@ -786,6 +927,7 @@ export const createCli = (version: string) => {
|
|
|
786
927
|
clipanion.register(OrientCommand);
|
|
787
928
|
clipanion.register(DiagnoseCommand);
|
|
788
929
|
clipanion.register(PerfCommand);
|
|
930
|
+
clipanion.register(DbCommand);
|
|
789
931
|
clipanion.register(RuntimeCommand);
|
|
790
932
|
clipanion.register(McpCommand);
|
|
791
933
|
clipanion.register(TraceCommand);
|