miii-cli 0.1.7 → 0.2.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 +10 -1
- package/dist/init.js +4 -0
- package/dist/init.js.map +1 -1
- package/dist/llm/ollama.d.ts +1 -0
- package/dist/llm/ollama.js +49 -0
- package/dist/llm/ollama.js.map +1 -1
- package/dist/llm/stream.d.ts +2 -3
- package/dist/llm/stream.js +22 -100
- package/dist/llm/stream.js.map +1 -1
- package/dist/parser/stream-parser.d.ts +4 -0
- package/dist/parser/stream-parser.js +170 -3
- package/dist/parser/stream-parser.js.map +1 -1
- package/dist/tools/index.js +42 -6
- package/dist/tools/index.js.map +1 -1
- package/dist/tui/App.js +62 -37
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/InputBar.js +63 -37
- package/dist/tui/InputBar.js.map +1 -1
- package/dist/tui/components/InputArea.d.ts +2 -1
- package/dist/tui/components/InputArea.js +14 -4
- package/dist/tui/components/InputArea.js.map +1 -1
- package/dist/tui/components/MessageList.d.ts +2 -1
- package/dist/tui/components/MessageList.js +23 -5
- package/dist/tui/components/MessageList.js.map +1 -1
- package/dist/tui/components/StatusBar.js +1 -1
- package/dist/tui/components/StatusBar.js.map +1 -1
- package/dist/tui/printer.js +10 -2
- package/dist/tui/printer.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
- package/src/llm/stream.ts +18 -82
- package/src/parser/stream-parser.ts +145 -3
- package/src/tools/index.ts +40 -6
- package/src/tui/App.tsx +81 -36
- package/src/tui/InputBar.tsx +27 -42
- package/src/tui/components/MessageList.tsx +33 -6
- package/src/tui/components/StatusBar.tsx +1 -1
- package/src/tui/printer.ts +11 -2
- package/src/types.ts +1 -1
|
@@ -57,7 +57,25 @@ function UserMsg({ msg }) {
|
|
|
57
57
|
? _jsx(Text, { color: "cyan", children: p }, i)
|
|
58
58
|
: _jsx(Text, { children: p }, i)) }) })] }));
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
const THINKING_PHRASES = [
|
|
61
|
+
'oh wow, a question. let me pretend to care…',
|
|
62
|
+
'consulting the void…',
|
|
63
|
+
'making something up, just a sec…',
|
|
64
|
+
'definitely not hallucinating right now…',
|
|
65
|
+
'running 47 mental tabs…',
|
|
66
|
+
'staring into the abyss (it blinked)…',
|
|
67
|
+
'calculating your fate, no pressure…',
|
|
68
|
+
'doing the thinking you pay me for…',
|
|
69
|
+
'processing your questionable life choices…',
|
|
70
|
+
'summoning coherent thoughts, rarely works…',
|
|
71
|
+
];
|
|
72
|
+
const SPARKLE = ['✦', '✧', '✶', '✷', '✸', '✹'];
|
|
73
|
+
function AssistantMsg({ msg, thinkingTick }) {
|
|
74
|
+
if (!msg.content && thinkingTick !== undefined) {
|
|
75
|
+
const phrase = THINKING_PHRASES[Math.floor(thinkingTick / 62) % THINKING_PHRASES.length];
|
|
76
|
+
const icon = SPARKLE[thinkingTick % SPARKLE.length];
|
|
77
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: "green", children: "miii" }), _jsxs(Box, { paddingLeft: 2, children: [_jsxs(Text, { color: "yellow", children: [icon, " "] }), _jsx(Text, { color: "gray", dimColor: true, italic: true, children: phrase })] })] }));
|
|
78
|
+
}
|
|
61
79
|
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: "green", children: "miii" }), _jsx(ContentBlock, { content: msg.content })] }));
|
|
62
80
|
}
|
|
63
81
|
function ToolMsg({ msg }) {
|
|
@@ -69,10 +87,10 @@ function ToolMsg({ msg }) {
|
|
|
69
87
|
function SystemMsg({ msg }) {
|
|
70
88
|
return (_jsx(Box, { marginBottom: 1, paddingLeft: 1, children: _jsxs(Text, { color: "gray", dimColor: true, children: ["\u2500 ", msg.content] }) }));
|
|
71
89
|
}
|
|
72
|
-
function MsgItem({ msg }) {
|
|
90
|
+
function MsgItem({ msg, thinkingTick }) {
|
|
73
91
|
switch (msg.role) {
|
|
74
92
|
case 'user': return _jsx(UserMsg, { msg: msg });
|
|
75
|
-
case 'assistant': return _jsx(AssistantMsg, { msg: msg });
|
|
93
|
+
case 'assistant': return _jsx(AssistantMsg, { msg: msg, thinkingTick: thinkingTick });
|
|
76
94
|
case 'tool': return _jsx(ToolMsg, { msg: msg });
|
|
77
95
|
case 'system': return _jsx(SystemMsg, { msg: msg });
|
|
78
96
|
default: return null;
|
|
@@ -90,9 +108,9 @@ function ScrollHint({ hiddenAbove, hiddenBelow }) {
|
|
|
90
108
|
return (_jsx(Box, { justifyContent: "center", children: _jsxs(Text, { color: "gray", dimColor: true, children: [parts.join(' '), " \u00B7 PgUp/PgDn"] }) }));
|
|
91
109
|
}
|
|
92
110
|
// ─── main export ─────────────────────────────────────────────────────────────
|
|
93
|
-
export function MessageList({ messages, rows, cols, scrollOffset, streaming }) {
|
|
111
|
+
export function MessageList({ messages, rows, cols, scrollOffset, streaming, thinkingTick }) {
|
|
94
112
|
const availRows = Math.max(rows - 2, 4);
|
|
95
113
|
const { visible, hiddenAbove, hiddenBelow } = useMemo(() => computeSlice(messages, availRows, scrollOffset, cols), [messages, availRows, scrollOffset, cols]);
|
|
96
|
-
return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, overflow: "hidden", paddingX: 1, children: [_jsx(ScrollHint, { hiddenAbove: hiddenAbove, hiddenBelow: hiddenBelow }), visible.length === 0 && hiddenAbove === 0 && (_jsx(Box, { paddingTop: 1, children: _jsx(Text, { color: "gray", dimColor: true, children: "start typing below \u2014 @ for files, / for commands" }) })), visible.map(msg => _jsx(MsgItem, { msg: msg }, msg.id)), streaming && scrollOffset === 0 && (_jsx(Box, { paddingLeft: 2, children: _jsx(Text, { color: "gray", dimColor: true, children: "\u258B" }) }))] }));
|
|
114
|
+
return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, overflow: "hidden", paddingX: 1, children: [_jsx(ScrollHint, { hiddenAbove: hiddenAbove, hiddenBelow: hiddenBelow }), visible.length === 0 && hiddenAbove === 0 && (_jsx(Box, { paddingTop: 1, children: _jsx(Text, { color: "gray", dimColor: true, children: "start typing below \u2014 @ for files, / for commands" }) })), visible.map(msg => _jsx(MsgItem, { msg: msg, thinkingTick: thinkingTick }, msg.id)), streaming && scrollOffset === 0 && (_jsx(Box, { paddingLeft: 2, children: _jsx(Text, { color: "gray", dimColor: true, children: "\u258B" }) }))] }));
|
|
97
115
|
}
|
|
98
116
|
//# sourceMappingURL=MessageList.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.js","sourceRoot":"","sources":["../../../src/tui/components/MessageList.tsx"],"names":[],"mappings":";AAAA,
|
|
1
|
+
{"version":3,"file":"MessageList.js","sourceRoot":"","sources":["../../../src/tui/components/MessageList.tsx"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ export function StatusBar({ model, provider, status, tick }) {
|
|
|
5
5
|
const isIdle = status === 'idle';
|
|
6
6
|
const spinner = DOTS[tick % DOTS.length];
|
|
7
7
|
const statusNode = status === 'idle' ? _jsxs(Text, { color: "green", children: ["\u25CF ", _jsx(Text, { color: "gray", children: "ready" })] })
|
|
8
|
-
: status === '
|
|
8
|
+
: status === 'thinking' ? _jsxs(Text, { color: "yellow", children: [spinner, " ", _jsx(Text, { color: "gray", children: "thinking" })] })
|
|
9
9
|
: _jsxs(Text, { color: "yellow", children: [spinner, " ", _jsx(Text, { color: "gray", children: "tool" })] });
|
|
10
10
|
return (_jsx(Box, { children: _jsxs(Box, { flexGrow: 1, paddingX: 1, paddingY: 0, justifyContent: "space-between", children: [_jsx(Text, { bold: true, color: "cyan", children: "MIII" }), _jsxs(Text, { color: "gray", dimColor: true, children: [provider, "/", model] }), statusNode] }) }));
|
|
11
11
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusBar.js","sourceRoot":"","sources":["../../../src/tui/components/StatusBar.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAG/B,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;AAS/D,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAS;IAChE,MAAM,MAAM,GAAG,MAAM,KAAK,MAAM,CAAA;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;IAExC,MAAM,UAAU,GACd,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,wBAAG,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,sBAAa,IAAO;QAChF,CAAC,CAAC,MAAM,KAAK,
|
|
1
|
+
{"version":3,"file":"StatusBar.js","sourceRoot":"","sources":["../../../src/tui/components/StatusBar.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAG/B,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;AAS/D,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAS;IAChE,MAAM,MAAM,GAAG,MAAM,KAAK,MAAM,CAAA;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;IAExC,MAAM,UAAU,GACd,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,wBAAG,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,sBAAa,IAAO;QAChF,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,aAAE,OAAO,OAAE,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,yBAAgB,IAAO;YAClG,CAAC,CAAC,MAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,aAAE,OAAO,OAAE,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,qBAAY,IAAO,CAAA;IAExE,OAAO,CACL,KAAC,GAAG,cACF,MAAC,GAAG,IAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,cAAc,EAAC,eAAe,aACxE,KAAC,IAAI,IAAC,IAAI,QAAC,KAAK,EAAC,MAAM,qBAAY,EACnC,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,QAAQ,mBAAE,QAAQ,OAAG,KAAK,IAAQ,EACpD,UAAU,IACP,GACF,CACP,CAAA;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EAAE,IAAI,EAAoB;IAChD,OAAO,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,QAAQ,kBAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAQ,CAAA;AAC5E,CAAC"}
|
package/dist/tui/printer.js
CHANGED
|
@@ -13,6 +13,14 @@ const yellow = (s) => col(93, s);
|
|
|
13
13
|
function indent(text, pad = ' ') {
|
|
14
14
|
return text.split('\n').map(l => pad + l).join('\n');
|
|
15
15
|
}
|
|
16
|
+
function stripMarkdown(s) {
|
|
17
|
+
return s
|
|
18
|
+
.replace(/\*\*\*(.+?)\*\*\*/g, '$1')
|
|
19
|
+
.replace(/\*\*(.+?)\*\*/g, '$1')
|
|
20
|
+
.replace(/\*(.+?)\*/g, '$1')
|
|
21
|
+
.replace(/`([^`]+)`/g, '$1')
|
|
22
|
+
.replace(/^#{1,6} /gm, '');
|
|
23
|
+
}
|
|
16
24
|
function formatContent(text) {
|
|
17
25
|
const lines = text.split('\n');
|
|
18
26
|
let inCode = false;
|
|
@@ -28,7 +36,7 @@ function formatContent(text) {
|
|
|
28
36
|
out.push(' ' + yellow(line || ' '));
|
|
29
37
|
}
|
|
30
38
|
else {
|
|
31
|
-
out.push(' ' + (line || ''));
|
|
39
|
+
out.push(' ' + stripMarkdown(line || ''));
|
|
32
40
|
}
|
|
33
41
|
}
|
|
34
42
|
return out.join('\n');
|
|
@@ -72,7 +80,7 @@ export function welcome(provider, model, cwd) {
|
|
|
72
80
|
row('', rcmd('/session', 'manage sessions')),
|
|
73
81
|
blank(),
|
|
74
82
|
row(` ${gray(provider + '/' + model)}`, ` ${bold(yellow('Tips'))}`),
|
|
75
|
-
row(` ${gray(shortCwd)}`, rcmd('ctrl+c', 'stop
|
|
83
|
+
row(` ${gray(shortCwd)}`, rcmd('ctrl+c', 'stop thinking')),
|
|
76
84
|
row('', rcmd('ctrl+c x2', 'exit')),
|
|
77
85
|
blank(),
|
|
78
86
|
bottom,
|
package/dist/tui/printer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printer.js","sourceRoot":"","sources":["../../src/tui/printer.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAE/D,MAAM,CAAC,GAAG,SAAS,CAAA;AACnB,MAAM,IAAI,GAAG,SAAS,CAAA;AACtB,MAAM,GAAG,GAAG,SAAS,CAAA;AAErB,SAAS,IAAI,CAAC,CAAS,IAAI,OAAO,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAA,CAAC,CAAC;AACrD,SAAS,GAAG,CAAC,CAAS,IAAI,OAAO,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAA,CAAC,CAAC;AACnD,SAAS,GAAG,CAAC,IAAY,EAAE,CAAS,IAAI,OAAO,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAA,CAAC,CAAC;AAExE,MAAM,IAAI,GAAK,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AACxC,MAAM,KAAK,GAAI,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AACxC,MAAM,IAAI,GAAK,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AACxC,MAAM,IAAI,GAAK,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AACxC,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AAExC,SAAS,MAAM,CAAC,IAAY,EAAE,GAAG,GAAG,IAAI;IACtC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACtD,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC9B,IAAI,MAAM,GAAG,KAAK,CAAA;IAClB,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC;YAAE,SAAQ;QAC/E,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,GAAG,CAAC,MAAM,CAAA;YAChB,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAClC,CAAC;aAAM,IAAI,MAAM,EAAE,CAAC;YAClB,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAA;QACtC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"printer.js","sourceRoot":"","sources":["../../src/tui/printer.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
package/src/llm/stream.ts
CHANGED
|
@@ -1,116 +1,52 @@
|
|
|
1
1
|
import type { ChatMessage } from '../types.js'
|
|
2
2
|
|
|
3
|
-
export interface
|
|
3
|
+
export interface ChatConfig {
|
|
4
4
|
provider: 'ollama' | 'openai-compat'
|
|
5
5
|
model: string
|
|
6
6
|
baseUrl: string
|
|
7
7
|
apiKey?: string
|
|
8
8
|
messages: ChatMessage[]
|
|
9
9
|
signal?: AbortSignal
|
|
10
|
-
onToken: (token: string) => void
|
|
11
10
|
onDone: (fullText: string) => void | Promise<void>
|
|
12
11
|
onError: (err: Error) => void
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
export async function
|
|
16
|
-
if (cfg.provider === 'openai-compat')
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
return streamOllama(cfg)
|
|
14
|
+
export async function chat(cfg: ChatConfig): Promise<void> {
|
|
15
|
+
if (cfg.provider === 'openai-compat') return chatOpenAI(cfg)
|
|
16
|
+
return chatOllama(cfg)
|
|
20
17
|
}
|
|
21
18
|
|
|
22
|
-
async function
|
|
23
|
-
const { model, messages, baseUrl, signal,
|
|
24
|
-
let res: Response
|
|
19
|
+
async function chatOllama(cfg: ChatConfig): Promise<void> {
|
|
20
|
+
const { model, messages, baseUrl, signal, onDone, onError } = cfg
|
|
25
21
|
try {
|
|
26
|
-
res = await fetch(`${baseUrl}/api/chat`, {
|
|
22
|
+
const res = await fetch(`${baseUrl}/api/chat`, {
|
|
27
23
|
method: 'POST',
|
|
28
24
|
headers: { 'Content-Type': 'application/json' },
|
|
29
|
-
body: JSON.stringify({ model, messages, stream:
|
|
25
|
+
body: JSON.stringify({ model, messages, stream: false }),
|
|
30
26
|
signal,
|
|
31
27
|
})
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
if (!res.ok) {
|
|
37
|
-
onError(new Error(`Ollama ${res.status}: ${await res.text()}`))
|
|
38
|
-
return
|
|
39
|
-
}
|
|
40
|
-
const reader = res.body!.getReader()
|
|
41
|
-
const dec = new TextDecoder()
|
|
42
|
-
let full = ''
|
|
43
|
-
let buf = ''
|
|
44
|
-
try {
|
|
45
|
-
while (true) {
|
|
46
|
-
const { done, value } = await reader.read()
|
|
47
|
-
if (done) break
|
|
48
|
-
buf += dec.decode(value, { stream: true })
|
|
49
|
-
const lines = buf.split('\n')
|
|
50
|
-
buf = lines.pop() ?? ''
|
|
51
|
-
for (const line of lines) {
|
|
52
|
-
if (!line.trim()) continue
|
|
53
|
-
try {
|
|
54
|
-
const obj = JSON.parse(line)
|
|
55
|
-
const tok: string = obj?.message?.content ?? ''
|
|
56
|
-
if (tok) { onToken(tok); full += tok }
|
|
57
|
-
if (obj?.done) { await onDone(full); return }
|
|
58
|
-
} catch {}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
await onDone(full)
|
|
28
|
+
if (!res.ok) { onError(new Error(`Ollama ${res.status}: ${await res.text()}`)); return }
|
|
29
|
+
const obj = await res.json()
|
|
30
|
+
await onDone(obj?.message?.content ?? '')
|
|
62
31
|
} catch (err) {
|
|
63
32
|
if ((err as Error)?.name !== 'AbortError') onError(toError(err))
|
|
64
|
-
} finally {
|
|
65
|
-
reader.releaseLock()
|
|
66
33
|
}
|
|
67
34
|
}
|
|
68
35
|
|
|
69
|
-
async function
|
|
70
|
-
const { model, messages, baseUrl, apiKey, signal,
|
|
71
|
-
let res: Response
|
|
36
|
+
async function chatOpenAI(cfg: ChatConfig): Promise<void> {
|
|
37
|
+
const { model, messages, baseUrl, apiKey, signal, onDone, onError } = cfg
|
|
72
38
|
try {
|
|
73
|
-
res = await fetch(`${baseUrl}/v1/chat/completions`, {
|
|
39
|
+
const res = await fetch(`${baseUrl}/v1/chat/completions`, {
|
|
74
40
|
method: 'POST',
|
|
75
41
|
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey ?? 'local'}` },
|
|
76
|
-
body: JSON.stringify({ model, messages
|
|
42
|
+
body: JSON.stringify({ model, messages }),
|
|
77
43
|
signal,
|
|
78
44
|
})
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
if (!res.ok) {
|
|
84
|
-
onError(new Error(`LLM ${res.status}: ${await res.text()}`))
|
|
85
|
-
return
|
|
86
|
-
}
|
|
87
|
-
const reader = res.body!.getReader()
|
|
88
|
-
const dec = new TextDecoder()
|
|
89
|
-
let full = ''
|
|
90
|
-
let buf = ''
|
|
91
|
-
try {
|
|
92
|
-
while (true) {
|
|
93
|
-
const { done, value } = await reader.read()
|
|
94
|
-
if (done) break
|
|
95
|
-
buf += dec.decode(value, { stream: true })
|
|
96
|
-
const lines = buf.split('\n')
|
|
97
|
-
buf = lines.pop() ?? ''
|
|
98
|
-
for (const line of lines) {
|
|
99
|
-
const trimmed = line.replace(/^data:\s*/, '').trim()
|
|
100
|
-
if (!trimmed || trimmed === '[DONE]') continue
|
|
101
|
-
try {
|
|
102
|
-
const obj = JSON.parse(trimmed)
|
|
103
|
-
const tok: string = obj?.choices?.[0]?.delta?.content ?? ''
|
|
104
|
-
if (tok) { onToken(tok); full += tok }
|
|
105
|
-
if (obj?.choices?.[0]?.finish_reason) { await onDone(full); return }
|
|
106
|
-
} catch {}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
await onDone(full)
|
|
45
|
+
if (!res.ok) { onError(new Error(`LLM ${res.status}: ${await res.text()}`)); return }
|
|
46
|
+
const obj = await res.json()
|
|
47
|
+
await onDone(obj?.choices?.[0]?.message?.content ?? '')
|
|
110
48
|
} catch (err) {
|
|
111
49
|
if ((err as Error)?.name !== 'AbortError') onError(toError(err))
|
|
112
|
-
} finally {
|
|
113
|
-
reader.releaseLock()
|
|
114
50
|
}
|
|
115
51
|
}
|
|
116
52
|
|
|
@@ -1,9 +1,127 @@
|
|
|
1
|
+
import { appendFileSync } from 'fs'
|
|
2
|
+
|
|
1
3
|
export interface ParsedText { type: 'text'; content: string }
|
|
2
4
|
export interface ParsedTool { type: 'tool_call'; content: string; toolName: string; toolArgs: Record<string, unknown> }
|
|
3
5
|
export type ParsedItem = ParsedText | ParsedTool
|
|
4
6
|
|
|
5
7
|
const OPEN = '<tool_call>'
|
|
6
8
|
const CLOSE = '</tool_call>'
|
|
9
|
+
const CTAG_OPEN = '<content>'
|
|
10
|
+
const CTAG_CLOSE = '</content>'
|
|
11
|
+
const OLD_OPEN = '<old>'
|
|
12
|
+
const OLD_CLOSE = '</old>'
|
|
13
|
+
const NEW_OPEN = '<new>'
|
|
14
|
+
const NEW_CLOSE = '</new>'
|
|
15
|
+
const DEBUG_LOG = '/tmp/miii-debug.log'
|
|
16
|
+
|
|
17
|
+
function dbg(msg: string) {
|
|
18
|
+
try { appendFileSync(DEBUG_LOG, `[${new Date().toISOString()}] ${msg}\n`) } catch {}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Fix literal newlines/tabs inside JSON string values — common LLM output mistake
|
|
22
|
+
function sanitizeJson(s: string): string {
|
|
23
|
+
let result = ''
|
|
24
|
+
let inString = false
|
|
25
|
+
let escaped = false
|
|
26
|
+
for (const ch of s) {
|
|
27
|
+
if (escaped) {
|
|
28
|
+
result += ch
|
|
29
|
+
escaped = false
|
|
30
|
+
} else if (ch === '\\' && inString) {
|
|
31
|
+
result += ch
|
|
32
|
+
escaped = true
|
|
33
|
+
} else if (ch === '"') {
|
|
34
|
+
result += ch
|
|
35
|
+
inString = !inString
|
|
36
|
+
} else if (inString && ch === '\n') {
|
|
37
|
+
result += '\\n'
|
|
38
|
+
} else if (inString && ch === '\r') {
|
|
39
|
+
result += '\\r'
|
|
40
|
+
} else if (inString && ch === '\t') {
|
|
41
|
+
result += '\\t'
|
|
42
|
+
} else {
|
|
43
|
+
result += ch
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function parseToolJson(s: string): { name: string; args?: Record<string, unknown> } {
|
|
50
|
+
try { return JSON.parse(s) }
|
|
51
|
+
catch { return JSON.parse(sanitizeJson(s)) }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Find end of a JSON object starting at `from`, correctly tracking strings
|
|
55
|
+
function findJsonEnd(text: string, from: number): number {
|
|
56
|
+
let depth = 0, inStr = false, escaped = false
|
|
57
|
+
for (let i = from; i < text.length; i++) {
|
|
58
|
+
const ch = text[i]
|
|
59
|
+
if (escaped) { escaped = false; continue }
|
|
60
|
+
if (ch === '\\' && inStr) { escaped = true; continue }
|
|
61
|
+
if (ch === '"') { inStr = !inStr; continue }
|
|
62
|
+
if (inStr) continue
|
|
63
|
+
if (ch === '{') depth++
|
|
64
|
+
else if (ch === '}') { depth--; if (depth === 0) return i }
|
|
65
|
+
}
|
|
66
|
+
return -1
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// For file-writing tools: content field may have unescaped chars — extract with lastIndexOf heuristic
|
|
70
|
+
function extractFileToolArgs(text: string, toolName: string): Record<string, unknown> | null {
|
|
71
|
+
if (!text.includes(`"${toolName}"`)) return null
|
|
72
|
+
const args: Record<string, string> = {}
|
|
73
|
+
|
|
74
|
+
const pathM = text.match(/"path"\s*:\s*"([^"]*)"/)
|
|
75
|
+
if (pathM) args.path = pathM[1]
|
|
76
|
+
|
|
77
|
+
// content is always the last string field — find its opening quote, take to last " before final }}
|
|
78
|
+
const ctIdx = text.indexOf('"content"')
|
|
79
|
+
if (ctIdx !== -1) {
|
|
80
|
+
const colon = text.indexOf(':', ctIdx)
|
|
81
|
+
const openQ = text.indexOf('"', colon + 1)
|
|
82
|
+
const lastBrace = text.lastIndexOf('}')
|
|
83
|
+
const closeQ = text.lastIndexOf('"', lastBrace - 1)
|
|
84
|
+
if (openQ !== -1 && closeQ > openQ) {
|
|
85
|
+
const raw = text.slice(openQ + 1, closeQ)
|
|
86
|
+
args.content = raw
|
|
87
|
+
.replace(/\\n/g, '\n').replace(/\\r/g, '\r').replace(/\\t/g, '\t')
|
|
88
|
+
.replace(/\\"/g, '"').replace(/\\\\/g, '\\')
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// For patch_file: extract old/new fields
|
|
93
|
+
const oldM = text.match(/"old"\s*:\s*"([\s\S]*?)"(?:\s*,|\s*\})/)
|
|
94
|
+
if (oldM) args.old = oldM[1].replace(/\\n/g, '\n').replace(/\\"/g, '"')
|
|
95
|
+
const newM = text.match(/"new"\s*:\s*"([\s\S]*?)"(?:\s*,|\s*\})/)
|
|
96
|
+
if (newM) args.new = newM[1].replace(/\\n/g, '\n').replace(/\\"/g, '"')
|
|
97
|
+
|
|
98
|
+
return Object.keys(args).length > 0 ? args : null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Extract a bare tool-call JSON from arbitrary text (LLM skipped <tool_call> wrapper)
|
|
102
|
+
export function extractBareToolCall(text: string): { name: string; args: Record<string, unknown> } | null {
|
|
103
|
+
// First try standard JSON parsing
|
|
104
|
+
let pos = 0
|
|
105
|
+
while (true) {
|
|
106
|
+
const start = text.indexOf('{"name"', pos)
|
|
107
|
+
if (start === -1) break
|
|
108
|
+
const end = findJsonEnd(text, start)
|
|
109
|
+
if (end === -1) break
|
|
110
|
+
try {
|
|
111
|
+
const obj = parseToolJson(text.slice(start, end + 1))
|
|
112
|
+
if (typeof obj.name === 'string') return { name: obj.name, args: (obj.args ?? {}) as Record<string, unknown> }
|
|
113
|
+
} catch {}
|
|
114
|
+
pos = start + 1
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Fallback: content-aware extraction for file-writing tools (immune to unescaped chars)
|
|
118
|
+
for (const name of ['edit_file', 'create_file', 'patch_file']) {
|
|
119
|
+
const args = extractFileToolArgs(text, name)
|
|
120
|
+
if (args) return { name, args }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return null
|
|
124
|
+
}
|
|
7
125
|
|
|
8
126
|
export class StreamParser {
|
|
9
127
|
private buf = ''
|
|
@@ -21,9 +139,33 @@ export class StreamParser {
|
|
|
21
139
|
this.buf = this.buf.slice(end + CLOSE.length)
|
|
22
140
|
this.inTool = false
|
|
23
141
|
try {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
142
|
+
dbg(`raw block (${raw.length} chars): ${raw.slice(0, 300)}`)
|
|
143
|
+
// Extract named content blocks so file content never needs JSON escaping
|
|
144
|
+
const extraArgs: Record<string, string> = {}
|
|
145
|
+
let jsonPart = raw
|
|
146
|
+
|
|
147
|
+
function extractBlock(open: string, close: string, key: string): void {
|
|
148
|
+
const s = raw.indexOf(open), e = raw.indexOf(close)
|
|
149
|
+
if (s === -1 || e === -1 || e <= s) return
|
|
150
|
+
let val = raw.slice(s + open.length, e)
|
|
151
|
+
if (val.startsWith('\n')) val = val.slice(1)
|
|
152
|
+
if (val.endsWith('\n')) val = val.slice(0, -1)
|
|
153
|
+
extraArgs[key] = val
|
|
154
|
+
// shrink jsonPart to before the first block
|
|
155
|
+
const blockStart = raw.indexOf(open)
|
|
156
|
+
if (blockStart < jsonPart.length) jsonPart = raw.slice(0, blockStart).trim()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
extractBlock(CTAG_OPEN, CTAG_CLOSE, 'content')
|
|
160
|
+
extractBlock(OLD_OPEN, OLD_CLOSE, 'old')
|
|
161
|
+
extractBlock(NEW_OPEN, NEW_CLOSE, 'new')
|
|
162
|
+
|
|
163
|
+
const obj = parseToolJson(jsonPart)
|
|
164
|
+
obj.args = { ...(obj.args ?? {}), ...extraArgs }
|
|
165
|
+
dbg(`parsed ok: name=${obj.name} args_keys=${Object.keys(obj.args).join(',')}`)
|
|
166
|
+
out.push({ type: 'tool_call', content: raw, toolName: obj.name, toolArgs: obj.args })
|
|
167
|
+
} catch (e) {
|
|
168
|
+
dbg(`parse FAILED: ${e} | raw: ${raw.slice(0, 300)}`)
|
|
27
169
|
out.push({ type: 'text', content: `${OPEN}${raw}${CLOSE}` })
|
|
28
170
|
}
|
|
29
171
|
} else {
|
package/src/tools/index.ts
CHANGED
|
@@ -46,13 +46,27 @@ export const tools: Tool[] = [
|
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
name: 'edit_file',
|
|
49
|
-
description: '
|
|
49
|
+
description: 'Overwrite entire file — use only for new files or full rewrites',
|
|
50
50
|
params: '{"path": "string", "content": "string"}',
|
|
51
51
|
execute: async ({ path, content }) => {
|
|
52
52
|
writeFile(guardPath(path as string), content as string)
|
|
53
53
|
return `written: ${path}`
|
|
54
54
|
},
|
|
55
55
|
},
|
|
56
|
+
{
|
|
57
|
+
name: 'patch_file',
|
|
58
|
+
description: 'Replace an exact string in a file — use for targeted edits to existing files',
|
|
59
|
+
params: '{"path": "string", "old": "string", "new": "string"}',
|
|
60
|
+
execute: async ({ path, old: oldStr, new: newStr }) => {
|
|
61
|
+
const safe = guardPath(path as string)
|
|
62
|
+
const current = readFile(safe)
|
|
63
|
+
if (!current) throw new Error(`file not found or empty: ${path}`)
|
|
64
|
+
if (!current.includes(oldStr as string)) throw new Error(`old text not found in ${path}`)
|
|
65
|
+
const updated = current.replace(oldStr as string, newStr as string)
|
|
66
|
+
writeFile(safe, updated)
|
|
67
|
+
return `patched: ${path}`
|
|
68
|
+
},
|
|
69
|
+
},
|
|
56
70
|
{
|
|
57
71
|
name: 'delete_file',
|
|
58
72
|
description: 'Delete a file',
|
|
@@ -100,18 +114,38 @@ Use tools by emitting:
|
|
|
100
114
|
{"name": "tool_name", "args": {...}}
|
|
101
115
|
</tool_call>
|
|
102
116
|
|
|
117
|
+
Put file content in named blocks (never inside JSON — avoids escaping errors):
|
|
118
|
+
|
|
119
|
+
For edit_file / create_file use <content> block:
|
|
120
|
+
<tool_call>
|
|
121
|
+
{"name": "edit_file", "args": {"path": "src/foo.ts"}}
|
|
122
|
+
<content>
|
|
123
|
+
full file content here
|
|
124
|
+
</content>
|
|
125
|
+
</tool_call>
|
|
126
|
+
|
|
127
|
+
For patch_file use <old> and <new> blocks:
|
|
128
|
+
<tool_call>
|
|
129
|
+
{"name": "patch_file", "args": {"path": "src/foo.ts"}}
|
|
130
|
+
<old>
|
|
131
|
+
exact text to replace
|
|
132
|
+
</old>
|
|
133
|
+
<new>
|
|
134
|
+
replacement text
|
|
135
|
+
</new>
|
|
136
|
+
</tool_call>
|
|
137
|
+
|
|
103
138
|
Tools:
|
|
104
139
|
${toolDocs}
|
|
105
140
|
|
|
106
141
|
Rules:
|
|
107
|
-
-
|
|
108
|
-
-
|
|
109
|
-
- read_file
|
|
110
|
-
- Show the full content when creating or editing
|
|
142
|
+
- To modify an existing file: use patch_file with the exact old text and new replacement — do NOT rewrite the whole file
|
|
143
|
+
- To create a new file: use edit_file with full content in the <content> block
|
|
144
|
+
- read_file before patch_file so you know the exact text to match
|
|
111
145
|
- Never delete without confirming
|
|
112
146
|
- Be concise
|
|
113
147
|
- Output plain text only — never use markdown formatting in your responses
|
|
114
148
|
- No headers (no #, ##), no bold (**text**), no italic (*text*), no bullet points with *, no horizontal rules (---)
|
|
115
|
-
- No fenced code blocks with backticks in prose
|
|
149
|
+
- No fenced code blocks with backticks in prose
|
|
116
150
|
- Use plain indentation and labels for structure. This is a terminal, not a chat UI${extra}`
|
|
117
151
|
}
|