@askalf/dario 5.5.48 → 5.5.49
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/cc-template.d.ts +0 -32
- package/dist/cc-template.js +45 -1
- package/package.json +1 -1
package/dist/cc-template.d.ts
CHANGED
|
@@ -505,38 +505,6 @@ export declare const EXTENDED_CACHE_TTL_BETA = "extended-cache-ttl-2025-04-11";
|
|
|
505
505
|
* is off or the beta is already present.
|
|
506
506
|
*/
|
|
507
507
|
export declare function withForced1hBeta(beta: string, env?: Record<string, string | undefined>): string;
|
|
508
|
-
/**
|
|
509
|
-
* Place CC-style prompt-cache breakpoints on the conversation. The system
|
|
510
|
-
* prompt is already cached at build time (2 system breakpoints); this adds a
|
|
511
|
-
* rolling breakpoint on the last user message plus an anchor on the previous
|
|
512
|
-
* one — total 4, the Anthropic max.
|
|
513
|
-
*
|
|
514
|
-
* Placement mirrors a live capture of CC v2.1.203 (dario#678):
|
|
515
|
-
*
|
|
516
|
-
* - Tools carry NO breakpoint. Real CC sends its tool array unstamped —
|
|
517
|
-
* Anthropic renders tools -> system -> messages, so the system breakpoints
|
|
518
|
-
* already cache the tools prefix. Stamping the last tool (pre-4.8.142) both
|
|
519
|
-
* diverged from CC's wire shape and spent the fourth slot the conversation
|
|
520
|
-
* anchor below needs.
|
|
521
|
-
*
|
|
522
|
-
* - The rolling breakpoint goes on the last USER message, not the last
|
|
523
|
-
* message. CC skips trailing role:"system" injections (agent-type updates
|
|
524
|
-
* etc.); stamping "the last message" meant any turn ending in one wrote no
|
|
525
|
-
* conversation entry at all, and the next request re-paid the entire
|
|
526
|
-
* history as fresh input.
|
|
527
|
-
*
|
|
528
|
-
* - The previous user message is anchored too. Anthropic's cache lookup
|
|
529
|
-
* walks back at most ~20 content blocks from a breakpoint; one parallel-
|
|
530
|
-
* tool turn (N tool_use + N tool_result blocks) can exceed that alone, and
|
|
531
|
-
* the rolling breakpoint then can't reach the prior turn's entry — the
|
|
532
|
-
* whole conversation re-bills at cache-WRITE cost every fan-out turn,
|
|
533
|
-
* which is the dario#678 burn ("read every file" sessions draining the
|
|
534
|
-
* Max window ~10x faster than direct CC). The anchor sits exactly where
|
|
535
|
-
* the previous request's rolling breakpoint was, so the lookup hits it
|
|
536
|
-
* positionally with no walk-back.
|
|
537
|
-
*
|
|
538
|
-
* Exported for unit testing.
|
|
539
|
-
*/
|
|
540
508
|
export declare function applyCcPromptCaching(ccRequest: Record<string, unknown>, cacheControl: CacheControl): void;
|
|
541
509
|
/**
|
|
542
510
|
* Drop later tools whose exact name already appeared. Upstream rejects the
|
package/dist/cc-template.js
CHANGED
|
@@ -1446,6 +1446,13 @@ export function withForced1hBeta(beta, env = process.env) {
|
|
|
1446
1446
|
*
|
|
1447
1447
|
* Exported for unit testing.
|
|
1448
1448
|
*/
|
|
1449
|
+
/**
|
|
1450
|
+
* A text block upstream treats as empty. `cache_control` on one of these is a
|
|
1451
|
+
* hard 400, so breakpoint placement must skip them.
|
|
1452
|
+
*/
|
|
1453
|
+
function isEmptyTextBlock(block) {
|
|
1454
|
+
return block?.type === 'text' && (typeof block.text !== 'string' || block.text === '');
|
|
1455
|
+
}
|
|
1449
1456
|
export function applyCcPromptCaching(ccRequest, cacheControl) {
|
|
1450
1457
|
// Tools — strip any stray client breakpoints (they'd count against the
|
|
1451
1458
|
// 4-breakpoint budget) without mutating shared element objects
|
|
@@ -1475,7 +1482,18 @@ export function applyCcPromptCaching(ccRequest, cacheControl) {
|
|
|
1475
1482
|
if (!Array.isArray(msg.content) || msg.content.length === 0)
|
|
1476
1483
|
continue;
|
|
1477
1484
|
const blocks = msg.content;
|
|
1478
|
-
|
|
1485
|
+
// Walk back past empty text blocks. Upstream rejects the whole request
|
|
1486
|
+
// with 400 "cache_control cannot be set for empty text blocks", so a
|
|
1487
|
+
// trailing empty text block would otherwise kill every request from
|
|
1488
|
+
// that turn onward (dario#1066). A turn with nothing else to stamp is
|
|
1489
|
+
// skipped rather than stamped illegally — it keeps its cache entry via
|
|
1490
|
+
// the next turn's anchor.
|
|
1491
|
+
let bi = blocks.length - 1;
|
|
1492
|
+
while (bi >= 0 && isEmptyTextBlock(blocks[bi]))
|
|
1493
|
+
bi--;
|
|
1494
|
+
if (bi < 0)
|
|
1495
|
+
continue;
|
|
1496
|
+
blocks[bi] = { ...blocks[bi], cache_control: cacheControl };
|
|
1479
1497
|
stamped++;
|
|
1480
1498
|
}
|
|
1481
1499
|
}
|
|
@@ -1659,6 +1677,32 @@ export function buildCCRequest(clientBody, billingTag, cacheControl, identity, o
|
|
|
1659
1677
|
}
|
|
1660
1678
|
}
|
|
1661
1679
|
}
|
|
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
|
+
}
|
|
1662
1706
|
// ── Drop trailing empty turns ──
|
|
1663
1707
|
// An assistant turn that was thinking-only before the strip above becomes
|
|
1664
1708
|
// 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.
|
|
3
|
+
"version": "5.5.49",
|
|
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": {
|