@miphamai/cli 0.6.0 → 0.6.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miphamai/cli",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Mipham Code — Multi-model open-core intelligent coding terminal by MiphamAI",
5
5
  "keywords": [
6
6
  "ai",
@@ -290,6 +290,7 @@ export class QueryEngine {
290
290
  yield { type: 'stop' }
291
291
  return
292
292
  }
293
+ yield { type: 'error', error: String(err) }
293
294
  return
294
295
  }
295
296
 
@@ -150,30 +150,100 @@ export class OpenAICompatProvider implements ProviderInstance {
150
150
  }
151
151
  }
152
152
 
153
- private convertMessages(
154
- messages: Message[],
155
- systemPrompt?: string,
156
- ): { role: string; content: string | unknown[] }[] {
157
- const result: { role: string; content: string | unknown[] }[] = []
153
+ private convertMessages(messages: Message[], systemPrompt?: string): Record<string, unknown>[] {
154
+ const result: Record<string, unknown>[] = []
158
155
 
159
156
  if (systemPrompt) {
160
157
  result.push({ role: 'system', content: systemPrompt })
161
158
  }
162
159
 
163
- for (const msg of messages) {
160
+ for (let i = 0; i < messages.length; i++) {
161
+ const msg = messages[i]!
162
+ if (!msg) continue
163
+
164
+ // ── String content ──
164
165
  if (typeof msg.content === 'string') {
166
+ // Combine: assistant text + next assistant message with tool_use blocks
167
+ const next: Message | undefined = messages[i + 1]
168
+ if (
169
+ msg.role === 'assistant' &&
170
+ msg.content.length > 0 &&
171
+ next &&
172
+ next.role === 'assistant' &&
173
+ typeof next.content !== 'string' &&
174
+ next.content.some((b) => b.type === 'tool_use')
175
+ ) {
176
+ const toolUses = next.content.filter((b) => b.type === 'tool_use')
177
+ result.push({
178
+ role: 'assistant',
179
+ content: msg.content,
180
+ tool_calls: toolUses.map((tu) => ({
181
+ id: tu.id,
182
+ type: 'function',
183
+ function: {
184
+ name: tu.name,
185
+ arguments: JSON.stringify(tu.input),
186
+ },
187
+ })),
188
+ })
189
+ i++ // skip the next message (consumed)
190
+ continue
191
+ }
192
+
165
193
  result.push({ role: msg.role, content: msg.content })
166
- } else {
167
- const parts: unknown[] = []
168
- for (const block of msg.content) {
169
- if (block.type === 'text') {
170
- parts.push({ type: 'text', text: block.text })
171
- } else if (block.type === 'image_url') {
172
- parts.push({ type: 'image_url', image_url: block.image_url })
173
- }
194
+ continue
195
+ }
196
+
197
+ // ── ContentBlock[] ──
198
+ const blocks = msg.content
199
+ const toolUses = blocks.filter((b) => b.type === 'tool_use')
200
+ const toolResults = blocks.filter((b) => b.type === 'tool_result')
201
+
202
+ // ── Assistant tool_use → OpenAI tool_calls ──
203
+ if (toolUses.length > 0 && msg.role === 'assistant') {
204
+ const textContent =
205
+ blocks
206
+ .filter((b) => b.type === 'text')
207
+ .map((b) => (b.type === 'text' ? b.text : ''))
208
+ .join('') || null
209
+
210
+ result.push({
211
+ role: 'assistant',
212
+ content: textContent,
213
+ tool_calls: toolUses.map((tu) => ({
214
+ id: tu.id,
215
+ type: 'function',
216
+ function: {
217
+ name: tu.name,
218
+ arguments: JSON.stringify(tu.input),
219
+ },
220
+ })),
221
+ })
222
+ continue
223
+ }
224
+
225
+ // ── Tool result → OpenAI tool role ──
226
+ if (toolResults.length > 0) {
227
+ for (const tr of toolResults) {
228
+ result.push({
229
+ role: 'tool',
230
+ tool_call_id: tr.tool_use_id,
231
+ content: tr.content,
232
+ })
233
+ }
234
+ continue
235
+ }
236
+
237
+ // ── Regular content blocks (text, image) ──
238
+ const parts: unknown[] = []
239
+ for (const block of blocks) {
240
+ if (block.type === 'text') {
241
+ parts.push({ type: 'text', text: block.text })
242
+ } else if (block.type === 'image_url') {
243
+ parts.push({ type: 'image_url', image_url: block.image_url })
174
244
  }
175
- result.push({ role: msg.role, content: parts })
176
245
  }
246
+ result.push({ role: msg.role, content: parts })
177
247
  }
178
248
 
179
249
  return result