@ww_nero/mini-cli 1.0.80 → 1.0.82
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 +40 -40
- package/package.json +38 -38
- package/src/chat.js +1150 -1150
- package/src/config.js +342 -387
- package/src/index.js +39 -39
- package/src/llm.js +147 -147
- package/src/prompt/tool.js +18 -18
- package/src/request.js +338 -328
- package/src/tools/bash.js +144 -144
- package/src/tools/edit.js +137 -137
- package/src/tools/index.js +74 -74
- package/src/tools/mcp.js +503 -503
- package/src/tools/read.js +44 -44
- package/src/tools/skills.js +49 -49
- package/src/tools/todos.js +90 -90
- package/src/tools/write.js +66 -66
- package/src/utils/cliOptions.js +9 -9
- package/src/utils/git.js +89 -89
- package/src/utils/history.js +181 -181
- package/src/utils/model.js +131 -131
- package/src/utils/output.js +75 -75
- package/src/utils/renderer.js +102 -102
- package/src/utils/settings.js +77 -77
- package/src/utils/skills.js +250 -250
- package/src/utils/think.js +214 -214
package/src/utils/think.js
CHANGED
|
@@ -1,214 +1,214 @@
|
|
|
1
|
-
const THINK_TAGS = [
|
|
2
|
-
{ name: 'think', open: '<think>', close: '</think>' },
|
|
3
|
-
{ name: 'tihinking', open: '<tihinking>', close: '</tihinking>' },
|
|
4
|
-
{ name: 'thought', open: '<thought>', close: '</thought>' }
|
|
5
|
-
];
|
|
6
|
-
|
|
7
|
-
const THINK_TAG_MAP = new Map(
|
|
8
|
-
THINK_TAGS.map(tag => [tag.name.toLowerCase(), { ...tag, closeLower: tag.close.toLowerCase() }])
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
const findTagEnd = (text, startIndex) => {
|
|
12
|
-
let inSingleQuote = false;
|
|
13
|
-
let inDoubleQuote = false;
|
|
14
|
-
|
|
15
|
-
for (let i = startIndex; i < text.length; i++) {
|
|
16
|
-
const char = text[i];
|
|
17
|
-
|
|
18
|
-
if (char === '\'' && !inDoubleQuote) {
|
|
19
|
-
inSingleQuote = !inSingleQuote;
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (char === '"' && !inSingleQuote) {
|
|
24
|
-
inDoubleQuote = !inDoubleQuote;
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (char === '>' && !inSingleQuote && !inDoubleQuote) {
|
|
29
|
-
return i;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return -1;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const parseTagInfo = (tagText) => {
|
|
37
|
-
if (!tagText.startsWith('<') || !tagText.endsWith('>')) return null;
|
|
38
|
-
|
|
39
|
-
let inner = tagText.slice(1, -1).trim();
|
|
40
|
-
if (!inner) return null;
|
|
41
|
-
|
|
42
|
-
let type = 'start';
|
|
43
|
-
if (inner.startsWith('/')) {
|
|
44
|
-
type = 'end';
|
|
45
|
-
inner = inner.slice(1).trim();
|
|
46
|
-
} else if (inner.endsWith('/')) {
|
|
47
|
-
type = 'self';
|
|
48
|
-
inner = inner.slice(0, -1).trim();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const nameMatch = inner.match(/^([a-zA-Z0-9_-]+)/);
|
|
52
|
-
if (!nameMatch) return null;
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
type,
|
|
56
|
-
name: nameMatch[1].toLowerCase()
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const createThinkParserState = () => ({
|
|
61
|
-
buffer: '',
|
|
62
|
-
currentThink: null
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const processThinkChunk = (state, chunk = '') => {
|
|
66
|
-
if (!state) {
|
|
67
|
-
throw new Error('processThinkChunk requires a state object.');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (chunk == null) {
|
|
71
|
-
chunk = '';
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (typeof chunk !== 'string') {
|
|
75
|
-
chunk = String(chunk);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (!state.buffer) {
|
|
79
|
-
state.buffer = '';
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
state.buffer += chunk;
|
|
83
|
-
|
|
84
|
-
let contentChunk = '';
|
|
85
|
-
let reasonChunk = '';
|
|
86
|
-
|
|
87
|
-
const consumePrefix = (length) => {
|
|
88
|
-
const prefix = state.buffer.slice(0, length);
|
|
89
|
-
state.buffer = state.buffer.slice(length);
|
|
90
|
-
return prefix;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
while (state.buffer.length > 0) {
|
|
94
|
-
if (state.currentThink) {
|
|
95
|
-
const thinkInfo = THINK_TAG_MAP.get(state.currentThink);
|
|
96
|
-
if (!thinkInfo) {
|
|
97
|
-
state.currentThink = null;
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const bufferLower = state.buffer.toLowerCase();
|
|
102
|
-
const closeIndex = bufferLower.indexOf(thinkInfo.closeLower);
|
|
103
|
-
|
|
104
|
-
if (closeIndex === -1) {
|
|
105
|
-
reasonChunk += consumePrefix(state.buffer.length);
|
|
106
|
-
return { contentChunk, reasonChunk };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
reasonChunk += consumePrefix(closeIndex);
|
|
110
|
-
consumePrefix(thinkInfo.close.length);
|
|
111
|
-
state.currentThink = null;
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const nextLt = state.buffer.indexOf('<');
|
|
116
|
-
|
|
117
|
-
if (nextLt === -1) {
|
|
118
|
-
contentChunk += consumePrefix(state.buffer.length);
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (nextLt > 0) {
|
|
123
|
-
contentChunk += consumePrefix(nextLt);
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const tagEnd = findTagEnd(state.buffer, 1);
|
|
128
|
-
if (tagEnd === -1) {
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const rawTag = consumePrefix(tagEnd + 1);
|
|
133
|
-
const tagInfo = parseTagInfo(rawTag);
|
|
134
|
-
|
|
135
|
-
if (!tagInfo) {
|
|
136
|
-
contentChunk += rawTag;
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (tagInfo.type === 'start') {
|
|
141
|
-
if (THINK_TAG_MAP.has(tagInfo.name)) {
|
|
142
|
-
state.currentThink = tagInfo.name;
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
contentChunk += rawTag;
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (tagInfo.type === 'end') {
|
|
151
|
-
contentChunk += rawTag;
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
contentChunk += rawTag;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return { contentChunk, reasonChunk };
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
const flushThinkState = (state) => {
|
|
162
|
-
if (!state || !state.buffer) {
|
|
163
|
-
return { contentChunk: '', reasonChunk: '' };
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const remaining = state.buffer;
|
|
167
|
-
state.buffer = '';
|
|
168
|
-
|
|
169
|
-
if (state.currentThink) {
|
|
170
|
-
state.currentThink = null;
|
|
171
|
-
return { contentChunk: '', reasonChunk: remaining };
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
return { contentChunk: remaining, reasonChunk: '' };
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const splitThinkContent = (text = '') => {
|
|
178
|
-
if (!text) {
|
|
179
|
-
return { content: '', reasoning: '' };
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const state = createThinkParserState();
|
|
183
|
-
let content = '';
|
|
184
|
-
let reasoning = '';
|
|
185
|
-
|
|
186
|
-
const result = processThinkChunk(state, text);
|
|
187
|
-
content += result.contentChunk;
|
|
188
|
-
reasoning += result.reasonChunk;
|
|
189
|
-
|
|
190
|
-
const tail = flushThinkState(state);
|
|
191
|
-
content += tail.contentChunk;
|
|
192
|
-
reasoning += tail.reasonChunk;
|
|
193
|
-
|
|
194
|
-
return { content, reasoning };
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
const summarizeReasoning = (text = '', maxLength = 100) => {
|
|
198
|
-
if (!text) return '';
|
|
199
|
-
const normalized = text.replace(/\s+/g, ' ').trim();
|
|
200
|
-
if (!normalized) return '';
|
|
201
|
-
if (normalized.length > maxLength) {
|
|
202
|
-
return normalized.substring(0, maxLength) + '...';
|
|
203
|
-
}
|
|
204
|
-
return normalized;
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
module.exports = {
|
|
208
|
-
THINK_TAGS,
|
|
209
|
-
createThinkParserState,
|
|
210
|
-
processThinkChunk,
|
|
211
|
-
flushThinkState,
|
|
212
|
-
splitThinkContent,
|
|
213
|
-
summarizeReasoning
|
|
214
|
-
};
|
|
1
|
+
const THINK_TAGS = [
|
|
2
|
+
{ name: 'think', open: '<think>', close: '</think>' },
|
|
3
|
+
{ name: 'tihinking', open: '<tihinking>', close: '</tihinking>' },
|
|
4
|
+
{ name: 'thought', open: '<thought>', close: '</thought>' }
|
|
5
|
+
];
|
|
6
|
+
|
|
7
|
+
const THINK_TAG_MAP = new Map(
|
|
8
|
+
THINK_TAGS.map(tag => [tag.name.toLowerCase(), { ...tag, closeLower: tag.close.toLowerCase() }])
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
const findTagEnd = (text, startIndex) => {
|
|
12
|
+
let inSingleQuote = false;
|
|
13
|
+
let inDoubleQuote = false;
|
|
14
|
+
|
|
15
|
+
for (let i = startIndex; i < text.length; i++) {
|
|
16
|
+
const char = text[i];
|
|
17
|
+
|
|
18
|
+
if (char === '\'' && !inDoubleQuote) {
|
|
19
|
+
inSingleQuote = !inSingleQuote;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (char === '"' && !inSingleQuote) {
|
|
24
|
+
inDoubleQuote = !inDoubleQuote;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (char === '>' && !inSingleQuote && !inDoubleQuote) {
|
|
29
|
+
return i;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return -1;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const parseTagInfo = (tagText) => {
|
|
37
|
+
if (!tagText.startsWith('<') || !tagText.endsWith('>')) return null;
|
|
38
|
+
|
|
39
|
+
let inner = tagText.slice(1, -1).trim();
|
|
40
|
+
if (!inner) return null;
|
|
41
|
+
|
|
42
|
+
let type = 'start';
|
|
43
|
+
if (inner.startsWith('/')) {
|
|
44
|
+
type = 'end';
|
|
45
|
+
inner = inner.slice(1).trim();
|
|
46
|
+
} else if (inner.endsWith('/')) {
|
|
47
|
+
type = 'self';
|
|
48
|
+
inner = inner.slice(0, -1).trim();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const nameMatch = inner.match(/^([a-zA-Z0-9_-]+)/);
|
|
52
|
+
if (!nameMatch) return null;
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
type,
|
|
56
|
+
name: nameMatch[1].toLowerCase()
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const createThinkParserState = () => ({
|
|
61
|
+
buffer: '',
|
|
62
|
+
currentThink: null
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const processThinkChunk = (state, chunk = '') => {
|
|
66
|
+
if (!state) {
|
|
67
|
+
throw new Error('processThinkChunk requires a state object.');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (chunk == null) {
|
|
71
|
+
chunk = '';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (typeof chunk !== 'string') {
|
|
75
|
+
chunk = String(chunk);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!state.buffer) {
|
|
79
|
+
state.buffer = '';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
state.buffer += chunk;
|
|
83
|
+
|
|
84
|
+
let contentChunk = '';
|
|
85
|
+
let reasonChunk = '';
|
|
86
|
+
|
|
87
|
+
const consumePrefix = (length) => {
|
|
88
|
+
const prefix = state.buffer.slice(0, length);
|
|
89
|
+
state.buffer = state.buffer.slice(length);
|
|
90
|
+
return prefix;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
while (state.buffer.length > 0) {
|
|
94
|
+
if (state.currentThink) {
|
|
95
|
+
const thinkInfo = THINK_TAG_MAP.get(state.currentThink);
|
|
96
|
+
if (!thinkInfo) {
|
|
97
|
+
state.currentThink = null;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const bufferLower = state.buffer.toLowerCase();
|
|
102
|
+
const closeIndex = bufferLower.indexOf(thinkInfo.closeLower);
|
|
103
|
+
|
|
104
|
+
if (closeIndex === -1) {
|
|
105
|
+
reasonChunk += consumePrefix(state.buffer.length);
|
|
106
|
+
return { contentChunk, reasonChunk };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
reasonChunk += consumePrefix(closeIndex);
|
|
110
|
+
consumePrefix(thinkInfo.close.length);
|
|
111
|
+
state.currentThink = null;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const nextLt = state.buffer.indexOf('<');
|
|
116
|
+
|
|
117
|
+
if (nextLt === -1) {
|
|
118
|
+
contentChunk += consumePrefix(state.buffer.length);
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (nextLt > 0) {
|
|
123
|
+
contentChunk += consumePrefix(nextLt);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const tagEnd = findTagEnd(state.buffer, 1);
|
|
128
|
+
if (tagEnd === -1) {
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const rawTag = consumePrefix(tagEnd + 1);
|
|
133
|
+
const tagInfo = parseTagInfo(rawTag);
|
|
134
|
+
|
|
135
|
+
if (!tagInfo) {
|
|
136
|
+
contentChunk += rawTag;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (tagInfo.type === 'start') {
|
|
141
|
+
if (THINK_TAG_MAP.has(tagInfo.name)) {
|
|
142
|
+
state.currentThink = tagInfo.name;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
contentChunk += rawTag;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (tagInfo.type === 'end') {
|
|
151
|
+
contentChunk += rawTag;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
contentChunk += rawTag;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return { contentChunk, reasonChunk };
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const flushThinkState = (state) => {
|
|
162
|
+
if (!state || !state.buffer) {
|
|
163
|
+
return { contentChunk: '', reasonChunk: '' };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const remaining = state.buffer;
|
|
167
|
+
state.buffer = '';
|
|
168
|
+
|
|
169
|
+
if (state.currentThink) {
|
|
170
|
+
state.currentThink = null;
|
|
171
|
+
return { contentChunk: '', reasonChunk: remaining };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return { contentChunk: remaining, reasonChunk: '' };
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const splitThinkContent = (text = '') => {
|
|
178
|
+
if (!text) {
|
|
179
|
+
return { content: '', reasoning: '' };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const state = createThinkParserState();
|
|
183
|
+
let content = '';
|
|
184
|
+
let reasoning = '';
|
|
185
|
+
|
|
186
|
+
const result = processThinkChunk(state, text);
|
|
187
|
+
content += result.contentChunk;
|
|
188
|
+
reasoning += result.reasonChunk;
|
|
189
|
+
|
|
190
|
+
const tail = flushThinkState(state);
|
|
191
|
+
content += tail.contentChunk;
|
|
192
|
+
reasoning += tail.reasonChunk;
|
|
193
|
+
|
|
194
|
+
return { content, reasoning };
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const summarizeReasoning = (text = '', maxLength = 100) => {
|
|
198
|
+
if (!text) return '';
|
|
199
|
+
const normalized = text.replace(/\s+/g, ' ').trim();
|
|
200
|
+
if (!normalized) return '';
|
|
201
|
+
if (normalized.length > maxLength) {
|
|
202
|
+
return normalized.substring(0, maxLength) + '...';
|
|
203
|
+
}
|
|
204
|
+
return normalized;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
module.exports = {
|
|
208
|
+
THINK_TAGS,
|
|
209
|
+
createThinkParserState,
|
|
210
|
+
processThinkChunk,
|
|
211
|
+
flushThinkState,
|
|
212
|
+
splitThinkContent,
|
|
213
|
+
summarizeReasoning
|
|
214
|
+
};
|