lumina-code-agent 1.6.10 → 1.6.11

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 +45 -82
  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');
@@ -35,6 +35,21 @@ async function onboarding() {
35
35
  saveConfig({ openrouterKey: apiKey.trim(), userName: 'User' });
36
36
  console.log(' ✅ Ready!\n');
37
37
  }
38
+ function extractFiles(text) {
39
+ const files = [];
40
+ const fileRegex = /FILENAME:\s*([^\n]+)\n([\s\S]*?)END FILE/g;
41
+ let match;
42
+ while ((match = fileRegex.exec(text)) !== null) {
43
+ const rawPath = match[1].trim();
44
+ const content = match[2].trim();
45
+ if (!rawPath || rawPath.endsWith('/') || !extname(rawPath))
46
+ continue;
47
+ if (rawPath.includes('<') || rawPath.includes('"') || rawPath.includes('`'))
48
+ continue;
49
+ files.push({ path: rawPath, content });
50
+ }
51
+ return files;
52
+ }
38
53
  async function chat(config) {
39
54
  console.log(' 💬 Type what you want to build. /exit to quit.\n');
40
55
  const createdFiles = new Set();
@@ -61,14 +76,14 @@ FILENAME: index.html
61
76
  END FILE
62
77
 
63
78
  FILENAME: style.css
64
- /* COMPLETE CSS — no truncation */
79
+ /* COMPLETE CSS */
65
80
  END FILE
66
81
 
67
82
  FILENAME: script.js
68
- // COMPLETE JS — Three.js robot, animations, scroll triggers
83
+ // COMPLETE JS
69
84
  END FILE
70
85
 
71
- RULES: Start IMMEDIATELY with FILENAME: index.html. Do NOT describe. JUST OUTPUT COMPLETE FILES. No placeholders. No TODOs. Robot: Three.js primitives, PBR materials, wave/blink animations, scroll-driven sections (Hero=wave, Features=point, About=think, Contact=wave goodbye), particles, dark gradient bg.
86
+ RULES: Start IMMEDIATELY with FILENAME: index.html. Do NOT describe. JUST OUTPUT COMPLETE FILES. No placeholders. No TODOs. Robot: Three.js primitives, PBR materials, wave/blink animations, scroll-driven sections (Hero=wave, Features=point, About=think, Contact=wave goodbye), particles, dark gradient bg. 56000 tokens max.
72
87
 
73
88
  Working directory: ${process.cwd()}`;
74
89
  while (true) {
@@ -78,7 +93,7 @@ Working directory: ${process.cwd()}`;
78
93
  continue;
79
94
  if (trimmed === '/exit')
80
95
  break;
81
- console.log('\n ⏳ Generating...\n');
96
+ console.log('\n ⏳ Streaming...\n');
82
97
  try {
83
98
  const res = await fetch('https://openrouter.ai/api/v1/chat/completions', {
84
99
  method: 'POST',
@@ -103,15 +118,11 @@ Working directory: ${process.cwd()}`;
103
118
  const err = await res.text().catch(() => '');
104
119
  throw new Error(`API ${res.status}: ${err.slice(0, 200)}`);
105
120
  }
106
- // Stream and parse files in real-time
121
+ // Stream and collect full text
107
122
  const reader = res.body.getReader();
108
123
  const decoder = new TextDecoder();
109
124
  let buf = '';
110
125
  let fullText = '';
111
- let fileBuf = '';
112
- let inFile = false;
113
- let fileName = '';
114
- let fileContent = '';
115
126
  let filesCreated = 0;
116
127
  while (true) {
117
128
  const { done, value } = await reader.read();
@@ -128,8 +139,7 @@ Working directory: ${process.cwd()}`;
128
139
  continue;
129
140
  let delta = '';
130
141
  try {
131
- const p = JSON.parse(d);
132
- delta = p.choices?.[0]?.delta?.content || '';
142
+ delta = JSON.parse(d).choices?.[0]?.delta?.content || '';
133
143
  }
134
144
  catch {
135
145
  continue;
@@ -137,78 +147,31 @@ Working directory: ${process.cwd()}`;
137
147
  if (!delta)
138
148
  continue;
139
149
  fullText += delta;
140
- // Real-time file detection
141
- for (const ch of delta) {
142
- if (!inFile) {
143
- fileBuf += ch;
144
- if (fileBuf.endsWith('FILENAME:')) {
145
- inFile = true;
146
- fileName = '';
147
- fileContent = '';
148
- fileBuf = '';
149
- process.stdout.write(' 📄 ');
150
- }
151
- else if (fileBuf.length > 50) {
152
- // Not matching, flush to output
153
- process.stdout.write(fileBuf);
154
- fileBuf = '';
155
- }
156
- }
157
- else {
158
- if (ch === '\n' && !fileName.includes('.')) {
159
- fileName = fileName.trim();
160
- process.stdout.write(fileName + '\n');
161
- }
162
- else if (ch === '\n' && fileName && !fileContent) {
163
- // First newline after filename, start content
164
- fileContent = '';
165
- }
166
- else if (fileContent !== null) {
167
- fileContent += ch;
168
- if (fileContent.endsWith('END FILE')) {
169
- const content = fileContent.slice(0, -8).trim();
170
- try {
171
- const fp = join(process.cwd(), fileName);
172
- const dir = dirname(resolve(fp));
173
- if (!existsSync(dir))
174
- mkdirSync(dir, { recursive: true });
175
- writeFileSync(fp, content, 'utf-8');
176
- createdFiles.add(fileName);
177
- filesCreated++;
178
- console.log(` ✅ Saved: ${fileName} (${content.length} chars)`);
179
- }
180
- catch (e) {
181
- console.log(` ❌ ${fileName}: ${e.message}`);
182
- }
183
- inFile = false;
184
- fileName = '';
185
- fileContent = null;
186
- }
187
- }
188
- else {
189
- fileName += ch;
190
- }
191
- }
192
- }
150
+ process.stdout.write(delta);
193
151
  }
194
152
  }
195
- // Handle any remaining file
196
- if (inFile && fileName && fileContent) {
197
- const content = fileContent.replace(/END FILE$/, '').trim();
198
- if (content) {
199
- try {
200
- const fp = join(process.cwd(), fileName);
201
- const dir = dirname(resolve(fp));
202
- if (!existsSync(dir))
203
- mkdirSync(dir, { recursive: true });
204
- writeFileSync(fp, content, 'utf-8');
205
- createdFiles.add(fileName);
206
- filesCreated++;
207
- console.log(` ✅ Saved: ${fileName} (${content.length} chars)`);
208
- }
209
- catch (e) {
210
- console.log(` ❌ ${fileName}: ${e.message}`);
211
- }
153
+ console.log('\n');
154
+ console.log(` ✅ Stream complete (${fullText.length} chars)`);
155
+ // Parse files from complete output
156
+ const files = extractFiles(fullText);
157
+ if (files.length === 0) {
158
+ console.log(' ⚠ No files detected.\n');
159
+ continue;
160
+ }
161
+ console.log(` 📁 Creating ${files.length} file(s):\n`);
162
+ for (const file of files) {
163
+ try {
164
+ const filePath = join(process.cwd(), file.path);
165
+ const dir = dirname(resolve(filePath));
166
+ if (!existsSync(dir))
167
+ mkdirSync(dir, { recursive: true });
168
+ writeFileSync(filePath, file.content, 'utf-8');
169
+ createdFiles.add(file.path);
170
+ filesCreated++;
171
+ console.log(` ✅ ${file.path} (${file.content.length} chars)`);
172
+ }
173
+ catch (e) {
174
+ console.log(` ❌ ${file.path}: ${e.message}`);
212
175
  }
213
176
  }
214
177
  console.log(`\n 📊 Created ${filesCreated} file(s) | Total: ${createdFiles.size}\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lumina-code-agent",
3
- "version": "1.6.10",
3
+ "version": "1.6.11",
4
4
  "description": "Lumina Code - AI coding agent",
5
5
  "license": "MIT",
6
6
  "type": "module",