gitarsenal-cli 1.9.106 ā 1.9.108
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/.venv_status.json +1 -1
- package/README-TYPING.md +91 -0
- package/START-HERE.md +230 -0
- package/bin/gitarsenal-tui.js +147 -0
- package/bin/gitarsenal.js +58 -15
- package/launch-tui.sh +18 -0
- package/package.json +9 -3
- package/scripts/ensure-dependencies.sh +46 -0
- package/scripts/postinstall.js +22 -7
- package/tui/App.jsx +326 -0
- package/tui/index.js +37 -0
- package/tui/simple-test.js +41 -0
- package/tui-app/bun.lock +200 -0
- package/tui-app/index-manual.js.bak +609 -0
- package/tui-app/index.jsx +848 -0
- package/tui-app/package-lock.json +1720 -0
- package/tui-app/package.json +16 -0
package/scripts/postinstall.js
CHANGED
|
@@ -138,21 +138,37 @@ async function createVirtualEnvironment() {
|
|
|
138
138
|
|
|
139
139
|
console.log(chalk.gray(`š Installing packages in virtual environment with uv...`));
|
|
140
140
|
|
|
141
|
+
// Determine the activation command based on platform
|
|
142
|
+
const isWindows = process.platform === 'win32';
|
|
143
|
+
const activateCmd = isWindows ?
|
|
144
|
+
'call .venv\\Scripts\\activate.bat && ' :
|
|
145
|
+
'source .venv/bin/activate && ';
|
|
146
|
+
|
|
141
147
|
// Install packages using uv pip from requirements.txt
|
|
142
148
|
const requirementsPath = path.join(packageDir, 'python', 'requirements.txt');
|
|
143
149
|
if (await fs.pathExists(requirementsPath)) {
|
|
144
150
|
console.log(chalk.gray(`š¦ Installing packages from requirements.txt...`));
|
|
145
|
-
|
|
151
|
+
const installCmd = isWindows ?
|
|
152
|
+
`${activateCmd}uv pip install -r ${requirementsPath}` :
|
|
153
|
+
`bash -c "${activateCmd}uv pip install -r ${requirementsPath}"`;
|
|
154
|
+
|
|
155
|
+
await execAsync(installCmd, {
|
|
146
156
|
cwd: packageDir,
|
|
147
157
|
env: { ...process.env, PYTHONIOENCODING: 'utf-8' },
|
|
148
|
-
stdio: 'inherit'
|
|
158
|
+
stdio: 'inherit',
|
|
159
|
+
shell: isWindows ? 'cmd.exe' : '/bin/bash'
|
|
149
160
|
});
|
|
150
161
|
} else {
|
|
151
162
|
console.log(chalk.gray(`š¦ Installing packages: ${packages.join(', ')}`));
|
|
152
|
-
|
|
163
|
+
const installCmd = isWindows ?
|
|
164
|
+
`${activateCmd}uv pip install ${packages.join(' ')}` :
|
|
165
|
+
`bash -c "${activateCmd}uv pip install ${packages.join(' ')}"`;
|
|
166
|
+
|
|
167
|
+
await execAsync(installCmd, {
|
|
153
168
|
cwd: packageDir,
|
|
154
169
|
env: { ...process.env, PYTHONIOENCODING: 'utf-8' },
|
|
155
|
-
stdio: 'inherit'
|
|
170
|
+
stdio: 'inherit',
|
|
171
|
+
shell: isWindows ? 'cmd.exe' : '/bin/bash'
|
|
156
172
|
});
|
|
157
173
|
}
|
|
158
174
|
|
|
@@ -160,7 +176,7 @@ async function createVirtualEnvironment() {
|
|
|
160
176
|
|
|
161
177
|
// Verify packages are installed
|
|
162
178
|
const pythonPath = path.join(venvPath, 'bin', 'python');
|
|
163
|
-
const packagesToVerify = [...packages, 'anthropic']; // Ensure anthropic
|
|
179
|
+
const packagesToVerify = [...packages, 'anthropic', 'e2b_code_interpreter']; // Ensure anthropic and e2b are checked
|
|
164
180
|
for (const pkg of packagesToVerify) {
|
|
165
181
|
try {
|
|
166
182
|
await execAsync(`${pythonPath} -c "import ${pkg}; print('${pkg} imported successfully')"`);
|
|
@@ -171,8 +187,6 @@ async function createVirtualEnvironment() {
|
|
|
171
187
|
}
|
|
172
188
|
|
|
173
189
|
// Create a script to activate the virtual environment
|
|
174
|
-
const isWindows = process.platform === 'win32';
|
|
175
|
-
|
|
176
190
|
const activateScript = isWindows ?
|
|
177
191
|
`@echo off
|
|
178
192
|
cd /d "%~dp0"
|
|
@@ -391,6 +405,7 @@ if __name__ == "__main__":
|
|
|
391
405
|
⢠GitArsenal CLI (npm package)
|
|
392
406
|
⢠Virtual environment with Python packages:
|
|
393
407
|
- Modal
|
|
408
|
+
- E2B Code Interpreter
|
|
394
409
|
- GitIngest
|
|
395
410
|
- Requests
|
|
396
411
|
- Anthropic (for Claude fallback)
|
package/tui/App.jsx
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { Box, Text, TextInput, List, Spinner } from '@opentui/react';
|
|
3
|
+
|
|
4
|
+
// Main TUI Application Component
|
|
5
|
+
export function App({ onSubmit, onExit }) {
|
|
6
|
+
const [screen, setScreen] = useState('menu');
|
|
7
|
+
const [repoUrl, setRepoUrl] = useState('');
|
|
8
|
+
const [selectedGpu, setSelectedGpu] = useState('A10G');
|
|
9
|
+
const [gpuCount, setGpuCount] = useState(1);
|
|
10
|
+
const [sandboxProvider, setSandboxProvider] = useState('modal');
|
|
11
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
12
|
+
const [loadingText, setLoadingText] = useState('');
|
|
13
|
+
const [analysisData, setAnalysisData] = useState(null);
|
|
14
|
+
|
|
15
|
+
const gpuOptions = [
|
|
16
|
+
{ label: 'T4 (16GB VRAM)', value: 'T4' },
|
|
17
|
+
{ label: 'L4 (24GB VRAM)', value: 'L4' },
|
|
18
|
+
{ label: 'A10G (24GB VRAM)', value: 'A10G' },
|
|
19
|
+
{ label: 'A100-40 (40GB VRAM)', value: 'A100-40GB' },
|
|
20
|
+
{ label: 'A100-80 (80GB VRAM)', value: 'A100-80GB' },
|
|
21
|
+
{ label: 'L40S (48GB VRAM)', value: 'L40S' },
|
|
22
|
+
{ label: 'H100 (80GB VRAM)', value: 'H100' },
|
|
23
|
+
{ label: 'H200 (141GB VRAM)', value: 'H200' },
|
|
24
|
+
{ label: 'B200 (141GB VRAM)', value: 'B200' }
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const gpuCountOptions = [
|
|
28
|
+
{ label: '1 GPU', value: 1 },
|
|
29
|
+
{ label: '2 GPUs', value: 2 },
|
|
30
|
+
{ label: '3 GPUs', value: 3 },
|
|
31
|
+
{ label: '4 GPUs', value: 4 },
|
|
32
|
+
{ label: '6 GPUs', value: 6 },
|
|
33
|
+
{ label: '8 GPUs', value: 8 }
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const menuItems = [
|
|
37
|
+
{ label: 'š Create New Sandbox', value: 'create' },
|
|
38
|
+
{ label: 'š Browse Repositories', value: 'browse' },
|
|
39
|
+
{ label: 'š API Keys Management', value: 'keys' },
|
|
40
|
+
{ label: 'āļø Settings', value: 'settings' },
|
|
41
|
+
{ label: 'ā Help & Examples', value: 'help' },
|
|
42
|
+
{ label: 'šŖ Exit', value: 'exit' }
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const sandboxProviders = [
|
|
46
|
+
{ label: 'Modal (GPU support, persistent volumes)', value: 'modal' },
|
|
47
|
+
{ label: 'E2B (Faster startup, no GPU)', value: 'e2b' }
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const handleMenuSelect = (item) => {
|
|
51
|
+
if (item.value === 'exit') {
|
|
52
|
+
onExit();
|
|
53
|
+
} else if (item.value === 'create') {
|
|
54
|
+
setScreen('repo-input');
|
|
55
|
+
} else if (item.value === 'keys') {
|
|
56
|
+
setScreen('keys');
|
|
57
|
+
} else if (item.value === 'help') {
|
|
58
|
+
setScreen('help');
|
|
59
|
+
} else if (item.value === 'settings') {
|
|
60
|
+
setScreen('settings');
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const handleRepoSubmit = () => {
|
|
65
|
+
if (repoUrl.trim()) {
|
|
66
|
+
setScreen('provider-select');
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const handleProviderSelect = (provider) => {
|
|
71
|
+
setSandboxProvider(provider.value);
|
|
72
|
+
if (provider.value === 'modal') {
|
|
73
|
+
setScreen('gpu-select');
|
|
74
|
+
} else {
|
|
75
|
+
// E2B doesn't need GPU selection
|
|
76
|
+
handleSubmit();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const handleGpuSelect = (gpu) => {
|
|
81
|
+
setSelectedGpu(gpu.value);
|
|
82
|
+
setScreen('gpu-count');
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const handleGpuCountSelect = (count) => {
|
|
86
|
+
setGpuCount(count.value);
|
|
87
|
+
setScreen('confirm');
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const handleSubmit = () => {
|
|
91
|
+
const config = {
|
|
92
|
+
repoUrl,
|
|
93
|
+
gpuType: selectedGpu,
|
|
94
|
+
gpuCount,
|
|
95
|
+
sandboxProvider,
|
|
96
|
+
analysisData
|
|
97
|
+
};
|
|
98
|
+
onSubmit(config);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Render different screens
|
|
102
|
+
if (isLoading) {
|
|
103
|
+
return (
|
|
104
|
+
<Box flexDirection="column" padding={2} gap={1}>
|
|
105
|
+
<Box borderStyle="round" borderColor="blue" padding={1}>
|
|
106
|
+
<Text bold color="cyan">ā³ GitArsenal</Text>
|
|
107
|
+
</Box>
|
|
108
|
+
<Box flexDirection="row" gap={1} marginTop={1}>
|
|
109
|
+
<Spinner />
|
|
110
|
+
<Text>{loadingText}</Text>
|
|
111
|
+
</Box>
|
|
112
|
+
</Box>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (screen === 'menu') {
|
|
117
|
+
return (
|
|
118
|
+
<Box flexDirection="column" padding={2} gap={1}>
|
|
119
|
+
<Box borderStyle="round" borderColor="cyan" padding={1}>
|
|
120
|
+
<Text bold color="cyan">šÆ GitArsenal - GPU-Accelerated Repository Sandbox</Text>
|
|
121
|
+
</Box>
|
|
122
|
+
<Box marginTop={1}>
|
|
123
|
+
<Text color="gray">Secure, cloud-based development environments with GPU acceleration</Text>
|
|
124
|
+
</Box>
|
|
125
|
+
<Box marginTop={1}>
|
|
126
|
+
<List
|
|
127
|
+
items={menuItems}
|
|
128
|
+
onSelect={handleMenuSelect}
|
|
129
|
+
selectedStyle={{ color: 'cyan', bold: true }}
|
|
130
|
+
/>
|
|
131
|
+
</Box>
|
|
132
|
+
<Box marginTop={1}>
|
|
133
|
+
<Text color="gray" dim>Use āā arrows to navigate, Enter to select, Ctrl+C to exit</Text>
|
|
134
|
+
</Box>
|
|
135
|
+
</Box>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (screen === 'repo-input') {
|
|
140
|
+
return (
|
|
141
|
+
<Box flexDirection="column" padding={2} gap={1}>
|
|
142
|
+
<Box borderStyle="round" borderColor="cyan" padding={1}>
|
|
143
|
+
<Text bold color="cyan">š Create New Sandbox</Text>
|
|
144
|
+
</Box>
|
|
145
|
+
<Box marginTop={1}>
|
|
146
|
+
<Text>Enter GitHub repository URL:</Text>
|
|
147
|
+
</Box>
|
|
148
|
+
<Box marginTop={1}>
|
|
149
|
+
<TextInput
|
|
150
|
+
value={repoUrl}
|
|
151
|
+
onChange={setRepoUrl}
|
|
152
|
+
onSubmit={handleRepoSubmit}
|
|
153
|
+
placeholder="https://github.com/username/repository.git"
|
|
154
|
+
/>
|
|
155
|
+
</Box>
|
|
156
|
+
<Box marginTop={1}>
|
|
157
|
+
<Text color="gray" dim>Examples:</Text>
|
|
158
|
+
<Text color="gray" dim>⢠https://github.com/microsoft/transformer</Text>
|
|
159
|
+
<Text color="gray" dim>⢠https://github.com/pytorch/pytorch</Text>
|
|
160
|
+
<Text color="gray" dim>⢠https://github.com/openai/gpt-2</Text>
|
|
161
|
+
</Box>
|
|
162
|
+
<Box marginTop={1}>
|
|
163
|
+
<Text color="gray" dim>Press Enter to continue ⢠Esc to go back</Text>
|
|
164
|
+
</Box>
|
|
165
|
+
</Box>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (screen === 'provider-select') {
|
|
170
|
+
return (
|
|
171
|
+
<Box flexDirection="column" padding={2} gap={1}>
|
|
172
|
+
<Box borderStyle="round" borderColor="cyan" padding={1}>
|
|
173
|
+
<Text bold color="cyan">š§ Select Sandbox Provider</Text>
|
|
174
|
+
</Box>
|
|
175
|
+
<Box marginTop={1}>
|
|
176
|
+
<Text>Repository: <Text color="green">{repoUrl}</Text></Text>
|
|
177
|
+
</Box>
|
|
178
|
+
<Box marginTop={1}>
|
|
179
|
+
<List
|
|
180
|
+
items={sandboxProviders}
|
|
181
|
+
onSelect={handleProviderSelect}
|
|
182
|
+
selectedStyle={{ color: 'cyan', bold: true }}
|
|
183
|
+
/>
|
|
184
|
+
</Box>
|
|
185
|
+
<Box marginTop={1}>
|
|
186
|
+
<Text color="gray" dim>Press Esc to go back</Text>
|
|
187
|
+
</Box>
|
|
188
|
+
</Box>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (screen === 'gpu-select') {
|
|
193
|
+
return (
|
|
194
|
+
<Box flexDirection="column" padding={2} gap={1}>
|
|
195
|
+
<Box borderStyle="round" borderColor="cyan" padding={1}>
|
|
196
|
+
<Text bold color="cyan">ā” Select GPU Configuration</Text>
|
|
197
|
+
</Box>
|
|
198
|
+
<Box marginTop={1}>
|
|
199
|
+
<Text>Repository: <Text color="green">{repoUrl}</Text></Text>
|
|
200
|
+
<Text>Provider: <Text color="green">{sandboxProvider}</Text></Text>
|
|
201
|
+
</Box>
|
|
202
|
+
<Box marginTop={1}>
|
|
203
|
+
<List
|
|
204
|
+
items={gpuOptions}
|
|
205
|
+
onSelect={handleGpuSelect}
|
|
206
|
+
selectedStyle={{ color: 'cyan', bold: true }}
|
|
207
|
+
/>
|
|
208
|
+
</Box>
|
|
209
|
+
<Box marginTop={1}>
|
|
210
|
+
<Text color="gray" dim>Press Esc to go back</Text>
|
|
211
|
+
</Box>
|
|
212
|
+
</Box>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (screen === 'gpu-count') {
|
|
217
|
+
return (
|
|
218
|
+
<Box flexDirection="column" padding={2} gap={1}>
|
|
219
|
+
<Box borderStyle="round" borderColor="cyan" padding={1}>
|
|
220
|
+
<Text bold color="cyan">ā” Select GPU Count</Text>
|
|
221
|
+
</Box>
|
|
222
|
+
<Box marginTop={1}>
|
|
223
|
+
<Text>GPU Type: <Text color="green">{selectedGpu}</Text></Text>
|
|
224
|
+
</Box>
|
|
225
|
+
<Box marginTop={1}>
|
|
226
|
+
<List
|
|
227
|
+
items={gpuCountOptions}
|
|
228
|
+
onSelect={handleGpuCountSelect}
|
|
229
|
+
selectedStyle={{ color: 'cyan', bold: true }}
|
|
230
|
+
/>
|
|
231
|
+
</Box>
|
|
232
|
+
<Box marginTop={1}>
|
|
233
|
+
<Text color="gray" dim>Press Esc to go back</Text>
|
|
234
|
+
</Box>
|
|
235
|
+
</Box>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (screen === 'confirm') {
|
|
240
|
+
return (
|
|
241
|
+
<Box flexDirection="column" padding={2} gap={1}>
|
|
242
|
+
<Box borderStyle="round" borderColor="cyan" padding={1}>
|
|
243
|
+
<Text bold color="cyan">š Configuration Summary</Text>
|
|
244
|
+
</Box>
|
|
245
|
+
<Box flexDirection="column" marginTop={1} gap={0}>
|
|
246
|
+
<Text><Text color="gray">Repository URL:</Text> <Text color="white">{repoUrl}</Text></Text>
|
|
247
|
+
<Text><Text color="gray">Sandbox Provider:</Text> <Text color="white">{sandboxProvider}</Text></Text>
|
|
248
|
+
{sandboxProvider === 'modal' && (
|
|
249
|
+
<>
|
|
250
|
+
<Text><Text color="gray">GPU Type:</Text> <Text color="white">{gpuCount > 1 ? `${gpuCount}x ${selectedGpu}` : selectedGpu}</Text></Text>
|
|
251
|
+
</>
|
|
252
|
+
)}
|
|
253
|
+
</Box>
|
|
254
|
+
<Box marginTop={1}>
|
|
255
|
+
<Text color="green" bold>ā
Press Enter to create sandbox</Text>
|
|
256
|
+
<Text color="gray" dim>Press Esc to go back to menu</Text>
|
|
257
|
+
</Box>
|
|
258
|
+
</Box>
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (screen === 'keys') {
|
|
263
|
+
return (
|
|
264
|
+
<Box flexDirection="column" padding={2} gap={1}>
|
|
265
|
+
<Box borderStyle="round" borderColor="cyan" padding={1}>
|
|
266
|
+
<Text bold color="cyan">š API Keys Management</Text>
|
|
267
|
+
</Box>
|
|
268
|
+
<Box marginTop={1}>
|
|
269
|
+
<Text color="yellow">Coming soon! Use 'gitarsenal keys' command for now.</Text>
|
|
270
|
+
</Box>
|
|
271
|
+
<Box marginTop={1}>
|
|
272
|
+
<Text color="gray" dim>Press Esc to go back</Text>
|
|
273
|
+
</Box>
|
|
274
|
+
</Box>
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (screen === 'help') {
|
|
279
|
+
return (
|
|
280
|
+
<Box flexDirection="column" padding={2} gap={1}>
|
|
281
|
+
<Box borderStyle="round" borderColor="cyan" padding={1}>
|
|
282
|
+
<Text bold color="cyan">ā Help & Examples</Text>
|
|
283
|
+
</Box>
|
|
284
|
+
<Box flexDirection="column" marginTop={1}>
|
|
285
|
+
<Text bold color="green">Quick Start:</Text>
|
|
286
|
+
<Text>1. Select "Create New Sandbox"</Text>
|
|
287
|
+
<Text>2. Enter a GitHub repository URL</Text>
|
|
288
|
+
<Text>3. Choose your sandbox provider</Text>
|
|
289
|
+
<Text>4. Select GPU type and count (Modal only)</Text>
|
|
290
|
+
<Text>5. Confirm and create!</Text>
|
|
291
|
+
|
|
292
|
+
<Text bold color="green" marginTop={1}>Example Repositories:</Text>
|
|
293
|
+
<Text>⢠https://github.com/pytorch/examples</Text>
|
|
294
|
+
<Text>⢠https://github.com/huggingface/transformers</Text>
|
|
295
|
+
<Text>⢠https://github.com/openai/whisper</Text>
|
|
296
|
+
</Box>
|
|
297
|
+
<Box marginTop={1}>
|
|
298
|
+
<Text color="gray" dim>Press Esc to go back</Text>
|
|
299
|
+
</Box>
|
|
300
|
+
</Box>
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (screen === 'settings') {
|
|
305
|
+
return (
|
|
306
|
+
<Box flexDirection="column" padding={2} gap={1}>
|
|
307
|
+
<Box borderStyle="round" borderColor="cyan" padding={1}>
|
|
308
|
+
<Text bold color="cyan">āļø Settings</Text>
|
|
309
|
+
</Box>
|
|
310
|
+
<Box marginTop={1}>
|
|
311
|
+
<Text color="yellow">Coming soon!</Text>
|
|
312
|
+
</Box>
|
|
313
|
+
<Box marginTop={1}>
|
|
314
|
+
<Text color="gray" dim>Press Esc to go back</Text>
|
|
315
|
+
</Box>
|
|
316
|
+
</Box>
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return (
|
|
321
|
+
<Box flexDirection="column" padding={2}>
|
|
322
|
+
<Text>Unknown screen: {screen}</Text>
|
|
323
|
+
</Box>
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
package/tui/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const { render } = require('@opentui/react');
|
|
2
|
+
const React = require('react');
|
|
3
|
+
const { App } = require('./App.jsx');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Launch the OpenTUI interface
|
|
7
|
+
* @param {Object} options - Configuration options
|
|
8
|
+
* @returns {Promise<Object>} - Selected configuration
|
|
9
|
+
*/
|
|
10
|
+
async function launchTUI(options = {}) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const handleSubmit = (config) => {
|
|
13
|
+
resolve(config);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const handleExit = () => {
|
|
17
|
+
resolve(null);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
render(
|
|
22
|
+
React.createElement(App, {
|
|
23
|
+
onSubmit: handleSubmit,
|
|
24
|
+
onExit: handleExit,
|
|
25
|
+
initialOptions: options
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
reject(error);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
launchTUI
|
|
36
|
+
};
|
|
37
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Simple test to verify OpenTUI is working
|
|
4
|
+
const { terminal } = require('@opentui/core');
|
|
5
|
+
|
|
6
|
+
async function testOpenTUI() {
|
|
7
|
+
try {
|
|
8
|
+
console.log('Testing OpenTUI installation...');
|
|
9
|
+
|
|
10
|
+
// Create a simple terminal instance
|
|
11
|
+
const term = terminal();
|
|
12
|
+
|
|
13
|
+
// Test basic output
|
|
14
|
+
term.writeln('šØ OpenTUI Test');
|
|
15
|
+
term.writeln('ā
OpenTUI core is installed and working!');
|
|
16
|
+
term.writeln('');
|
|
17
|
+
term.writeln('This confirms that:');
|
|
18
|
+
term.writeln(' ⢠@opentui/core is installed');
|
|
19
|
+
term.writeln(' ⢠Terminal interface is accessible');
|
|
20
|
+
term.writeln(' ⢠Ready to build the full TUI');
|
|
21
|
+
term.writeln('');
|
|
22
|
+
term.writeln('Press any key to exit...');
|
|
23
|
+
|
|
24
|
+
// Wait for key press
|
|
25
|
+
await term.waitForKeyPress();
|
|
26
|
+
|
|
27
|
+
console.log('\nā
Test complete!');
|
|
28
|
+
process.exit(0);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error('ā OpenTUI test failed:', error.message);
|
|
31
|
+
console.error('');
|
|
32
|
+
console.error('This might mean:');
|
|
33
|
+
console.error(' ⢠OpenTUI is not installed correctly');
|
|
34
|
+
console.error(' ⢠API has changed');
|
|
35
|
+
console.error(' ⢠Need to adjust the implementation');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
testOpenTUI();
|
|
41
|
+
|