codevf 1.0.0 → 1.0.1

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 (199) hide show
  1. package/LICENSE +30 -21
  2. package/README.md +6 -1
  3. package/bin/codevf-mcp.js +11 -0
  4. package/dist/commands/fix.d.ts +5 -1
  5. package/dist/commands/fix.d.ts.map +1 -1
  6. package/dist/commands/fix.js +170 -13
  7. package/dist/commands/fix.js.map +1 -1
  8. package/dist/commands/init.d.ts.map +1 -1
  9. package/dist/commands/init.js +72 -2
  10. package/dist/commands/init.js.map +1 -1
  11. package/dist/commands/mcp-tools.d.ts +17 -0
  12. package/dist/commands/mcp-tools.d.ts.map +1 -0
  13. package/dist/commands/mcp-tools.js +237 -0
  14. package/dist/commands/mcp-tools.js.map +1 -0
  15. package/dist/commands/setup.d.ts +8 -0
  16. package/dist/commands/setup.d.ts.map +1 -0
  17. package/dist/commands/setup.js +250 -0
  18. package/dist/commands/setup.js.map +1 -0
  19. package/dist/commands/welcome.d.ts +9 -0
  20. package/dist/commands/welcome.d.ts.map +1 -0
  21. package/dist/commands/welcome.js +175 -0
  22. package/dist/commands/welcome.js.map +1 -0
  23. package/dist/index.js +194 -149
  24. package/dist/index.js.map +1 -1
  25. package/dist/lib/api/client.d.ts +28 -0
  26. package/dist/lib/api/client.d.ts.map +1 -0
  27. package/dist/lib/api/client.js +66 -0
  28. package/dist/lib/api/client.js.map +1 -0
  29. package/dist/lib/api/tasks.d.ts +36 -0
  30. package/dist/lib/api/tasks.d.ts.map +1 -0
  31. package/dist/lib/api/tasks.js +62 -0
  32. package/dist/lib/api/tasks.js.map +1 -0
  33. package/dist/lib/api/websocket.d.ts +50 -0
  34. package/dist/lib/api/websocket.d.ts.map +1 -0
  35. package/dist/lib/api/websocket.js +153 -0
  36. package/dist/lib/api/websocket.js.map +1 -0
  37. package/dist/lib/auth/oauth-flow.d.ts +37 -0
  38. package/dist/lib/auth/oauth-flow.d.ts.map +1 -0
  39. package/dist/lib/auth/oauth-flow.js +119 -0
  40. package/dist/lib/auth/oauth-flow.js.map +1 -0
  41. package/dist/lib/auth/token-manager.d.ts +26 -0
  42. package/dist/lib/auth/token-manager.d.ts.map +1 -0
  43. package/dist/lib/auth/token-manager.js +87 -0
  44. package/dist/lib/auth/token-manager.js.map +1 -0
  45. package/dist/lib/config/manager.d.ts +50 -0
  46. package/dist/lib/config/manager.d.ts.map +1 -0
  47. package/dist/lib/config/manager.js +84 -0
  48. package/dist/lib/config/manager.js.map +1 -0
  49. package/dist/lib/utils/errors.d.ts +28 -0
  50. package/dist/lib/utils/errors.d.ts.map +1 -0
  51. package/dist/lib/utils/errors.js +44 -0
  52. package/dist/lib/utils/errors.js.map +1 -0
  53. package/dist/lib/utils/logger.d.ts +20 -0
  54. package/dist/lib/utils/logger.d.ts.map +1 -0
  55. package/dist/lib/utils/logger.js +40 -0
  56. package/dist/lib/utils/logger.js.map +1 -0
  57. package/dist/mcp/index.d.ts +7 -0
  58. package/dist/mcp/index.d.ts.map +1 -0
  59. package/dist/mcp/index.js +158 -0
  60. package/dist/mcp/index.js.map +1 -0
  61. package/dist/mcp/tools/chat.d.ts +30 -0
  62. package/dist/mcp/tools/chat.d.ts.map +1 -0
  63. package/dist/mcp/tools/chat.js +82 -0
  64. package/dist/mcp/tools/chat.js.map +1 -0
  65. package/dist/mcp/tools/instant.d.ts +36 -0
  66. package/dist/mcp/tools/instant.d.ts.map +1 -0
  67. package/dist/mcp/tools/instant.js +100 -0
  68. package/dist/mcp/tools/instant.js.map +1 -0
  69. package/dist/modules/aiAgent.d.ts +75 -0
  70. package/dist/modules/aiAgent.d.ts.map +1 -0
  71. package/dist/modules/aiAgent.js +707 -0
  72. package/dist/modules/aiAgent.js.map +1 -0
  73. package/dist/modules/api.d.ts +7 -0
  74. package/dist/modules/api.d.ts.map +1 -1
  75. package/dist/modules/api.js +13 -4
  76. package/dist/modules/api.js.map +1 -1
  77. package/dist/modules/commandHandler.d.ts +40 -0
  78. package/dist/modules/commandHandler.d.ts.map +1 -0
  79. package/dist/modules/commandHandler.js +345 -0
  80. package/dist/modules/commandHandler.js.map +1 -0
  81. package/dist/modules/config.d.ts +2 -0
  82. package/dist/modules/config.d.ts.map +1 -1
  83. package/dist/modules/config.js +9 -0
  84. package/dist/modules/config.js.map +1 -1
  85. package/dist/modules/constants.d.ts +83 -0
  86. package/dist/modules/constants.d.ts.map +1 -0
  87. package/dist/modules/constants.js +75 -0
  88. package/dist/modules/constants.js.map +1 -0
  89. package/dist/modules/permissions.d.ts +14 -0
  90. package/dist/modules/permissions.d.ts.map +1 -1
  91. package/dist/modules/permissions.js +94 -0
  92. package/dist/modules/permissions.js.map +1 -1
  93. package/dist/modules/toolRegistry.d.ts +50 -0
  94. package/dist/modules/toolRegistry.d.ts.map +1 -0
  95. package/dist/modules/toolRegistry.js +114 -0
  96. package/dist/modules/toolRegistry.js.map +1 -0
  97. package/dist/modules/tunnel.d.ts +33 -0
  98. package/dist/modules/tunnel.d.ts.map +1 -0
  99. package/dist/modules/tunnel.js +79 -0
  100. package/dist/modules/tunnel.js.map +1 -0
  101. package/dist/modules/vibeHelper.d.ts +16 -0
  102. package/dist/modules/vibeHelper.d.ts.map +1 -0
  103. package/dist/modules/vibeHelper.js +38 -0
  104. package/dist/modules/vibeHelper.js.map +1 -0
  105. package/dist/modules/websocket.d.ts +9 -0
  106. package/dist/modules/websocket.d.ts.map +1 -1
  107. package/dist/modules/websocket.js +70 -0
  108. package/dist/modules/websocket.js.map +1 -1
  109. package/dist/tools/consultEngineer.d.ts +13 -0
  110. package/dist/tools/consultEngineer.d.ts.map +1 -0
  111. package/dist/tools/consultEngineer.js +161 -0
  112. package/dist/tools/consultEngineer.js.map +1 -0
  113. package/dist/tools/realtimeChat.d.ts +9 -0
  114. package/dist/tools/realtimeChat.d.ts.map +1 -0
  115. package/dist/tools/realtimeChat.js +101 -0
  116. package/dist/tools/realtimeChat.js.map +1 -0
  117. package/dist/types/index.d.ts +183 -0
  118. package/dist/types/index.d.ts.map +1 -1
  119. package/dist/types/index.js.map +1 -1
  120. package/dist/ui/InteractiveApp.d.ts +13 -0
  121. package/dist/ui/InteractiveApp.d.ts.map +1 -0
  122. package/dist/ui/InteractiveApp.js +84 -0
  123. package/dist/ui/InteractiveApp.js.map +1 -0
  124. package/dist/ui/InteractivePrompt.d.ts +53 -0
  125. package/dist/ui/InteractivePrompt.d.ts.map +1 -0
  126. package/dist/ui/InteractivePrompt.js +422 -0
  127. package/dist/ui/InteractivePrompt.js.map +1 -0
  128. package/dist/ui/LiveSession.d.ts +2 -0
  129. package/dist/ui/LiveSession.d.ts.map +1 -1
  130. package/dist/ui/LiveSession.js +461 -180
  131. package/dist/ui/LiveSession.js.map +1 -1
  132. package/dist/ui/PromptInput.d.ts +14 -0
  133. package/dist/ui/PromptInput.d.ts.map +1 -0
  134. package/dist/ui/PromptInput.js +206 -0
  135. package/dist/ui/PromptInput.js.map +1 -0
  136. package/dist/ui/SessionUI.d.ts +40 -0
  137. package/dist/ui/SessionUI.d.ts.map +1 -0
  138. package/dist/ui/SessionUI.js +227 -0
  139. package/dist/ui/SessionUI.js.map +1 -0
  140. package/dist/ui/input/Command.d.ts +22 -0
  141. package/dist/ui/input/Command.d.ts.map +1 -0
  142. package/dist/ui/input/Command.js +30 -0
  143. package/dist/ui/input/Command.js.map +1 -0
  144. package/dist/ui/input/CustomInput.d.ts +15 -0
  145. package/dist/ui/input/CustomInput.d.ts.map +1 -0
  146. package/dist/ui/input/CustomInput.js +182 -0
  147. package/dist/ui/input/CustomInput.js.map +1 -0
  148. package/dist/ui/input/handlers/handleCursor.d.ts +22 -0
  149. package/dist/ui/input/handlers/handleCursor.d.ts.map +1 -0
  150. package/dist/ui/input/handlers/handleCursor.js +53 -0
  151. package/dist/ui/input/handlers/handleCursor.js.map +1 -0
  152. package/dist/ui/input/handlers/handleEdit.d.ts +18 -0
  153. package/dist/ui/input/handlers/handleEdit.d.ts.map +1 -0
  154. package/dist/ui/input/handlers/handleEdit.js +55 -0
  155. package/dist/ui/input/handlers/handleEdit.js.map +1 -0
  156. package/dist/ui/input/handlers/handleHistory.d.ts +18 -0
  157. package/dist/ui/input/handlers/handleHistory.d.ts.map +1 -0
  158. package/dist/ui/input/handlers/handleHistory.js +85 -0
  159. package/dist/ui/input/handlers/handleHistory.js.map +1 -0
  160. package/dist/ui/input/handlers/handlePaste.d.ts +19 -0
  161. package/dist/ui/input/handlers/handlePaste.d.ts.map +1 -0
  162. package/dist/ui/input/handlers/handlePaste.js +49 -0
  163. package/dist/ui/input/handlers/handlePaste.js.map +1 -0
  164. package/dist/ui/input/handlers/handleSubmit.d.ts +18 -0
  165. package/dist/ui/input/handlers/handleSubmit.d.ts.map +1 -0
  166. package/dist/ui/input/handlers/handleSubmit.js +39 -0
  167. package/dist/ui/input/handlers/handleSubmit.js.map +1 -0
  168. package/dist/ui/input/helpers.d.ts +4 -0
  169. package/dist/ui/input/helpers.d.ts.map +1 -0
  170. package/dist/ui/input/helpers.js +13 -0
  171. package/dist/ui/input/helpers.js.map +1 -0
  172. package/dist/ui/input/keyMatchers.d.ts +14 -0
  173. package/dist/ui/input/keyMatchers.d.ts.map +1 -0
  174. package/dist/ui/input/keyMatchers.js +49 -0
  175. package/dist/ui/input/keyMatchers.js.map +1 -0
  176. package/dist/ui/input/types.d.ts +33 -0
  177. package/dist/ui/input/types.d.ts.map +1 -0
  178. package/dist/ui/input/types.js +2 -0
  179. package/dist/ui/input/types.js.map +1 -0
  180. package/dist/ui/promptWithModes.d.ts +12 -0
  181. package/dist/ui/promptWithModes.d.ts.map +1 -0
  182. package/dist/ui/promptWithModes.js +24 -0
  183. package/dist/ui/promptWithModes.js.map +1 -0
  184. package/dist/ui/renderPrompt.d.ts +12 -0
  185. package/dist/ui/renderPrompt.d.ts.map +1 -0
  186. package/dist/ui/renderPrompt.js +14 -0
  187. package/dist/ui/renderPrompt.js.map +1 -0
  188. package/dist/ui/simplePrompt.d.ts +7 -0
  189. package/dist/ui/simplePrompt.d.ts.map +1 -0
  190. package/dist/ui/simplePrompt.js +38 -0
  191. package/dist/ui/simplePrompt.js.map +1 -0
  192. package/dist/ui/spinner.d.ts +7 -0
  193. package/dist/ui/spinner.d.ts.map +1 -0
  194. package/dist/ui/spinner.js +13 -0
  195. package/dist/ui/spinner.js.map +1 -0
  196. package/package.json +36 -25
  197. package/ARCHITECTURE.md +0 -285
  198. package/BUILD_SUMMARY.md +0 -340
  199. package/QUICKSTART.md +0 -180
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Welcome screen for first-time users
3
+ */
4
+ import chalk from 'chalk';
5
+ import prompts from 'prompts';
6
+ import { setupCommand } from './setup.js';
7
+ import { ConfigManager } from '../lib/config/manager.js';
8
+ const WELCOME_ART = `
9
+ ╔═══════════════════════════════════════════════════════════╗
10
+ ║ ║
11
+ ║ █████╗ ██████╗ ██████╗ ███████╗██╗ ██╗███████╗ ║
12
+ ║ ██╔══██╗██╔═══██╗██╔══██╗██╔════╝██║ ██║██╔════╝ ║
13
+ ║ ██║ ╚═╝██║ ██║██║ ██║█████╗ ╚██╗ ██╔╝█████╗ ║
14
+ ║ ██║ ██╗██║ ██║██║ ██║██╔══╝ ╚████╔╝ ██╔══╝ ║
15
+ ║ ╚█████╔╝╚██████╔╝██████╔╝███████╗ ╚██╔╝ ██║ ║
16
+ ║ ╚════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ║
17
+ ║ ║
18
+ ║ Live Debugging with Vetted Engineers ║
19
+ ║ ║
20
+ ╚═══════════════════════════════════════════════════════════╝
21
+ `;
22
+ export async function welcomeCommand() {
23
+ console.clear();
24
+ console.log(chalk.cyan(WELCOME_ART));
25
+ console.log(chalk.bold('\n👋 Welcome to CodeVF!\n'));
26
+ console.log('Get help from expert engineers when you need it most.\n');
27
+ const { setupType } = await prompts({
28
+ type: 'select',
29
+ name: 'setupType',
30
+ message: 'How would you like to use CodeVF?',
31
+ choices: [
32
+ {
33
+ title: chalk.bold.green('🤖 Claude Code Integration') + chalk.dim(' (Recommended)'),
34
+ description: 'Add CodeVF tools to Claude Code - ask Claude to consult engineers',
35
+ value: 'mcp',
36
+ },
37
+ {
38
+ title: chalk.bold.blue('💻 Standalone CLI') + chalk.dim(' (Beta)'),
39
+ description: 'Use CodeVF directly from your terminal for live debugging sessions',
40
+ value: 'cli',
41
+ },
42
+ {
43
+ title: chalk.dim('ℹ️ Learn More'),
44
+ description: 'Show me what CodeVF can do',
45
+ value: 'info',
46
+ },
47
+ {
48
+ title: chalk.dim('❌ Exit'),
49
+ description: 'Exit setup',
50
+ value: 'exit',
51
+ },
52
+ ],
53
+ initial: 0,
54
+ });
55
+ if (!setupType || setupType === 'exit') {
56
+ console.log(chalk.dim('\n👋 Run `codevf` anytime to get started!\n'));
57
+ return;
58
+ }
59
+ switch (setupType) {
60
+ case 'mcp':
61
+ await setupMCPFlow();
62
+ break;
63
+ case 'cli':
64
+ await setupCLIFlow();
65
+ break;
66
+ case 'info':
67
+ await showInfo();
68
+ break;
69
+ }
70
+ }
71
+ async function setupMCPFlow() {
72
+ console.log(chalk.bold.cyan('\n🤖 Claude Code Integration Setup\n'));
73
+ console.log(chalk.dim('This will:'));
74
+ console.log(chalk.dim(' 1. Authenticate with CodeVF'));
75
+ console.log(chalk.dim(' 2. Configure Claude Code to use CodeVF tools'));
76
+ console.log(chalk.dim(' 3. Enable codevf-instant and codevf-chat commands\n'));
77
+ const { proceed } = await prompts({
78
+ type: 'confirm',
79
+ name: 'proceed',
80
+ message: 'Ready to set up?',
81
+ initial: true,
82
+ });
83
+ if (!proceed) {
84
+ console.log(chalk.dim('\n👋 Run `codevf setup` anytime to configure!\n'));
85
+ return;
86
+ }
87
+ // Run the setup command
88
+ await setupCommand();
89
+ console.log(chalk.bold.green('\n✨ All set! Here\'s what you can do:\n'));
90
+ console.log(chalk.cyan('In Claude Code, you can now ask:\n'));
91
+ console.log(chalk.dim(' "Use codevf-instant to ask an engineer if this fix works"'));
92
+ console.log(chalk.dim(' "Use codevf-chat to debug this complex issue with an engineer"\n'));
93
+ console.log(chalk.bold('Available Tools:'));
94
+ console.log(chalk.green(' • codevf-instant') + chalk.dim(' - Quick validation (1-10 credits, ~2 min)'));
95
+ console.log(chalk.green(' • codevf-chat') + chalk.dim(' - Extended session (4-1920 credits, up to 16 hours)\n'));
96
+ }
97
+ async function setupCLIFlow() {
98
+ console.log(chalk.bold.blue('\n💻 Standalone CLI Setup\n'));
99
+ console.log(chalk.yellow('⚠️ The CLI is currently in beta. For the best experience, we recommend'));
100
+ console.log(chalk.yellow(' using Claude Code integration instead.\n'));
101
+ console.log(chalk.dim('CLI Features:'));
102
+ console.log(chalk.dim(' • Live debugging sessions with engineers'));
103
+ console.log(chalk.dim(' • Real-time chat and screen sharing'));
104
+ console.log(chalk.dim(' • Project initialization and sync\n'));
105
+ const { proceed } = await prompts({
106
+ type: 'confirm',
107
+ name: 'proceed',
108
+ message: 'Continue with CLI setup?',
109
+ initial: false,
110
+ });
111
+ if (!proceed) {
112
+ console.log(chalk.dim('\n💡 Tip: Try `codevf` again and choose Claude Code Integration!\n'));
113
+ return;
114
+ }
115
+ console.log(chalk.bold('\n📚 CLI Commands:\n'));
116
+ console.log(chalk.cyan(' codevf login') + chalk.dim(' - Authenticate with CodeVF'));
117
+ console.log(chalk.cyan(' codevf init') + chalk.dim(' - Initialize project'));
118
+ console.log(chalk.cyan(' codevf fix') + chalk.dim(' - Start live debugging session'));
119
+ console.log(chalk.cyan(' codevf sync') + chalk.dim(' - Sync your code\n'));
120
+ const { startLogin } = await prompts({
121
+ type: 'confirm',
122
+ name: 'startLogin',
123
+ message: 'Start with login?',
124
+ initial: true,
125
+ });
126
+ if (startLogin) {
127
+ console.log(chalk.dim('\nRun: codevf login\n'));
128
+ }
129
+ }
130
+ async function showInfo() {
131
+ console.log(chalk.bold.cyan('\n📖 What is CodeVF?\n'));
132
+ console.log('CodeVF connects you with vetted software engineers for live debugging');
133
+ console.log('and code review. Get expert help when you need it most.\n');
134
+ console.log(chalk.bold('🎯 Use Cases:\n'));
135
+ console.log(chalk.green(' ✓ ') + 'Complex bugs that AI can\'t solve alone');
136
+ console.log(chalk.green(' ✓ ') + 'Architecture and design decisions');
137
+ console.log(chalk.green(' ✓ ') + 'Code review and security audits');
138
+ console.log(chalk.green(' ✓ ') + 'Performance optimization');
139
+ console.log(chalk.green(' ✓ ') + 'Learning from experienced developers\n');
140
+ console.log(chalk.bold('💰 Credit-Based Pricing:\n'));
141
+ console.log(chalk.dim(' • Quick questions: 1-10 credits (~$0.10-$1.00)'));
142
+ console.log(chalk.dim(' • Extended sessions: 2 credits/minute (~$0.20/min)\n'));
143
+ console.log(chalk.bold('🔒 Security:\n'));
144
+ console.log(chalk.dim(' • Engineers only see what you share'));
145
+ console.log(chalk.dim(' • All sessions are private and secure'));
146
+ console.log(chalk.dim(' • No code is stored after sessions\n'));
147
+ const { next } = await prompts({
148
+ type: 'select',
149
+ name: 'next',
150
+ message: 'What would you like to do?',
151
+ choices: [
152
+ { title: 'Set up Claude Code Integration', value: 'mcp' },
153
+ { title: 'Set up Standalone CLI', value: 'cli' },
154
+ { title: 'Exit', value: 'exit' },
155
+ ],
156
+ });
157
+ switch (next) {
158
+ case 'mcp':
159
+ await setupMCPFlow();
160
+ break;
161
+ case 'cli':
162
+ await setupCLIFlow();
163
+ break;
164
+ }
165
+ }
166
+ /**
167
+ * Check if this is the first run
168
+ */
169
+ export function isFirstRun() {
170
+ const mcpConfig = new ConfigManager('mcp-config.json');
171
+ const cliConfig = new ConfigManager('config.json');
172
+ // First run if neither config exists
173
+ return !mcpConfig.exists() && !cliConfig.exists();
174
+ }
175
+ //# sourceMappingURL=welcome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"welcome.js","sourceRoot":"","sources":["../../src/commands/welcome.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,177 +4,189 @@ import 'dotenv/config';
4
4
  import yargs from 'yargs';
