naiad-cli 0.2.55 → 0.2.56
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.
|
@@ -282,6 +282,20 @@ export default function (pi: ExtensionAPI) {
|
|
|
282
282
|
assistantMsg.content = textBlocks.map((b) => b.text).join("");
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
// Round-trip thinking/reasoning blocks
|
|
286
|
+
const thinkingBlocks = msg.content.filter((b: any) => b.type === "thinking" && b.thinking?.trim());
|
|
287
|
+
if (thinkingBlocks.length > 0) {
|
|
288
|
+
// Prefer raw reasoning_details if stored (preserves structure for models that need it)
|
|
289
|
+
const rawDetails = thinkingBlocks.flatMap((b: any) => b.rawReasoningDetails || []);
|
|
290
|
+
if (rawDetails.length > 0) {
|
|
291
|
+
assistantMsg.reasoning_details = rawDetails;
|
|
292
|
+
} else {
|
|
293
|
+
// Fall back to flattened reasoning_content string
|
|
294
|
+
const reasoningText = thinkingBlocks.map((b: any) => b.thinking).join("\n");
|
|
295
|
+
assistantMsg.reasoning_content = reasoningText;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
285
299
|
const toolCalls = msg.content.filter((b): b is ToolCall => b.type === "toolCall");
|
|
286
300
|
if (toolCalls.length > 0) {
|
|
287
301
|
assistantMsg.tool_calls = toolCalls.map((tc) => ({
|
|
@@ -294,8 +308,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
294
308
|
}));
|
|
295
309
|
}
|
|
296
310
|
|
|
297
|
-
// Skip empty assistant messages
|
|
298
|
-
|
|
311
|
+
// Skip truly empty assistant messages (but keep thinking-only or tool-only)
|
|
312
|
+
const hasReasoning = assistantMsg.reasoning_details || assistantMsg.reasoning_content;
|
|
313
|
+
if (assistantMsg.content === null && !assistantMsg.tool_calls && !hasReasoning) continue;
|
|
299
314
|
messages.push(assistantMsg);
|
|
300
315
|
} else if (msg.role === "toolResult") {
|
|
301
316
|
const textResult = msg.content
|
|
@@ -436,6 +451,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
436
451
|
toolCall: block as ToolCall,
|
|
437
452
|
partial: output,
|
|
438
453
|
});
|
|
454
|
+
} else if (block.type === "thinking") {
|
|
455
|
+
stream.push({
|
|
456
|
+
type: "thinking_end",
|
|
457
|
+
contentIndex: blockIndex(),
|
|
458
|
+
content: block.thinking,
|
|
459
|
+
partial: output,
|
|
460
|
+
});
|
|
439
461
|
}
|
|
440
462
|
};
|
|
441
463
|
|
|
@@ -471,6 +493,40 @@ export default function (pi: ExtensionAPI) {
|
|
|
471
493
|
}
|
|
472
494
|
}
|
|
473
495
|
|
|
496
|
+
// Handle reasoning/thinking deltas FIRST (reasoning precedes content/tool_calls)
|
|
497
|
+
// OpenRouter normalized format: reasoning_details array
|
|
498
|
+
const reasoningDetails = choice.delta?.reasoning_details;
|
|
499
|
+
if (reasoningDetails && Array.isArray(reasoningDetails)) {
|
|
500
|
+
for (const detail of reasoningDetails) {
|
|
501
|
+
const reasoningText = detail.text ?? detail.summary ?? "";
|
|
502
|
+
if (!reasoningText) continue;
|
|
503
|
+
|
|
504
|
+
if (!currentBlock || currentBlock.type !== "thinking") {
|
|
505
|
+
finishCurrentBlock(currentBlock);
|
|
506
|
+
currentBlock = { type: "thinking", thinking: "", rawReasoningDetails: [] };
|
|
507
|
+
output.content.push(currentBlock);
|
|
508
|
+
stream.push({ type: "thinking_start", contentIndex: blockIndex(), partial: output });
|
|
509
|
+
}
|
|
510
|
+
currentBlock.thinking += reasoningText;
|
|
511
|
+
// Accumulate raw details verbatim for lossless round-tripping
|
|
512
|
+
currentBlock.rawReasoningDetails.push(detail);
|
|
513
|
+
stream.push({ type: "thinking_delta", contentIndex: blockIndex(), delta: reasoningText, partial: output });
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Legacy reasoning/reasoning_content string field (skip if array format already handled)
|
|
518
|
+
const reasoningStr = choice.delta?.reasoning ?? choice.delta?.reasoning_content;
|
|
519
|
+
if (!(reasoningDetails?.length > 0) && reasoningStr && typeof reasoningStr === "string") {
|
|
520
|
+
if (!currentBlock || currentBlock.type !== "thinking") {
|
|
521
|
+
finishCurrentBlock(currentBlock);
|
|
522
|
+
currentBlock = { type: "thinking", thinking: "" };
|
|
523
|
+
output.content.push(currentBlock);
|
|
524
|
+
stream.push({ type: "thinking_start", contentIndex: blockIndex(), partial: output });
|
|
525
|
+
}
|
|
526
|
+
currentBlock.thinking += reasoningStr;
|
|
527
|
+
stream.push({ type: "thinking_delta", contentIndex: blockIndex(), delta: reasoningStr, partial: output });
|
|
528
|
+
}
|
|
529
|
+
|
|
474
530
|
// Handle text content delta
|
|
475
531
|
const delta = choice.delta?.content;
|
|
476
532
|
if (delta) {
|