miii-agent 0.1.14 → 0.1.15
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 +31 -2
- package/dist/cli.js +98 -30
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<a href="https://ollama.com"><img src="https://img.shields.io/badge/powered%20by-Ollama-black" alt="powered by Ollama"></a>
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
|
-
miii is a local-first AI coding agent that lives in your terminal. Powered by [Ollama](https://ollama.com)
|
|
19
|
+
miii is a local-first AI coding agent that lives in your terminal. Powered by [Ollama](https://ollama.com) — or any OpenAI-compatible local server like [llama.cpp](https://github.com/ggml-org/llama.cpp) and [LM Studio](https://lmstudio.ai) — it reads your code, writes features, runs tests, and fixes bugs entirely on your hardware, at native speed.
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
@@ -48,7 +48,7 @@ Most AI coding tools are wrappers around cloud APIs. They are slow, expensive, a
|
|
|
48
48
|
|
|
49
49
|
miii flips the script:
|
|
50
50
|
|
|
51
|
-
- **Absolute Privacy** — Powered by Ollama. Your code stays on your disk, period.
|
|
51
|
+
- **Absolute Privacy** — Powered by Ollama, llama.cpp, or any local OpenAI-compatible server. Your code stays on your disk, period.
|
|
52
52
|
- **Zero Friction** — No API keys, no billing, no accounts. Just `miii`.
|
|
53
53
|
- **True Agency** — miii doesn't just chat; it decomposes problems, invokes tools, and verifies results like a senior engineer.
|
|
54
54
|
- **Native Performance** — No network round-trips. Latency is limited by your GPU, not a CDN.
|
|
@@ -197,6 +197,35 @@ Settings live in `~/.miii/config.json` and are created on first run.
|
|
|
197
197
|
| `ollamaHost` | Ollama API endpoint | URL string |
|
|
198
198
|
| `effort` | Controls temperature & limits | `low` \| `medium` \| `high` |
|
|
199
199
|
|
|
200
|
+
### Other Local Backends
|
|
201
|
+
|
|
202
|
+
Ollama is the default, but miii talks to any **OpenAI-compatible** local server — so you can run [llama.cpp](https://github.com/ggml-org/llama.cpp) or [LM Studio](https://lmstudio.ai) instead. Your code still never leaves your machine.
|
|
203
|
+
|
|
204
|
+
Start `llama-server` (ships with llama.cpp), then point a named provider at it:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
llama-server -m ./qwen2.5-coder-14b.gguf --port 8080
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"model": "qwen2.5-coder-14b",
|
|
213
|
+
"provider": "llamacpp",
|
|
214
|
+
"providers": {
|
|
215
|
+
"llamacpp": { "type": "openai", "baseUrl": "http://localhost:8080" }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
| Field | Description | Values |
|
|
221
|
+
|-------|-------------|--------|
|
|
222
|
+
| `provider` | Active provider name (keys into `providers`) | e.g. `ollama`, `llamacpp` |
|
|
223
|
+
| `providers.<name>.type` | Wire protocol | `ollama` \| `openai` |
|
|
224
|
+
| `providers.<name>.baseUrl` | Server endpoint | URL string |
|
|
225
|
+
| `providers.<name>.apiKey` | Optional bearer token | string |
|
|
226
|
+
|
|
227
|
+
Switch the active provider at launch with `miii --provider llamacpp`. Any `openai`-type provider on a `localhost` URL counts as local — no key, no cloud.
|
|
228
|
+
|
|
200
229
|
---
|
|
201
230
|
|
|
202
231
|
## System Architecture
|
package/dist/cli.js
CHANGED
|
@@ -1767,7 +1767,7 @@ import { sep as sep2 } from "path";
|
|
|
1767
1767
|
// src/ui/WelcomeBlock.tsx
|
|
1768
1768
|
import { Box, Text } from "ink";
|
|
1769
1769
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1770
|
-
function WelcomeBlock({ model, activeCtx, effort, cwd }) {
|
|
1770
|
+
function WelcomeBlock({ model, activeCtx, effort, cwd, updateAvailable }) {
|
|
1771
1771
|
const ctxLabel = activeCtx != null ? `${Math.round(activeCtx / 1024)}k ctx` : "\u2014 ctx";
|
|
1772
1772
|
return /* @__PURE__ */ jsxs(
|
|
1773
1773
|
Box,
|
|
@@ -1790,18 +1790,19 @@ function WelcomeBlock({ model, activeCtx, effort, cwd }) {
|
|
|
1790
1790
|
" effort"
|
|
1791
1791
|
] })
|
|
1792
1792
|
] }),
|
|
1793
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: cwd })
|
|
1793
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: cwd }),
|
|
1794
|
+
updateAvailable && /* @__PURE__ */ jsx(Text, { color: "yellow", children: `\u2191 update available: v${updateAvailable} \u2014 run: miii --update` })
|
|
1794
1795
|
]
|
|
1795
1796
|
}
|
|
1796
1797
|
);
|
|
1797
1798
|
}
|
|
1798
1799
|
|
|
1799
1800
|
// src/ui/InputBar.tsx
|
|
1800
|
-
import { useEffect, useState } from "react";
|
|
1801
|
+
import { memo, useEffect, useState } from "react";
|
|
1801
1802
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
1802
1803
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1803
1804
|
var SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1804
|
-
|
|
1805
|
+
var InputBar = memo(function InputBar2({ input, disabled, processingLabel }) {
|
|
1805
1806
|
const [frame, setFrame] = useState(0);
|
|
1806
1807
|
useEffect(() => {
|
|
1807
1808
|
if (!disabled) return;
|
|
@@ -1829,7 +1830,7 @@ function InputBar({ input, disabled, processingLabel }) {
|
|
|
1829
1830
|
] })
|
|
1830
1831
|
}
|
|
1831
1832
|
);
|
|
1832
|
-
}
|
|
1833
|
+
});
|
|
1833
1834
|
|
|
1834
1835
|
// src/ui/ModelsView.tsx
|
|
1835
1836
|
import { Box as Box3, Text as Text3 } from "ink";
|
|
@@ -1837,7 +1838,7 @@ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
|
1837
1838
|
function ModelsView({ models, cursor, model, host, provider, effort, query, requireSelection }) {
|
|
1838
1839
|
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginLeft: 2, children: [
|
|
1839
1840
|
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginBottom: 1, children: [
|
|
1840
|
-
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1841
|
+
/* @__PURE__ */ jsxs3(Text3, { wrap: "truncate", children: [
|
|
1841
1842
|
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "provider " }),
|
|
1842
1843
|
/* @__PURE__ */ jsx3(Text3, { color: "cyan", children: provider }),
|
|
1843
1844
|
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
@@ -1855,7 +1856,7 @@ function ModelsView({ models, cursor, model, host, provider, effort, query, requ
|
|
|
1855
1856
|
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "select model" }),
|
|
1856
1857
|
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: models.length === 0 ? /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: query ? `no models match "${query}"` : provider === "lmstudio" ? "no models. load a model in LM Studio and start the server." : "no models found." }) : models.map((m, i) => {
|
|
1857
1858
|
const sel = i === cursor;
|
|
1858
|
-
return /* @__PURE__ */ jsxs3(Text3, { color: sel ? "blue" : void 0, dimColor: !sel, children: [
|
|
1859
|
+
return /* @__PURE__ */ jsxs3(Text3, { wrap: "truncate", color: sel ? "blue" : void 0, dimColor: !sel, children: [
|
|
1859
1860
|
sel ? "\u276F " : " ",
|
|
1860
1861
|
m,
|
|
1861
1862
|
m === model ? /* @__PURE__ */ jsx3(Text3, { color: "green", children: " \u25CF" }) : null
|
|
@@ -1901,6 +1902,11 @@ function ProviderPicker({ entries, cursor, activeName, query }) {
|
|
|
1901
1902
|
// src/ui/SessionsView.tsx
|
|
1902
1903
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
1903
1904
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1905
|
+
function truncate(s, max) {
|
|
1906
|
+
if (max <= 0) return "";
|
|
1907
|
+
if (s.length <= max) return s;
|
|
1908
|
+
return s.slice(0, Math.max(0, max - 1)) + "\u2026";
|
|
1909
|
+
}
|
|
1904
1910
|
function relativeTime(iso) {
|
|
1905
1911
|
const diff = Date.now() - new Date(iso).getTime();
|
|
1906
1912
|
const min = Math.floor(diff / 6e4);
|
|
@@ -1916,13 +1922,16 @@ function SessionsView({ sessions, cursor }) {
|
|
|
1916
1922
|
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "resume session" }),
|
|
1917
1923
|
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: sessions.length === 0 ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "no saved sessions yet" }) : sessions.map((s, i) => {
|
|
1918
1924
|
const active2 = i === cursor;
|
|
1919
|
-
const
|
|
1925
|
+
const meta = `\xB7 ${s.messageCount} msgs \xB7 ${relativeTime(s.updatedAt)}`;
|
|
1926
|
+
const cols = process.stdout.columns ?? 80;
|
|
1927
|
+
const titleMax = cols - 9 - meta.length;
|
|
1928
|
+
const label = truncate(s.title, titleMax);
|
|
1920
1929
|
return /* @__PURE__ */ jsxs5(Box5, { gap: 1, children: [
|
|
1921
|
-
/* @__PURE__ */ jsxs5(Text5, { color: active2 ? "blue" : void 0, dimColor: !active2, children: [
|
|
1930
|
+
/* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", color: active2 ? "blue" : void 0, dimColor: !active2, children: [
|
|
1922
1931
|
active2 ? "\u276F " : " ",
|
|
1923
1932
|
label
|
|
1924
1933
|
] }),
|
|
1925
|
-
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children:
|
|
1934
|
+
/* @__PURE__ */ jsx5(Text5, { wrap: "truncate", dimColor: true, children: meta })
|
|
1926
1935
|
] }, s.id);
|
|
1927
1936
|
}) }),
|
|
1928
1937
|
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "\u2191\u2193 navigate enter resume d delete esc cancel" }) })
|
|
@@ -2198,8 +2207,9 @@ function FilePicker({ matches: matches2, cursor }) {
|
|
|
2198
2207
|
}
|
|
2199
2208
|
|
|
2200
2209
|
// src/ui/ChatView.tsx
|
|
2201
|
-
import { useState as useState3, useEffect as useEffect3 } from "react";
|
|
2210
|
+
import { memo as memo2, useState as useState3, useEffect as useEffect3 } from "react";
|
|
2202
2211
|
import { Box as Box9, Text as Text9 } from "ink";
|
|
2212
|
+
import { highlight } from "cli-highlight";
|
|
2203
2213
|
|
|
2204
2214
|
// src/ui/ThinkingBlock.tsx
|
|
2205
2215
|
import { useState as useState2, useEffect as useEffect2 } from "react";
|
|
@@ -2292,6 +2302,55 @@ function countLines(s) {
|
|
|
2292
2302
|
if (!s) return 0;
|
|
2293
2303
|
return s.split("\n").length;
|
|
2294
2304
|
}
|
|
2305
|
+
var EXT_LANG = {
|
|
2306
|
+
ts: "typescript",
|
|
2307
|
+
tsx: "typescript",
|
|
2308
|
+
mts: "typescript",
|
|
2309
|
+
cts: "typescript",
|
|
2310
|
+
js: "javascript",
|
|
2311
|
+
jsx: "javascript",
|
|
2312
|
+
mjs: "javascript",
|
|
2313
|
+
cjs: "javascript",
|
|
2314
|
+
json: "json",
|
|
2315
|
+
py: "python",
|
|
2316
|
+
rb: "ruby",
|
|
2317
|
+
go: "go",
|
|
2318
|
+
rs: "rust",
|
|
2319
|
+
java: "java",
|
|
2320
|
+
c: "c",
|
|
2321
|
+
h: "c",
|
|
2322
|
+
cpp: "cpp",
|
|
2323
|
+
cc: "cpp",
|
|
2324
|
+
hpp: "cpp",
|
|
2325
|
+
cs: "csharp",
|
|
2326
|
+
php: "php",
|
|
2327
|
+
swift: "swift",
|
|
2328
|
+
kt: "kotlin",
|
|
2329
|
+
scala: "scala",
|
|
2330
|
+
sh: "bash",
|
|
2331
|
+
bash: "bash",
|
|
2332
|
+
zsh: "bash",
|
|
2333
|
+
yml: "yaml",
|
|
2334
|
+
yaml: "yaml",
|
|
2335
|
+
html: "xml",
|
|
2336
|
+
xml: "xml",
|
|
2337
|
+
css: "css",
|
|
2338
|
+
scss: "scss",
|
|
2339
|
+
sql: "sql",
|
|
2340
|
+
md: "markdown"
|
|
2341
|
+
};
|
|
2342
|
+
function langFromPath(path) {
|
|
2343
|
+
const ext = path.split(".").pop()?.toLowerCase();
|
|
2344
|
+
return ext ? EXT_LANG[ext] : void 0;
|
|
2345
|
+
}
|
|
2346
|
+
function highlightLine(text, lang) {
|
|
2347
|
+
if (!lang) return text;
|
|
2348
|
+
try {
|
|
2349
|
+
return highlight(text, { language: lang, ignoreIllegals: true });
|
|
2350
|
+
} catch {
|
|
2351
|
+
return text;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2295
2354
|
function FileEditBlock({
|
|
2296
2355
|
label,
|
|
2297
2356
|
path,
|
|
@@ -2302,6 +2361,7 @@ function FileEditBlock({
|
|
|
2302
2361
|
const expanded = useToolExpanded();
|
|
2303
2362
|
const shown = expanded ? previewLines : previewLines.slice(0, COLLAPSED_LINES);
|
|
2304
2363
|
const extra = previewLines.length - shown.length;
|
|
2364
|
+
const lang = langFromPath(path);
|
|
2305
2365
|
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginLeft: 2, children: [
|
|
2306
2366
|
/* @__PURE__ */ jsxs9(Box9, { children: [
|
|
2307
2367
|
/* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u25CF " }),
|
|
@@ -2319,15 +2379,19 @@ function FileEditBlock({
|
|
|
2319
2379
|
] }) }),
|
|
2320
2380
|
shown.map((ln, i) => {
|
|
2321
2381
|
const width = (process.stdout.columns ?? 80) - 6 - 20;
|
|
2322
|
-
const
|
|
2323
|
-
const
|
|
2324
|
-
|
|
2382
|
+
const textWidth = Math.max(0, width - 2);
|
|
2383
|
+
const plain = ln.text.length > textWidth ? ln.text.slice(0, textWidth) : ln.text.padEnd(textWidth);
|
|
2384
|
+
const code = ln.sign === " " ? plain : highlightLine(plain, lang);
|
|
2385
|
+
return /* @__PURE__ */ jsx9(Box9, { marginLeft: 4, children: /* @__PURE__ */ jsxs9(
|
|
2325
2386
|
Text9,
|
|
2326
2387
|
{
|
|
2327
2388
|
wrap: "truncate",
|
|
2328
2389
|
backgroundColor: ln.sign === "+" ? "#13351f" : ln.sign === "-" ? "#3b1414" : void 0,
|
|
2329
2390
|
dimColor: ln.sign === " ",
|
|
2330
|
-
children:
|
|
2391
|
+
children: [
|
|
2392
|
+
`${ln.sign} `,
|
|
2393
|
+
code
|
|
2394
|
+
]
|
|
2331
2395
|
}
|
|
2332
2396
|
) }, i);
|
|
2333
2397
|
}),
|
|
@@ -2346,7 +2410,7 @@ var TOOL_LABEL = {
|
|
|
2346
2410
|
glob: "Glob",
|
|
2347
2411
|
grep: "Grep"
|
|
2348
2412
|
};
|
|
2349
|
-
function
|
|
2413
|
+
function truncate2(s, max) {
|
|
2350
2414
|
if (s.length <= max) return s;
|
|
2351
2415
|
return s.slice(0, max - 1) + "\u2026";
|
|
2352
2416
|
}
|
|
@@ -2362,15 +2426,15 @@ function toolHeader(use) {
|
|
|
2362
2426
|
break;
|
|
2363
2427
|
case "run_bash": {
|
|
2364
2428
|
const cmd2 = String(input.command ?? "").replace(/\s+/g, " ");
|
|
2365
|
-
arg =
|
|
2429
|
+
arg = truncate2(cmd2, 120);
|
|
2366
2430
|
break;
|
|
2367
2431
|
}
|
|
2368
2432
|
case "glob":
|
|
2369
2433
|
case "grep":
|
|
2370
|
-
arg =
|
|
2434
|
+
arg = truncate2(String(input.pattern ?? ""), 120);
|
|
2371
2435
|
break;
|
|
2372
2436
|
default: {
|
|
2373
|
-
arg =
|
|
2437
|
+
arg = truncate2(JSON.stringify(input), 80);
|
|
2374
2438
|
}
|
|
2375
2439
|
}
|
|
2376
2440
|
return { label, arg };
|
|
@@ -2412,7 +2476,7 @@ function ToolResultBlock({ result, toolName }) {
|
|
|
2412
2476
|
}
|
|
2413
2477
|
const MAX_LINE_WIDTH = 200;
|
|
2414
2478
|
const visible = expanded ? lines : lines.slice(0, COLLAPSED_LINES);
|
|
2415
|
-
const shown = visible.map((l) =>
|
|
2479
|
+
const shown = visible.map((l) => truncate2(l, MAX_LINE_WIDTH));
|
|
2416
2480
|
const extra = lines.length - shown.length;
|
|
2417
2481
|
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginLeft: 2, children: [
|
|
2418
2482
|
/* @__PURE__ */ jsxs9(Text9, { color: result.is_error ? "red" : void 0, dimColor: !result.is_error, children: [
|
|
@@ -2462,7 +2526,13 @@ function ToolUseLine({ use, result }) {
|
|
|
2462
2526
|
result && /* @__PURE__ */ jsx9(ToolResultBlock, { result, toolName: use.name })
|
|
2463
2527
|
] });
|
|
2464
2528
|
}
|
|
2465
|
-
function
|
|
2529
|
+
var UserMessage = memo2(function UserMessage2({ msg }) {
|
|
2530
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "row", marginBottom: 1, children: [
|
|
2531
|
+
/* @__PURE__ */ jsx9(Text9, { color: "blue", children: "\u25CF " }),
|
|
2532
|
+
/* @__PURE__ */ jsx9(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx9(Text9, { children: msg.content }) })
|
|
2533
|
+
] });
|
|
2534
|
+
});
|
|
2535
|
+
var AssistantMessage = memo2(function AssistantMessage2({ msg }) {
|
|
2466
2536
|
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginBottom: 1, children: [
|
|
2467
2537
|
msg.content && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "row", children: [
|
|
2468
2538
|
/* @__PURE__ */ jsx9(Text9, { color: "white", children: "\u25CF " }),
|
|
@@ -2477,14 +2547,16 @@ function AssistantMessage({ msg }) {
|
|
|
2477
2547
|
msg.duration != null ? ` \xB7 ${formatDuration(msg.duration)}` : ""
|
|
2478
2548
|
] }) })
|
|
2479
2549
|
] });
|
|
2480
|
-
}
|
|
2550
|
+
});
|
|
2481
2551
|
function summarizeInput(input) {
|
|
2482
2552
|
if (!input || typeof input !== "object") return "";
|
|
2483
2553
|
const obj = input;
|
|
2484
2554
|
const priority = ["path", "file_path", "command", "pattern", "query"];
|
|
2485
2555
|
for (const k of priority) {
|
|
2486
2556
|
const v = obj[k];
|
|
2487
|
-
if (typeof v === "string" && v.length > 0)
|
|
2557
|
+
if (typeof v === "string" && v.length > 0) {
|
|
2558
|
+
return `${k}: ${v.length > 120 ? v.slice(0, 120) + "\u2026" : v}`;
|
|
2559
|
+
}
|
|
2488
2560
|
}
|
|
2489
2561
|
const first = Object.entries(obj).find(([, v]) => typeof v === "string");
|
|
2490
2562
|
if (first) {
|
|
@@ -2509,7 +2581,7 @@ function PermissionPrompt({ req, cursor }) {
|
|
|
2509
2581
|
/* @__PURE__ */ jsx9(Text9, { bold: true, children: label }),
|
|
2510
2582
|
"?"
|
|
2511
2583
|
] }) }),
|
|
2512
|
-
summary && /* @__PURE__ */ jsx9(Box9, { marginLeft: 2, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: summary }) }),
|
|
2584
|
+
summary && /* @__PURE__ */ jsx9(Box9, { marginLeft: 2, children: /* @__PURE__ */ jsx9(Text9, { wrap: "truncate", dimColor: true, children: summary }) }),
|
|
2513
2585
|
/* @__PURE__ */ jsx9(Box9, { flexDirection: "column", marginTop: 1, children: options.map((opt, i) => /* @__PURE__ */ jsxs9(Text9, { color: i === cursor ? "blue" : void 0, children: [
|
|
2514
2586
|
i === cursor ? "\u276F " : " ",
|
|
2515
2587
|
i + 1,
|
|
@@ -2540,10 +2612,7 @@ function ChatView({
|
|
|
2540
2612
|
] }, i))
|
|
2541
2613
|
] }),
|
|
2542
2614
|
messages.map(
|
|
2543
|
-
(msg, i) => msg.role === "user" ? /* @__PURE__ */
|
|
2544
|
-
/* @__PURE__ */ jsx9(Text9, { color: "blue", children: "\u25CF " }),
|
|
2545
|
-
/* @__PURE__ */ jsx9(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx9(Text9, { children: msg.content }) })
|
|
2546
|
-
] }, i) : /* @__PURE__ */ jsx9(AssistantMessage, { msg }, i)
|
|
2615
|
+
(msg, i) => msg.role === "user" ? /* @__PURE__ */ jsx9(UserMessage, { msg }, i) : /* @__PURE__ */ jsx9(AssistantMessage, { msg }, i)
|
|
2547
2616
|
),
|
|
2548
2617
|
thinking && /* @__PURE__ */ jsx9(ThinkingBlock, { content: thinkingContent }),
|
|
2549
2618
|
streaming && streamingContent && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "row", marginBottom: 1, children: [
|
|
@@ -3262,8 +3331,7 @@ function App() {
|
|
|
3262
3331
|
return Math.round(used / activeCtx * 100);
|
|
3263
3332
|
})();
|
|
3264
3333
|
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: 1, children: [
|
|
3265
|
-
/* @__PURE__ */ jsx10(WelcomeBlock, { model: cfg.model, activeCtx, effort, cwd, error: agent.error }),
|
|
3266
|
-
updateAvailable && /* @__PURE__ */ jsx10(Box10, { marginLeft: 2, marginBottom: 1, children: /* @__PURE__ */ jsx10(Text10, { color: "yellow", children: `\u2191 update available: v${updateAvailable} \u2014 run: miii --update` }) }),
|
|
3334
|
+
/* @__PURE__ */ jsx10(WelcomeBlock, { model: cfg.model, activeCtx, effort, cwd, error: agent.error, updateAvailable }),
|
|
3267
3335
|
state === "loading" && !agent.error && /* @__PURE__ */ jsx10(Box10, { marginLeft: 2, marginBottom: 1, children: /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: `connecting to ${provName}\u2026` }) }),
|
|
3268
3336
|
agent.error && state !== "ready" && /* @__PURE__ */ jsx10(
|
|
3269
3337
|
ChatView,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "miii-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "Terminal AI coding agent powered by Ollama",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
],
|
|
37
37
|
"license": "MIT",
|
|
38
38
|
"dependencies": {
|
|
39
|
+
"cli-highlight": "^2.1.11",
|
|
39
40
|
"execa": "^9.0.0",
|
|
40
41
|
"ink": "^5.0.0",
|
|
41
42
|
"ollama": "^0.5.0",
|