miii-agent 0.1.21 → 0.1.23
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/cli.js +35 -210
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -190,8 +190,7 @@ async function* chat(entry, model, messages, tools, opts) {
|
|
|
190
190
|
keep_alive: opts?.keep_alive ?? "10m",
|
|
191
191
|
options
|
|
192
192
|
};
|
|
193
|
-
if (
|
|
194
|
-
else if (tools) req.tools = tools;
|
|
193
|
+
if (tools) req.tools = tools;
|
|
195
194
|
try {
|
|
196
195
|
stream = await client.chat(
|
|
197
196
|
req
|
|
@@ -517,62 +516,6 @@ var init_client = __esm({
|
|
|
517
516
|
}
|
|
518
517
|
});
|
|
519
518
|
|
|
520
|
-
// src/llm/grammar.ts
|
|
521
|
-
function argProperties(props) {
|
|
522
|
-
const out = {};
|
|
523
|
-
for (const [key, spec] of Object.entries(props)) {
|
|
524
|
-
const node = { type: spec.type };
|
|
525
|
-
if (spec.enum && spec.enum.length) node.enum = spec.enum;
|
|
526
|
-
out[key] = node;
|
|
527
|
-
}
|
|
528
|
-
return out;
|
|
529
|
-
}
|
|
530
|
-
function toolBranch(tool) {
|
|
531
|
-
const args2 = {
|
|
532
|
-
type: "object",
|
|
533
|
-
additionalProperties: false,
|
|
534
|
-
properties: argProperties(tool.input_schema.properties)
|
|
535
|
-
};
|
|
536
|
-
if (tool.input_schema.required && tool.input_schema.required.length) {
|
|
537
|
-
args2.required = tool.input_schema.required;
|
|
538
|
-
}
|
|
539
|
-
return {
|
|
540
|
-
type: "object",
|
|
541
|
-
additionalProperties: false,
|
|
542
|
-
required: ["name", "arguments"],
|
|
543
|
-
properties: {
|
|
544
|
-
name: { const: tool.name },
|
|
545
|
-
arguments: args2
|
|
546
|
-
}
|
|
547
|
-
};
|
|
548
|
-
}
|
|
549
|
-
function respondBranch() {
|
|
550
|
-
return {
|
|
551
|
-
type: "object",
|
|
552
|
-
additionalProperties: false,
|
|
553
|
-
required: ["name", "arguments"],
|
|
554
|
-
properties: {
|
|
555
|
-
name: { const: RESPOND_ACTION },
|
|
556
|
-
arguments: {
|
|
557
|
-
type: "object",
|
|
558
|
-
additionalProperties: false,
|
|
559
|
-
required: ["message"],
|
|
560
|
-
properties: { message: { type: "string" } }
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
};
|
|
564
|
-
}
|
|
565
|
-
function buildToolGrammar(tools) {
|
|
566
|
-
return { oneOf: [...tools.map(toolBranch), respondBranch()] };
|
|
567
|
-
}
|
|
568
|
-
var RESPOND_ACTION;
|
|
569
|
-
var init_grammar = __esm({
|
|
570
|
-
"src/llm/grammar.ts"() {
|
|
571
|
-
"use strict";
|
|
572
|
-
RESPOND_ACTION = "respond";
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
|
-
|
|
576
519
|
// src/tools/paths.ts
|
|
577
520
|
import { resolve, relative as relative2, isAbsolute, sep, join as join4 } from "path";
|
|
578
521
|
import { homedir as homedir3 } from "os";
|
|
@@ -1265,15 +1208,8 @@ var init_context = __esm({
|
|
|
1265
1208
|
});
|
|
1266
1209
|
|
|
1267
1210
|
// src/prompt/system.ts
|
|
1268
|
-
function buildSystemPrompt(tools, cwd, project
|
|
1211
|
+
function buildSystemPrompt(tools, cwd, project) {
|
|
1269
1212
|
const toolLines = tools.map((t) => `- ${t.name}: ${t.description}`).join("\n");
|
|
1270
|
-
const actionProtocol = grammarMode ? `
|
|
1271
|
-
# Action protocol (strict)
|
|
1272
|
-
Every reply is exactly ONE JSON action object, nothing else \u2014 no prose outside it, no markdown, no fences. Decoding is grammar-constrained, so malformed output is impossible; your only job is to choose the right action.
|
|
1273
|
-
To use a tool: {"name": "<tool_name>", "arguments": { ...that tool's args }}
|
|
1274
|
-
To give your final answer to the user: {"name": "respond", "arguments": {"message": "<your full answer here>"}}
|
|
1275
|
-
Call tools until the GOAL is met, then emit a single "respond" action with the complete answer. The "respond" action is the ONLY way to end the turn and talk to the user \u2014 never put your final answer in a tool call.
|
|
1276
|
-
` : "";
|
|
1277
1213
|
const projectSection = project && project.content.trim() ? `
|
|
1278
1214
|
# ${CONTEXT_FILENAME} \u2014 project instructions (authoritative, read first)
|
|
1279
1215
|
The user maintains ${CONTEXT_FILENAME} at ${project.source} to steer how you work in this project: conventions, commands, architecture, do's and don'ts. Treat it as direct instruction from the user, higher priority than your defaults. When it conflicts with a default rule below, ${CONTEXT_FILENAME} wins (except permissions and safety, which you never override).${project.truncated ? `
|
|
@@ -1358,7 +1294,7 @@ Ask in a numbered list. One round of questions per turn. Then wait.
|
|
|
1358
1294
|
# Tools
|
|
1359
1295
|
You have access to the following tools. Call them via the function-calling interface.
|
|
1360
1296
|
${toolLines}
|
|
1361
|
-
|
|
1297
|
+
|
|
1362
1298
|
# Loop semantics
|
|
1363
1299
|
- When you need to act on the filesystem or run a command, emit a tool call.
|
|
1364
1300
|
- After each tool result, decide: more tool calls, or a final plain-text answer.
|
|
@@ -1588,89 +1524,6 @@ function extractFirstJsonObject(s) {
|
|
|
1588
1524
|
}
|
|
1589
1525
|
return null;
|
|
1590
1526
|
}
|
|
1591
|
-
function parseGrammarAction(content, knownToolNames) {
|
|
1592
|
-
if (!content) return null;
|
|
1593
|
-
let raw = content.trim();
|
|
1594
|
-
if (!raw.startsWith("{")) {
|
|
1595
|
-
const found = extractFirstJsonObject(raw);
|
|
1596
|
-
if (!found) return null;
|
|
1597
|
-
raw = found.json;
|
|
1598
|
-
}
|
|
1599
|
-
let obj;
|
|
1600
|
-
try {
|
|
1601
|
-
obj = JSON.parse(raw);
|
|
1602
|
-
} catch {
|
|
1603
|
-
const found = extractFirstJsonObject(raw);
|
|
1604
|
-
if (!found) return null;
|
|
1605
|
-
try {
|
|
1606
|
-
obj = JSON.parse(found.json);
|
|
1607
|
-
} catch {
|
|
1608
|
-
return null;
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
const name = typeof obj.name === "string" ? obj.name : void 0;
|
|
1612
|
-
if (!name) return null;
|
|
1613
|
-
let args2;
|
|
1614
|
-
const wrapped = obj.arguments ?? obj.parameters ?? obj.input ?? obj.args;
|
|
1615
|
-
if (typeof wrapped === "string") {
|
|
1616
|
-
try {
|
|
1617
|
-
const parsed = JSON.parse(wrapped);
|
|
1618
|
-
args2 = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
1619
|
-
} catch {
|
|
1620
|
-
args2 = {};
|
|
1621
|
-
}
|
|
1622
|
-
} else if (wrapped && typeof wrapped === "object" && !Array.isArray(wrapped)) {
|
|
1623
|
-
args2 = wrapped;
|
|
1624
|
-
} else {
|
|
1625
|
-
const { name: _n, ...rest } = obj;
|
|
1626
|
-
args2 = rest;
|
|
1627
|
-
}
|
|
1628
|
-
if (name === "respond") {
|
|
1629
|
-
const message = typeof args2.message === "string" ? args2.message : "";
|
|
1630
|
-
return { kind: "respond", message };
|
|
1631
|
-
}
|
|
1632
|
-
if (!knownToolNames.includes(name)) return null;
|
|
1633
|
-
return { kind: "tool", name, arguments: args2 };
|
|
1634
|
-
}
|
|
1635
|
-
function streamRespondMessage(text) {
|
|
1636
|
-
if (!/"name"\s*:\s*"respond"/.test(text)) return null;
|
|
1637
|
-
const m = text.match(/"message"\s*:\s*"/);
|
|
1638
|
-
if (!m || m.index == null) return null;
|
|
1639
|
-
const start = m.index + m[0].length;
|
|
1640
|
-
const escapes = {
|
|
1641
|
-
n: "\n",
|
|
1642
|
-
t: " ",
|
|
1643
|
-
r: "\r",
|
|
1644
|
-
b: "\b",
|
|
1645
|
-
f: "\f",
|
|
1646
|
-
'"': '"',
|
|
1647
|
-
"\\": "\\",
|
|
1648
|
-
"/": "/"
|
|
1649
|
-
};
|
|
1650
|
-
let out = "";
|
|
1651
|
-
let i = start;
|
|
1652
|
-
while (i < text.length) {
|
|
1653
|
-
const ch = text[i];
|
|
1654
|
-
if (ch === '"') return { message: out, complete: true };
|
|
1655
|
-
if (ch === "\\") {
|
|
1656
|
-
const nx = text[i + 1];
|
|
1657
|
-
if (nx === void 0) break;
|
|
1658
|
-
if (nx === "u") {
|
|
1659
|
-
const hex = text.slice(i + 2, i + 6);
|
|
1660
|
-
if (hex.length < 4) break;
|
|
1661
|
-
out += String.fromCharCode(parseInt(hex, 16));
|
|
1662
|
-
i += 6;
|
|
1663
|
-
continue;
|
|
1664
|
-
}
|
|
1665
|
-
out += escapes[nx] ?? nx;
|
|
1666
|
-
i += 2;
|
|
1667
|
-
continue;
|
|
1668
|
-
}
|
|
1669
|
-
out += ch;
|
|
1670
|
-
i++;
|
|
1671
|
-
}
|
|
1672
|
-
return { message: out, complete: false };
|
|
1673
|
-
}
|
|
1674
1527
|
function blocksFromOllama(text, tool_calls, knownToolNames = []) {
|
|
1675
1528
|
const blocks = [];
|
|
1676
1529
|
let finalText = text;
|
|
@@ -1752,9 +1605,7 @@ function markSeen(name, input, seen) {
|
|
|
1752
1605
|
async function* runAgent(opts) {
|
|
1753
1606
|
const { model, cwd, permissions, hooks, signal, num_ctx } = opts;
|
|
1754
1607
|
const startTime = Date.now();
|
|
1755
|
-
const
|
|
1756
|
-
const system = buildSystemPrompt(TOOLS, cwd, loadProjectContext(cwd), useGrammar);
|
|
1757
|
-
const grammar = useGrammar ? buildToolGrammar(TOOLS) : void 0;
|
|
1608
|
+
const system = buildSystemPrompt(TOOLS, cwd, loadProjectContext(cwd));
|
|
1758
1609
|
const ollamaTools = toOllamaTools(TOOLS);
|
|
1759
1610
|
const toolNames = TOOLS.map((t) => t.name);
|
|
1760
1611
|
const effort = EFFORT_OPTIONS[loadConfig().effort ?? "medium"];
|
|
@@ -1770,8 +1621,6 @@ async function* runAgent(opts) {
|
|
|
1770
1621
|
for (let turn = 0; turn < MAX_TURNS; turn++) {
|
|
1771
1622
|
let text = "";
|
|
1772
1623
|
let tool_calls;
|
|
1773
|
-
let respondEmitted = 0;
|
|
1774
|
-
let streamedRespond = false;
|
|
1775
1624
|
let emittedText = false;
|
|
1776
1625
|
let lastTail = "";
|
|
1777
1626
|
let tailRepeats = 0;
|
|
@@ -1781,24 +1630,12 @@ async function* runAgent(opts) {
|
|
|
1781
1630
|
const composedSignal = signal ? AbortSignal.any ? AbortSignal.any([signal, ac.signal]) : ac.signal : ac.signal;
|
|
1782
1631
|
if (signal) signal.addEventListener("abort", () => ac.abort(), { once: true });
|
|
1783
1632
|
try {
|
|
1784
|
-
for await (const chunk of chat3(model, toOllamaMessages(history, system),
|
|
1633
|
+
for await (const chunk of chat3(model, toOllamaMessages(history, system), ollamaTools, { signal: composedSignal, num_ctx, num_predict: effort.num_predict, temperature: effort.temperature })) {
|
|
1785
1634
|
if (signal?.aborted) break;
|
|
1786
1635
|
if (chunk.content) {
|
|
1787
1636
|
text += chunk.content;
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
yield { type: "text-delta", text: chunk.content };
|
|
1791
|
-
} else {
|
|
1792
|
-
const r = streamRespondMessage(text);
|
|
1793
|
-
if (r) {
|
|
1794
|
-
streamedRespond = true;
|
|
1795
|
-
if (r.message.length > respondEmitted) {
|
|
1796
|
-
emittedText = true;
|
|
1797
|
-
yield { type: "text-delta", text: r.message.slice(respondEmitted) };
|
|
1798
|
-
respondEmitted = r.message.length;
|
|
1799
|
-
}
|
|
1800
|
-
}
|
|
1801
|
-
}
|
|
1637
|
+
emittedText = true;
|
|
1638
|
+
yield { type: "text-delta", text: chunk.content };
|
|
1802
1639
|
if (text.length >= REPEAT_TAIL) {
|
|
1803
1640
|
const tail = text.slice(-REPEAT_TAIL);
|
|
1804
1641
|
if (tail === lastTail) {
|
|
@@ -1847,19 +1684,7 @@ async function* runAgent(opts) {
|
|
|
1847
1684
|
};
|
|
1848
1685
|
return history;
|
|
1849
1686
|
}
|
|
1850
|
-
|
|
1851
|
-
if (useGrammar) {
|
|
1852
|
-
const action = parseGrammarAction(text, toolNames);
|
|
1853
|
-
if (action?.kind === "tool") {
|
|
1854
|
-
blocks = [{ type: "tool_use", id: mintToolUseId(), name: action.name, input: action.arguments }];
|
|
1855
|
-
} else {
|
|
1856
|
-
const message = action?.kind === "respond" ? action.message : text.trim();
|
|
1857
|
-
if (message && !streamedRespond) yield { type: "text-delta", text: message };
|
|
1858
|
-
blocks = message ? [{ type: "text", text: message }] : [];
|
|
1859
|
-
}
|
|
1860
|
-
} else {
|
|
1861
|
-
blocks = blocksFromOllama(text, tool_calls, toolNames);
|
|
1862
|
-
}
|
|
1687
|
+
const blocks = blocksFromOllama(text, tool_calls, toolNames);
|
|
1863
1688
|
const tool_uses = blocks.filter((b) => b.type === "tool_use");
|
|
1864
1689
|
history.push({ role: "assistant", content: blocks });
|
|
1865
1690
|
if (truncated && tool_uses.length > 0) {
|
|
@@ -1988,7 +1813,6 @@ var init_loop = __esm({
|
|
|
1988
1813
|
"src/agent/loop.ts"() {
|
|
1989
1814
|
"use strict";
|
|
1990
1815
|
init_client();
|
|
1991
|
-
init_grammar();
|
|
1992
1816
|
init_paths();
|
|
1993
1817
|
init_registry();
|
|
1994
1818
|
init_validate();
|
|
@@ -2239,32 +2063,33 @@ import { Box, Text } from "ink";
|
|
|
2239
2063
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2240
2064
|
function WelcomeBlock({ model, activeCtx, effort, cwd, updateAvailable }) {
|
|
2241
2065
|
const ctxLabel = activeCtx != null ? `${Math.round(activeCtx / 1024)}k ctx` : "\u2014 ctx";
|
|
2242
|
-
return /* @__PURE__ */ jsxs(
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2066
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
2067
|
+
/* @__PURE__ */ jsxs(
|
|
2068
|
+
Box,
|
|
2069
|
+
{
|
|
2070
|
+
flexDirection: "column",
|
|
2071
|
+
borderStyle: "round",
|
|
2072
|
+
borderColor: "gray",
|
|
2073
|
+
paddingX: 2,
|
|
2074
|
+
children: [
|
|
2075
|
+
/* @__PURE__ */ jsxs(Box, { gap: 2, children: [
|
|
2076
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "blue", children: "MIII CLI" }),
|
|
2077
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
2078
|
+
/* @__PURE__ */ jsx(Text, { children: model ?? "/models" }),
|
|
2079
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
2080
|
+
/* @__PURE__ */ jsx(Text, { children: ctxLabel }),
|
|
2081
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
2082
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2083
|
+
effort,
|
|
2084
|
+
" effort"
|
|
2085
|
+
] })
|
|
2086
|
+
] }),
|
|
2087
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: cwd })
|
|
2088
|
+
]
|
|
2089
|
+
}
|
|
2090
|
+
),
|
|
2091
|
+
updateAvailable && /* @__PURE__ */ jsx(Text, { color: "yellow", children: `\u2191 update available: v${updateAvailable} \u2014 run: miii --update` })
|
|
2092
|
+
] });
|
|
2268
2093
|
}
|
|
2269
2094
|
|
|
2270
2095
|
// src/ui/InputBar.tsx
|
package/package.json
CHANGED