open-multi-agent-kit 0.99.0 → 1.0.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/CHANGELOG.md +24 -0
- package/README.md +3 -3
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js +1 -0
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/register-bundled-coding-agent.d.ts +10 -0
- package/dist/bun/register-bundled-coding-agent.d.ts.map +1 -0
- package/dist/bun/register-bundled-coding-agent.js +12 -0
- package/dist/bun/register-bundled-coding-agent.js.map +1 -0
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +1 -1
- package/dist/cli/help.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +14 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/neo-cli.d.ts +9 -0
- package/dist/commands/neo-cli.d.ts.map +1 -0
- package/dist/commands/neo-cli.js +61 -0
- package/dist/commands/neo-cli.js.map +1 -0
- package/dist/core/agent-session.d.ts +29 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +107 -30
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bundled-skills.d.ts +4 -0
- package/dist/core/bundled-skills.d.ts.map +1 -0
- package/dist/core/bundled-skills.js +32 -0
- package/dist/core/bundled-skills.js.map +1 -0
- package/dist/core/cli-diagnostics.d.ts +6 -0
- package/dist/core/cli-diagnostics.d.ts.map +1 -0
- package/dist/core/cli-diagnostics.js +20 -0
- package/dist/core/cli-diagnostics.js.map +1 -0
- package/dist/core/context-budget-headroom.d.ts +12 -0
- package/dist/core/context-budget-headroom.d.ts.map +1 -1
- package/dist/core/context-budget-headroom.js +35 -0
- package/dist/core/context-budget-headroom.js.map +1 -1
- package/dist/core/context-budget-v2-input-validation.d.ts +4 -0
- package/dist/core/context-budget-v2-input-validation.d.ts.map +1 -0
- package/dist/core/context-budget-v2-input-validation.js +79 -0
- package/dist/core/context-budget-v2-input-validation.js.map +1 -0
- package/dist/core/context-budget-v2-observability.d.ts +15 -0
- package/dist/core/context-budget-v2-observability.d.ts.map +1 -0
- package/dist/core/context-budget-v2-observability.js +35 -0
- package/dist/core/context-budget-v2-observability.js.map +1 -0
- package/dist/core/context-budget-v2-planned-items.d.ts +5 -0
- package/dist/core/context-budget-v2-planned-items.d.ts.map +1 -0
- package/dist/core/context-budget-v2-planned-items.js +40 -0
- package/dist/core/context-budget-v2-planned-items.js.map +1 -0
- package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
- package/dist/core/context-budget-v2-planner.js +57 -38
- package/dist/core/context-budget-v2-planner.js.map +1 -1
- package/dist/core/context-budget-v2-selection.d.ts +19 -3
- package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
- package/dist/core/context-budget-v2-selection.js +35 -57
- package/dist/core/context-budget-v2-selection.js.map +1 -1
- package/dist/core/context-budget-v2-tiers.d.ts.map +1 -1
- package/dist/core/context-budget-v2-tiers.js +9 -42
- package/dist/core/context-budget-v2-tiers.js.map +1 -1
- package/dist/core/context-budget-v2-types.d.ts +8 -1
- package/dist/core/context-budget-v2-types.d.ts.map +1 -1
- package/dist/core/context-budget-v2-types.js.map +1 -1
- package/dist/core/extensions/bundled-virtual-modules.d.ts +15 -0
- package/dist/core/extensions/bundled-virtual-modules.d.ts.map +1 -0
- package/dist/core/extensions/bundled-virtual-modules.js +63 -0
- package/dist/core/extensions/bundled-virtual-modules.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -42
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +6 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +10 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/loadout-runtime.d.ts +2 -8
- package/dist/core/loadout-runtime.d.ts.map +1 -1
- package/dist/core/loadout-runtime.js.map +1 -1
- package/dist/core/mcp/client.d.ts +27 -6
- package/dist/core/mcp/client.d.ts.map +1 -1
- package/dist/core/mcp/client.js +80 -20
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/manager.d.ts +10 -1
- package/dist/core/mcp/manager.d.ts.map +1 -1
- package/dist/core/mcp/manager.js +68 -9
- package/dist/core/mcp/manager.js.map +1 -1
- package/dist/core/mcp/protocol.d.ts +9 -3
- package/dist/core/mcp/protocol.d.ts.map +1 -1
- package/dist/core/mcp/protocol.js +61 -15
- package/dist/core/mcp/protocol.js.map +1 -1
- package/dist/core/mcp/stdio-transport.d.ts +12 -1
- package/dist/core/mcp/stdio-transport.d.ts.map +1 -1
- package/dist/core/mcp/stdio-transport.js +30 -2
- package/dist/core/mcp/stdio-transport.js.map +1 -1
- package/dist/core/mcp-descriptor-injection.d.ts +26 -0
- package/dist/core/mcp-descriptor-injection.d.ts.map +1 -0
- package/dist/core/mcp-descriptor-injection.js +25 -0
- package/dist/core/mcp-descriptor-injection.js.map +1 -0
- package/dist/core/mcp-public-presets.d.ts +1 -3
- package/dist/core/mcp-public-presets.d.ts.map +1 -1
- package/dist/core/mcp-public-presets.js +3 -15
- package/dist/core/mcp-public-presets.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +24 -3
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/neo/catalog.d.ts +20 -0
- package/dist/core/neo/catalog.d.ts.map +1 -0
- package/dist/core/neo/catalog.js +50 -0
- package/dist/core/neo/catalog.js.map +1 -0
- package/dist/core/neo/setup.d.ts +3 -0
- package/dist/core/neo/setup.d.ts.map +1 -0
- package/dist/core/neo/setup.js +47 -0
- package/dist/core/neo/setup.js.map +1 -0
- package/dist/core/provider-default-models.d.ts +1 -0
- package/dist/core/provider-default-models.d.ts.map +1 -1
- package/dist/core/provider-default-models.js +1 -0
- package/dist/core/provider-default-models.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +1 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/provider-error-classification.d.ts +57 -0
- package/dist/core/provider-error-classification.d.ts.map +1 -0
- package/dist/core/provider-error-classification.js +103 -0
- package/dist/core/provider-error-classification.js.map +1 -0
- package/dist/core/provider-resilience.d.ts +10 -0
- package/dist/core/provider-resilience.d.ts.map +1 -1
- package/dist/core/provider-resilience.js +36 -3
- package/dist/core/provider-resilience.js.map +1 -1
- package/dist/core/provider-usage-commandcode.d.ts +9 -0
- package/dist/core/provider-usage-commandcode.d.ts.map +1 -0
- package/dist/core/provider-usage-commandcode.js +198 -0
- package/dist/core/provider-usage-commandcode.js.map +1 -0
- package/dist/core/provider-usage-devin.d.ts +5 -3
- package/dist/core/provider-usage-devin.d.ts.map +1 -1
- package/dist/core/provider-usage-devin.js +15 -5
- package/dist/core/provider-usage-devin.js.map +1 -1
- package/dist/core/provider-usage-types.d.ts +1 -1
- package/dist/core/provider-usage-types.d.ts.map +1 -1
- package/dist/core/provider-usage-types.js.map +1 -1
- package/dist/core/provider-usage.d.ts.map +1 -1
- package/dist/core/provider-usage.js +6 -0
- package/dist/core/provider-usage.js.map +1 -1
- package/dist/core/resource-admission.d.ts +36 -0
- package/dist/core/resource-admission.d.ts.map +1 -1
- package/dist/core/resource-admission.js +59 -0
- package/dist/core/resource-admission.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +2 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/run-usage-ledger.d.ts +47 -0
- package/dist/core/run-usage-ledger.d.ts.map +1 -0
- package/dist/core/run-usage-ledger.js +162 -0
- package/dist/core/run-usage-ledger.js.map +1 -0
- package/dist/core/run-usage-operation.d.ts +8 -0
- package/dist/core/run-usage-operation.d.ts.map +1 -0
- package/dist/core/run-usage-operation.js +12 -0
- package/dist/core/run-usage-operation.js.map +1 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +5 -6
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-failure-cause.d.ts.map +1 -1
- package/dist/core/session-failure-cause.js +14 -5
- package/dist/core/session-failure-cause.js.map +1 -1
- package/dist/core/session-prompt-lifecycle.d.ts +6 -0
- package/dist/core/session-prompt-lifecycle.d.ts.map +1 -1
- package/dist/core/session-prompt-lifecycle.js +47 -2
- package/dist/core/session-prompt-lifecycle.js.map +1 -1
- package/dist/core/session-termination.d.ts.map +1 -1
- package/dist/core/session-termination.js +4 -2
- package/dist/core/session-termination.js.map +1 -1
- package/dist/core/subagent-lane-authority.d.ts +28 -0
- package/dist/core/subagent-lane-authority.d.ts.map +1 -0
- package/dist/core/subagent-lane-authority.js +119 -0
- package/dist/core/subagent-lane-authority.js.map +1 -0
- package/dist/core/subagent-lane-contract.d.ts +114 -0
- package/dist/core/subagent-lane-contract.d.ts.map +1 -0
- package/dist/core/subagent-lane-contract.js +18 -0
- package/dist/core/subagent-lane-contract.js.map +1 -0
- package/dist/core/subagent-lane-launcher.d.ts +3 -6
- package/dist/core/subagent-lane-launcher.d.ts.map +1 -1
- package/dist/core/subagent-lane-launcher.js +53 -12
- package/dist/core/subagent-lane-launcher.js.map +1 -1
- package/dist/core/subagent-orchestration.d.ts +4 -17
- package/dist/core/subagent-orchestration.d.ts.map +1 -1
- package/dist/core/subagent-orchestration.js.map +1 -1
- package/dist/core/verified-run/broker.d.ts.map +1 -1
- package/dist/core/verified-run/broker.js +4 -1
- package/dist/core/verified-run/broker.js.map +1 -1
- package/dist/core/workload-permit-pool.d.ts +1 -1
- package/dist/core/workload-permit-pool.d.ts.map +1 -1
- package/dist/core/workload-permit-pool.js +3 -0
- package/dist/core/workload-permit-pool.js.map +1 -1
- package/dist/guardrails/strict-evidence-approval-adapter.d.ts +34 -0
- package/dist/guardrails/strict-evidence-approval-adapter.d.ts.map +1 -0
- package/dist/guardrails/strict-evidence-approval-adapter.js +70 -0
- package/dist/guardrails/strict-evidence-approval-adapter.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +11 -18
- package/dist/main.js.map +1 -1
- package/dist/modes/acp/acp-agent.d.ts +24 -0
- package/dist/modes/acp/acp-agent.d.ts.map +1 -0
- package/dist/modes/acp/acp-agent.js +133 -0
- package/dist/modes/acp/acp-agent.js.map +1 -0
- package/dist/modes/acp/acp-mode.d.ts +4 -0
- package/dist/modes/acp/acp-mode.d.ts.map +1 -0
- package/dist/modes/acp/acp-mode.js +34 -0
- package/dist/modes/acp/acp-mode.js.map +1 -0
- package/dist/modes/acp/acp-session.d.ts +4 -0
- package/dist/modes/acp/acp-session.d.ts.map +1 -0
- package/dist/modes/acp/acp-session.js +76 -0
- package/dist/modes/acp/acp-session.js.map +1 -0
- package/dist/modes/acp/acp-transport.d.ts +5 -0
- package/dist/modes/acp/acp-transport.d.ts.map +1 -0
- package/dist/modes/acp/acp-transport.js +90 -0
- package/dist/modes/acp/acp-transport.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/audit-revalidation-2026-09-17.md +77 -0
- package/docs/devin-harness.md +33 -4
- package/docs/ecraf-normalization.md +83 -0
- package/docs/model-catalog-refresh.md +51 -1
- package/docs/models.md +1 -1
- package/docs/neo.md +134 -0
- package/docs/providers.md +72 -6
- package/docs/run-usage-ledger.md +56 -0
- package/docs/runtime-algorithms.md +44 -0
- package/docs/skills.md +1 -1
- package/docs/usage.md +2 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/subagent/adaptive-agent-runtime.ts +14 -1
- package/examples/extensions/subagent/graph-result.ts +48 -0
- package/examples/extensions/subagent/index.ts +246 -111
- package/examples/extensions/subagent/managed-process-tree.ts +42 -0
- package/examples/extensions/subagent/managed-process.test.ts +24 -0
- package/examples/extensions/subagent/managed-process.ts +93 -112
- package/examples/extensions/subagent/subagent-runtime-types.ts +17 -1
- package/examples/extensions/subagent/subagent-stream.ts +161 -0
- package/examples/extensions/terminal-browser/README.md +54 -0
- package/examples/extensions/terminal-browser/bridge-protocol.ts +29 -0
- package/examples/extensions/terminal-browser/bridge.ts +219 -0
- package/examples/extensions/terminal-browser/browser-surface.ts +288 -0
- package/examples/extensions/terminal-browser/index.ts +215 -0
- package/examples/extensions/terminal-browser/placeholders.ts +49 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +18 -18
- package/package.json +8 -7
- package/resources/neo/skills/omk-browser/SKILL.md +32 -0
- package/resources/neo/skills/omk-code-review/SKILL.md +24 -0
- package/resources/neo/skills/omk-computeruse/SKILL.md +34 -0
- package/resources/neo/skills/omk-mcp-setup/SKILL.md +48 -0
- package/resources/neo/skills/omk-research/SKILL.md +24 -0
- package/resources/neo/skills/omk-site/SKILL.md +28 -0
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { DEFAULT_HEADROOM_QUALITY_POLICY, } from "./context-budget-headroom.js";
|
|
2
2
|
import { buildContextBudgetPlanCacheKeyV2, createContextBudgetCacheKeyBaseV2, createContextBudgetSelectionCacheV2, finalizeContextBudgetCacheTelemetryV2, readValidPlanCacheV2, writePlanCacheV2, } from "./context-budget-v2-cache.js";
|
|
3
|
+
import { validateBudgetItems } from "./context-budget-v2-input-validation.js";
|
|
4
|
+
import { buildObservability } from "./context-budget-v2-observability.js";
|
|
3
5
|
import { computePlanHash } from "./context-budget-v2-plan-hash.js";
|
|
6
|
+
import { createPlannedItems } from "./context-budget-v2-planned-items.js";
|
|
4
7
|
import { compareOptionalForSelection } from "./context-budget-v2-scoring.js";
|
|
5
|
-
import { applyPlannerRedundancyPenalties, buildTierAllocations,
|
|
8
|
+
import { applyPlannerRedundancyPenalties, buildTierAllocations, createTierUsage, emitCoverageDiagnostics, emitOmissionDiagnostics, selectHardItem, selectOptionalItem, } from "./context-budget-v2-selection.js";
|
|
6
9
|
import { allocateTiers, computeTierDemand } from "./context-budget-v2-tiers.js";
|
|
7
|
-
import { CONTEXT_BUDGET_POLICY_VERSION_V2, DEFAULT_TIER_POLICY_V2, } from "./context-budget-v2-types.js";
|
|
8
|
-
const TOKEN_OPTIMIZER_RUNTIME_STATUS = {
|
|
9
|
-
optimizerId: "legacy-token-optimizer",
|
|
10
|
-
status: "quarantined_compatibility",
|
|
11
|
-
active: false,
|
|
12
|
-
activeContextBudgetOptimizer: "context-budget-v2",
|
|
13
|
-
compatibilityOnly: true,
|
|
14
|
-
};
|
|
10
|
+
import { ALL_TIERS_V2, CONTEXT_BUDGET_POLICY_VERSION_V2, DEFAULT_TIER_POLICY_V2, } from "./context-budget-v2-types.js";
|
|
15
11
|
export function planPromptContextBudgetV2(input) {
|
|
16
12
|
const modelId = input.modelId ?? "unknown";
|
|
17
13
|
const qualityPolicy = input.qualityPolicy ?? DEFAULT_HEADROOM_QUALITY_POLICY;
|
|
@@ -21,12 +17,13 @@ export function planPromptContextBudgetV2(input) {
|
|
|
21
17
|
const responseReserve = normalizeBudgetTokens("responseReserveTokens", input.responseReserveTokens ?? 0, diagnostics);
|
|
22
18
|
const safetyMargin = normalizeBudgetTokens("safetyMarginTokens", input.safetyMarginTokens ?? Math.ceil(maxTokens * 0.05), diagnostics);
|
|
23
19
|
const available = Math.max(0, maxTokens - responseReserve - safetyMargin);
|
|
24
|
-
const canUsePlanCache = !diagnostics.some((diagnostic) => diagnostic.reason === "invalid_budget");
|
|
25
20
|
const tierPolicy = {
|
|
26
21
|
...DEFAULT_TIER_POLICY_V2,
|
|
27
22
|
...(input.tierPolicy ?? {}),
|
|
28
23
|
};
|
|
29
|
-
const basePlanned = createPlannedItems(input.items, input.tokenCounter, modelId, qualityPolicy);
|
|
24
|
+
const basePlanned = createPlannedItems(validateBudgetItems(input.items, diagnostics), input.tokenCounter, modelId, qualityPolicy);
|
|
25
|
+
// Sanitized items can share a key with valid input, but their diagnostics cannot.
|
|
26
|
+
const canUsePlanCache = diagnostics.length === 0;
|
|
30
27
|
applyPlannerRedundancyPenalties(basePlanned);
|
|
31
28
|
const rawTokens = basePlanned.reduce((sum, planned) => sum + planned.fullTokens, 0);
|
|
32
29
|
const demand = computeTierDemand(basePlanned);
|
|
@@ -90,7 +87,55 @@ export function planPromptContextBudgetV2(input) {
|
|
|
90
87
|
});
|
|
91
88
|
}
|
|
92
89
|
const optionalPlanned = basePlanned.filter((planned) => !planned.isHard).sort(compareOptionalForSelection);
|
|
90
|
+
// Floor-reservation pass: each tier spends its guaranteed claim (the
|
|
91
|
+
// `allocated` field — hard demand, else demand capped at the floor) on its
|
|
92
|
+
// own optional items before anything competes globally. A tier's floor is
|
|
93
|
+
// therefore a real reservation, not a lower bound on its ceiling. Items
|
|
94
|
+
// that cannot fit inside the remaining floor stay unselected for the
|
|
95
|
+
// global pass; when the summed floors exceed the budget the reservation is
|
|
96
|
+
// best-effort in tier order and the plan reports it explicitly.
|
|
97
|
+
// One cache-resolution per item, shared by both passes so an item that is
|
|
98
|
+
// deferred out of the floor and reconsidered globally does not double
|
|
99
|
+
// count provider reads or redo materialization work.
|
|
100
|
+
const resolvedCandidates = new Map();
|
|
101
|
+
let totalFloor = 0;
|
|
102
|
+
for (const tier of ALL_TIERS_V2) {
|
|
103
|
+
totalFloor += allocation.get(tier)?.floor ?? 0;
|
|
104
|
+
}
|
|
105
|
+
if (totalFloor > available) {
|
|
106
|
+
diagnostics.push({
|
|
107
|
+
reason: "tier_floor_over_budget",
|
|
108
|
+
detail: `tier floor guarantees total ${totalFloor} tokens against ${available} available; floors degrade to tier-order best effort`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
for (const tier of ALL_TIERS_V2) {
|
|
112
|
+
const floor = allocation.get(tier)?.floor ?? 0;
|
|
113
|
+
if (floor <= 0 || tierUsed[tier] >= floor)
|
|
114
|
+
continue;
|
|
115
|
+
for (const planned of optionalPlanned) {
|
|
116
|
+
if (planned.item.tier !== tier || selection.has(planned.item.id))
|
|
117
|
+
continue;
|
|
118
|
+
usedTokens = selectOptionalItem(planned, {
|
|
119
|
+
allocation,
|
|
120
|
+
available,
|
|
121
|
+
cache,
|
|
122
|
+
diagnostics,
|
|
123
|
+
omitted,
|
|
124
|
+
qualityPolicy,
|
|
125
|
+
retrievalFallbacks,
|
|
126
|
+
selection,
|
|
127
|
+
tierUsed,
|
|
128
|
+
usedTokens,
|
|
129
|
+
floorReservation: { tier, floorTokens: floor },
|
|
130
|
+
resolvedCandidates,
|
|
131
|
+
});
|
|
132
|
+
if (tierUsed[tier] >= floor || usedTokens >= available)
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
93
136
|
for (const planned of optionalPlanned) {
|
|
137
|
+
if (selection.has(planned.item.id))
|
|
138
|
+
continue;
|
|
94
139
|
usedTokens = selectOptionalItem(planned, {
|
|
95
140
|
allocation,
|
|
96
141
|
available,
|
|
@@ -98,6 +143,7 @@ export function planPromptContextBudgetV2(input) {
|
|
|
98
143
|
diagnostics,
|
|
99
144
|
omitted,
|
|
100
145
|
qualityPolicy,
|
|
146
|
+
resolvedCandidates,
|
|
101
147
|
retrievalFallbacks,
|
|
102
148
|
selection,
|
|
103
149
|
tierUsed,
|
|
@@ -179,31 +225,4 @@ function normalizeBudgetTokens(field, value, diagnostics) {
|
|
|
179
225
|
}
|
|
180
226
|
return Math.floor(value);
|
|
181
227
|
}
|
|
182
|
-
function buildObservability(input) {
|
|
183
|
-
const selected = [...input.selection.values()];
|
|
184
|
-
return {
|
|
185
|
-
counts: {
|
|
186
|
-
selected: selected.length,
|
|
187
|
-
omitted: input.omittedItemIds.length,
|
|
188
|
-
pointer: selected.filter((representation) => representation.kind === "pointer").length,
|
|
189
|
-
compressed: selected.filter((representation) => representation.kind === "headroom-compressed").length,
|
|
190
|
-
full: selected.filter((representation) => representation.kind === "full").length,
|
|
191
|
-
retrievalFallback: countUniqueRetrievalFallbacks(input.retrievalFallbacks),
|
|
192
|
-
},
|
|
193
|
-
diagnosticReasons: [...new Set(input.diagnostics.map((diagnostic) => diagnostic.reason))].sort(),
|
|
194
|
-
tokens: {
|
|
195
|
-
available: input.available,
|
|
196
|
-
used: input.usedTokens,
|
|
197
|
-
raw: input.rawTokens,
|
|
198
|
-
omitted: input.omittedTokens,
|
|
199
|
-
tokenSavings: Math.max(0, input.rawTokens - input.usedTokens),
|
|
200
|
-
},
|
|
201
|
-
planHash: input.planHash,
|
|
202
|
-
cache: input.cacheTelemetry,
|
|
203
|
-
tokenOptimizer: TOKEN_OPTIMIZER_RUNTIME_STATUS,
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
function countUniqueRetrievalFallbacks(retrievalFallbacks) {
|
|
207
|
-
return new Set(retrievalFallbacks.map((ref) => [ref.uri, ref.contentHash, ref.symbol ?? "", ref.range?.startLine ?? "", ref.range?.endLine ?? ""].join("\0"))).size;
|
|
208
|
-
}
|
|
209
228
|
//# sourceMappingURL=context-budget-v2-planner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-budget-v2-planner.js","sourceRoot":"","sources":["../../src/core/context-budget-v2-planner.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype ContextBudgetItemV2,\n\ttype ContextBudgetTierV2,\n\ttype ContextSourceRefV2,\n\tDEFAULT_HEADROOM_QUALITY_POLICY,\n} from \"./context-budget-headroom.ts\";\nimport {\n\tbuildContextBudgetPlanCacheKeyV2,\n\tcreateContextBudgetCacheKeyBaseV2,\n\tcreateContextBudgetSelectionCacheV2,\n\tfinalizeContextBudgetCacheTelemetryV2,\n\treadValidPlanCacheV2,\n\twritePlanCacheV2,\n} from \"./context-budget-v2-cache.ts\";\nimport { computePlanHash } from \"./context-budget-v2-plan-hash.ts\";\nimport { compareOptionalForSelection } from \"./context-budget-v2-scoring.ts\";\nimport {\n\tapplyPlannerRedundancyPenalties,\n\tbuildTierAllocations,\n\tcreatePlannedItems,\n\tcreateTierUsage,\n\temitCoverageDiagnostics,\n\temitOmissionDiagnostics,\n\tselectHardItem,\n\tselectOptionalItem,\n} from \"./context-budget-v2-selection.ts\";\nimport { allocateTiers, computeTierDemand } from \"./context-budget-v2-tiers.ts\";\nimport {\n\tCONTEXT_BUDGET_POLICY_VERSION_V2,\n\tDEFAULT_TIER_POLICY_V2,\n\ttype PromptContextBudgetInputV2,\n\ttype PromptContextBudgetObservabilityV2,\n\ttype PromptContextBudgetPlanV2,\n\ttype QualityDiagnosticV2,\n\ttype SelectedRepresentationV2,\n\ttype TierBudgetPolicyV2,\n\ttype TokenOptimizerRuntimeStatus,\n} from \"./context-budget-v2-types.ts\";\n\nconst TOKEN_OPTIMIZER_RUNTIME_STATUS: TokenOptimizerRuntimeStatus = {\n\toptimizerId: \"legacy-token-optimizer\",\n\tstatus: \"quarantined_compatibility\",\n\tactive: false,\n\tactiveContextBudgetOptimizer: \"context-budget-v2\",\n\tcompatibilityOnly: true,\n};\n\nexport function planPromptContextBudgetV2(input: PromptContextBudgetInputV2): PromptContextBudgetPlanV2 {\n\tconst modelId = input.modelId ?? \"unknown\";\n\tconst qualityPolicy = input.qualityPolicy ?? DEFAULT_HEADROOM_QUALITY_POLICY;\n\tconst policyVersion = input.policyVersion ?? CONTEXT_BUDGET_POLICY_VERSION_V2;\n\tconst diagnostics: QualityDiagnosticV2[] = [];\n\n\tconst maxTokens = normalizeBudgetTokens(\"maxTokens\", input.maxTokens, diagnostics);\n\tconst responseReserve = normalizeBudgetTokens(\n\t\t\"responseReserveTokens\",\n\t\tinput.responseReserveTokens ?? 0,\n\t\tdiagnostics,\n\t);\n\tconst safetyMargin = normalizeBudgetTokens(\n\t\t\"safetyMarginTokens\",\n\t\tinput.safetyMarginTokens ?? Math.ceil(maxTokens * 0.05),\n\t\tdiagnostics,\n\t);\n\tconst available = Math.max(0, maxTokens - responseReserve - safetyMargin);\n\tconst canUsePlanCache = !diagnostics.some((diagnostic) => diagnostic.reason === \"invalid_budget\");\n\n\tconst tierPolicy: Readonly<Record<ContextBudgetTierV2, TierBudgetPolicyV2>> = {\n\t\t...DEFAULT_TIER_POLICY_V2,\n\t\t...(input.tierPolicy ?? {}),\n\t};\n\tconst basePlanned = createPlannedItems(input.items, input.tokenCounter, modelId, qualityPolicy);\n\tapplyPlannerRedundancyPenalties(basePlanned);\n\tconst rawTokens = basePlanned.reduce((sum, planned) => sum + planned.fullTokens, 0);\n\n\tconst demand = computeTierDemand(basePlanned);\n\tconst allocation = allocateTiers(available, tierPolicy, demand);\n\tconst cacheKeyBase = createContextBudgetCacheKeyBaseV2({\n\t\tbudgetBucket: input.cacheBudgetBucket ?? String(available),\n\t\tcacheInvalidationSnapshot: input.cacheInvalidationSnapshot ?? input.cacheProvider?.getInvalidationSnapshot?.(),\n\t\tmodelId,\n\t\tnamespace: input.cacheNamespace,\n\t\tpolicyVersion,\n\t\tselectionPolicyVersion: input.selectionPolicyVersion,\n\t\tquery: input.query,\n\t\tqueryIntentHash: input.queryIntentHash,\n\t\tredactionPolicyHash: input.redactionPolicyHash,\n\t\tsafetyProfileHash: input.safetyProfileHash,\n\t\ttokenizerId: input.tokenizerId,\n\t});\n\tconst planCacheKey = buildContextBudgetPlanCacheKeyV2({\n\t\tavailableTokens: available,\n\t\tkeyBase: cacheKeyBase,\n\t\tmaxTokens,\n\t\tplanned: basePlanned,\n\t\tpromptHash: input.promptHash,\n\t\tqualityPolicy,\n\t\tresponseReserveTokens: responseReserve,\n\t\tsafetyMarginTokens: safetyMargin,\n\t\ttierPolicy,\n\t});\n\tconst cache = createContextBudgetSelectionCacheV2({\n\t\tkeyBase: cacheKeyBase,\n\t\tnowEpochMs: input.cacheNowEpochMs,\n\t\tplanCacheKey,\n\t\tprovider: input.cacheProvider,\n\t\tttlMs: input.cacheTtlMs,\n\t});\n\tconst cachedPlan = canUsePlanCache\n\t\t? readValidPlanCacheV2({\n\t\t\t\tavailableTokens: available,\n\t\t\t\tcache,\n\t\t\t\tkey: planCacheKey,\n\t\t\t\tplanned: basePlanned,\n\t\t\t})\n\t\t: undefined;\n\tif (cachedPlan) {\n\t\treturn cachedPlan;\n\t}\n\tconst selection = new Map<string, SelectedRepresentationV2>();\n\tconst tierUsed = createTierUsage();\n\tconst omitted: ContextBudgetItemV2[] = [];\n\tconst retrievalFallbacks: ContextSourceRefV2[] = [];\n\tlet usedTokens = 0;\n\n\tfor (const planned of basePlanned) {\n\t\tif (!planned.isHard) continue;\n\t\tusedTokens += selectHardItem(planned, selection, tierUsed);\n\t}\n\tif (usedTokens > available) {\n\t\tdiagnostics.push({\n\t\t\treason: \"hard_pin_over_capacity\",\n\t\t\tdetail: `hard-pinned context uses ${usedTokens} tokens against ${available} available tokens`,\n\t\t});\n\t}\n\n\tconst optionalPlanned = basePlanned.filter((planned) => !planned.isHard).sort(compareOptionalForSelection);\n\tfor (const planned of optionalPlanned) {\n\t\tusedTokens = selectOptionalItem(planned, {\n\t\t\tallocation,\n\t\t\tavailable,\n\t\t\tcache,\n\t\t\tdiagnostics,\n\t\t\tomitted,\n\t\t\tqualityPolicy,\n\t\t\tretrievalFallbacks,\n\t\t\tselection,\n\t\t\ttierUsed,\n\t\t\tusedTokens,\n\t\t});\n\t}\n\n\tconst omittedHighPriority = omitted.some((item) => item.priority === \"high\" || item.required === true);\n\temitOmissionDiagnostics(omitted, diagnostics, retrievalFallbacks);\n\temitCoverageDiagnostics(input.query, selection, diagnostics);\n\n\tconst tierAllocations = buildTierAllocations(allocation, demand, tierUsed);\n\tconst omittedTokens = omitted.reduce(\n\t\t(sum, item) => sum + (basePlanned.find((planned) => planned.item.id === item.id)?.fullTokens ?? 0),\n\t\t0,\n\t);\n\tconst omittedItemIds = omitted.map((item) => item.id);\n\tconst planHash = computePlanHash({\n\t\tpolicyVersion,\n\t\tpromptHash: input.promptHash,\n\t\tplanned: basePlanned,\n\t\tselection,\n\t\tallocations: tierAllocations,\n\t\tomittedItemIds,\n\t});\n\tconst observability = buildObservability({\n\t\tavailable,\n\t\tdiagnostics,\n\t\tomittedItemIds,\n\t\tomittedTokens,\n\t\tplanHash,\n\t\trawTokens,\n\t\tretrievalFallbacks,\n\t\tselection,\n\t\tusedTokens,\n\t\tcacheTelemetry: finalizeContextBudgetCacheTelemetryV2(cache.telemetry, {\n\t\t\tomittedTokens,\n\t\t\trawTokens,\n\t\t\tusedTokens,\n\t\t}),\n\t});\n\n\tconst plan: PromptContextBudgetPlanV2 = {\n\t\tpolicyVersion,\n\t\tpromptHash: input.promptHash,\n\t\tplanHash,\n\t\tmaxTokens,\n\t\tresponseReserveTokens: responseReserve,\n\t\tsafetyMarginTokens: safetyMargin,\n\t\tavailableTokens: available,\n\t\tusedTokens,\n\t\tomittedTokens,\n\t\trawTokens,\n\t\ttokenSavingsRatio: rawTokens > 0 ? Math.max(0, 1 - usedTokens / rawTokens) : 0,\n\t\temergency: usedTokens > available || diagnostics.some((diagnostic) => diagnostic.reason === \"invalid_budget\"),\n\t\tomittedHighPriority,\n\t\ttierAllocations,\n\t\tselectedRepresentations: [...selection.values()].sort((a, b) => a.itemId.localeCompare(b.itemId)),\n\t\tincludedItemIds: basePlanned\n\t\t\t.map((planned) => planned.item.id)\n\t\t\t.filter((id) => selection.has(id))\n\t\t\t.sort(),\n\t\tomittedItemIds,\n\t\tdiagnostics,\n\t\tretrievalFallbacks,\n\t\tobservability,\n\t};\n\tif (canUsePlanCache) {\n\t\twritePlanCacheV2({\n\t\t\tcache,\n\t\t\tkey: planCacheKey,\n\t\t\tplan,\n\t\t\tplanned: basePlanned,\n\t\t});\n\t}\n\treturn plan;\n}\n\nfunction normalizeBudgetTokens(field: string, value: number, diagnostics: QualityDiagnosticV2[]): number {\n\tif (!Number.isFinite(value) || value < 0) {\n\t\tdiagnostics.push({\n\t\t\treason: \"invalid_budget\",\n\t\t\tdetail: `${field} must be a non-negative finite number, got ${value}`,\n\t\t});\n\t\treturn 0;\n\t}\n\treturn Math.floor(value);\n}\n\nfunction buildObservability(input: {\n\treadonly available: number;\n\treadonly diagnostics: readonly QualityDiagnosticV2[];\n\treadonly omittedItemIds: readonly string[];\n\treadonly omittedTokens: number;\n\treadonly planHash: string;\n\treadonly rawTokens: number;\n\treadonly retrievalFallbacks: readonly ContextSourceRefV2[];\n\treadonly selection: ReadonlyMap<string, SelectedRepresentationV2>;\n\treadonly usedTokens: number;\n\treadonly cacheTelemetry: PromptContextBudgetObservabilityV2[\"cache\"];\n}): PromptContextBudgetObservabilityV2 {\n\tconst selected = [...input.selection.values()];\n\treturn {\n\t\tcounts: {\n\t\t\tselected: selected.length,\n\t\t\tomitted: input.omittedItemIds.length,\n\t\t\tpointer: selected.filter((representation) => representation.kind === \"pointer\").length,\n\t\t\tcompressed: selected.filter((representation) => representation.kind === \"headroom-compressed\").length,\n\t\t\tfull: selected.filter((representation) => representation.kind === \"full\").length,\n\t\t\tretrievalFallback: countUniqueRetrievalFallbacks(input.retrievalFallbacks),\n\t\t},\n\t\tdiagnosticReasons: [...new Set(input.diagnostics.map((diagnostic) => diagnostic.reason))].sort(),\n\t\ttokens: {\n\t\t\tavailable: input.available,\n\t\t\tused: input.usedTokens,\n\t\t\traw: input.rawTokens,\n\t\t\tomitted: input.omittedTokens,\n\t\t\ttokenSavings: Math.max(0, input.rawTokens - input.usedTokens),\n\t\t},\n\t\tplanHash: input.planHash,\n\t\tcache: input.cacheTelemetry,\n\t\ttokenOptimizer: TOKEN_OPTIMIZER_RUNTIME_STATUS,\n\t};\n}\n\nfunction countUniqueRetrievalFallbacks(retrievalFallbacks: readonly ContextSourceRefV2[]): number {\n\treturn new Set(\n\t\tretrievalFallbacks.map((ref) =>\n\t\t\t[ref.uri, ref.contentHash, ref.symbol ?? \"\", ref.range?.startLine ?? \"\", ref.range?.endLine ?? \"\"].join(\"\\0\"),\n\t\t),\n\t).size;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"context-budget-v2-planner.js","sourceRoot":"","sources":["../../src/core/context-budget-v2-planner.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype ContextBudgetItemV2,\n\ttype ContextBudgetTierV2,\n\ttype ContextRepresentationCandidateV2,\n\ttype ContextSourceRefV2,\n\tDEFAULT_HEADROOM_QUALITY_POLICY,\n} from \"./context-budget-headroom.ts\";\nimport {\n\tbuildContextBudgetPlanCacheKeyV2,\n\tcreateContextBudgetCacheKeyBaseV2,\n\tcreateContextBudgetSelectionCacheV2,\n\tfinalizeContextBudgetCacheTelemetryV2,\n\treadValidPlanCacheV2,\n\twritePlanCacheV2,\n} from \"./context-budget-v2-cache.ts\";\nimport { validateBudgetItems } from \"./context-budget-v2-input-validation.ts\";\nimport { buildObservability } from \"./context-budget-v2-observability.ts\";\nimport { computePlanHash } from \"./context-budget-v2-plan-hash.ts\";\nimport { createPlannedItems } from \"./context-budget-v2-planned-items.ts\";\nimport { compareOptionalForSelection } from \"./context-budget-v2-scoring.ts\";\nimport {\n\tapplyPlannerRedundancyPenalties,\n\tbuildTierAllocations,\n\tcreateTierUsage,\n\temitCoverageDiagnostics,\n\temitOmissionDiagnostics,\n\tselectHardItem,\n\tselectOptionalItem,\n} from \"./context-budget-v2-selection.ts\";\nimport { allocateTiers, computeTierDemand } from \"./context-budget-v2-tiers.ts\";\nimport {\n\tALL_TIERS_V2,\n\tCONTEXT_BUDGET_POLICY_VERSION_V2,\n\tDEFAULT_TIER_POLICY_V2,\n\ttype PromptContextBudgetInputV2,\n\ttype PromptContextBudgetPlanV2,\n\ttype QualityDiagnosticV2,\n\ttype SelectedRepresentationV2,\n\ttype TierBudgetPolicyV2,\n} from \"./context-budget-v2-types.ts\";\n\nexport function planPromptContextBudgetV2(input: PromptContextBudgetInputV2): PromptContextBudgetPlanV2 {\n\tconst modelId = input.modelId ?? \"unknown\";\n\tconst qualityPolicy = input.qualityPolicy ?? DEFAULT_HEADROOM_QUALITY_POLICY;\n\tconst policyVersion = input.policyVersion ?? CONTEXT_BUDGET_POLICY_VERSION_V2;\n\tconst diagnostics: QualityDiagnosticV2[] = [];\n\n\tconst maxTokens = normalizeBudgetTokens(\"maxTokens\", input.maxTokens, diagnostics);\n\tconst responseReserve = normalizeBudgetTokens(\n\t\t\"responseReserveTokens\",\n\t\tinput.responseReserveTokens ?? 0,\n\t\tdiagnostics,\n\t);\n\tconst safetyMargin = normalizeBudgetTokens(\n\t\t\"safetyMarginTokens\",\n\t\tinput.safetyMarginTokens ?? Math.ceil(maxTokens * 0.05),\n\t\tdiagnostics,\n\t);\n\tconst available = Math.max(0, maxTokens - responseReserve - safetyMargin);\n\n\tconst tierPolicy: Readonly<Record<ContextBudgetTierV2, TierBudgetPolicyV2>> = {\n\t\t...DEFAULT_TIER_POLICY_V2,\n\t\t...(input.tierPolicy ?? {}),\n\t};\n\tconst basePlanned = createPlannedItems(\n\t\tvalidateBudgetItems(input.items, diagnostics),\n\t\tinput.tokenCounter,\n\t\tmodelId,\n\t\tqualityPolicy,\n\t);\n\t// Sanitized items can share a key with valid input, but their diagnostics cannot.\n\tconst canUsePlanCache = diagnostics.length === 0;\n\tapplyPlannerRedundancyPenalties(basePlanned);\n\tconst rawTokens = basePlanned.reduce((sum, planned) => sum + planned.fullTokens, 0);\n\n\tconst demand = computeTierDemand(basePlanned);\n\tconst allocation = allocateTiers(available, tierPolicy, demand);\n\tconst cacheKeyBase = createContextBudgetCacheKeyBaseV2({\n\t\tbudgetBucket: input.cacheBudgetBucket ?? String(available),\n\t\tcacheInvalidationSnapshot: input.cacheInvalidationSnapshot ?? input.cacheProvider?.getInvalidationSnapshot?.(),\n\t\tmodelId,\n\t\tnamespace: input.cacheNamespace,\n\t\tpolicyVersion,\n\t\tselectionPolicyVersion: input.selectionPolicyVersion,\n\t\tquery: input.query,\n\t\tqueryIntentHash: input.queryIntentHash,\n\t\tredactionPolicyHash: input.redactionPolicyHash,\n\t\tsafetyProfileHash: input.safetyProfileHash,\n\t\ttokenizerId: input.tokenizerId,\n\t});\n\tconst planCacheKey = buildContextBudgetPlanCacheKeyV2({\n\t\tavailableTokens: available,\n\t\tkeyBase: cacheKeyBase,\n\t\tmaxTokens,\n\t\tplanned: basePlanned,\n\t\tpromptHash: input.promptHash,\n\t\tqualityPolicy,\n\t\tresponseReserveTokens: responseReserve,\n\t\tsafetyMarginTokens: safetyMargin,\n\t\ttierPolicy,\n\t});\n\tconst cache = createContextBudgetSelectionCacheV2({\n\t\tkeyBase: cacheKeyBase,\n\t\tnowEpochMs: input.cacheNowEpochMs,\n\t\tplanCacheKey,\n\t\tprovider: input.cacheProvider,\n\t\tttlMs: input.cacheTtlMs,\n\t});\n\tconst cachedPlan = canUsePlanCache\n\t\t? readValidPlanCacheV2({\n\t\t\t\tavailableTokens: available,\n\t\t\t\tcache,\n\t\t\t\tkey: planCacheKey,\n\t\t\t\tplanned: basePlanned,\n\t\t\t})\n\t\t: undefined;\n\tif (cachedPlan) {\n\t\treturn cachedPlan;\n\t}\n\tconst selection = new Map<string, SelectedRepresentationV2>();\n\tconst tierUsed = createTierUsage();\n\tconst omitted: ContextBudgetItemV2[] = [];\n\tconst retrievalFallbacks: ContextSourceRefV2[] = [];\n\tlet usedTokens = 0;\n\n\tfor (const planned of basePlanned) {\n\t\tif (!planned.isHard) continue;\n\t\tusedTokens += selectHardItem(planned, selection, tierUsed);\n\t}\n\tif (usedTokens > available) {\n\t\tdiagnostics.push({\n\t\t\treason: \"hard_pin_over_capacity\",\n\t\t\tdetail: `hard-pinned context uses ${usedTokens} tokens against ${available} available tokens`,\n\t\t});\n\t}\n\n\tconst optionalPlanned = basePlanned.filter((planned) => !planned.isHard).sort(compareOptionalForSelection);\n\n\t// Floor-reservation pass: each tier spends its guaranteed claim (the\n\t// `allocated` field — hard demand, else demand capped at the floor) on its\n\t// own optional items before anything competes globally. A tier's floor is\n\t// therefore a real reservation, not a lower bound on its ceiling. Items\n\t// that cannot fit inside the remaining floor stay unselected for the\n\t// global pass; when the summed floors exceed the budget the reservation is\n\t// best-effort in tier order and the plan reports it explicitly.\n\t// One cache-resolution per item, shared by both passes so an item that is\n\t// deferred out of the floor and reconsidered globally does not double\n\t// count provider reads or redo materialization work.\n\tconst resolvedCandidates = new Map<string, readonly ContextRepresentationCandidateV2[]>();\n\tlet totalFloor = 0;\n\tfor (const tier of ALL_TIERS_V2) {\n\t\ttotalFloor += allocation.get(tier)?.floor ?? 0;\n\t}\n\tif (totalFloor > available) {\n\t\tdiagnostics.push({\n\t\t\treason: \"tier_floor_over_budget\",\n\t\t\tdetail: `tier floor guarantees total ${totalFloor} tokens against ${available} available; floors degrade to tier-order best effort`,\n\t\t});\n\t}\n\tfor (const tier of ALL_TIERS_V2) {\n\t\tconst floor = allocation.get(tier)?.floor ?? 0;\n\t\tif (floor <= 0 || tierUsed[tier] >= floor) continue;\n\t\tfor (const planned of optionalPlanned) {\n\t\t\tif (planned.item.tier !== tier || selection.has(planned.item.id)) continue;\n\t\t\tusedTokens = selectOptionalItem(planned, {\n\t\t\t\tallocation,\n\t\t\t\tavailable,\n\t\t\t\tcache,\n\t\t\t\tdiagnostics,\n\t\t\t\tomitted,\n\t\t\t\tqualityPolicy,\n\t\t\t\tretrievalFallbacks,\n\t\t\t\tselection,\n\t\t\t\ttierUsed,\n\t\t\t\tusedTokens,\n\t\t\t\tfloorReservation: { tier, floorTokens: floor },\n\t\t\t\tresolvedCandidates,\n\t\t\t});\n\t\t\tif (tierUsed[tier] >= floor || usedTokens >= available) break;\n\t\t}\n\t}\n\n\tfor (const planned of optionalPlanned) {\n\t\tif (selection.has(planned.item.id)) continue;\n\t\tusedTokens = selectOptionalItem(planned, {\n\t\t\tallocation,\n\t\t\tavailable,\n\t\t\tcache,\n\t\t\tdiagnostics,\n\t\t\tomitted,\n\t\t\tqualityPolicy,\n\t\t\tresolvedCandidates,\n\t\t\tretrievalFallbacks,\n\t\t\tselection,\n\t\t\ttierUsed,\n\t\t\tusedTokens,\n\t\t});\n\t}\n\n\tconst omittedHighPriority = omitted.some((item) => item.priority === \"high\" || item.required === true);\n\temitOmissionDiagnostics(omitted, diagnostics, retrievalFallbacks);\n\temitCoverageDiagnostics(input.query, selection, diagnostics);\n\n\tconst tierAllocations = buildTierAllocations(allocation, demand, tierUsed);\n\tconst omittedTokens = omitted.reduce(\n\t\t(sum, item) => sum + (basePlanned.find((planned) => planned.item.id === item.id)?.fullTokens ?? 0),\n\t\t0,\n\t);\n\tconst omittedItemIds = omitted.map((item) => item.id);\n\tconst planHash = computePlanHash({\n\t\tpolicyVersion,\n\t\tpromptHash: input.promptHash,\n\t\tplanned: basePlanned,\n\t\tselection,\n\t\tallocations: tierAllocations,\n\t\tomittedItemIds,\n\t});\n\tconst observability = buildObservability({\n\t\tavailable,\n\t\tdiagnostics,\n\t\tomittedItemIds,\n\t\tomittedTokens,\n\t\tplanHash,\n\t\trawTokens,\n\t\tretrievalFallbacks,\n\t\tselection,\n\t\tusedTokens,\n\t\tcacheTelemetry: finalizeContextBudgetCacheTelemetryV2(cache.telemetry, {\n\t\t\tomittedTokens,\n\t\t\trawTokens,\n\t\t\tusedTokens,\n\t\t}),\n\t});\n\n\tconst plan: PromptContextBudgetPlanV2 = {\n\t\tpolicyVersion,\n\t\tpromptHash: input.promptHash,\n\t\tplanHash,\n\t\tmaxTokens,\n\t\tresponseReserveTokens: responseReserve,\n\t\tsafetyMarginTokens: safetyMargin,\n\t\tavailableTokens: available,\n\t\tusedTokens,\n\t\tomittedTokens,\n\t\trawTokens,\n\t\ttokenSavingsRatio: rawTokens > 0 ? Math.max(0, 1 - usedTokens / rawTokens) : 0,\n\t\temergency: usedTokens > available || diagnostics.some((diagnostic) => diagnostic.reason === \"invalid_budget\"),\n\t\tomittedHighPriority,\n\t\ttierAllocations,\n\t\tselectedRepresentations: [...selection.values()].sort((a, b) => a.itemId.localeCompare(b.itemId)),\n\t\tincludedItemIds: basePlanned\n\t\t\t.map((planned) => planned.item.id)\n\t\t\t.filter((id) => selection.has(id))\n\t\t\t.sort(),\n\t\tomittedItemIds,\n\t\tdiagnostics,\n\t\tretrievalFallbacks,\n\t\tobservability,\n\t};\n\tif (canUsePlanCache) {\n\t\twritePlanCacheV2({\n\t\t\tcache,\n\t\t\tkey: planCacheKey,\n\t\t\tplan,\n\t\t\tplanned: basePlanned,\n\t\t});\n\t}\n\treturn plan;\n}\n\nfunction normalizeBudgetTokens(field: string, value: number, diagnostics: QualityDiagnosticV2[]): number {\n\tif (!Number.isFinite(value) || value < 0) {\n\t\tdiagnostics.push({\n\t\t\treason: \"invalid_budget\",\n\t\t\tdetail: `${field} must be a non-negative finite number, got ${value}`,\n\t\t});\n\t\treturn 0;\n\t}\n\treturn Math.floor(value);\n}\n"]}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { type ContextBudgetItemV2, type ContextBudgetTierV2, type ContextSourceRefV2, chooseHeadroomRepresentation
|
|
2
|
-
import { type TokenCounterAdapter } from "./context-budget-token-counter.ts";
|
|
1
|
+
import { type ContextBudgetItemV2, type ContextBudgetTierV2, type ContextRepresentationCandidateV2, type ContextSourceRefV2, chooseHeadroomRepresentation } from "./context-budget-headroom.ts";
|
|
3
2
|
import { type ContextBudgetSelectionCacheV2 } from "./context-budget-v2-cache.ts";
|
|
4
3
|
import { type PlannedItemV2 } from "./context-budget-v2-scoring.ts";
|
|
5
4
|
import { type QualityDiagnosticV2, type SelectedRepresentationV2, type TierBudgetAllocationV2 } from "./context-budget-v2-types.ts";
|
|
@@ -16,8 +15,25 @@ export interface OptionalSelectionState {
|
|
|
16
15
|
readonly selection: Map<string, SelectedRepresentationV2>;
|
|
17
16
|
readonly tierUsed: Record<ContextBudgetTierV2, number>;
|
|
18
17
|
readonly usedTokens: number;
|
|
18
|
+
/**
|
|
19
|
+
* Floor-reservation pass state. When set and the item belongs to this
|
|
20
|
+
* tier, the call admits it only while the tier's floor has headroom; an
|
|
21
|
+
* item that cannot fit inside the remaining floor is left unselected
|
|
22
|
+
* (never omitted) for the later global pass to reconsider under the
|
|
23
|
+
* tier's ceiling.
|
|
24
|
+
*/
|
|
25
|
+
readonly floorReservation?: {
|
|
26
|
+
readonly tier: ContextBudgetTierV2;
|
|
27
|
+
readonly floorTokens: number;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Cache-resolved candidates per item, shared across the floor and global
|
|
31
|
+
* passes so one item does not double-count provider reads (negative hits,
|
|
32
|
+
* stale rejects, misses) or repeat materialization work when it is
|
|
33
|
+
* reconsidered.
|
|
34
|
+
*/
|
|
35
|
+
readonly resolvedCandidates?: Map<string, readonly ContextRepresentationCandidateV2[]>;
|
|
19
36
|
}
|
|
20
|
-
export declare function createPlannedItems(items: readonly ContextBudgetItemV2[], tokenCounter: TokenCounterAdapter | undefined, modelId: string, qualityPolicy?: Parameters<typeof deriveRepresentationCandidates>[1]): PlannedItemV2[];
|
|
21
37
|
export declare function applyPlannerRedundancyPenalties(plannedItems: PlannedItemV2[]): void;
|
|
22
38
|
export declare function selectHardItem(planned: PlannedItemV2, selection: Map<string, SelectedRepresentationV2>, tierUsed: Record<ContextBudgetTierV2, number>): number;
|
|
23
39
|
export declare function selectOptionalItem(planned: PlannedItemV2, state: OptionalSelectionState): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-budget-v2-selection.d.ts","sourceRoot":"","sources":["../../src/core/context-budget-v2-selection.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype ContextBudgetItemV2,\n\ttype ContextBudgetTierV2,\n\ttype ContextRepresentationCandidateV2,\n\ttype ContextSourceRefV2,\n\tchooseHeadroomRepresentation,\n\tderiveRepresentationCandidates,\n\tfullTextTokens,\n} from \"./context-budget-headroom.ts\";\nimport { createFallbackTokenCounter, type TokenCounterAdapter } from \"./context-budget-token-counter.ts\";\nimport {\n\tapplyRepresentationCacheV2,\n\ttype ContextBudgetSelectionCacheV2,\n\twriteRepresentationCacheV2,\n} from \"./context-budget-v2-cache.ts\";\nimport { recordContextBudgetRepresentationCacheHitV2 } from \"./context-budget-v2-cache-telemetry.ts\";\nimport { computeCoverageGap } from \"./context-budget-v2-coverage.ts\";\nimport { contentHashOf } from \"./context-budget-v2-plan-hash.ts\";\nimport { applyRedundancyPenalties, type PlannedItemV2, scoreContextBudgetItemV2 } from \"./context-budget-v2-scoring.ts\";\nimport {\n\tALL_TIERS_V2,\n\ttype QualityDiagnosticV2,\n\ttype SelectedRepresentationV2,\n\ttype TierBudgetAllocationV2,\n} from \"./context-budget-v2-types.ts\";\n\nexport interface OptionalSelectionState {\n\treadonly allocation: ReadonlyMap<ContextBudgetTierV2, { readonly ceiling: number }>;\n\treadonly available: number;\n\treadonly cache?: ContextBudgetSelectionCacheV2;\n\treadonly diagnostics: QualityDiagnosticV2[];\n\treadonly omitted: ContextBudgetItemV2[];\n\treadonly qualityPolicy: Parameters<typeof chooseHeadroomRepresentation>[2];\n\treadonly retrievalFallbacks: ContextSourceRefV2[];\n\treadonly selection: Map<string, SelectedRepresentationV2>;\n\treadonly tierUsed: Record<ContextBudgetTierV2, number>;\n\treadonly usedTokens: number;\n}\n\n/**\n * Cheapest non-omit representation cost for an item, i.e. what admitting it\n * actually costs when the budget is tight. Falls back to full text when no\n * cheaper representation exists.\n */\nfunction minAdmissibleTokens(candidates: readonly ContextRepresentationCandidateV2[], fullTokens: number): number {\n\tlet min = Number.POSITIVE_INFINITY;\n\tfor (const candidate of candidates) {\n\t\tif (candidate.kind === \"omit\") continue;\n\t\tif (candidate.estimatedTokens < min) min = candidate.estimatedTokens;\n\t}\n\treturn Math.max(1, Number.isFinite(min) ? min : fullTokens);\n}\n\nexport function createPlannedItems(\n\titems: readonly ContextBudgetItemV2[],\n\ttokenCounter: TokenCounterAdapter | undefined,\n\tmodelId: string,\n\tqualityPolicy?: Parameters<typeof deriveRepresentationCandidates>[1],\n): PlannedItemV2[] {\n\tconst counter = tokenCounter ?? createFallbackTokenCounter();\n\treturn items.map((item) => {\n\t\tconst overrideTokenEstimate = item.tokenEstimate ?? counter.countText(item.text, modelId).tokens;\n\t\tconst itemWithTokens =\n\t\t\titem.tokenEstimate === undefined ? { ...item, tokenEstimate: overrideTokenEstimate } : item;\n\t\tconst fullTokens = fullTextTokens(itemWithTokens);\n\t\tconst isHard = item.priority === \"hard\" || item.required === true;\n\t\tconst baseScore = isHard ? Number.POSITIVE_INFINITY : scoreContextBudgetItemV2(itemWithTokens, fullTokens);\n\t\tconst candidates =\n\t\t\titemWithTokens.representations ?? deriveRepresentationCandidates(itemWithTokens, qualityPolicy);\n\t\treturn {\n\t\t\titem: itemWithTokens,\n\t\t\tfullTokens,\n\t\t\tadmissibleTokens: minAdmissibleTokens(candidates, fullTokens),\n\t\t\tcontentHash: contentHashOf(item.text),\n\t\t\tbaseScore,\n\t\t\tredundancyPenalty: 0,\n\t\t\teffectiveScore: baseScore,\n\t\t\tisHard,\n\t\t};\n\t});\n}\n\nexport function applyPlannerRedundancyPenalties(plannedItems: PlannedItemV2[]): void {\n\tconst penalties = applyRedundancyPenalties(plannedItems.filter((planned) => !planned.isHard));\n\tfor (const planned of plannedItems) {\n\t\tconst penalty = penalties.get(planned.item.id);\n\t\tif (penalty === undefined) continue;\n\t\tplanned.redundancyPenalty = penalty;\n\t\tplanned.effectiveScore = planned.baseScore - penalty;\n\t}\n}\n\nexport function selectHardItem(\n\tplanned: PlannedItemV2,\n\tselection: Map<string, SelectedRepresentationV2>,\n\ttierUsed: Record<ContextBudgetTierV2, number>,\n): number {\n\tconst candidate: ContextRepresentationCandidateV2 = {\n\t\tkind: \"full\",\n\t\ttext: planned.item.text,\n\t\testimatedTokens: planned.fullTokens,\n\t\tfidelity: planned.item.tokenEstimate !== undefined ? \"exact\" : \"bounded\",\n\t\tsourceRef: planned.item.sourceRef,\n\t};\n\tselection.set(planned.item.id, toSelected(planned.item.id, candidate));\n\ttierUsed[planned.item.tier] += planned.fullTokens;\n\treturn planned.fullTokens;\n}\n\nexport function selectOptionalItem(planned: PlannedItemV2, state: OptionalSelectionState): number {\n\tif (state.usedTokens >= state.available) {\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tconst tierCeiling = state.allocation.get(planned.item.tier)?.ceiling ?? state.available;\n\tconst remaining = Math.max(0, state.available - state.usedTokens);\n\tconst candidates = planned.item.representations ?? deriveRepresentationCandidates(planned.item, state.qualityPolicy);\n\tconst materializedEnabled = planned.item.representations === undefined;\n\tconst cachedCandidates = state.cache\n\t\t? applyRepresentationCacheV2({ planned, candidates, cache: state.cache, materializedEnabled })\n\t\t: candidates;\n\tconst chosen = chooseHeadroomRepresentation(\n\t\t{ ...planned.item, representations: cachedCandidates },\n\t\t{\n\t\t\ttierUsedTokens: state.tierUsed[planned.item.tier],\n\t\t\ttierCeilingTokens: tierCeiling,\n\t\t\tremainingGlobalTokens: remaining,\n\t\t},\n\t\tstate.qualityPolicy,\n\t);\n\tif (chosen.kind === \"omit\") {\n\t\tconst tierRemaining = Math.max(0, tierCeiling - state.tierUsed[planned.item.tier]);\n\t\tconst globalFit = cachedCandidates.filter(\n\t\t\t(candidate) => candidate.kind !== \"omit\" && candidate.estimatedTokens <= remaining,\n\t\t);\n\t\tif (globalFit.length > 0 && globalFit.every((candidate) => candidate.estimatedTokens > tierRemaining)) {\n\t\t\tstate.diagnostics.push({\n\t\t\t\treason: \"tier_ceiling_exceeded\",\n\t\t\t\titemId: planned.item.id,\n\t\t\t\tdetail: `${planned.item.tier} item \"${planned.item.id}\" needs ${Math.min(\n\t\t\t\t\t...globalFit.map((candidate) => candidate.estimatedTokens),\n\t\t\t\t)} tokens with ${tierRemaining} tier tokens remaining`,\n\t\t\t});\n\t\t}\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.tierUsed[planned.item.tier] + chosen.estimatedTokens > tierCeiling) {\n\t\tstate.diagnostics.push({\n\t\t\treason: \"tier_ceiling_exceeded\",\n\t\t\titemId: planned.item.id,\n\t\t\tdetail: `${planned.item.tier} item \"${planned.item.id}\" needs ${chosen.estimatedTokens} tokens with ${Math.max(0, tierCeiling - state.tierUsed[planned.item.tier])} tier tokens remaining`,\n\t\t});\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.usedTokens + chosen.estimatedTokens > state.available) {\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.cache) {\n\t\tif (chosen.cache?.hit === true) {\n\t\t\trecordContextBudgetRepresentationCacheHitV2(\n\t\t\t\tstate.cache.telemetry,\n\t\t\t\tchosen.kind,\n\t\t\t\tchosen.cache.keyKind,\n\t\t\t\tplanned.fullTokens,\n\t\t\t);\n\t\t}\n\t\twriteRepresentationCacheV2({ planned, selected: chosen, cache: state.cache, materializedEnabled });\n\t}\n\tstate.selection.set(planned.item.id, toSelected(planned.item.id, chosen));\n\tstate.tierUsed[planned.item.tier] += chosen.estimatedTokens;\n\treturn state.usedTokens + chosen.estimatedTokens;\n}\n\nexport function emitOmissionDiagnostics(\n\tomitted: readonly ContextBudgetItemV2[],\n\tdiagnostics: QualityDiagnosticV2[],\n\tretrievalFallbacks: ContextSourceRefV2[],\n): void {\n\tfor (const item of omitted) {\n\t\tif (item.priority === \"high\" || item.required === true) {\n\t\t\tdiagnostics.push({\n\t\t\t\treason: \"omitted_high_priority\",\n\t\t\t\titemId: item.id,\n\t\t\t\tdetail: `${item.tier} item \"${item.id}\" could not fit within the prompt budget`,\n\t\t\t});\n\t\t}\n\t\tif (item.sourceRef?.retrievable) {\n\t\t\tdiagnostics.push({\n\t\t\t\treason: \"restore_on_demand_hint\",\n\t\t\t\titemId: item.id,\n\t\t\t\tdetail: `retrievable \"${item.id}\" kept as fallback via ${item.sourceRef.uri}`,\n\t\t\t});\n\t\t\tretrievalFallbacks.push(item.sourceRef);\n\t\t}\n\t}\n}\n\nexport function emitCoverageDiagnostics(\n\tquery: string | undefined,\n\tselection: ReadonlyMap<string, SelectedRepresentationV2>,\n\tdiagnostics: QualityDiagnosticV2[],\n): void {\n\tconst coverage = computeCoverageGap(\n\t\tquery,\n\t\t[...selection.values()].map((representation) => representation.text),\n\t);\n\tif (!coverage.gap) return;\n\tdiagnostics.push({\n\t\treason: \"coverage_gap\",\n\t\tdetail: `query terms not covered by selected context: ${coverage.missing.join(\", \")}`,\n\t});\n}\n\nexport function buildTierAllocations(\n\tallocation: ReadonlyMap<\n\t\tContextBudgetTierV2,\n\t\t{ readonly floor: number; readonly ceiling: number; readonly allocated: number }\n\t>,\n\tdemand: ReadonlyMap<ContextBudgetTierV2, { readonly hard: number }>,\n\ttierUsed: Record<ContextBudgetTierV2, number>,\n): TierBudgetAllocationV2[] {\n\treturn ALL_TIERS_V2.map((tier) => {\n\t\tconst raw = allocation.get(tier) ?? { floor: 0, ceiling: 0, allocated: 0 };\n\t\treturn {\n\t\t\ttier,\n\t\t\tfloorTokens: raw.floor,\n\t\t\tceilingTokens: raw.ceiling,\n\t\t\tallocatedTokens: raw.allocated,\n\t\t\tusedTokens: tierUsed[tier],\n\t\t\thardTokens: demand.get(tier)?.hard ?? 0,\n\t\t};\n\t});\n}\n\nexport function createTierUsage(): Record<ContextBudgetTierV2, number> {\n\treturn {\n\t\tsystem: 0,\n\t\t\"active-goal\": 0,\n\t\t\"current-files\": 0,\n\t\ttools: 0,\n\t\tskills: 0,\n\t\tmcp: 0,\n\t\thistory: 0,\n\t\tevidence: 0,\n\t\tscratch: 0,\n\t};\n}\n\nfunction toSelected(itemId: string, candidate: ContextRepresentationCandidateV2): SelectedRepresentationV2 {\n\treturn {\n\t\titemId,\n\t\tkind: candidate.kind,\n\t\ttext: candidate.text,\n\t\testimatedTokens: candidate.estimatedTokens,\n\t\tfidelity: candidate.fidelity,\n\t\tsourceRef: candidate.sourceRef,\n\t\tsummaryHash: candidate.summaryHash,\n\t\tcompressorId: candidate.compressorId,\n\t\tcache: candidate.cache,\n\t};\n}\n\nfunction omitItem(\n\tplanned: PlannedItemV2,\n\tstate: Pick<OptionalSelectionState, \"diagnostics\" | \"omitted\" | \"retrievalFallbacks\">,\n): void {\n\tstate.omitted.push(planned.item);\n\tif (planned.item.sourceRef?.retrievable) {\n\t\tstate.diagnostics.push({\n\t\t\treason: \"retrieval_miss_risk\",\n\t\t\titemId: planned.item.id,\n\t\t\tdetail: `retrievable ${planned.item.tier} item \"${planned.item.id}\" omitted; keep pointer for restore-on-demand`,\n\t\t});\n\t\tstate.retrievalFallbacks.push(planned.item.sourceRef);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"context-budget-v2-selection.d.ts","sourceRoot":"","sources":["../../src/core/context-budget-v2-selection.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype ContextBudgetItemV2,\n\ttype ContextBudgetTierV2,\n\ttype ContextRepresentationCandidateV2,\n\ttype ContextSourceRefV2,\n\tchooseHeadroomRepresentation,\n\tderiveRepresentationCandidates,\n} from \"./context-budget-headroom.ts\";\nimport {\n\tapplyRepresentationCacheV2,\n\ttype ContextBudgetSelectionCacheV2,\n\twriteRepresentationCacheV2,\n} from \"./context-budget-v2-cache.ts\";\nimport { recordContextBudgetRepresentationCacheHitV2 } from \"./context-budget-v2-cache-telemetry.ts\";\nimport { computeCoverageGap } from \"./context-budget-v2-coverage.ts\";\nimport { applyRedundancyPenalties, type PlannedItemV2 } from \"./context-budget-v2-scoring.ts\";\nimport {\n\tALL_TIERS_V2,\n\ttype QualityDiagnosticV2,\n\ttype SelectedRepresentationV2,\n\ttype TierBudgetAllocationV2,\n} from \"./context-budget-v2-types.ts\";\n\nexport interface OptionalSelectionState {\n\treadonly allocation: ReadonlyMap<ContextBudgetTierV2, { readonly ceiling: number }>;\n\treadonly available: number;\n\treadonly cache?: ContextBudgetSelectionCacheV2;\n\treadonly diagnostics: QualityDiagnosticV2[];\n\treadonly omitted: ContextBudgetItemV2[];\n\treadonly qualityPolicy: Parameters<typeof chooseHeadroomRepresentation>[2];\n\treadonly retrievalFallbacks: ContextSourceRefV2[];\n\treadonly selection: Map<string, SelectedRepresentationV2>;\n\treadonly tierUsed: Record<ContextBudgetTierV2, number>;\n\treadonly usedTokens: number;\n\t/**\n\t * Floor-reservation pass state. When set and the item belongs to this\n\t * tier, the call admits it only while the tier's floor has headroom; an\n\t * item that cannot fit inside the remaining floor is left unselected\n\t * (never omitted) for the later global pass to reconsider under the\n\t * tier's ceiling.\n\t */\n\treadonly floorReservation?: { readonly tier: ContextBudgetTierV2; readonly floorTokens: number };\n\t/**\n\t * Cache-resolved candidates per item, shared across the floor and global\n\t * passes so one item does not double-count provider reads (negative hits,\n\t * stale rejects, misses) or repeat materialization work when it is\n\t * reconsidered.\n\t */\n\treadonly resolvedCandidates?: Map<string, readonly ContextRepresentationCandidateV2[]>;\n}\n\nexport function applyPlannerRedundancyPenalties(plannedItems: PlannedItemV2[]): void {\n\tconst penalties = applyRedundancyPenalties(plannedItems.filter((planned) => !planned.isHard));\n\tfor (const planned of plannedItems) {\n\t\tconst penalty = penalties.get(planned.item.id);\n\t\tif (penalty === undefined) continue;\n\t\tplanned.redundancyPenalty = penalty;\n\t\tplanned.effectiveScore = planned.baseScore - penalty;\n\t}\n}\n\nexport function selectHardItem(\n\tplanned: PlannedItemV2,\n\tselection: Map<string, SelectedRepresentationV2>,\n\ttierUsed: Record<ContextBudgetTierV2, number>,\n): number {\n\tconst candidate: ContextRepresentationCandidateV2 = {\n\t\tkind: \"full\",\n\t\ttext: planned.item.text,\n\t\testimatedTokens: planned.fullTokens,\n\t\tfidelity: planned.item.tokenEstimate !== undefined ? \"exact\" : \"bounded\",\n\t\tsourceRef: planned.item.sourceRef,\n\t};\n\tselection.set(planned.item.id, toSelected(planned.item.id, candidate));\n\ttierUsed[planned.item.tier] += planned.fullTokens;\n\treturn planned.fullTokens;\n}\n\nexport function selectOptionalItem(planned: PlannedItemV2, state: OptionalSelectionState): number {\n\tconst floorPass =\n\t\tstate.floorReservation !== undefined && planned.item.tier === state.floorReservation.tier\n\t\t\t? state.floorReservation\n\t\t\t: undefined;\n\tif (floorPass !== undefined && state.tierUsed[planned.item.tier] >= floorPass.floorTokens) {\n\t\t// This tier's guaranteed claim is already spent; leave the item for the\n\t\t// global pass rather than consuming another tier's budget.\n\t\treturn state.usedTokens;\n\t}\n\tif (state.usedTokens >= state.available) {\n\t\tif (floorPass === undefined) omitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\t// During the floor pass the binding cap is the tier's remaining floor;\n\t// afterwards the tier's ceiling (or the global remainder) applies.\n\tconst tierCeiling =\n\t\tfloorPass !== undefined\n\t\t\t? floorPass.floorTokens\n\t\t\t: (state.allocation.get(planned.item.tier)?.ceiling ?? state.available);\n\tconst remaining = Math.max(0, state.available - state.usedTokens);\n\tconst candidates = planned.item.representations ?? deriveRepresentationCandidates(planned.item, state.qualityPolicy);\n\tconst materializedEnabled = planned.item.representations === undefined;\n\tlet cachedCandidates = state.resolvedCandidates?.get(planned.item.id);\n\tif (cachedCandidates === undefined) {\n\t\tcachedCandidates = state.cache\n\t\t\t? applyRepresentationCacheV2({ planned, candidates, cache: state.cache, materializedEnabled })\n\t\t\t: candidates;\n\t\tstate.resolvedCandidates?.set(planned.item.id, cachedCandidates);\n\t}\n\tconst chosen = chooseHeadroomRepresentation(\n\t\t{ ...planned.item, representations: cachedCandidates },\n\t\t{\n\t\t\ttierUsedTokens: state.tierUsed[planned.item.tier],\n\t\t\ttierCeilingTokens: tierCeiling,\n\t\t\tremainingGlobalTokens: remaining,\n\t\t},\n\t\tstate.qualityPolicy,\n\t);\n\tif (chosen.kind === \"omit\") {\n\t\tif (floorPass !== undefined) {\n\t\t\t// No admissible representation fits inside the remaining floor; the\n\t\t\t// global pass may still admit it against the tier's ceiling.\n\t\t\treturn state.usedTokens;\n\t\t}\n\t\tconst tierRemaining = Math.max(0, tierCeiling - state.tierUsed[planned.item.tier]);\n\t\tconst globalFit = cachedCandidates.filter(\n\t\t\t(candidate) => candidate.kind !== \"omit\" && candidate.estimatedTokens <= remaining,\n\t\t);\n\t\tif (globalFit.length > 0 && globalFit.every((candidate) => candidate.estimatedTokens > tierRemaining)) {\n\t\t\tstate.diagnostics.push({\n\t\t\t\treason: \"tier_ceiling_exceeded\",\n\t\t\t\titemId: planned.item.id,\n\t\t\t\tdetail: `${planned.item.tier} item \"${planned.item.id}\" needs ${Math.min(\n\t\t\t\t\t...globalFit.map((candidate) => candidate.estimatedTokens),\n\t\t\t\t)} tokens with ${tierRemaining} tier tokens remaining`,\n\t\t\t});\n\t\t}\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.tierUsed[planned.item.tier] + chosen.estimatedTokens > tierCeiling) {\n\t\tif (floorPass !== undefined) {\n\t\t\treturn state.usedTokens;\n\t\t}\n\t\tstate.diagnostics.push({\n\t\t\treason: \"tier_ceiling_exceeded\",\n\t\t\titemId: planned.item.id,\n\t\t\tdetail: `${planned.item.tier} item \"${planned.item.id}\" needs ${chosen.estimatedTokens} tokens with ${Math.max(0, tierCeiling - state.tierUsed[planned.item.tier])} tier tokens remaining`,\n\t\t});\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.usedTokens + chosen.estimatedTokens > state.available) {\n\t\tif (floorPass === undefined) omitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.cache) {\n\t\tif (chosen.cache?.hit === true) {\n\t\t\trecordContextBudgetRepresentationCacheHitV2(\n\t\t\t\tstate.cache.telemetry,\n\t\t\t\tchosen.kind,\n\t\t\t\tchosen.cache.keyKind,\n\t\t\t\tplanned.fullTokens,\n\t\t\t);\n\t\t}\n\t\twriteRepresentationCacheV2({ planned, selected: chosen, cache: state.cache, materializedEnabled });\n\t}\n\tstate.selection.set(planned.item.id, toSelected(planned.item.id, chosen));\n\tstate.tierUsed[planned.item.tier] += chosen.estimatedTokens;\n\treturn state.usedTokens + chosen.estimatedTokens;\n}\n\nexport function emitOmissionDiagnostics(\n\tomitted: readonly ContextBudgetItemV2[],\n\tdiagnostics: QualityDiagnosticV2[],\n\tretrievalFallbacks: ContextSourceRefV2[],\n): void {\n\tfor (const item of omitted) {\n\t\tif (item.priority === \"high\" || item.required === true) {\n\t\t\tdiagnostics.push({\n\t\t\t\treason: \"omitted_high_priority\",\n\t\t\t\titemId: item.id,\n\t\t\t\tdetail: `${item.tier} item \"${item.id}\" could not fit within the prompt budget`,\n\t\t\t});\n\t\t}\n\t\tif (item.sourceRef?.retrievable) {\n\t\t\tdiagnostics.push({\n\t\t\t\treason: \"restore_on_demand_hint\",\n\t\t\t\titemId: item.id,\n\t\t\t\tdetail: `retrievable \"${item.id}\" kept as fallback via ${item.sourceRef.uri}`,\n\t\t\t});\n\t\t\tretrievalFallbacks.push(item.sourceRef);\n\t\t}\n\t}\n}\n\nexport function emitCoverageDiagnostics(\n\tquery: string | undefined,\n\tselection: ReadonlyMap<string, SelectedRepresentationV2>,\n\tdiagnostics: QualityDiagnosticV2[],\n): void {\n\tconst coverage = computeCoverageGap(\n\t\tquery,\n\t\t[...selection.values()].map((representation) => representation.text),\n\t);\n\tif (!coverage.gap) return;\n\tdiagnostics.push({\n\t\treason: \"coverage_gap\",\n\t\tdetail: `query terms not covered by selected context: ${coverage.missing.join(\", \")}`,\n\t});\n}\n\nexport function buildTierAllocations(\n\tallocation: ReadonlyMap<\n\t\tContextBudgetTierV2,\n\t\t{ readonly floor: number; readonly ceiling: number; readonly allocated: number }\n\t>,\n\tdemand: ReadonlyMap<ContextBudgetTierV2, { readonly hard: number }>,\n\ttierUsed: Record<ContextBudgetTierV2, number>,\n): TierBudgetAllocationV2[] {\n\treturn ALL_TIERS_V2.map((tier) => {\n\t\tconst raw = allocation.get(tier) ?? { floor: 0, ceiling: 0, allocated: 0 };\n\t\treturn {\n\t\t\ttier,\n\t\t\tfloorTokens: raw.floor,\n\t\t\tceilingTokens: raw.ceiling,\n\t\t\tallocatedTokens: raw.allocated,\n\t\t\tusedTokens: tierUsed[tier],\n\t\t\thardTokens: demand.get(tier)?.hard ?? 0,\n\t\t};\n\t});\n}\n\nexport function createTierUsage(): Record<ContextBudgetTierV2, number> {\n\treturn Object.fromEntries(ALL_TIERS_V2.map((tier) => [tier, 0])) as Record<ContextBudgetTierV2, number>;\n}\n\nfunction toSelected(itemId: string, candidate: ContextRepresentationCandidateV2): SelectedRepresentationV2 {\n\treturn {\n\t\titemId,\n\t\tkind: candidate.kind,\n\t\ttext: candidate.text,\n\t\testimatedTokens: candidate.estimatedTokens,\n\t\tfidelity: candidate.fidelity,\n\t\tsourceRef: candidate.sourceRef,\n\t\tsummaryHash: candidate.summaryHash,\n\t\tcompressorId: candidate.compressorId,\n\t\tcache: candidate.cache,\n\t};\n}\n\nfunction omitItem(\n\tplanned: PlannedItemV2,\n\tstate: Pick<OptionalSelectionState, \"diagnostics\" | \"omitted\" | \"retrievalFallbacks\">,\n): void {\n\tstate.omitted.push(planned.item);\n\tif (planned.item.sourceRef?.retrievable) {\n\t\tstate.diagnostics.push({\n\t\t\treason: \"retrieval_miss_risk\",\n\t\t\titemId: planned.item.id,\n\t\t\tdetail: `retrievable ${planned.item.tier} item \"${planned.item.id}\" omitted; keep pointer for restore-on-demand`,\n\t\t});\n\t\tstate.retrievalFallbacks.push(planned.item.sourceRef);\n\t}\n}\n"]}
|
|
@@ -1,47 +1,9 @@
|
|
|
1
|
-
import { chooseHeadroomRepresentation, deriveRepresentationCandidates,
|
|
2
|
-
import { createFallbackTokenCounter } from "./context-budget-token-counter.js";
|
|
1
|
+
import { chooseHeadroomRepresentation, deriveRepresentationCandidates, } from "./context-budget-headroom.js";
|
|
3
2
|
import { applyRepresentationCacheV2, writeRepresentationCacheV2, } from "./context-budget-v2-cache.js";
|
|
4
3
|
import { recordContextBudgetRepresentationCacheHitV2 } from "./context-budget-v2-cache-telemetry.js";
|
|
5
4
|
import { computeCoverageGap } from "./context-budget-v2-coverage.js";
|
|
6
|
-
import {
|
|
7
|
-
import { applyRedundancyPenalties, scoreContextBudgetItemV2 } from "./context-budget-v2-scoring.js";
|
|
5
|
+
import { applyRedundancyPenalties } from "./context-budget-v2-scoring.js";
|
|
8
6
|
import { ALL_TIERS_V2, } from "./context-budget-v2-types.js";
|
|
9
|
-
/**
|
|
10
|
-
* Cheapest non-omit representation cost for an item, i.e. what admitting it
|
|
11
|
-
* actually costs when the budget is tight. Falls back to full text when no
|
|
12
|
-
* cheaper representation exists.
|
|
13
|
-
*/
|
|
14
|
-
function minAdmissibleTokens(candidates, fullTokens) {
|
|
15
|
-
let min = Number.POSITIVE_INFINITY;
|
|
16
|
-
for (const candidate of candidates) {
|
|
17
|
-
if (candidate.kind === "omit")
|
|
18
|
-
continue;
|
|
19
|
-
if (candidate.estimatedTokens < min)
|
|
20
|
-
min = candidate.estimatedTokens;
|
|
21
|
-
}
|
|
22
|
-
return Math.max(1, Number.isFinite(min) ? min : fullTokens);
|
|
23
|
-
}
|
|
24
|
-
export function createPlannedItems(items, tokenCounter, modelId, qualityPolicy) {
|
|
25
|
-
const counter = tokenCounter ?? createFallbackTokenCounter();
|
|
26
|
-
return items.map((item) => {
|
|
27
|
-
const overrideTokenEstimate = item.tokenEstimate ?? counter.countText(item.text, modelId).tokens;
|
|
28
|
-
const itemWithTokens = item.tokenEstimate === undefined ? { ...item, tokenEstimate: overrideTokenEstimate } : item;
|
|
29
|
-
const fullTokens = fullTextTokens(itemWithTokens);
|
|
30
|
-
const isHard = item.priority === "hard" || item.required === true;
|
|
31
|
-
const baseScore = isHard ? Number.POSITIVE_INFINITY : scoreContextBudgetItemV2(itemWithTokens, fullTokens);
|
|
32
|
-
const candidates = itemWithTokens.representations ?? deriveRepresentationCandidates(itemWithTokens, qualityPolicy);
|
|
33
|
-
return {
|
|
34
|
-
item: itemWithTokens,
|
|
35
|
-
fullTokens,
|
|
36
|
-
admissibleTokens: minAdmissibleTokens(candidates, fullTokens),
|
|
37
|
-
contentHash: contentHashOf(item.text),
|
|
38
|
-
baseScore,
|
|
39
|
-
redundancyPenalty: 0,
|
|
40
|
-
effectiveScore: baseScore,
|
|
41
|
-
isHard,
|
|
42
|
-
};
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
7
|
export function applyPlannerRedundancyPenalties(plannedItems) {
|
|
46
8
|
const penalties = applyRedundancyPenalties(plannedItems.filter((planned) => !planned.isHard));
|
|
47
9
|
for (const planned of plannedItems) {
|
|
@@ -65,23 +27,45 @@ export function selectHardItem(planned, selection, tierUsed) {
|
|
|
65
27
|
return planned.fullTokens;
|
|
66
28
|
}
|
|
67
29
|
export function selectOptionalItem(planned, state) {
|
|
30
|
+
const floorPass = state.floorReservation !== undefined && planned.item.tier === state.floorReservation.tier
|
|
31
|
+
? state.floorReservation
|
|
32
|
+
: undefined;
|
|
33
|
+
if (floorPass !== undefined && state.tierUsed[planned.item.tier] >= floorPass.floorTokens) {
|
|
34
|
+
// This tier's guaranteed claim is already spent; leave the item for the
|
|
35
|
+
// global pass rather than consuming another tier's budget.
|
|
36
|
+
return state.usedTokens;
|
|
37
|
+
}
|
|
68
38
|
if (state.usedTokens >= state.available) {
|
|
69
|
-
|
|
39
|
+
if (floorPass === undefined)
|
|
40
|
+
omitItem(planned, state);
|
|
70
41
|
return state.usedTokens;
|
|
71
42
|
}
|
|
72
|
-
|
|
43
|
+
// During the floor pass the binding cap is the tier's remaining floor;
|
|
44
|
+
// afterwards the tier's ceiling (or the global remainder) applies.
|
|
45
|
+
const tierCeiling = floorPass !== undefined
|
|
46
|
+
? floorPass.floorTokens
|
|
47
|
+
: (state.allocation.get(planned.item.tier)?.ceiling ?? state.available);
|
|
73
48
|
const remaining = Math.max(0, state.available - state.usedTokens);
|
|
74
49
|
const candidates = planned.item.representations ?? deriveRepresentationCandidates(planned.item, state.qualityPolicy);
|
|
75
50
|
const materializedEnabled = planned.item.representations === undefined;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
51
|
+
let cachedCandidates = state.resolvedCandidates?.get(planned.item.id);
|
|
52
|
+
if (cachedCandidates === undefined) {
|
|
53
|
+
cachedCandidates = state.cache
|
|
54
|
+
? applyRepresentationCacheV2({ planned, candidates, cache: state.cache, materializedEnabled })
|
|
55
|
+
: candidates;
|
|
56
|
+
state.resolvedCandidates?.set(planned.item.id, cachedCandidates);
|
|
57
|
+
}
|
|
79
58
|
const chosen = chooseHeadroomRepresentation({ ...planned.item, representations: cachedCandidates }, {
|
|
80
59
|
tierUsedTokens: state.tierUsed[planned.item.tier],
|
|
81
60
|
tierCeilingTokens: tierCeiling,
|
|
82
61
|
remainingGlobalTokens: remaining,
|
|
83
62
|
}, state.qualityPolicy);
|
|
84
63
|
if (chosen.kind === "omit") {
|
|
64
|
+
if (floorPass !== undefined) {
|
|
65
|
+
// No admissible representation fits inside the remaining floor; the
|
|
66
|
+
// global pass may still admit it against the tier's ceiling.
|
|
67
|
+
return state.usedTokens;
|
|
68
|
+
}
|
|
85
69
|
const tierRemaining = Math.max(0, tierCeiling - state.tierUsed[planned.item.tier]);
|
|
86
70
|
const globalFit = cachedCandidates.filter((candidate) => candidate.kind !== "omit" && candidate.estimatedTokens <= remaining);
|
|
87
71
|
if (globalFit.length > 0 && globalFit.every((candidate) => candidate.estimatedTokens > tierRemaining)) {
|
|
@@ -95,6 +79,9 @@ export function selectOptionalItem(planned, state) {
|
|
|
95
79
|
return state.usedTokens;
|
|
96
80
|
}
|
|
97
81
|
if (state.tierUsed[planned.item.tier] + chosen.estimatedTokens > tierCeiling) {
|
|
82
|
+
if (floorPass !== undefined) {
|
|
83
|
+
return state.usedTokens;
|
|
84
|
+
}
|
|
98
85
|
state.diagnostics.push({
|
|
99
86
|
reason: "tier_ceiling_exceeded",
|
|
100
87
|
itemId: planned.item.id,
|
|
@@ -104,7 +91,8 @@ export function selectOptionalItem(planned, state) {
|
|
|
104
91
|
return state.usedTokens;
|
|
105
92
|
}
|
|
106
93
|
if (state.usedTokens + chosen.estimatedTokens > state.available) {
|
|
107
|
-
|
|
94
|
+
if (floorPass === undefined)
|
|
95
|
+
omitItem(planned, state);
|
|
108
96
|
return state.usedTokens;
|
|
109
97
|
}
|
|
110
98
|
if (state.cache) {
|
|
@@ -159,17 +147,7 @@ export function buildTierAllocations(allocation, demand, tierUsed) {
|
|
|
159
147
|
});
|
|
160
148
|
}
|
|
161
149
|
export function createTierUsage() {
|
|
162
|
-
return
|
|
163
|
-
system: 0,
|
|
164
|
-
"active-goal": 0,
|
|
165
|
-
"current-files": 0,
|
|
166
|
-
tools: 0,
|
|
167
|
-
skills: 0,
|
|
168
|
-
mcp: 0,
|
|
169
|
-
history: 0,
|
|
170
|
-
evidence: 0,
|
|
171
|
-
scratch: 0,
|
|
172
|
-
};
|
|
150
|
+
return Object.fromEntries(ALL_TIERS_V2.map((tier) => [tier, 0]));
|
|
173
151
|
}
|
|
174
152
|
function toSelected(itemId, candidate) {
|
|
175
153
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-budget-v2-selection.js","sourceRoot":"","sources":["../../src/core/context-budget-v2-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAKN,4BAA4B,EAC5B,8BAA8B,EAC9B,cAAc,GACd,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,0BAA0B,EAA4B,MAAM,mCAAmC,CAAC;AACzG,OAAO,EACN,0BAA0B,EAE1B,0BAA0B,GAC1B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,2CAA2C,EAAE,MAAM,wCAAwC,CAAC;AACrG,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAsB,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AACxH,OAAO,EACN,YAAY,GAIZ,MAAM,8BAA8B,CAAC;AAetC;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,UAAuD,EAAE,UAAkB,EAAU;IACjH,IAAI,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACnC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QACxC,IAAI,SAAS,CAAC,eAAe,GAAG,GAAG;YAAE,GAAG,GAAG,SAAS,CAAC,eAAe,CAAC;IACtE,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;AAAA,CAC5D;AAED,MAAM,UAAU,kBAAkB,CACjC,KAAqC,EACrC,YAA6C,EAC7C,OAAe,EACf,aAAoE,EAClD;IAClB,MAAM,OAAO,GAAG,YAAY,IAAI,0BAA0B,EAAE,CAAC;IAC7D,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC1B,MAAM,qBAAqB,GAAG,IAAI,CAAC,aAAa,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC;QACjG,MAAM,cAAc,GACnB,IAAI,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,aAAa,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7F,MAAM,UAAU,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC;QAClE,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,wBAAwB,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;QAC3G,MAAM,UAAU,GACf,cAAc,CAAC,eAAe,IAAI,8BAA8B,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;QACjG,OAAO;YACN,IAAI,EAAE,cAAc;YACpB,UAAU;YACV,gBAAgB,EAAE,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC;YAC7D,WAAW,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;YACrC,SAAS;YACT,iBAAiB,EAAE,CAAC;YACpB,cAAc,EAAE,SAAS;YACzB,MAAM;SACN,CAAC;IAAA,CACF,CAAC,CAAC;AAAA,CACH;AAED,MAAM,UAAU,+BAA+B,CAAC,YAA6B,EAAQ;IACpF,MAAM,SAAS,GAAG,wBAAwB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9F,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/C,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QACpC,OAAO,CAAC,iBAAiB,GAAG,OAAO,CAAC;QACpC,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC;IACtD,CAAC;AAAA,CACD;AAED,MAAM,UAAU,cAAc,CAC7B,OAAsB,EACtB,SAAgD,EAChD,QAA6C,EACpC;IACT,MAAM,SAAS,GAAqC;QACnD,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI;QACvB,eAAe,EAAE,OAAO,CAAC,UAAU;QACnC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;QACxE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS;KACjC,CAAC;IACF,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;IACvE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC;IAClD,OAAO,OAAO,CAAC,UAAU,CAAC;AAAA,CAC1B;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAsB,EAAE,KAA6B,EAAU;IACjG,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACzC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACzB,OAAO,KAAK,CAAC,UAAU,CAAC;IACzB,CAAC;IACD,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,IAAI,KAAK,CAAC,SAAS,CAAC;IACxF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,IAAI,8BAA8B,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IACrH,MAAM,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,KAAK,SAAS,CAAC;IACvE,MAAM,gBAAgB,GAAG,KAAK,CAAC,KAAK;QACnC,CAAC,CAAC,0BAA0B,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,mBAAmB,EAAE,CAAC;QAC9F,CAAC,CAAC,UAAU,CAAC;IACd,MAAM,MAAM,GAAG,4BAA4B,CAC1C,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,eAAe,EAAE,gBAAgB,EAAE,EACtD;QACC,cAAc,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QACjD,iBAAiB,EAAE,WAAW;QAC9B,qBAAqB,EAAE,SAAS;KAChC,EACD,KAAK,CAAC,aAAa,CACnB,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACnF,MAAM,SAAS,GAAG,gBAAgB,CAAC,MAAM,CACxC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,MAAM,IAAI,SAAS,CAAC,eAAe,IAAI,SAAS,CAClF,CAAC;QACF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,eAAe,GAAG,aAAa,CAAC,EAAE,CAAC;YACvG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC;gBACtB,MAAM,EAAE,uBAAuB;gBAC/B,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE;gBACvB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,UAAU,OAAO,CAAC,IAAI,CAAC,EAAE,WAAW,IAAI,CAAC,GAAG,CACvE,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,eAAe,CAAC,CAC1D,gBAAgB,aAAa,wBAAwB;aACtD,CAAC,CAAC;QACJ,CAAC;QACD,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACzB,OAAO,KAAK,CAAC,UAAU,CAAC;IACzB,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,eAAe,GAAG,WAAW,EAAE,CAAC;QAC9E,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC;YACtB,MAAM,EAAE,uBAAuB;YAC/B,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE;YACvB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,UAAU,OAAO,CAAC,IAAI,CAAC,EAAE,WAAW,MAAM,CAAC,eAAe,gBAAgB,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,wBAAwB;SAC1L,CAAC,CAAC;QACH,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACzB,OAAO,KAAK,CAAC,UAAU,CAAC;IACzB,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,eAAe,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;QACjE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACzB,OAAO,KAAK,CAAC,UAAU,CAAC;IACzB,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QACjB,IAAI,MAAM,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC;YAChC,2CAA2C,CAC1C,KAAK,CAAC,KAAK,CAAC,SAAS,EACrB,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,KAAK,CAAC,OAAO,EACpB,OAAO,CAAC,UAAU,CAClB,CAAC;QACH,CAAC;QACD,0BAA0B,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1E,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,eAAe,CAAC;IAC5D,OAAO,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,eAAe,CAAC;AAAA,CACjD;AAED,MAAM,UAAU,uBAAuB,CACtC,OAAuC,EACvC,WAAkC,EAClC,kBAAwC,EACjC;IACP,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACxD,WAAW,CAAC,IAAI,CAAC;gBAChB,MAAM,EAAE,uBAAuB;gBAC/B,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,0CAA0C;aAC/E,CAAC,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,CAAC;YACjC,WAAW,CAAC,IAAI,CAAC;gBAChB,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,MAAM,EAAE,gBAAgB,IAAI,CAAC,EAAE,0BAA0B,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE;aAC7E,CAAC,CAAC;YACH,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC;IACF,CAAC;AAAA,CACD;AAED,MAAM,UAAU,uBAAuB,CACtC,KAAyB,EACzB,SAAwD,EACxD,WAAkC,EAC3B;IACP,MAAM,QAAQ,GAAG,kBAAkB,CAClC,KAAK,EACL,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CACpE,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,GAAG;QAAE,OAAO;IAC1B,WAAW,CAAC,IAAI,CAAC;QAChB,MAAM,EAAE,cAAc;QACtB,MAAM,EAAE,gDAAgD,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;KACrF,CAAC,CAAC;AAAA,CACH;AAED,MAAM,UAAU,oBAAoB,CACnC,UAGC,EACD,MAAmE,EACnE,QAA6C,EAClB;IAC3B,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;QAC3E,OAAO;YACN,IAAI;YACJ,WAAW,EAAE,GAAG,CAAC,KAAK;YACtB,aAAa,EAAE,GAAG,CAAC,OAAO;YAC1B,eAAe,EAAE,GAAG,CAAC,SAAS;YAC9B,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC;YAC1B,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC;SACvC,CAAC;IAAA,CACF,CAAC,CAAC;AAAA,CACH;AAED,MAAM,UAAU,eAAe,GAAwC;IACtE,OAAO;QACN,MAAM,EAAE,CAAC;QACT,aAAa,EAAE,CAAC;QAChB,eAAe,EAAE,CAAC;QAClB,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,GAAG,EAAE,CAAC;QACN,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,CAAC;QACX,OAAO,EAAE,CAAC;KACV,CAAC;AAAA,CACF;AAED,SAAS,UAAU,CAAC,MAAc,EAAE,SAA2C,EAA4B;IAC1G,OAAO;QACN,MAAM;QACN,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,eAAe,EAAE,SAAS,CAAC,eAAe;QAC1C,QAAQ,EAAE,SAAS,CAAC,QAAQ;QAC5B,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,YAAY,EAAE,SAAS,CAAC,YAAY;QACpC,KAAK,EAAE,SAAS,CAAC,KAAK;KACtB,CAAC;AAAA,CACF;AAED,SAAS,QAAQ,CAChB,OAAsB,EACtB,KAAqF,EAC9E;IACP,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,CAAC;QACzC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC;YACtB,MAAM,EAAE,qBAAqB;YAC7B,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE;YACvB,MAAM,EAAE,eAAe,OAAO,CAAC,IAAI,CAAC,IAAI,UAAU,OAAO,CAAC,IAAI,CAAC,EAAE,+CAA+C;SAChH,CAAC,CAAC;QACH,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvD,CAAC;AAAA,CACD","sourcesContent":["import {\n\ttype ContextBudgetItemV2,\n\ttype ContextBudgetTierV2,\n\ttype ContextRepresentationCandidateV2,\n\ttype ContextSourceRefV2,\n\tchooseHeadroomRepresentation,\n\tderiveRepresentationCandidates,\n\tfullTextTokens,\n} from \"./context-budget-headroom.ts\";\nimport { createFallbackTokenCounter, type TokenCounterAdapter } from \"./context-budget-token-counter.ts\";\nimport {\n\tapplyRepresentationCacheV2,\n\ttype ContextBudgetSelectionCacheV2,\n\twriteRepresentationCacheV2,\n} from \"./context-budget-v2-cache.ts\";\nimport { recordContextBudgetRepresentationCacheHitV2 } from \"./context-budget-v2-cache-telemetry.ts\";\nimport { computeCoverageGap } from \"./context-budget-v2-coverage.ts\";\nimport { contentHashOf } from \"./context-budget-v2-plan-hash.ts\";\nimport { applyRedundancyPenalties, type PlannedItemV2, scoreContextBudgetItemV2 } from \"./context-budget-v2-scoring.ts\";\nimport {\n\tALL_TIERS_V2,\n\ttype QualityDiagnosticV2,\n\ttype SelectedRepresentationV2,\n\ttype TierBudgetAllocationV2,\n} from \"./context-budget-v2-types.ts\";\n\nexport interface OptionalSelectionState {\n\treadonly allocation: ReadonlyMap<ContextBudgetTierV2, { readonly ceiling: number }>;\n\treadonly available: number;\n\treadonly cache?: ContextBudgetSelectionCacheV2;\n\treadonly diagnostics: QualityDiagnosticV2[];\n\treadonly omitted: ContextBudgetItemV2[];\n\treadonly qualityPolicy: Parameters<typeof chooseHeadroomRepresentation>[2];\n\treadonly retrievalFallbacks: ContextSourceRefV2[];\n\treadonly selection: Map<string, SelectedRepresentationV2>;\n\treadonly tierUsed: Record<ContextBudgetTierV2, number>;\n\treadonly usedTokens: number;\n}\n\n/**\n * Cheapest non-omit representation cost for an item, i.e. what admitting it\n * actually costs when the budget is tight. Falls back to full text when no\n * cheaper representation exists.\n */\nfunction minAdmissibleTokens(candidates: readonly ContextRepresentationCandidateV2[], fullTokens: number): number {\n\tlet min = Number.POSITIVE_INFINITY;\n\tfor (const candidate of candidates) {\n\t\tif (candidate.kind === \"omit\") continue;\n\t\tif (candidate.estimatedTokens < min) min = candidate.estimatedTokens;\n\t}\n\treturn Math.max(1, Number.isFinite(min) ? min : fullTokens);\n}\n\nexport function createPlannedItems(\n\titems: readonly ContextBudgetItemV2[],\n\ttokenCounter: TokenCounterAdapter | undefined,\n\tmodelId: string,\n\tqualityPolicy?: Parameters<typeof deriveRepresentationCandidates>[1],\n): PlannedItemV2[] {\n\tconst counter = tokenCounter ?? createFallbackTokenCounter();\n\treturn items.map((item) => {\n\t\tconst overrideTokenEstimate = item.tokenEstimate ?? counter.countText(item.text, modelId).tokens;\n\t\tconst itemWithTokens =\n\t\t\titem.tokenEstimate === undefined ? { ...item, tokenEstimate: overrideTokenEstimate } : item;\n\t\tconst fullTokens = fullTextTokens(itemWithTokens);\n\t\tconst isHard = item.priority === \"hard\" || item.required === true;\n\t\tconst baseScore = isHard ? Number.POSITIVE_INFINITY : scoreContextBudgetItemV2(itemWithTokens, fullTokens);\n\t\tconst candidates =\n\t\t\titemWithTokens.representations ?? deriveRepresentationCandidates(itemWithTokens, qualityPolicy);\n\t\treturn {\n\t\t\titem: itemWithTokens,\n\t\t\tfullTokens,\n\t\t\tadmissibleTokens: minAdmissibleTokens(candidates, fullTokens),\n\t\t\tcontentHash: contentHashOf(item.text),\n\t\t\tbaseScore,\n\t\t\tredundancyPenalty: 0,\n\t\t\teffectiveScore: baseScore,\n\t\t\tisHard,\n\t\t};\n\t});\n}\n\nexport function applyPlannerRedundancyPenalties(plannedItems: PlannedItemV2[]): void {\n\tconst penalties = applyRedundancyPenalties(plannedItems.filter((planned) => !planned.isHard));\n\tfor (const planned of plannedItems) {\n\t\tconst penalty = penalties.get(planned.item.id);\n\t\tif (penalty === undefined) continue;\n\t\tplanned.redundancyPenalty = penalty;\n\t\tplanned.effectiveScore = planned.baseScore - penalty;\n\t}\n}\n\nexport function selectHardItem(\n\tplanned: PlannedItemV2,\n\tselection: Map<string, SelectedRepresentationV2>,\n\ttierUsed: Record<ContextBudgetTierV2, number>,\n): number {\n\tconst candidate: ContextRepresentationCandidateV2 = {\n\t\tkind: \"full\",\n\t\ttext: planned.item.text,\n\t\testimatedTokens: planned.fullTokens,\n\t\tfidelity: planned.item.tokenEstimate !== undefined ? \"exact\" : \"bounded\",\n\t\tsourceRef: planned.item.sourceRef,\n\t};\n\tselection.set(planned.item.id, toSelected(planned.item.id, candidate));\n\ttierUsed[planned.item.tier] += planned.fullTokens;\n\treturn planned.fullTokens;\n}\n\nexport function selectOptionalItem(planned: PlannedItemV2, state: OptionalSelectionState): number {\n\tif (state.usedTokens >= state.available) {\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tconst tierCeiling = state.allocation.get(planned.item.tier)?.ceiling ?? state.available;\n\tconst remaining = Math.max(0, state.available - state.usedTokens);\n\tconst candidates = planned.item.representations ?? deriveRepresentationCandidates(planned.item, state.qualityPolicy);\n\tconst materializedEnabled = planned.item.representations === undefined;\n\tconst cachedCandidates = state.cache\n\t\t? applyRepresentationCacheV2({ planned, candidates, cache: state.cache, materializedEnabled })\n\t\t: candidates;\n\tconst chosen = chooseHeadroomRepresentation(\n\t\t{ ...planned.item, representations: cachedCandidates },\n\t\t{\n\t\t\ttierUsedTokens: state.tierUsed[planned.item.tier],\n\t\t\ttierCeilingTokens: tierCeiling,\n\t\t\tremainingGlobalTokens: remaining,\n\t\t},\n\t\tstate.qualityPolicy,\n\t);\n\tif (chosen.kind === \"omit\") {\n\t\tconst tierRemaining = Math.max(0, tierCeiling - state.tierUsed[planned.item.tier]);\n\t\tconst globalFit = cachedCandidates.filter(\n\t\t\t(candidate) => candidate.kind !== \"omit\" && candidate.estimatedTokens <= remaining,\n\t\t);\n\t\tif (globalFit.length > 0 && globalFit.every((candidate) => candidate.estimatedTokens > tierRemaining)) {\n\t\t\tstate.diagnostics.push({\n\t\t\t\treason: \"tier_ceiling_exceeded\",\n\t\t\t\titemId: planned.item.id,\n\t\t\t\tdetail: `${planned.item.tier} item \"${planned.item.id}\" needs ${Math.min(\n\t\t\t\t\t...globalFit.map((candidate) => candidate.estimatedTokens),\n\t\t\t\t)} tokens with ${tierRemaining} tier tokens remaining`,\n\t\t\t});\n\t\t}\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.tierUsed[planned.item.tier] + chosen.estimatedTokens > tierCeiling) {\n\t\tstate.diagnostics.push({\n\t\t\treason: \"tier_ceiling_exceeded\",\n\t\t\titemId: planned.item.id,\n\t\t\tdetail: `${planned.item.tier} item \"${planned.item.id}\" needs ${chosen.estimatedTokens} tokens with ${Math.max(0, tierCeiling - state.tierUsed[planned.item.tier])} tier tokens remaining`,\n\t\t});\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.usedTokens + chosen.estimatedTokens > state.available) {\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.cache) {\n\t\tif (chosen.cache?.hit === true) {\n\t\t\trecordContextBudgetRepresentationCacheHitV2(\n\t\t\t\tstate.cache.telemetry,\n\t\t\t\tchosen.kind,\n\t\t\t\tchosen.cache.keyKind,\n\t\t\t\tplanned.fullTokens,\n\t\t\t);\n\t\t}\n\t\twriteRepresentationCacheV2({ planned, selected: chosen, cache: state.cache, materializedEnabled });\n\t}\n\tstate.selection.set(planned.item.id, toSelected(planned.item.id, chosen));\n\tstate.tierUsed[planned.item.tier] += chosen.estimatedTokens;\n\treturn state.usedTokens + chosen.estimatedTokens;\n}\n\nexport function emitOmissionDiagnostics(\n\tomitted: readonly ContextBudgetItemV2[],\n\tdiagnostics: QualityDiagnosticV2[],\n\tretrievalFallbacks: ContextSourceRefV2[],\n): void {\n\tfor (const item of omitted) {\n\t\tif (item.priority === \"high\" || item.required === true) {\n\t\t\tdiagnostics.push({\n\t\t\t\treason: \"omitted_high_priority\",\n\t\t\t\titemId: item.id,\n\t\t\t\tdetail: `${item.tier} item \"${item.id}\" could not fit within the prompt budget`,\n\t\t\t});\n\t\t}\n\t\tif (item.sourceRef?.retrievable) {\n\t\t\tdiagnostics.push({\n\t\t\t\treason: \"restore_on_demand_hint\",\n\t\t\t\titemId: item.id,\n\t\t\t\tdetail: `retrievable \"${item.id}\" kept as fallback via ${item.sourceRef.uri}`,\n\t\t\t});\n\t\t\tretrievalFallbacks.push(item.sourceRef);\n\t\t}\n\t}\n}\n\nexport function emitCoverageDiagnostics(\n\tquery: string | undefined,\n\tselection: ReadonlyMap<string, SelectedRepresentationV2>,\n\tdiagnostics: QualityDiagnosticV2[],\n): void {\n\tconst coverage = computeCoverageGap(\n\t\tquery,\n\t\t[...selection.values()].map((representation) => representation.text),\n\t);\n\tif (!coverage.gap) return;\n\tdiagnostics.push({\n\t\treason: \"coverage_gap\",\n\t\tdetail: `query terms not covered by selected context: ${coverage.missing.join(\", \")}`,\n\t});\n}\n\nexport function buildTierAllocations(\n\tallocation: ReadonlyMap<\n\t\tContextBudgetTierV2,\n\t\t{ readonly floor: number; readonly ceiling: number; readonly allocated: number }\n\t>,\n\tdemand: ReadonlyMap<ContextBudgetTierV2, { readonly hard: number }>,\n\ttierUsed: Record<ContextBudgetTierV2, number>,\n): TierBudgetAllocationV2[] {\n\treturn ALL_TIERS_V2.map((tier) => {\n\t\tconst raw = allocation.get(tier) ?? { floor: 0, ceiling: 0, allocated: 0 };\n\t\treturn {\n\t\t\ttier,\n\t\t\tfloorTokens: raw.floor,\n\t\t\tceilingTokens: raw.ceiling,\n\t\t\tallocatedTokens: raw.allocated,\n\t\t\tusedTokens: tierUsed[tier],\n\t\t\thardTokens: demand.get(tier)?.hard ?? 0,\n\t\t};\n\t});\n}\n\nexport function createTierUsage(): Record<ContextBudgetTierV2, number> {\n\treturn {\n\t\tsystem: 0,\n\t\t\"active-goal\": 0,\n\t\t\"current-files\": 0,\n\t\ttools: 0,\n\t\tskills: 0,\n\t\tmcp: 0,\n\t\thistory: 0,\n\t\tevidence: 0,\n\t\tscratch: 0,\n\t};\n}\n\nfunction toSelected(itemId: string, candidate: ContextRepresentationCandidateV2): SelectedRepresentationV2 {\n\treturn {\n\t\titemId,\n\t\tkind: candidate.kind,\n\t\ttext: candidate.text,\n\t\testimatedTokens: candidate.estimatedTokens,\n\t\tfidelity: candidate.fidelity,\n\t\tsourceRef: candidate.sourceRef,\n\t\tsummaryHash: candidate.summaryHash,\n\t\tcompressorId: candidate.compressorId,\n\t\tcache: candidate.cache,\n\t};\n}\n\nfunction omitItem(\n\tplanned: PlannedItemV2,\n\tstate: Pick<OptionalSelectionState, \"diagnostics\" | \"omitted\" | \"retrievalFallbacks\">,\n): void {\n\tstate.omitted.push(planned.item);\n\tif (planned.item.sourceRef?.retrievable) {\n\t\tstate.diagnostics.push({\n\t\t\treason: \"retrieval_miss_risk\",\n\t\t\titemId: planned.item.id,\n\t\t\tdetail: `retrievable ${planned.item.tier} item \"${planned.item.id}\" omitted; keep pointer for restore-on-demand`,\n\t\t});\n\t\tstate.retrievalFallbacks.push(planned.item.sourceRef);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"context-budget-v2-selection.js","sourceRoot":"","sources":["../../src/core/context-budget-v2-selection.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype ContextBudgetItemV2,\n\ttype ContextBudgetTierV2,\n\ttype ContextRepresentationCandidateV2,\n\ttype ContextSourceRefV2,\n\tchooseHeadroomRepresentation,\n\tderiveRepresentationCandidates,\n} from \"./context-budget-headroom.ts\";\nimport {\n\tapplyRepresentationCacheV2,\n\ttype ContextBudgetSelectionCacheV2,\n\twriteRepresentationCacheV2,\n} from \"./context-budget-v2-cache.ts\";\nimport { recordContextBudgetRepresentationCacheHitV2 } from \"./context-budget-v2-cache-telemetry.ts\";\nimport { computeCoverageGap } from \"./context-budget-v2-coverage.ts\";\nimport { applyRedundancyPenalties, type PlannedItemV2 } from \"./context-budget-v2-scoring.ts\";\nimport {\n\tALL_TIERS_V2,\n\ttype QualityDiagnosticV2,\n\ttype SelectedRepresentationV2,\n\ttype TierBudgetAllocationV2,\n} from \"./context-budget-v2-types.ts\";\n\nexport interface OptionalSelectionState {\n\treadonly allocation: ReadonlyMap<ContextBudgetTierV2, { readonly ceiling: number }>;\n\treadonly available: number;\n\treadonly cache?: ContextBudgetSelectionCacheV2;\n\treadonly diagnostics: QualityDiagnosticV2[];\n\treadonly omitted: ContextBudgetItemV2[];\n\treadonly qualityPolicy: Parameters<typeof chooseHeadroomRepresentation>[2];\n\treadonly retrievalFallbacks: ContextSourceRefV2[];\n\treadonly selection: Map<string, SelectedRepresentationV2>;\n\treadonly tierUsed: Record<ContextBudgetTierV2, number>;\n\treadonly usedTokens: number;\n\t/**\n\t * Floor-reservation pass state. When set and the item belongs to this\n\t * tier, the call admits it only while the tier's floor has headroom; an\n\t * item that cannot fit inside the remaining floor is left unselected\n\t * (never omitted) for the later global pass to reconsider under the\n\t * tier's ceiling.\n\t */\n\treadonly floorReservation?: { readonly tier: ContextBudgetTierV2; readonly floorTokens: number };\n\t/**\n\t * Cache-resolved candidates per item, shared across the floor and global\n\t * passes so one item does not double-count provider reads (negative hits,\n\t * stale rejects, misses) or repeat materialization work when it is\n\t * reconsidered.\n\t */\n\treadonly resolvedCandidates?: Map<string, readonly ContextRepresentationCandidateV2[]>;\n}\n\nexport function applyPlannerRedundancyPenalties(plannedItems: PlannedItemV2[]): void {\n\tconst penalties = applyRedundancyPenalties(plannedItems.filter((planned) => !planned.isHard));\n\tfor (const planned of plannedItems) {\n\t\tconst penalty = penalties.get(planned.item.id);\n\t\tif (penalty === undefined) continue;\n\t\tplanned.redundancyPenalty = penalty;\n\t\tplanned.effectiveScore = planned.baseScore - penalty;\n\t}\n}\n\nexport function selectHardItem(\n\tplanned: PlannedItemV2,\n\tselection: Map<string, SelectedRepresentationV2>,\n\ttierUsed: Record<ContextBudgetTierV2, number>,\n): number {\n\tconst candidate: ContextRepresentationCandidateV2 = {\n\t\tkind: \"full\",\n\t\ttext: planned.item.text,\n\t\testimatedTokens: planned.fullTokens,\n\t\tfidelity: planned.item.tokenEstimate !== undefined ? \"exact\" : \"bounded\",\n\t\tsourceRef: planned.item.sourceRef,\n\t};\n\tselection.set(planned.item.id, toSelected(planned.item.id, candidate));\n\ttierUsed[planned.item.tier] += planned.fullTokens;\n\treturn planned.fullTokens;\n}\n\nexport function selectOptionalItem(planned: PlannedItemV2, state: OptionalSelectionState): number {\n\tconst floorPass =\n\t\tstate.floorReservation !== undefined && planned.item.tier === state.floorReservation.tier\n\t\t\t? state.floorReservation\n\t\t\t: undefined;\n\tif (floorPass !== undefined && state.tierUsed[planned.item.tier] >= floorPass.floorTokens) {\n\t\t// This tier's guaranteed claim is already spent; leave the item for the\n\t\t// global pass rather than consuming another tier's budget.\n\t\treturn state.usedTokens;\n\t}\n\tif (state.usedTokens >= state.available) {\n\t\tif (floorPass === undefined) omitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\t// During the floor pass the binding cap is the tier's remaining floor;\n\t// afterwards the tier's ceiling (or the global remainder) applies.\n\tconst tierCeiling =\n\t\tfloorPass !== undefined\n\t\t\t? floorPass.floorTokens\n\t\t\t: (state.allocation.get(planned.item.tier)?.ceiling ?? state.available);\n\tconst remaining = Math.max(0, state.available - state.usedTokens);\n\tconst candidates = planned.item.representations ?? deriveRepresentationCandidates(planned.item, state.qualityPolicy);\n\tconst materializedEnabled = planned.item.representations === undefined;\n\tlet cachedCandidates = state.resolvedCandidates?.get(planned.item.id);\n\tif (cachedCandidates === undefined) {\n\t\tcachedCandidates = state.cache\n\t\t\t? applyRepresentationCacheV2({ planned, candidates, cache: state.cache, materializedEnabled })\n\t\t\t: candidates;\n\t\tstate.resolvedCandidates?.set(planned.item.id, cachedCandidates);\n\t}\n\tconst chosen = chooseHeadroomRepresentation(\n\t\t{ ...planned.item, representations: cachedCandidates },\n\t\t{\n\t\t\ttierUsedTokens: state.tierUsed[planned.item.tier],\n\t\t\ttierCeilingTokens: tierCeiling,\n\t\t\tremainingGlobalTokens: remaining,\n\t\t},\n\t\tstate.qualityPolicy,\n\t);\n\tif (chosen.kind === \"omit\") {\n\t\tif (floorPass !== undefined) {\n\t\t\t// No admissible representation fits inside the remaining floor; the\n\t\t\t// global pass may still admit it against the tier's ceiling.\n\t\t\treturn state.usedTokens;\n\t\t}\n\t\tconst tierRemaining = Math.max(0, tierCeiling - state.tierUsed[planned.item.tier]);\n\t\tconst globalFit = cachedCandidates.filter(\n\t\t\t(candidate) => candidate.kind !== \"omit\" && candidate.estimatedTokens <= remaining,\n\t\t);\n\t\tif (globalFit.length > 0 && globalFit.every((candidate) => candidate.estimatedTokens > tierRemaining)) {\n\t\t\tstate.diagnostics.push({\n\t\t\t\treason: \"tier_ceiling_exceeded\",\n\t\t\t\titemId: planned.item.id,\n\t\t\t\tdetail: `${planned.item.tier} item \"${planned.item.id}\" needs ${Math.min(\n\t\t\t\t\t...globalFit.map((candidate) => candidate.estimatedTokens),\n\t\t\t\t)} tokens with ${tierRemaining} tier tokens remaining`,\n\t\t\t});\n\t\t}\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.tierUsed[planned.item.tier] + chosen.estimatedTokens > tierCeiling) {\n\t\tif (floorPass !== undefined) {\n\t\t\treturn state.usedTokens;\n\t\t}\n\t\tstate.diagnostics.push({\n\t\t\treason: \"tier_ceiling_exceeded\",\n\t\t\titemId: planned.item.id,\n\t\t\tdetail: `${planned.item.tier} item \"${planned.item.id}\" needs ${chosen.estimatedTokens} tokens with ${Math.max(0, tierCeiling - state.tierUsed[planned.item.tier])} tier tokens remaining`,\n\t\t});\n\t\tomitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.usedTokens + chosen.estimatedTokens > state.available) {\n\t\tif (floorPass === undefined) omitItem(planned, state);\n\t\treturn state.usedTokens;\n\t}\n\tif (state.cache) {\n\t\tif (chosen.cache?.hit === true) {\n\t\t\trecordContextBudgetRepresentationCacheHitV2(\n\t\t\t\tstate.cache.telemetry,\n\t\t\t\tchosen.kind,\n\t\t\t\tchosen.cache.keyKind,\n\t\t\t\tplanned.fullTokens,\n\t\t\t);\n\t\t}\n\t\twriteRepresentationCacheV2({ planned, selected: chosen, cache: state.cache, materializedEnabled });\n\t}\n\tstate.selection.set(planned.item.id, toSelected(planned.item.id, chosen));\n\tstate.tierUsed[planned.item.tier] += chosen.estimatedTokens;\n\treturn state.usedTokens + chosen.estimatedTokens;\n}\n\nexport function emitOmissionDiagnostics(\n\tomitted: readonly ContextBudgetItemV2[],\n\tdiagnostics: QualityDiagnosticV2[],\n\tretrievalFallbacks: ContextSourceRefV2[],\n): void {\n\tfor (const item of omitted) {\n\t\tif (item.priority === \"high\" || item.required === true) {\n\t\t\tdiagnostics.push({\n\t\t\t\treason: \"omitted_high_priority\",\n\t\t\t\titemId: item.id,\n\t\t\t\tdetail: `${item.tier} item \"${item.id}\" could not fit within the prompt budget`,\n\t\t\t});\n\t\t}\n\t\tif (item.sourceRef?.retrievable) {\n\t\t\tdiagnostics.push({\n\t\t\t\treason: \"restore_on_demand_hint\",\n\t\t\t\titemId: item.id,\n\t\t\t\tdetail: `retrievable \"${item.id}\" kept as fallback via ${item.sourceRef.uri}`,\n\t\t\t});\n\t\t\tretrievalFallbacks.push(item.sourceRef);\n\t\t}\n\t}\n}\n\nexport function emitCoverageDiagnostics(\n\tquery: string | undefined,\n\tselection: ReadonlyMap<string, SelectedRepresentationV2>,\n\tdiagnostics: QualityDiagnosticV2[],\n): void {\n\tconst coverage = computeCoverageGap(\n\t\tquery,\n\t\t[...selection.values()].map((representation) => representation.text),\n\t);\n\tif (!coverage.gap) return;\n\tdiagnostics.push({\n\t\treason: \"coverage_gap\",\n\t\tdetail: `query terms not covered by selected context: ${coverage.missing.join(\", \")}`,\n\t});\n}\n\nexport function buildTierAllocations(\n\tallocation: ReadonlyMap<\n\t\tContextBudgetTierV2,\n\t\t{ readonly floor: number; readonly ceiling: number; readonly allocated: number }\n\t>,\n\tdemand: ReadonlyMap<ContextBudgetTierV2, { readonly hard: number }>,\n\ttierUsed: Record<ContextBudgetTierV2, number>,\n): TierBudgetAllocationV2[] {\n\treturn ALL_TIERS_V2.map((tier) => {\n\t\tconst raw = allocation.get(tier) ?? { floor: 0, ceiling: 0, allocated: 0 };\n\t\treturn {\n\t\t\ttier,\n\t\t\tfloorTokens: raw.floor,\n\t\t\tceilingTokens: raw.ceiling,\n\t\t\tallocatedTokens: raw.allocated,\n\t\t\tusedTokens: tierUsed[tier],\n\t\t\thardTokens: demand.get(tier)?.hard ?? 0,\n\t\t};\n\t});\n}\n\nexport function createTierUsage(): Record<ContextBudgetTierV2, number> {\n\treturn Object.fromEntries(ALL_TIERS_V2.map((tier) => [tier, 0])) as Record<ContextBudgetTierV2, number>;\n}\n\nfunction toSelected(itemId: string, candidate: ContextRepresentationCandidateV2): SelectedRepresentationV2 {\n\treturn {\n\t\titemId,\n\t\tkind: candidate.kind,\n\t\ttext: candidate.text,\n\t\testimatedTokens: candidate.estimatedTokens,\n\t\tfidelity: candidate.fidelity,\n\t\tsourceRef: candidate.sourceRef,\n\t\tsummaryHash: candidate.summaryHash,\n\t\tcompressorId: candidate.compressorId,\n\t\tcache: candidate.cache,\n\t};\n}\n\nfunction omitItem(\n\tplanned: PlannedItemV2,\n\tstate: Pick<OptionalSelectionState, \"diagnostics\" | \"omitted\" | \"retrievalFallbacks\">,\n): void {\n\tstate.omitted.push(planned.item);\n\tif (planned.item.sourceRef?.retrievable) {\n\t\tstate.diagnostics.push({\n\t\t\treason: \"retrieval_miss_risk\",\n\t\t\titemId: planned.item.id,\n\t\t\tdetail: `retrievable ${planned.item.tier} item \"${planned.item.id}\" omitted; keep pointer for restore-on-demand`,\n\t\t});\n\t\tstate.retrievalFallbacks.push(planned.item.sourceRef);\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-budget-v2-tiers.d.ts","sourceRoot":"","sources":["../../src/core/context-budget-v2-tiers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAgB,KAAK,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAErF,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,SAAS,aAAa,EAAE,GAAG,GAAG,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAajH;AAED,wBAAgB,aAAa,CAC5B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC,EACjE,MAAM,EAAE,GAAG,CAAC,mBAAmB,EAAE,aAAa,CAAC,GAC7C,GAAG,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"context-budget-v2-tiers.d.ts","sourceRoot":"","sources":["../../src/core/context-budget-v2-tiers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAgB,KAAK,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAErF,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,SAAS,aAAa,EAAE,GAAG,GAAG,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAajH;AAED,wBAAgB,aAAa,CAC5B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC,EACjE,MAAM,EAAE,GAAG,CAAC,mBAAmB,EAAE,aAAa,CAAC,GAC7C,GAAG,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAmB7C","sourcesContent":["import type { ContextBudgetTierV2 } from \"./context-budget-headroom.ts\";\nimport type { PlannedItemV2 } from \"./context-budget-v2-scoring.ts\";\nimport { ALL_TIERS_V2, type TierBudgetPolicyV2 } from \"./context-budget-v2-types.ts\";\n\nexport interface RawTierDemand {\n\treadonly demand: number;\n\treadonly hard: number;\n}\n\nexport interface RawTierAllocation {\n\treadonly floor: number;\n\treadonly ceiling: number;\n\treadonly allocated: number;\n}\n\nexport function computeTierDemand(plannedItems: readonly PlannedItemV2[]): Map<ContextBudgetTierV2, RawTierDemand> {\n\tconst demand = new Map<ContextBudgetTierV2, RawTierDemand>();\n\tfor (const tier of ALL_TIERS_V2) {\n\t\tdemand.set(tier, { demand: 0, hard: 0 });\n\t}\n\tfor (const planned of plannedItems) {\n\t\tconst entry = demand.get(planned.item.tier) ?? { demand: 0, hard: 0 };\n\t\tdemand.set(planned.item.tier, {\n\t\t\tdemand: entry.demand + planned.fullTokens,\n\t\t\thard: entry.hard + (planned.isHard ? planned.fullTokens : 0),\n\t\t});\n\t}\n\treturn demand;\n}\n\nexport function allocateTiers(\n\tavailable: number,\n\tpolicy: Readonly<Record<ContextBudgetTierV2, TierBudgetPolicyV2>>,\n\tdemand: Map<ContextBudgetTierV2, RawTierDemand>,\n): Map<ContextBudgetTierV2, RawTierAllocation> {\n\tconst out = new Map<ContextBudgetTierV2, RawTierAllocation>();\n\n\tfor (const tier of ALL_TIERS_V2) {\n\t\tconst floor = Math.max(0, Math.floor(policy[tier].floorPct * available));\n\t\tconst ceiling = Math.max(floor, Math.floor(policy[tier].ceilingPct * available));\n\t\tconst entry = demand.get(tier) ?? { demand: 0, hard: 0 };\n\t\tconst want = Math.max(entry.demand, entry.hard);\n\t\t// `allocated` is the tier's guaranteed claim — what the floor pass is\n\t\t// entitled to spend on this tier's own items before global competition:\n\t\t// its hard demand (always admitted) or, beyond that, its demand capped\n\t\t// at the floor. The previous residual-redistribution loop could never\n\t\t// move this number on normal input (min(want, max(ceiling, hard)) makes\n\t\t// want-allocated or ceiling-allocated zero), so it is removed rather\n\t\t// than kept as dead code. Leftover budget competes globally in the\n\t\t// ceiling-bounded selection pass instead.\n\t\tout.set(tier, { floor, ceiling, allocated: Math.min(want, Math.max(floor, entry.hard)) });\n\t}\n\treturn out;\n}\n"]}
|