cvc-tui 0.1.0 → 0.4.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 (130) hide show
  1. package/dist/app/completion.js +4 -0
  2. package/dist/app/createGatewayEventHandler.js +508 -0
  3. package/dist/app/createSlashHandler.js +101 -0
  4. package/dist/app/delegationStore.js +51 -0
  5. package/dist/app/gatewayContext.js +17 -0
  6. package/dist/app/historyStore.js +4 -0
  7. package/dist/app/inputBuffer.js +4 -0
  8. package/dist/app/inputSelectionStore.js +8 -0
  9. package/dist/app/inputStore.js +4 -0
  10. package/dist/app/interfaces.js +6 -0
  11. package/dist/app/overlayStore.js +40 -0
  12. package/dist/app/promptStore.js +4 -0
  13. package/dist/app/queueStore.js +4 -0
  14. package/dist/app/scroll.js +44 -0
  15. package/dist/app/setupHandoff.js +28 -0
  16. package/dist/app/slash/commands/core.js +421 -234
  17. package/dist/app/slash/commands/debug.js +39 -6
  18. package/dist/app/slash/commands/ops.js +471 -136
  19. package/dist/app/slash/commands/session.js +405 -65
  20. package/dist/app/slash/commands/setup.js +16 -43
  21. package/dist/app/slash/commands/toggles.js +4 -0
  22. package/dist/app/slash/registry.js +7 -68
  23. package/dist/app/slash/types.js +1 -16
  24. package/dist/app/spawnHistoryStore.js +105 -0
  25. package/dist/app/turnController.js +650 -0
  26. package/dist/app/turnStore.js +47 -59
  27. package/dist/app/uiStore.js +34 -29
  28. package/dist/app/useComposerState.js +265 -0
  29. package/dist/app/useConfigSync.js +144 -0
  30. package/dist/app/useInputHandlers.js +403 -0
  31. package/dist/app/useLongRunToolCharms.js +50 -0
  32. package/dist/app/useMainApp.js +629 -0
  33. package/dist/app/useSessionLifecycle.js +175 -0
  34. package/dist/app/useSubmission.js +287 -0
  35. package/dist/app.js +13 -217
  36. package/dist/banner.js +40 -3
  37. package/dist/components/agentsOverlay.js +474 -0
  38. package/dist/components/appChrome.js +252 -0
  39. package/dist/components/appLayout.js +121 -22
  40. package/dist/components/appOverlays.js +65 -0
  41. package/dist/components/branding.js +97 -6
  42. package/dist/components/fpsOverlay.js +22 -0
  43. package/dist/components/helpHint.js +21 -0
  44. package/dist/components/markdown.js +501 -0
  45. package/dist/components/maskedPrompt.js +12 -0
  46. package/dist/components/messageLine.js +82 -0
  47. package/dist/components/modelPicker.js +254 -0
  48. package/dist/components/overlayControls.js +30 -0
  49. package/dist/components/overlays/helpOverlay.js +1 -0
  50. package/dist/components/overlays/historySearch.js +1 -0
  51. package/dist/components/overlays/modelPicker.js +2 -1
  52. package/dist/components/overlays/overlayUtils.js +2 -1
  53. package/dist/components/overlays/secretPrompt.js +1 -0
  54. package/dist/components/overlays/sessionPicker.js +1 -0
  55. package/dist/components/overlays/skillsHub.js +1 -0
  56. package/dist/components/prompts.js +95 -0
  57. package/dist/components/queuedMessages.js +24 -0
  58. package/dist/components/sessionPicker.js +130 -0
  59. package/dist/components/skillsHub.js +165 -0
  60. package/dist/components/streamingAssistant.js +35 -0
  61. package/dist/components/streamingMarkdown.js +110 -186
  62. package/dist/components/textInput.js +748 -218
  63. package/dist/components/themed.js +12 -0
  64. package/dist/components/thinking.js +493 -36
  65. package/dist/components/todoPanel.js +40 -0
  66. package/dist/config/env.js +18 -0
  67. package/dist/config/limits.js +22 -0
  68. package/dist/config/timing.js +4 -0
  69. package/dist/content/charms.js +5 -0
  70. package/dist/content/faces.js +21 -0
  71. package/dist/content/fortunes.js +29 -0
  72. package/dist/content/hotkeys.js +38 -0
  73. package/dist/content/placeholders.js +15 -0
  74. package/dist/content/setup.js +14 -0
  75. package/dist/content/verbs.js +41 -0
  76. package/dist/domain/details.js +53 -0
  77. package/dist/domain/messages.js +63 -0
  78. package/dist/domain/paths.js +16 -0
  79. package/dist/domain/providers.js +11 -0
  80. package/dist/domain/roles.js +6 -0
  81. package/dist/domain/slash.js +11 -0
  82. package/dist/domain/usage.js +1 -0
  83. package/dist/domain/viewport.js +33 -0
  84. package/dist/entry.js +65 -40
  85. package/dist/gatewayClient.js +574 -0
  86. package/dist/gatewayTypes.js +1 -0
  87. package/dist/hooks/useCompletion.js +86 -0
  88. package/dist/hooks/useGitBranch.js +58 -0
  89. package/dist/hooks/useInputHistory.js +12 -0
  90. package/dist/hooks/useQueue.js +57 -0
  91. package/dist/hooks/useVirtualHistory.js +401 -0
  92. package/dist/lib/circularBuffer.js +43 -0
  93. package/dist/lib/clipboard.js +126 -0
  94. package/dist/lib/editor.js +41 -0
  95. package/dist/lib/editor.test.js +58 -0
  96. package/dist/lib/emoji.js +49 -0
  97. package/dist/lib/externalCli.js +11 -0
  98. package/dist/lib/forceTruecolor.js +26 -0
  99. package/dist/lib/fpsStore.js +36 -0
  100. package/dist/lib/gracefulExit.js +29 -0
  101. package/dist/lib/history.js +69 -0
  102. package/dist/lib/inputMetrics.js +143 -0
  103. package/dist/lib/liveProgress.js +51 -0
  104. package/dist/lib/liveProgress.test.js +89 -0
  105. package/dist/lib/mathUnicode.js +685 -0
  106. package/dist/lib/memory.js +123 -0
  107. package/dist/lib/memoryMonitor.js +76 -0
  108. package/dist/lib/messages.js +3 -0
  109. package/dist/lib/messages.test.js +25 -0
  110. package/dist/lib/osc52.js +53 -0
  111. package/dist/lib/perfPane.js +94 -0
  112. package/dist/lib/platform.js +312 -0
  113. package/dist/lib/precisionWheel.js +25 -0
  114. package/dist/lib/reasoning.js +39 -0
  115. package/dist/lib/rpc.js +26 -0
  116. package/dist/lib/subagentTree.js +287 -0
  117. package/dist/lib/syntax.js +89 -0
  118. package/dist/lib/terminalModes.js +46 -0
  119. package/dist/lib/terminalParity.js +48 -0
  120. package/dist/lib/terminalSetup.js +321 -0
  121. package/dist/lib/text.js +203 -0
  122. package/dist/lib/text.test.js +18 -0
  123. package/dist/lib/todo.js +2 -0
  124. package/dist/lib/todo.test.js +22 -0
  125. package/dist/lib/viewportStore.js +82 -0
  126. package/dist/lib/virtualHeights.js +61 -0
  127. package/dist/lib/wheelAccel.js +143 -0
  128. package/dist/theme.js +398 -0
  129. package/dist/types.js +1 -7
  130. package/package.json +2 -1
