lumina-code-agent 1.3.0 → 1.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.
- package/dist/index.js +108 -67
- package/package.json +7 -18
package/dist/index.js
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
// @ts-nocheck
|
|
3
3
|
import React, { useState, useCallback, useRef } from 'react';
|
|
4
4
|
import { Box, Text, useInput, useApp, Spacer } from 'ink';
|
|
5
|
-
import
|
|
6
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'fs';
|
|
7
6
|
import { homedir } from 'os';
|
|
8
|
-
import { join } from 'path';
|
|
7
|
+
import { join, dirname, resolve, relative } from 'path';
|
|
9
8
|
const CONFIG_DIR = join(homedir(), '.lumina');
|
|
10
9
|
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
11
10
|
function loadConfig() {
|
|
@@ -23,12 +22,27 @@ function saveConfig(config) {
|
|
|
23
22
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
24
23
|
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
25
24
|
}
|
|
25
|
+
// ── Simple Text Input Component ─────────────────────────────────────
|
|
26
|
+
function PromptInput({ value, onChange, onSubmit, placeholder }) {
|
|
27
|
+
useInput((input, key) => {
|
|
28
|
+
if (key.return && onSubmit) {
|
|
29
|
+
onSubmit(value);
|
|
30
|
+
}
|
|
31
|
+
else if (key.backspace || key.delete) {
|
|
32
|
+
onChange(value.slice(0, -1));
|
|
33
|
+
}
|
|
34
|
+
else if (!key.ctrl && !key.meta && input) {
|
|
35
|
+
onChange(value + input);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return React.createElement(Box, null, React.createElement(Text, { color: '#7C5CFC' }, ' > '), React.createElement(Text, { color: '#FAFAFA' }, value || placeholder || 'Type something...'), React.createElement(Text, { color: '#52525B' }, '▌'));
|
|
39
|
+
}
|
|
26
40
|
// ── Onboarding Screen ───────────────────────────────────────────────
|
|
27
41
|
function Onboarding({ onComplete }) {
|
|
28
42
|
const [step, setStep] = useState(0);
|
|
29
43
|
const [apiKey, setApiKey] = useState('');
|
|
30
44
|
const [name, setName] = useState('');
|
|
31
|
-
|
|
45
|
+
const handleKey = useCallback((input, key) => {
|
|
32
46
|
if (key.return) {
|
|
33
47
|
if (step === 0) {
|
|
34
48
|
setStep(1);
|
|
@@ -37,70 +51,60 @@ function Onboarding({ onComplete }) {
|
|
|
37
51
|
setStep(2);
|
|
38
52
|
}
|
|
39
53
|
else if (step === 2) {
|
|
40
|
-
saveConfig({ openrouterKey: apiKey.trim(), userName: name.trim() || 'User'
|
|
54
|
+
saveConfig({ openrouterKey: apiKey.trim(), userName: name.trim() || 'User' });
|
|
41
55
|
onComplete();
|
|
42
56
|
}
|
|
43
57
|
}
|
|
44
|
-
|
|
45
|
-
|
|
58
|
+
else if (key.backspace || key.delete) {
|
|
59
|
+
if (step === 1)
|
|
60
|
+
setApiKey(v => v.slice(0, -1));
|
|
61
|
+
if (step === 2)
|
|
62
|
+
setName(v => v.slice(0, -1));
|
|
63
|
+
}
|
|
64
|
+
else if (!key.ctrl && !key.meta && input) {
|
|
65
|
+
if (step === 1)
|
|
66
|
+
setApiKey(v => v + input);
|
|
67
|
+
if (step === 2)
|
|
68
|
+
setName(v => v + input);
|
|
69
|
+
}
|
|
70
|
+
}, [step, apiKey, name, onComplete]);
|
|
71
|
+
useInput(handleKey);
|
|
72
|
+
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
73
|
}
|
|
47
74
|
// ── Chat Screen ─────────────────────────────────────────────────────
|
|
48
75
|
function ChatScreen({ config }) {
|
|
49
76
|
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
|
-
]);
|
|
77
|
+
const [messages, setMessages] = useState([]);
|
|
73
78
|
const [input, setInput] = useState('');
|
|
74
79
|
const [status, setStatus] = useState('Ready');
|
|
75
80
|
const [thinking, setThinking] = useState(false);
|
|
76
81
|
const scrollRef = useRef(0);
|
|
77
|
-
const visibleMessages = messages.
|
|
78
|
-
const handleSubmit = useCallback(async () => {
|
|
79
|
-
const trimmed =
|
|
82
|
+
const visibleMessages = messages.slice(-50);
|
|
83
|
+
const handleSubmit = useCallback(async (text) => {
|
|
84
|
+
const trimmed = text.trim();
|
|
80
85
|
if (!trimmed || thinking)
|
|
81
86
|
return;
|
|
82
87
|
setInput('');
|
|
83
88
|
setThinking(true);
|
|
84
89
|
setStatus('Thinking...');
|
|
90
|
+
scrollRef.current++;
|
|
85
91
|
const userMsg = { role: 'user', content: trimmed };
|
|
86
92
|
const newMessages = [...messages, userMsg];
|
|
87
93
|
setMessages(newMessages);
|
|
88
|
-
scrollRef.current++;
|
|
89
94
|
try {
|
|
90
95
|
const OPENROUTER_URL = 'https://openrouter.ai/api/v1/chat/completions';
|
|
91
96
|
const tools = [
|
|
92
97
|
{ 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'] } } },
|
|
98
|
+
{ type: 'function', function: { name: 'read_file', description: 'Read file contents. ALWAYS read before editing.', parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] } } },
|
|
99
|
+
{ 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'] } } },
|
|
100
|
+
{ 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
101
|
{ 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'] } } },
|
|
102
|
+
{ 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
103
|
{ type: 'function', function: { name: 'grep', description: 'Search file contents', parameters: { type: 'object', properties: { pattern: { type: 'string' }, path: { type: 'string' } }, required: ['pattern', 'path'] } } },
|
|
99
104
|
{ 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'] } } },
|
|
105
|
+
{ 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
106
|
{ type: 'function', function: { name: 'deploy', description: 'Deploy to Vercel', parameters: { type: 'object', properties: { target: { type: 'string' }, cwd: { type: 'string' } } } } },
|
|
102
107
|
];
|
|
103
|
-
let assistantContent = '';
|
|
104
108
|
let iterations = 0;
|
|
105
109
|
const maxIterations = 30;
|
|
106
110
|
let currentMessages = [...newMessages];
|
|
@@ -110,7 +114,47 @@ Working directory: ${process.cwd()}` },
|
|
|
110
114
|
const res = await fetch(OPENROUTER_URL, {
|
|
111
115
|
method: 'POST',
|
|
112
116
|
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${config.openrouterKey}`, 'HTTP-Referer': 'https://luminaai.co.in', 'X-Title': 'Lumina Code' },
|
|
113
|
-
body: JSON.stringify({
|
|
117
|
+
body: JSON.stringify({
|
|
118
|
+
model: 'openrouter/owl-alpha',
|
|
119
|
+
messages: [{ role: 'system', content: `You are LUMINA CODE — an elite AI coding agent.
|
|
120
|
+
|
|
121
|
+
MODEL: openrouter/owl-alpha (1M+ context, best reasoning)
|
|
122
|
+
|
|
123
|
+
WORKFLOW:
|
|
124
|
+
1. PLAN: Analyze the task. Create a brief plan.
|
|
125
|
+
2. ACT: Execute tools step by step. Read before writing.
|
|
126
|
+
3. VERIFY: Run builds, check for errors.
|
|
127
|
+
4. FIX: If something fails, debug and fix immediately.
|
|
128
|
+
5. DEPLOY: If requested, deploy automatically.
|
|
129
|
+
|
|
130
|
+
QUALITY STANDARDS:
|
|
131
|
+
- Production-grade code, always
|
|
132
|
+
- TypeScript with proper types (never use 'any')
|
|
133
|
+
- Error handling everywhere
|
|
134
|
+
- Responsive design (320px to 2560px)
|
|
135
|
+
- Accessible (semantic HTML, ARIA, keyboard navigation)
|
|
136
|
+
- Clean architecture, modern patterns
|
|
137
|
+
- Beautiful UI (consistent spacing, typography, color)
|
|
138
|
+
|
|
139
|
+
FORBIDDEN:
|
|
140
|
+
- Lorem ipsum or placeholder content
|
|
141
|
+
- TODO/FIXME comments in production code
|
|
142
|
+
- Emoji in code or UI
|
|
143
|
+
- var keyword (always let/const)
|
|
144
|
+
- any type in TypeScript
|
|
145
|
+
- Skipping error handling
|
|
146
|
+
- Hardcoded secrets
|
|
147
|
+
|
|
148
|
+
When using a tool, output ONLY:
|
|
149
|
+
TOOL: <name>
|
|
150
|
+
PARAMS: <json>
|
|
151
|
+
|
|
152
|
+
Working directory: ${process.cwd()}` }, ...currentMessages],
|
|
153
|
+
tools,
|
|
154
|
+
stream: false,
|
|
155
|
+
max_tokens: 32000,
|
|
156
|
+
temperature: 0.1,
|
|
157
|
+
}),
|
|
114
158
|
});
|
|
115
159
|
if (!res.ok) {
|
|
116
160
|
const err = await res.text().catch(() => '');
|
|
@@ -122,10 +166,10 @@ Working directory: ${process.cwd()}` },
|
|
|
122
166
|
throw new Error('No response from model');
|
|
123
167
|
const content = choice.message?.content || '';
|
|
124
168
|
const toolCalls = choice.message?.tool_calls || [];
|
|
125
|
-
|
|
126
|
-
|
|
169
|
+
currentMessages.push({ role: 'assistant', content });
|
|
170
|
+
setMessages([...currentMessages]);
|
|
171
|
+
scrollRef.current++;
|
|
127
172
|
if (toolCalls.length === 0) {
|
|
128
|
-
setMessages([...currentMessages]);
|
|
129
173
|
setStatus('Done');
|
|
130
174
|
break;
|
|
131
175
|
}
|
|
@@ -137,9 +181,9 @@ Working directory: ${process.cwd()}` },
|
|
|
137
181
|
scrollRef.current++;
|
|
138
182
|
let output = '';
|
|
139
183
|
try {
|
|
184
|
+
const { execSync } = await import('child_process');
|
|
140
185
|
switch (toolName) {
|
|
141
186
|
case 'run_command': {
|
|
142
|
-
const { execSync } = await import('child_process');
|
|
143
187
|
const cwd = args.cwd || process.cwd();
|
|
144
188
|
output = execSync(args.command, { cwd, encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: args.timeout || 120000, shell: true }) || '(no output)';
|
|
145
189
|
break;
|
|
@@ -149,7 +193,7 @@ Working directory: ${process.cwd()}` },
|
|
|
149
193
|
break;
|
|
150
194
|
}
|
|
151
195
|
case 'write_file': {
|
|
152
|
-
const dir =
|
|
196
|
+
const dir = dirname(resolve(args.path));
|
|
153
197
|
if (!existsSync(dir))
|
|
154
198
|
mkdirSync(dir, { recursive: true });
|
|
155
199
|
writeFileSync(args.path, args.content, 'utf-8');
|
|
@@ -171,21 +215,19 @@ Working directory: ${process.cwd()}` },
|
|
|
171
215
|
break;
|
|
172
216
|
}
|
|
173
217
|
case 'search_files': {
|
|
174
|
-
const { readdirSync } = await import('fs');
|
|
175
|
-
const { join: pathJoin, relative: pathRelative } = await import('path');
|
|
176
218
|
const results = [];
|
|
177
219
|
const search = (dir, depth) => {
|
|
178
220
|
if (depth > 5)
|
|
179
221
|
return;
|
|
180
222
|
try {
|
|
181
223
|
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
182
|
-
if (e.name.startsWith('.') || e.name === 'node_modules')
|
|
224
|
+
if (e.name.startsWith('.') || e.name === 'node_modules' || e.name === 'dist')
|
|
183
225
|
continue;
|
|
184
|
-
const fp =
|
|
226
|
+
const fp = join(dir, e.name);
|
|
185
227
|
if (e.isDirectory())
|
|
186
228
|
search(fp, depth + 1);
|
|
187
|
-
else if (new RegExp(pattern.replace(/\*/g, '.*'), 'i').test(e.name))
|
|
188
|
-
results.push(
|
|
229
|
+
else if (new RegExp(args.pattern.replace(/\*/g, '.*'), 'i').test(e.name))
|
|
230
|
+
results.push(relative(args.cwd || process.cwd(), fp));
|
|
189
231
|
}
|
|
190
232
|
}
|
|
191
233
|
catch { }
|
|
@@ -202,18 +244,15 @@ Working directory: ${process.cwd()}` },
|
|
|
202
244
|
break;
|
|
203
245
|
}
|
|
204
246
|
case 'git': {
|
|
205
|
-
const { execSync } = await import('child_process');
|
|
206
247
|
output = execSync(`git ${args.args}`, { cwd: args.cwd || process.cwd(), encoding: 'utf-8', maxBuffer: 1024 * 1024 }) || '(ok)';
|
|
207
248
|
break;
|
|
208
249
|
}
|
|
209
250
|
case 'npm': {
|
|
210
|
-
const { execSync } = await import('child_process');
|
|
211
251
|
const pm = existsSync(join(args.cwd || process.cwd(), 'bun.lockb')) ? 'bun' : existsSync(join(args.cwd || process.cwd(), 'yarn.lock')) ? 'yarn' : 'npm';
|
|
212
252
|
output = execSync(`${pm} ${args.args}`, { cwd: args.cwd || process.cwd(), encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: 120000 }) || '(ok)';
|
|
213
253
|
break;
|
|
214
254
|
}
|
|
215
255
|
case 'deploy': {
|
|
216
|
-
const { execSync } = await import('child_process');
|
|
217
256
|
output = execSync('npx vercel deploy --prod --yes', { cwd: args.cwd || process.cwd(), encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: 300000 }) || '(deployed)';
|
|
218
257
|
break;
|
|
219
258
|
}
|
|
@@ -229,9 +268,8 @@ Working directory: ${process.cwd()}` },
|
|
|
229
268
|
scrollRef.current++;
|
|
230
269
|
}
|
|
231
270
|
}
|
|
232
|
-
if (iterations >= maxIterations)
|
|
271
|
+
if (iterations >= maxIterations)
|
|
233
272
|
setStatus('Reached max iterations');
|
|
234
|
-
}
|
|
235
273
|
}
|
|
236
274
|
catch (e) {
|
|
237
275
|
setMessages(prev => [...prev, { role: 'assistant', content: `⚠ Error: ${e.message}` }]);
|
|
@@ -239,11 +277,20 @@ Working directory: ${process.cwd()}` },
|
|
|
239
277
|
}
|
|
240
278
|
setThinking(false);
|
|
241
279
|
}, [input, thinking, messages, config]);
|
|
242
|
-
useInput((
|
|
243
|
-
if (key.ctrl &&
|
|
280
|
+
useInput((input, key) => {
|
|
281
|
+
if (key.ctrl && input === 'c')
|
|
244
282
|
exit();
|
|
245
|
-
if (key.ctrl &&
|
|
283
|
+
if (key.ctrl && input === 'd')
|
|
246
284
|
exit();
|
|
285
|
+
if (key.return) {
|
|
286
|
+
handleSubmit(input);
|
|
287
|
+
}
|
|
288
|
+
else if (key.backspace || key.delete) {
|
|
289
|
+
setInput(v => v.slice(0, -1));
|
|
290
|
+
}
|
|
291
|
+
else if (!key.ctrl && !key.meta) {
|
|
292
|
+
setInput(v => v + input);
|
|
293
|
+
}
|
|
247
294
|
});
|
|
248
295
|
return React.createElement(Box, { flexDirection: 'column', height: '100%' },
|
|
249
296
|
// Header
|
|
@@ -256,16 +303,10 @@ Working directory: ${process.cwd()}` },
|
|
|
256
303
|
if (m.role === 'tool') {
|
|
257
304
|
return React.createElement(Box, { key: i, marginTop: 0, paddingLeft: 2 }, React.createElement(Text, { color: '#52525B' }, ' ' + m.content.slice(0, 200)));
|
|
258
305
|
}
|
|
259
|
-
// Assistant
|
|
260
306
|
return React.createElement(Box, { key: i, marginTop: 1, paddingLeft: 2 }, React.createElement(Text, { color: '#A1A1AA' }, m.content.slice(0, 500)));
|
|
261
307
|
}), thinking && React.createElement(Text, { color: '#F59E0B' }, ' ⏳ thinking...')),
|
|
262
308
|
// Input
|
|
263
|
-
React.createElement(Box, { borderStyle: 'single', borderColor: '#3F3F46', paddingX: 1 }, React.createElement(Text, { color: '#7C5CFC' }, ' > '), React.createElement(
|
|
264
|
-
value: input,
|
|
265
|
-
onChange: setInput,
|
|
266
|
-
onSubmit: handleSubmit,
|
|
267
|
-
placeholder: 'What do you want to build?',
|
|
268
|
-
})),
|
|
309
|
+
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' }, '▌')),
|
|
269
310
|
// Footer
|
|
270
311
|
React.createElement(Box, { paddingX: 2 }, React.createElement(Text, { color: '#3F3F46' }, ' Ctrl+C to exit | OWL-Alpha ')));
|
|
271
312
|
}
|
package/package.json
CHANGED
|
@@ -1,29 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lumina-code-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.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",
|