@alia-codea/cli 1.0.0
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/README.md +131 -0
- package/dist/api-X2G5QROW.js +10 -0
- package/dist/chunk-SVPL4GNV.js +230 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +878 -0
- package/package.json +52 -0
- package/src/commands/auth.ts +66 -0
- package/src/commands/repl.ts +309 -0
- package/src/commands/run.ts +177 -0
- package/src/commands/sessions.ts +122 -0
- package/src/index.ts +87 -0
- package/src/tools/executor.ts +191 -0
- package/src/utils/api.ts +213 -0
- package/src/utils/config.ts +70 -0
- package/src/utils/context.ts +127 -0
- package/src/utils/ui.ts +153 -0
- package/tsconfig.json +21 -0
package/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Codea CLI
|
|
2
|
+
|
|
3
|
+
AI coding assistant for your terminal by Alia.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
██████╗ ██████╗ ██████╗ ███████╗ █████╗
|
|
7
|
+
██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗
|
|
8
|
+
██║ ██║ ██║██║ ██║█████╗ ███████║
|
|
9
|
+
██║ ██║ ██║██║ ██║██╔══╝ ██╔══██║
|
|
10
|
+
╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║
|
|
11
|
+
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g @alia-codea/cli
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
1. Login with your Alia API key:
|
|
23
|
+
```bash
|
|
24
|
+
codea login
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
2. Start coding:
|
|
28
|
+
```bash
|
|
29
|
+
codea
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- **Interactive Chat**: Natural language conversations with your AI coding assistant
|
|
35
|
+
- **File Operations**: Read, write, and edit files directly
|
|
36
|
+
- **Command Execution**: Run shell commands, build, test, and more
|
|
37
|
+
- **Codebase Context**: Automatically understands your project structure
|
|
38
|
+
- **Session Management**: Save and resume conversations
|
|
39
|
+
- **Multiple Models**: Switch between Codea, Codea Pro, and Codea Thinking
|
|
40
|
+
|
|
41
|
+
## Commands
|
|
42
|
+
|
|
43
|
+
### Start Interactive Session
|
|
44
|
+
```bash
|
|
45
|
+
codea # Start a new chat session
|
|
46
|
+
codea chat # Same as above
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Run Single Prompt
|
|
50
|
+
```bash
|
|
51
|
+
codea run "fix the bug in auth.ts"
|
|
52
|
+
codea r "add unit tests for the User class" -y # Auto-approve changes
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Session Management
|
|
56
|
+
```bash
|
|
57
|
+
codea sessions # List recent sessions
|
|
58
|
+
codea resume # Resume a previous session
|
|
59
|
+
codea resume 1 # Resume session #1
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Configuration
|
|
63
|
+
```bash
|
|
64
|
+
codea login # Configure API key
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Slash Commands (in chat)
|
|
68
|
+
|
|
69
|
+
| Command | Description |
|
|
70
|
+
|------------|----------------------------|
|
|
71
|
+
| `/help` | Show available commands |
|
|
72
|
+
| `/clear` | Clear conversation |
|
|
73
|
+
| `/model` | Switch model |
|
|
74
|
+
| `/context` | Show current context |
|
|
75
|
+
| `/save` | Save conversation |
|
|
76
|
+
| `/exit` | Exit Codea |
|
|
77
|
+
|
|
78
|
+
## Models
|
|
79
|
+
|
|
80
|
+
| Model | Description |
|
|
81
|
+
|-----------------|-----------------------------------|
|
|
82
|
+
| `codea` | Fast coding assistant (default) |
|
|
83
|
+
| `codea-pro` | Advanced reasoning |
|
|
84
|
+
| `codea-thinking`| Extended thinking for complex tasks|
|
|
85
|
+
|
|
86
|
+
Switch models with:
|
|
87
|
+
```bash
|
|
88
|
+
codea --model codea-pro
|
|
89
|
+
# or in chat:
|
|
90
|
+
/model codea-pro
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Tools
|
|
94
|
+
|
|
95
|
+
Codea can:
|
|
96
|
+
- **read_file**: Read file contents
|
|
97
|
+
- **write_file**: Create or overwrite files
|
|
98
|
+
- **edit_file**: Make targeted edits
|
|
99
|
+
- **list_files**: Explore directories
|
|
100
|
+
- **search_files**: Search code patterns
|
|
101
|
+
- **run_command**: Execute shell commands
|
|
102
|
+
|
|
103
|
+
## Examples
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Start coding
|
|
107
|
+
codea
|
|
108
|
+
|
|
109
|
+
# In chat:
|
|
110
|
+
❯ explain this codebase
|
|
111
|
+
❯ fix the TypeScript errors
|
|
112
|
+
❯ add authentication to the API
|
|
113
|
+
❯ write tests for the User model
|
|
114
|
+
❯ run npm test and fix any failures
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Configuration
|
|
118
|
+
|
|
119
|
+
Config is stored in `~/.config/alia-codea-cli/config.json`:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"apiKey": "your-api-key",
|
|
124
|
+
"apiBaseUrl": "https://api.alia.onl",
|
|
125
|
+
"defaultModel": "alia-v1-codea"
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT - Created by [Alia](https://alia.onl)
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// src/utils/api.ts
|
|
2
|
+
import OpenAI from "openai";
|
|
3
|
+
|
|
4
|
+
// src/utils/config.ts
|
|
5
|
+
import Conf from "conf";
|
|
6
|
+
var config = new Conf({
|
|
7
|
+
projectName: "alia-codea-cli",
|
|
8
|
+
defaults: {
|
|
9
|
+
apiKey: "",
|
|
10
|
+
apiBaseUrl: "https://api.alia.onl",
|
|
11
|
+
defaultModel: "alia-v1-codea",
|
|
12
|
+
sessions: [],
|
|
13
|
+
currentSessionId: null
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
function saveSession(session) {
|
|
17
|
+
const sessions = config.get("sessions") || [];
|
|
18
|
+
const existingIndex = sessions.findIndex((s) => s.id === session.id);
|
|
19
|
+
if (existingIndex >= 0) {
|
|
20
|
+
sessions[existingIndex] = session;
|
|
21
|
+
} else {
|
|
22
|
+
sessions.unshift(session);
|
|
23
|
+
}
|
|
24
|
+
if (sessions.length > 50) {
|
|
25
|
+
sessions.splice(50);
|
|
26
|
+
}
|
|
27
|
+
config.set("sessions", sessions);
|
|
28
|
+
}
|
|
29
|
+
function getSession(id) {
|
|
30
|
+
const sessions = config.get("sessions") || [];
|
|
31
|
+
return sessions.find((s) => s.id === id);
|
|
32
|
+
}
|
|
33
|
+
function getSessions() {
|
|
34
|
+
return config.get("sessions") || [];
|
|
35
|
+
}
|
|
36
|
+
function createSession() {
|
|
37
|
+
const session = {
|
|
38
|
+
id: Date.now().toString(),
|
|
39
|
+
title: "New conversation",
|
|
40
|
+
messages: [],
|
|
41
|
+
createdAt: Date.now(),
|
|
42
|
+
updatedAt: Date.now(),
|
|
43
|
+
cwd: process.cwd()
|
|
44
|
+
};
|
|
45
|
+
saveSession(session);
|
|
46
|
+
config.set("currentSessionId", session.id);
|
|
47
|
+
return session;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/utils/api.ts
|
|
51
|
+
var fileTools = [
|
|
52
|
+
{
|
|
53
|
+
type: "function",
|
|
54
|
+
function: {
|
|
55
|
+
name: "read_file",
|
|
56
|
+
description: "Read the contents of a file",
|
|
57
|
+
parameters: {
|
|
58
|
+
type: "object",
|
|
59
|
+
properties: {
|
|
60
|
+
path: { type: "string", description: "The file path to read" }
|
|
61
|
+
},
|
|
62
|
+
required: ["path"]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: "function",
|
|
68
|
+
function: {
|
|
69
|
+
name: "write_file",
|
|
70
|
+
description: "Write content to a file (creates or overwrites)",
|
|
71
|
+
parameters: {
|
|
72
|
+
type: "object",
|
|
73
|
+
properties: {
|
|
74
|
+
path: { type: "string", description: "The file path to write to" },
|
|
75
|
+
content: { type: "string", description: "The content to write" }
|
|
76
|
+
},
|
|
77
|
+
required: ["path", "content"]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
type: "function",
|
|
83
|
+
function: {
|
|
84
|
+
name: "edit_file",
|
|
85
|
+
description: "Make targeted edits to a file by replacing specific text",
|
|
86
|
+
parameters: {
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
path: { type: "string", description: "The file path to edit" },
|
|
90
|
+
old_text: { type: "string", description: "The text to find and replace" },
|
|
91
|
+
new_text: { type: "string", description: "The replacement text" }
|
|
92
|
+
},
|
|
93
|
+
required: ["path", "old_text", "new_text"]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: "function",
|
|
99
|
+
function: {
|
|
100
|
+
name: "list_files",
|
|
101
|
+
description: "List files in a directory",
|
|
102
|
+
parameters: {
|
|
103
|
+
type: "object",
|
|
104
|
+
properties: {
|
|
105
|
+
path: { type: "string", description: "The directory path (default: current directory)" },
|
|
106
|
+
recursive: { type: "boolean", description: "Whether to list recursively" }
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
type: "function",
|
|
113
|
+
function: {
|
|
114
|
+
name: "search_files",
|
|
115
|
+
description: "Search for text patterns across files",
|
|
116
|
+
parameters: {
|
|
117
|
+
type: "object",
|
|
118
|
+
properties: {
|
|
119
|
+
pattern: { type: "string", description: "The search pattern (regex supported)" },
|
|
120
|
+
path: { type: "string", description: "Directory to search in (default: current)" },
|
|
121
|
+
file_pattern: { type: "string", description: 'File glob pattern (e.g., "*.ts")' }
|
|
122
|
+
},
|
|
123
|
+
required: ["pattern"]
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
type: "function",
|
|
129
|
+
function: {
|
|
130
|
+
name: "run_command",
|
|
131
|
+
description: "Execute a shell command",
|
|
132
|
+
parameters: {
|
|
133
|
+
type: "object",
|
|
134
|
+
properties: {
|
|
135
|
+
command: { type: "string", description: "The command to execute" },
|
|
136
|
+
cwd: { type: "string", description: "Working directory (default: current)" }
|
|
137
|
+
},
|
|
138
|
+
required: ["command"]
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
];
|
|
143
|
+
async function streamChat(messages, systemMessage, model, callbacks) {
|
|
144
|
+
const apiKey = config.get("apiKey");
|
|
145
|
+
const baseUrl = config.get("apiBaseUrl") || "https://api.alia.onl";
|
|
146
|
+
const openai = new OpenAI({
|
|
147
|
+
apiKey,
|
|
148
|
+
baseURL: `${baseUrl}/v1`
|
|
149
|
+
});
|
|
150
|
+
const allMessages = [
|
|
151
|
+
{ role: "system", content: systemMessage },
|
|
152
|
+
...messages.map((m) => {
|
|
153
|
+
if (m.role === "tool") {
|
|
154
|
+
return { role: "tool", tool_call_id: m.tool_call_id, content: m.content };
|
|
155
|
+
} else if (m.tool_calls) {
|
|
156
|
+
return { role: "assistant", content: m.content || "", tool_calls: m.tool_calls };
|
|
157
|
+
}
|
|
158
|
+
return { role: m.role, content: m.content };
|
|
159
|
+
})
|
|
160
|
+
];
|
|
161
|
+
try {
|
|
162
|
+
const stream = await openai.chat.completions.create({
|
|
163
|
+
model,
|
|
164
|
+
messages: allMessages,
|
|
165
|
+
tools: fileTools,
|
|
166
|
+
stream: true
|
|
167
|
+
});
|
|
168
|
+
let fullContent = "";
|
|
169
|
+
const toolCalls = [];
|
|
170
|
+
const toolCallsMap = /* @__PURE__ */ new Map();
|
|
171
|
+
for await (const chunk of stream) {
|
|
172
|
+
const delta = chunk.choices?.[0]?.delta;
|
|
173
|
+
if (!delta) continue;
|
|
174
|
+
if (delta.content) {
|
|
175
|
+
fullContent += delta.content;
|
|
176
|
+
callbacks.onContent(delta.content);
|
|
177
|
+
}
|
|
178
|
+
if (delta.tool_calls) {
|
|
179
|
+
for (const tc of delta.tool_calls) {
|
|
180
|
+
const index = tc.index ?? 0;
|
|
181
|
+
if (!toolCallsMap.has(index)) {
|
|
182
|
+
const newToolCall = {
|
|
183
|
+
id: tc.id || "",
|
|
184
|
+
type: "function",
|
|
185
|
+
function: {
|
|
186
|
+
name: tc.function?.name || "",
|
|
187
|
+
arguments: tc.function?.arguments || ""
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
toolCallsMap.set(index, newToolCall);
|
|
191
|
+
toolCalls.push(newToolCall);
|
|
192
|
+
} else {
|
|
193
|
+
const existingToolCall = toolCallsMap.get(index);
|
|
194
|
+
if (tc.function?.name) {
|
|
195
|
+
existingToolCall.function.name = tc.function.name;
|
|
196
|
+
}
|
|
197
|
+
if (tc.function?.arguments) {
|
|
198
|
+
existingToolCall.function.arguments += tc.function.arguments;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
callbacks.onDone(fullContent, toolCalls.length > 0 ? toolCalls : void 0);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
callbacks.onError(error);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function fetchModels() {
|
|
210
|
+
const baseUrl = config.get("apiBaseUrl") || "https://api.alia.onl";
|
|
211
|
+
try {
|
|
212
|
+
const response = await fetch(`${baseUrl}/v1/models?category=coding`);
|
|
213
|
+
if (!response.ok) return [];
|
|
214
|
+
const data = await response.json();
|
|
215
|
+
return data.data || [];
|
|
216
|
+
} catch {
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export {
|
|
222
|
+
config,
|
|
223
|
+
saveSession,
|
|
224
|
+
getSession,
|
|
225
|
+
getSessions,
|
|
226
|
+
createSession,
|
|
227
|
+
fileTools,
|
|
228
|
+
streamChat,
|
|
229
|
+
fetchModels
|
|
230
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|