agentfootprint 2.5.0 → 2.6.0
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/README.md +86 -0
- package/dist/adapters/llm/BrowserAnthropicProvider.js +68 -0
- package/dist/adapters/llm/BrowserAnthropicProvider.js.map +1 -1
- package/dist/cache/CacheDecisionSubflow.js +172 -0
- package/dist/cache/CacheDecisionSubflow.js.map +1 -0
- package/dist/cache/CacheGateDecider.js +122 -0
- package/dist/cache/CacheGateDecider.js.map +1 -0
- package/dist/cache/applyCachePolicy.js +55 -0
- package/dist/cache/applyCachePolicy.js.map +1 -0
- package/dist/cache/cacheRecorder.js +120 -0
- package/dist/cache/cacheRecorder.js.map +1 -0
- package/dist/cache/index.js +47 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/strategies/AnthropicCacheStrategy.js +102 -0
- package/dist/cache/strategies/AnthropicCacheStrategy.js.map +1 -0
- package/dist/cache/strategies/BedrockCacheStrategy.js +81 -0
- package/dist/cache/strategies/BedrockCacheStrategy.js.map +1 -0
- package/dist/cache/strategies/NoOpCacheStrategy.js +40 -0
- package/dist/cache/strategies/NoOpCacheStrategy.js.map +1 -0
- package/dist/cache/strategies/OpenAICacheStrategy.js +75 -0
- package/dist/cache/strategies/OpenAICacheStrategy.js.map +1 -0
- package/dist/cache/strategyRegistry.js +80 -0
- package/dist/cache/strategyRegistry.js.map +1 -0
- package/dist/cache/types.js +25 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/conventions.js +18 -0
- package/dist/conventions.js.map +1 -1
- package/dist/core/Agent.js +173 -4
- package/dist/core/Agent.js.map +1 -1
- package/dist/esm/adapters/llm/BrowserAnthropicProvider.js +68 -0
- package/dist/esm/adapters/llm/BrowserAnthropicProvider.js.map +1 -1
- package/dist/esm/cache/CacheDecisionSubflow.js +166 -0
- package/dist/esm/cache/CacheDecisionSubflow.js.map +1 -0
- package/dist/esm/cache/CacheGateDecider.js +116 -0
- package/dist/esm/cache/CacheGateDecider.js.map +1 -0
- package/dist/esm/cache/applyCachePolicy.js +50 -0
- package/dist/esm/cache/applyCachePolicy.js.map +1 -0
- package/dist/esm/cache/cacheRecorder.js +116 -0
- package/dist/esm/cache/cacheRecorder.js.map +1 -0
- package/dist/esm/cache/index.js +36 -0
- package/dist/esm/cache/index.js.map +1 -0
- package/dist/esm/cache/strategies/AnthropicCacheStrategy.js +98 -0
- package/dist/esm/cache/strategies/AnthropicCacheStrategy.js.map +1 -0
- package/dist/esm/cache/strategies/BedrockCacheStrategy.js +77 -0
- package/dist/esm/cache/strategies/BedrockCacheStrategy.js.map +1 -0
- package/dist/esm/cache/strategies/NoOpCacheStrategy.js +36 -0
- package/dist/esm/cache/strategies/NoOpCacheStrategy.js.map +1 -0
- package/dist/esm/cache/strategies/OpenAICacheStrategy.js +71 -0
- package/dist/esm/cache/strategies/OpenAICacheStrategy.js.map +1 -0
- package/dist/esm/cache/strategyRegistry.js +73 -0
- package/dist/esm/cache/strategyRegistry.js.map +1 -0
- package/dist/esm/cache/types.js +24 -0
- package/dist/esm/cache/types.js.map +1 -0
- package/dist/esm/conventions.js +18 -0
- package/dist/esm/conventions.js.map +1 -1
- package/dist/esm/core/Agent.js +173 -4
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/index.js +9 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/injection-engine/factories/defineFact.js +3 -0
- package/dist/esm/lib/injection-engine/factories/defineFact.js.map +1 -1
- package/dist/esm/lib/injection-engine/factories/defineInstruction.js +3 -0
- package/dist/esm/lib/injection-engine/factories/defineInstruction.js.map +1 -1
- package/dist/esm/lib/injection-engine/factories/defineSkill.js +5 -0
- package/dist/esm/lib/injection-engine/factories/defineSkill.js.map +1 -1
- package/dist/esm/lib/injection-engine/factories/defineSteering.js +3 -0
- package/dist/esm/lib/injection-engine/factories/defineSteering.js.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/injection-engine/factories/defineFact.js +3 -0
- package/dist/lib/injection-engine/factories/defineFact.js.map +1 -1
- package/dist/lib/injection-engine/factories/defineInstruction.js +3 -0
- package/dist/lib/injection-engine/factories/defineInstruction.js.map +1 -1
- package/dist/lib/injection-engine/factories/defineSkill.js +5 -0
- package/dist/lib/injection-engine/factories/defineSkill.js.map +1 -1
- package/dist/lib/injection-engine/factories/defineSteering.js +3 -0
- package/dist/lib/injection-engine/factories/defineSteering.js.map +1 -1
- package/dist/types/adapters/types.d.ts +11 -0
- package/dist/types/adapters/types.d.ts.map +1 -1
- package/dist/types/cache/CacheDecisionSubflow.d.ts +89 -0
- package/dist/types/cache/CacheDecisionSubflow.d.ts.map +1 -0
- package/dist/types/cache/CacheGateDecider.d.ts +114 -0
- package/dist/types/cache/CacheGateDecider.d.ts.map +1 -0
- package/dist/types/cache/applyCachePolicy.d.ts +38 -0
- package/dist/types/cache/applyCachePolicy.d.ts.map +1 -0
- package/dist/types/cache/cacheRecorder.d.ts +86 -0
- package/dist/types/cache/cacheRecorder.d.ts.map +1 -0
- package/dist/types/cache/index.d.ts +34 -0
- package/dist/types/cache/index.d.ts.map +1 -0
- package/dist/types/cache/strategies/AnthropicCacheStrategy.d.ts +39 -0
- package/dist/types/cache/strategies/AnthropicCacheStrategy.d.ts.map +1 -0
- package/dist/types/cache/strategies/BedrockCacheStrategy.d.ts +34 -0
- package/dist/types/cache/strategies/BedrockCacheStrategy.d.ts.map +1 -0
- package/dist/types/cache/strategies/NoOpCacheStrategy.d.ts +30 -0
- package/dist/types/cache/strategies/NoOpCacheStrategy.d.ts.map +1 -0
- package/dist/types/cache/strategies/OpenAICacheStrategy.d.ts +37 -0
- package/dist/types/cache/strategies/OpenAICacheStrategy.d.ts.map +1 -0
- package/dist/types/cache/strategyRegistry.d.ts +46 -0
- package/dist/types/cache/strategyRegistry.d.ts.map +1 -0
- package/dist/types/cache/types.d.ts +244 -0
- package/dist/types/cache/types.d.ts.map +1 -0
- package/dist/types/conventions.d.ts +18 -0
- package/dist/types/conventions.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts +86 -2
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/factories/defineFact.d.ts +9 -0
- package/dist/types/lib/injection-engine/factories/defineFact.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/factories/defineInstruction.d.ts +11 -0
- package/dist/types/lib/injection-engine/factories/defineInstruction.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/factories/defineSkill.d.ts +15 -0
- package/dist/types/lib/injection-engine/factories/defineSkill.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/factories/defineSteering.d.ts +12 -0
- package/dist/types/lib/injection-engine/factories/defineSteering.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CacheDecision subflow — provider-agnostic translation from
|
|
3
|
+
* `activeInjections + DSL directives` → `CacheMarker[]`.
|
|
4
|
+
*
|
|
5
|
+
* This is the core "policy → markers" Lego layer. It runs every
|
|
6
|
+
* iteration (after slot subflows produce their output, before the
|
|
7
|
+
* CacheGate decider). Pure transform: no IO, no LLM calls, no
|
|
8
|
+
* provider knowledge.
|
|
9
|
+
*
|
|
10
|
+
* Algorithm:
|
|
11
|
+
* 1. Build a `CachePolicyContext` from agent state
|
|
12
|
+
* 2. For each injection in `activeInjections`, evaluate its
|
|
13
|
+
* `metadata.cache` directive against the context → cacheable boolean
|
|
14
|
+
* 3. For each slot (system / tools / messages):
|
|
15
|
+
* a. Walk the slot's contributions in order
|
|
16
|
+
* b. Find the LAST index that's contiguous-from-start cacheable
|
|
17
|
+
* c. Emit one CacheMarker at that boundary if any cacheable
|
|
18
|
+
*
|
|
19
|
+
* Each marker is provider-agnostic. Provider strategy translates
|
|
20
|
+
* to wire format in Phase 6+.
|
|
21
|
+
*
|
|
22
|
+
* Special case — base system prompt: the agent's
|
|
23
|
+
* `agent.getSystemPromptCachePolicy()` value is folded in at index 0
|
|
24
|
+
* of the system slot. Always-on injections (Steering / Fact /
|
|
25
|
+
* always-active rules) follow.
|
|
26
|
+
*/
|
|
27
|
+
import { type FlowChart } from 'footprintjs';
|
|
28
|
+
import type { CacheMarker, CachePolicy, CachePolicyContext } from './types.js';
|
|
29
|
+
import type { Injection } from '../lib/injection-engine/types.js';
|
|
30
|
+
/**
|
|
31
|
+
* Subflow scope state. Set via inputMapper from the agent's parent
|
|
32
|
+
* scope; produces `cacheMarkers` consumed by the BuildLLMRequest stage.
|
|
33
|
+
*/
|
|
34
|
+
export interface CacheDecisionState {
|
|
35
|
+
readonly activeInjections: readonly Injection[];
|
|
36
|
+
readonly iteration: number;
|
|
37
|
+
readonly maxIterations: number;
|
|
38
|
+
readonly userMessage: string;
|
|
39
|
+
readonly lastToolName?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Cumulative input tokens spent across all LLM calls in THIS
|
|
42
|
+
* `agent.run()` invocation only. Resets at the start of each turn
|
|
43
|
+
* (each `agent.run()` call). Predicates can use this for budget-
|
|
44
|
+
* aware cache invalidation (e.g., "flush cache after 50K tokens").
|
|
45
|
+
*/
|
|
46
|
+
readonly cumulativeInputTokens: number;
|
|
47
|
+
/**
|
|
48
|
+
* Base system prompt's cache policy (from
|
|
49
|
+
* `agent.getSystemPromptCachePolicy()`). Folded in at index 0 of
|
|
50
|
+
* the system slot's cache evaluation, ahead of any always-on
|
|
51
|
+
* injections.
|
|
52
|
+
*/
|
|
53
|
+
readonly systemPromptCachePolicy: CachePolicy;
|
|
54
|
+
/** Global kill switch. When `true`, subflow emits zero markers. */
|
|
55
|
+
readonly cachingDisabled: boolean;
|
|
56
|
+
cacheMarkers: readonly CacheMarker[];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Evaluate a `CachePolicy` against the current context.
|
|
60
|
+
* Returns `true` if the policy says THIS iteration's content is cacheable.
|
|
61
|
+
*/
|
|
62
|
+
export declare function evaluateCachePolicy(policy: CachePolicy, ctx: CachePolicyContext): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Identify which slots an injection contributes to. An injection can
|
|
65
|
+
* target multiple slots simultaneously (Skills target both system +
|
|
66
|
+
* tools); we visit each contributing slot independently.
|
|
67
|
+
*/
|
|
68
|
+
export declare function injectionTargetSlots(injection: Injection): ReadonlyArray<'system' | 'tools' | 'messages'>;
|
|
69
|
+
/**
|
|
70
|
+
* Pure transform: state → markers. Exported so tests can exercise
|
|
71
|
+
* the algorithm directly without the FlowChartExecutor ceremony of
|
|
72
|
+
* mounting the subflow as a child of a parent chart.
|
|
73
|
+
*
|
|
74
|
+
* The subflow body (`decide` below) is a thin wrapper that pulls
|
|
75
|
+
* state from scope and delegates here.
|
|
76
|
+
*/
|
|
77
|
+
export declare function computeCacheMarkers(state: Omit<CacheDecisionState, 'cacheMarkers'>): readonly CacheMarker[];
|
|
78
|
+
/**
|
|
79
|
+
* The cache-decision subflow. Mounted into the agent's main chart
|
|
80
|
+
* after the slot subflows (System / Messages / Tools) and before
|
|
81
|
+
* the CacheGate decider stage.
|
|
82
|
+
*
|
|
83
|
+
* Mounted via `addSubFlowChartNext(SUBFLOW_IDS.CACHE_DECISION, ...)`
|
|
84
|
+
* with `arrayMerge: ArrayMergeMode.Replace` on the outputMapper —
|
|
85
|
+
* `cacheMarkers` MUST replace, not concatenate, across iterations
|
|
86
|
+
* (same lesson as the v2.5.1 InjectionEngine fix).
|
|
87
|
+
*/
|
|
88
|
+
export declare const cacheDecisionSubflow: FlowChart;
|
|
89
|
+
//# sourceMappingURL=CacheDecisionSubflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CacheDecisionSubflow.d.ts","sourceRoot":"","sources":["../../../src/cache/CacheDecisionSubflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAa,KAAK,SAAS,EAAmB,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAElE;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IAEjC,QAAQ,CAAC,gBAAgB,EAAE,SAAS,SAAS,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,uBAAuB,EAAE,WAAW,CAAC;IAC9C,mEAAmE;IACnE,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAElC,YAAY,EAAE,SAAS,WAAW,EAAE,CAAC;CACtC;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAuBzF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,SAAS,GACnB,aAAa,CAAC,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC,CAYhD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,cAAc,CAAC,GAC9C,SAAS,WAAW,EAAE,CA2DxB;AAmBD;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAM1B,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CacheGate — runtime decider that gates cache-marker application.
|
|
3
|
+
*
|
|
4
|
+
* Runs every iteration AFTER the CacheDecision subflow produces
|
|
5
|
+
* `scope.cacheMarkers` and BEFORE the BuildLLMRequest stage applies
|
|
6
|
+
* them. Three rules can fall through to "no-markers" (skip caching);
|
|
7
|
+
* default branch is "apply-markers" (proceed with caching).
|
|
8
|
+
*
|
|
9
|
+
* Why a decider stage and not a function: footprintjs's `decide()`
|
|
10
|
+
* captures evidence on `FlowRecorder.onDecision` natively. The
|
|
11
|
+
* `cacheRecorder()` (Phase 9) reads
|
|
12
|
+
* `event.evidence.rules.find(r => r.matched).inputs[]` to surface
|
|
13
|
+
* WHY caching was applied or skipped each iter. Same channel
|
|
14
|
+
* footprintjs uses for every other decision; same renderer in Lens.
|
|
15
|
+
*
|
|
16
|
+
* Three rules (evaluated top-down; first match wins):
|
|
17
|
+
* 1. Kill switch — `Agent.create({ caching: 'off' })` was set
|
|
18
|
+
* 2. Hit-rate floor — recent hit rate < 30%; cache writes outpacing
|
|
19
|
+
* reads, auto-disable to avoid the cache-write penalty
|
|
20
|
+
* 3. Skill churn — active skills changing too rapidly for caching
|
|
21
|
+
* to amortize (Anthropic LLM expert's concern from Phase 4 review)
|
|
22
|
+
*
|
|
23
|
+
* Default branch (no rule matches): `'apply-markers'`.
|
|
24
|
+
*/
|
|
25
|
+
import { type DecisionResult, type TypedScope } from 'footprintjs';
|
|
26
|
+
/**
|
|
27
|
+
* Subset of agent scope state the CacheGate decider reads.
|
|
28
|
+
* Phase 6 wires these keys into the agent's main chart.
|
|
29
|
+
*/
|
|
30
|
+
export interface CacheGateState {
|
|
31
|
+
/**
|
|
32
|
+
* Global kill switch. When `true`, decider skips caching
|
|
33
|
+
* unconditionally. Set via `Agent.create({ caching: 'off' })`.
|
|
34
|
+
*/
|
|
35
|
+
readonly cachingDisabled: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Running cache hit rate from the last N iterations (0..1).
|
|
38
|
+
* `undefined` when no cache events have fired yet (e.g., iter 1 of
|
|
39
|
+
* the first turn — no history). The cacheRecorder (Phase 9)
|
|
40
|
+
* computes this from `CacheMetrics` events.
|
|
41
|
+
*/
|
|
42
|
+
readonly recentHitRate: number | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Rolling window of active-skill IDs across recent iterations,
|
|
45
|
+
* one per iteration (latest LAST). Maintained by the
|
|
46
|
+
* UpdateSkillHistory function stage (Phase 6 mount).
|
|
47
|
+
*
|
|
48
|
+
* `undefined` entry = no skill active that iteration.
|
|
49
|
+
*/
|
|
50
|
+
readonly skillHistory: readonly (string | undefined)[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Hit-rate floor below which we auto-disable caching. The 30% number
|
|
54
|
+
* is calibrated for Anthropic's pricing: cache write costs +25%
|
|
55
|
+
* premium, cache read costs 90% off. Break-even at ~25% hit rate.
|
|
56
|
+
* 30% gives a buffer; below that we're losing money on writes that
|
|
57
|
+
* never recoup.
|
|
58
|
+
*
|
|
59
|
+
* Reasoning: if hit rate is X, cost-per-token vs no caching is
|
|
60
|
+
* (1 - X) * 1.0 + X * 0.1 // baseline
|
|
61
|
+
* minus
|
|
62
|
+
* write_iters * 1.25 + read_iters * 0.1 // with caching
|
|
63
|
+
* Solving for break-even gives X ≈ 0.25 for typical agent shapes.
|
|
64
|
+
*/
|
|
65
|
+
export declare const HIT_RATE_FLOOR = 0.3;
|
|
66
|
+
/**
|
|
67
|
+
* Window size for skill-churn detection. Last 5 iterations of
|
|
68
|
+
* active skill IDs are inspected.
|
|
69
|
+
*/
|
|
70
|
+
export declare const SKILL_CHURN_WINDOW = 5;
|
|
71
|
+
/**
|
|
72
|
+
* Threshold above which skill churn is considered detected: this many
|
|
73
|
+
* UNIQUE skills in the rolling window. With window=5 and threshold=3,
|
|
74
|
+
* the pattern A → B → A → C still triggers (3 unique skills in 4 iters).
|
|
75
|
+
*/
|
|
76
|
+
export declare const SKILL_CHURN_THRESHOLD = 3;
|
|
77
|
+
/**
|
|
78
|
+
* Pure helper: detect skill churn given a rolling history.
|
|
79
|
+
* Exported for direct testing without decider/scope ceremony.
|
|
80
|
+
*/
|
|
81
|
+
export declare function detectSkillChurn(history: readonly (string | undefined)[], windowSize?: number, threshold?: number): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Branch routing keys for the CacheGate decider. Two outcomes:
|
|
84
|
+
* apply markers (proceed with cache) or skip (no markers this iter).
|
|
85
|
+
*/
|
|
86
|
+
export type CacheGateBranch = 'apply-markers' | 'no-markers';
|
|
87
|
+
/**
|
|
88
|
+
* The decider function. Mounted via `addDeciderFunction` in the
|
|
89
|
+
* agent's main chart in Phase 6.
|
|
90
|
+
*
|
|
91
|
+
* Returns a `DecisionResult` (footprintjs's `decide()` helper output)
|
|
92
|
+
* which the engine unwraps via `.branch` for routing AND publishes
|
|
93
|
+
* `evidence.rules[matched].inputs[]` to FlowRecorder.onDecision.
|
|
94
|
+
* cacheRecorder (Phase 9) subscribes to that channel for the audit trail.
|
|
95
|
+
*
|
|
96
|
+
* For non-routing consumers (testing the decision in isolation), read
|
|
97
|
+
* the `.branch` field of the returned DecisionResult.
|
|
98
|
+
*/
|
|
99
|
+
export declare function cacheGateDecide(scope: TypedScope<CacheGateState>): DecisionResult;
|
|
100
|
+
/**
|
|
101
|
+
* Update the skill-history rolling window. Called as a function
|
|
102
|
+
* stage BEFORE the CacheGate decider. Reads the current iteration's
|
|
103
|
+
* active skill (head of `activatedInjectionIds`) and appends to the
|
|
104
|
+
* `skillHistory` array.
|
|
105
|
+
*
|
|
106
|
+
* Window length is bounded at `SKILL_CHURN_WINDOW * 2` so the array
|
|
107
|
+
* doesn't grow unboundedly across long agent runs. Old entries
|
|
108
|
+
* fall off the front naturally.
|
|
109
|
+
*/
|
|
110
|
+
export declare function updateSkillHistory(scope: TypedScope<{
|
|
111
|
+
activatedInjectionIds?: readonly string[];
|
|
112
|
+
skillHistory: readonly (string | undefined)[];
|
|
113
|
+
}>): void;
|
|
114
|
+
//# sourceMappingURL=CacheGateDecider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CacheGateDecider.d.ts","sourceRoot":"","sources":["../../../src/cache/CacheGateDecider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAU,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3E;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;CACxD;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,EACxC,UAAU,GAAE,MAA2B,EACvC,SAAS,GAAE,MAA8B,GACxC,OAAO,CAQT;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG,YAAY,CAAC;AAE7D;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,GAAG,cAAc,CAsBjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,UAAU,CAAC;IAChB,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,YAAY,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;CAC/C,CAAC,GACD,IAAI,CAQN"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* applyCachePolicy — internal helper for injection factories.
|
|
3
|
+
*
|
|
4
|
+
* Each factory (`defineSkill`, `defineSteering`, `defineFact`,
|
|
5
|
+
* `defineInstruction`, `defineMemory`) calls this to merge the
|
|
6
|
+
* consumer-supplied `cache` option with the flavor-specific default.
|
|
7
|
+
* The merged policy lands in `Injection.metadata.cache` for the
|
|
8
|
+
* CacheDecision subflow (Phase 4) to read back.
|
|
9
|
+
*
|
|
10
|
+
* Why it lives in src/cache/ (not co-located with each factory):
|
|
11
|
+
* - Single source of truth for per-flavor defaults
|
|
12
|
+
* - Tests for the defaults live in one place (test/cache/)
|
|
13
|
+
* - Adding a new factory means adding one entry to the map below;
|
|
14
|
+
* not duplicating the default-resolution logic five times
|
|
15
|
+
*/
|
|
16
|
+
import type { CachePolicy } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Per-flavor default `cache` values when consumer doesn't specify.
|
|
19
|
+
* These match the documentation in `CachePolicy`'s JSDoc — keep
|
|
20
|
+
* synchronized.
|
|
21
|
+
*/
|
|
22
|
+
declare const FLAVOR_DEFAULTS: Readonly<Record<string, CachePolicy>>;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the effective `cache` policy for an injection.
|
|
25
|
+
*
|
|
26
|
+
* @param flavor - The injection flavor (drives the default if `consumerValue` undefined)
|
|
27
|
+
* @param consumerValue - What the consumer wrote in `cache:` (or undefined)
|
|
28
|
+
* @returns The effective CachePolicy. Always defined.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveCachePolicy(flavor: keyof typeof FLAVOR_DEFAULTS | string, consumerValue: CachePolicy | undefined): CachePolicy;
|
|
31
|
+
/**
|
|
32
|
+
* Read-only access to the per-flavor default table. Exported for
|
|
33
|
+
* tests asserting the documented defaults are wired correctly. Not
|
|
34
|
+
* intended for runtime use — callers should use `resolveCachePolicy`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getFlavorDefault(flavor: string): CachePolicy;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=applyCachePolicy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyCachePolicy.d.ts","sourceRoot":"","sources":["../../../src/cache/applyCachePolicy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;GAIG;AACH,QAAA,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAMzD,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,OAAO,eAAe,GAAG,MAAM,EAC7C,aAAa,EAAE,WAAW,GAAG,SAAS,GACrC,WAAW,CAKb;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAE5D"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cacheRecorder() — observability for the v2.6 cache layer.
|
|
3
|
+
*
|
|
4
|
+
* Subscribes to:
|
|
5
|
+
* - `FlowRecorder.onDecision` — captures CacheGate routing decisions
|
|
6
|
+
* (apply-markers / no-markers + the rule that fired + evidence
|
|
7
|
+
* from `decide()`). Read directly from `event.evidence.rules[matched]`
|
|
8
|
+
* since footprintjs already auto-captures predicate `inputs[]`.
|
|
9
|
+
* - `agentfootprint.stream.llm_end` events — read provider's `usage`
|
|
10
|
+
* and call the agent's CacheStrategy.extractMetrics() to normalize
|
|
11
|
+
* into CacheMetrics (cacheReadTokens / cacheWriteTokens / fresh).
|
|
12
|
+
*
|
|
13
|
+
* Produces:
|
|
14
|
+
* - per-iteration `agentfootprint.cache.applied` events (markers
|
|
15
|
+
* applied this iter or empty if skipped) — for Lens trace
|
|
16
|
+
* - per-iteration `agentfootprint.cache.metrics` events (hit/write
|
|
17
|
+
* token counts + estimated dollars via PricingTable) — for
|
|
18
|
+
* dashboards
|
|
19
|
+
* - a turn-end summary printable via `recorder.report()` —
|
|
20
|
+
* numeric tally plus dollars saved
|
|
21
|
+
*
|
|
22
|
+
* v2.6 LIMITATION: doesn't yet write `scope.recentHitRate` back into
|
|
23
|
+
* agent state. CacheGate's hit-rate-floor rule won't fire automatically;
|
|
24
|
+
* consumers can manually wire feedback via `Agent.create(...).attach(rec)`.
|
|
25
|
+
* Full feedback loop deferred to v2.7 (needs an agent-side accessor
|
|
26
|
+
* convention since recorders don't normally write to scope).
|
|
27
|
+
*/
|
|
28
|
+
import type { CombinedRecorder } from 'footprintjs';
|
|
29
|
+
import type { CacheMetrics, CacheStrategy } from './types.js';
|
|
30
|
+
import type { PricingTable } from '../adapters/types.js';
|
|
31
|
+
interface PerIterEntry {
|
|
32
|
+
readonly iteration: number;
|
|
33
|
+
readonly branch: 'apply-markers' | 'no-markers';
|
|
34
|
+
readonly rule?: string;
|
|
35
|
+
readonly metrics?: CacheMetrics;
|
|
36
|
+
readonly dollarsSpent: number;
|
|
37
|
+
readonly dollarsSavedVsNoCache: number;
|
|
38
|
+
}
|
|
39
|
+
interface CacheReportSummary {
|
|
40
|
+
readonly totalIterations: number;
|
|
41
|
+
readonly applyMarkersIterations: number;
|
|
42
|
+
readonly noMarkersIterations: number;
|
|
43
|
+
readonly cacheReadTokensTotal: number;
|
|
44
|
+
readonly cacheWriteTokensTotal: number;
|
|
45
|
+
readonly freshInputTokensTotal: number;
|
|
46
|
+
readonly hitRate: number;
|
|
47
|
+
readonly estimatedDollarsSpent: number;
|
|
48
|
+
readonly estimatedDollarsSavedVsNoCache: number;
|
|
49
|
+
readonly perIter: readonly PerIterEntry[];
|
|
50
|
+
}
|
|
51
|
+
export interface CacheRecorderOptions {
|
|
52
|
+
/**
|
|
53
|
+
* The agent's CacheStrategy. Required for `extractMetrics` —
|
|
54
|
+
* normalizes provider-specific `usage` shapes into CacheMetrics.
|
|
55
|
+
* If not provided, recorder logs the raw usage and skips dollar math.
|
|
56
|
+
*/
|
|
57
|
+
readonly strategy?: CacheStrategy;
|
|
58
|
+
/**
|
|
59
|
+
* PricingTable for dollar estimates. Falls back to token-count-only
|
|
60
|
+
* reporting when omitted. Looks up `'input'` / `'cacheRead'` /
|
|
61
|
+
* `'cacheWrite'` token kinds (PricingTable already supports these
|
|
62
|
+
* as of v2.5).
|
|
63
|
+
*/
|
|
64
|
+
readonly pricing?: PricingTable;
|
|
65
|
+
/**
|
|
66
|
+
* Model id for pricing lookup. Defaults to a placeholder; set to
|
|
67
|
+
* the actual model the agent is using for accurate dollar math.
|
|
68
|
+
*/
|
|
69
|
+
readonly model?: string;
|
|
70
|
+
}
|
|
71
|
+
export interface CacheRecorderHandle extends CombinedRecorder {
|
|
72
|
+
/**
|
|
73
|
+
* Build a per-turn report. Call after `agent.run()` completes.
|
|
74
|
+
* Returns a frozen snapshot — recorder keeps accumulating but the
|
|
75
|
+
* report you held is stable.
|
|
76
|
+
*/
|
|
77
|
+
report(): CacheReportSummary;
|
|
78
|
+
/**
|
|
79
|
+
* Reset accumulated state. Call between turns if you want
|
|
80
|
+
* per-turn rather than per-session reporting.
|
|
81
|
+
*/
|
|
82
|
+
reset(): void;
|
|
83
|
+
}
|
|
84
|
+
export declare function cacheRecorder(options?: CacheRecorderOptions): CacheRecorderHandle;
|
|
85
|
+
export {};
|
|
86
|
+
//# sourceMappingURL=cacheRecorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cacheRecorder.d.ts","sourceRoot":"","sources":["../../../src/cache/cacheRecorder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,UAAU,YAAY;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,YAAY,CAAC;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;CACxC;AAED,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,8BAA8B,EAAE,MAAM,CAAC;IAChD,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC3D;;;;OAIG;IACH,MAAM,IAAI,kBAAkB,CAAC;IAC7B;;;OAGG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,CA8FrF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agentfootprint/cache — public surface for the cache layer (v2.6+).
|
|
3
|
+
*
|
|
4
|
+
* Importing this module side-effect-registers every built-in cache
|
|
5
|
+
* strategy in the registry. The agentfootprint main barrel imports
|
|
6
|
+
* from here so consumers get the registered strategies without
|
|
7
|
+
* needing to know they exist.
|
|
8
|
+
*
|
|
9
|
+
* Strategies registered as of v2.6:
|
|
10
|
+
* - NoOp (wildcard '*' fallback) — always available, registered by
|
|
11
|
+
* the registry module itself
|
|
12
|
+
* - AnthropicCacheStrategy ('anthropic', 'browser-anthropic')
|
|
13
|
+
*
|
|
14
|
+
* Future strategies (Phase 8+):
|
|
15
|
+
* - OpenAICacheStrategy
|
|
16
|
+
* - BedrockCacheStrategy
|
|
17
|
+
* - GeminiCacheStrategy (v2.7+, async handle-based)
|
|
18
|
+
*
|
|
19
|
+
* Public types (re-exported for consumers):
|
|
20
|
+
* - CachePolicy, CacheMarker, CacheStrategy, CacheCapabilities,
|
|
21
|
+
* CacheMetrics, CachePolicyContext, CacheStrategyContext
|
|
22
|
+
*/
|
|
23
|
+
import './strategies/AnthropicCacheStrategy.js';
|
|
24
|
+
import './strategies/OpenAICacheStrategy.js';
|
|
25
|
+
import './strategies/BedrockCacheStrategy.js';
|
|
26
|
+
export type { CachePolicy, CachePolicyContext, CacheMarker, CacheStrategy, CacheStrategyContext, CacheCapabilities, CacheMetrics, } from './types.js';
|
|
27
|
+
export { getDefaultCacheStrategy, registerCacheStrategy, listRegisteredStrategies, } from './strategyRegistry.js';
|
|
28
|
+
export { NoOpCacheStrategy } from './strategies/NoOpCacheStrategy.js';
|
|
29
|
+
export { AnthropicCacheStrategy } from './strategies/AnthropicCacheStrategy.js';
|
|
30
|
+
export { OpenAICacheStrategy } from './strategies/OpenAICacheStrategy.js';
|
|
31
|
+
export { BedrockCacheStrategy } from './strategies/BedrockCacheStrategy.js';
|
|
32
|
+
export { cacheRecorder } from './cacheRecorder.js';
|
|
33
|
+
export type { CacheRecorderOptions, CacheRecorderHandle } from './cacheRecorder.js';
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,wCAAwC,CAAC;AAChD,OAAO,qCAAqC,CAAC;AAC7C,OAAO,sCAAsC,CAAC;AAG9C,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAG5E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AnthropicCacheStrategy — translates agnostic CacheMarker[] to
|
|
3
|
+
* Anthropic API's `cache_control: { type: 'ephemeral' }` markers.
|
|
4
|
+
*
|
|
5
|
+
* Anthropic-specific behaviors honored:
|
|
6
|
+
* - **4-marker limit**: Anthropic allows ≤4 cache breakpoints per
|
|
7
|
+
* request. Strategy clamps oversize candidate sets, keeping the
|
|
8
|
+
* first 4 in slot order.
|
|
9
|
+
* - **TTL mapping**: 'short' → default 5min ephemeral; 'long' →
|
|
10
|
+
* `ttl: '1h'` (1-hour beta).
|
|
11
|
+
* - **Provider-side hashing**: this strategy doesn't hash — Anthropic
|
|
12
|
+
* keys cache by exact byte prefix server-side. We don't need
|
|
13
|
+
* content hashes for the v2.6 surface; reserved for v2.7+ if a
|
|
14
|
+
* pre-flight cache-warm-check API ships.
|
|
15
|
+
*
|
|
16
|
+
* What this strategy DOES vs DOESN'T do:
|
|
17
|
+
* - DOES: clamp markers, attach to LLMRequest.cacheMarkers,
|
|
18
|
+
* extract metrics from response.usage
|
|
19
|
+
* - DOES NOT: rewrite the wire body. The provider
|
|
20
|
+
* (BrowserAnthropicProvider) reads `cacheMarkers` and applies
|
|
21
|
+
* `cache_control` blocks during body construction. Separation of
|
|
22
|
+
* concerns: strategy decides WHAT to cache; provider knows HOW
|
|
23
|
+
* to encode on its specific wire.
|
|
24
|
+
*
|
|
25
|
+
* Auto-registers in the strategy registry on module import for
|
|
26
|
+
* provider names: 'anthropic', 'browser-anthropic'.
|
|
27
|
+
*/
|
|
28
|
+
import type { CacheCapabilities, CacheMarker, CacheMetrics, CacheStrategy, CacheStrategyContext } from '../types.js';
|
|
29
|
+
import type { LLMRequest } from '../../adapters/types.js';
|
|
30
|
+
export declare class AnthropicCacheStrategy implements CacheStrategy {
|
|
31
|
+
readonly providerName = "anthropic";
|
|
32
|
+
readonly capabilities: CacheCapabilities;
|
|
33
|
+
prepareRequest(req: LLMRequest, candidates: readonly CacheMarker[], ctx: CacheStrategyContext): Promise<{
|
|
34
|
+
readonly request: LLMRequest;
|
|
35
|
+
readonly markersApplied: readonly CacheMarker[];
|
|
36
|
+
}>;
|
|
37
|
+
extractMetrics(usage: unknown): CacheMetrics | undefined;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=AnthropicCacheStrategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnthropicCacheStrategy.d.ts","sourceRoot":"","sources":["../../../../src/cache/strategies/AnthropicCacheStrategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAc1D,qBAAa,sBAAuB,YAAW,aAAa;IAC1D,QAAQ,CAAC,YAAY,eAAe;IACpC,QAAQ,CAAC,YAAY,oBAA0B;IAEzC,cAAc,CAClB,GAAG,EAAE,UAAU,EACf,UAAU,EAAE,SAAS,WAAW,EAAE,EAClC,GAAG,EAAE,oBAAoB,GACxB,OAAO,CAAC;QACT,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;QAC7B,QAAQ,CAAC,cAAc,EAAE,SAAS,WAAW,EAAE,CAAC;KACjD,CAAC;IA4BF,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS;CAoBzD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BedrockCacheStrategy — model-aware strategy for AWS Bedrock.
|
|
3
|
+
*
|
|
4
|
+
* Bedrock hosts multiple model families. Cache support varies:
|
|
5
|
+
* - Claude on Bedrock → identical mechanics to direct Anthropic
|
|
6
|
+
* (`cache_control: { type: 'ephemeral' }` markers, 4-marker
|
|
7
|
+
* limit). Strategy delegates to Anthropic-shaped behavior.
|
|
8
|
+
* - Llama / Mistral / Cohere on Bedrock → no cache support today
|
|
9
|
+
* (as of 2026-04-30). Strategy passes through, returns no metrics.
|
|
10
|
+
*
|
|
11
|
+
* Auto-detection: inspects `req.model` to decide. Claude model IDs
|
|
12
|
+
* start with `'anthropic.claude'` on Bedrock (e.g.,
|
|
13
|
+
* `anthropic.claude-3-5-sonnet-20240620-v1:0`).
|
|
14
|
+
*
|
|
15
|
+
* Auto-registers under provider name `'bedrock'`.
|
|
16
|
+
*
|
|
17
|
+
* Per the Phase 1 review (Reviewer 6 — Provider SDK expert): for
|
|
18
|
+
* non-Claude Bedrock models the strategy reports `enabled: false` in
|
|
19
|
+
* its capabilities so the CacheDecision subflow can short-circuit
|
|
20
|
+
* marker emission (potential v2.7 optimization). Today markers still
|
|
21
|
+
* emit and we drop them silently in prepareRequest.
|
|
22
|
+
*/
|
|
23
|
+
import type { CacheCapabilities, CacheMarker, CacheMetrics, CacheStrategy, CacheStrategyContext } from '../types.js';
|
|
24
|
+
import type { LLMRequest } from '../../adapters/types.js';
|
|
25
|
+
export declare class BedrockCacheStrategy implements CacheStrategy {
|
|
26
|
+
readonly providerName = "bedrock";
|
|
27
|
+
readonly capabilities: CacheCapabilities;
|
|
28
|
+
prepareRequest(req: LLMRequest, candidates: readonly CacheMarker[], ctx: CacheStrategyContext): Promise<{
|
|
29
|
+
readonly request: LLMRequest;
|
|
30
|
+
readonly markersApplied: readonly CacheMarker[];
|
|
31
|
+
}>;
|
|
32
|
+
extractMetrics(usage: unknown): CacheMetrics | undefined;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=BedrockCacheStrategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BedrockCacheStrategy.d.ts","sourceRoot":"","sources":["../../../../src/cache/strategies/BedrockCacheStrategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAoB1D,qBAAa,oBAAqB,YAAW,aAAa;IACxD,QAAQ,CAAC,YAAY,aAAa;IAClC,QAAQ,CAAC,YAAY,oBAAwB;IAEvC,cAAc,CAClB,GAAG,EAAE,UAAU,EACf,UAAU,EAAE,SAAS,WAAW,EAAE,EAClC,GAAG,EAAE,oBAAoB,GACxB,OAAO,CAAC;QACT,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;QAC7B,QAAQ,CAAC,cAAc,EAAE,SAAS,WAAW,EAAE,CAAC;KACjD,CAAC;IAmBF,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS;CAmBzD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NoOpCacheStrategy — fallback strategy for providers without cache
|
|
3
|
+
* support (Mock, unknown providers, intentional opt-out).
|
|
4
|
+
*
|
|
5
|
+
* Returns the request unchanged; reports no metrics. The
|
|
6
|
+
* `capabilities.enabled` flag is `false` so the CacheDecision subflow
|
|
7
|
+
* could choose to skip emitting markers entirely (potential v2.7
|
|
8
|
+
* optimization), though current Phase 4+5 always emit markers and
|
|
9
|
+
* let the strategy decide what to do with them.
|
|
10
|
+
*
|
|
11
|
+
* Always-available default. Registered against the special wildcard
|
|
12
|
+
* `'*'` so any unrecognized provider name falls back to NoOp.
|
|
13
|
+
*/
|
|
14
|
+
import type { CacheCapabilities, CacheMarker, CacheMetrics, CacheStrategy, CacheStrategyContext } from '../types.js';
|
|
15
|
+
import type { LLMRequest } from '../../adapters/types.js';
|
|
16
|
+
export declare class NoOpCacheStrategy implements CacheStrategy {
|
|
17
|
+
/**
|
|
18
|
+
* Wildcard provider name. The strategy registry treats this as the
|
|
19
|
+
* fallback for any provider that doesn't have a specific strategy
|
|
20
|
+
* registered.
|
|
21
|
+
*/
|
|
22
|
+
readonly providerName = "*";
|
|
23
|
+
readonly capabilities: CacheCapabilities;
|
|
24
|
+
prepareRequest(req: LLMRequest, _candidates: readonly CacheMarker[], _ctx: CacheStrategyContext): Promise<{
|
|
25
|
+
readonly request: LLMRequest;
|
|
26
|
+
readonly markersApplied: readonly CacheMarker[];
|
|
27
|
+
}>;
|
|
28
|
+
extractMetrics(_usage: unknown): CacheMetrics | undefined;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=NoOpCacheStrategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoOpCacheStrategy.d.ts","sourceRoot":"","sources":["../../../../src/cache/strategies/NoOpCacheStrategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAU1D,qBAAa,iBAAkB,YAAW,aAAa;IACrD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,OAAO;IAC5B,QAAQ,CAAC,YAAY,oBAAqB;IAEpC,cAAc,CAClB,GAAG,EAAE,UAAU,EACf,WAAW,EAAE,SAAS,WAAW,EAAE,EACnC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC;QACT,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;QAC7B,QAAQ,CAAC,cAAc,EAAE,SAAS,WAAW,EAAE,CAAC;KACjD,CAAC;IAIF,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS;CAG1D"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAICacheStrategy — metrics-only strategy for OpenAI providers.
|
|
3
|
+
*
|
|
4
|
+
* OpenAI auto-caches request prefixes ≥1024 tokens at 50% off.
|
|
5
|
+
* No client-side opt-in markers needed (and no way to influence
|
|
6
|
+
* cache behavior from the client). The strategy:
|
|
7
|
+
*
|
|
8
|
+
* - **prepareRequest**: pass-through. We can't tell OpenAI what
|
|
9
|
+
* to cache; they decide automatically. Markers are silently
|
|
10
|
+
* dropped (the 80% case for OpenAI consumers is "I declared
|
|
11
|
+
* cache: 'always' for my injections" — that's still meaningful
|
|
12
|
+
* because (a) it's portable across providers, (b) for OpenAI
|
|
13
|
+
* the auto-cache may still hit on stable prefixes regardless).
|
|
14
|
+
* - **extractMetrics**: reads `prompt_tokens_details.cached_tokens`
|
|
15
|
+
* from OpenAI's usage response so cacheRecorder can surface
|
|
16
|
+
* hit rates / dollar savings.
|
|
17
|
+
*
|
|
18
|
+
* Auto-registers on module import for: 'openai', 'browser-openai'.
|
|
19
|
+
*
|
|
20
|
+
* Documentation note for consumers (Phase 12 docs): the `cache:`
|
|
21
|
+
* directive on injection definitions is portable but has NO LOCAL
|
|
22
|
+
* EFFECT on OpenAI runs — the provider auto-caches based on prefix
|
|
23
|
+
* length. The directive still ships correctly with the agent and
|
|
24
|
+
* lights up automatically when you swap to Anthropic / Bedrock.
|
|
25
|
+
*/
|
|
26
|
+
import type { CacheCapabilities, CacheMarker, CacheMetrics, CacheStrategy, CacheStrategyContext } from '../types.js';
|
|
27
|
+
import type { LLMRequest } from '../../adapters/types.js';
|
|
28
|
+
export declare class OpenAICacheStrategy implements CacheStrategy {
|
|
29
|
+
readonly providerName = "openai";
|
|
30
|
+
readonly capabilities: CacheCapabilities;
|
|
31
|
+
prepareRequest(req: LLMRequest, _candidates: readonly CacheMarker[], _ctx: CacheStrategyContext): Promise<{
|
|
32
|
+
readonly request: LLMRequest;
|
|
33
|
+
readonly markersApplied: readonly CacheMarker[];
|
|
34
|
+
}>;
|
|
35
|
+
extractMetrics(usage: unknown): CacheMetrics | undefined;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=OpenAICacheStrategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenAICacheStrategy.d.ts","sourceRoot":"","sources":["../../../../src/cache/strategies/OpenAICacheStrategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAc1D,qBAAa,mBAAoB,YAAW,aAAa;IACvD,QAAQ,CAAC,YAAY,YAAY;IACjC,QAAQ,CAAC,YAAY,oBAAuB;IAEtC,cAAc,CAClB,GAAG,EAAE,UAAU,EACf,WAAW,EAAE,SAAS,WAAW,EAAE,EACnC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC;QACT,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;QAC7B,QAAQ,CAAC,cAAc,EAAE,SAAS,WAAW,EAAE,CAAC;KACjD,CAAC;IAKF,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS;CAezD"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy registry — maps provider name → CacheStrategy.
|
|
3
|
+
*
|
|
4
|
+
* Auto-resolution at agent build time: agentfootprint inspects
|
|
5
|
+
* `provider.name` and looks up the registered strategy for that
|
|
6
|
+
* name. Falls back to `NoOpCacheStrategy` (registered under wildcard
|
|
7
|
+
* `'*'`) when the provider isn't recognized.
|
|
8
|
+
*
|
|
9
|
+
* Phases shipping registered strategies:
|
|
10
|
+
* - v2.6 Phase 6 (this phase): NoOp
|
|
11
|
+
* - v2.6 Phase 7: AnthropicCacheStrategy ('anthropic',
|
|
12
|
+
* 'browser-anthropic')
|
|
13
|
+
* - v2.6 Phase 8: OpenAICacheStrategy ('openai', 'browser-openai'),
|
|
14
|
+
* BedrockCacheStrategy ('bedrock')
|
|
15
|
+
* - v2.7+ : GeminiCacheStrategy (handle-based, async, deferred)
|
|
16
|
+
*
|
|
17
|
+
* Consumers can register their own strategy via
|
|
18
|
+
* `registerCacheStrategy(strategy)`. Useful for in-house LLM proxies
|
|
19
|
+
* or test mocks.
|
|
20
|
+
*/
|
|
21
|
+
import type { CacheStrategy } from './types.js';
|
|
22
|
+
/**
|
|
23
|
+
* Look up a CacheStrategy by provider name. Falls back to the
|
|
24
|
+
* wildcard NoOp strategy if no match.
|
|
25
|
+
*
|
|
26
|
+
* Lookup is case-insensitive on the provider name.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getDefaultCacheStrategy(providerName: string): CacheStrategy;
|
|
29
|
+
/**
|
|
30
|
+
* Register (or replace) a strategy for a provider name. Called by
|
|
31
|
+
* strategy modules (v2.6 Phase 7+) at module load OR by consumers
|
|
32
|
+
* needing a custom backend. Replacing an existing strategy is allowed
|
|
33
|
+
* — the most-recent registration wins.
|
|
34
|
+
*/
|
|
35
|
+
export declare function registerCacheStrategy(strategy: CacheStrategy): void;
|
|
36
|
+
/**
|
|
37
|
+
* Read-only view of registered strategy names. Useful for diagnostics
|
|
38
|
+
* (e.g., logging "we have strategies for: anthropic, openai, *").
|
|
39
|
+
*/
|
|
40
|
+
export declare function listRegisteredStrategies(): readonly string[];
|
|
41
|
+
/**
|
|
42
|
+
* Internal helper for tests: reset the registry to the default
|
|
43
|
+
* (wildcard → NoOp only). Not exported from the public barrel.
|
|
44
|
+
*/
|
|
45
|
+
export declare function _resetRegistryForTests(): void;
|
|
46
|
+
//# sourceMappingURL=strategyRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategyRegistry.d.ts","sourceRoot":"","sources":["../../../src/cache/strategyRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAYhD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAU3E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAEnE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,SAAS,MAAM,EAAE,CAE5D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C"}
|