naiad-cli 0.2.51 → 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.
package/dist/index.js CHANGED
File without changes
@@ -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
- if (assistantMsg.content === null && !assistantMsg.tool_calls) continue;
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naiad-cli",
3
- "version": "0.2.51",
3
+ "version": "0.2.56",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "naiad": "./dist/index.js"
@@ -12,6 +12,11 @@
12
12
  "engines": {
13
13
  "node": ">=20"
14
14
  },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/ericvanlare/Naiad2.0.git",
18
+ "directory": "mvp1/clients/cli"
19
+ },
15
20
  "publishConfig": {
16
21
  "access": "public"
17
22
  },