lumina-code-agent 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +111 -75
- package/package.json +7 -18
package/dist/index.js
CHANGED
|
@@ -1,11 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @ts-nocheck
|
|
3
|
+
// Check if we have a proper TTY for the TUI
|
|
4
|
+
const hasTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
5
|
+
if (!hasTTY) {
|
|
6
|
+
// Non-TUI mode: just show help
|
|
7
|
+
console.log('');
|
|
8
|
+
console.log(' ⚡ LUMINA CODE — AI Coding Agent');
|
|
9
|
+
console.log('');
|
|
10
|
+
console.log(' Lumina Code requires a proper terminal (TTY) to run.');
|
|
11
|
+
console.log(' Please open one of these and type: lumina');
|
|
12
|
+
console.log('');
|
|
13
|
+
console.log(' • Windows Terminal (recommended)');
|
|
14
|
+
console.log(' • PowerShell');
|
|
15
|
+
console.log(' • Command Prompt (cmd.exe)');
|
|
16
|
+
console.log(' • iTerm2 / Terminal.app (macOS)');
|
|
17
|
+
console.log(' • Any Linux terminal');
|
|
18
|
+
console.log('');
|
|
19
|
+
console.log(' If you\'re in Git Bash, try running from Windows Terminal instead.');
|
|
20
|
+
console.log('');
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
3
23
|
import React, { useState, useCallback, useRef } from 'react';
|
|
4
24
|
import { Box, Text, useInput, useApp, Spacer } from 'ink';
|
|
5
|
-
import
|
|
6
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
25
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'fs';
|
|
7
26
|
import { homedir } from 'os';
|
|
8
|
-
import { join } from 'path';
|
|
27
|
+
import { join, dirname, resolve, relative } from 'path';
|
|
9
28
|
const CONFIG_DIR = join(homedir(), '.lumina');
|
|
10
29
|
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
11
30
|
function loadConfig() {
|
|
@@ -37,70 +56,59 @@ function Onboarding({ onComplete }) {
|
|
|
37
56
|
setStep(2);
|
|
38
57
|
}
|
|
39
58
|
else if (step === 2) {
|
|
40
|
-
saveConfig({ openrouterKey: apiKey.trim(), userName: name.trim() || 'User'
|
|
59
|
+
saveConfig({ openrouterKey: apiKey.trim(), userName: name.trim() || 'User' });
|
|
41
60
|
onComplete();
|
|
42
61
|
}
|
|
43
62
|
}
|
|
63
|
+
else if (key.backspace || key.delete) {
|
|
64
|
+
if (step === 1)
|
|
65
|
+
setApiKey(v => v.slice(0, -1));
|
|
66
|
+
if (step === 2)
|
|
67
|
+
setName(v => v.slice(0, -1));
|
|
68
|
+
}
|
|
69
|
+
else if (!key.ctrl && !key.meta && input) {
|
|
70
|
+
if (step === 1)
|
|
71
|
+
setApiKey(v => v + input);
|
|
72
|
+
if (step === 2)
|
|
73
|
+
setName(v => v + input);
|
|
74
|
+
}
|
|
44
75
|
});
|
|
45
|
-
return React.createElement(Box, { flexDirection: 'column', padding: 2 }, React.createElement(Box, { flexDirection: 'column', marginBottom: 2 }, React.createElement(Text, { bold: true, color: '#7C5CFC' }, ' ⚡ LUMINA CODE'), React.createElement(Text, { color: '#52525B' }, ' AI Coding Agent
|
|
76
|
+
return React.createElement(Box, { flexDirection: 'column', padding: 2 }, React.createElement(Box, { flexDirection: 'column', marginBottom: 2 }, React.createElement(Text, { bold: true, color: '#7C5CFC' }, ' ⚡ LUMINA CODE'), React.createElement(Text, { color: '#52525B' }, ' AI Coding Agent')), step === 0 && React.createElement(Box, { flexDirection: 'column' }, React.createElement(Text, { color: '#A1A1AA' }, ' Welcome! Let\'s get you set up.'), React.createElement(Text, { color: '#52525B' }, ' Press Enter to continue...')), step === 1 && React.createElement(Box, { flexDirection: 'column' }, React.createElement(Text, { color: '#A1A1AA' }, ' Enter your OpenRouter API key:'), React.createElement(Text, { color: '#52525B' }, ' (Get one at https://openrouter.ai/keys)'), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, { color: '#7C5CFC' }, ' > '), React.createElement(Text, { color: '#FAFAFA' }, apiKey || 'sk-or-...'), React.createElement(Text, { color: '#52525B' }, '▌')), React.createElement(Text, { color: '#3F3F46', marginTop: 1 }, ' Press Enter to continue')), step === 2 && React.createElement(Box, { flexDirection: 'column' }, React.createElement(Text, { color: '#A1A1AA' }, ' What should I call you? (optional)'), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, { color: '#7C5CFC' }, ' > '), React.createElement(Text, { color: '#FAFAFA' }, name || 'Your name'), React.createElement(Text, { color: '#52525B' }, '▌')), React.createElement(Text, { color: '#3F3F46', marginTop: 1 }, ' Press Enter to start coding!')));
|
|
46
77
|
}
|
|
47
78
|
// ── Chat Screen ─────────────────────────────────────────────────────
|
|
48
79
|
function ChatScreen({ config }) {
|
|
49
80
|
const { exit } = useApp();
|
|
50
|
-
const [messages, setMessages] = useState([
|
|
51
|
-
{ role: 'system', content: `You are LUMINA CODE — an elite AI coding agent running locally.
|
|
52
|
-
|
|
53
|
-
MODEL: openrouter/owl-alpha (1M+ context, best reasoning)
|
|
54
|
-
|
|
55
|
-
WORKFLOW:
|
|
56
|
-
1. PLAN: Analyze the task. Create a brief plan.
|
|
57
|
-
2. ACT: Execute tools step by step. Read before writing.
|
|
58
|
-
3. VERIFY: Run builds, check for errors.
|
|
59
|
-
4. FIX: If something fails, debug and fix.
|
|
60
|
-
5. DEPLOY: If requested, deploy automatically.
|
|
61
|
-
|
|
62
|
-
QUALITY: Production-grade code. No placeholders. No TODOs. No emoji in code.
|
|
63
|
-
Handle errors. Use TypeScript. Responsive design. Accessible.
|
|
64
|
-
|
|
65
|
-
TOOLS: run_command, read_file, write_file, edit_file, list_dir, search_files, grep, git, npm, deploy, detect_project, get_file_tree
|
|
66
|
-
|
|
67
|
-
When using a tool, output ONLY:
|
|
68
|
-
TOOL: <name>
|
|
69
|
-
PARAMS: <json>
|
|
70
|
-
|
|
71
|
-
Working directory: ${process.cwd()}` },
|
|
72
|
-
]);
|
|
81
|
+
const [messages, setMessages] = useState([]);
|
|
73
82
|
const [input, setInput] = useState('');
|
|
74
83
|
const [status, setStatus] = useState('Ready');
|
|
75
84
|
const [thinking, setThinking] = useState(false);
|
|
76
85
|
const scrollRef = useRef(0);
|
|
77
|
-
const visibleMessages = messages.
|
|
78
|
-
const handleSubmit = useCallback(async () => {
|
|
79
|
-
const trimmed =
|
|
86
|
+
const visibleMessages = messages.slice(-50);
|
|
87
|
+
const handleSubmit = useCallback(async (text) => {
|
|
88
|
+
const trimmed = text.trim();
|
|
80
89
|
if (!trimmed || thinking)
|
|
81
90
|
return;
|
|
82
91
|
setInput('');
|
|
83
92
|
setThinking(true);
|
|
84
93
|
setStatus('Thinking...');
|
|
94
|
+
scrollRef.current++;
|
|
85
95
|
const userMsg = { role: 'user', content: trimmed };
|
|
86
96
|
const newMessages = [...messages, userMsg];
|
|
87
97
|
setMessages(newMessages);
|
|
88
|
-
scrollRef.current++;
|
|
89
98
|
try {
|
|
90
99
|
const OPENROUTER_URL = 'https://openrouter.ai/api/v1/chat/completions';
|
|
91
100
|
const tools = [
|
|
92
101
|
{ type: 'function', function: { name: 'run_command', description: 'Run any shell command', parameters: { type: 'object', properties: { command: { type: 'string' }, cwd: { type: 'string' }, timeout: { type: 'number' } }, required: ['command'] } } },
|
|
93
|
-
{ type: 'function', function: { name: 'read_file', description: 'Read file contents', parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] } } },
|
|
94
|
-
{ type: 'function', function: { name: 'write_file', description: 'Create or overwrite a file', parameters: { type: 'object', properties: { path: { type: 'string' }, content: { type: 'string' } }, required: ['path', 'content'] } } },
|
|
95
|
-
{ type: 'function', function: { name: 'edit_file', description: 'Make precise edits to a file', parameters: { type: 'object', properties: { path: { type: 'string' }, search: { type: 'string' }, replace: { type: 'string' } }, required: ['path', 'search', 'replace'] } } },
|
|
102
|
+
{ type: 'function', function: { name: 'read_file', description: 'Read file contents. ALWAYS read before editing.', parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] } } },
|
|
103
|
+
{ type: 'function', function: { name: 'write_file', description: 'Create or overwrite a file. Creates directories automatically.', parameters: { type: 'object', properties: { path: { type: 'string' }, content: { type: 'string' } }, required: ['path', 'content'] } } },
|
|
104
|
+
{ type: 'function', function: { name: 'edit_file', description: 'Make precise edits to a file. search/replace.', parameters: { type: 'object', properties: { path: { type: 'string' }, search: { type: 'string' }, replace: { type: 'string' } }, required: ['path', 'search', 'replace'] } } },
|
|
96
105
|
{ type: 'function', function: { name: 'list_dir', description: 'List directory contents', parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] } } },
|
|
97
|
-
{ type: 'function', function: { name: 'search_files', description: 'Find files by pattern', parameters: { type: 'object', properties: { pattern: { type: 'string' }, cwd: { type: 'string' } }, required: ['pattern'] } } },
|
|
106
|
+
{ type: 'function', function: { name: 'search_files', description: 'Find files by glob pattern', parameters: { type: 'object', properties: { pattern: { type: 'string' }, cwd: { type: 'string' } }, required: ['pattern'] } } },
|
|
98
107
|
{ type: 'function', function: { name: 'grep', description: 'Search file contents', parameters: { type: 'object', properties: { pattern: { type: 'string' }, path: { type: 'string' } }, required: ['pattern', 'path'] } } },
|
|
99
108
|
{ type: 'function', function: { name: 'git', description: 'Run git commands', parameters: { type: 'object', properties: { args: { type: 'string' }, cwd: { type: 'string' } }, required: ['args'] } } },
|
|
100
|
-
{ type: 'function', function: { name: 'npm', description: 'Run npm/yarn/pnpm commands', parameters: { type: 'object', properties: { args: { type: 'string' }, cwd: { type: 'string' } }, required: ['args'] } } },
|
|
109
|
+
{ type: 'function', function: { name: 'npm', description: 'Run npm/yarn/pnpm/bun commands', parameters: { type: 'object', properties: { args: { type: 'string' }, cwd: { type: 'string' } }, required: ['args'] } } },
|
|
101
110
|
{ type: 'function', function: { name: 'deploy', description: 'Deploy to Vercel', parameters: { type: 'object', properties: { target: { type: 'string' }, cwd: { type: 'string' } } } } },
|
|
102
111
|
];
|
|
103
|
-
let assistantContent = '';
|
|
104
112
|
let iterations = 0;
|
|
105
113
|
const maxIterations = 30;
|
|
106
114
|
let currentMessages = [...newMessages];
|
|
@@ -110,7 +118,47 @@ Working directory: ${process.cwd()}` },
|
|
|
110
118
|
const res = await fetch(OPENROUTER_URL, {
|
|
111
119
|
method: 'POST',
|
|
112
120
|
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${config.openrouterKey}`, 'HTTP-Referer': 'https://luminaai.co.in', 'X-Title': 'Lumina Code' },
|
|
113
|
-
body: JSON.stringify({
|
|
121
|
+
body: JSON.stringify({
|
|
122
|
+
model: 'openrouter/owl-alpha',
|
|
123
|
+
messages: [{ role: 'system', content: `You are LUMINA CODE — an elite AI coding agent.
|
|
124
|
+
|
|
125
|
+
MODEL: openrouter/owl-alpha (1M+ context, best reasoning)
|
|
126
|
+
|
|
127
|
+
WORKFLOW:
|
|
128
|
+
1. PLAN: Analyze the task. Create a brief plan.
|
|
129
|
+
2. ACT: Execute tools step by step. Read before writing.
|
|
130
|
+
3. VERIFY: Run builds, check for errors.
|
|
131
|
+
4. FIX: If something fails, debug and fix immediately.
|
|
132
|
+
5. DEPLOY: If requested, deploy automatically.
|
|
133
|
+
|
|
134
|
+
QUALITY STANDARDS:
|
|
135
|
+
- Production-grade code, always
|
|
136
|
+
- TypeScript with proper types (never use 'any')
|
|
137
|
+
- Error handling everywhere
|
|
138
|
+
- Responsive design (320px to 2560px)
|
|
139
|
+
- Accessible (semantic HTML, ARIA, keyboard navigation)
|
|
140
|
+
- Clean architecture, modern patterns
|
|
141
|
+
- Beautiful UI (consistent spacing, typography, color)
|
|
142
|
+
|
|
143
|
+
FORBIDDEN:
|
|
144
|
+
- Lorem ipsum or placeholder content
|
|
145
|
+
- TODO/FIXME comments in production code
|
|
146
|
+
- Emoji in code or UI
|
|
147
|
+
- var keyword (always let/const)
|
|
148
|
+
- any type in TypeScript
|
|
149
|
+
- Skipping error handling
|
|
150
|
+
- Hardcoded secrets
|
|
151
|
+
|
|
152
|
+
When using a tool, output ONLY:
|
|
153
|
+
TOOL: <name>
|
|
154
|
+
PARAMS: <json>
|
|
155
|
+
|
|
156
|
+
Working directory: ${process.cwd()}` }, ...currentMessages],
|
|
157
|
+
tools,
|
|
158
|
+
stream: false,
|
|
159
|
+
max_tokens: 32000,
|
|
160
|
+
temperature: 0.1,
|
|
161
|
+
}),
|
|
114
162
|
});
|
|
115
163
|
if (!res.ok) {
|
|
116
164
|
const err = await res.text().catch(() => '');
|
|
@@ -122,14 +170,13 @@ Working directory: ${process.cwd()}` },
|
|
|
122
170
|
throw new Error('No response from model');
|
|
123
171
|
const content = choice.message?.content || '';
|
|
124
172
|
const toolCalls = choice.message?.tool_calls || [];
|
|
125
|
-
|
|
126
|
-
|
|
173
|
+
currentMessages.push({ role: 'assistant', content });
|
|
174
|
+
setMessages([...currentMessages]);
|
|
175
|
+
scrollRef.current++;
|
|
127
176
|
if (toolCalls.length === 0) {
|
|
128
|
-
setMessages([...currentMessages]);
|
|
129
177
|
setStatus('Done');
|
|
130
178
|
break;
|
|
131
179
|
}
|
|
132
|
-
// Execute tools
|
|
133
180
|
for (const tc of toolCalls) {
|
|
134
181
|
const args = JSON.parse(tc.function.arguments || '{}');
|
|
135
182
|
const toolName = tc.function.name;
|
|
@@ -137,9 +184,9 @@ Working directory: ${process.cwd()}` },
|
|
|
137
184
|
scrollRef.current++;
|
|
138
185
|
let output = '';
|
|
139
186
|
try {
|
|
187
|
+
const { execSync } = await import('child_process');
|
|
140
188
|
switch (toolName) {
|
|
141
189
|
case 'run_command': {
|
|
142
|
-
const { execSync } = await import('child_process');
|
|
143
190
|
const cwd = args.cwd || process.cwd();
|
|
144
191
|
output = execSync(args.command, { cwd, encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: args.timeout || 120000, shell: true }) || '(no output)';
|
|
145
192
|
break;
|
|
@@ -149,7 +196,7 @@ Working directory: ${process.cwd()}` },
|
|
|
149
196
|
break;
|
|
150
197
|
}
|
|
151
198
|
case 'write_file': {
|
|
152
|
-
const dir =
|
|
199
|
+
const dir = dirname(resolve(args.path));
|
|
153
200
|
if (!existsSync(dir))
|
|
154
201
|
mkdirSync(dir, { recursive: true });
|
|
155
202
|
writeFileSync(args.path, args.content, 'utf-8');
|
|
@@ -171,21 +218,19 @@ Working directory: ${process.cwd()}` },
|
|
|
171
218
|
break;
|
|
172
219
|
}
|
|
173
220
|
case 'search_files': {
|
|
174
|
-
const { readdirSync } = await import('fs');
|
|
175
|
-
const { join: pathJoin, relative: pathRelative } = await import('path');
|
|
176
221
|
const results = [];
|
|
177
222
|
const search = (dir, depth) => {
|
|
178
223
|
if (depth > 5)
|
|
179
224
|
return;
|
|
180
225
|
try {
|
|
181
226
|
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
182
|
-
if (e.name.startsWith('.') || e.name === 'node_modules')
|
|
227
|
+
if (e.name.startsWith('.') || e.name === 'node_modules' || e.name === 'dist')
|
|
183
228
|
continue;
|
|
184
|
-
const fp =
|
|
229
|
+
const fp = join(dir, e.name);
|
|
185
230
|
if (e.isDirectory())
|
|
186
231
|
search(fp, depth + 1);
|
|
187
|
-
else if (new RegExp(pattern.replace(/\*/g, '.*'), 'i').test(e.name))
|
|
188
|
-
results.push(
|
|
232
|
+
else if (new RegExp(args.pattern.replace(/\*/g, '.*'), 'i').test(e.name))
|
|
233
|
+
results.push(relative(args.cwd || process.cwd(), fp));
|
|
189
234
|
}
|
|
190
235
|
}
|
|
191
236
|
catch { }
|
|
@@ -202,18 +247,15 @@ Working directory: ${process.cwd()}` },
|
|
|
202
247
|
break;
|
|
203
248
|
}
|
|
204
249
|
case 'git': {
|
|
205
|
-
const { execSync } = await import('child_process');
|
|
206
250
|
output = execSync(`git ${args.args}`, { cwd: args.cwd || process.cwd(), encoding: 'utf-8', maxBuffer: 1024 * 1024 }) || '(ok)';
|
|
207
251
|
break;
|
|
208
252
|
}
|
|
209
253
|
case 'npm': {
|
|
210
|
-
const { execSync } = await import('child_process');
|
|
211
254
|
const pm = existsSync(join(args.cwd || process.cwd(), 'bun.lockb')) ? 'bun' : existsSync(join(args.cwd || process.cwd(), 'yarn.lock')) ? 'yarn' : 'npm';
|
|
212
255
|
output = execSync(`${pm} ${args.args}`, { cwd: args.cwd || process.cwd(), encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: 120000 }) || '(ok)';
|
|
213
256
|
break;
|
|
214
257
|
}
|
|
215
258
|
case 'deploy': {
|
|
216
|
-
const { execSync } = await import('child_process');
|
|
217
259
|
output = execSync('npx vercel deploy --prod --yes', { cwd: args.cwd || process.cwd(), encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: 300000 }) || '(deployed)';
|
|
218
260
|
break;
|
|
219
261
|
}
|
|
@@ -229,9 +271,8 @@ Working directory: ${process.cwd()}` },
|
|
|
229
271
|
scrollRef.current++;
|
|
230
272
|
}
|
|
231
273
|
}
|
|
232
|
-
if (iterations >= maxIterations)
|
|
274
|
+
if (iterations >= maxIterations)
|
|
233
275
|
setStatus('Reached max iterations');
|
|
234
|
-
}
|
|
235
276
|
}
|
|
236
277
|
catch (e) {
|
|
237
278
|
setMessages(prev => [...prev, { role: 'assistant', content: `⚠ Error: ${e.message}` }]);
|
|
@@ -239,35 +280,30 @@ Working directory: ${process.cwd()}` },
|
|
|
239
280
|
}
|
|
240
281
|
setThinking(false);
|
|
241
282
|
}, [input, thinking, messages, config]);
|
|
242
|
-
useInput((
|
|
243
|
-
if (key.ctrl &&
|
|
283
|
+
useInput((input, key) => {
|
|
284
|
+
if (key.ctrl && input === 'c')
|
|
244
285
|
exit();
|
|
245
|
-
if (key.ctrl &&
|
|
286
|
+
if (key.ctrl && input === 'd')
|
|
246
287
|
exit();
|
|
288
|
+
if (key.return) {
|
|
289
|
+
handleSubmit(input);
|
|
290
|
+
}
|
|
291
|
+
else if (key.backspace || key.delete) {
|
|
292
|
+
setInput(v => v.slice(0, -1));
|
|
293
|
+
}
|
|
294
|
+
else if (!key.ctrl && !key.meta) {
|
|
295
|
+
setInput(v => v + input);
|
|
296
|
+
}
|
|
247
297
|
});
|
|
248
|
-
return React.createElement(Box, { flexDirection: 'column', height: '100%' },
|
|
249
|
-
// Header
|
|
250
|
-
React.createElement(Box, { borderStyle: 'round', borderColor: '#7C5CFC', paddingX: 2, paddingY: 1 }, React.createElement(Text, { bold: true, color: '#7C5CFC' }, ' ⚡ LUMINA CODE'), React.createElement(Spacer, null), React.createElement(Text, { color: '#52525B' }, thinking ? ' ⏳ ' + status : ' ● ' + status)),
|
|
251
|
-
// Messages
|
|
252
|
-
React.createElement(Box, { flexDirection: 'column', flexGrow: 1, paddingX: 2, paddingY: 1, overflowY: 'hidden' }, visibleMessages.map((m, i) => {
|
|
298
|
+
return React.createElement(Box, { flexDirection: 'column', height: '100%' }, React.createElement(Box, { borderStyle: 'round', borderColor: '#7C5CFC', paddingX: 2, paddingY: 1 }, React.createElement(Text, { bold: true, color: '#7C5CFC' }, ' ⚡ LUMINA CODE'), React.createElement(Spacer, null), React.createElement(Text, { color: '#52525B' }, thinking ? ' ⏳ ' + status : ' ● ' + status)), React.createElement(Box, { flexDirection: 'column', flexGrow: 1, paddingX: 2, paddingY: 1, overflowY: 'hidden' }, visibleMessages.map((m, i) => {
|
|
253
299
|
if (m.role === 'user') {
|
|
254
300
|
return React.createElement(Box, { key: i, marginTop: 1 }, React.createElement(Text, { color: '#7C5CFC', bold: true }, '> '), React.createElement(Text, { color: '#FAFAFA' }, m.content));
|
|
255
301
|
}
|
|
256
302
|
if (m.role === 'tool') {
|
|
257
303
|
return React.createElement(Box, { key: i, marginTop: 0, paddingLeft: 2 }, React.createElement(Text, { color: '#52525B' }, ' ' + m.content.slice(0, 200)));
|
|
258
304
|
}
|
|
259
|
-
// Assistant
|
|
260
305
|
return React.createElement(Box, { key: i, marginTop: 1, paddingLeft: 2 }, React.createElement(Text, { color: '#A1A1AA' }, m.content.slice(0, 500)));
|
|
261
|
-
}), thinking && React.createElement(Text, { color: '#F59E0B' }, ' ⏳ thinking...')),
|
|
262
|
-
// Input
|
|
263
|
-
React.createElement(Box, { borderStyle: 'single', borderColor: '#3F3F46', paddingX: 1 }, React.createElement(Text, { color: '#7C5CFC' }, ' > '), React.createElement(TextInput, {
|
|
264
|
-
value: input,
|
|
265
|
-
onChange: setInput,
|
|
266
|
-
onSubmit: handleSubmit,
|
|
267
|
-
placeholder: 'What do you want to build?',
|
|
268
|
-
})),
|
|
269
|
-
// Footer
|
|
270
|
-
React.createElement(Box, { paddingX: 2 }, React.createElement(Text, { color: '#3F3F46' }, ' Ctrl+C to exit | OWL-Alpha ')));
|
|
306
|
+
}), thinking && React.createElement(Text, { color: '#F59E0B' }, ' ⏳ thinking...')), React.createElement(Box, { borderStyle: 'single', borderColor: '#3F3F46', paddingX: 1 }, React.createElement(Text, { color: '#7C5CFC' }, ' > '), React.createElement(Text, { color: '#FAFAFA' }, input || 'What do you want to build?'), React.createElement(Text, { color: '#52525B' }, '▌')), React.createElement(Box, { paddingX: 2 }, React.createElement(Text, { color: '#3F3F46' }, ' Ctrl+C to exit | OWL-Alpha ')));
|
|
271
307
|
}
|
|
272
308
|
// ── Main App ────────────────────────────────────────────────────────
|
|
273
309
|
export default function App() {
|
package/package.json
CHANGED
|
@@ -1,29 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lumina-code-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Lumina Code - AI coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"bin": {
|
|
8
|
-
"lumina": "dist/index.js"
|
|
9
|
-
},
|
|
7
|
+
"bin": { "lumina": "dist/index.js" },
|
|
10
8
|
"main": "dist/index.js",
|
|
11
|
-
"files": [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
],
|
|
15
|
-
"engines": {
|
|
16
|
-
"node": ">=18.0.0"
|
|
17
|
-
},
|
|
18
|
-
"scripts": {
|
|
19
|
-
"build": "tsc --noEmit false",
|
|
20
|
-
"prepublishOnly": "npm run build"
|
|
21
|
-
},
|
|
9
|
+
"files": ["dist/", "README.md"],
|
|
10
|
+
"engines": { "node": ">=18.0.0" },
|
|
11
|
+
"scripts": { "build": "tsc --noEmit false", "prepublishOnly": "npm run build" },
|
|
22
12
|
"dependencies": {
|
|
23
|
-
"chalk": "^5.3.0",
|
|
24
13
|
"ink": "^5.1.0",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
14
|
+
"react": "^18.3.1",
|
|
15
|
+
"chalk": "^5.3.0"
|
|
27
16
|
},
|
|
28
17
|
"devDependencies": {
|
|
29
18
|
"@types/react": "^18.3.12",
|