5
5
  import { hideBin } from 'yargs/helpers';
6
6
  import chalk from 'chalk';
7
- import prompts from 'prompts';
8
- import { exec, spawn } from 'child_process';
9
- import { promisify } from 'util';
10
7
  import { loginCommand } from './commands/login.js';
11
8
  import { logoutCommand } from './commands/logout.js';
9
+ import { setupCommand } from './commands/setup.js';
10
+ import { welcomeCommand, isFirstRun } from './commands/welcome.js';
12
11
  import { initCommand } from './commands/init.js';
13
12
  import { syncCommand } from './commands/sync.js';
14
13
  import { fixCommand } from './commands/fix.js';
15
14
  import { tasksCommand } from './commands/tasks.js';
16
15
  import { handleError } from './utils/errors.js';
17
16
  import { ConfigManager } from './modules/config.js';
18
- const CLI_VERSION = '1.0.0';
19
- const execAsync = promisify(exec);
17
+ import { AiAgent } from './modules/aiAgent.js';
18
+ import React from 'react';
19
+ import { render } from 'ink';
20
+ import { CLI_VERSION } from './modules/constants.js';
21
+ import { InteractiveApp } from './ui/InteractiveApp.js';
22
+ import { renderHeader, renderQuickCommands, showModeSwitched, } from './ui/SessionUI.js';
23
+ import { handleSlashCommand, isSlashCommand, handleHybridMode, handleAiMode, handleHumanMode, } from './modules/commandHandler.js';
20
24
  const args = hideBin(process.argv);
