miii-cli 0.1.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/.claude/settings.local.json +18 -0
- package/Makefile +13 -0
- package/README.md +182 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +24 -0
- package/dist/config.js.map +1 -0
- package/dist/files/ops.d.ts +11 -0
- package/dist/files/ops.js +66 -0
- package/dist/files/ops.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +1 -0
- package/dist/init.js +32 -0
- package/dist/init.js.map +1 -0
- package/dist/llm/ollama.d.ts +9 -0
- package/dist/llm/ollama.js +51 -0
- package/dist/llm/ollama.js.map +1 -0
- package/dist/llm/stream.d.ts +12 -0
- package/dist/llm/stream.js +129 -0
- package/dist/llm/stream.js.map +1 -0
- package/dist/parser/stream-parser.d.ts +17 -0
- package/dist/parser/stream-parser.js +54 -0
- package/dist/parser/stream-parser.js.map +1 -0
- package/dist/sessions.d.ts +9 -0
- package/dist/sessions.js +48 -0
- package/dist/sessions.js.map +1 -0
- package/dist/skills/loader.d.ts +23 -0
- package/dist/skills/loader.js +91 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +79 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tui/App.d.ts +9 -0
- package/dist/tui/App.js +259 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/InputBar.d.ts +10 -0
- package/dist/tui/InputBar.js +289 -0
- package/dist/tui/InputBar.js.map +1 -0
- package/dist/tui/components/AtPicker.d.ts +8 -0
- package/dist/tui/components/AtPicker.js +19 -0
- package/dist/tui/components/AtPicker.js.map +1 -0
- package/dist/tui/components/CommandPalette.d.ts +8 -0
- package/dist/tui/components/CommandPalette.js +25 -0
- package/dist/tui/components/CommandPalette.js.map +1 -0
- package/dist/tui/components/InputArea.d.ts +11 -0
- package/dist/tui/components/InputArea.js +268 -0
- package/dist/tui/components/InputArea.js.map +1 -0
- package/dist/tui/components/MessageList.d.ts +10 -0
- package/dist/tui/components/MessageList.js +98 -0
- package/dist/tui/components/MessageList.js.map +1 -0
- package/dist/tui/components/ModelPicker.d.ts +18 -0
- package/dist/tui/components/ModelPicker.js +74 -0
- package/dist/tui/components/ModelPicker.js.map +1 -0
- package/dist/tui/components/StatusBar.d.ts +12 -0
- package/dist/tui/components/StatusBar.js +15 -0
- package/dist/tui/components/StatusBar.js.map +1 -0
- package/dist/tui/printer.d.ts +7 -0
- package/dist/tui/printer.js +106 -0
- package/dist/tui/printer.js.map +1 -0
- package/dist/types.d.ts +19 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/workers/context.worker.d.ts +1 -0
- package/dist/workers/context.worker.js +69 -0
- package/dist/workers/context.worker.js.map +1 -0
- package/dist/workers/diff.worker.d.ts +1 -0
- package/dist/workers/diff.worker.js +12 -0
- package/dist/workers/diff.worker.js.map +1 -0
- package/dist/workers/spawn.d.ts +1 -0
- package/dist/workers/spawn.js +18 -0
- package/dist/workers/spawn.js.map +1 -0
- package/install.sh +6 -0
- package/package.json +29 -0
- package/src/config.ts +25 -0
- package/src/files/ops.ts +71 -0
- package/src/index.ts +11 -0
- package/src/init.ts +39 -0
- package/src/llm/ollama.ts +58 -0
- package/src/llm/stream.ts +118 -0
- package/src/parser/stream-parser.ts +54 -0
- package/src/sessions.ts +46 -0
- package/src/skills/loader.ts +109 -0
- package/src/tools/index.ts +83 -0
- package/src/tui/App.tsx +308 -0
- package/src/tui/InputBar.tsx +347 -0
- package/src/tui/components/AtPicker.tsx +49 -0
- package/src/tui/components/CommandPalette.tsx +50 -0
- package/src/tui/components/InputArea.tsx +285 -0
- package/src/tui/components/MessageList.tsx +192 -0
- package/src/tui/components/ModelPicker.tsx +134 -0
- package/src/tui/components/StatusBar.tsx +36 -0
- package/src/tui/printer.ts +121 -0
- package/src/types.ts +25 -0
- package/src/workers/context.worker.ts +62 -0
- package/src/workers/diff.worker.ts +20 -0
- package/src/workers/spawn.ts +19 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(git -C /Users/akshay/Desktop/essentials/akshay-workspace/miii-cli status)",
|
|
5
|
+
"Bash(npm install *)",
|
|
6
|
+
"Bash(npx tsc *)",
|
|
7
|
+
"Bash(node --input-type=module)",
|
|
8
|
+
"Bash(chmod +x dist/index.js)",
|
|
9
|
+
"Bash(node dist/index.js --help)",
|
|
10
|
+
"Bash(node dist/index.js)",
|
|
11
|
+
"Bash(chmod +x install.sh)",
|
|
12
|
+
"Bash(npm whoami *)",
|
|
13
|
+
"Bash(npm run *)",
|
|
14
|
+
"Bash(npm publish *)",
|
|
15
|
+
"Bash(npm pkg *)"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
package/Makefile
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# miii
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
╭─ MIII - CLI ───────────────────────────────────────────╮
|
|
5
|
+
│ Claude Code-level terminal workflows, local models. │
|
|
6
|
+
╰────────────────────────────────────────────────────────╯
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
A fast, local AI coding assistant that runs entirely on your machine.
|
|
10
|
+
No cloud. No API keys. Just you, your terminal, and whatever model you pull.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g miii-cli
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or run from source:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git clone https://github.com/maruakshay/miii-cli
|
|
24
|
+
cd miii-cli
|
|
25
|
+
npm install
|
|
26
|
+
npm run build
|
|
27
|
+
npm link
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
miii # start with default session
|
|
36
|
+
miii --model codellama # use a specific model
|
|
37
|
+
miii --session myproject # start in a named session
|
|
38
|
+
miii -s work -m llama3.2 # short flags
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
On startup, miii opens the model picker — pick a model and start coding.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Commands
|
|
46
|
+
|
|
47
|
+
Type `/` to open the command palette and browse everything.
|
|
48
|
+
|
|
49
|
+
| Command | What it does |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `/models` | Open model picker — switch or pull Ollama models |
|
|
52
|
+
| `/clear` | Clear current session's chat history |
|
|
53
|
+
| `/sessions` | List all saved sessions |
|
|
54
|
+
| `/session <name>` | Switch to (or create) a named session |
|
|
55
|
+
| `/list` | List all loaded skills |
|
|
56
|
+
| `/exit` | Exit miii |
|
|
57
|
+
|
|
58
|
+
Skills loaded from `~/.config/miii/skills/` appear in the palette too.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## File context with `@`
|
|
63
|
+
|
|
64
|
+
Type `@` anywhere in your message to fuzzy-find project files and inject their content into the LLM context.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
❯ review the auth logic in @src/auth/middleware.ts
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The file content is injected automatically — the model sees the full source.
|
|
71
|
+
|
|
72
|
+
Filtered automatically: `node_modules`, `dist`, `.git`, lock files, binaries, images.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Sessions
|
|
77
|
+
|
|
78
|
+
Every conversation is saved. Sessions persist between launches.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
miii # continues "default" session
|
|
82
|
+
miii --session feature-auth # continues or creates "feature-auth"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Mid-conversation:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
/session feature-auth switch sessions
|
|
89
|
+
/sessions see all sessions with message counts
|
|
90
|
+
/clear wipe current session history
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Sessions stored at `~/.config/miii/sessions/`.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Tools
|
|
98
|
+
|
|
99
|
+
miii has built-in file and shell tools the model can use automatically:
|
|
100
|
+
|
|
101
|
+
| Tool | What it does |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `read_file` | Read any file |
|
|
104
|
+
| `list_files` | List directory contents |
|
|
105
|
+
| `edit_file` | Create or overwrite a file |
|
|
106
|
+
| `delete_file` | Delete a file |
|
|
107
|
+
| `run_command` | Run a shell command in cwd |
|
|
108
|
+
|
|
109
|
+
The model calls these via `<tool_call>` tags, miii executes them and feeds results back automatically — up to 6 hops deep.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Skills
|
|
114
|
+
|
|
115
|
+
Skills are custom commands you can invoke with `/`.
|
|
116
|
+
|
|
117
|
+
Create `~/.config/miii/skills/review.md`:
|
|
118
|
+
|
|
119
|
+
```markdown
|
|
120
|
+
---
|
|
121
|
+
name: review
|
|
122
|
+
description: review current changes for bugs and improvements
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
Review the code I'm about to share. Look for bugs, edge cases, and improvements.
|
|
126
|
+
Be direct and specific. No markdown.
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Then use it:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
/review
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Skills can also be TypeScript files with an `execute` function for programmatic behavior.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Configuration
|
|
140
|
+
|
|
141
|
+
miii looks for config in:
|
|
142
|
+
1. `.miii.json` in the current directory
|
|
143
|
+
2. `~/.config/miii/config.json`
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"model": "llama3.2",
|
|
148
|
+
"provider": "ollama",
|
|
149
|
+
"baseUrl": "http://localhost:11434"
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
For OpenAI-compatible APIs:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"model": "gpt-4o",
|
|
158
|
+
"provider": "openai",
|
|
159
|
+
"baseUrl": "https://api.openai.com/v1"
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Works with any OpenAI-compatible server: LM Studio, vLLM, Groq, Together, etc.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Requirements
|
|
168
|
+
|
|
169
|
+
- Node.js 18+
|
|
170
|
+
- [Ollama](https://ollama.com) (or any OpenAI-compatible API)
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Keybindings
|
|
175
|
+
|
|
176
|
+
| Key | Action |
|
|
177
|
+
|---|---|
|
|
178
|
+
| `enter` | Send message |
|
|
179
|
+
| `ctrl+c` | Abort streaming |
|
|
180
|
+
| `ctrl+c` x2 | Exit |
|
|
181
|
+
| `esc` | Close overlay / abort |
|
|
182
|
+
| `↑ ↓` | Navigate command palette or file picker |
|
package/dist/config.d.ts
ADDED
package/dist/config.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'fs';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
const defaults = {
|
|
5
|
+
model: 'llama3.2',
|
|
6
|
+
provider: 'ollama',
|
|
7
|
+
baseUrl: 'http://localhost:11434',
|
|
8
|
+
};
|
|
9
|
+
export function loadConfig() {
|
|
10
|
+
const candidates = [
|
|
11
|
+
join(process.cwd(), '.miii.json'),
|
|
12
|
+
join(homedir(), '.config', 'miii', 'config.json'),
|
|
13
|
+
];
|
|
14
|
+
for (const p of candidates) {
|
|
15
|
+
if (existsSync(p)) {
|
|
16
|
+
try {
|
|
17
|
+
return { ...defaults, ...JSON.parse(readFileSync(p, 'utf-8')) };
|
|
18
|
+
}
|
|
19
|
+
catch { }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return { ...defaults };
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAA;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAG3B,MAAM,QAAQ,GAAW;IACvB,KAAK,EAAE,UAAU;IACjB,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,wBAAwB;CAClC,CAAA;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC;QACjC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC;KAClD,CAAA;IACD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,IAAI,CAAC;gBACH,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAA;YACjE,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAA;AACxB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function readFile(p: string): string;
|
|
2
|
+
export declare function writeFile(p: string, content: string): void;
|
|
3
|
+
export declare function deleteFile(p: string): void;
|
|
4
|
+
export interface FileEntry {
|
|
5
|
+
name: string;
|
|
6
|
+
path: string;
|
|
7
|
+
rel: string;
|
|
8
|
+
type: 'file' | 'dir';
|
|
9
|
+
size?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function listFiles(dir: string, recursive?: boolean, cwd?: string): FileEntry[];
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, unlinkSync, mkdirSync, readdirSync, statSync, existsSync, } from 'fs';
|
|
2
|
+
import { join, dirname, relative, extname } from 'path';
|
|
3
|
+
const SKIP_DIRS = new Set([
|
|
4
|
+
'node_modules', 'dist', 'build', '.git', '.next', '.nuxt', '.svelte-kit',
|
|
5
|
+
'out', '__pycache__', '.cache', 'coverage', '.nyc_output', 'vendor',
|
|
6
|
+
'target', '.turbo', '.vercel', 'generated', '.gradle', '.expo',
|
|
7
|
+
'bin', 'obj', '.idea', '.vscode', 'tmp', 'temp', 'logs',
|
|
8
|
+
]);
|
|
9
|
+
const SKIP_EXTS = new Set([
|
|
10
|
+
'.map', '.lock',
|
|
11
|
+
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.bmp', '.tiff',
|
|
12
|
+
'.mp4', '.mp3', '.wav', '.ogg', '.pdf',
|
|
13
|
+
'.zip', '.tar', '.gz', '.rar', '.7z',
|
|
14
|
+
'.exe', '.dll', '.so', '.dylib', '.wasm', '.class', '.pyc',
|
|
15
|
+
'.ttf', '.woff', '.woff2', '.eot',
|
|
16
|
+
]);
|
|
17
|
+
const SKIP_NAMES = new Set([
|
|
18
|
+
'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'Cargo.lock',
|
|
19
|
+
'poetry.lock', 'Gemfile.lock', 'composer.lock',
|
|
20
|
+
'.DS_Store', 'Thumbs.db', '.env.local', 'LICENSE', 'LICENSE.md',
|
|
21
|
+
]);
|
|
22
|
+
export function readFile(p) {
|
|
23
|
+
if (!existsSync(p))
|
|
24
|
+
return '';
|
|
25
|
+
return readFileSync(p, 'utf-8');
|
|
26
|
+
}
|
|
27
|
+
export function writeFile(p, content) {
|
|
28
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
29
|
+
writeFileSync(p, content, 'utf-8');
|
|
30
|
+
}
|
|
31
|
+
export function deleteFile(p) {
|
|
32
|
+
unlinkSync(p);
|
|
33
|
+
}
|
|
34
|
+
export function listFiles(dir, recursive = false, cwd = process.cwd()) {
|
|
35
|
+
if (!existsSync(dir))
|
|
36
|
+
return [];
|
|
37
|
+
const entries = [];
|
|
38
|
+
for (const name of readdirSync(dir)) {
|
|
39
|
+
if (name.startsWith('.'))
|
|
40
|
+
continue;
|
|
41
|
+
if (SKIP_NAMES.has(name))
|
|
42
|
+
continue;
|
|
43
|
+
if (SKIP_DIRS.has(name))
|
|
44
|
+
continue;
|
|
45
|
+
const ext = extname(name);
|
|
46
|
+
if (SKIP_EXTS.has(ext))
|
|
47
|
+
continue;
|
|
48
|
+
if (name.endsWith('.d.ts') || name.endsWith('.js.map'))
|
|
49
|
+
continue;
|
|
50
|
+
let stat;
|
|
51
|
+
try {
|
|
52
|
+
stat = statSync(join(dir, name));
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const full = join(dir, name);
|
|
58
|
+
const type = stat.isDirectory() ? 'dir' : 'file';
|
|
59
|
+
entries.push({ name, path: full, rel: relative(cwd, full), type, size: stat.isFile() ? stat.size : undefined });
|
|
60
|
+
if (recursive && type === 'dir') {
|
|
61
|
+
entries.push(...listFiles(full, true, cwd));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return entries;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../../src/files/ops.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
// Minimal entry — heavy imports lazy-loaded
|
|
4
|
+
async function main() {
|
|
5
|
+
const { lazyInit } = await import('./init.js');
|
|
6
|
+
await lazyInit();
|
|
7
|
+
}
|
|
8
|
+
main().catch(err => {
|
|
9
|
+
process.stderr.write(`fatal: ${err.message}\n`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AACA,4CAA4C;AAC5C,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;IAC9C,MAAM,QAAQ,EAAE,CAAA;AAClB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,IAAI,CAAC,CAAA;IAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
package/dist/init.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function lazyInit(): Promise<void>;
|
package/dist/init.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { render } from 'ink';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import minimist from 'minimist';
|
|
4
|
+
import { loadConfig } from './config.js';
|
|
5
|
+
import { SkillLoader } from './skills/loader.js';
|
|
6
|
+
import { InputBar } from './tui/InputBar.js';
|
|
7
|
+
import { welcome } from './tui/printer.js';
|
|
8
|
+
export async function lazyInit() {
|
|
9
|
+
const argv = minimist(process.argv.slice(2), {
|
|
10
|
+
string: ['model', 'url', 'provider', 'session'],
|
|
11
|
+
alias: { m: 'model', u: 'url', p: 'provider', s: 'session' },
|
|
12
|
+
});
|
|
13
|
+
const config = loadConfig();
|
|
14
|
+
if (argv.model)
|
|
15
|
+
config.model = argv.model;
|
|
16
|
+
if (argv.url)
|
|
17
|
+
config.baseUrl = argv.url;
|
|
18
|
+
if (argv.provider)
|
|
19
|
+
config.provider = argv.provider;
|
|
20
|
+
const skills = new SkillLoader();
|
|
21
|
+
await skills.loadAll();
|
|
22
|
+
// Print welcome banner to scrollback BEFORE Ink starts
|
|
23
|
+
welcome(config.provider, config.model, process.cwd());
|
|
24
|
+
// Move cursor to last terminal row so Ink renders at absolute bottom
|
|
25
|
+
process.stdout.write(`\x1b[${process.stdout.rows ?? 24};1H`);
|
|
26
|
+
// Ink renders ONLY the input bar (small footprint at bottom)
|
|
27
|
+
// patchConsole: true (default) ensures console.log output appears above Ink
|
|
28
|
+
const sessionName = argv.session || 'default';
|
|
29
|
+
const { waitUntilExit } = render(React.createElement(InputBar, { config, skills, cwd: process.cwd(), session: sessionName }), { exitOnCtrlC: false });
|
|
30
|
+
await waitUntilExit();
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,QAAQ,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAE1C,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;QAC3C,MAAM,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,CAAC;QAC/C,KAAK,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE;KAC7D,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;IACzC,IAAI,IAAI,CAAC,GAAG;QAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAA;IACvC,IAAI,IAAI,CAAC,QAAQ;QAAE,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAkC,CAAA;IAE5E,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAA;IAChC,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;IAEtB,uDAAuD;IACvD,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAErD,qEAAqE;IACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,KAAK,CAAC,CAAA;IAE5D,6DAA6D;IAC7D,4EAA4E;IAC5E,MAAM,WAAW,GAAI,IAAI,CAAC,OAAkB,IAAI,SAAS,CAAA;IAEzD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAC9B,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,EAC3F,EAAE,WAAW,EAAE,KAAK,EAAE,CACvB,CAAA;IAED,MAAM,aAAa,EAAE,CAAA;AACvB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface OllamaModel {
|
|
2
|
+
name: string;
|
|
3
|
+
size: number;
|
|
4
|
+
modified_at: string;
|
|
5
|
+
digest?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function listModels(baseUrl: string): Promise<OllamaModel[]>;
|
|
8
|
+
export declare function pullModel(baseUrl: string, name: string, onProgress: (status: string, pct: number | undefined) => void, signal?: AbortSignal): Promise<void>;
|
|
9
|
+
export declare function fmtSize(bytes: number): string;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export async function listModels(baseUrl) {
|
|
2
|
+
const res = await fetch(`${baseUrl}/api/tags`);
|
|
3
|
+
if (!res.ok)
|
|
4
|
+
throw new Error(`Ollama ${res.status}: ${await res.text()}`);
|
|
5
|
+
const data = (await res.json());
|
|
6
|
+
return data.models ?? [];
|
|
7
|
+
}
|
|
8
|
+
export async function pullModel(baseUrl, name, onProgress, signal) {
|
|
9
|
+
const res = await fetch(`${baseUrl}/api/pull`, {
|
|
10
|
+
method: 'POST',
|
|
11
|
+
headers: { 'Content-Type': 'application/json' },
|
|
12
|
+
body: JSON.stringify({ name, stream: true }),
|
|
13
|
+
signal,
|
|
14
|
+
});
|
|
15
|
+
if (!res.ok)
|
|
16
|
+
throw new Error(`pull failed: ${res.status} ${await res.text()}`);
|
|
17
|
+
const reader = res.body.getReader();
|
|
18
|
+
const dec = new TextDecoder();
|
|
19
|
+
let buf = '';
|
|
20
|
+
try {
|
|
21
|
+
while (true) {
|
|
22
|
+
const { done, value } = await reader.read();
|
|
23
|
+
if (done)
|
|
24
|
+
break;
|
|
25
|
+
buf += dec.decode(value, { stream: true });
|
|
26
|
+
const lines = buf.split('\n');
|
|
27
|
+
buf = lines.pop() ?? '';
|
|
28
|
+
for (const line of lines) {
|
|
29
|
+
if (!line.trim())
|
|
30
|
+
continue;
|
|
31
|
+
try {
|
|
32
|
+
const obj = JSON.parse(line);
|
|
33
|
+
const pct = obj.total ? Math.round(((obj.completed ?? 0) / obj.total) * 100) : undefined;
|
|
34
|
+
onProgress(obj.status ?? '', pct);
|
|
35
|
+
}
|
|
36
|
+
catch { }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
reader.releaseLock();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function fmtSize(bytes) {
|
|
45
|
+
if (bytes >= 1e9)
|
|
46
|
+
return `${(bytes / 1e9).toFixed(1)}GB`;
|
|
47
|
+
if (bytes >= 1e6)
|
|
48
|
+
return `${(bytes / 1e6).toFixed(0)}MB`;
|
|
49
|
+
return `${(bytes / 1e3).toFixed(0)}KB`;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=ollama.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/llm/ollama.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChatMessage } from '../types.js';
|
|
2
|
+
export interface StreamConfig {
|
|
3
|
+
provider: 'ollama' | 'openai-compat';
|
|
4
|
+
model: string;
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
messages: ChatMessage[];
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
onToken: (token: string) => void;
|
|
9
|
+
onDone: (fullText: string) => void | Promise<void>;
|
|
10
|
+
onError: (err: Error) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function stream(cfg: StreamConfig): Promise<void>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
export async function stream(cfg) {
|
|
2
|
+
if (cfg.provider === 'openai-compat') {
|
|
3
|
+
return streamOpenAI(cfg);
|
|
4
|
+
}
|
|
5
|
+
return streamOllama(cfg);
|
|
6
|
+
}
|
|
7
|
+
async function streamOllama(cfg) {
|
|
8
|
+
const { model, messages, baseUrl, signal, onToken, onDone, onError } = cfg;
|
|
9
|
+
let res;
|
|
10
|
+
try {
|
|
11
|
+
res = await fetch(`${baseUrl}/api/chat`, {
|
|
12
|
+
method: 'POST',
|
|
13
|
+
headers: { 'Content-Type': 'application/json' },
|
|
14
|
+
body: JSON.stringify({ model, messages, stream: true }),
|
|
15
|
+
signal,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
onError(toError(err));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (!res.ok) {
|
|
23
|
+
onError(new Error(`Ollama ${res.status}: ${await res.text()}`));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const reader = res.body.getReader();
|
|
27
|
+
const dec = new TextDecoder();
|
|
28
|
+
let full = '';
|
|
29
|
+
let buf = '';
|
|
30
|
+
try {
|
|
31
|
+
while (true) {
|
|
32
|
+
const { done, value } = await reader.read();
|
|
33
|
+
if (done)
|
|
34
|
+
break;
|
|
35
|
+
buf += dec.decode(value, { stream: true });
|
|
36
|
+
const lines = buf.split('\n');
|
|
37
|
+
buf = lines.pop() ?? '';
|
|
38
|
+
for (const line of lines) {
|
|
39
|
+
if (!line.trim())
|
|
40
|
+
continue;
|
|
41
|
+
try {
|
|
42
|
+
const obj = JSON.parse(line);
|
|
43
|
+
const tok = obj?.message?.content ?? '';
|
|
44
|
+
if (tok) {
|
|
45
|
+
onToken(tok);
|
|
46
|
+
full += tok;
|
|
47
|
+
}
|
|
48
|
+
if (obj?.done) {
|
|
49
|
+
await onDone(full);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch { }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
await onDone(full);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
if (err?.name !== 'AbortError')
|
|
60
|
+
onError(toError(err));
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
reader.releaseLock();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function streamOpenAI(cfg) {
|
|
67
|
+
const { model, messages, baseUrl, signal, onToken, onDone, onError } = cfg;
|
|
68
|
+
let res;
|
|
69
|
+
try {
|
|
70
|
+
res = await fetch(`${baseUrl}/v1/chat/completions`, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: { 'Content-Type': 'application/json', Authorization: 'Bearer local' },
|
|
73
|
+
body: JSON.stringify({ model, messages, stream: true }),
|
|
74
|
+
signal,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
onError(toError(err));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (!res.ok) {
|
|
82
|
+
onError(new Error(`LLM ${res.status}: ${await res.text()}`));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const reader = res.body.getReader();
|
|
86
|
+
const dec = new TextDecoder();
|
|
87
|
+
let full = '';
|
|
88
|
+
let buf = '';
|
|
89
|
+
try {
|
|
90
|
+
while (true) {
|
|
91
|
+
const { done, value } = await reader.read();
|
|
92
|
+
if (done)
|
|
93
|
+
break;
|
|
94
|
+
buf += dec.decode(value, { stream: true });
|
|
95
|
+
const lines = buf.split('\n');
|
|
96
|
+
buf = lines.pop() ?? '';
|
|
97
|
+
for (const line of lines) {
|
|
98
|
+
const trimmed = line.replace(/^data:\s*/, '').trim();
|
|
99
|
+
if (!trimmed || trimmed === '[DONE]')
|
|
100
|
+
continue;
|
|
101
|
+
try {
|
|
102
|
+
const obj = JSON.parse(trimmed);
|
|
103
|
+
const tok = obj?.choices?.[0]?.delta?.content ?? '';
|
|
104
|
+
if (tok) {
|
|
105
|
+
onToken(tok);
|
|
106
|
+
full += tok;
|
|
107
|
+
}
|
|
108
|
+
if (obj?.choices?.[0]?.finish_reason) {
|
|
109
|
+
await onDone(full);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch { }
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
await onDone(full);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
if (err?.name !== 'AbortError')
|
|
120
|
+
onError(toError(err));
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
reader.releaseLock();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function toError(e) {
|
|
127
|
+
return e instanceof Error ? e : new Error(String(e));
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/llm/stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface ParsedText {
|
|
2
|
+
type: 'text';
|
|
3
|
+
content: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ParsedTool {
|
|
6
|
+
type: 'tool_call';
|
|
7
|
+
content: string;
|
|
8
|
+
toolName: string;
|
|
9
|
+
toolArgs: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
export type ParsedItem = ParsedText | ParsedTool;
|
|
12
|
+
export declare class StreamParser {
|
|
13
|
+
private buf;
|
|
14
|
+
private inTool;
|
|
15
|
+
feed(token: string): ParsedItem[];
|
|
16
|
+
flush(): ParsedItem[];
|
|
17
|
+
}
|