lumina-code-agent 1.6.6 → 1.6.8

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 (2) hide show
  1. package/dist/index.js +67 -134
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // @ts-nocheck
3
3
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
4
4
  import { homedir } from 'os';
5
- import { join, dirname, resolve } from 'path';
5
+ import { join, dirname, resolve, extname } from 'path';
6
6
  import { createInterface } from 'readline';
7
7
  const CONFIG_DIR = join(homedir(), '.lumina');
8
8
  const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
@@ -34,6 +34,21 @@ async function onboarding() {
34
34
  saveConfig({ openrouterKey: apiKey.trim(), userName: name.trim() || 'User' });
35
35
  console.log(' ✓ Ready!\n');
36
36
  }
37
+ function extractFiles(text) {
38
+ const files = [];
39
+ const fileRegex = /FILENAME:\s*([^\n]+)\n([\s\S]*?)END FILE/g;
40
+ let match;
41
+ while ((match = fileRegex.exec(text)) !== null) {
42
+ const rawPath = match[1].trim();
43
+ const content = match[2].trim();
44
+ if (!rawPath || rawPath.endsWith('/') || !extname(rawPath))
45
+ continue;
46
+ if (rawPath.includes('<') || rawPath.includes('>') || rawPath.includes('"'))
47
+ continue;
48
+ files.push({ path: rawPath, content });
49
+ }
50
+ return files;
51
+ }
37
52
  async function chat(config) {
38
53
  console.log(' Type what you want to build. I\'ll handle the rest.');
39
54
  console.log(' Commands: /help /clear /files /exit\n');
@@ -65,10 +80,9 @@ async function chat(config) {
65
80
  console.log(' /help /clear /files /exit\n');
66
81
  continue;
67
82
  }
68
- // Ultra-explicit system prompt
69
- const systemPrompt = `You are LUMINA CODE. You MUST output files using this EXACT format. Do NOT describe what you will do. DO IT.
83
+ const systemPrompt = `You are LUMINA CODE. Create COMPLETE production-grade websites.
70
84
 
71
- OUTPUT THIS EXACT FORMAT NO EXCEPTIONS:
85
+ OUTPUT FORMAT — Use this EXACT format for EVERY file:
72
86
 
73
87
  FILENAME: index.html
74
88
  <!DOCTYPE html>
@@ -76,39 +90,38 @@ FILENAME: index.html
76
90
  <head>
77
91
  <meta charset="UTF-8">
78
92
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
79
- <title>Page</title>
80
- <style>
81
- /* ALL CSS here */
82
- </style>
93
+ <title>Title</title>
94
+ <link rel="stylesheet" href="style.css">
83
95
  </head>
84
96
  <body>
85
- <!-- ALL HTML here -->
86
- <script>
87
- // ALL JavaScript here
88
- </script>
97
+ <!-- Complete HTML here -->
98
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
99
+ <script src="script.js"></script>
89
100
  </body>
90
101
  </html>
91
102
  END FILE
92
103
 
93
104
  FILENAME: style.css
94
- /* ALL CSS */
105
+ /* Complete CSS here */
95
106
  END FILE
96
107
 
97
108
  FILENAME: script.js
98
- // ALL JavaScript
109
+ // Complete JavaScript here
99
110
  END FILE
100
111
 
101
112
  RULES:
102
113
  - Start IMMEDIATELY with FILENAME: index.html
103
- - Output COMPLETE file contents — every single line
114
+ - Output COMPLETE files — every line, no truncation
115
+ - Do NOT describe what you will do — JUST DO IT
104
116
  - Do NOT output any text before FILENAME:
105
- - Do NOT describe what you will do
106
- - Do NOT output markdown code blocks
107
- - ONLY use FILENAME: ... END FILE format
117
+ - Do NOT use markdown code blocks
108
118
  - Create ALL files needed for a complete working project
119
+ - Use Three.js from CDN for 3D
120
+ - No placeholders, no TODOs, no lorem ipsum
109
121
 
110
122
  Working directory: ${process.cwd()}`;
111
- console.log(' ⏳ Generating...\n');
123
+ console.log('');
124
+ console.log(' ⏳ Sending to AI...');
112
125
  try {
113
126
  const controller = new AbortController();
114
127
  const timeout = setTimeout(() => controller.abort(), 300000);
@@ -126,7 +139,7 @@ Working directory: ${process.cwd()}`;
126
139
  { role: 'system', content: systemPrompt },
127
140
  { role: 'user', content: trimmed },
128
141
  ],
129
- stream: true,
142
+ stream: false,
130
143
  max_tokens: 16000,
131
144
  temperature: 0.1,
132
145
  }),
