lumina-code-agent 1.6.1 → 1.6.2
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 +191 -116
- package/package.json +15 -5
package/dist/index.js
CHANGED
|
@@ -29,26 +29,119 @@ function ask(question) {
|
|
|
29
29
|
async function onboarding() {
|
|
30
30
|
console.log('');
|
|
31
31
|
console.log(' ⚡ LUMINA CODE — AI Coding Agent');
|
|
32
|
-
console.log(' Better than Claude Code. Better than Codex.');
|
|
33
|
-
console.log('');
|
|
34
|
-
console.log(' Welcome! Let\'s get you set up.');
|
|
35
32
|
console.log('');
|
|
36
33
|
const apiKey = await ask(' Enter your OpenRouter API key: ');
|
|
37
34
|
if (!apiKey.trim() || apiKey.trim().length < 10) {
|
|
38
|
-
console.log(' ❌ Invalid API key.
|
|
35
|
+
console.log(' ❌ Invalid API key.');
|
|
39
36
|
process.exit(1);
|
|
40
37
|
}
|
|
41
|
-
const name = await ask('
|
|
38
|
+
const name = await ask(' Your name (optional): ');
|
|
42
39
|
saveConfig({ openrouterKey: apiKey.trim(), userName: name.trim() || 'User' });
|
|
43
|
-
console.log('');
|
|
44
|
-
console.log(' ✓ Setup complete! Let\'s build something amazing.');
|
|
40
|
+
console.log(' ✓ Ready!');
|
|
45
41
|
console.log('');
|
|
46
42
|
}
|
|
43
|
+
// ── Tool Execution ──────────────────────────────────────────────────
|
|
44
|
+
async function executeTool(name, args, cwd) {
|
|
45
|
+
const workDir = cwd || process.cwd();
|
|
46
|
+
let output = '';
|
|
47
|
+
try {
|
|
48
|
+
switch (name) {
|
|
49
|
+
case 'run_command': {
|
|
50
|
+
const cmdCwd = args.cwd || workDir;
|
|
51
|
+
output = execSync(args.command, { cwd: cmdCwd, encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: args.timeout || 120000 }) || '(ok)';
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 'read_file': {
|
|
55
|
+
const p = args.path.startsWith('/') ? args.path : join(workDir, args.path);
|
|
56
|
+
if (!existsSync(p)) {
|
|
57
|
+
output = `File not found: ${args.path}`;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
output = readFileSync(p, 'utf-8');
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case 'write_file': {
|
|
64
|
+
const p = args.path.startsWith('/') ? args.path : join(workDir, args.path);
|
|
65
|
+
const dir = dirname(resolve(p));
|
|
66
|
+
if (!existsSync(dir))
|
|
67
|
+
mkdirSync(dir, { recursive: true });
|
|
68
|
+
writeFileSync(p, args.content, 'utf-8');
|
|
69
|
+
output = `✓ Created ${args.path} (${args.content.length} chars)`;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
case 'edit_file': {
|
|
73
|
+
const p = args.path.startsWith('/') ? args.path : join(workDir, args.path);
|
|
74
|
+
let fc = readFileSync(p, 'utf-8');
|
|
75
|
+
if (!fc.includes(args.search))
|
|
76
|
+
throw new Error(`Not found: "${args.search.slice(0, 50)}"`);
|
|
77
|
+
fc = fc.replace(args.search, args.replace);
|
|
78
|
+
writeFileSync(p, fc, 'utf-8');
|
|
79
|
+
output = `✓ Edited ${args.path}`;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case 'list_dir': {
|
|
83
|
+
const p = args.path || workDir;
|
|
84
|
+
const entries = readdirSync(p, { withFileTypes: true });
|
|
85
|
+
output = entries.slice(0, 50).map(e => `${e.isDirectory() ? '📁' : '📄'} ${e.name}`).join('\n');
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case 'search_files': {
|
|
89
|
+
const results = [];
|
|
90
|
+
const search = (dir, depth) => {
|
|
91
|
+
if (depth > 5)
|
|
92
|
+
return;
|
|
93
|
+
try {
|
|
94
|
+
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
95
|
+
if (e.name.startsWith('.') || e.name === 'node_modules' || e.name === 'dist' || e.name === '.git')
|
|
96
|
+
continue;
|
|
97
|
+
const fp = join(dir, e.name);
|
|
98
|
+
if (e.isDirectory())
|
|
99
|
+
search(fp, depth + 1);
|
|
100
|
+
else if (new RegExp(args.pattern.replace(/\*/g, '.*').replace(/\?/g, '.'), 'i').test(e.name))
|
|
101
|
+
results.push(relative(workDir, fp));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch { }
|
|
105
|
+
};
|
|
106
|
+
search(args.cwd || workDir, 0);
|
|
107
|
+
output = results.join('\n') || 'No files found';
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
case 'grep': {
|
|
111
|
+
const p = args.path.startsWith('/') ? args.path : join(workDir, args.path);
|
|
112
|
+
const c = readFileSync(p, 'utf-8');
|
|
113
|
+
output = c.split('\n').map((l, i) => new RegExp(args.pattern, 'gi').test(l) ? `${i + 1}: ${l}` : null).filter(Boolean).join('\n') || 'No matches';
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case 'git': {
|
|
117
|
+
output = execSync(`git ${args.args}`, { cwd: args.cwd || workDir, encoding: 'utf-8', maxBuffer: 1024 * 1024 }) || '(ok)';
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case 'npm': {
|
|
121
|
+
const pm = existsSync(join(args.cwd || workDir, 'bun.lockb')) ? 'bun' : existsSync(join(args.cwd || workDir, 'yarn.lock')) ? 'yarn' : 'npm';
|
|
122
|
+
output = execSync(`${pm} ${args.args}`, { cwd: args.cwd || workDir, encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: 120000 }) || '(ok)';
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
case 'deploy': {
|
|
126
|
+
output = execSync('npx vercel deploy --prod --yes', { cwd: args.cwd || workDir, encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: 300000 }) || '(deployed)';
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
default:
|
|
130
|
+
output = `Unknown tool: ${name}`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
output = `Error: ${e.message}`;
|
|
135
|
+
}
|
|
136
|
+
return output;
|
|
137
|
+
}
|
|
138
|
+
// ── Chat Loop ───────────────────────────────────────────────────────
|
|
47
139
|
async function chat(config) {
|
|
48
140
|
console.log(' Type what you want to build. I\'ll handle the rest.');
|
|
49
|
-
console.log(' Commands: /help /clear /exit');
|
|
141
|
+
console.log(' Commands: /help /clear /files /exit');
|
|
50
142
|
console.log('');
|
|
51
143
|
let messages = [];
|
|
144
|
+
const createdFiles = new Set();
|
|
52
145
|
while (true) {
|
|
53
146
|
const input = await ask(' > ');
|
|
54
147
|
const trimmed = input.trim();
|
|
@@ -61,61 +154,97 @@ async function chat(config) {
|
|
|
61
154
|
console.log(' ✓ Cleared.');
|
|
62
155
|
continue;
|
|
63
156
|
}
|
|
157
|
+
if (trimmed === '/files') {
|
|
158
|
+
if (createdFiles.size === 0) {
|
|
159
|
+
console.log(' No files created yet.');
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
console.log(' Created files:');
|
|
163
|
+
for (const f of createdFiles)
|
|
164
|
+
console.log(` ${f}`);
|
|
165
|
+
}
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
64
168
|
if (trimmed === '/help') {
|
|
65
|
-
console.log(' Commands: /help /clear /exit');
|
|
169
|
+
console.log(' Commands: /help /clear /files /exit');
|
|
66
170
|
continue;
|
|
67
171
|
}
|
|
68
172
|
messages.push({ role: 'user', content: trimmed });
|
|
69
173
|
console.log('');
|
|
70
174
|
try {
|
|
175
|
+
const systemPrompt = `You are LUMINA CODE — an elite AI coding agent.
|
|
176
|
+
|
|
177
|
+
WORKFLOW:
|
|
178
|
+
1. PLAN: Think about what files you need to create.
|
|
179
|
+
2. ACT: Use write_file to create each file. Use run_command to install packages, run builds.
|
|
180
|
+
3. VERIFY: Run builds to check for errors.
|
|
181
|
+
4. FIX: If something fails, debug and fix immediately.
|
|
182
|
+
|
|
183
|
+
QUALITY STANDARDS:
|
|
184
|
+
- Production-grade code, always
|
|
185
|
+
- TypeScript with proper types (never use 'any')
|
|
186
|
+
- Error handling everywhere
|
|
187
|
+
- Responsive design (320px to 2560px)
|
|
188
|
+
- Accessible (semantic HTML, ARIA, keyboard navigation)
|
|
189
|
+
- Clean architecture, modern patterns
|
|
190
|
+
- Beautiful UI (consistent spacing, typography, color)
|
|
191
|
+
- Use modern CSS (grid, flexbox, custom properties)
|
|
192
|
+
- Use Three.js or CSS 3D for 3D effects
|
|
193
|
+
|
|
194
|
+
FORBIDDEN:
|
|
195
|
+
- Lorem ipsum or placeholder content
|
|
196
|
+
- TODO/FIXME comments in production code
|
|
197
|
+
- Emoji in code or UI
|
|
198
|
+
- var keyword (always let/const)
|
|
199
|
+
- any type in TypeScript
|
|
200
|
+
- Skipping error handling
|
|
201
|
+
- Hardcoded secrets
|
|
202
|
+
|
|
203
|
+
IMPORTANT: When you need to create a file, use the write_file tool IMMEDIATELY.
|
|
204
|
+
Don't just describe what you'll do — actually DO it.
|
|
205
|
+
Create ALL necessary files for a complete, working project.
|
|
206
|
+
|
|
207
|
+
Working directory: ${process.cwd()}
|
|
208
|
+
|
|
209
|
+
When using a tool, output ONLY:
|
|
210
|
+
TOOL: <tool_name>
|
|
211
|
+
PARAMS: {"key": "value"}`;
|
|
71
212
|
const tools = [
|
|
72
|
-
{ 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'] } } },
|
|
213
|
+
{ type: 'function', function: { name: 'run_command', description: 'Run any shell command (npm, git, build, etc.)', parameters: { type: 'object', properties: { command: { type: 'string' }, cwd: { type: 'string' }, timeout: { type: 'number' } }, required: ['command'] } } },
|
|
73
214
|
{ type: 'function', function: { name: 'read_file', description: 'Read file contents', parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] } } },
|
|
74
|
-
{ 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'] } } },
|
|
75
|
-
{ type: 'function', function: { name: 'edit_file', description: '
|
|
215
|
+
{ type: 'function', function: { name: 'write_file', description: 'Create or overwrite a file with exact content', parameters: { type: 'object', properties: { path: { type: 'string' }, content: { type: 'string' } }, required: ['path', 'content'] } } },
|
|
216
|
+
{ type: 'function', function: { name: 'edit_file', description: 'Edit a file by replacing exact text', parameters: { type: 'object', properties: { path: { type: 'string' }, search: { type: 'string' }, replace: { type: 'string' } }, required: ['path', 'search', 'replace'] } } },
|
|
76
217
|
{ type: 'function', function: { name: 'list_dir', description: 'List directory contents', parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] } } },
|
|
77
|
-
{ type: 'function', function: { name: 'search_files', description: 'Find files by pattern', parameters: { type: 'object', properties: { pattern: { type: 'string' }, cwd: { type: 'string' } }, required: ['pattern'] } } },
|
|
218
|
+
{ type: 'function', function: { name: 'search_files', description: 'Find files by glob pattern', parameters: { type: 'object', properties: { pattern: { type: 'string' }, cwd: { type: 'string' } }, required: ['pattern'] } } },
|
|
78
219
|
{ type: 'function', function: { name: 'grep', description: 'Search file contents', parameters: { type: 'object', properties: { pattern: { type: 'string' }, path: { type: 'string' } }, required: ['pattern', 'path'] } } },
|
|
79
220
|
{ type: 'function', function: { name: 'git', description: 'Run git commands', parameters: { type: 'object', properties: { args: { type: 'string' }, cwd: { type: 'string' } }, required: ['args'] } } },
|
|
80
221
|
{ type: 'function', function: { name: 'npm', description: 'Run npm/yarn/pnpm/bun commands', parameters: { type: 'object', properties: { args: { type: 'string' }, cwd: { type: 'string' } }, required: ['args'] } } },
|
|
81
222
|
{ type: 'function', function: { name: 'deploy', description: 'Deploy to Vercel', parameters: { type: 'object', properties: { target: { type: 'string' }, cwd: { type: 'string' } } } } },
|
|
82
223
|
];
|
|
83
224
|
let iterations = 0;
|
|
84
|
-
const maxIterations =
|
|
225
|
+
const maxIterations = 50;
|
|
85
226
|
let currentMessages = [...messages];
|
|
227
|
+
let lastAssistantContent = '';
|
|
86
228
|
while (iterations < maxIterations) {
|
|
87
229
|
iterations++;
|
|
88
|
-
process.stdout.write(` ⏳
|
|
230
|
+
process.stdout.write(` ⏳ Thinking (step ${iterations})...\r`);
|
|
231
|
+
const controller = new AbortController();
|
|
232
|
+
const timeout = setTimeout(() => controller.abort(), 120000);
|
|
89
233
|
const res = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
|
90
234
|
method: 'POST',
|
|
91
235
|
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${config.openrouterKey}`, 'HTTP-Referer': 'https://luminaai.co.in', 'X-Title': 'Lumina Code' },
|
|
92
236
|
body: JSON.stringify({
|
|
93
237
|
model: 'openrouter/owl-alpha',
|
|
94
|
-
messages: [{ role: 'system', content:
|
|
95
|
-
|
|
96
|
-
WORKFLOW:
|
|
97
|
-
1. PLAN: Analyze the task. Create a brief plan.
|
|
98
|
-
2. ACT: Execute tools step by step. Read before writing.
|
|
99
|
-
3. VERIFY: Run builds, check for errors.
|
|
100
|
-
4. FIX: If something fails, debug and fix immediately.
|
|
101
|
-
5. DEPLOY: If requested, deploy automatically.
|
|
102
|
-
|
|
103
|
-
QUALITY: Production-grade code. No placeholders. No TODOs. No emoji in code.
|
|
104
|
-
Handle errors. TypeScript. Responsive. Accessible. Clean architecture.
|
|
105
|
-
|
|
106
|
-
FORBIDDEN: lorem ipsum, TODO comments, emoji in code, var keyword, any type, skipping error handling, hardcoded secrets.
|
|
107
|
-
|
|
108
|
-
When using a tool, output ONLY:
|
|
109
|
-
TOOL: <name>
|
|
110
|
-
PARAMS: <json>
|
|
111
|
-
|
|
112
|
-
Working directory: ${process.cwd()}` }, ...currentMessages],
|
|
238
|
+
messages: [{ role: 'system', content: systemPrompt }, ...currentMessages],
|
|
113
239
|
tools,
|
|
240
|
+
tool_choice: 'auto',
|
|
114
241
|
stream: false,
|
|
115
|
-
max_tokens:
|
|
242
|
+
max_tokens: 8000,
|
|
116
243
|
temperature: 0.1,
|
|
117
244
|
}),
|
|
245
|
+
signal: controller.signal,
|
|
118
246
|
});
|
|
247
|
+
clearTimeout(timeout);
|
|
119
248
|
if (!res.ok) {
|
|
120
249
|
const err = await res.text().catch(() => '');
|
|
121
250
|
throw new Error(`API error ${res.status}: ${err.slice(0, 200)}`);
|
|
@@ -126,98 +255,44 @@ Working directory: ${process.cwd()}` }, ...currentMessages],
|
|
|
126
255
|
throw new Error('No response from model');
|
|
127
256
|
const content = choice.message?.content || '';
|
|
128
257
|
const toolCalls = choice.message?.tool_calls || [];
|
|
129
|
-
|
|
258
|
+
lastAssistantContent = content;
|
|
259
|
+
currentMessages.push({ role: 'assistant', content, ...(toolCalls.length ? { tool_calls: toolCalls } : {}) });
|
|
130
260
|
if (toolCalls.length === 0) {
|
|
131
261
|
messages = currentMessages;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
console.log(' ...');
|
|
262
|
+
if (content)
|
|
263
|
+
console.log(` ${content.slice(0, 300)}`);
|
|
135
264
|
console.log('');
|
|
136
265
|
break;
|
|
137
266
|
}
|
|
138
267
|
for (const tc of toolCalls) {
|
|
139
|
-
|
|
140
|
-
const toolName = tc.function.name;
|
|
141
|
-
console.log(` ⚙ ${toolName}(${JSON.stringify(args).slice(0, 80)})`);
|
|
142
|
-
let output = '';
|
|
268
|
+
let args = {};
|
|
143
269
|
try {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const dir = dirname(resolve(args.path));
|
|
155
|
-
if (!existsSync(dir))
|
|
156
|
-
mkdirSync(dir, { recursive: true });
|
|
157
|
-
writeFileSync(args.path, args.content, 'utf-8');
|
|
158
|
-
output = `Wrote ${args.content.length} chars to ${args.path}`;
|
|
159
|
-
break;
|
|
160
|
-
}
|
|
161
|
-
case 'edit_file': {
|
|
162
|
-
let fc = readFileSync(args.path, 'utf-8');
|
|
163
|
-
if (!fc.includes(args.search))
|
|
164
|
-
throw new Error(`Not found: "${args.search.slice(0, 50)}"`);
|
|
165
|
-
fc = fc.replace(args.search, args.replace);
|
|
166
|
-
writeFileSync(args.path, fc, 'utf-8');
|
|
167
|
-
output = `Edited ${args.path}`;
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
case 'list_dir':
|
|
171
|
-
output = readdirSync(args.path, { withFileTypes: true }).map(e => `${e.isDirectory() ? '📁' : '📄'} ${e.name}`).join('\n');
|
|
172
|
-
break;
|
|
173
|
-
case 'search_files': {
|
|
174
|
-
const results = [];
|
|
175
|
-
const search = (dir, depth) => {
|
|
176
|
-
if (depth > 5)
|
|
177
|
-
return;
|
|
178
|
-
try {
|
|
179
|
-
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
180
|
-
if (e.name.startsWith('.') || e.name === 'node_modules')
|
|
181
|
-
continue;
|
|
182
|
-
const fp = join(dir, e.name);
|
|
183
|
-
if (e.isDirectory())
|
|
184
|
-
search(fp, depth + 1);
|
|
185
|
-
else if (new RegExp(args.pattern.replace(/\*/g, '.*'), 'i').test(e.name))
|
|
186
|
-
results.push(relative(args.cwd || process.cwd(), fp));
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
catch { }
|
|
190
|
-
};
|
|
191
|
-
search(args.cwd || process.cwd(), 0);
|
|
192
|
-
output = results.join('\n') || 'No files found';
|
|
193
|
-
break;
|
|
194
|
-
}
|
|
195
|
-
case 'grep': {
|
|
196
|
-
const c = readFileSync(args.path, 'utf-8');
|
|
197
|
-
output = c.split('\n').map((l, i) => new RegExp(args.pattern, 'gi').test(l) ? `${i + 1}: ${l}` : null).filter(Boolean).join('\n') || 'No matches';
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
200
|
-
case 'git':
|
|
201
|
-
output = execSync(`git ${args.args}`, { cwd: args.cwd || process.cwd(), encoding: 'utf-8', maxBuffer: 1024 * 1024 }) || '(ok)';
|
|
202
|
-
break;
|
|
203
|
-
case 'npm': {
|
|
204
|
-
const pm = existsSync(join(args.cwd || process.cwd(), 'bun.lockb')) ? 'bun' : existsSync(join(args.cwd || process.cwd(), 'yarn.lock')) ? 'yarn' : 'npm';
|
|
205
|
-
output = execSync(`${pm} ${args.args}`, { cwd: args.cwd || process.cwd(), encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: 120000 }) || '(ok)';
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
case 'deploy':
|
|
209
|
-
output = execSync('npx vercel deploy --prod --yes', { cwd: args.cwd || process.cwd(), encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024, timeout: 300000 }) || '(deployed)';
|
|
210
|
-
break;
|
|
211
|
-
default: output = `Unknown tool: ${toolName}`;
|
|
212
|
-
}
|
|
270
|
+
args = JSON.parse(tc.function.arguments || '{}');
|
|
271
|
+
}
|
|
272
|
+
catch { }
|
|
273
|
+
const toolName = tc.function.name;
|
|
274
|
+
console.log(` ⚙ ${toolName}(${JSON.stringify(args).slice(0, 100)})`);
|
|
275
|
+
const output = await executeTool(toolName, args, process.cwd());
|
|
276
|
+
// Track created files
|
|
277
|
+
if (toolName === 'write_file' && args.path) {
|
|
278
|
+
createdFiles.add(args.path);
|
|
279
|
+
console.log(` ✓ Created: ${args.path}`);
|
|
213
280
|
}
|
|
214
|
-
|
|
215
|
-
|
|
281
|
+
else {
|
|
282
|
+
const shortOut = output.slice(0, 150).replace(/\n/g, ' ');
|
|
283
|
+
console.log(` ✓ ${shortOut}`);
|
|
216
284
|
}
|
|
217
|
-
currentMessages.push({ role: 'tool', content: output.slice(0,
|
|
218
|
-
console.log(` ✓ ${output.slice(0, 100)}`);
|
|
285
|
+
currentMessages.push({ role: 'tool', content: output.slice(0, 3000), tool_call_id: tc.id });
|
|
219
286
|
}
|
|
220
287
|
}
|
|
288
|
+
if (iterations >= maxIterations) {
|
|
289
|
+
console.log(' ⚠ Reached max iterations. Partial result:');
|
|
290
|
+
console.log(` ${lastAssistantContent.slice(0, 300)}`);
|
|
291
|
+
}
|
|
292
|
+
if (createdFiles.size > 0) {
|
|
293
|
+
console.log(` 📁 Created ${createdFiles.size} file(s)`);
|
|
294
|
+
}
|
|
295
|
+
console.log('');
|
|
221
296
|
}
|
|
222
297
|
catch (e) {
|
|
223
298
|
console.log(` ⚠ Error: ${e.message}`);
|
package/package.json
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lumina-code-agent",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "Lumina Code - AI coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"bin": {
|
|
7
|
+
"bin": {
|
|
8
|
+
"lumina": "dist/index.js"
|
|
9
|
+
},
|
|
8
10
|
"main": "dist/index.js",
|
|
9
|
-
"files": [
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
"files": [
|
|
12
|
+
"dist/",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18.0.0"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc --noEmit false",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
12
22
|
"dependencies": {},
|
|
13
23
|
"devDependencies": {
|
|
14
24
|
"@types/node": "^22.10.0",
|