lumina-code-agent 1.5.0 → 1.5.1
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 +22 -30
- package/package.json +15 -5
package/dist/index.js
CHANGED
|
@@ -1,26 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @ts-nocheck
|
|
3
|
-
// Check if we have a proper TTY for the TUI
|
|
4
3
|
const hasTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
5
4
|
if (!hasTTY) {
|
|
6
|
-
// Non-TUI mode: just show help
|
|
7
5
|
console.log('');
|
|
8
6
|
console.log(' ⚡ LUMINA CODE — AI Coding Agent');
|
|
9
7
|
console.log('');
|
|
10
8
|
console.log(' Lumina Code requires a proper terminal (TTY) to run.');
|
|
11
|
-
console.log(' Please open
|
|
12
|
-
console.log('');
|
|
13
|
-
console.log(' • Windows Terminal (recommended)');
|
|
14
|
-
console.log(' • PowerShell');
|
|
15
|
-
console.log(' • Command Prompt (cmd.exe)');
|
|
16
|
-
console.log(' • iTerm2 / Terminal.app (macOS)');
|
|
17
|
-
console.log(' • Any Linux terminal');
|
|
18
|
-
console.log('');
|
|
19
|
-
console.log(' If you\'re in Git Bash, try running from Windows Terminal instead.');
|
|
9
|
+
console.log(' Please open Windows Terminal, PowerShell, or Command Prompt.');
|
|
20
10
|
console.log('');
|
|
21
11
|
process.exit(0);
|
|
22
12
|
}
|
|
23
|
-
import React, { useState, useCallback
|
|
13
|
+
import React, { useState, useCallback } from 'react';
|
|
24
14
|
import { Box, Text, useInput, useApp, Spacer } from 'ink';
|
|
25
15
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'fs';
|
|
26
16
|
import { homedir } from 'os';
|
|
@@ -42,8 +32,22 @@ function saveConfig(config) {
|
|
|
42
32
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
43
33
|
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
44
34
|
}
|
|
35
|
+
// ── Main App (handles onboarding vs chat) ───────────────────────────
|
|
36
|
+
function App() {
|
|
37
|
+
const [config, setConfig] = useState(loadConfig());
|
|
38
|
+
const [screen, setScreen] = useState(config?.openrouterKey ? 'chat' : 'onboarding');
|
|
39
|
+
const handleOnboardingComplete = useCallback(() => {
|
|
40
|
+
const newConfig = loadConfig();
|
|
41
|
+
setConfig(newConfig);
|
|
42
|
+
setScreen('chat');
|
|
43
|
+
}, []);
|
|
44
|
+
if (screen === 'onboarding') {
|
|
45
|
+
return React.createElement(OnboardingScreen, { onComplete: handleOnboardingComplete });
|
|
46
|
+
}
|
|
47
|
+
return React.createElement(ChatScreen, { config });
|
|
48
|
+
}
|
|
45
49
|
// ── Onboarding Screen ───────────────────────────────────────────────
|
|
46
|
-
function
|
|
50
|
+
function OnboardingScreen({ onComplete }) {
|
|
47
51
|
const [step, setStep] = useState(0);
|
|
48
52
|
const [apiKey, setApiKey] = useState('');
|
|
49
53
|
const [name, setName] = useState('');
|
|
@@ -82,7 +86,6 @@ function ChatScreen({ config }) {
|
|
|
82
86
|
const [input, setInput] = useState('');
|
|
83
87
|
const [status, setStatus] = useState('Ready');
|
|
84
88
|
const [thinking, setThinking] = useState(false);
|
|
85
|
-
const scrollRef = useRef(0);
|
|
86
89
|
const visibleMessages = messages.slice(-50);
|
|
87
90
|
const handleSubmit = useCallback(async (text) => {
|
|
88
91
|
const trimmed = text.trim();
|
|
@@ -91,7 +94,6 @@ function ChatScreen({ config }) {
|
|
|
91
94
|
setInput('');
|
|
92
95
|
setThinking(true);
|
|
93
96
|
setStatus('Thinking...');
|
|
94
|
-
scrollRef.current++;
|
|
95
97
|
const userMsg = { role: 'user', content: trimmed };
|
|
96
98
|
const newMessages = [...messages, userMsg];
|
|
97
99
|
setMessages(newMessages);
|
|
@@ -99,11 +101,11 @@ function ChatScreen({ config }) {
|
|
|
99
101
|
const OPENROUTER_URL = 'https://openrouter.ai/api/v1/chat/completions';
|
|
100
102
|
const tools = [
|
|
101
103
|
{ 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'] } } },
|
|
102
|
-
{ type: 'function', function: { name: 'read_file', description: 'Read file contents
|
|
103
|
-
{ type: 'function', function: { name: 'write_file', description: 'Create or overwrite a file
|
|
104
|
-
{ type: 'function', function: { name: 'edit_file', description: 'Make precise edits to a file
|
|
104
|
+
{ type: 'function', function: { name: 'read_file', description: 'Read file contents', parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] } } },
|
|
105
|
+
{ 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'] } } },
|
|
106
|
+
{ 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'] } } },
|
|
105
107
|
{ type: 'function', function: { name: 'list_dir', description: 'List directory contents', parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] } } },
|
|
106
|
-
{ type: 'function', function: { name: 'search_files', description: 'Find files by
|
|
108
|
+
{ type: 'function', function: { name: 'search_files', description: 'Find files by pattern', parameters: { type: 'object', properties: { pattern: { type: 'string' }, cwd: { type: 'string' } }, required: ['pattern'] } } },
|
|
107
109
|
{ type: 'function', function: { name: 'grep', description: 'Search file contents', parameters: { type: 'object', properties: { pattern: { type: 'string' }, path: { type: 'string' } }, required: ['pattern', 'path'] } } },
|
|
108
110
|
{ type: 'function', function: { name: 'git', description: 'Run git commands', parameters: { type: 'object', properties: { args: { type: 'string' }, cwd: { type: 'string' } }, required: ['args'] } } },
|
|
109
111
|
{ type: 'function', function: { name: 'npm', description: 'Run npm/yarn/pnpm/bun commands', parameters: { type: 'object', properties: { args: { type: 'string' }, cwd: { type: 'string' } }, required: ['args'] } } },
|
|
@@ -172,7 +174,6 @@ Working directory: ${process.cwd()}` }, ...currentMessages],
|
|
|
172
174
|
const toolCalls = choice.message?.tool_calls || [];
|
|
173
175
|
currentMessages.push({ role: 'assistant', content });
|
|
174
176
|
setMessages([...currentMessages]);
|
|
175
|
-
scrollRef.current++;
|
|
176
177
|
if (toolCalls.length === 0) {
|
|
177
178
|
setStatus('Done');
|
|
178
179
|
break;
|
|
@@ -181,7 +182,6 @@ Working directory: ${process.cwd()}` }, ...currentMessages],
|
|
|
181
182
|
const args = JSON.parse(tc.function.arguments || '{}');
|
|
182
183
|
const toolName = tc.function.name;
|
|
183
184
|
setStatus(`Running: ${toolName}...`);
|
|
184
|
-
scrollRef.current++;
|
|
185
185
|
let output = '';
|
|
186
186
|
try {
|
|
187
187
|
const { execSync } = await import('child_process');
|
|
@@ -268,7 +268,6 @@ Working directory: ${process.cwd()}` }, ...currentMessages],
|
|
|
268
268
|
}
|
|
269
269
|
currentMessages.push({ role: 'tool', content: output.slice(0, 2000), tool_call_id: tc.id });
|
|
270
270
|
setMessages([...currentMessages]);
|
|
271
|
-
scrollRef.current++;
|
|
272
271
|
}
|
|
273
272
|
}
|
|
274
273
|
if (iterations >= maxIterations)
|
|
@@ -305,11 +304,4 @@ Working directory: ${process.cwd()}` }, ...currentMessages],
|
|
|
305
304
|
return React.createElement(Box, { key: i, marginTop: 1, paddingLeft: 2 }, React.createElement(Text, { color: '#A1A1AA' }, m.content.slice(0, 500)));
|
|
306
305
|
}), thinking && React.createElement(Text, { color: '#F59E0B' }, ' ⏳ thinking...')), 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' }, '▌')), React.createElement(Box, { paddingX: 2 }, React.createElement(Text, { color: '#3F3F46' }, ' Ctrl+C to exit | OWL-Alpha ')));
|
|
307
306
|
}
|
|
308
|
-
|
|
309
|
-
export default function App() {
|
|
310
|
-
const config = loadConfig();
|
|
311
|
-
if (!config?.openrouterKey) {
|
|
312
|
-
return React.createElement(Onboarding, { onComplete: () => { } });
|
|
313
|
-
}
|
|
314
|
-
return React.createElement(ChatScreen, { config });
|
|
315
|
-
}
|
|
307
|
+
export default App;
|
package/package.json
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lumina-code-agent",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
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
|
"ink": "^5.1.0",
|
|
14
24
|
"react": "^18.3.1",
|