@@ -137,125 +150,45 @@ Working directory: ${process.cwd()}`;
137
150
  const err = await res.text().catch(() => '');
138
151
  throw new Error(`API error ${res.status}: ${err.slice(0, 200)}`);
139
152
  }
140
- // Stream and parse files in real-time
141
- const reader = res.body.getReader();
142
- const decoder = new TextDecoder();
143
- let buffer = '';
144
- let currentFile = null;
145
- let currentContent = '';
146
- let inFile = false;
147
- let fileCount = 0;
148
- let outputBuffer = '';
149
- while (true) {
150
- const { done, value } = await reader.read();
151
- if (done)
152
- break;
153
- buffer += decoder.decode(value, { stream: true });
154
- const lines = buffer.split('\n');
155
- buffer = lines.pop();
153
+ console.log(' ⏳ AI is thinking...');
154
+ const data = await res.json();
155
+ const content = data.choices?.[0]?.message?.content || '';
156
+ if (!content) {
157
+ console.log(' ⚠ No response from model.\n');
158
+ continue;
159
+ }
160
+ console.log(' ✓ AI responded! Parsing files...\n');
161
+ const files = extractFiles(content);
162
+ if (files.length === 0) {
163
+ console.log(' ⚠ No files detected. Full output:\n');
164
+ console.log(' ──────────────────────────────────────');
165
+ // Print first 100 lines
166
+ const lines = content.split('\n').slice(0, 100);
156
167
  for (const line of lines) {
157
- if (!line.startsWith('data: '))
158
- continue;
159
- const data = line.slice(6).trim();
160
- if (data === '[DONE]')
161
- continue;
162
- let delta = '';
163
- try {
164
- const parsed = JSON.parse(data);
165
- delta = parsed.choices?.[0]?.delta?.content || '';
166
- }
167
- catch {
168
- continue;
169
- }
170
- if (!delta)
171
- continue;
172
- // Process delta for file detection
173
- for (let i = 0; i < delta.length; i++) {
174
- const char = delta[i];
175
- if (!inFile) {
176
- // Look for FILENAME:
177
- outputBuffer += char;
178
- if (outputBuffer.endsWith('FILENAME:')) {
179
- // Found it! Extract filename on next line
180
- currentFile = '';
181
- inFile = true;
182
- currentContent = '';
183
- outputBuffer = '';
184
- process.stdout.write(' 📄 ');
185
- }
186
- else if (outputBuffer.length > 20) {
187
- // Not matching, flush
188
- process.stdout.write(outputBuffer);
189
- outputBuffer = '';
190
- }
191
- }
192
- else {
193
- // In filename or content
194
- if (char === '\n' && !currentFile.includes('/')) {
195
- // Still in filename line (no path separator yet)
196
- if (currentFile.length > 0 && !currentFile.includes('.')) {
197
- // This is a path separator line, keep accumulating
198
- currentFile += char;
199
- }
200
- else {
201
- // End of filename
202
- currentFile = currentFile.trim();
203
- console.log(currentFile);
204
- fileCount++;
205
- }
206
- }
207
- else if (currentFile && !currentContent && char === '\n' && currentFile.includes('.')) {
208
- // First newline after filename, start content
209
- currentContent = '';
210
- }
211
- else if (currentContent !== null) {
212
- currentContent += char;
213
- // Check for END FILE
214
- if (currentContent.endsWith('END FILE')) {
215
- const fileContent = currentContent.slice(0, -8).trim();
216
- try {
217
- const filePath = join(process.cwd(), currentFile);
218
- const dir = dirname(resolve(filePath));
219
- if (!existsSync(dir))
220
- mkdirSync(dir, { recursive: true });
221
- writeFileSync(filePath, fileContent, 'utf-8');
222
- createdFiles.add(currentFile);
223
- console.log(` ✓ Saved: ${currentFile} (${fileContent.length} chars)`);
224
- }
225
- catch (e) {
226
- console.log(` ✗ Error: ${currentFile}: ${e.message}`);
227
- }
228
- currentFile = null;
229
- currentContent = null;
230
- inFile = false;
231
- }
232
- }
233
- else {
234
- currentFile += char;
235
- }
236
- }
237
- }
168
+ console.log(' ' + line);
169
+ }
170
+ if (content.split('\n').length > 100) {
171
+ console.log(' ... (truncated)');
238
172
  }
173
+ console.log(' ──────────────────────────────────────\n');
174
+ continue;
239
175
  }
240
- // Handle any remaining content
241
- if (inFile && currentFile && currentContent) {
242
- const fileContent = currentContent.replace(/END FILE$/, '').trim();
243
- if (fileContent) {
244
- try {
245
- const filePath = join(process.cwd(), currentFile);
246
- const dir = dirname(resolve(filePath));
247
- if (!existsSync(dir))
248
- mkdirSync(dir, { recursive: true });
249
- writeFileSync(filePath, fileContent, 'utf-8');
250
- createdFiles.add(currentFile);
251
- console.log(` ✓ Saved: ${currentFile} (${fileContent.length} chars)`);
252
- }
253
- catch (e) {
254
- console.log(` ✗ Error: ${currentFile}: ${e.message}`);
255
- }
176
+ console.log(` 📁 Found ${files.length} file(s):\n`);
177
+ for (const file of files) {
178
+ try {
179
+ const filePath = join(process.cwd(), file.path);
180
+ const dir = dirname(resolve(filePath));
181
+ if (!existsSync(dir))
182
+ mkdirSync(dir, { recursive: true });
183
+ writeFileSync(filePath, file.content, 'utf-8');
184
+ createdFiles.add(file.path);
185
+ console.log(` ✅ ${file.path} (${file.content.length} chars)`);
186
+ }
187
+ catch (e) {
188
+ console.log(` ❌ ${file.path}: ${e.message}`);
256
189
  }
257
190
  }
258
- console.log(`\n 📊 Created ${fileCount} file(s) | Total: ${createdFiles.size}`);
191
+ console.log(`\n 📊 Total files created: ${createdFiles.size}`);
259
192
  console.log('');
260
193
  }
261
194
  catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lumina-code-agent",
3
- "version": "1.6.6",
3
+ "version": "1.6.8",
4
4
  "description": "Lumina Code - AI coding agent",
5
5
  "license": "MIT",
6
6
  "type": "module",