/** * CacheDecision subflow — provider-agnostic translation from * `activeInjections + DSL directives` → `CacheMarker[]`. * * This is the core "policy → markers" Lego layer. It runs every * iteration (after slot subflows produce their output, before the * CacheGate decider). Pure transform: no IO, no LLM calls, no * provider knowledge. * * Algorithm: * 1. Build a `CachePolicyContext` from agent state * 2. For each injection in `activeInjections`, evaluate its * `metadata.cache` directive against the context → cacheable boolean * 3. For each slot (system / tools / messages): * a. Walk the slot's contributions in order * b. Find the LAST index that's contiguous-from-start cacheable * c. Emit one CacheMarker at that boundary if any cacheable * * Each marker is provider-agnostic. Provider strategy translates * to wire format in Phase 6+. * * Special case — base system prompt: the agent's * `agent.getSystemPromptCachePolicy()` value is folded in at index 0 * of the system slot. Always-on injections (Steering / Fact / * always-active rules) follow. */ import type { TypedScope } from 'footprintjs'; import type { CacheMarker, CachePolicy, CachePolicyContext } from './types.js'; import type { Injection } from '../lib/injection-engine/types.js'; /** * Subflow scope state. Set via inputMapper from the agent's parent * scope; produces `cacheMarkers` consumed by the BuildLLMRequest stage. */ export interface CacheDecisionState { readonly activeInjections: readonly Injection[]; readonly iteration: number; readonly maxIterations: number; readonly userMessage: string; readonly lastToolName?: string; /** * Cumulative input tokens spent across all LLM calls in THIS * `agent.run()` invocation only. Resets at the start of each turn * (each `agent.run()` call). Predicates can use this for budget- * aware cache invalidation (e.g., "flush cache after 50K tokens"). */ readonly cumulativeInputTokens: number; /** * Base system prompt's cache policy (from * `agent.getSystemPromptCachePolicy()`). Folded in at index 0 of * the system slot's cache evaluation, ahead of any always-on * injections. */ readonly systemPromptCachePolicy: CachePolicy; /** Global kill switch. When `true`, subflow emits zero markers. */ readonly cachingDisabled: boolean; cacheMarkers: readonly CacheMarker[]; } /** * Evaluate a `CachePolicy` against the current context. * Returns `true` if the policy says THIS iteration's content is cacheable. */ export declare function evaluateCachePolicy(policy: CachePolicy, ctx: CachePolicyContext): boolean; /** * Identify which slots an injection contributes to. An injection can * target multiple slots simultaneously (Skills target both system + * tools); we visit each contributing slot independently. */ export declare function injectionTargetSlots(injection: Injection): ReadonlyArray<'system' | 'tools' | 'messages'>; /** * Pure transform: state → markers. Exported so tests can exercise * the algorithm directly without the FlowChartExecutor ceremony of * mounting the subflow as a child of a parent chart. * * The subflow body (`decide` below) is a thin wrapper that pulls * state from scope and delegates here. */ export declare function computeCacheMarkers(state: Omit): readonly CacheMarker[]; /** * The decision stage function. Thin scope-binding wrapper around * `computeCacheMarkers`. Exported so it can serve as the ROOT stage of * the `sf-cache` subflow (a chart cannot start with a nested subflow), * while `cacheDecisionSubflow` below still wraps the SAME function for * standalone use — no logic duplication. */ export declare function decideCacheMarkers(scope: TypedScope): void; //# sourceMappingURL=CacheDecisionSubflow.d.ts.map