@askalf/dario 5.5.51 → 5.5.52

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.
Files changed (2) hide show
  1. package/dist/cc-template.js +43 -29
  2. package/package.json +1 -1
@@ -1584,6 +1584,41 @@ export function buildCCRequest(clientBody, billingTag, cacheControl, identity, o
1584
1584
  const messages = clientBody.messages || [];
1585
1585
  const clientTools = clientBody.tools;
1586
1586
  const stream = clientBody.stream ?? false;
1587
+ // ── Drop empty text blocks from history (ALL paths) ──
1588
+ // Upstream rejects empty text blocks OUTRIGHT — stamped or not — and treats
1589
+ // whitespace-only text the same way ("messages: text content blocks must be
1590
+ // non-empty"; with a breakpoint on it, "cache_control cannot be set for
1591
+ // empty text blocks"). One such block entering the transcript mid-run
1592
+ // therefore killed every subsequent request of the session (dario#1066).
1593
+ // Filtering here fixes the REQUEST, which no breakpoint guard can: skipping
1594
+ // the stamp still leaves the illegal block on the wire.
1595
+ //
1596
+ // Sits ABOVE the genuine-CC early return on purpose. #1067 placed this
1597
+ // below it, where real Claude Code — the one client whose messages are
1598
+ // forwarded verbatim — never reached it, and the #1066 session-killer
1599
+ // survived on exactly the client it hurts most (dario#1077). An empty text
1600
+ // block is not a wire shape the client is authority over; it is a
1601
+ // guaranteed upstream 400. `messages` aliases clientBody.messages, so
1602
+ // these mutations reach the genuine-CC body, which spreads clientBody.
1603
+ for (const msg of messages) {
1604
+ if (!Array.isArray(msg.content))
1605
+ continue;
1606
+ msg.content = msg.content.filter((b) => !(b.type === 'text' && (typeof b.text !== 'string' || b.text.trim() === '')));
1607
+ }
1608
+ // A USER turn left with no blocks is dropped — but only MID-conversation,
1609
+ // where the API combines the now-adjacent same-role turns and where the
1610
+ // #1066 session-killer lives (the empty turn sits in history, so every
1611
+ // later request carries it). The FINAL turn is deliberately left in place
1612
+ // per the dario#1033 decision below: popping it would expose the assistant
1613
+ // turn behind it and convert an honest "content must contain at least one
1614
+ // block" into a misleading prefill rejection. Hoisted with the filter
1615
+ // (dario#1077): removing a block can empty a turn on any path.
1616
+ for (let i = messages.length - 2; i >= 0; i--) {
1617
+ const m = messages[i];
1618
+ if (m.role === 'user' && Array.isArray(m.content) && m.content.length === 0) {
1619
+ messages.splice(i, 1);
1620
+ }
1621
+ }
1587
1622
  // ── Genuine Claude Code client → byte-faithful passthrough ──
1588
1623
  // A real CC request already IS the CC wire shape. Replacing its system
1589
1624
  // prompt with the template (prepending ~25KB per request shape) and
@@ -1600,9 +1635,11 @@ export function buildCCRequest(clientBody, billingTag, cacheControl, identity, o
1600
1635
  // here, conversation in applyCcPromptCaching) so the 4-breakpoint
1601
1636
  // budget stays deterministic.
1602
1637
  // Messages, thinking, effort, max_tokens, top-level key order: untouched —
1603
- // the client is the authority on its own wire shape. Outranks the
1604
- // tool-mode flags: those configure how NON-CC clients are dressed up as
1605
- // CC, which a genuine CC client doesn't need.
1638
+ // the client is the authority on its own wire shape. One exception, the
1639
+ // empty-text filter above (dario#1077): a guaranteed upstream 400 is a
1640
+ // defect, not a wire-shape preference. Outranks the tool-mode flags: those
1641
+ // configure how NON-CC clients are dressed up as CC, which a genuine CC
1642
+ // client doesn't need.
1606
1643
  if (isGenuineCCClient(clientBody)) {
1607
1644
  const clientSystem = clientBody.system;
1608
1645
  const system = clientSystem.map((b, i) => {
@@ -1677,32 +1714,9 @@ export function buildCCRequest(clientBody, billingTag, cacheControl, identity, o
1677
1714
  }
1678
1715
  }
1679
1716
  }
1680
- // ── Drop empty text blocks from history ──
1681
- // Upstream rejects empty text blocks OUTRIGHT stamped or not and treats
1682
- // whitespace-only text the same way ("messages: text content blocks must be
1683
- // non-empty"; with a breakpoint on it, "cache_control cannot be set for
1684
- // empty text blocks"). One such block entering the transcript mid-run
1685
- // therefore killed every subsequent request of the session (dario#1066).
1686
- // Filtering here fixes the REQUEST, which no breakpoint guard can: skipping
1687
- // the stamp still leaves the illegal block on the wire.
1688
- for (const msg of messages) {
1689
- if (!Array.isArray(msg.content))
1690
- continue;
1691
- msg.content = msg.content.filter((b) => !(b.type === 'text' && (typeof b.text !== 'string' || b.text.trim() === '')));
1692
- }
1693
- // A USER turn left with no blocks is dropped — but only MID-conversation,
1694
- // where the API combines the now-adjacent same-role turns and where the
1695
- // #1066 session-killer lives (the empty turn sits in history, so every
1696
- // later request carries it). The FINAL turn is deliberately left in place
1697
- // per the dario#1033 decision below: popping it would expose the assistant
1698
- // turn behind it and convert an honest "content must contain at least one
1699
- // block" into a misleading prefill rejection.
1700
- for (let i = messages.length - 2; i >= 0; i--) {
1701
- const m = messages[i];
1702
- if (m.role === 'user' && Array.isArray(m.content) && m.content.length === 0) {
1703
- messages.splice(i, 1);
1704
- }
1705
- }
1717
+ // (Empty text blocks and the mid-conversation empty-user-turn drop moved
1718
+ // above the genuine-CC branchdario#1077. Only the thinking strip stays
1719
+ // path-local: genuine CC forwards its signed thinking verbatim.)
1706
1720
  // ── Drop trailing empty turns ──
1707
1721
  // An assistant turn that was thinking-only before the strip above becomes
1708
1722
  // content: []. Forwarding that shape makes Anthropic interpret the request
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "5.5.51",
3
+ "version": "5.5.52",
4
4
  "description": "Use your Claude Pro/Max subscription in any tool — Cursor, Cline, Aider, the Agent SDK, your scripts — at subscription pricing, not per-token API bills. One local Anthropic + OpenAI-compatible endpoint.",
5
5
  "type": "module",
6
6
  "bin": {