21
- if (args.length === 0) {
22
- // Minimal interactive entry (Codex-style): no question, just a prompt
23
- (async () => {
25
+ /**
26
+ * Safely loads config without throwing errors
27
+ */
28
+ function loadConfigSafely(configManager) {
29
+ if (configManager.isInitialized()) {
24
30
  try {
25
- const cwd = process.cwd();
26
- const configManager = new ConfigManager();
27
- const isInitialized = configManager.isInitialized();
28
- const boxInfo = isInitialized
29
- ? chalk.green(`Initialized project: ${configManager.loadConfig().projectId}`)
30
- : chalk.yellow('Not initialized (run `codevf init`)');
31
- // Header box similar to Codex
32
- const boxLines = [
33
- `${chalk.dim('>_')} ${chalk.bold.white('CodeVF CLI')} ${chalk.dim(`(v${CLI_VERSION})`)}`,
34
- `${chalk.dim('model:')} ${chalk.cyan('codevf-live')} ${chalk.dim('/human to ask for help')}`,
35
- `${chalk.dim('dir:')} ${chalk.cyan(cwd)}`,
36
- `${chalk.dim('init:')} ${boxInfo}`,
37
- ];
38
- const maxLen = Math.max(...boxLines.map((l) => l.length));
39
- const width = maxLen + 2; // padding inside box
40
- const border = chalk.dim('┌' + '─'.repeat(width) + '┐');
41
- const footer = chalk.dim('└' + '─'.repeat(width) + '┘');
42
- console.log('\n' + border);
43
- boxLines.forEach((line) => {
44
- const padLength = width - line.length;
45
- const padding = padLength > 0 ? ' '.repeat(padLength) : '';
46
- console.log(chalk.dim('│') + line + padding + chalk.dim('│'));
47
- });
48
- console.log(footer + '\n');
49
- console.log(chalk.dim('To get started, type your issue or one of these commands:\n'));
50
- const commands = [
51
- ['/human <text>', 'ask for help from a human engineer'],
52
- ['/shell', 'switch to local shell (not shared)'],
53
- ['/codevf', 'return from shell to session'],
54
- ['/end', 'end the session'],
55
- ['/tasks', 'list open tasks'],
56
- ['/cancel <id>', 'cancel a task'],
57
- ['/?', 'list commands'],
58
- ['/exit', 'quit the CLI'],
59
- ];
60
- commands.forEach(([cmd, desc]) => {
61
- console.log(`${chalk.white(cmd.padEnd(15))}${chalk.dim('–')} ${chalk.gray(desc)}`);
31
+ return configManager.loadConfig();
32
+ }
33
+ catch (error) {
34
+ return null;
35
+ }
36
+ }
37
+ return null;
38
+ }
39
+ /**
40
+ * Interactive session mode - main entry point when no arguments provided
41
+ */
42
+ async function runInteractiveMode() {
43
+ try {
44
+ const configManager = new ConfigManager();
45
+ let loadedConfig = loadConfigSafely(configManager);
46
+ const isInitialized = configManager.isInitialized();
47
+ let aiEnabled = !!loadedConfig?.ai?.enabled;
48
+ let routingMode = aiEnabled ? 'hybrid' : 'human';
49
+ let agentMode = 'build';
50
+ const aiAgent = new AiAgent(configManager);
51
+ const logUserMessage = (message) => {
52
+ // Display the user's input inside a full-width highlight block, left-aligned
53
+ const columns = process.stdout.columns || 80;
54
+ const lines = message.split(/\r?\n/);
55
+ const contentWidth = Math.min(Math.max(...lines.map((line) => line.length), 1), columns - 6);
56
+ const horizontalPad = ' ';
57
+ const totalWidth = Math.min(columns, contentWidth + horizontalPad.length * 2);
58
+ const fullLine = (text) => {
59
+ const padded = text.padEnd(contentWidth, ' ');
60
+ return chalk.bgGray.white(`${horizontalPad}${padded}${horizontalPad}`);
61
+ };
62
+ lines.forEach((line) => {
63
+ console.log(fullLine(line));
62
64
  });
63
- console.log();
65
+ };
66
+ // Render header and quick commands
67
+ renderHeader(isInitialized, loadedConfig);
68
+ renderQuickCommands(isInitialized, aiEnabled, aiEnabled, agentMode);
69
+ // Command submission handler
70
+ const handleSubmit = async (text, mode) => {
71
+ const trimmed = text.trim();
72
+ logUserMessage(trimmed);
73
+ // Handle slash commands
74
+ if (isSlashCommand(trimmed)) {
75
+ await handleSlashCommand(trimmed, {
76
+ configManager,
77
+ aiAgent,
78
+ routingMode: mode,
79
+ agentMode,
80
+ aiEnabled,
81
+ autoAcceptMode: false,
82
+ loadedConfig,
83
+ });
84
+ return;
85
+ }
86
+ // Route to appropriate mode handler
87
+ if (mode === 'hybrid' && aiEnabled) {
88
+ await handleHybridMode(trimmed, {
89
+ configManager,
90
+ aiAgent,
91
+ routingMode: mode,
92
+ agentMode,
93
+ aiEnabled,
94
+ autoAcceptMode: false,
95
+ loadedConfig,
96
+ });
97
+ }
98
+ else if (mode === 'ai' && aiEnabled) {
99
+ await handleAiMode(trimmed, {
100
+ configManager,
101
+ aiAgent,
102
+ routingMode: mode,
103
+ agentMode,
104
+ aiEnabled,
105
+ autoAcceptMode: false,
106
+ loadedConfig,
107
+ });
108
+ }
109
+ else {
110
+ await handleHumanMode(trimmed);
111
+ }
112
+ };
113
+ // Try to use ink - it will handle raw mode setup internally
114
+ try {
115
+ // Render ink app and keep it mounted
116
+ render(React.createElement(InteractiveApp, {
117
+ initialRoutingMode: routingMode,
118
+ initialAgentMode: agentMode,
119
+ aiEnabled,
120
+ onSubmit: handleSubmit,
121
+ onModeChange: (mode) => {
122
+ routingMode = mode;
123
+ showModeSwitched(mode);
124
+ },
125
+ onAgentModeChange: (mode) => {
126
+ agentMode = mode;
127
+ },
128
+ }));
129
+ }
130
+ catch (inkError) {
131
+ // Fallback if ink fails
132
+ console.error(chalk.yellow('\nWarning: Interactive mode requires TTY support'));
133
+ console.log(chalk.yellow('\nFalling back to compatibility mode (paste support disabled)'));
134
+ console.log(chalk.cyan('\nFor full features with paste support, run directly:'));
135
+ console.log(chalk.white(' cd ' + process.cwd()));
136
+ console.log(chalk.white(' CODEVF_API_URL=http://localhost:3000 tsx src/index.ts\n'));
137
+ const readline = await import('readline');
64
138
  while (true) {
65
- let shellMode = false;
66
- const shellHistory = [];
67
- console.log(chalk.dim('Type /? for menu'));
68
- const { line } = await prompts({
69
- type: 'text',
70
- name: 'line',
71
- message: chalk.bold('codevf> '),
139
+ const rl = readline.createInterface({
140
+ input: process.stdin,
141
+ output: process.stdout,
72
142
  });
73
- if (!line || !line.trim()) {
74
- // empty input: re-prompt instead of exiting
75
- continue;
76
- }
77
- let trimmed = line.trim();
78
- // Any slash command is handled locally; do not start a session
79
- if (trimmed.startsWith('/')) {
80
- if (['/?', '/help', '/commands'].includes(trimmed)) {
81
- console.log();
82
- console.log(chalk.white('/human <text>').padEnd(18) + chalk.gray('ask for help from a human engineer'));
83
- console.log(chalk.white('/shell').padEnd(18) + chalk.gray('local shell (not shared)'));
84
- console.log(chalk.white('/codevf').padEnd(18) + chalk.gray('back to session'));
85
- console.log(chalk.white('/end').padEnd(18) + chalk.gray('end the session'));
86
- console.log(chalk.white('/tasks').padEnd(18) + chalk.gray('list open tasks'));
87
- console.log(chalk.white('/cancel <id>').padEnd(18) + chalk.gray('cancel a task'));
88
- console.log(chalk.white('/?').padEnd(18) + chalk.gray('list commands'));
89
- console.log(chalk.white('/exit').padEnd(18) + chalk.gray('quit'));
90
- console.log();
91
- continue;
92
- }
93
- else if (trimmed === '/tasks') {
94
- await tasksCommand(undefined);
143
+ const getModeIndicator = (mode) => {
144
+ switch (mode) {
145
+ case 'hybrid':
146
+ return chalk.green('[Hybrid]');
147
+ case 'ai':
148
+ return chalk.cyan('[AI]');
149
+ case 'human':
150
+ return chalk.magenta('[Human]');
151
+ default:
152
+ return chalk.white('[Unknown]');
95
153
  }
96
- else if (trimmed.startsWith('/cancel ')) {
97
- const id = trimmed.replace('/cancel', '').trim();
98
- if (!id) {
99
- console.log(chalk.red('Usage: /cancel <taskId>'));
100
- }
101
- else {
102
- await tasksCommand(id);
103
- }
104
- }
105
- else if (trimmed === '/exit' || trimmed === '/quit') {
106
- console.log(chalk.dim('Goodbye.'));
107
- process.exit(0);
108
- }
109
- else if (trimmed === '/shell') {
110
- shellMode = true;
111
- console.log(chalk.dim('Entered local shell mode (not shared). Type /resume to go back.'));
112
- // enter shell loop
113
- while (shellMode) {
114
- const { line: shellLine } = await prompts({
115
- type: 'text',
116
- name: 'line',
117
- message: chalk.bold('shell> ') + chalk.dim('(local)'),
118
- });
119
- if (!shellLine) {
120
- continue;
121
- }
122
- const shellTrimmed = shellLine.trim();
123
- if (shellTrimmed === '/resume' || shellTrimmed === '/session' || shellTrimmed === '/codevf') {
124
- shellMode = false;
125
- console.log(chalk.dim('Back to CodeVF prompt.'));
126
- continue;
127
- }
128
- if (shellTrimmed === '/exit' || shellTrimmed === '/quit') {
129
- console.log(chalk.dim('Goodbye.'));
130
- process.exit(0);
131
- }
132
- if (shellTrimmed.startsWith('/')) {
133
- console.log(chalk.yellow(`Unknown command in shell: ${shellTrimmed}`));
134
- console.log(chalk.dim('Use /resume to return to the session prompt.'));
135
- continue;
136
- }
137
- try {
138
- await new Promise((resolve) => {
139
- const child = spawn(shellTrimmed, {
140
- shell: true,
141
- stdio: 'inherit',
142
- cwd: process.cwd(),
143
- });
144
- child.on('exit', () => resolve());
145
- child.on('error', (err) => {
146
- console.log(chalk.red(`Command failed: ${err.message}`));
147
- resolve();
148
- });
149
- });
150
- shellHistory.push(`$ ${shellTrimmed} (ran with stdio:inherit)`);
151
- }
152
- catch (error) {
153
- console.log(chalk.red(`Command failed: ${error.message || error}`));
154
- }
155
- }
156
- }
157
- else {
158
- console.log(chalk.yellow(`Unknown command: ${trimmed}`));
159
- console.log(chalk.dim('Type /? to see available commands.'));
160
- }
161
- continue;
154
+ };
155
+ const answer = await new Promise((resolve) => {
156
+ rl.question(` ${getModeIndicator(routingMode)} ${chalk.dim('›')} `, (answer) => {
157
+ rl.close();
158
+ resolve(answer);
159
+ });
160
+ });
161
+ if (answer.trim()) {
162
+ await handleSubmit(answer.trim(), routingMode);
162
163
  }
163
- await fixCommand(trimmed);
164
- // After session ends, return to prompt loop
165
164
  }
166
165
  }
167
- catch (error) {
168
- handleError(error);
169
- }
170
- })();
166
+ }
167
+ catch (error) {
168
+ handleError(error);
169
+ }
170
+ }
171
+ /**
172
+ * Command-line argument mode - handle specific commands
173
+ */
174
+ if (args.length === 0) {
175
+ // Check if this is the first run
176
+ if (isFirstRun()) {
177
+ welcomeCommand().catch(handleError);
178
+ }
179
+ else {
180
+ runInteractiveMode();
181
+ }
171
182
  }
172
183
  else {
173
184
  yargs(args)
174
185
  .scriptName('codevf')
175
186
  .version(CLI_VERSION)
176
187
  .usage('$0 <command> [options]')
177
- .command('login', 'Authenticate with CodeVF', () => { }, async () => {
188
+ .epilogue('For first-time setup, run: codevf welcome\nDocumentation: https://docs.codevf.com')
189
+ .command('login', 'Authenticate with CodeVF (for CLI usage)', () => { }, async () => {
178
190
  try {
179
191
  await loginCommand();
180
192
  }
@@ -189,6 +201,22 @@ else {
189
201
  catch (error) {
190
202
  handleError(error);
191
203
  }
204
+ })
205
+ .command('setup', 'Configure MCP server for Claude Code integration', () => { }, async () => {
206
+ try {
207
+ await setupCommand();
208
+ }
209
+ catch (error) {
210
+ handleError(error);
211
+ }
212
+ })
213
+ .command('welcome', 'Show welcome screen and setup guide', () => { }, async () => {
214
+ try {
215
+ await welcomeCommand();
216
+ }
217
+ catch (error) {
218
+ handleError(error);
219
+ }
192
220
  })
193
221
  .command('init', 'Initialize CodeVF in your project', () => { }, async () => {
194
222
  try {
@@ -222,13 +250,30 @@ else {
222
250
  }
223
251
  })
224
252
  .command('fix <issue>', 'Start a live debugging session', (yargs) => {
225
- return yargs.positional('issue', {
253
+ return yargs
254
+ .positional('issue', {
226
255
  type: 'string',
227
256
  describe: 'Description of the issue to fix (or type commands like /human need help with X)',
228
257
  demandOption: true,
258
+ })
259
+ .option('ai', {
260
+ type: 'boolean',
261
+ default: false,
262
+ describe: 'Route through local AI (opencode SDK) if enabled',
263
+ })
264
+ .option('no-start-server', {
265
+ type: 'boolean',
266
+ default: false,
267
+ describe: 'Do not auto-start opencode server; require existing server',
229
268
  });
230
269
  }, async (argv) => {
231
270
  try {
271
+ if (argv.ai) {
272
+ const configManager = new ConfigManager();
273
+ const aiAgent = new AiAgent(configManager);
274
+ await aiAgent.run(argv.issue, { startServer: !argv['no-start-server'] });
275
+ return;
276
+ }
232
277
  await fixCommand(argv.issue);
233
278
  }
234
279
  catch (error) {