vgxness 1.2.0 → 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.
Files changed (70) hide show
  1. package/README.md +7 -6
  2. package/dist/cli/cli-help.js +8 -7
  3. package/dist/cli/commands/index.js +1 -1
  4. package/dist/cli/commands/interactive-entrypoint-dispatcher.js +150 -0
  5. package/dist/cli/commands/setup-dispatcher.js +7 -4
  6. package/dist/cli/dispatcher.js +10 -8
  7. package/dist/cli/index.js +0 -0
  8. package/dist/cli/setup-wizard-renderer.js +1 -1
  9. package/dist/cli/tui/main-menu/index.js +0 -1
  10. package/dist/cli/tui/main-menu/main-menu-controller.js +0 -2
  11. package/dist/cli/tui/main-menu/main-menu-read-model.js +2 -8
  12. package/dist/cli/tui/main-menu/main-menu-render-shape.js +5 -1
  13. package/dist/cli/tui/main-menu/main-menu-state.js +1 -1
  14. package/dist/cli/tui/opentui/code/index.js +210 -0
  15. package/dist/cli/tui/opentui/code/screen.js +107 -0
  16. package/dist/cli/tui/opentui/code/smoke.js +32 -0
  17. package/dist/cli/tui/opentui/main-menu/index.js +3 -0
  18. package/dist/cli/tui/opentui/main-menu/renderer.js +68 -0
  19. package/dist/cli/tui/opentui/main-menu/screen.js +62 -0
  20. package/dist/cli/tui/opentui/main-menu/smoke.js +17 -0
  21. package/dist/cli/tui/opentui/main-menu/view.js +8 -0
  22. package/dist/cli/tui/opentui/setup/index.js +3 -0
  23. package/dist/cli/tui/opentui/setup/renderer.js +87 -0
  24. package/dist/cli/tui/opentui/setup/screen.js +170 -0
  25. package/dist/cli/tui/opentui/setup/smoke.js +42 -0
  26. package/dist/cli/tui/opentui/setup/view.js +12 -0
  27. package/dist/cli/tui/setup/setup-tui-input.js +43 -0
  28. package/dist/cli/tui/setup/setup-tui-read-model.js +1 -1
  29. package/dist/cli/tui/setup/setup-tui-render-shape.js +1 -1
  30. package/dist/cli/tui/setup/setup-tui-view-helpers.js +46 -0
  31. package/dist/cli/tui/visual/index.js +0 -2
  32. package/dist/code/tui/approval-actions.js +33 -0
  33. package/dist/code/tui/prompt-mode.js +11 -0
  34. package/dist/code/tui/runtime-events.js +320 -0
  35. package/dist/sdd/sdd-workflow-service.js +0 -24
  36. package/dist/setup/providers/antigravity-setup-adapter.js +1 -1
  37. package/dist/setup/providers/claude-setup-adapter.js +2 -2
  38. package/dist/setup/providers/custom-setup-adapter.js +1 -1
  39. package/dist/setup/providers/opencode-setup-adapter.js +3 -3
  40. package/dist/setup/setup-lifecycle-service.js +1 -1
  41. package/docs/architecture.md +4 -4
  42. package/docs/cli.md +11 -10
  43. package/docs/funcionamiento-del-sistema.md +6 -7
  44. package/docs/prd.md +4 -4
  45. package/docs/vgxcode.md +76 -0
  46. package/package.json +5 -6
  47. package/dist/cli/commands/dashboard-dispatcher.js +0 -560
  48. package/dist/cli/dashboard-operational-read-models.js +0 -428
  49. package/dist/cli/dashboard-renderer.js +0 -158
  50. package/dist/cli/dashboard-screen-renderers.js +0 -256
  51. package/dist/cli/dashboard-tui-read-model.js +0 -73
  52. package/dist/cli/dashboard-tui-state.js +0 -314
  53. package/dist/cli/interactive-dashboard.js +0 -34
  54. package/dist/cli/tui/dashboard/dashboard-adapter.js +0 -4
  55. package/dist/cli/tui/main-menu/main-menu-app.js +0 -28
  56. package/dist/cli/tui/render-ink-app.js +0 -10
  57. package/dist/cli/tui/setup/screens/applying-screen.js +0 -6
  58. package/dist/cli/tui/setup/screens/cancellation-screen.js +0 -6
  59. package/dist/cli/tui/setup/screens/error-recovery-screen.js +0 -6
  60. package/dist/cli/tui/setup/screens/final-confirmation-screen.js +0 -6
  61. package/dist/cli/tui/setup/screens/opencode-details-screen.js +0 -10
  62. package/dist/cli/tui/setup/screens/plan-review-screen.js +0 -6
  63. package/dist/cli/tui/setup/screens/project-database-screen.js +0 -6
  64. package/dist/cli/tui/setup/screens/provider-screen.js +0 -7
  65. package/dist/cli/tui/setup/screens/result-screen.js +0 -16
  66. package/dist/cli/tui/setup/screens/screen-components.js +0 -103
  67. package/dist/cli/tui/setup/screens/welcome-screen.js +0 -6
  68. package/dist/cli/tui/setup/setup-tui-app.js +0 -113
  69. package/dist/cli/tui/visual/choice-list.js +0 -10
  70. package/dist/cli/tui/visual/layout.js +0 -10
