@miphamai/cli 0.6.2 → 0.6.3
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/package.json +1 -1
- package/src/core/engine.ts +38 -8
- package/src/providers/openai-compat.ts +26 -9
- package/src/shared/types.ts +4 -0
package/package.json
CHANGED
package/src/core/engine.ts
CHANGED
|
@@ -140,6 +140,7 @@ export class QueryEngine {
|
|
|
140
140
|
const toolDefs = this.getToolDefinitions()
|
|
141
141
|
|
|
142
142
|
let assistantContent = ''
|
|
143
|
+
let reasoningContent = ''
|
|
143
144
|
const toolUses: Array<{ id: string; name: string; input: Record<string, unknown> }> = []
|
|
144
145
|
|
|
145
146
|
// Stream model response
|
|
@@ -162,6 +163,10 @@ export class QueryEngine {
|
|
|
162
163
|
assistantContent += chunk.content
|
|
163
164
|
}
|
|
164
165
|
|
|
166
|
+
if (chunk.reasoning_content) {
|
|
167
|
+
reasoningContent += chunk.reasoning_content
|
|
168
|
+
}
|
|
169
|
+
|
|
165
170
|
if (chunk.type === 'tool_use' && chunk.toolUse) {
|
|
166
171
|
toolUses.push({
|
|
167
172
|
id: chunk.toolUse.id,
|
|
@@ -172,16 +177,26 @@ export class QueryEngine {
|
|
|
172
177
|
|
|
173
178
|
if (chunk.type === 'stop') {
|
|
174
179
|
// Add assistant response to context
|
|
175
|
-
if (assistantContent) {
|
|
176
|
-
|
|
180
|
+
if (assistantContent || reasoningContent) {
|
|
181
|
+
const msg: import('../shared/types').Message = {
|
|
182
|
+
role: 'assistant',
|
|
183
|
+
content: assistantContent || '',
|
|
184
|
+
}
|
|
185
|
+
if (reasoningContent) msg.reasoning_content = reasoningContent
|
|
186
|
+
this.context.addMessage(msg)
|
|
177
187
|
}
|
|
178
188
|
}
|
|
179
189
|
}
|
|
180
190
|
} catch (err) {
|
|
181
191
|
if (isAbortError(err)) {
|
|
182
192
|
// User interrupted — keep partial content, stop gracefully
|
|
183
|
-
if (assistantContent) {
|
|
184
|
-
|
|
193
|
+
if (assistantContent || reasoningContent) {
|
|
194
|
+
const msg: import('../shared/types').Message = {
|
|
195
|
+
role: 'assistant',
|
|
196
|
+
content: assistantContent || '',
|
|
197
|
+
}
|
|
198
|
+
if (reasoningContent) msg.reasoning_content = reasoningContent
|
|
199
|
+
this.context.addMessage(msg)
|
|
185
200
|
}
|
|
186
201
|
yield { type: 'stop' }
|
|
187
202
|
return
|
|
@@ -259,6 +274,7 @@ export class QueryEngine {
|
|
|
259
274
|
const messages = this.context.getMessages()
|
|
260
275
|
|
|
261
276
|
let assistantContent = ''
|
|
277
|
+
let reasoningContent = ''
|
|
262
278
|
const toolUses: Array<{ id: string; name: string; input: Record<string, unknown> }> = []
|
|
263
279
|
|
|
264
280
|
try {
|
|
@@ -274,6 +290,10 @@ export class QueryEngine {
|
|
|
274
290
|
if (chunk.type === 'error') return
|
|
275
291
|
if (chunk.type === 'text' && chunk.content) assistantContent += chunk.content
|
|
276
292
|
|
|
293
|
+
if (chunk.reasoning_content) {
|
|
294
|
+
reasoningContent += chunk.reasoning_content
|
|
295
|
+
}
|
|
296
|
+
|
|
277
297
|
if (chunk.type === 'tool_use' && chunk.toolUse) {
|
|
278
298
|
toolUses.push({
|
|
279
299
|
id: chunk.toolUse.id,
|
|
@@ -284,8 +304,13 @@ export class QueryEngine {
|
|
|
284
304
|
}
|
|
285
305
|
} catch (err) {
|
|
286
306
|
if (isAbortError(err)) {
|
|
287
|
-
if (assistantContent) {
|
|
288
|
-
|
|
307
|
+
if (assistantContent || reasoningContent) {
|
|
308
|
+
const msg: import('../shared/types').Message = {
|
|
309
|
+
role: 'assistant',
|
|
310
|
+
content: assistantContent || '',
|
|
311
|
+
}
|
|
312
|
+
if (reasoningContent) msg.reasoning_content = reasoningContent
|
|
313
|
+
this.context.addMessage(msg)
|
|
289
314
|
}
|
|
290
315
|
yield { type: 'stop' }
|
|
291
316
|
return
|
|
@@ -294,8 +319,13 @@ export class QueryEngine {
|
|
|
294
319
|
return
|
|
295
320
|
}
|
|
296
321
|
|
|
297
|
-
if (assistantContent) {
|
|
298
|
-
|
|
322
|
+
if (assistantContent || reasoningContent) {
|
|
323
|
+
const msg: import('../shared/types').Message = {
|
|
324
|
+
role: 'assistant',
|
|
325
|
+
content: assistantContent || '',
|
|
326
|
+
}
|
|
327
|
+
if (reasoningContent) msg.reasoning_content = reasoningContent
|
|
328
|
+
this.context.addMessage(msg)
|
|
299
329
|
}
|
|
300
330
|
|
|
301
331
|
// No more tool calls — fire Stop hook and potentially continue
|
|
@@ -44,8 +44,9 @@ export class OpenAICompatProvider implements ProviderInstance {
|
|
|
44
44
|
const decoder = new TextDecoder()
|
|
45
45
|
let buffer = ''
|
|
46
46
|
|
|
47
|
-
// Track incremental tool calls across streaming deltas
|
|
47
|
+
// Track incremental tool calls and reasoning content across streaming deltas
|
|
48
48
|
const pendingToolCalls = new Map<number, { id: string; name: string; arguments: string }>()
|
|
49
|
+
let reasoningContent = ''
|
|
49
50
|
|
|
50
51
|
while (true) {
|
|
51
52
|
const { done, value } = await reader.read()
|
|
@@ -72,7 +73,7 @@ export class OpenAICompatProvider implements ProviderInstance {
|
|
|
72
73
|
},
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
|
-
yield { type: 'stop' }
|
|
76
|
+
yield { type: 'stop', reasoning_content: reasoningContent }
|
|
76
77
|
return
|
|
77
78
|
}
|
|
78
79
|
|
|
@@ -104,6 +105,10 @@ export class OpenAICompatProvider implements ProviderInstance {
|
|
|
104
105
|
yield { type: 'text', content: delta.content }
|
|
105
106
|
}
|
|
106
107
|
|
|
108
|
+
if (delta?.reasoning_content) {
|
|
109
|
+
reasoningContent += delta.reasoning_content
|
|
110
|
+
}
|
|
111
|
+
|
|
107
112
|
if (choice.finish_reason === 'tool_calls') {
|
|
108
113
|
// Emit fully accumulated tool calls
|
|
109
114
|
for (const [, tc] of pendingToolCalls) {
|
|
@@ -121,7 +126,7 @@ export class OpenAICompatProvider implements ProviderInstance {
|
|
|
121
126
|
}
|
|
122
127
|
|
|
123
128
|
if (choice.finish_reason === 'stop') {
|
|
124
|
-
yield { type: 'stop' }
|
|
129
|
+
yield { type: 'stop', reasoning_content: reasoningContent }
|
|
125
130
|
}
|
|
126
131
|
} catch {
|
|
127
132
|
// skip unparseable chunks
|
|
@@ -129,7 +134,7 @@ export class OpenAICompatProvider implements ProviderInstance {
|
|
|
129
134
|
}
|
|
130
135
|
}
|
|
131
136
|
|
|
132
|
-
yield { type: 'stop' }
|
|
137
|
+
yield { type: 'stop', reasoning_content: reasoningContent }
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
async listModels(): Promise<ModelInfo[]> {
|
|
@@ -174,7 +179,7 @@ export class OpenAICompatProvider implements ProviderInstance {
|
|
|
174
179
|
next.content.some((b) => b.type === 'tool_use')
|
|
175
180
|
) {
|
|
176
181
|
const toolUses = next.content.filter((b) => b.type === 'tool_use')
|
|
177
|
-
|
|
182
|
+
const combinedMsg: Record<string, unknown> = {
|
|
178
183
|
role: 'assistant',
|
|
179
184
|
content: msg.content,
|
|
180
185
|
tool_calls: toolUses.map((tu) => ({
|
|
@@ -185,12 +190,20 @@ export class OpenAICompatProvider implements ProviderInstance {
|
|
|
185
190
|
arguments: JSON.stringify(tu.input),
|
|
186
191
|
},
|
|
187
192
|
})),
|
|
188
|
-
}
|
|
193
|
+
}
|
|
194
|
+
if (msg.reasoning_content) {
|
|
195
|
+
combinedMsg.reasoning_content = msg.reasoning_content
|
|
196
|
+
}
|
|
197
|
+
result.push(combinedMsg)
|
|
189
198
|
i++ // skip the next message (consumed)
|
|
190
199
|
continue
|
|
191
200
|
}
|
|
192
201
|
|
|
193
|
-
|
|
202
|
+
const standaloneMsg: Record<string, unknown> = { role: msg.role, content: msg.content }
|
|
203
|
+
if (msg.role === 'assistant' && msg.reasoning_content) {
|
|
204
|
+
standaloneMsg.reasoning_content = msg.reasoning_content
|
|
205
|
+
}
|
|
206
|
+
result.push(standaloneMsg)
|
|
194
207
|
continue
|
|
195
208
|
}
|
|
196
209
|
|
|
@@ -207,7 +220,7 @@ export class OpenAICompatProvider implements ProviderInstance {
|
|
|
207
220
|
.map((b) => (b.type === 'text' ? b.text : ''))
|
|
208
221
|
.join('') || null
|
|
209
222
|
|
|
210
|
-
|
|
223
|
+
const toolUseMsg: Record<string, unknown> = {
|
|
211
224
|
role: 'assistant',
|
|
212
225
|
content: textContent,
|
|
213
226
|
tool_calls: toolUses.map((tu) => ({
|
|
@@ -218,7 +231,11 @@ export class OpenAICompatProvider implements ProviderInstance {
|
|
|
218
231
|
arguments: JSON.stringify(tu.input),
|
|
219
232
|
},
|
|
220
233
|
})),
|
|
221
|
-
}
|
|
234
|
+
}
|
|
235
|
+
if (msg.reasoning_content) {
|
|
236
|
+
toolUseMsg.reasoning_content = msg.reasoning_content
|
|
237
|
+
}
|
|
238
|
+
result.push(toolUseMsg)
|
|
222
239
|
continue
|
|
223
240
|
}
|
|
224
241
|
|
package/src/shared/types.ts
CHANGED
|
@@ -46,6 +46,8 @@ export type ContentBlock = TextContent | ImageContent | ToolUseContent | ToolRes
|
|
|
46
46
|
export interface Message {
|
|
47
47
|
role: 'system' | 'user' | 'assistant'
|
|
48
48
|
content: string | ContentBlock[]
|
|
49
|
+
/** DeepSeek reasoning tokens — must be passed back to the API in multi-turn conversations. */
|
|
50
|
+
reasoning_content?: string
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
// ── Tool Types ──
|
|
@@ -105,6 +107,8 @@ export interface StreamChunk {
|
|
|
105
107
|
toolUse?: ToolUseContent
|
|
106
108
|
tool_use_id?: string
|
|
107
109
|
error?: string
|
|
110
|
+
/** DeepSeek reasoning tokens accumulated during this stream. */
|
|
111
|
+
reasoning_content?: string
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
// ── Config Types ──
|