vgxness 1.2.1 → 1.3.0
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/README.md +7 -6
- package/dist/cli/cli-help.js +4 -7
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/interactive-entrypoint-dispatcher.js +150 -0
- package/dist/cli/commands/setup-dispatcher.js +7 -4
- package/dist/cli/dispatcher.js +1 -8
- package/dist/cli/index.js +0 -0
- package/dist/cli/setup-wizard-renderer.js +1 -1
- package/dist/cli/tui/main-menu/index.js +0 -1
- package/dist/cli/tui/main-menu/main-menu-controller.js +0 -2
- package/dist/cli/tui/main-menu/main-menu-read-model.js +2 -8
- package/dist/cli/tui/main-menu/main-menu-render-shape.js +5 -1
- package/dist/cli/tui/main-menu/main-menu-state.js +1 -1
- package/dist/cli/tui/opentui/code/index.js +210 -0
- package/dist/cli/tui/opentui/code/screen.js +107 -0
- package/dist/cli/tui/opentui/code/smoke.js +32 -0
- package/dist/cli/tui/opentui/main-menu/index.js +3 -0
- package/dist/cli/tui/opentui/main-menu/renderer.js +68 -0
- package/dist/cli/tui/opentui/main-menu/screen.js +62 -0
- package/dist/cli/tui/opentui/main-menu/smoke.js +17 -0
- package/dist/cli/tui/opentui/main-menu/view.js +8 -0
- package/dist/cli/tui/opentui/setup/index.js +3 -0
- package/dist/cli/tui/opentui/setup/renderer.js +87 -0
- package/dist/cli/tui/opentui/setup/screen.js +170 -0
- package/dist/cli/tui/opentui/setup/smoke.js +42 -0
- package/dist/cli/tui/opentui/setup/view.js +12 -0
- package/dist/cli/tui/setup/setup-tui-input.js +43 -0
- package/dist/cli/tui/setup/setup-tui-read-model.js +1 -1
- package/dist/cli/tui/setup/setup-tui-render-shape.js +1 -1
- package/dist/cli/tui/setup/setup-tui-view-helpers.js +46 -0
- package/dist/cli/tui/visual/index.js +0 -2
- package/dist/code/tui/approval-actions.js +33 -0
- package/dist/code/tui/prompt-mode.js +11 -0
- package/dist/code/tui/runtime-events.js +320 -0
- package/dist/sdd/sdd-workflow-service.js +0 -24
- package/dist/setup/providers/antigravity-setup-adapter.js +1 -1
- package/dist/setup/providers/claude-setup-adapter.js +2 -2
- package/dist/setup/providers/custom-setup-adapter.js +1 -1
- package/dist/setup/providers/opencode-setup-adapter.js +3 -3
- package/dist/setup/setup-lifecycle-service.js +1 -1
- package/docs/architecture.md +4 -4
- package/docs/cli.md +11 -10
- package/docs/funcionamiento-del-sistema.md +6 -7
- package/docs/prd.md +4 -4
- package/docs/vgxcode.md +76 -0
- package/package.json +5 -6
- package/dist/cli/commands/dashboard-dispatcher.js +0 -560
- package/dist/cli/dashboard-operational-read-models.js +0 -428
- package/dist/cli/dashboard-renderer.js +0 -158
- package/dist/cli/dashboard-screen-renderers.js +0 -256
- package/dist/cli/dashboard-tui-read-model.js +0 -73
- package/dist/cli/dashboard-tui-state.js +0 -314
- package/dist/cli/interactive-dashboard.js +0 -34
- package/dist/cli/tui/dashboard/dashboard-adapter.js +0 -4
- package/dist/cli/tui/main-menu/main-menu-app.js +0 -28
- package/dist/cli/tui/render-ink-app.js +0 -10
- package/dist/cli/tui/setup/screens/applying-screen.js +0 -6
- package/dist/cli/tui/setup/screens/cancellation-screen.js +0 -6
- package/dist/cli/tui/setup/screens/error-recovery-screen.js +0 -6
- package/dist/cli/tui/setup/screens/final-confirmation-screen.js +0 -6
- package/dist/cli/tui/setup/screens/opencode-details-screen.js +0 -10
- package/dist/cli/tui/setup/screens/plan-review-screen.js +0 -6
- package/dist/cli/tui/setup/screens/project-database-screen.js +0 -6
- package/dist/cli/tui/setup/screens/provider-screen.js +0 -7
- package/dist/cli/tui/setup/screens/result-screen.js +0 -16
- package/dist/cli/tui/setup/screens/screen-components.js +0 -103
- package/dist/cli/tui/setup/screens/welcome-screen.js +0 -6
- package/dist/cli/tui/setup/setup-tui-app.js +0 -113
- package/dist/cli/tui/visual/choice-list.js +0 -10
- package/dist/cli/tui/visual/layout.js +0 -10
|
@@ -1,560 +0,0 @@
|
|
|
1
|
-
import { AgentRegistryService } from '../../agents/agent-registry-service.js';
|
|
2
|
-
import { ManagerProfileOverlayService } from '../../agents/manager-profile-overlay-service.js';
|
|
3
|
-
import { ManagerProfileOverlayRepository } from '../../agents/repositories/manager-profile-overlays.js';
|
|
4
|
-
import { runCodeCommand } from '../../code/cli/code-command.js';
|
|
5
|
-
import { InMemoryRunGateway } from '../../code/runtime/gateways.js';
|
|
6
|
-
import { MemoryServiceCodeGateway } from '../../code/runtime/memory-service-gateway.js';
|
|
7
|
-
import { RunsCodeRunGateway } from '../../code/runtime/runs-code-run-gateway.js';
|
|
8
|
-
import { SddWorkflowGateway } from '../../code/runtime/sdd-workflow-gateway.js';
|
|
9
|
-
import React from 'react';
|
|
10
|
-
import { ProviderChangePlanService } from '../../mcp/provider-change-plan.js';
|
|
11
|
-
import { ProviderDoctorService } from '../../mcp/provider-doctor.js';
|
|
12
|
-
import { ProviderStatusService } from '../../mcp/provider-status.js';
|
|
13
|
-
import { MemoryService } from '../../memory/memory-service.js';
|
|
14
|
-
import { RunService } from '../../runs/run-service.js';
|
|
15
|
-
import { SddWorkflowService } from '../../sdd/sdd-workflow-service.js';
|
|
16
|
-
import { SkillRegistryService } from '../../skills/skill-registry-service.js';
|
|
17
|
-
import { codeApprovalPolicyFlag, codeMemoryPolicyFlag, codeTranscriptModeFlag, codeVerificationModeFlag, databasePathFor, optionalNumberFlag, optionalStringFlag, requiredFlag, } from '../cli-flags.js';
|
|
18
|
-
import { okText, usageFailure, validationFailure } from '../cli-help.js';
|
|
19
|
-
import { openCliDatabase, resultFailure } from '../cli-helpers.js';
|
|
20
|
-
import { buildDashboardApprovalsReadModel, buildDashboardInstallationReadModel, buildDashboardManagementReadModels, buildDashboardRunsReadModel, buildDashboardWorkflowsReadModel, } from '../dashboard-operational-read-models.js';
|
|
21
|
-
import { renderDashboard as renderStatusDashboard } from '../dashboard-renderer.js';
|
|
22
|
-
import { sanitizeDashboardError, } from '../dashboard-tui-read-model.js';
|
|
23
|
-
import { dashboardKeyFromInput, loadInitialDashboardState, reduceDashboardKey, refreshDashboard, renderDashboard as renderInteractiveDashboard, resolveDashboardRenderStyle, } from '../interactive-dashboard.js';
|
|
24
|
-
import { MainMenuApp } from '../tui/main-menu/index.js';
|
|
25
|
-
import { renderInkApp } from '../tui/render-ink-app.js';
|
|
26
|
-
import { canRunInteractiveTui } from '../tui/terminal-capabilities.js';
|
|
27
|
-
import { collectRunDetails, collectRunInsights, createSetupLifecycleService, readSetupStatus, runSetupTuiCommand } from './setup-dispatcher.js';
|
|
28
|
-
function defaultNoTtyGuidance() {
|
|
29
|
-
return ([
|
|
30
|
-
'VGXNESS main menu requires a TTY; no provider config was written.',
|
|
31
|
-
'Next: rerun `vgx` in an interactive terminal, run `vgx init --plan` or `vgx setup plan` for read-only installation guidance, use `vgx dashboard interactive` for the dashboard, or run `vgx dashboard status --project <name>` for scriptable read-only output.',
|
|
32
|
-
].join('\n') + '\n');
|
|
33
|
-
}
|
|
34
|
-
function guidanceForMainMenuResult(result) {
|
|
35
|
-
if (result.type === 'show-doctor-guidance')
|
|
36
|
-
return ['Doctor / recovery guidance:', '- Read-only status: `vgx setup status`', '- Provider doctor: `vgx mcp doctor opencode`', '- No provider config was written.'].join('\n') + '\n';
|
|
37
|
-
if (result.type === 'show-sdd-guidance')
|
|
38
|
-
return ['SDD / workflow guidance:', '- Use VGXNESS MCP tools from OpenCode for normal SDD progression.', '- Manual status: `vgx sdd status --project <name> --change <change>`', '- No provider config was written.'].join('\n') + '\n';
|
|
39
|
-
if (result.type === 'show-advanced-cli')
|
|
40
|
-
return ['Advanced CLI guidance:', '- Installation preview: `vgx init --plan` or `vgx setup plan`', '- Dashboard: `vgx dashboard interactive`', '- Scriptable status: `vgx dashboard status --project <name>`', '- No provider config was written.'].join('\n') + '\n';
|
|
41
|
-
if (result.type === 'exit')
|
|
42
|
-
return 'Exited main menu; no provider config was written.\n';
|
|
43
|
-
return undefined;
|
|
44
|
-
}
|
|
45
|
-
async function renderDefaultMainMenu(environment, onResult) {
|
|
46
|
-
await renderInkApp(React.createElement(MainMenuApp, { onResult }), {
|
|
47
|
-
stdin: environment.stdin,
|
|
48
|
-
stdout: environment.stdout,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
export async function runDefaultInteractiveEntrypointWithMainMenu(environment, input = {}) {
|
|
52
|
-
if (!canRunInteractiveTui(environment.stdin, environment.stdout))
|
|
53
|
-
return okText(defaultNoTtyGuidance());
|
|
54
|
-
let selected;
|
|
55
|
-
await (input.renderMainMenu ?? ((onResult) => renderDefaultMainMenu(environment, onResult)))((result) => {
|
|
56
|
-
selected = result;
|
|
57
|
-
});
|
|
58
|
-
const result = selected ?? { type: 'exit' };
|
|
59
|
-
if (result.type === 'open-setup')
|
|
60
|
-
return (input.setupTui ?? runSetupTuiCommand)(environment);
|
|
61
|
-
if (result.type === 'open-dashboard')
|
|
62
|
-
return (input.dashboardInteractive ?? runDashboardInteractiveCommand)({ positionals: ['dashboard', 'interactive'], flags: {} }, environment);
|
|
63
|
-
return okText(guidanceForMainMenuResult(result) ?? 'No provider config was written.\n');
|
|
64
|
-
}
|
|
65
|
-
function buildDashboardProfiles(managerProfiles, project, setupStatus, sectionErrors) {
|
|
66
|
-
const resolved = managerProfiles.resolveEffectiveManager({ project, scope: 'project', managerName: 'vgxness-manager' });
|
|
67
|
-
if (!resolved.ok) {
|
|
68
|
-
sectionErrors.agents = sanitizeDashboardError(resolved.error.message);
|
|
69
|
-
return { status: setupStatus === undefined ? 'error' : 'blocked', managerName: 'vgxness-manager', scope: 'project', error: sectionErrors.agents };
|
|
70
|
-
}
|
|
71
|
-
const providerAdapter = setupStatus?.defaults.providerAdapter ?? Object.keys(resolved.value.manager.adapters)[0];
|
|
72
|
-
const adapter = providerAdapter === undefined ? undefined : resolved.value.manager.adapters[providerAdapter];
|
|
73
|
-
return {
|
|
74
|
-
status: providerAdapter === undefined && adapter?.model === undefined ? 'empty' : 'ready',
|
|
75
|
-
managerName: 'vgxness-manager',
|
|
76
|
-
scope: 'project',
|
|
77
|
-
agentId: resolved.value.manager.id,
|
|
78
|
-
...(providerAdapter === undefined ? {} : { providerAdapter }),
|
|
79
|
-
...(adapter?.model === undefined ? (setupStatus?.defaults.model === undefined ? {} : { model: setupStatus.defaults.model }) : { model: adapter.model }),
|
|
80
|
-
...(setupStatus?.defaults.profile === undefined ? {} : { profile: setupStatus.defaults.profile }),
|
|
81
|
-
overlayPresent: resolved.value.overlay !== undefined,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function buildDashboardAgentsSkills(agents, skills, project, limit, sectionErrors) {
|
|
85
|
-
const agentList = agents.listAgents({ project, scope: 'project' });
|
|
86
|
-
const skillList = skills.listSkills({ project, scope: 'project' });
|
|
87
|
-
if (!agentList.ok)
|
|
88
|
-
sectionErrors.agents = sanitizeDashboardError(agentList.error.message);
|
|
89
|
-
if (!skillList.ok)
|
|
90
|
-
sectionErrors.agents = sanitizeDashboardError(skillList.error.message);
|
|
91
|
-
const agentValues = agentList.ok ? agentList.value : [];
|
|
92
|
-
const skillValues = skillList.ok ? skillList.value : [];
|
|
93
|
-
const visibleAgents = agentValues.slice(0, limit).map((summary) => {
|
|
94
|
-
const details = agents.getAgent(summary.id);
|
|
95
|
-
const providerAdapter = details.ok ? Object.keys(details.value.adapters)[0] : undefined;
|
|
96
|
-
const model = details.ok && providerAdapter !== undefined ? details.value.adapters[providerAdapter]?.model : undefined;
|
|
97
|
-
return {
|
|
98
|
-
id: summary.id,
|
|
99
|
-
name: summary.name,
|
|
100
|
-
mode: summary.mode,
|
|
101
|
-
scope: summary.scope,
|
|
102
|
-
description: summary.description,
|
|
103
|
-
...(providerAdapter === undefined ? {} : { providerAdapter }),
|
|
104
|
-
...(model === undefined ? {} : { model }),
|
|
105
|
-
...(summary.parentAgentId === undefined ? {} : { parentAgentId: summary.parentAgentId }),
|
|
106
|
-
};
|
|
107
|
-
});
|
|
108
|
-
const visibleSkills = skillValues.slice(0, limit).map((skill) => ({ id: skill.id, name: skill.name, scope: skill.scope, description: skill.description }));
|
|
109
|
-
const status = sectionErrors.agents !== undefined ? 'error' : visibleAgents.length === 0 && visibleSkills.length === 0 ? 'empty' : 'ready';
|
|
110
|
-
return {
|
|
111
|
-
status,
|
|
112
|
-
agents: visibleAgents,
|
|
113
|
-
skills: visibleSkills,
|
|
114
|
-
truncated: agentValues.length > limit || skillValues.length > limit,
|
|
115
|
-
...(sectionErrors.agents === undefined ? {} : { error: sectionErrors.agents }),
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
function buildDashboardDoctor(project, setupStatus, sectionErrors) {
|
|
119
|
-
void sectionErrors;
|
|
120
|
-
if (setupStatus === undefined) {
|
|
121
|
-
return {
|
|
122
|
-
status: 'empty',
|
|
123
|
-
summary: 'No setup evidence is available; the TUI did not run doctor checks.',
|
|
124
|
-
warnings: ['Doctor execution is explicit because checks may prepare local state.'],
|
|
125
|
-
commands: ['npm run cli -- mcp doctor', 'npm run cli -- mcp doctor opencode'],
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
const blocked = setupStatus.store.status !== 'ready' || setupStatus.defaults.status !== 'ready' || setupStatus.mcp.status !== 'ready';
|
|
129
|
-
return {
|
|
130
|
-
status: blocked ? 'blocked' : 'ready',
|
|
131
|
-
summary: blocked
|
|
132
|
-
? `Setup diagnostics need attention for ${project}: ${setupStatus.nextAction.reason}`
|
|
133
|
-
: `Setup evidence is ready for ${project}; run doctor outside TUI for fresh checks.`,
|
|
134
|
-
warnings: [...setupStatus.mcp.evidence, 'The TUI never executes doctor checks implicitly.'].slice(0, 4),
|
|
135
|
-
commands: ['npm run cli -- mcp doctor', 'npm run cli -- mcp doctor opencode', 'npm run cli -- setup status'],
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
async function runInteractiveDashboardLoop(input) {
|
|
139
|
-
let state = await loadInitialDashboardState(input.project, input.loader);
|
|
140
|
-
const renderStyle = resolveDashboardRenderStyle({ isTTY: input.output.isTTY, env: input.env });
|
|
141
|
-
return new Promise((resolve) => {
|
|
142
|
-
const render = () => input.output.write(`c${renderInteractiveDashboard(state, { style: renderStyle })}`);
|
|
143
|
-
const finish = () => {
|
|
144
|
-
input.input.setRawMode?.(false);
|
|
145
|
-
input.input.pause?.();
|
|
146
|
-
if (input.input.off !== undefined)
|
|
147
|
-
input.input.off('data', onData);
|
|
148
|
-
else
|
|
149
|
-
input.input.removeListener?.('data', onData);
|
|
150
|
-
resolve();
|
|
151
|
-
};
|
|
152
|
-
const onData = (chunk) => {
|
|
153
|
-
void (async () => {
|
|
154
|
-
const key = dashboardKeyFromInput(chunk.toString());
|
|
155
|
-
if (key === undefined)
|
|
156
|
-
return;
|
|
157
|
-
if (key === 'refresh')
|
|
158
|
-
state = await refreshDashboard(state, input.loader);
|
|
159
|
-
else
|
|
160
|
-
state = reduceDashboardKey(state, key);
|
|
161
|
-
render();
|
|
162
|
-
if (state.shouldExit)
|
|
163
|
-
finish();
|
|
164
|
-
})();
|
|
165
|
-
};
|
|
166
|
-
input.input.setRawMode?.(true);
|
|
167
|
-
input.input.resume?.();
|
|
168
|
-
input.input.on('data', onData);
|
|
169
|
-
render();
|
|
170
|
-
if (state.shouldExit)
|
|
171
|
-
finish();
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
function resolveInteractiveTerminal(environment) {
|
|
175
|
-
const input = environment.stdin;
|
|
176
|
-
const output = environment.stdout;
|
|
177
|
-
if (input === undefined || output === undefined || input.isTTY !== true || output.isTTY !== true || input.setRawMode === undefined) {
|
|
178
|
-
return validationFailure('Interactive dashboard mode is unavailable because stdin/stdout are not an interactive terminal');
|
|
179
|
-
}
|
|
180
|
-
return { ok: true, value: { input, output } };
|
|
181
|
-
}
|
|
182
|
-
function codeApprovalChannelFlag(flags) {
|
|
183
|
-
const value = optionalStringFlag(flags, 'approval-channel');
|
|
184
|
-
if (value === undefined)
|
|
185
|
-
return { ok: true, value: undefined };
|
|
186
|
-
return value === 'stdio' ? { ok: true, value } : validationFailure('--approval-channel must be stdio');
|
|
187
|
-
}
|
|
188
|
-
export function runDashboardCommand(command, parsed, database, environment, databasePath) {
|
|
189
|
-
if (command !== 'status')
|
|
190
|
-
return usageFailure(`Unknown dashboard command: ${command}`);
|
|
191
|
-
const project = requiredFlag(parsed.flags, 'project');
|
|
192
|
-
if (!project.ok)
|
|
193
|
-
return resultFailure(project);
|
|
194
|
-
const limit = optionalNumberFlag(parsed.flags, 'limit');
|
|
195
|
-
if (!limit.ok)
|
|
196
|
-
return resultFailure(limit);
|
|
197
|
-
const runs = new RunService(database);
|
|
198
|
-
const listed = runs.listRuns({ project: project.value });
|
|
199
|
-
if (!listed.ok)
|
|
200
|
-
return resultFailure(listed);
|
|
201
|
-
const runId = optionalStringFlag(parsed.flags, 'run-id');
|
|
202
|
-
const selectedRun = runId === undefined ? undefined : runs.getRun(runId);
|
|
203
|
-
if (selectedRun !== undefined && !selectedRun.ok)
|
|
204
|
-
return resultFailure(validationFailure(`Unknown run: ${runId}`));
|
|
205
|
-
const selectedRunInsights = runId === undefined ? undefined : runs.getRunInsights(runId);
|
|
206
|
-
if (selectedRunInsights !== undefined && !selectedRunInsights.ok)
|
|
207
|
-
return resultFailure(selectedRunInsights);
|
|
208
|
-
const change = optionalStringFlag(parsed.flags, 'change');
|
|
209
|
-
const memory = new MemoryService(database);
|
|
210
|
-
const sddService = new SddWorkflowService(memory);
|
|
211
|
-
const setupService = createSetupLifecycleService({ opened: { ok: true, value: database }, databasePath, environment });
|
|
212
|
-
const setupStatus = readSetupStatus(setupService, { project: project.value, projectRoot: environment.cwd, scope: 'project', env: environment.env });
|
|
213
|
-
if (!setupStatus.ok)
|
|
214
|
-
return resultFailure(setupStatus);
|
|
215
|
-
const sddStatus = change === undefined ? undefined : sddService.getStatus({ project: project.value, change });
|
|
216
|
-
if (sddStatus !== undefined && !sddStatus.ok)
|
|
217
|
-
return resultFailure(sddStatus);
|
|
218
|
-
const cockpit = change === undefined ? undefined : sddService.getCockpit({ project: project.value, change });
|
|
219
|
-
if (cockpit !== undefined && !cockpit.ok)
|
|
220
|
-
return resultFailure(cockpit);
|
|
221
|
-
const nextReadyPhase = sddStatus?.value.nextReadyPhase;
|
|
222
|
-
const readiness = change !== undefined && nextReadyPhase !== undefined ? sddService.getReady({ project: project.value, change, phase: nextReadyPhase }) : undefined;
|
|
223
|
-
if (readiness !== undefined && !readiness.ok)
|
|
224
|
-
return resultFailure(readiness);
|
|
225
|
-
return okText(renderStatusDashboard({
|
|
226
|
-
project: project.value,
|
|
227
|
-
databasePath,
|
|
228
|
-
runs: listed.value.slice(0, limit.value ?? 5),
|
|
229
|
-
setup: setupStatus.value,
|
|
230
|
-
...(selectedRun?.ok ? { selectedRun: selectedRun.value } : {}),
|
|
231
|
-
...(selectedRunInsights?.ok ? { selectedRunInsights: selectedRunInsights.value } : {}),
|
|
232
|
-
...(change !== undefined && sddStatus?.ok
|
|
233
|
-
? { sdd: { change, status: sddStatus.value, ...(readiness?.ok ? { readiness: readiness.value } : {}), ...(cockpit?.ok ? { cockpit: cockpit.value } : {}) } }
|
|
234
|
-
: {}),
|
|
235
|
-
}));
|
|
236
|
-
}
|
|
237
|
-
export async function runDashboardInteractiveCommand(parsed, environment) {
|
|
238
|
-
const project = optionalStringFlag(parsed.flags, 'project');
|
|
239
|
-
const terminal = resolveInteractiveTerminal(environment);
|
|
240
|
-
if (!terminal.ok)
|
|
241
|
-
return resultFailure(terminal);
|
|
242
|
-
const limit = optionalNumberFlag(parsed.flags, 'limit');
|
|
243
|
-
if (!limit.ok)
|
|
244
|
-
return resultFailure(limit);
|
|
245
|
-
const selectedDatabasePath = databasePathFor(parsed.flags, environment);
|
|
246
|
-
if (!selectedDatabasePath.ok)
|
|
247
|
-
return resultFailure(selectedDatabasePath);
|
|
248
|
-
const databasePath = selectedDatabasePath.value;
|
|
249
|
-
const opened = openCliDatabase(databasePath);
|
|
250
|
-
if (!opened.ok)
|
|
251
|
-
return resultFailure(opened);
|
|
252
|
-
try {
|
|
253
|
-
const memory = new MemoryService(opened.value);
|
|
254
|
-
const runs = new RunService(opened.value);
|
|
255
|
-
const sdd = new SddWorkflowService(memory);
|
|
256
|
-
const setup = createSetupLifecycleService({ opened, databasePath, environment });
|
|
257
|
-
const agents = new AgentRegistryService(opened.value);
|
|
258
|
-
const skills = new SkillRegistryService(opened.value);
|
|
259
|
-
const managerProfiles = new ManagerProfileOverlayService({ agents, overlays: new ManagerProfileOverlayRepository(opened.value) });
|
|
260
|
-
const providerStatusService = new ProviderStatusService();
|
|
261
|
-
const providerDoctorService = new ProviderDoctorService();
|
|
262
|
-
const providerChangePlanService = new ProviderChangePlanService({
|
|
263
|
-
providerStatus: providerStatusService,
|
|
264
|
-
providerDoctor: providerDoctorService,
|
|
265
|
-
env: environment.env,
|
|
266
|
-
});
|
|
267
|
-
const change = optionalStringFlag(parsed.flags, 'change');
|
|
268
|
-
const loader = () => {
|
|
269
|
-
if (project === undefined) {
|
|
270
|
-
const setupStatus = readSetupStatus(setup, { projectRoot: environment.cwd, scope: 'project', env: environment.env });
|
|
271
|
-
const sectionErrors = {};
|
|
272
|
-
if (!setupStatus.ok)
|
|
273
|
-
sectionErrors.setup = sanitizeDashboardError(setupStatus.error.message);
|
|
274
|
-
const generatedAt = new Date().toISOString();
|
|
275
|
-
const providerStatus = providerStatusService.getStatus({
|
|
276
|
-
project: 'vgxness',
|
|
277
|
-
providerAdapter: 'opencode',
|
|
278
|
-
workspaceRoot: environment.cwd,
|
|
279
|
-
env: environment.env,
|
|
280
|
-
payloadMode: 'compact',
|
|
281
|
-
});
|
|
282
|
-
const providerDoctor = providerDoctorService.getDoctor({
|
|
283
|
-
project: 'vgxness',
|
|
284
|
-
providerAdapter: 'opencode',
|
|
285
|
-
workspaceRoot: environment.cwd,
|
|
286
|
-
env: environment.env,
|
|
287
|
-
payloadMode: 'compact',
|
|
288
|
-
});
|
|
289
|
-
const providerChangePlan = providerChangePlanService.getPlan({
|
|
290
|
-
project: 'vgxness',
|
|
291
|
-
provider: 'opencode',
|
|
292
|
-
changeType: 'opencode-mcp-install',
|
|
293
|
-
workspaceRoot: environment.cwd,
|
|
294
|
-
payloadMode: 'compact',
|
|
295
|
-
});
|
|
296
|
-
return {
|
|
297
|
-
ok: true,
|
|
298
|
-
value: {
|
|
299
|
-
runs: [],
|
|
300
|
-
workflows: buildDashboardWorkflowsReadModel({ generatedAt }),
|
|
301
|
-
operationalRuns: buildDashboardRunsReadModel({ runs: [], generatedAt }),
|
|
302
|
-
approvals: buildDashboardApprovalsReadModel({ runs: [], generatedAt }),
|
|
303
|
-
installation: buildDashboardInstallationReadModel({
|
|
304
|
-
...(setupStatus.ok ? { setup: setupStatus.value } : {}),
|
|
305
|
-
...(providerStatus.ok ? { providerStatus: providerStatus.value } : {}),
|
|
306
|
-
...(providerDoctor.ok ? { providerDoctor: providerDoctor.value } : {}),
|
|
307
|
-
...(providerChangePlan.ok ? { providerChangePlan: providerChangePlan.value } : {}),
|
|
308
|
-
generatedAt,
|
|
309
|
-
}),
|
|
310
|
-
management: buildDashboardManagementReadModels({ runs: [], memoryObservations: [], workspaceRoot: environment.cwd, databasePath, generatedAt }),
|
|
311
|
-
doctor: {
|
|
312
|
-
status: 'ready-without-project',
|
|
313
|
-
summary: 'No project selected; environment-only dashboard checks are available.',
|
|
314
|
-
warnings: ['Project-scoped run, SDD, approval, and agent checks are deferred.'],
|
|
315
|
-
commands: ['npm run cli -- setup status', 'npm run cli -- mcp setup --provider opencode --preview'],
|
|
316
|
-
},
|
|
317
|
-
...(setupStatus.ok ? { setup: setupStatus.value } : {}),
|
|
318
|
-
sectionErrors,
|
|
319
|
-
},
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
const listed = runs.listRuns({ project });
|
|
323
|
-
if (!listed.ok)
|
|
324
|
-
return listed;
|
|
325
|
-
const visibleRuns = listed.value.slice(0, limit.value ?? 10);
|
|
326
|
-
const details = collectRunDetails(runs, visibleRuns);
|
|
327
|
-
if (!details.ok)
|
|
328
|
-
return details;
|
|
329
|
-
const insights = collectRunInsights(runs, visibleRuns);
|
|
330
|
-
if (!insights.ok)
|
|
331
|
-
return insights;
|
|
332
|
-
const generatedAt = new Date().toISOString();
|
|
333
|
-
const workflowsReadModel = buildDashboardWorkflowsReadModel({ project, runs: visibleRuns, generatedAt });
|
|
334
|
-
const operationalRuns = buildDashboardRunsReadModel({
|
|
335
|
-
project,
|
|
336
|
-
runs: visibleRuns,
|
|
337
|
-
detailsByRunId: details.value,
|
|
338
|
-
insightsByRunId: insights.value,
|
|
339
|
-
generatedAt,
|
|
340
|
-
});
|
|
341
|
-
const approvalsReadModel = buildDashboardApprovalsReadModel({ project, runs: visibleRuns, detailsByRunId: details.value, generatedAt });
|
|
342
|
-
const setupStatus = readSetupStatus(setup, { project, projectRoot: environment.cwd, scope: 'project', env: environment.env });
|
|
343
|
-
const sectionErrors = {};
|
|
344
|
-
if (!setupStatus.ok)
|
|
345
|
-
sectionErrors.setup = sanitizeDashboardError(setupStatus.error.message);
|
|
346
|
-
const profiles = buildDashboardProfiles(managerProfiles, project, setupStatus.ok ? setupStatus.value : undefined, sectionErrors);
|
|
347
|
-
const agentsSkills = buildDashboardAgentsSkills(agents, skills, project, limit.value ?? 10, sectionErrors);
|
|
348
|
-
const doctor = buildDashboardDoctor(project, setupStatus.ok ? setupStatus.value : undefined, sectionErrors);
|
|
349
|
-
const providerStatus = providerStatusService.getStatus({
|
|
350
|
-
project,
|
|
351
|
-
providerAdapter: 'opencode',
|
|
352
|
-
workspaceRoot: environment.cwd,
|
|
353
|
-
env: environment.env,
|
|
354
|
-
payloadMode: 'compact',
|
|
355
|
-
...(change === undefined ? {} : { change }),
|
|
356
|
-
});
|
|
357
|
-
const providerDoctor = providerDoctorService.getDoctor({
|
|
358
|
-
project,
|
|
359
|
-
providerAdapter: 'opencode',
|
|
360
|
-
workspaceRoot: environment.cwd,
|
|
361
|
-
env: environment.env,
|
|
362
|
-
payloadMode: 'compact',
|
|
363
|
-
});
|
|
364
|
-
const providerChangePlan = providerChangePlanService.getPlan({
|
|
365
|
-
project,
|
|
366
|
-
provider: 'opencode',
|
|
367
|
-
changeType: 'opencode-mcp-install',
|
|
368
|
-
workspaceRoot: environment.cwd,
|
|
369
|
-
payloadMode: 'compact',
|
|
370
|
-
});
|
|
371
|
-
const memoryObservations = memory.observations.searchPreviews({ project, scope: 'project', limit: limit.value ?? 10 });
|
|
372
|
-
if (!memoryObservations.ok)
|
|
373
|
-
sectionErrors.memory = sanitizeDashboardError(memoryObservations.error.message);
|
|
374
|
-
if (change === undefined)
|
|
375
|
-
return {
|
|
376
|
-
ok: true,
|
|
377
|
-
value: {
|
|
378
|
-
runs: visibleRuns,
|
|
379
|
-
runInsights: insights.value,
|
|
380
|
-
workflows: workflowsReadModel,
|
|
381
|
-
operationalRuns,
|
|
382
|
-
approvals: approvalsReadModel,
|
|
383
|
-
...(setupStatus.ok ? { setup: setupStatus.value } : {}),
|
|
384
|
-
profiles,
|
|
385
|
-
agentsSkills,
|
|
386
|
-
doctor,
|
|
387
|
-
installation: buildDashboardInstallationReadModel({
|
|
388
|
-
project,
|
|
389
|
-
...(setupStatus.ok ? { setup: setupStatus.value } : {}),
|
|
390
|
-
...(providerStatus.ok ? { providerStatus: providerStatus.value } : {}),
|
|
391
|
-
...(providerDoctor.ok ? { providerDoctor: providerDoctor.value } : {}),
|
|
392
|
-
...(providerChangePlan.ok ? { providerChangePlan: providerChangePlan.value } : {}),
|
|
393
|
-
generatedAt,
|
|
394
|
-
}),
|
|
395
|
-
management: buildDashboardManagementReadModels({
|
|
396
|
-
project,
|
|
397
|
-
agentsSkills,
|
|
398
|
-
runs: visibleRuns,
|
|
399
|
-
approvals: approvalsReadModel,
|
|
400
|
-
...(memoryObservations.ok ? { memoryObservations: memoryObservations.value } : {}),
|
|
401
|
-
workspaceRoot: environment.cwd,
|
|
402
|
-
databasePath,
|
|
403
|
-
generatedAt,
|
|
404
|
-
}),
|
|
405
|
-
sectionErrors,
|
|
406
|
-
},
|
|
407
|
-
};
|
|
408
|
-
const status = sdd.getDashboardStatus({ project, change });
|
|
409
|
-
if (!status.ok)
|
|
410
|
-
sectionErrors.sdd = sanitizeDashboardError(status.error.message);
|
|
411
|
-
const cockpit = sdd.getCockpit({ project, change });
|
|
412
|
-
if (!cockpit.ok)
|
|
413
|
-
sectionErrors.sdd = sanitizeDashboardError(cockpit.error.message);
|
|
414
|
-
const readiness = status.ok && status.value.nextReadyPhase !== undefined ? sdd.getReady({ project, change, phase: status.value.nextReadyPhase }) : undefined;
|
|
415
|
-
if (readiness !== undefined && !readiness.ok)
|
|
416
|
-
sectionErrors.sdd = sanitizeDashboardError(readiness.error.message);
|
|
417
|
-
const sddState = status.ok ? { change, status: status.value, ...(readiness?.ok ? { readiness: readiness.value } : {}), ...(cockpit.ok ? { cockpit: cockpit.value } : {}) } : undefined;
|
|
418
|
-
return {
|
|
419
|
-
ok: true,
|
|
420
|
-
value: {
|
|
421
|
-
runs: visibleRuns,
|
|
422
|
-
runInsights: insights.value,
|
|
423
|
-
workflows: workflowsReadModel,
|
|
424
|
-
operationalRuns,
|
|
425
|
-
approvals: approvalsReadModel,
|
|
426
|
-
...(setupStatus.ok ? { setup: setupStatus.value } : {}),
|
|
427
|
-
...(sddState === undefined ? {} : { sdd: sddState }),
|
|
428
|
-
profiles,
|
|
429
|
-
agentsSkills,
|
|
430
|
-
doctor,
|
|
431
|
-
installation: buildDashboardInstallationReadModel({
|
|
432
|
-
project,
|
|
433
|
-
...(setupStatus.ok ? { setup: setupStatus.value } : {}),
|
|
434
|
-
...(providerStatus.ok ? { providerStatus: providerStatus.value } : {}),
|
|
435
|
-
...(providerDoctor.ok ? { providerDoctor: providerDoctor.value } : {}),
|
|
436
|
-
...(providerChangePlan.ok ? { providerChangePlan: providerChangePlan.value } : {}),
|
|
437
|
-
generatedAt,
|
|
438
|
-
}),
|
|
439
|
-
management: buildDashboardManagementReadModels({
|
|
440
|
-
project,
|
|
441
|
-
agentsSkills,
|
|
442
|
-
...(sddState === undefined ? {} : { sdd: sddState }),
|
|
443
|
-
runs: visibleRuns,
|
|
444
|
-
approvals: approvalsReadModel,
|
|
445
|
-
...(memoryObservations.ok ? { memoryObservations: memoryObservations.value } : {}),
|
|
446
|
-
workspaceRoot: environment.cwd,
|
|
447
|
-
databasePath,
|
|
448
|
-
generatedAt,
|
|
449
|
-
}),
|
|
450
|
-
sectionErrors,
|
|
451
|
-
},
|
|
452
|
-
};
|
|
453
|
-
};
|
|
454
|
-
await runInteractiveDashboardLoop({
|
|
455
|
-
...(project === undefined ? {} : { project }),
|
|
456
|
-
loader,
|
|
457
|
-
input: terminal.value.input,
|
|
458
|
-
output: terminal.value.output,
|
|
459
|
-
env: environment.env,
|
|
460
|
-
});
|
|
461
|
-
return { exitCode: 0, stdout: '', stderr: '' };
|
|
462
|
-
}
|
|
463
|
-
finally {
|
|
464
|
-
opened.value.close();
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
export async function runDefaultInteractiveEntrypoint(environment) {
|
|
468
|
-
return runDefaultInteractiveEntrypointWithMainMenu(environment);
|
|
469
|
-
}
|
|
470
|
-
export async function runCodeCliCommand(parsed, environment) {
|
|
471
|
-
const [, command] = parsed.positionals;
|
|
472
|
-
if (command !== 'inspect' && command !== 'plan' && command !== 'craft' && command !== 'craft-preview' && command !== 'sdd')
|
|
473
|
-
return usageFailure(`Unknown code command: ${command ?? ''}`.trim());
|
|
474
|
-
const eventsJsonl = parsed.flags['events-jsonl'] === true;
|
|
475
|
-
const approvalChannel = codeApprovalChannelFlag(parsed.flags);
|
|
476
|
-
if (!approvalChannel.ok)
|
|
477
|
-
return resultFailure(approvalChannel);
|
|
478
|
-
if (approvalChannel.value === 'stdio' && (command !== 'craft' || !eventsJsonl))
|
|
479
|
-
return usageFailure('--approval-channel stdio is supported only for code craft --events-jsonl');
|
|
480
|
-
if (eventsJsonl && command !== 'inspect' && command !== 'plan' && command !== 'craft-preview' && approvalChannel.value !== 'stdio')
|
|
481
|
-
return usageFailure('code craft --events-jsonl requires --approval-channel stdio; JSONL without approvals is currently supported only for read-only inspect, plan, and craft-preview');
|
|
482
|
-
const maxSourceBytes = optionalNumberFlag(parsed.flags, 'max-source-bytes');
|
|
483
|
-
if (!maxSourceBytes.ok)
|
|
484
|
-
return resultFailure(maxSourceBytes);
|
|
485
|
-
const output = parsed.flags.json === true || optionalStringFlag(parsed.flags, 'output') === 'json' ? 'json' : 'human';
|
|
486
|
-
const approvalPolicy = codeApprovalPolicyFlag(parsed.flags);
|
|
487
|
-
if (!approvalPolicy.ok)
|
|
488
|
-
return resultFailure(approvalPolicy);
|
|
489
|
-
const verificationMode = codeVerificationModeFlag(parsed.flags);
|
|
490
|
-
if (!verificationMode.ok)
|
|
491
|
-
return resultFailure(verificationMode);
|
|
492
|
-
const transcriptMode = codeTranscriptModeFlag(parsed.flags);
|
|
493
|
-
if (!transcriptMode.ok)
|
|
494
|
-
return resultFailure(transcriptMode);
|
|
495
|
-
const memoryPolicy = codeMemoryPolicyFlag(parsed.flags);
|
|
496
|
-
if (!memoryPolicy.ok)
|
|
497
|
-
return resultFailure(memoryPolicy);
|
|
498
|
-
const provider = optionalStringFlag(parsed.flags, 'provider');
|
|
499
|
-
const model = optionalStringFlag(parsed.flags, 'model');
|
|
500
|
-
if (eventsJsonl) {
|
|
501
|
-
if (approvalChannel.value === 'stdio' && (environment.stdin === undefined || environment.stdout === undefined))
|
|
502
|
-
return resultFailure(validationFailure('--approval-channel stdio requires CLI stdin and stdout streams'));
|
|
503
|
-
return await runCodeCommand({
|
|
504
|
-
command,
|
|
505
|
-
args: parsed.positionals.slice(2),
|
|
506
|
-
cwd: environment.cwd,
|
|
507
|
-
output,
|
|
508
|
-
runGateway: new InMemoryRunGateway(),
|
|
509
|
-
project: optionalStringFlag(parsed.flags, 'project') ?? 'vgxness',
|
|
510
|
-
...(provider === undefined ? {} : { provider }),
|
|
511
|
-
...(model === undefined ? {} : { model }),
|
|
512
|
-
stream: parsed.flags.stream === true,
|
|
513
|
-
env: environment.env,
|
|
514
|
-
eventsJsonl,
|
|
515
|
-
memoryPolicy: 'off',
|
|
516
|
-
...(approvalChannel.value === undefined ? {} : { approvalChannel: approvalChannel.value }),
|
|
517
|
-
...(approvalChannel.value === 'stdio' ? { approvalDecisionInput: environment.stdin, eventOutput: environment.stdout } : {}),
|
|
518
|
-
...(maxSourceBytes.value !== undefined ? { maxSourceBytes: maxSourceBytes.value } : {}),
|
|
519
|
-
...(approvalPolicy.value === undefined ? {} : { approvalPolicy: approvalPolicy.value }),
|
|
520
|
-
...(verificationMode.value === undefined ? {} : { verificationMode: verificationMode.value }),
|
|
521
|
-
...(transcriptMode.value === undefined ? {} : { transcriptMode: transcriptMode.value }),
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
const selectedDatabasePath = databasePathFor(parsed.flags, environment);
|
|
525
|
-
if (!selectedDatabasePath.ok)
|
|
526
|
-
return resultFailure(selectedDatabasePath);
|
|
527
|
-
const opened = openCliDatabase(selectedDatabasePath.value);
|
|
528
|
-
if (!opened.ok)
|
|
529
|
-
return resultFailure(opened);
|
|
530
|
-
try {
|
|
531
|
-
const runs = new RunService(opened.value);
|
|
532
|
-
const memory = new MemoryService(opened.value);
|
|
533
|
-
return await runCodeCommand({
|
|
534
|
-
command,
|
|
535
|
-
args: parsed.positionals.slice(2),
|
|
536
|
-
cwd: environment.cwd,
|
|
537
|
-
output,
|
|
538
|
-
runGateway: new RunsCodeRunGateway(runs),
|
|
539
|
-
sddGateway: new SddWorkflowGateway(new SddWorkflowService(memory)),
|
|
540
|
-
memoryGateway: new MemoryServiceCodeGateway(memory),
|
|
541
|
-
project: optionalStringFlag(parsed.flags, 'project') ?? 'vgxness',
|
|
542
|
-
...(provider === undefined ? {} : { provider }),
|
|
543
|
-
...(model === undefined ? {} : { model }),
|
|
544
|
-
stream: parsed.flags.stream === true,
|
|
545
|
-
env: environment.env,
|
|
546
|
-
eventsJsonl,
|
|
547
|
-
persistArtifact: parsed.flags['save-artifact'] === true || parsed.flags.persist === true,
|
|
548
|
-
...(maxSourceBytes.value !== undefined ? { maxSourceBytes: maxSourceBytes.value } : {}),
|
|
549
|
-
...(approvalPolicy.value === undefined ? {} : { approvalPolicy: approvalPolicy.value }),
|
|
550
|
-
...(verificationMode.value === undefined ? {} : { verificationMode: verificationMode.value }),
|
|
551
|
-
...(transcriptMode.value === undefined ? {} : { transcriptMode: transcriptMode.value }),
|
|
552
|
-
...(memoryPolicy.value === undefined ? {} : { memoryPolicy: memoryPolicy.value }),
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
finally {
|
|
556
|
-
opened.value.close();
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
// Re-export helpers
|
|
560
|
-
export { buildDashboardAgentsSkills, buildDashboardApprovalsReadModel, buildDashboardDoctor, buildDashboardInstallationReadModel, buildDashboardManagementReadModels, buildDashboardProfiles, buildDashboardRunsReadModel, buildDashboardWorkflowsReadModel, defaultNoTtyGuidance, resolveInteractiveTerminal, runInteractiveDashboardLoop, };
|