agentfootprint 9.58.0 → 9.59.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/CLAUDE.md +1 -1
- package/dist/cache/cacheRecorder.js +154 -46
- package/dist/cache/cacheRecorder.js.map +1 -1
- package/dist/cache/index.js +20 -6
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/portUsage.js +47 -0
- package/dist/cache/portUsage.js.map +1 -0
- package/dist/cache/strategies/AnthropicCacheStrategy.js +5 -17
- package/dist/cache/strategies/AnthropicCacheStrategy.js.map +1 -1
- package/dist/cache/strategies/BedrockCacheStrategy.js +74 -58
- package/dist/cache/strategies/BedrockCacheStrategy.js.map +1 -1
- package/dist/cache/strategies/NoOpCacheStrategy.js +2 -1
- package/dist/cache/strategies/NoOpCacheStrategy.js.map +1 -1
- package/dist/cache/strategies/OpenAICacheStrategy.js +14 -13
- package/dist/cache/strategies/OpenAICacheStrategy.js.map +1 -1
- package/dist/core/Agent.js +7 -0
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +35 -1
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/buildAgentChart.js +27 -0
- package/dist/core/agent/buildAgentChart.js.map +1 -1
- package/dist/core/agent/buildDynamicAgentChart.js +45 -0
- package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/core/agent/stages/toolCalls.js +49 -3
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/slots/buildToolsSlot.js +27 -1
- package/dist/core/slots/buildToolsSlot.js.map +1 -1
- package/dist/doors/maps.js +7 -2
- package/dist/doors/maps.js.map +1 -1
- package/dist/esm/cache/cacheRecorder.d.ts +82 -36
- package/dist/esm/cache/cacheRecorder.js +154 -46
- package/dist/esm/cache/cacheRecorder.js.map +1 -1
- package/dist/esm/cache/index.d.ts +12 -7
- package/dist/esm/cache/index.js +13 -5
- package/dist/esm/cache/index.js.map +1 -1
- package/dist/esm/cache/portUsage.d.ts +30 -0
- package/dist/esm/cache/portUsage.js +43 -0
- package/dist/esm/cache/portUsage.js.map +1 -0
- package/dist/esm/cache/strategies/AnthropicCacheStrategy.d.ts +6 -3
- package/dist/esm/cache/strategies/AnthropicCacheStrategy.js +5 -17
- package/dist/esm/cache/strategies/AnthropicCacheStrategy.js.map +1 -1
- package/dist/esm/cache/strategies/BedrockCacheStrategy.d.ts +48 -19
- package/dist/esm/cache/strategies/BedrockCacheStrategy.js +74 -58
- package/dist/esm/cache/strategies/BedrockCacheStrategy.js.map +1 -1
- package/dist/esm/cache/strategies/NoOpCacheStrategy.d.ts +3 -2
- package/dist/esm/cache/strategies/NoOpCacheStrategy.js +2 -1
- package/dist/esm/cache/strategies/NoOpCacheStrategy.js.map +1 -1
- package/dist/esm/cache/strategies/OpenAICacheStrategy.d.ts +13 -2
- package/dist/esm/cache/strategies/OpenAICacheStrategy.js +14 -13
- package/dist/esm/cache/strategies/OpenAICacheStrategy.js.map +1 -1
- package/dist/esm/cache/types.d.ts +35 -7
- package/dist/esm/core/Agent.js +7 -0
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.js +35 -1
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/buildAgentChart.js +27 -0
- package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
- package/dist/esm/core/agent/buildDynamicAgentChart.js +45 -0
- package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/esm/core/agent/stages/toolCalls.d.ts +7 -0
- package/dist/esm/core/agent/stages/toolCalls.js +47 -1
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +5 -0
- package/dist/esm/core/slots/buildToolsSlot.js +27 -1
- package/dist/esm/core/slots/buildToolsSlot.js.map +1 -1
- package/dist/esm/doors/maps.d.ts +7 -2
- package/dist/esm/doors/maps.js +7 -2
- package/dist/esm/doors/maps.js.map +1 -1
- package/dist/esm/events/eventTail.d.ts +18 -0
- package/dist/esm/events/eventTail.js +4 -1
- package/dist/esm/events/eventTail.js.map +1 -1
- package/dist/esm/events/payloads.d.ts +28 -8
- package/dist/esm/integrity/disposition/ledger.d.ts +60 -0
- package/dist/esm/integrity/disposition/ledger.js +0 -0
- package/dist/esm/integrity/disposition/ledger.js.map +1 -0
- package/dist/esm/integrity/disposition/types.d.ts +60 -0
- package/dist/esm/integrity/disposition/types.js +19 -0
- package/dist/esm/integrity/disposition/types.js.map +1 -0
- package/dist/esm/{maps → lib}/claim/claim.d.ts +8 -4
- package/dist/esm/{maps → lib}/claim/claim.js +8 -4
- package/dist/esm/lib/claim/claim.js.map +1 -0
- package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js +45 -1
- package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
- package/dist/esm/lib/injection-engine/evaluator.js +10 -4
- package/dist/esm/lib/injection-engine/evaluator.js.map +1 -1
- package/dist/esm/maps/engagement/evidence.d.ts +48 -7
- package/dist/esm/maps/engagement/evidence.js +29 -11
- package/dist/esm/maps/engagement/evidence.js.map +1 -1
- package/dist/esm/maps/engagement/lease.d.ts +28 -6
- package/dist/esm/maps/engagement/lease.js +148 -13
- package/dist/esm/maps/engagement/lease.js.map +1 -1
- package/dist/esm/maps/engagement/parkCard.d.ts +48 -0
- package/dist/esm/maps/engagement/parkCard.js +88 -0
- package/dist/esm/maps/engagement/parkCard.js.map +1 -0
- package/dist/esm/maps/engagement/types.d.ts +138 -8
- package/dist/esm/maps/engagement/types.js +23 -1
- package/dist/esm/maps/engagement/types.js.map +1 -1
- package/dist/esm/recorders/observability/recordRun.d.ts +4 -0
- package/dist/esm/recorders/observability/recordRun.js +3 -0
- package/dist/esm/recorders/observability/recordRun.js.map +1 -1
- package/dist/esm/recorders/observability/recordingEnvelope.d.ts +17 -0
- package/dist/esm/recorders/observability/recordingEnvelope.js +23 -0
- package/dist/esm/recorders/observability/recordingEnvelope.js.map +1 -1
- package/dist/events/eventTail.js +4 -1
- package/dist/events/eventTail.js.map +1 -1
- package/dist/integrity/disposition/ledger.js +0 -0
- package/dist/integrity/disposition/ledger.js.map +1 -0
- package/dist/integrity/disposition/types.js +20 -0
- package/dist/integrity/disposition/types.js.map +1 -0
- package/dist/{maps → lib}/claim/claim.js +8 -4
- package/dist/lib/claim/claim.js.map +1 -0
- package/dist/lib/injection-engine/buildInjectionEngineSubflow.js +45 -1
- package/dist/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
- package/dist/lib/injection-engine/evaluator.js +10 -4
- package/dist/lib/injection-engine/evaluator.js.map +1 -1
- package/dist/maps/engagement/evidence.js +29 -11
- package/dist/maps/engagement/evidence.js.map +1 -1
- package/dist/maps/engagement/lease.js +148 -13
- package/dist/maps/engagement/lease.js.map +1 -1
- package/dist/maps/engagement/parkCard.js +92 -0
- package/dist/maps/engagement/parkCard.js.map +1 -0
- package/dist/maps/engagement/types.js +25 -0
- package/dist/maps/engagement/types.js.map +1 -1
- package/dist/recorders/observability/recordRun.js +3 -0
- package/dist/recorders/observability/recordRun.js.map +1 -1
- package/dist/recorders/observability/recordingEnvelope.js +23 -0
- package/dist/recorders/observability/recordingEnvelope.js.map +1 -1
- package/dist/types/cache/cacheRecorder.d.ts +82 -36
- package/dist/types/cache/cacheRecorder.d.ts.map +1 -1
- package/dist/types/cache/index.d.ts +12 -7
- package/dist/types/cache/index.d.ts.map +1 -1
- package/dist/types/cache/portUsage.d.ts +31 -0
- package/dist/types/cache/portUsage.d.ts.map +1 -0
- package/dist/types/cache/strategies/AnthropicCacheStrategy.d.ts +6 -3
- package/dist/types/cache/strategies/AnthropicCacheStrategy.d.ts.map +1 -1
- package/dist/types/cache/strategies/BedrockCacheStrategy.d.ts +48 -19
- package/dist/types/cache/strategies/BedrockCacheStrategy.d.ts.map +1 -1
- package/dist/types/cache/strategies/NoOpCacheStrategy.d.ts +3 -2
- package/dist/types/cache/strategies/NoOpCacheStrategy.d.ts.map +1 -1
- package/dist/types/cache/strategies/OpenAICacheStrategy.d.ts +13 -2
- package/dist/types/cache/strategies/OpenAICacheStrategy.d.ts.map +1 -1
- package/dist/types/cache/types.d.ts +35 -7
- package/dist/types/cache/types.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/stages/toolCalls.d.ts +7 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +5 -0
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/core/slots/buildToolsSlot.d.ts.map +1 -1
- package/dist/types/doors/maps.d.ts +7 -2
- package/dist/types/doors/maps.d.ts.map +1 -1
- package/dist/types/events/eventTail.d.ts +18 -0
- package/dist/types/events/eventTail.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +28 -8
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/integrity/disposition/ledger.d.ts +61 -0
- package/dist/types/integrity/disposition/ledger.d.ts.map +1 -0
- package/dist/types/integrity/disposition/types.d.ts +61 -0
- package/dist/types/integrity/disposition/types.d.ts.map +1 -0
- package/dist/types/{maps → lib}/claim/claim.d.ts +8 -4
- package/dist/types/lib/claim/claim.d.ts.map +1 -0
- package/dist/types/lib/injection-engine/buildInjectionEngineSubflow.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/evaluator.d.ts.map +1 -1
- package/dist/types/maps/engagement/evidence.d.ts +48 -7
- package/dist/types/maps/engagement/evidence.d.ts.map +1 -1
- package/dist/types/maps/engagement/lease.d.ts +28 -6
- package/dist/types/maps/engagement/lease.d.ts.map +1 -1
- package/dist/types/maps/engagement/parkCard.d.ts +49 -0
- package/dist/types/maps/engagement/parkCard.d.ts.map +1 -0
- package/dist/types/maps/engagement/types.d.ts +138 -8
- package/dist/types/maps/engagement/types.d.ts.map +1 -1
- package/dist/types/recorders/observability/recordRun.d.ts +4 -0
- package/dist/types/recorders/observability/recordRun.d.ts.map +1 -1
- package/dist/types/recorders/observability/recordingEnvelope.d.ts +17 -0
- package/dist/types/recorders/observability/recordingEnvelope.d.ts.map +1 -1
- package/package.json +3 -2
- package/dist/esm/maps/claim/claim.js.map +0 -1
- package/dist/maps/claim/claim.js.map +0 -1
- package/dist/types/maps/claim/claim.d.ts.map +0 -1
package/CLAUDE.md
CHANGED
|
@@ -43,7 +43,7 @@ not in this table, search `src/index.ts` for the nearest noun before writing cod
|
|
|
43
43
|
| letting the UI draw an artifact without the model naming a component | `registerArtifactComponent` (in the `agentfootprint-lens` package) | — | — |
|
|
44
44
|
| finding which tools the model keeps writing by hand | `agentfootprint.tools.code_run` + `codeShape` | `src/core/codeRunnerTool.ts` | 9.46.0 |
|
|
45
45
|
| a skill wrongly activated by a keyword staying loaded for the whole turn — suspending/parking a map's prompt + tools when its contribution goes unused, WITHOUT touching its cursor, and re-engaging it on evidence | `.maps()` + `advanceEngagement` + `agentfootprint.map.engaged/parked` + skip reason `'parked'` | `src/maps/` | 9.58.0 |
|
|
46
|
-
| a value that must say how it knows itself — an unknown count that can never render as zero | `Claim<T>` (`known`/`unknown`/`notApplicable`) | `src/
|
|
46
|
+
| a value that must say how it knows itself — an unknown count that can never render as zero | `Claim<T>` (`known`/`unknown`/`notApplicable`) | `src/lib/claim/claim.ts` | 9.58.0 |
|
|
47
47
|
| a tool answering "I looked and found nothing", routably | `absent` | `src/core/agent/coverage/absent.ts` | 9.43.0 |
|
|
48
48
|
| stating what a clean answer does NOT rule out | `coverage` | `src/core/agent/coverage/ledger.ts` | 9.43.0 |
|
|
49
49
|
| proving a session store really honours the port | `runSessionLifecycleConformance` | `src/hosting/conformance/` | 9.37.0 |
|
|
@@ -1,35 +1,72 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* cacheRecorder() —
|
|
3
|
+
* cacheRecorder() — the cache layer's meter.
|
|
4
4
|
*
|
|
5
5
|
* Subscribes to:
|
|
6
|
-
* - `FlowRecorder.onDecision` —
|
|
7
|
-
* (apply-markers / no-markers + the rule that fired + evidence
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* into CacheMetrics (cacheReadTokens / cacheWriteTokens / fresh).
|
|
6
|
+
* - `FlowRecorder.onDecision` — CacheGate routing decisions
|
|
7
|
+
* (apply-markers / no-markers + the rule that fired + evidence from
|
|
8
|
+
* `decide()`).
|
|
9
|
+
* - `agentfootprint.stream.llm_end` — reads that event's `usage` (the PORT
|
|
10
|
+
* shape: `{ input, output, cacheRead?, cacheWrite? }`) and asks the
|
|
11
|
+
* agent's `CacheStrategy.extractMetrics` what is known about it.
|
|
13
12
|
*
|
|
14
|
-
* Produces:
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* - per-iteration `agentfootprint.cache.metrics` events (hit/write
|
|
18
|
-
* token counts + estimated dollars via PricingTable) — for
|
|
19
|
-
* dashboards
|
|
20
|
-
* - a turn-end summary printable via `recorder.report()` —
|
|
21
|
-
* numeric tally plus dollars saved
|
|
13
|
+
* Produces: a per-turn report via `recorder.report()` — token tallies, hit
|
|
14
|
+
* rate and dollar estimates, each carried as a `Claim` so an UNMEASURED turn
|
|
15
|
+
* can never render as a zero one.
|
|
22
16
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
17
|
+
* ── Why every number here is a Claim (9.59.0) ─────────────────────────
|
|
18
|
+
* The shipped 9.58.0 meter reported `hitRate: 0` for a 20-call turn that hit
|
|
19
|
+
* cache on every call. Two faults, and the second is why the first went
|
|
20
|
+
* unnoticed for so long: (1) the strategies parsed RAW WIRE field names off a
|
|
21
|
+
* value that carries the PORT shape, so every field read `undefined`; (2) the
|
|
22
|
+
* report typed its aggregates as bare `number`, so "nobody measured" and
|
|
23
|
+
* "measured, and it was zero" rendered identically. Fixing (1) alone would
|
|
24
|
+
* have left a meter that still cannot say "unmeasured" — hence `Claim<T>`,
|
|
25
|
+
* plus `measuredIterations` / `unmeasuredIterations` so a rate computed from
|
|
26
|
+
* 3 of 20 calls states its own denominator.
|
|
27
|
+
*
|
|
28
|
+
* Read the number through `isKnown(report.hitRate)` (or `describeClaim` for a
|
|
29
|
+
* one-line render). There is deliberately no door that hands you a bare
|
|
30
|
+
* number without your having branched.
|
|
31
|
+
*
|
|
32
|
+
* ── And an unknown carries ITS OWN reason (9.59.1) ────────────────────
|
|
33
|
+
* 9.59.0 enforced that law per call and then broke it in `report()`, which
|
|
34
|
+
* hardcoded "the provider reported no cache fields" for the whole turn no
|
|
35
|
+
* matter what the rows said. With no strategy passed and a provider that DID
|
|
36
|
+
* report cache fields, the row said "nothing read the usage" and the summary
|
|
37
|
+
* blamed the provider — pointing the reader away from their actual mistake.
|
|
38
|
+
* The summary now carries the rows' own reasons, and says so plainly when the
|
|
39
|
+
* rows disagree rather than picking one.
|
|
40
|
+
*
|
|
41
|
+
* ── What this recorder does NOT do ────────────────────────────────────
|
|
42
|
+
* It emits no events. (Earlier prose here promised per-iteration
|
|
43
|
+
* `agentfootprint.cache.applied` / `agentfootprint.cache.metrics` events;
|
|
44
|
+
* neither name has ever existed in the event registry and no `typedEmit` has
|
|
45
|
+
* ever been in this file. The prose was the bug.)
|
|
46
|
+
*
|
|
47
|
+
* It does not write `scope.recentHitRate` back into agent state either, so
|
|
48
|
+
* CacheGate's hit-rate-floor rule never fires on its own — the loop is
|
|
49
|
+
* severed at both ends (the key is seeded `undefined` and written by
|
|
50
|
+
* nothing). Recorders do not write to chart scope, so closing that loop needs
|
|
51
|
+
* an agent-side accessor convention; it is separable work from measuring the
|
|
52
|
+
* number, which is what this file now does.
|
|
28
53
|
*/
|
|
29
54
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
55
|
exports.cacheRecorder = void 0;
|
|
31
56
|
const trace_1 = require("footprintjs/trace");
|
|
32
57
|
const conventions_js_1 = require("../conventions.js");
|
|
58
|
+
const claim_js_1 = require("../lib/claim/claim.js");
|
|
59
|
+
/**
|
|
60
|
+
* How many distinct reasons a disagreeing summary spells out before it
|
|
61
|
+
* switches to counting the rest. A summary sentence must stay readable.
|
|
62
|
+
*/
|
|
63
|
+
const MAX_LISTED_REASONS = 3;
|
|
64
|
+
/** The metrics of a row already filtered by `isKnown`. Narrowing helper only. */
|
|
65
|
+
function valueOfMetrics(entry) {
|
|
66
|
+
return (0, claim_js_1.isKnown)(entry.metrics)
|
|
67
|
+
? entry.metrics.value
|
|
68
|
+
: { cacheReadTokens: 0, cacheWriteTokens: 0, freshInputTokens: 0 };
|
|
69
|
+
}
|
|
33
70
|
function cacheRecorder(options = {}) {
|
|
34
71
|
const perIter = [];
|
|
35
72
|
let lastDecision;
|
|
@@ -64,8 +101,11 @@ function cacheRecorder(options = {}) {
|
|
|
64
101
|
if (event.type !== 'agentfootprint.stream.llm_end')
|
|
65
102
|
return;
|
|
66
103
|
iterationCounter++;
|
|
104
|
+
// The PORT shape, which is the only shape this event has ever carried.
|
|
67
105
|
const usage = event.payload.usage;
|
|
68
|
-
const metrics = options.strategy
|
|
106
|
+
const metrics = options.strategy === undefined
|
|
107
|
+
? (0, claim_js_1.unknown)('no CacheStrategy was given to cacheRecorder(), so nothing read the usage')
|
|
108
|
+
: options.strategy.extractMetrics(usage);
|
|
69
109
|
const branch = lastDecision?.branch ?? 'apply-markers';
|
|
70
110
|
// Compute dollar math:
|
|
71
111
|
// spent = freshInput * inputPrice
|
|
@@ -73,21 +113,34 @@ function cacheRecorder(options = {}) {
|
|
|
73
113
|
// + cacheWrite * cacheWritePrice
|
|
74
114
|
// no-cache cost = (freshInput + cacheRead + cacheWrite) * inputPrice
|
|
75
115
|
// saved = no-cache cost - spent
|
|
76
|
-
let dollarsSpent
|
|
77
|
-
let savedVsNoCache
|
|
78
|
-
if (metrics) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const noCacheCost = dollars(
|
|
84
|
-
|
|
116
|
+
let dollarsSpent;
|
|
117
|
+
let savedVsNoCache;
|
|
118
|
+
if ((0, claim_js_1.isKnown)(metrics)) {
|
|
119
|
+
const m = metrics.value;
|
|
120
|
+
const spent = dollars(m.freshInputTokens, 'input') +
|
|
121
|
+
dollars(m.cacheReadTokens, 'cacheRead') +
|
|
122
|
+
dollars(m.cacheWriteTokens, 'cacheWrite');
|
|
123
|
+
const noCacheCost = dollars(m.freshInputTokens + m.cacheReadTokens + m.cacheWriteTokens, 'input');
|
|
124
|
+
const ev = options.pricing === undefined
|
|
125
|
+
? 'measured tokens, but no PricingTable was given — every price is 0'
|
|
126
|
+
: 'measured tokens priced with the given PricingTable';
|
|
127
|
+
dollarsSpent = (0, claim_js_1.known)(spent, ev);
|
|
128
|
+
savedVsNoCache = (0, claim_js_1.known)(noCacheCost - spent, ev);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// No tokens measured ⇒ no dollars. Carrying the metrics claim's own
|
|
132
|
+
// reason forward is what keeps a $0 estimate from reading as "free".
|
|
133
|
+
const why = metrics.kind === 'unknown'
|
|
134
|
+
? metrics.reason
|
|
135
|
+
: `no cache tokens are measurable here — ${metrics.evidence}`;
|
|
136
|
+
dollarsSpent = (0, claim_js_1.unknown)(why);
|
|
137
|
+
savedVsNoCache = (0, claim_js_1.unknown)(why);
|
|
85
138
|
}
|
|
86
139
|
const entry = {
|
|
87
140
|
iteration: iterationCounter,
|
|
88
141
|
branch,
|
|
89
142
|
...(lastDecision?.rule !== undefined && { rule: lastDecision.rule }),
|
|
90
|
-
|
|
143
|
+
metrics,
|
|
91
144
|
dollarsSpent,
|
|
92
145
|
dollarsSavedVsNoCache: savedVsNoCache,
|
|
93
146
|
};
|
|
@@ -97,23 +150,78 @@ function cacheRecorder(options = {}) {
|
|
|
97
150
|
report() {
|
|
98
151
|
const apply = perIter.filter((p) => p.branch === 'apply-markers').length;
|
|
99
152
|
const skip = perIter.filter((p) => p.branch === 'no-markers').length;
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
153
|
+
const measured = perIter.filter((p) => (0, claim_js_1.isKnown)(p.metrics));
|
|
154
|
+
const n = measured.length;
|
|
155
|
+
const total = perIter.length;
|
|
156
|
+
// ONE reason, stated once, reused by every claim below — so a reader
|
|
157
|
+
// who prints any single field learns why the whole report is empty.
|
|
158
|
+
//
|
|
159
|
+
// ── The summary CARRIES the rows' reasons; it never invents one (9.59.1)
|
|
160
|
+
// 9.59.0 hardcoded 'the provider reported no cache fields' here. That
|
|
161
|
+
// sentence is a fabrication whenever the rows said something else — most
|
|
162
|
+
// painfully when no CacheStrategy was passed and the provider DID report
|
|
163
|
+
// cacheRead/cacheWrite: the rows said "nothing read the usage", and the
|
|
164
|
+
// summary blamed the provider for the caller's own omission. An unknown
|
|
165
|
+
// must carry ITS OWN reason. That is the law this file exists to
|
|
166
|
+
// enforce, and this is it applied to the summary too.
|
|
167
|
+
const unmeasured = perIter.filter((p) => !(0, claim_js_1.isKnown)(p.metrics));
|
|
168
|
+
const reasons = [];
|
|
169
|
+
for (const row of unmeasured) {
|
|
170
|
+
const m = row.metrics;
|
|
171
|
+
// `unmeasured` already excluded 'known'; this narrows the type.
|
|
172
|
+
if ((0, claim_js_1.isKnown)(m))
|
|
173
|
+
continue;
|
|
174
|
+
const stated = m.kind === 'not-applicable' ? `this provider cannot report it (${m.evidence})` : m.reason;
|
|
175
|
+
if (!reasons.includes(stated))
|
|
176
|
+
reasons.push(stated);
|
|
177
|
+
}
|
|
178
|
+
// Rows can disagree — a turn may mix an adapter that cannot report with
|
|
179
|
+
// calls that carried no usage at all. Picking one silently would state a
|
|
180
|
+
// cause for calls that stated a different one, so the summary says there
|
|
181
|
+
// was more than one and lists them. Bounded by construction: at most
|
|
182
|
+
// MAX_LISTED_REASONS are spelled out and the remainder is COUNTED, so a
|
|
183
|
+
// strategy whose reason varies per call cannot grow this into a wall.
|
|
184
|
+
const listed = reasons.slice(0, MAX_LISTED_REASONS);
|
|
185
|
+
const remaining = reasons.length - listed.length;
|
|
186
|
+
const [onlyReason] = reasons;
|
|
187
|
+
const carried = reasons.length === 1 && onlyReason !== undefined
|
|
188
|
+
? onlyReason
|
|
189
|
+
: `the calls did not agree on why — ${reasons.length} different reasons were ` +
|
|
190
|
+
`given: ${listed.map((r, i) => `(${i + 1}) ${r}`).join('; ')}` +
|
|
191
|
+
(remaining > 0 ? `; and ${remaining} more not listed here` : '');
|
|
192
|
+
const why = total === 0
|
|
193
|
+
? 'no LLM call was observed, so there is nothing to measure'
|
|
194
|
+
: reasons.length === 0
|
|
195
|
+
? // Unreachable where `why` is USED (it is read only when nothing
|
|
196
|
+
// was measured, and an unmeasured row always states a reason).
|
|
197
|
+
`all ${total} observed call(s) reported cache usage`
|
|
198
|
+
: `none of the ${total} observed call(s) reported cache usage — ${carried}`;
|
|
199
|
+
const evidence = `summed over the ${n} of ${total} call(s) whose usage was measured`;
|
|
200
|
+
const claimOf = (value) => n === 0 ? (0, claim_js_1.unknown)(why) : (0, claim_js_1.known)(value, evidence);
|
|
201
|
+
const cacheRead = measured.reduce((s2, p) => s2 + valueOfMetrics(p).cacheReadTokens, 0);
|
|
202
|
+
const cacheWrite = measured.reduce((s2, p) => s2 + valueOfMetrics(p).cacheWriteTokens, 0);
|
|
203
|
+
const fresh = measured.reduce((s2, p) => s2 + valueOfMetrics(p).freshInputTokens, 0);
|
|
204
|
+
const requestTotal = cacheRead + cacheWrite + fresh;
|
|
205
|
+
const dollarsSpent = measured.reduce((s2, p) => s2 + ((0, claim_js_1.isKnown)(p.dollarsSpent) ? p.dollarsSpent.value : 0), 0);
|
|
206
|
+
const dollarsSaved = measured.reduce((s2, p) => s2 + ((0, claim_js_1.isKnown)(p.dollarsSavedVsNoCache) ? p.dollarsSavedVsNoCache.value : 0), 0);
|
|
107
207
|
return Object.freeze({
|
|
108
|
-
totalIterations:
|
|
208
|
+
totalIterations: total,
|
|
109
209
|
applyMarkersIterations: apply,
|
|
110
210
|
noMarkersIterations: skip,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
211
|
+
measuredIterations: n,
|
|
212
|
+
unmeasuredIterations: total - n,
|
|
213
|
+
cacheReadTokensTotal: claimOf(cacheRead),
|
|
214
|
+
cacheWriteTokensTotal: claimOf(cacheWrite),
|
|
215
|
+
freshInputTokensTotal: claimOf(fresh),
|
|
216
|
+
// A measured turn with zero prompt tokens is not a thing; guard it
|
|
217
|
+
// anyway rather than divide by zero and hand back NaN as a rate.
|
|
218
|
+
hitRate: n === 0
|
|
219
|
+
? (0, claim_js_1.unknown)(why)
|
|
220
|
+
: requestTotal === 0
|
|
221
|
+
? (0, claim_js_1.unknown)(`the ${n} measured call(s) reported 0 prompt tokens in total, so a hit rate has no denominator`)
|
|
222
|
+
: (0, claim_js_1.known)(cacheRead / requestTotal, evidence),
|
|
223
|
+
estimatedDollarsSpent: claimOf(dollarsSpent),
|
|
224
|
+
estimatedDollarsSavedVsNoCache: claimOf(dollarsSaved),
|
|
117
225
|
perIter: Object.freeze([...perIter]),
|
|
118
226
|
});
|
|
119
227
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cacheRecorder.js","sourceRoot":"","sources":["../../src/cache/cacheRecorder.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"cacheRecorder.js","sourceRoot":"","sources":["../../src/cache/cacheRecorder.ts"],"names":[],"mappings":"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"}
|
package/dist/cache/index.js
CHANGED
|
@@ -10,23 +10,37 @@
|
|
|
10
10
|
* Strategies registered as of v2.6:
|
|
11
11
|
* - NoOp (wildcard '*' fallback) — always available, registered by
|
|
12
12
|
* the registry module itself
|
|
13
|
-
* - AnthropicCacheStrategy ('anthropic', 'browser-anthropic')
|
|
13
|
+
* - AnthropicCacheStrategy ('anthropic', 'browser-anthropic') — the one
|
|
14
|
+
* end-to-end strategy: the adapter sends markers AND reads cache usage
|
|
15
|
+
* - OpenAICacheStrategy ('openai', 'browser-openai') — pass-through
|
|
16
|
+
* (OpenAI auto-caches); reports `not-applicable` metrics until the
|
|
17
|
+
* adapter lifts `prompt_tokens_details.cached_tokens` onto the port
|
|
18
|
+
* - BedrockCacheStrategy ('bedrock') — `enabled: false`; the Bedrock
|
|
19
|
+
* adapter implements neither half of the cache contract
|
|
14
20
|
*
|
|
15
|
-
* Future strategies
|
|
16
|
-
* -
|
|
17
|
-
* - BedrockCacheStrategy
|
|
18
|
-
* - GeminiCacheStrategy (v2.7+, async handle-based)
|
|
21
|
+
* Future strategies:
|
|
22
|
+
* - GeminiCacheStrategy (async handle-based)
|
|
19
23
|
*
|
|
20
24
|
* Public types (re-exported for consumers):
|
|
21
25
|
* - CachePolicy, CacheMarker, CacheStrategy, CacheCapabilities,
|
|
22
26
|
* CacheMetrics, CachePolicyContext, CacheStrategyContext
|
|
23
27
|
*/
|
|
24
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.cacheRecorder = exports.BedrockCacheStrategy = exports.OpenAICacheStrategy = exports.AnthropicCacheStrategy = exports.NoOpCacheStrategy = exports.listRegisteredStrategies = exports.registerCacheStrategy = exports.getDefaultCacheStrategy = void 0;
|
|
29
|
+
exports.cacheRecorder = exports.BedrockCacheStrategy = exports.OpenAICacheStrategy = exports.AnthropicCacheStrategy = exports.NoOpCacheStrategy = exports.listRegisteredStrategies = exports.registerCacheStrategy = exports.getDefaultCacheStrategy = exports.describeClaim = exports.valueOr = exports.isKnown = exports.notApplicable = exports.unknown = exports.known = void 0;
|
|
26
30
|
// Side-effect imports — register strategies on module load.
|
|
27
31
|
require("./strategies/AnthropicCacheStrategy.js");
|
|
28
32
|
require("./strategies/OpenAICacheStrategy.js");
|
|
29
33
|
require("./strategies/BedrockCacheStrategy.js");
|
|
34
|
+
// The honesty primitive the meter is typed in (9.59.0). Re-exported
|
|
35
|
+
// reference-equal from `src/lib/claim/` — the SAME symbols
|
|
36
|
+
// `agentfootprint/maps` exports, so `known` from either door is one function.
|
|
37
|
+
var claim_js_1 = require("../lib/claim/claim.js");
|
|
38
|
+
Object.defineProperty(exports, "known", { enumerable: true, get: function () { return claim_js_1.known; } });
|
|
39
|
+
Object.defineProperty(exports, "unknown", { enumerable: true, get: function () { return claim_js_1.unknown; } });
|
|
40
|
+
Object.defineProperty(exports, "notApplicable", { enumerable: true, get: function () { return claim_js_1.notApplicable; } });
|
|
41
|
+
Object.defineProperty(exports, "isKnown", { enumerable: true, get: function () { return claim_js_1.isKnown; } });
|
|
42
|
+
Object.defineProperty(exports, "valueOr", { enumerable: true, get: function () { return claim_js_1.valueOr; } });
|
|
43
|
+
Object.defineProperty(exports, "describeClaim", { enumerable: true, get: function () { return claim_js_1.describeClaim; } });
|
|
30
44
|
// Strategy registry
|
|
31
45
|
var strategyRegistry_js_1 = require("./strategyRegistry.js");
|
|
32
46
|
Object.defineProperty(exports, "getDefaultCacheStrategy", { enumerable: true, get: function () { return strategyRegistry_js_1.getDefaultCacheStrategy; } });
|
package/dist/cache/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;;;AAEH,4DAA4D;AAC5D,kDAAgD;AAChD,+CAA6C;AAC7C,gDAA8C;AAc9C,oEAAoE;AACpE,2DAA2D;AAC3D,8EAA8E;AAC9E,kDAQ+B;AAP7B,iGAAA,KAAK,OAAA;AACL,mGAAA,OAAO,OAAA;AACP,yGAAA,aAAa,OAAA;AACb,mGAAA,OAAO,OAAA;AACP,mGAAA,OAAO,OAAA;AACP,yGAAA,aAAa,OAAA;AAIf,oBAAoB;AACpB,6DAI+B;AAH7B,8HAAA,uBAAuB,OAAA;AACvB,4HAAA,qBAAqB,OAAA;AACrB,+HAAA,wBAAwB,OAAA;AAG1B,wEAAwE;AACxE,0EAAsE;AAA7D,yHAAA,iBAAiB,OAAA;AAC1B,oFAAgF;AAAvE,mIAAA,sBAAsB,OAAA;AAC/B,8EAA0E;AAAjE,6HAAA,mBAAmB,OAAA;AAC5B,gFAA4E;AAAnE,+HAAA,oBAAoB,OAAA;AAE7B,WAAW;AACX,uDAAmD;AAA1C,iHAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The one reader of PORT-shaped usage for the cache meter.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: pure function, one job. Given the `usage` the framework put on
|
|
6
|
+
* `agentfootprint.stream.llm_end`, answer what is actually known
|
|
7
|
+
* about cache traffic on that call.
|
|
8
|
+
* Role: the honest half of the 9.59.0 meter fix. Before it, three
|
|
9
|
+
* strategies each parsed RAW WIRE field names (`cache_read_input_tokens`,
|
|
10
|
+
* `prompt_tokens_details.cached_tokens`) off a value that has never
|
|
11
|
+
* carried them — the framework normalises the wire at the ADAPTER
|
|
12
|
+
* ring (`readCacheUsage`) and only ever hands a strategy the port
|
|
13
|
+
* shape. Every field read `undefined`, `?? 0` turned that into a
|
|
14
|
+
* zero, the guard tripped, and a 20-call turn that hit cache on
|
|
15
|
+
* every call reported hitRate 0.
|
|
16
|
+
*
|
|
17
|
+
* The distinction this function exists to preserve: an adapter sets
|
|
18
|
+
* `cacheRead` / `cacheWrite` ONLY when the provider reported a number, so
|
|
19
|
+
* • both absent → nobody measured → `unknown`
|
|
20
|
+
* • either present → measured → `known` (a present 0 is a real 0)
|
|
21
|
+
* That is exactly the line `Claim<T>` was written to hold.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.readPortCacheUsage = void 0;
|
|
25
|
+
const claim_js_1 = require("../lib/claim/claim.js");
|
|
26
|
+
/**
|
|
27
|
+
* Read cache metrics off port usage.
|
|
28
|
+
*
|
|
29
|
+
* @param usage the `usage` field of `agentfootprint.stream.llm_end`
|
|
30
|
+
* @param who the adapter named in the evidence sentence, e.g. `'the Anthropic adapter'`
|
|
31
|
+
*/
|
|
32
|
+
function readPortCacheUsage(usage, who) {
|
|
33
|
+
if (usage === undefined || usage === null || typeof usage !== 'object') {
|
|
34
|
+
return (0, claim_js_1.unknown)('the llm_end event carried no usage payload, so nothing about cache traffic was measured', 'agentfootprint.stream.llm_end');
|
|
35
|
+
}
|
|
36
|
+
const { cacheRead, cacheWrite, input } = usage;
|
|
37
|
+
if (cacheRead === undefined && cacheWrite === undefined) {
|
|
38
|
+
return (0, claim_js_1.unknown)(`${who} reported no cache fields on this call — that is "nobody measured", not "no cache traffic"`, 'agentfootprint.stream.llm_end usage (port shape)');
|
|
39
|
+
}
|
|
40
|
+
return (0, claim_js_1.known)({
|
|
41
|
+
cacheReadTokens: cacheRead ?? 0,
|
|
42
|
+
cacheWriteTokens: cacheWrite ?? 0,
|
|
43
|
+
freshInputTokens: typeof input === 'number' ? input : 0,
|
|
44
|
+
}, `${who} reported cache token counts on the port usage`);
|
|
45
|
+
}
|
|
46
|
+
exports.readPortCacheUsage = readPortCacheUsage;
|
|
47
|
+
//# sourceMappingURL=portUsage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portUsage.js","sourceRoot":"","sources":["../../src/cache/portUsage.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAEH,oDAAmE;AAGnE;;;;;GAKG;AACH,SAAgB,kBAAkB,CAChC,KAA6B,EAC7B,GAAW;IAEX,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvE,OAAO,IAAA,kBAAO,EACZ,yFAAyF,EACzF,+BAA+B,CAChC,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAC/C,IAAI,SAAS,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QACxD,OAAO,IAAA,kBAAO,EACZ,GAAG,GAAG,4FAA4F,EAClG,kDAAkD,CACnD,CAAC;IACJ,CAAC;IACD,OAAO,IAAA,gBAAK,EACV;QACE,eAAe,EAAE,SAAS,IAAI,CAAC;QAC/B,gBAAgB,EAAE,UAAU,IAAI,CAAC;QACjC,gBAAgB,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KACxD,EACD,GAAG,GAAG,gDAAgD,CACvD,CAAC;AACJ,CAAC;AAzBD,gDAyBC"}
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
*
|
|
17
17
|
* What this strategy DOES vs DOESN'T do:
|
|
18
18
|
* - DOES: clamp markers, attach to LLMRequest.cacheMarkers,
|
|
19
|
-
*
|
|
19
|
+
* read cache metrics off the PORT usage the framework hands it
|
|
20
|
+
* (`{ input, output, cacheRead?, cacheWrite? }`) — never off the raw
|
|
21
|
+
* Anthropic wire, which the adapter has already normalised
|
|
20
22
|
* - DOES NOT: rewrite the wire body. The provider
|
|
21
23
|
* (BrowserAnthropicProvider) reads `cacheMarkers` and applies
|
|
22
24
|
* `cache_control` blocks during body construction. Separation of
|
|
@@ -28,6 +30,7 @@
|
|
|
28
30
|
*/
|
|
29
31
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
32
|
exports.AnthropicCacheStrategy = void 0;
|
|
33
|
+
const portUsage_js_1 = require("../portUsage.js");
|
|
31
34
|
const strategyRegistry_js_1 = require("../strategyRegistry.js");
|
|
32
35
|
/** Anthropic enforces 4 cache breakpoints per request. */
|
|
33
36
|
const ANTHROPIC_MAX_MARKERS = 4;
|
|
@@ -65,22 +68,7 @@ class AnthropicCacheStrategy {
|
|
|
65
68
|
return { request, markersApplied };
|
|
66
69
|
}
|
|
67
70
|
extractMetrics(usage) {
|
|
68
|
-
|
|
69
|
-
return undefined;
|
|
70
|
-
const u = usage;
|
|
71
|
-
const cacheRead = u.cache_read_input_tokens ?? 0;
|
|
72
|
-
const cacheWrite = u.cache_creation_input_tokens ?? 0;
|
|
73
|
-
const fresh = u.input_tokens ?? 0;
|
|
74
|
-
// If neither cache field present, response didn't involve caching.
|
|
75
|
-
// Returning undefined signals "no cache info" so cacheRecorder
|
|
76
|
-
// doesn't compute a misleading 0% hit rate.
|
|
77
|
-
if (cacheRead === 0 && cacheWrite === 0)
|
|
78
|
-
return undefined;
|
|
79
|
-
return {
|
|
80
|
-
cacheReadTokens: cacheRead,
|
|
81
|
-
cacheWriteTokens: cacheWrite,
|
|
82
|
-
freshInputTokens: fresh,
|
|
83
|
-
};
|
|
71
|
+
return (0, portUsage_js_1.readPortCacheUsage)(usage, 'the Anthropic adapter');
|
|
84
72
|
}
|
|
85
73
|
}
|
|
86
74
|
exports.AnthropicCacheStrategy = AnthropicCacheStrategy;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnthropicCacheStrategy.js","sourceRoot":"","sources":["../../../src/cache/strategies/AnthropicCacheStrategy.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"AnthropicCacheStrategy.js","sourceRoot":"","sources":["../../../src/cache/strategies/AnthropicCacheStrategy.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;;;AAWH,kDAAqD;AAErD,gEAA+D;AAE/D,0DAA0D;AAC1D,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEhC,MAAM,sBAAsB,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC9D,OAAO,EAAE,IAAI;IACb,UAAU,EAAE,qBAAqB;IACjC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,CAAkC;IACxD,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAiD;IACvF,SAAS,EAAE,KAAK;CACjB,CAAC,CAAC;AAEH,MAAa,sBAAsB;IACxB,YAAY,GAAG,WAAW,CAAC;IAC3B,YAAY,GAAG,sBAAsB,CAAC;IAE/C,KAAK,CAAC,cAAc,CAClB,GAAe,EACf,UAAkC,EAClC,GAAyB;QAKzB,8DAA8D;QAC9D,kEAAkE;QAClE,gEAAgE;QAChE,kEAAkE;QAClE,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;YACxB,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;QAC9C,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;QAC9C,CAAC;QAED,2DAA2D;QAC3D,4DAA4D;QAC5D,kEAAkE;QAClE,MAAM,cAAc,GAClB,UAAU,CAAC,MAAM,IAAI,qBAAqB;YACxC,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;QAEjD,MAAM,OAAO,GAAe;YAC1B,GAAG,GAAG;YACN,YAAY,EAAE,cAAc;SAC7B,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;IACrC,CAAC;IAED,cAAc,CAAC,KAA6B;QAC1C,OAAO,IAAA,iCAAkB,EAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;IAC5D,CAAC;CACF;AA1CD,wDA0CC;AAED,qEAAqE;AACrE,sEAAsE;AACtE,CAAC;IACC,MAAM,QAAQ,GAAG,IAAI,sBAAsB,EAAE,CAAC;IAC9C,IAAA,2CAAqB,EAAC,QAAQ,CAAC,CAAC;IAChC,2EAA2E;IAC3E,oDAAoD;IACpD,MAAM,eAAe,GAAkB;QACrC,YAAY,EAAE,mBAAmB;QACjC,YAAY,EAAE,QAAQ,CAAC,YAAY;QACnC,cAAc,EAAE,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;QACtD,cAAc,EAAE,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;KACvD,CAAC;IACF,IAAA,2CAAqB,EAAC,eAAe,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -1,79 +1,95 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* BedrockCacheStrategy —
|
|
3
|
+
* BedrockCacheStrategy — REGISTERED, AND HONEST ABOUT DOING NOTHING (9.59.0).
|
|
4
4
|
*
|
|
5
|
-
* Bedrock
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* limit). Strategy delegates to Anthropic-shaped behavior.
|
|
9
|
-
* - Llama / Mistral / Cohere on Bedrock → no cache support today
|
|
10
|
-
* (as of 2026-04-30). Strategy passes through, returns no metrics.
|
|
5
|
+
* What Bedrock supports and what THIS ADAPTER does are two different facts,
|
|
6
|
+
* and until 9.59.0 the strategy stated the first while the runtime lived
|
|
7
|
+
* under the second:
|
|
11
8
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `
|
|
9
|
+
* - AWS's Converse API does support prompt caching for Claude models
|
|
10
|
+
* (`cachePoint: { type: 'default' }` entries inserted into the `system` /
|
|
11
|
+
* `tools` / `messages` arrays) and does report
|
|
12
|
+
* `cacheReadInputTokens` / `cacheWriteInputTokens` in its usage block.
|
|
13
|
+
* - `BedrockProvider` implements NEITHER half. It never reads
|
|
14
|
+
* `req.cacheMarkers` (compare `AnthropicProvider`, which calls
|
|
15
|
+
* `applyCacheMarkers`) and it builds `usage` as `{ input, output }` at
|
|
16
|
+
* both its streaming and non-streaming sites. The string "cache" does
|
|
17
|
+
* not appear in that file.
|
|
15
18
|
*
|
|
16
|
-
*
|
|
19
|
+
* So this strategy used to clamp markers onto a request field the adapter
|
|
20
|
+
* then discarded, and report `markersApplied` for markers that never reached
|
|
21
|
+
* a wire — a meter attached to a provider that cannot feed it. It now:
|
|
22
|
+
*
|
|
23
|
+
* - declares `enabled: false` (nothing here works end to end);
|
|
24
|
+
* - passes the request through with `markersApplied: []`, and says why
|
|
25
|
+
* once, in dev mode;
|
|
26
|
+
* - answers `extractMetrics` with `not-applicable` and the reason.
|
|
27
|
+
*
|
|
28
|
+
* It stays REGISTERED rather than being deleted so that a Bedrock consumer
|
|
29
|
+
* asking the registry what it got is told the truth by name, instead of
|
|
30
|
+
* silently falling through to the wildcard NoOp and being left to guess.
|
|
17
31
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
32
|
+
* Note on Converse: the send half is genuinely a DIFFERENT wire from
|
|
33
|
+
* Anthropic's `cache_control` block, so implementing it wants its own
|
|
34
|
+
* `bedrockCacheWire.ts` beside `anthropicCacheWire.ts` — not a reuse. That
|
|
35
|
+
* is the follow-up this file is waiting for; when it lands, flip `enabled`
|
|
36
|
+
* and give `extractMetrics` the `readPortCacheUsage` body the Anthropic
|
|
37
|
+
* strategy has.
|
|
38
|
+
*
|
|
39
|
+
* Auto-registers under provider name `'bedrock'`.
|
|
23
40
|
*/
|
|
24
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
42
|
exports.BedrockCacheStrategy = void 0;
|
|
43
|
+
const claim_js_1 = require("../../lib/claim/claim.js");
|
|
26
44
|
const strategyRegistry_js_1 = require("../strategyRegistry.js");
|
|
27
|
-
|
|
28
|
-
const BEDROCK_CLAUDE_RE = /^anthropic\.claude/i;
|
|
29
|
-
/** Anthropic's 4-marker limit applies to Bedrock-Claude too. */
|
|
30
|
-
const BEDROCK_MAX_MARKERS = 4;
|
|
45
|
+
const footprintjs_1 = require("footprintjs");
|
|
31
46
|
const BEDROCK_CAPABILITIES = Object.freeze({
|
|
32
|
-
//
|
|
33
|
-
// Claude
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
47
|
+
// `false`, and it is a statement about the ADAPTER, not about Bedrock.
|
|
48
|
+
// Bedrock-Claude supports prompt caching; `BedrockProvider` implements
|
|
49
|
+
// neither half of the contract (never sends markers, never reads cache
|
|
50
|
+
// usage), so nothing this strategy could do would reach a wire. Saying
|
|
51
|
+
// `true` here is what let a dead meter look alive.
|
|
52
|
+
enabled: false,
|
|
53
|
+
maxMarkers: 0,
|
|
54
|
+
ttls: [],
|
|
55
|
+
fields: [],
|
|
39
56
|
automatic: false,
|
|
40
57
|
});
|
|
58
|
+
/** One warning per process, not one per call — the fact does not change. */
|
|
59
|
+
let warnedAboutAdapterGap = false;
|
|
41
60
|
class BedrockCacheStrategy {
|
|
42
61
|
providerName = 'bedrock';
|
|
43
62
|
capabilities = BEDROCK_CAPABILITIES;
|
|
44
|
-
async prepareRequest(req, candidates,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
63
|
+
async prepareRequest(req, candidates, _ctx) {
|
|
64
|
+
// Pass-through, ALWAYS. Writing `req.cacheMarkers` here would be writing
|
|
65
|
+
// to a field `BedrockProvider` never reads, and returning a non-empty
|
|
66
|
+
// `markersApplied` would put markers that never reached a wire onto the
|
|
67
|
+
// recorder's record.
|
|
68
|
+
if (candidates.length > 0 && !warnedAboutAdapterGap && (0, footprintjs_1.isDevMode)()) {
|
|
69
|
+
warnedAboutAdapterGap = true;
|
|
70
|
+
// eslint-disable-next-line no-console
|
|
71
|
+
console.warn(`[agentfootprint] cache: ${candidates.length} cache marker(s) were declared for ` +
|
|
72
|
+
`model "${req.model}", but the Bedrock adapter does not implement prompt caching — ` +
|
|
73
|
+
`it never sends cachePoint entries and never reads cacheReadInputTokens off the ` +
|
|
74
|
+
`Converse response. No markers were applied and no hit rate can be measured. ` +
|
|
75
|
+
`Your cache: directives stay portable and light up on the Anthropic providers.`);
|
|
52
76
|
}
|
|
53
|
-
|
|
54
|
-
? candidates
|
|
55
|
-
: candidates.slice(0, BEDROCK_MAX_MARKERS);
|
|
56
|
-
return {
|
|
57
|
-
request: { ...req, cacheMarkers: markersApplied },
|
|
58
|
-
markersApplied,
|
|
59
|
-
};
|
|
77
|
+
return { request: req, markersApplied: [] };
|
|
60
78
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
freshInputTokens: u.input_tokens ?? 0,
|
|
76
|
-
};
|
|
79
|
+
/**
|
|
80
|
+
* Always `not-applicable` — and that is a statement about THIS adapter,
|
|
81
|
+
* not about Bedrock. AWS's Converse API does report
|
|
82
|
+
* `cacheReadInputTokens` / `cacheWriteInputTokens`, but
|
|
83
|
+
* `BedrockProvider` never reads them: its `usage` is built as
|
|
84
|
+
* `{ input, output }` at both the streaming and non-streaming sites. So
|
|
85
|
+
* `cacheRead`/`cacheWrite` are ALWAYS absent on this port, and an
|
|
86
|
+
* `unknown` per call would read as a measurement that merely failed.
|
|
87
|
+
* `not-applicable` says the true thing: nothing here can be measured
|
|
88
|
+
* until the adapter grows the read half.
|
|
89
|
+
*/
|
|
90
|
+
extractMetrics(_usage) {
|
|
91
|
+
return (0, claim_js_1.notApplicable)('the Bedrock adapter does not read cache usage off the Converse response, so no ' +
|
|
92
|
+
'cache tokens ever reach the port');
|
|
77
93
|
}
|
|
78
94
|
}
|
|
79
95
|
exports.BedrockCacheStrategy = BedrockCacheStrategy;
|