package/dist/app.js CHANGED
@@ -1,219 +1,15 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useMemo, useRef, useState } from 'react';
3
- import { Box, Text, useApp, useInput } from 'ink';
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // @ts-nocheck
3
+ // SPDX-License-Identifier: MIT
4
+ // Ported from CVC Agent (https://github.com/NousResearch/cvc)
5
+ // Original Copyright (c) 2025 Nous Research. CVC adaptations (c) 2026 Jai Kumar Meena.
4
6
  import { useStore } from '@nanostores/react';
7
+ import { GatewayProvider } from './app/gatewayContext.js';
8
+ import { $uiState } from './app/uiStore.js';
9
+ import { useMainApp } from './app/useMainApp.js';
5
10
  import { AppLayout } from './components/appLayout.js';
6
- import { Branding } from './components/branding.js';
7
- import { TextInput } from './components/textInput.js';
8
- import { Thinking } from './components/thinking.js';
9
- import { Transcript } from './components/transcript.js';
10
- import { appendDelta, beginAssistantTurn, endTurn, pushUserMessage, pushSystemMessage, } from './app/turnStore.js';
11
- import { $ui, $activeOverlay, openOverlay, closeOverlay, setBusy } from './app/uiStore.js';
12
- import { CVC_THEME } from './types.js';
13
- import { dispatchSlash } from './app/slash/registry.js';
14
- import { ModelPicker } from './components/overlays/modelPicker.js';
15
- import { SessionPicker, loadSessions } from './components/overlays/sessionPicker.js';
16
- import { SkillsHub } from './components/overlays/skillsHub.js';
17
- import { HelpOverlay } from './components/overlays/helpOverlay.js';
18
- import { ConfirmPrompt } from './components/overlays/confirmPrompt.js';
19
- import { SecretPrompt } from './components/overlays/secretPrompt.js';
20
- import { $prompt } from './app/promptStore.js';
21
- const InputLine = ({ onSubmit }) => {
22
- const [value, setValue] = useState('');
23
- const ui = useStore($ui);
24
- const overlay = useStore($activeOverlay);
25
- const prompt = useStore($prompt);
26
- if (overlay || prompt)
27
- return null; // overlay/prompt owns input
28
- if (ui.busy)
29
- return _jsx(Thinking, { label: "thinking" });
30
- return (_jsx(TextInput, { value: value, onChange: setValue, onSubmit: (v) => {
31
- const trimmed = v.trim();
32
- setValue('');
33
- if (trimmed)
34
- onSubmit(trimmed);
35
- }, placeholder: "ask CVC anything" }));
36
- };
37
- const StatusLine = ({ error }) => {
38
- if (!error)
39
- return null;
40
- return (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: CVC_THEME.primary, children: ["\u26A0 ", error] }) }));
41
- };
42
- const Overlays = ({ gateway, onPickModel, onPickSession, onPickSkill }) => {
43
- const overlay = useStore($activeOverlay);
44
- const [sessions, setSessions] = useState([]);
45
- const [skills, setSkills] = useState([]);
46
- useEffect(() => {
47
- if (overlay === 'sessionPicker') {
48
- try {
49
- setSessions(loadSessions());
50
- }
51
- catch {
52
- setSessions([]);
53
- }
54
- }
55
- if (overlay === 'skillsHub' && gateway) {
56
- gateway
57
- .send('skills.list', {})
58
- .then((res) => {
59
- const items = Array.isArray(res?.skills) ? res.skills : [];
60
- setSkills(items);
61
- })
62
- .catch(() => setSkills([]));
63
- }
64
- }, [overlay, gateway]);
65
- if (!overlay)
66
- return null;
67
- if (overlay === 'help')
68
- return _jsx(HelpOverlay, { onClose: closeOverlay });
69
- if (overlay === 'modelPicker') {
70
- // Static provider list — gateway can extend later via models.list RPC.
71
- const providers = [
72
- { slug: 'github-copilot', name: 'GitHub Copilot', models: ['claude-sonnet-4.6', 'gpt-5', 'gemini-2.5-pro'] },
73
- { slug: 'nvidia-nim', name: 'NVIDIA NIM', models: ['nemotron-3-super-120b', 'kimi-k2.5', 'minimax-m2.5'] },
74
- { slug: 'google', name: 'Google', models: ['gemini-3.1-pro-preview', 'gemini-3.1-flash-lite', 'gemma-4-31b'] },
75
- ];
76
- return (_jsx(ModelPicker, { providers: providers, onSelect: (p, m) => { onPickModel(`${p}/${m}`); closeOverlay(); }, onCancel: closeOverlay }));
77
- }
78
- if (overlay === 'sessionPicker') {
79
- return (_jsx(SessionPicker, { sessions: sessions, onSelect: (id) => {
80
- const s = sessions.find((x) => x.id === id);
81
- if (s)
82
- onPickSession(s);
83
- closeOverlay();
84
- }, onCancel: closeOverlay }));
85
- }
86
- if (overlay === 'skillsHub') {
87
- return (_jsx(SkillsHub, { skills: skills, onActivate: (s) => { onPickSkill(s); closeOverlay(); }, onCancel: closeOverlay }));
88
- }
89
- return null;
90
- };
91
- const Prompts = () => {
92
- const prompt = useStore($prompt);
93
- if (!prompt)
94
- return null;
95
- if (prompt.kind === 'confirm')
96
- return _jsx(ConfirmPrompt, {});
97
- if (prompt.kind === 'secret')
98
- return _jsx(SecretPrompt, {});
99
- return null;
100
- };
101
- export const App = ({ version, model, gateway }) => {
102
- const { exit } = useApp();
103
- const [error, setError] = useState(null);
104
- const [activeModel, setActiveModel] = useState(model);
105
- const gatewayRef = useRef(gateway ?? null);
106
- useInput((input, key) => {
107
- if (key.ctrl && (input === 'c' || input === 'd')) {
108
- exit();
109
- }
110
- });
111
- useEffect(() => {
112
- return () => {
113
- void gatewayRef.current?.close().catch(() => { });
114
- };
115
- }, []);
116
- const handleEffect = useMemo(() => (effect) => {
117
- switch (effect.kind) {
118
- case 'sys':
119
- if (effect.text)
120
- pushSystemMessage(effect.text);
121
- return;
122
- case 'panel':
123
- case 'page':
124
- if (effect.title)
125
- pushSystemMessage(`── ${effect.title} ──`);
126
- for (const sec of effect.sections ?? []) {
127
- if (sec.title)
128
- pushSystemMessage(`▸ ${sec.title}`);
129
- if (sec.text)
130
- pushSystemMessage(sec.text);
131
- for (const [k, v] of sec.rows ?? [])
132
- pushSystemMessage(` ${k}: ${v}`);
133
- }
134
- return;
135
- case 'overlay':
136
- if (effect.overlay === 'modelPicker')
137
- openOverlay('modelPicker');
138
- else if (effect.overlay === 'sessionPicker')
139
- openOverlay('sessionPicker');
140
- else if (effect.overlay === 'skillsHub')
141
- openOverlay('skillsHub');
142
- else if (effect.overlay === 'help')
143
- openOverlay('help');
144
- else
145
- pushSystemMessage(`overlay '${effect.overlay}' not yet implemented`);
146
- return;
147
- case 'rpc':
148
- if (effect.method && gatewayRef.current) {
149
- void gatewayRef.current
150
- .send(effect.method, effect.params ?? {})
151
- .catch((err) => setError(`rpc ${effect.method}: ${err.message}`));
152
- }
153
- return;
154
- case 'die':
155
- exit();
156
- return;
157
- case 'patchUi':
158
- case 'noop':
159
- default:
160
- return;
161
- }
162
- }, [exit]);
163
- const handleSubmit = async (text) => {
164
- // Slash command path
165
- if (text.startsWith('/')) {
166
- const ctx = {
167
- sid: null,
168
- ui: {},
169
- emit: handleEffect,
170
- history: () => [],
171
- rpc: gatewayRef.current
172
- ? (method, params) => gatewayRef.current.send(method, params ?? {})
173
- : undefined,
174
- };
175
- pushUserMessage(text);
176
- await dispatchSlash(text, ctx);
177
- return;
178
- }
179
- // Normal chat path
180
- const gw = gatewayRef.current;
181
- if (!gw) {
182
- setError('gateway not connected');
183
- return;
184
- }
185
- pushUserMessage(text);
186
- beginAssistantTurn();
187
- setBusy(true);
188
- setError(null);
189
- try {
190
- await gw.sendChat({ message: text }, {
191
- onDelta: (chunk) => appendDelta(chunk),
192
- onError: (err) => setError(err.message),
193
- });
194
- endTurn();
195
- }
196
- catch (err) {
197
- const msg = err.message;
198
- setError(msg);
199
- endTurn(msg);
200
- }
201
- finally {
202
- setBusy(false);
203
- }
204
- };
205
- return (_jsxs(AppLayout, { children: [_jsx(Branding, { version: version, model: activeModel }), _jsx(Transcript, {}), _jsx(StatusLine, { error: error }), _jsx(Overlays, { gateway: gatewayRef.current, onPickModel: (m) => {
206
- setActiveModel(m);
207
- pushSystemMessage(`model → ${m}`);
208
- if (gatewayRef.current) {
209
- void gatewayRef.current.send('model.set', { model: m }).catch(() => { });
210
- }
211
- }, onPickSession: (s) => {
212
- pushSystemMessage(`session → ${s.id}`);
213
- if (gatewayRef.current) {
214
- void gatewayRef.current.send('session.resume', { id: s.id });
215
- }
216
- }, onPickSkill: (s) => {
217
- pushSystemMessage(`skill → ${s.name}`);
218
- } }), _jsx(Prompts, {}), _jsx(InputLine, { onSubmit: handleSubmit })] }));
219
- };
11
+ export function App({ gw }) {
12
+ const { appActions, appComposer, appProgress, appStatus, appTranscript, gateway } = useMainApp(gw);
13
+ const { mouseTracking } = useStore($uiState);
14
+ return (_jsx(GatewayProvider, { value: gateway, children: _jsx(AppLayout, { actions: appActions, composer: appComposer, mouseTracking: mouseTracking, progress: appProgress, status: appStatus, transcript: appTranscript }) }));
15
+ }
package/dist/banner.js CHANGED
@@ -1,5 +1,35 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Ported from CVC Agent (https://github.com/NousResearch/cvc)
3
+ // Original Copyright (c) 2025 Nous Research. CVC adaptations (c) 2026 Jai Kumar Meena.
4
+ //
1
5
  // CVC ASCII banner. Rendered once at startup by <Branding/>.
2
6
  // Colour applied at render-time via Ink <Text color="..."> wrappers.
7
+ import { readFileSync } from 'node:fs';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { dirname, resolve } from 'node:path';
10
+ function readPkgVersion() {
11
+ try {
12
+ // src/banner.ts → ../package.json (src) or dist/banner.js → ../package.json (dist)
13
+ const here = dirname(fileURLToPath(import.meta.url));
14
+ const candidates = [resolve(here, '../package.json'), resolve(here, '../../package.json')];
15
+ for (const p of candidates) {
16
+ try {
17
+ const raw = readFileSync(p, 'utf8');
18
+ const parsed = JSON.parse(raw);
19
+ if (parsed.name === 'cvc-tui' && typeof parsed.version === 'string') {
20
+ return parsed.version;
21
+ }
22
+ }
23
+ catch {
24
+ /* try next */
25
+ }
26
+ }
27
+ }
28
+ catch {
29
+ /* fall through */
30
+ }
31
+ return '0.0.0';
32
+ }
3
33
  export const CVC_BANNER = String.raw `
4
34
  ██████╗██╗ ██╗ ██████╗
5
35
  ██╔════╝██║ ██║██╔════╝
@@ -8,13 +38,20 @@ export const CVC_BANNER = String.raw `
8
38
  ╚██████╗ ╚████╔╝ ╚██████╗
9
39
  ╚═════╝ ╚═══╝ ╚═════╝
10
40
  `.trim();
11
- export const CVC_TAGLINE = 'Cognitive Version Control';
41
+ export const CVC_TAGLINE = 'Cognitive Version Control — git for your AI\u2019s mind';
42
+ export const CVC_BOOT_TIP = 'Type /help for commands · Ctrl+C to exit';
12
43
  export const BANNER_COLOR = '#e63946';
13
44
  export const TAGLINE_COLOR = '#4a9eff';
45
+ /**
46
+ * Version of cvc-tui as published in package.json.
47
+ * Wired here so the banner is never out-of-date with the package version
48
+ * (this fixes the v0.0.1 fallback bug).
49
+ */
50
+ export const CVC_VERSION = readPkgVersion();
14
51
  /**
15
52
  * Returns the banner as a plain (uncoloured) string suitable for tests
16
53
  * and for non-TTY fallbacks. The TTY renderer colours it via Ink.
17
54
  */
18
- export function renderBannerPlain({ version = '0.0.1', model = 'unknown' } = {}) {
19
- return [CVC_BANNER, '', `${CVC_TAGLINE} v${version} · model: ${model}`].join('\n');
55
+ export function renderBannerPlain({ version = CVC_VERSION, model = 'unknown' } = {}) {
56
+ return [CVC_BANNER, '', `${CVC_TAGLINE} v${version} · model: ${model}`, CVC_BOOT_TIP].join('\n');
20
57
  }