lumina-code-agent 1.6.9 → 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 +65 -96
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -24,15 +24,16 @@ function saveConfig(config) {
24
24
  const rl = createInterface({ input: process.stdin, output: process.stdout });
25
25
  function ask(q) { return new Promise(r => rl.question(q, r)); }
26
26
  async function onboarding() {
27
- console.log('\n ⚡ LUMINA CODE — AI Coding Agent\n');
28
- const apiKey = await ask(' Enter your OpenRouter API key: ');
27
+ console.log('\n╔══════════════════════════════════════╗');
28
+ console.log('║ ⚡ LUMINA CODE AI Coding Agent ║');
29
+ console.log('╚══════════════════════════════════════╝\n');
30
+ const apiKey = await ask(' 🔑 OpenRouter API key: ');
29
31
  if (!apiKey.trim() || apiKey.trim().length < 10) {
30
- console.log(' ❌ Invalid key.');
32
+ console.log(' ❌ Invalid.');
31
33
  process.exit(1);
32
34
  }
33
- const name = await ask(' Your name (optional): ');
34
- saveConfig({ openrouterKey: apiKey.trim(), userName: name.trim() || 'User' });
35
- console.log(' ✓ Ready!\n');
35
+ saveConfig({ openrouterKey: apiKey.trim(), userName: 'User' });
36
+ console.log(' ✅ Ready!\n');
36
37
  }
37
38
  function extractFiles(text) {
38
39
  const files = [];
@@ -43,88 +44,57 @@ function extractFiles(text) {
43
44
  const content = match[2].trim();
44
45
  if (!rawPath || rawPath.endsWith('/') || !extname(rawPath))
45
46
  continue;
46
- if (rawPath.includes('<') || rawPath.includes('>') || rawPath.includes('"'))
47
+ if (rawPath.includes('<') || rawPath.includes('"') || rawPath.includes('`'))
47
48
  continue;
48
49
  files.push({ path: rawPath, content });
49
50
  }
50
51
  return files;
51
52
  }
52
53
  async function chat(config) {
53
- console.log(' Type what you want to build. I\'ll handle the rest.');
54
- console.log(' Commands: /help /clear /files /exit\n');
54
+ console.log(' 💬 Type what you want to build. /exit to quit.\n');
55
55
  const createdFiles = new Set();
56
- while (true) {
57
- const input = await ask(' > ');
58
- const trimmed = input.trim();
59
- if (!trimmed)
60
- continue;
61
- if (trimmed === '/exit' || trimmed === '/quit')
62
- break;
63
- if (trimmed === '/clear') {
64
- console.log(' ✓ Cleared.\n');
65
- continue;
66
- }
67
- if (trimmed === '/files') {
68
- if (createdFiles.size === 0) {
69
- console.log(' No files yet.\n');
70
- }
71
- else {
72
- console.log(' Files:');
73
- for (const f of createdFiles)
74
- console.log(` ${f}`);
75
- console.log('');
76
- }
77
- continue;
78
- }
79
- if (trimmed === '/help') {
80
- console.log(' /help /clear /files /exit\n');
81
- continue;
82
- }
83
- const systemPrompt = `You are LUMINA CODE. Create COMPLETE production-grade websites.
84
-
85
- OUTPUT FORMAT — Use this EXACT format for EVERY file:
56
+ const SYSTEM = `You are LUMINA CODE — the world's best AI coding agent.
86
57
 
58
+ OUTPUT FORMAT — MANDATORY:
87
59
  FILENAME: index.html
88
60
  <!DOCTYPE html>
89
61
  <html lang="en">
90
62
  <head>
91
63
  <meta charset="UTF-8">
92
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
64
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
93
65
  <title>Title</title>
94
66
  <link rel="stylesheet" href="style.css">
95
67
  </head>
96
68
  <body>
97
- <!-- Complete HTML here -->
69
+ <!-- COMPLETE HTML -->
98
70
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
71
+ <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
72
+ <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
99
73
  <script src="script.js"></script>
100
74
  </body>
101
75
  </html>
102
76
  END FILE
103
77
 
104
78
  FILENAME: style.css
105
- /* Complete CSS here */
79
+ /* COMPLETE CSS */
106
80
  END FILE
107
81
 
108
82
  FILENAME: script.js
109
- // Complete JavaScript here
83
+ // COMPLETE JS
110
84
  END FILE
111
85
 
112
- RULES:
113
- - Start IMMEDIATELY with FILENAME: index.html
114
- - Output COMPLETE files — every line, no truncation
115
- - Do NOT describe what you will do — JUST DO IT
116
- - Do NOT output any text before FILENAME:
117
- - Do NOT use markdown code blocks
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
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.
121
87
 
122
88
  Working directory: ${process.cwd()}`;
123
- console.log('');
124
- console.log(' Generating...');
89
+ while (true) {
90
+ const input = await ask(' > ');
91
+ const trimmed = input.trim();
92
+ if (!trimmed)
93
+ continue;
94
+ if (trimmed === '/exit')
95
+ break;
96
+ console.log('\n ⏳ Streaming...\n');
125
97
  try {
126
- const controller = new AbortController();
127
- const timeout = setTimeout(() => controller.abort(), 600000); // 10 min timeout
128
98
  const res = await fetch('https://openrouter.ai/api/v1/chat/completions', {
129
99
  method: 'POST',
130
100
  headers: {
@@ -136,58 +106,56 @@ Working directory: ${process.cwd()}`;
136
106
  body: JSON.stringify({
137
107
  model: 'openrouter/owl-alpha',
138
108
  messages: [
139
- { role: 'system', content: systemPrompt },
109
+ { role: 'system', content: SYSTEM },
140
110
  { role: 'user', content: trimmed },
141
111
  ],
142
- stream: false,
143
- max_tokens: 65000,
112
+ stream: true,
113
+ max_tokens: 56000,
144
114
  temperature: 0.1,
145
115
  }),
146
- signal: controller.signal,
147
116
  });
148
- clearTimeout(timeout);
149
117
  if (!res.ok) {
150
118
  const err = await res.text().catch(() => '');
151
- throw new Error(`API error ${res.status}: ${err.slice(0, 200)}`);
152
- }
153
- // Read response as text first, then parse
154
- const rawText = await res.text();
155
- let data;
156
- try {
157
- data = JSON.parse(rawText);
119
+ throw new Error(`API ${res.status}: ${err.slice(0, 200)}`);
158
120
  }
159
- catch (e) {
160
- // If JSON is truncated, try to fix it
161
- console.log(' ⚠ Response was truncated. Attempting to parse...');
162
- // Try to find the last complete JSON object
163
- const lastBrace = rawText.lastIndexOf('}');
164
- if (lastBrace > 0) {
121
+ // Stream and collect full text
122
+ const reader = res.body.getReader();
123
+ const decoder = new TextDecoder();
124
+ let buf = '';
125
+ let fullText = '';
126
+ let filesCreated = 0;
127
+ while (true) {
128
+ const { done, value } = await reader.read();
129
+ if (done)
130
+ break;
131
+ buf += decoder.decode(value, { stream: true });
132
+ const lines = buf.split('\n');
133
+ buf = lines.pop();
134
+ for (const line of lines) {
135
+ if (!line.startsWith('data: '))
136
+ continue;
137
+ const d = line.slice(6).trim();
138
+ if (d === '[DONE]')
139
+ continue;
140
+ let delta = '';
165
141
  try {
166
- data = JSON.parse(rawText.slice(0, lastBrace + 1));
142
+ delta = JSON.parse(d).choices?.[0]?.delta?.content || '';
167
143
  }
168
- catch (e2) {
169
- throw new Error('Response was truncated and could not be parsed. Try a shorter prompt.');
144
+ catch {
145
+ continue;
170
146
  }
147
+ if (!delta)
148
+ continue;
149
+ fullText += delta;
150
+ process.stdout.write(delta);
171
151
  }
172
- else {
173
- throw new Error('Response was truncated. Try a shorter prompt.');
174
- }
175
- }
176
- const content = data.choices?.[0]?.message?.content || '';
177
- if (!content) {
178
- console.log(' ⚠ No response from model.\n');
179
- continue;
180
152
  }
181
- console.log(` ✓ AI responded (${content.length} chars)`);
182
- const files = extractFiles(content);
153
+ console.log('\n');
154
+ console.log(` ✅ Stream complete (${fullText.length} chars)`);
155
+ // Parse files from complete output
156
+ const files = extractFiles(fullText);
183
157
  if (files.length === 0) {
184
- console.log(' ⚠ No files detected in output.\n');
185
- // Show first 50 lines of output
186
- const lines = content.split('\n').slice(0, 50);
187
- console.log(' ── Output preview ──');
188
- for (const line of lines)
189
- console.log(' ' + line);
190
- console.log(' ── End ──\n');
158
+ console.log(' ⚠ No files detected.\n');
191
159
  continue;
192
160
  }
193
161
  console.log(` 📁 Creating ${files.length} file(s):\n`);
@@ -199,16 +167,17 @@ Working directory: ${process.cwd()}`;
199
167
  mkdirSync(dir, { recursive: true });
200
168
  writeFileSync(filePath, file.content, 'utf-8');
201
169
  createdFiles.add(file.path);
170
+ filesCreated++;
202
171
  console.log(` ✅ ${file.path} (${file.content.length} chars)`);
203
172
  }
204
173
  catch (e) {
205
174
  console.log(` ❌ ${file.path}: ${e.message}`);
206
175
  }
207
176
  }
208
- console.log(`\n 📊 Total files: ${createdFiles.size}\n`);
177
+ console.log(`\n 📊 Created ${filesCreated} file(s) | Total: ${createdFiles.size}\n`);
209
178
  }
210
179
  catch (e) {
211
- console.log(` Error: ${e.message}\n`);
180
+ console.log(` ${e.message}\n`);
212
181
  }
213
182
  }
214
183
  rl.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lumina-code-agent",
3
- "version": "1.6.9",
3
+ "version": "1.6.11",
4
4
  "description": "Lumina Code - AI coding agent",
5
5
  "license": "MIT",
6
6
  "type": "module",