@@ -1,4 +0,0 @@
1
- export const dashboardInkMigrationBoundary = {
2
- statusRendererRemainsText: true,
3
- interactiveDashboardRemainsCustom: true,
4
- };
@@ -1,28 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text, useApp, useInput, useStdout } from 'ink';
3
- import { useMemo, useState } from 'react';
4
- import { ChoiceList, createTuiViewport, ResponsiveColumns, TuiPanel, tuiBadges } from '../visual/index.js';
5
- import { mainMenuActionFromInput, reduceMainMenuState } from './main-menu-actions.js';
6
- import { buildMainMenuViewModel } from './main-menu-read-model.js';
7
- import { createMainMenuState } from './main-menu-state.js';
8
- export function MainMenuApp(props) {
9
- const { exit } = useApp();
10
- const { stdout } = useStdout();
11
- const initial = useMemo(() => props.initialState ?? createMainMenuState({ width: stdout?.columns }), [props.initialState, stdout?.columns]);
12
- const [state, setState] = useState(initial);
13
- const viewport = createTuiViewport(stdout?.columns, state.viewport.width);
14
- const visibleState = { ...state, viewport };
15
- const vm = useMemo(() => buildMainMenuViewModel(visibleState), [visibleState]);
16
- useInput((input, key) => {
17
- const action = mainMenuActionFromInput(input, key);
18
- if (action === undefined)
19
- return;
20
- const reduced = reduceMainMenuState(visibleState, action);
21
- setState(reduced.state);
22
- if (reduced.result !== undefined) {
23
- props.onResult?.(reduced.result);
24
- exit();
25
- }
26
- });
27
- return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: vm.title }), _jsxs(Text, { children: [vm.subtitle, " ", tuiBadges.readOnly] }), vm.contextLines.map((line) => (_jsx(Text, { children: line }, line)))] }), _jsx(ResponsiveColumns, { mode: viewport.mode, left: _jsx(TuiPanel, { title: "Menu", children: _jsx(ChoiceList, { choices: vm.options }) }), right: _jsx(TuiPanel, { title: vm.detail.title, badge: vm.detail.badges.join(' '), children: vm.detail.lines.map((line) => (_jsx(Text, { children: line }, line))) }) }), _jsx(TuiPanel, { title: "Safety", badge: tuiBadges.noProviderWrites, children: vm.safetyLines.map((line) => (_jsx(Text, { children: line }, line))) }), vm.helpLines.length === 0 ? null : (_jsx(TuiPanel, { title: "Help", badge: tuiBadges.readOnly, children: vm.helpLines.map((line) => (_jsx(Text, { children: line }, line))) })), _jsx(Text, { dimColor: true, children: vm.footer })] }));
28
- }
@@ -1,10 +0,0 @@
1
- import { render } from 'ink';
2
- export async function renderInkApp(element, options = {}) {
3
- const instance = render(element, options);
4
- try {
5
- await instance.waitUntilExit();
6
- }
7
- finally {
8
- instance.cleanup();
9
- }
10
- }
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text } from 'ink';
3
- import { badgeLabels, Panel, SetupScreenFrame } from './screen-components.js';
4
- export function ApplyingScreen() {
5
- return (_jsx(SetupScreenFrame, { title: "Applying", footer: [], children: _jsxs(Panel, { title: "Applying setup", badge: { label: badgeLabels.pending }, children: [_jsx(Text, { children: "Applying confirmed OpenCode setup..." }), _jsx(Text, { children: "Waiting for the confirmed apply operation to finish." })] }) }));
6
- }
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text } from 'ink';
3
- import { badgeLabels, Panel, SetupScreenFrame, setupFooterHints } from './screen-components.js';
4
- export function CancellationScreen() {
5
- return (_jsx(SetupScreenFrame, { title: "Setup cancelled", tone: "cancelled", footer: [setupFooterHints.close], children: _jsxs(Panel, { title: "Cancelled", badge: { label: badgeLabels.cancelled }, children: [_jsx(Text, { children: "Setup was not completed." }), _jsx(Text, { children: "No provider config was written." }), _jsx(Text, { children: "No agent seeding was performed." })] }) }));
6
- }
@@ -1,6 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { Text } from 'ink';
3
- import { badgeLabels, Panel, SetupScreenFrame, setupFooterHints } from './screen-components.js';
4
- export function ErrorRecoveryScreen(props) {
5
- return (_jsx(SetupScreenFrame, { title: "Setup recovery", tone: "error", footer: [setupFooterHints.close], children: _jsxs(Panel, { title: "Error", badge: { label: badgeLabels.error }, children: [_jsxs(Text, { children: ["Error: ", props.message ?? 'Unknown setup error'] }), _jsx(Text, { children: "No unconfirmed provider config write was performed." }), _jsx(Text, { children: "Next: inspect `vgx setup plan`, resolve blockers, then retry." })] }) }));
6
- }
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text } from 'ink';
3
- import { Panel, PlanSummary, SetupWorkspace, setupFooterHints } from './screen-components.js';
4
- export function FinalConfirmationScreen(props) {
5
- return (_jsx(SetupWorkspace, { title: "Final confirmation", viewModel: props.viewModel, footer: [setupFooterHints.confirmApply, setupFooterHints.back, setupFooterHints.cancel], children: _jsxs(Panel, { title: "Confirm OpenCode setup", children: [_jsx(PlanSummary, { viewModel: props.viewModel }), _jsx(Text, { children: "[warning]" }), _jsx(Text, { color: "yellow", children: "WARNING: OpenCode provider config may be modified at the target path above. Existing config is backed up when planned." }), _jsx(Text, { children: "After confirmation: run doctor, then restart OpenCode to reload MCP configuration." }), _jsx(Text, { children: "Press Enter to confirm and apply OpenCode setup, or Esc/q to cancel without writing." })] }) }));
6
- }
@@ -1,10 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text } from 'ink';
3
- import { badgeLabels, ChoiceList, KeyValue, ManualNoProviderNotice, Panel, SetupWorkspace, setupFooterHints } from './screen-components.js';
4
- export function OpenCodeDetailsScreen(props) {
5
- const vm = props.viewModel;
6
- if (vm.providerLabel !== 'OpenCode') {
7
- return (_jsx(SetupWorkspace, { title: "OpenCode details", viewModel: vm, footer: [setupFooterHints.continue, setupFooterHints.back, setupFooterHints.cancel], children: _jsx(ManualNoProviderNotice, {}) }));
8
- }
9
- return (_jsx(SetupWorkspace, { title: "OpenCode details", viewModel: vm, footer: [setupFooterHints.select, setupFooterHints.continue, setupFooterHints.back, setupFooterHints.cancel], children: _jsxs(Panel, { title: "OpenCode plan", badge: { label: badgeLabels.writeAfterConfirm }, children: [_jsx(ChoiceList, { choices: vm.scopeChoices }), _jsx(ChoiceList, { choices: vm.installModeChoices }), _jsx(KeyValue, { label: "Scope", value: vm.scopeLabel }), _jsx(KeyValue, { label: "Install mode", value: vm.installModeLabel }), _jsx(KeyValue, { label: "Target config", value: vm.targetPathLabel }), _jsx(KeyValue, { label: "Action", value: vm.opencodeActionLabel }), _jsx(KeyValue, { label: "Agent readiness", value: vm.agentReadinessLabel }), _jsx(Text, { children: vm.agentReadinessDetail }), _jsx(Text, { children: "Details are preview-only here; writes require final confirmation." })] }) }));
10
- }
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text } from 'ink';
3
- import { badgeLabels, Panel, PlanSummary, SetupWorkspace, setupFooterHints } from './screen-components.js';
4
- export function PlanReviewScreen(props) {
5
- return (_jsx(SetupWorkspace, { title: "Read-only plan review", viewModel: props.viewModel, footer: [setupFooterHints.finalConfirmation, setupFooterHints.back, setupFooterHints.cancel], children: _jsxs(Panel, { title: "Plan summary", badge: { label: badgeLabels.readOnly }, children: [_jsx(PlanSummary, { viewModel: props.viewModel }), _jsxs(Text, { children: ["Doctor next step: ", props.viewModel.nextCommands.find((command) => /\bdoctor\b/.test(command)) ?? 'vgx doctor'] }), _jsx(Text, { children: "Restart next step: Restart OpenCode after confirmed setup so it reloads MCP configuration." }), _jsx(Text, { children: "Review only: this screen does not write provider config." }), _jsx(Text, { children: props.viewModel.canAutoApply ? 'Press Enter to continue to final confirmation.' : 'Manual setup required; no automatic apply is available.' })] }) }));
6
- }
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ChoiceList, KeyValue, Panel, SetupWorkspace, setupFooterHints } from './screen-components.js';
3
- export function ProjectDatabaseScreen(props) {
4
- const vm = props.viewModel;
5
- return (_jsxs(SetupWorkspace, { title: "Project and database", viewModel: vm, footer: [setupFooterHints.select, setupFooterHints.continue, setupFooterHints.back, setupFooterHints.cancel], children: [_jsxs(Panel, { title: "Project", children: [_jsx(KeyValue, { label: "Project", value: vm.projectLabel }), _jsx(KeyValue, { label: "Workspace", value: vm.workspaceRootLabel })] }), _jsxs(Panel, { title: "Database", children: [_jsx(ChoiceList, { choices: vm.databaseChoices }), _jsx(KeyValue, { label: "Mode", value: vm.databaseLabel }), _jsx(KeyValue, { label: "Path", value: vm.databasePathLabel }), _jsx(KeyValue, { label: "Source", value: vm.databaseSourceLabel }), _jsx(KeyValue, { label: "Memory path explanation", value: vm.memoryPathExplanation })] })] }));
6
- }
@@ -1,7 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text } from 'ink';
3
- import { ChoiceList, Panel, SetupWorkspace, setupFooterHints } from './screen-components.js';
4
- export function ProviderScreen(props) {
5
- const vm = props.viewModel;
6
- return (_jsx(SetupWorkspace, { title: "Provider", viewModel: vm, footer: [setupFooterHints.select, setupFooterHints.continue, setupFooterHints.back, setupFooterHints.cancel], children: _jsxs(Panel, { title: "Provider selection", children: [_jsx(ChoiceList, { choices: vm.providerChoices }), _jsx(Text, { children: vm.providerInstallabilityLabel }), _jsx(Text, { children: "OpenCode setup remains gated by final confirmation. Non-OpenCode/manual has no auto-apply." })] }) }));
7
- }
@@ -1,16 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text } from 'ink';
3
- import { badgeLabels, KeyValue, Panel, SetupScreenFrame, setupFooterHints } from './screen-components.js';
4
- export function ResultScreen(props) {
5
- const result = props.result;
6
- if (result?.status === 'installed')
7
- return (_jsx(SetupScreenFrame, { title: "Setup complete", tone: "success", footer: [setupFooterHints.close], children: _jsxs(Panel, { title: "Installed", badge: { label: badgeLabels.success }, children: [_jsx(KeyValue, { label: "Target config", value: result.targetPath }), result.backupPath === undefined ? _jsx(Text, { children: "Backup: none created" }) : _jsx(KeyValue, { label: "Backup", value: result.backupPath }), result.warnings.map((warning) => (_jsxs(Text, { children: ["Warning: ", warning] }, warning))), resultNextCommands(props.viewModel).map((command) => (_jsxs(Text, { children: ["Next: ", command] }, command)))] }) }));
8
- if (result?.status === 'manual-required')
9
- return (_jsx(SetupScreenFrame, { title: "Manual setup", tone: "warning", footer: [setupFooterHints.close], children: _jsxs(Panel, { title: "Manual follow-up", badge: { label: badgeLabels.warning }, children: [_jsx(Text, { children: result.message }), props.viewModel.nextCommands.map((command) => (_jsxs(Text, { children: ["Next: ", command] }, command)))] }) }));
10
- return (_jsx(SetupScreenFrame, { title: "Setup result", footer: [setupFooterHints.close], children: _jsx(Panel, { title: "No write", children: _jsx(Text, { children: "No provider config write occurred." }) }) }));
11
- }
12
- function resultNextCommands(viewModel) {
13
- const filtered = viewModel.nextCommands.filter((command) => !/^vgx(?:ness)? setup apply\b/.test(command));
14
- const withDoctor = filtered.some((command) => /\bdoctor\b/.test(command)) ? filtered : [...filtered, 'vgx doctor'];
15
- return withDoctor.some((command) => /Restart OpenCode/i.test(command)) ? withDoctor : [...withDoctor, 'Restart OpenCode and verify the vgxness MCP server is visible.'];
16
- }
@@ -1,103 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- import { formatTuiFooter } from '../../visual/footer.js';
4
- export const badgeLabels = {
5
- recommended: '[recommended]',
6
- selected: '[selected]',
7
- focused: '[focused]',
8
- warning: '[warning]',
9
- error: '[error]',
10
- writeAfterConfirm: '[will write after confirm]',
11
- readOnly: '[read-only]',
12
- manual: '[manual]',
13
- deferred: '[deferred]',
14
- cancelled: '[cancelled]',
15
- pending: '[pending]',
16
- success: '[success]',
17
- };
18
- export const setupFooterHints = {
19
- continue: { key: 'Enter', label: 'continue' },
20
- select: { key: 'Enter/Space', label: 'select focused row' },
21
- finalConfirmation: { key: 'Enter', label: 'final confirmation' },
22
- confirmApply: { key: 'Enter', label: 'confirm and apply' },
23
- help: { key: '?/h', label: 'help' },
24
- back: { key: 'Shift+Tab', label: 'back' },
25
- cancel: { key: 'q/Esc', label: 'cancel' },
26
- close: { key: 'q/Esc', label: 'close' },
27
- };
28
- export function SetupScreenFrame(props) {
29
- return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: props.title }), props.tone === undefined || props.tone === 'neutral' ? null : _jsx(Text, { children: toneBadge(props.tone) })] }), props.children, _jsx(Footer, { hints: props.footer ?? [setupFooterHints.continue, setupFooterHints.cancel] })] }));
30
- }
31
- export function SetupWorkspace(props) {
32
- return (_jsxs(SetupScreenFrame, { title: props.viewModel.title, ...(props.footer === undefined ? {} : { footer: props.footer }), children: [_jsxs(Panel, { title: props.viewModel.frameLabel, children: [_jsx(Text, { children: props.viewModel.progressLabel }), _jsx(Text, { children: props.viewModel.previewLabel })] }), _jsx(PreviewPane, { viewModel: props.viewModel }), props.children, _jsx(Text, { children: props.viewModel.footerSafetyLabel }), props.viewModel.helpVisible ? _jsx(HelpPanel, { lines: props.viewModel.helpLines }) : null] }));
33
- }
34
- export function Panel(props) {
35
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [_jsxs(Text, { bold: true, children: [props.title, props.badge === undefined ? '' : ` ${props.badge.label}`] }), props.children] }));
36
- }
37
- export function Badge(props) {
38
- return _jsx(Text, { children: props.label });
39
- }
40
- export function ChoiceRow(props) {
41
- const badges = [
42
- ...(props.selected === true ? [{ label: badgeLabels.selected }] : []),
43
- ...(props.focused === true ? [{ label: badgeLabels.focused }] : []),
44
- ...(props.badges ?? []),
45
- ]
46
- .map((badge) => badge.label)
47
- .join(' ');
48
- return (_jsxs(Text, { children: [props.selected === true ? '›' : ' ', " ", props.label, badges.length === 0 ? '' : ` ${badges}`, " \u2014 ", props.description] }));
49
- }
50
- export function ChoiceList(props) {
51
- return (_jsx(Box, { flexDirection: "column", children: props.choices.map((choice) => (_jsx(ChoiceRow, { label: choice.label, description: choice.description, selected: choice.selected, focused: choice.focused, badges: choice.badges.map((label) => ({ label })) }, choice.id))) }));
52
- }
53
- export function HelpPanel(props) {
54
- return (_jsx(Panel, { title: "Help", badge: { label: badgeLabels.readOnly }, children: props.lines.map((line) => (_jsx(Text, { children: line }, line))) }));
55
- }
56
- export function PreviewPane(props) {
57
- return (_jsx(Panel, { title: "Live preview / details", badge: { label: badgeLabels.readOnly }, children: props.viewModel.previewDetailLines.map((line) => (_jsx(Text, { children: line }, line))) }));
58
- }
59
- export function Footer(props) {
60
- return _jsx(Text, { dimColor: true, children: formatFooter(props.hints, props.width ?? 80) });
61
- }
62
- export function KeyValue(props) {
63
- return (_jsxs(Text, { children: [props.label, ": ", props.value] }));
64
- }
65
- export function PlanSummary(props) {
66
- const vm = props.viewModel;
67
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(KeyValue, { label: "Readiness", value: `${vm.readinessBadge} ${vm.readinessLabel}` }), _jsx(KeyValue, { label: "Provider", value: vm.providerLabel }), _jsx(KeyValue, { label: "Database", value: vm.databaseLabel }), _jsx(KeyValue, { label: "Database path", value: vm.databasePathLabel }), _jsx(KeyValue, { label: "OpenCode scope", value: vm.scopeLabel }), _jsx(KeyValue, { label: "Install mode", value: vm.installModeLabel }), _jsx(KeyValue, { label: "Provider installability", value: vm.providerInstallabilityLabel }), _jsx(KeyValue, { label: "Agent readiness", value: vm.agentReadinessLabel }), _jsx(KeyValue, { label: "Agent detail", value: vm.agentReadinessDetail }), _jsx(KeyValue, { label: "Target config", value: vm.targetPathLabel }), _jsx(Text, { children: vm.backupLabel }), vm.plannedActions.map((action) => (_jsxs(Text, { children: ["Action: ", action.safetyBadge, " ", action.label, action.targetPathLabel === undefined ? '' : ` (${action.targetPathLabel})`] }, `action:${action.id}`))), vm.warnings.map((warning) => (_jsxs(Text, { children: ["Warning: ", warning] }, `warning:${warning}`))), vm.blockers.map((blocker) => (_jsxs(Text, { children: ["Blocked: ", blocker] }, `blocker:${blocker}`)))] }));
68
- }
69
- export function ManualNoProviderNotice() {
70
- return (_jsxs(Panel, { title: "Manual / no-provider-write mode", badge: { label: badgeLabels.manual }, children: [_jsx(Text, { children: "OpenCode-only scope and install controls are disabled because provider is Manual / none." }), _jsx(Text, { children: "Claude remains deferred/not installable in guided setup." }), _jsx(Text, { children: "No provider config will be written; use the manual next commands from the plan." })] }));
71
- }
72
- export function compactPath(path, width) {
73
- if (width <= 0 || path.length <= width)
74
- return path;
75
- const basename = path.split(/[\\/]/).filter(Boolean).pop() ?? path;
76
- if (basename.length + 4 >= width)
77
- return `.../${basename}`;
78
- const prefixWidth = Math.max(1, width - basename.length - 5);
79
- return `${path.slice(0, prefixWidth)}.../${basename}`;
80
- }
81
- export function wrapLabel(value, width) {
82
- if (width <= 0 || value.length <= width)
83
- return value;
84
- const protectedPhrases = ['final confirmation', 'confirm and apply', 'not installable', 'read-only', 'requires confirmation', 'will write after confirm', 'error', 'cancelled'];
85
- const phrase = protectedPhrases.find((candidate) => value.includes(candidate));
86
- if (phrase !== undefined)
87
- return `${value.slice(0, Math.max(0, width - phrase.length - 5)).trim()} ... ${phrase}`.trim();
88
- return `${value.slice(0, Math.max(0, width - 1)).trim()}…`;
89
- }
90
- export function formatFooter(hints, width) {
91
- return formatTuiFooter(hints, width);
92
- }
93
- function toneBadge(tone) {
94
- if (tone === 'success')
95
- return badgeLabels.success;
96
- if (tone === 'warning')
97
- return badgeLabels.warning;
98
- if (tone === 'error')
99
- return badgeLabels.error;
100
- if (tone === 'cancelled')
101
- return badgeLabels.cancelled;
102
- return '';
103
- }
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text } from 'ink';
3
- import { Panel, SetupWorkspace, setupFooterHints } from './screen-components.js';
4
- export function WelcomeScreen(props) {
5
- return (_jsx(SetupWorkspace, { title: "Detect", viewModel: props.viewModel, footer: [setupFooterHints.continue, setupFooterHints.help, setupFooterHints.cancel], children: _jsxs(Panel, { title: "Guided installation sequence", children: [_jsx(Text, { children: "Setup welcome: global memory \u2192 provider \u2192 OpenCode details \u2192 agent readiness \u2192 preview \u2192 final confirmation \u2192 doctor/restart." }), _jsx(Text, { children: "VGXNESS Setup Assistant" }), _jsx(Text, { children: "Configure local storage and OpenCode integration with read-only previews first." }), _jsx(Text, { children: "No provider config is written until the final confirmation." })] }) }));
6
- }
@@ -1,113 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useApp, useInput } from 'ink';
3
- import { useEffect, useMemo, useState } from 'react';
4
- import { navigationIntentFromInput } from '../keymap.js';
5
- import { ApplyingScreen } from './screens/applying-screen.js';
6
- import { CancellationScreen } from './screens/cancellation-screen.js';
7
- import { ErrorRecoveryScreen } from './screens/error-recovery-screen.js';
8
- import { FinalConfirmationScreen } from './screens/final-confirmation-screen.js';
9
- import { OpenCodeDetailsScreen } from './screens/opencode-details-screen.js';
10
- import { PlanReviewScreen } from './screens/plan-review-screen.js';
11
- import { ProjectDatabaseScreen } from './screens/project-database-screen.js';
12
- import { ProviderScreen } from './screens/provider-screen.js';
13
- import { ResultScreen } from './screens/result-screen.js';
14
- import { WelcomeScreen } from './screens/welcome-screen.js';
15
- import { createSetupTuiController } from './setup-tui-controller.js';
16
- import { buildSetupTuiViewModel } from './setup-tui-read-model.js';
17
- import { createSetupTuiState } from './setup-tui-state.js';
18
- export function SetupTuiApp(props) {
19
- const { exit } = useApp();
20
- const [state, setState] = useState(props.initialState ?? createSetupTuiState({ selections: props.runtime.selections }));
21
- const viewModel = useMemo(() => buildSetupTuiViewModel(state), [state]);
22
- useEffect(() => {
23
- let active = true;
24
- void createSetupTuiController({ state, services: props.services, runtime: props.runtime })
25
- .load()
26
- .then((controller) => {
27
- if (active)
28
- setState(controller.state);
29
- });
30
- return () => {
31
- active = false;
32
- };
33
- // Load once for the mounted app; later previews flow through controller dispatch.
34
- // eslint-disable-next-line react-hooks/exhaustive-deps
35
- }, [props.runtime, props.services]);
36
- const dispatch = (action) => {
37
- void createSetupTuiController({ state, services: props.services, runtime: props.runtime })
38
- .dispatch(action)
39
- .then((controller) => {
40
- setState(controller.state);
41
- if (controller.state.screen === 'cancelled' || controller.state.screen === 'result' || controller.state.screen === 'error-recovery') {
42
- if (action.type === 'cancel')
43
- exit();
44
- }
45
- });
46
- };
47
- useInput((input, key) => {
48
- const action = setupTuiActionFromInput(input, key, state);
49
- if (action !== undefined)
50
- dispatch(action);
51
- });
52
- if (state.screen === 'welcome')
53
- return _jsx(WelcomeScreen, { viewModel: viewModel });
54
- if (state.screen === 'project-database')
55
- return _jsx(ProjectDatabaseScreen, { viewModel: viewModel });
56
- if (state.screen === 'provider')
57
- return _jsx(ProviderScreen, { viewModel: viewModel });
58
- if (state.screen === 'opencode-details')
59
- return _jsx(OpenCodeDetailsScreen, { viewModel: viewModel });
60
- if (state.screen === 'plan-review')
61
- return _jsx(PlanReviewScreen, { viewModel: viewModel });
62
- if (state.screen === 'final-confirmation')
63
- return _jsx(FinalConfirmationScreen, { viewModel: viewModel });
64
- if (state.screen === 'applying')
65
- return _jsx(ApplyingScreen, {});
66
- if (state.screen === 'cancelled')
67
- return _jsx(CancellationScreen, {});
68
- if (state.screen === 'error-recovery')
69
- return _jsx(ErrorRecoveryScreen, { message: state.error });
70
- return _jsx(ResultScreen, { result: state.result, viewModel: viewModel });
71
- }
72
- export function setupTuiActionFromInput(input, key, state) {
73
- if (key.upArrow === true)
74
- return { type: 'focus-previous-choice' };
75
- if (key.downArrow === true)
76
- return { type: 'focus-next-choice' };
77
- if (key.escape === true)
78
- return state.helpVisible ? { type: 'toggle-help' } : { type: 'cancel' };
79
- if (key.tab === true && key.shift === true)
80
- return { type: 'back' };
81
- if (key.tab === true)
82
- return { type: 'continue' };
83
- const raw = key.return === true ? '\n' : input;
84
- const intent = navigationIntentFromInput(raw);
85
- if (intent === 'cancel')
86
- return state.helpVisible ? { type: 'toggle-help' } : { type: 'cancel' };
87
- if (intent === 'help')
88
- return { type: 'toggle-help' };
89
- if (intent === 'up')
90
- return { type: 'focus-previous-choice' };
91
- if (intent === 'down')
92
- return { type: 'focus-next-choice' };
93
- if (intent === 'select')
94
- return { type: 'select-focused-choice' };
95
- if (intent === 'back')
96
- return { type: 'back' };
97
- if (intent !== 'next')
98
- return undefined;
99
- if (key.return === true && isEditableChoiceScreen(state))
100
- return { type: 'select-focused-choice' };
101
- if (state.screen === 'plan-review')
102
- return { type: 'request-apply' };
103
- if (state.screen === 'final-confirmation')
104
- return { type: 'confirm-apply' };
105
- return { type: 'continue' };
106
- }
107
- function isEditableChoiceScreen(state) {
108
- if (state.focusedChoiceId === undefined)
109
- return false;
110
- if (state.screen === 'project-database' || state.screen === 'provider')
111
- return true;
112
- return state.screen === 'opencode-details' && state.selections.provider === 'opencode';
113
- }
@@ -1,10 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- import { formatBadges, tuiBadges } from './badges.js';
4
- export function choiceLine(choice) {
5
- const badges = formatBadges([...(choice.focused === true ? [tuiBadges.focused] : []), ...(choice.badges ?? [])]);
6
- return `${choice.focused === true ? '›' : ' '} ${choice.label}${badges.length === 0 ? '' : ` ${badges}`} — ${choice.description}`;
7
- }
8
- export function ChoiceList(props) {
9
- return (_jsx(Box, { flexDirection: "column", children: props.choices.map((choice) => (_jsx(Text, { children: choiceLine(choice) }, choice.id))) }));
10
- }
@@ -1,10 +0,0 @@
1
- import { jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- export function TuiPanel(props) {
4
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [_jsxs(Text, { bold: true, children: [props.title, props.badge === undefined ? '' : ` ${props.badge}`] }), props.children] }));
5
- }
6
- export function ResponsiveColumns(props) {
7
- if (props.mode === 'narrow')
8
- return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [props.left, props.right] }));
9
- return (_jsxs(Box, { flexDirection: "row", gap: 2, children: [props.left, props.right] }));
10
- }