@cortexkit/opencode-magic-context 0.36.1 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +2 -1
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +10 -0
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-mt0ttc4x.js → conflict-warning-hook-an4fxhwf.js} +3 -3
- package/dist/{derive-budgets-88mxk2w1.js → derive-budgets-da4yg3tz.js} +3 -2
- package/dist/features/magic-context/context-authority.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/classify-prompt.d.ts +5 -1
- package/dist/features/magic-context/dreamer/classify-prompt.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/manifest-parser.d.ts +8 -0
- package/dist/features/magic-context/dreamer/manifest-parser.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +7 -1
- package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts +18 -0
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +5 -0
- package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify-prompt.d.ts +5 -1
- package/dist/features/magic-context/dreamer/verify-prompt.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/fail-closed-block.d.ts +6 -1
- package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-openai.d.ts +3 -1
- package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity.d.ts +6 -0
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
- package/dist/features/magic-context/reclaim-protection.d.ts +13 -0
- package/dist/features/magic-context/reclaim-protection.d.ts.map +1 -0
- package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/wake-plane.d.ts +21 -0
- package/dist/features/magic-context/smart-notes/wake-plane.d.ts.map +1 -0
- package/dist/features/magic-context/storage-db.d.ts +19 -3
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +23 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
- package/dist/features/magic-context/storage-primers.d.ts +11 -0
- package/dist/features/magic-context/storage-primers.d.ts.map +1 -1
- package/dist/features/magic-context/storage-schema-helpers.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +13 -5
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +7 -0
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
- package/dist/features/magic-context/window-report-ledger.d.ts +70 -0
- package/dist/features/magic-context/window-report-ledger.d.ts.map +1 -0
- package/dist/hooks/auto-update-checker/checker.d.ts +8 -1
- package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
- package/dist/hooks/auto-update-checker/index.d.ts.map +1 -1
- package/dist/hooks/magic-context/channel2-cycle.d.ts +16 -0
- package/dist/hooks/magic-context/channel2-cycle.d.ts.map +1 -0
- package/dist/hooks/magic-context/channel2-delivery.d.ts +3 -9
- package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +2 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +33 -103
- package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
- package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts +4 -0
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts +3 -1
- package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/fold-execution-gate.d.ts +2 -0
- package/dist/hooks/magic-context/fold-execution-gate.d.ts.map +1 -0
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/live-session-state.d.ts +3 -0
- package/dist/hooks/magic-context/live-session-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +20 -0
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-state-sync.d.ts +8 -0
- package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-wire.d.ts +6 -1
- package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +21 -2
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +27 -0
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +78 -0
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -0
- package/dist/hooks/magic-context/tool-reclaim.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +14 -3
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +10 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
- package/dist/{index-nsx2n9eg.js → index-4cz5nfxf.js} +3 -3
- package/dist/{index-f1tnb3vm.js → index-8pqfcghm.js} +21 -9
- package/dist/index-9zhhvr4w.js +733 -0
- package/dist/{index-zp6x6s6a.js → index-cae89eas.js} +25 -6
- package/dist/index-cgyfn1s2.js +53 -0
- package/dist/{index-3zqcdwqr.js → index-crke4z5j.js} +7 -4
- package/dist/{index-1skzp4dc.js → index-mmvhrqqb.js} +1991 -274
- package/dist/{index-tsgs7td8.js → index-pck9vadr.js} +1 -1
- package/dist/{index-3tnkymva.js → index-sw8gnq34.js} +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1714 -988
- package/dist/plugin/hooks/create-session-hooks.d.ts +3 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +2 -0
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/{recomp-orchestrator-a0g9b52q.js → recomp-orchestrator-jsde4ygw.js} +7 -6
- package/dist/{safe-notification-target-c11fdda2.js → safe-notification-target-b693f9x3.js} +2 -2
- package/dist/{send-session-notification-bgtf4853.js → send-session-notification-dxske5zm.js} +3 -3
- package/dist/shared/conflict-detector.d.ts +63 -0
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/harness-provider-map.d.ts +8 -0
- package/dist/shared/harness-provider-map.d.ts.map +1 -1
- package/dist/shared/logger.d.ts +8 -0
- package/dist/shared/logger.d.ts.map +1 -1
- package/dist/shared/models-dev-cache.d.ts +7 -0
- package/dist/shared/models-dev-cache.d.ts.map +1 -1
- package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
- package/dist/shared/prompt-surface.d.ts +2 -0
- package/dist/shared/prompt-surface.d.ts.map +1 -1
- package/dist/shared/rpc-client.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +29 -0
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/rpc-utils.d.ts +28 -9
- package/dist/shared/rpc-utils.d.ts.map +1 -1
- package/dist/shared/tail-hygiene-status.d.ts +15 -0
- package/dist/shared/tail-hygiene-status.d.ts.map +1 -0
- package/dist/shared/window-geometry.d.ts +90 -0
- package/dist/shared/window-geometry.d.ts.map +1 -0
- package/dist/{storage-meta-session-df9tstzr.js → storage-meta-session-mk4gsnke.js} +4 -3
- package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/tui/data/context-db.d.ts.map +1 -1
- package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/config/index.ts +2 -0
- package/src/config/latch-permanence-guard.test.ts +218 -0
- package/src/config/project-security.ts +10 -1
- package/src/config/schema/magic-context.ts +12 -2
- package/src/shared/__fixtures__/window-overlay.v1.json +337 -0
- package/src/shared/conflict-detector.test.ts +176 -1
- package/src/shared/conflict-detector.ts +126 -3
- package/src/shared/harness-provider-map.test.ts +20 -0
- package/src/shared/harness-provider-map.ts +19 -0
- package/src/shared/logger.test.ts +119 -0
- package/src/shared/logger.ts +33 -15
- package/src/shared/models-dev-cache.test.ts +42 -0
- package/src/shared/models-dev-cache.ts +62 -9
- package/src/shared/prompt-surface-runtime.ts +5 -3
- package/src/shared/prompt-surface.test.ts +38 -0
- package/src/shared/prompt-surface.ts +15 -2
- package/src/shared/rpc-client.ts +4 -2
- package/src/shared/rpc-server.ts +1 -0
- package/src/shared/rpc-types.ts +30 -0
- package/src/shared/rpc-utils.test.ts +162 -13
- package/src/shared/rpc-utils.ts +224 -31
- package/src/shared/tail-hygiene-status.ts +57 -0
- package/src/shared/window-geometry.test.ts +342 -0
- package/src/shared/window-geometry.ts +626 -0
- package/src/tui/data/context-db.ts +5 -0
- package/src/tui/index.tsx +33 -1
- package/src/tui/slots/sidebar-content.tsx +17 -5
- package/src/tui-compiled/data/context-db.ts +5 -0
- package/src/tui-compiled/index.tsx +359 -273
- package/src/tui-compiled/slots/sidebar-content.tsx +316 -287
- package/dist/index-wgvxkqpx.js +0 -342
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { getDataDir } from "./data-path";
|
|
4
|
+
import { modelRefLookupOrder } from "./harness-provider-map";
|
|
5
|
+
import { sessionLog } from "./logger";
|
|
6
|
+
import type { ModelLimit } from "./models-dev-cache";
|
|
7
|
+
|
|
8
|
+
export const WINDOW_OVERLAY_SCHEMA = "fusiform-window-overlay/v1";
|
|
9
|
+
export const PROMPT_WALL_MARGIN = 4_096;
|
|
10
|
+
export const PI_OUTPUT_FLOOR = 4_096;
|
|
11
|
+
export const OPENCODE_OUTPUT_CAP = 32_000;
|
|
12
|
+
|
|
13
|
+
const MIN_PLAUSIBLE_CONTEXT_LIMIT = 1_024;
|
|
14
|
+
const OUTPUT_RESERVE_CAP_RATIO = 0.25;
|
|
15
|
+
|
|
16
|
+
export type WindowGeometry = "shared_upfront" | "shared_truncating" | "separate";
|
|
17
|
+
export type WindowReserveSource = "output_catalog" | "output_config" | "wall_margin" | "none";
|
|
18
|
+
export type WindowOverlayGrade =
|
|
19
|
+
| "provider_asserted_runtime"
|
|
20
|
+
| "measured"
|
|
21
|
+
| "provider_asserted_doc"
|
|
22
|
+
| "catalog"
|
|
23
|
+
| "unknown";
|
|
24
|
+
export type WindowOverlayUnits = "provider" | "estimate";
|
|
25
|
+
export type WindowOverlayBoundary = "Observed" | "Asserted" | "Corrected";
|
|
26
|
+
export type WindowOverlayUnknownWhy =
|
|
27
|
+
| "placeholder_output_equals_context"
|
|
28
|
+
| "placeholder_zero"
|
|
29
|
+
| "never_measured"
|
|
30
|
+
// Asserts the KEY cannot hold one fact (e.g. a router samples heterogeneous
|
|
31
|
+
// backends per request), so measurement cannot settle it and measured
|
|
32
|
+
// reports must not be promoted into stated/bracket cells at this key.
|
|
33
|
+
// Ratified terminal at fusiform 080e70208aad713d (2026-08-13), added without a schema bump: an
|
|
34
|
+
// additive vocabulary value degrades per-cell for ignorant consumers,
|
|
35
|
+
// whereas a version bump would trigger the file-level refusal rule.
|
|
36
|
+
| "not_single_valued_at_key"
|
|
37
|
+
| "retracted";
|
|
38
|
+
|
|
39
|
+
export type WindowOverlayFactValue =
|
|
40
|
+
| { kind: "stated"; value: number | string }
|
|
41
|
+
| { kind: "bracket"; at_least?: number; below?: number }
|
|
42
|
+
| { kind: "unknown"; why: WindowOverlayUnknownWhy };
|
|
43
|
+
|
|
44
|
+
export interface WindowOverlayFact {
|
|
45
|
+
value: WindowOverlayFactValue;
|
|
46
|
+
grade: WindowOverlayGrade;
|
|
47
|
+
units: WindowOverlayUnits;
|
|
48
|
+
boundary: WindowOverlayBoundary;
|
|
49
|
+
source_ref: string;
|
|
50
|
+
observed_at: string;
|
|
51
|
+
[unknownField: string]: unknown;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface WindowOverlayCell {
|
|
55
|
+
provider_id: string;
|
|
56
|
+
model_id: string;
|
|
57
|
+
/** Unknown fact keys are retained so a newer producer can coexist with this v1 consumer. */
|
|
58
|
+
facts: Record<string, WindowOverlayFact>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface WindowOverlay {
|
|
62
|
+
schema: typeof WINDOW_OVERLAY_SCHEMA;
|
|
63
|
+
generated_at: string;
|
|
64
|
+
minted_provider_ids: string[];
|
|
65
|
+
cells: WindowOverlayCell[];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ResolvedWindowOverlayFacts {
|
|
69
|
+
/** Includes facts whose tagged value is explicitly unknown. */
|
|
70
|
+
facts: Record<string, WindowOverlayFact>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface WindowDerivation {
|
|
74
|
+
window: number;
|
|
75
|
+
reserve: number;
|
|
76
|
+
reserveSource: WindowReserveSource;
|
|
77
|
+
geometry: WindowGeometry;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface WindowGeometryResult {
|
|
81
|
+
usableSoft: number;
|
|
82
|
+
usableHard: number;
|
|
83
|
+
geometry: WindowGeometry;
|
|
84
|
+
derivation: WindowDerivation;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface DeriveWindowGeometryOptions {
|
|
88
|
+
overlay?: ResolvedWindowOverlayFacts;
|
|
89
|
+
/** A provider/auth hook has higher precedence than the overlay, field by field. */
|
|
90
|
+
providerLimit?: ModelLimit;
|
|
91
|
+
/** Resolved user override; higher precedence than catalog, overlay, and geometry defaults. */
|
|
92
|
+
outputReserveOverride?: number;
|
|
93
|
+
harness?: "opencode" | "pi";
|
|
94
|
+
/** Detected overflow remains the final downward cap regardless of other sources. */
|
|
95
|
+
contextCap?: number;
|
|
96
|
+
log?: (message: string) => void;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const PROVIDER_GEOMETRY: Readonly<Record<string, WindowGeometry>> = {
|
|
100
|
+
anthropic: "shared_truncating",
|
|
101
|
+
xai: "shared_truncating",
|
|
102
|
+
google: "separate",
|
|
103
|
+
"google-antigravity": "separate",
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const GRADES = new Set<WindowOverlayGrade>([
|
|
107
|
+
"provider_asserted_runtime",
|
|
108
|
+
"measured",
|
|
109
|
+
"provider_asserted_doc",
|
|
110
|
+
"catalog",
|
|
111
|
+
"unknown",
|
|
112
|
+
]);
|
|
113
|
+
const UNITS = new Set<WindowOverlayUnits>(["provider", "estimate"]);
|
|
114
|
+
const BOUNDARIES = new Set<WindowOverlayBoundary>(["Observed", "Asserted", "Corrected"]);
|
|
115
|
+
const UNKNOWN_REASONS = new Set<WindowOverlayUnknownWhy>([
|
|
116
|
+
"placeholder_output_equals_context",
|
|
117
|
+
"placeholder_zero",
|
|
118
|
+
"never_measured",
|
|
119
|
+
"not_single_valued_at_key",
|
|
120
|
+
"retracted",
|
|
121
|
+
]);
|
|
122
|
+
const NUMERIC_FACT_KEYS = new Set([
|
|
123
|
+
"window.advertised",
|
|
124
|
+
"window.enforced",
|
|
125
|
+
"output.advertised",
|
|
126
|
+
"output.enforced",
|
|
127
|
+
"output.default",
|
|
128
|
+
]);
|
|
129
|
+
|
|
130
|
+
let configuredOverlayPath: string | undefined;
|
|
131
|
+
let loadedOverlayPath: string | undefined;
|
|
132
|
+
let loadedOverlay: WindowOverlay | null | undefined;
|
|
133
|
+
const geometryClampLogSeen = new Set<string>();
|
|
134
|
+
|
|
135
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
136
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function isFinitePositive(value: unknown): value is number {
|
|
140
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Convert the ratified tagged numeric union into the conservative scalar used by derivation. */
|
|
144
|
+
export function scalarizeFact(value: WindowOverlayFactValue): number | undefined {
|
|
145
|
+
if (value.kind === "stated") return isFinitePositive(value.value) ? value.value : undefined;
|
|
146
|
+
if (value.kind === "bracket") {
|
|
147
|
+
return isFinitePositive(value.at_least) ? value.at_least : undefined;
|
|
148
|
+
}
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function parseFactValue(value: unknown): WindowOverlayFactValue | undefined {
|
|
153
|
+
if (!isRecord(value) || typeof value.kind !== "string") return undefined;
|
|
154
|
+
if (value.kind === "stated") {
|
|
155
|
+
if (
|
|
156
|
+
(typeof value.value !== "number" || !Number.isFinite(value.value)) &&
|
|
157
|
+
typeof value.value !== "string"
|
|
158
|
+
) {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
return { kind: "stated", value: value.value };
|
|
162
|
+
}
|
|
163
|
+
if (value.kind === "bracket") {
|
|
164
|
+
const atLeast = value.at_least;
|
|
165
|
+
const below = value.below;
|
|
166
|
+
if (atLeast === undefined && below === undefined) return { kind: "bracket" };
|
|
167
|
+
if (atLeast !== undefined && !isFinitePositive(atLeast)) return undefined;
|
|
168
|
+
if (below !== undefined && !isFinitePositive(below)) return undefined;
|
|
169
|
+
if (isFinitePositive(atLeast) && isFinitePositive(below) && below <= atLeast) {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
kind: "bracket",
|
|
174
|
+
...(isFinitePositive(atLeast) ? { at_least: atLeast } : {}),
|
|
175
|
+
...(isFinitePositive(below) ? { below } : {}),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
if (value.kind === "unknown" && UNKNOWN_REASONS.has(value.why as WindowOverlayUnknownWhy)) {
|
|
179
|
+
return { kind: "unknown", why: value.why as WindowOverlayUnknownWhy };
|
|
180
|
+
}
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function parseFact(key: string, value: unknown): WindowOverlayFact | undefined {
|
|
185
|
+
if (!isRecord(value)) return undefined;
|
|
186
|
+
const parsedValue = parseFactValue(value.value);
|
|
187
|
+
if (
|
|
188
|
+
!parsedValue ||
|
|
189
|
+
!GRADES.has(value.grade as WindowOverlayGrade) ||
|
|
190
|
+
!UNITS.has(value.units as WindowOverlayUnits) ||
|
|
191
|
+
!BOUNDARIES.has(value.boundary as WindowOverlayBoundary) ||
|
|
192
|
+
typeof value.source_ref !== "string" ||
|
|
193
|
+
value.source_ref.length === 0 ||
|
|
194
|
+
typeof value.observed_at !== "string" ||
|
|
195
|
+
value.observed_at.length === 0
|
|
196
|
+
) {
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
199
|
+
if (
|
|
200
|
+
NUMERIC_FACT_KEYS.has(key) &&
|
|
201
|
+
parsedValue.kind === "stated" &&
|
|
202
|
+
!isFinitePositive(parsedValue.value)
|
|
203
|
+
) {
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
if (
|
|
207
|
+
key === "geometry" &&
|
|
208
|
+
parsedValue.kind === "stated" &&
|
|
209
|
+
!["shared_upfront", "shared_truncating", "separate"].includes(String(parsedValue.value))
|
|
210
|
+
) {
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
...value,
|
|
215
|
+
value: parsedValue,
|
|
216
|
+
grade: value.grade as WindowOverlayGrade,
|
|
217
|
+
units: value.units as WindowOverlayUnits,
|
|
218
|
+
boundary: value.boundary as WindowOverlayBoundary,
|
|
219
|
+
source_ref: value.source_ref,
|
|
220
|
+
observed_at: value.observed_at,
|
|
221
|
+
} as WindowOverlayFact;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function parseWindowOverlay(value: unknown): {
|
|
225
|
+
overlay?: WindowOverlay;
|
|
226
|
+
badCells: number;
|
|
227
|
+
refusal?: string;
|
|
228
|
+
} {
|
|
229
|
+
if (!isRecord(value)) {
|
|
230
|
+
return { badCells: 0, refusal: "overlay root is not an object" };
|
|
231
|
+
}
|
|
232
|
+
if (value.schema !== WINDOW_OVERLAY_SCHEMA) {
|
|
233
|
+
return {
|
|
234
|
+
badCells: 0,
|
|
235
|
+
refusal: `unrecognized schema ${JSON.stringify(value.schema)}`,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
if (
|
|
239
|
+
typeof value.generated_at !== "string" ||
|
|
240
|
+
!Array.isArray(value.minted_provider_ids) ||
|
|
241
|
+
!value.minted_provider_ids.every((id) => typeof id === "string" && id.length > 0) ||
|
|
242
|
+
!Array.isArray(value.cells)
|
|
243
|
+
) {
|
|
244
|
+
return { badCells: 0, refusal: "invalid v1 envelope" };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const cells: WindowOverlayCell[] = [];
|
|
248
|
+
let badCells = 0;
|
|
249
|
+
for (const rawCell of value.cells) {
|
|
250
|
+
if (
|
|
251
|
+
!isRecord(rawCell) ||
|
|
252
|
+
typeof rawCell.provider_id !== "string" ||
|
|
253
|
+
rawCell.provider_id.length === 0 ||
|
|
254
|
+
typeof rawCell.model_id !== "string" ||
|
|
255
|
+
rawCell.model_id.length === 0 ||
|
|
256
|
+
!isRecord(rawCell.facts)
|
|
257
|
+
) {
|
|
258
|
+
badCells++;
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
const facts: Record<string, WindowOverlayFact> = {};
|
|
262
|
+
let valid = true;
|
|
263
|
+
for (const [key, rawFact] of Object.entries(rawCell.facts)) {
|
|
264
|
+
const fact = parseFact(key, rawFact);
|
|
265
|
+
if (!fact) {
|
|
266
|
+
valid = false;
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
facts[key] = fact;
|
|
270
|
+
}
|
|
271
|
+
if (!valid) {
|
|
272
|
+
badCells++;
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
cells.push({
|
|
276
|
+
provider_id: rawCell.provider_id,
|
|
277
|
+
model_id: rawCell.model_id,
|
|
278
|
+
facts,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
overlay: {
|
|
284
|
+
schema: WINDOW_OVERLAY_SCHEMA,
|
|
285
|
+
generated_at: value.generated_at,
|
|
286
|
+
minted_provider_ids: [...value.minted_provider_ids],
|
|
287
|
+
cells,
|
|
288
|
+
},
|
|
289
|
+
badCells,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function defaultWindowOverlayPath(): string {
|
|
294
|
+
return join(getDataDir(), "fusiform", "window-overlay.json");
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export function readWindowOverlayFile(
|
|
298
|
+
path: string,
|
|
299
|
+
log: (message: string) => void = (message) => sessionLog("global", message),
|
|
300
|
+
): WindowOverlay | undefined {
|
|
301
|
+
let raw: string;
|
|
302
|
+
try {
|
|
303
|
+
raw = readFileSync(path, "utf8");
|
|
304
|
+
} catch (error) {
|
|
305
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
|
|
306
|
+
log(`window-overlay: unable to read ${path}; overlay ignored`);
|
|
307
|
+
return undefined;
|
|
308
|
+
}
|
|
309
|
+
let decoded: unknown;
|
|
310
|
+
try {
|
|
311
|
+
decoded = JSON.parse(raw);
|
|
312
|
+
} catch {
|
|
313
|
+
log(`window-overlay: invalid JSON in ${path}; overlay ignored`);
|
|
314
|
+
return undefined;
|
|
315
|
+
}
|
|
316
|
+
const parsed = parseWindowOverlay(decoded);
|
|
317
|
+
if (parsed.refusal) {
|
|
318
|
+
log(`window-overlay: ${parsed.refusal} in ${path}; entire overlay ignored`);
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
if (parsed.badCells > 0) {
|
|
322
|
+
log(`window-overlay: skipped ${parsed.badCells} invalid cell(s) from ${path}`);
|
|
323
|
+
}
|
|
324
|
+
return parsed.overlay;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/** Set the user-tier overlay path. Undefined restores the Fusiform data-dir default. */
|
|
328
|
+
export function setWindowOverlayPath(path: string | undefined): void {
|
|
329
|
+
configuredOverlayPath = path;
|
|
330
|
+
loadedOverlayPath = undefined;
|
|
331
|
+
loadedOverlay = undefined;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function clearWindowOverlayCacheForTest(): void {
|
|
335
|
+
loadedOverlayPath = undefined;
|
|
336
|
+
loadedOverlay = undefined;
|
|
337
|
+
geometryClampLogSeen.clear();
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function getWindowOverlay(): WindowOverlay | undefined {
|
|
341
|
+
const path = configuredOverlayPath ?? defaultWindowOverlayPath();
|
|
342
|
+
if (loadedOverlayPath === path && loadedOverlay !== undefined) {
|
|
343
|
+
return loadedOverlay ?? undefined;
|
|
344
|
+
}
|
|
345
|
+
loadedOverlayPath = path;
|
|
346
|
+
loadedOverlay = readWindowOverlayFile(path) ?? null;
|
|
347
|
+
return loadedOverlay ?? undefined;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function resolveWindowOverlayFacts(
|
|
351
|
+
providerID: string,
|
|
352
|
+
modelID: string,
|
|
353
|
+
overlay: WindowOverlay | undefined = getWindowOverlay(),
|
|
354
|
+
): ResolvedWindowOverlayFacts | undefined {
|
|
355
|
+
if (!overlay) return undefined;
|
|
356
|
+
const modelRefs = modelRefLookupOrder(`${providerID}/${modelID}`);
|
|
357
|
+
const providerCandidates = new Set(modelRefs.map((ref) => ref.slice(0, ref.indexOf("/"))));
|
|
358
|
+
const modelCandidates = new Set([
|
|
359
|
+
modelID,
|
|
360
|
+
...modelRefs.map((ref) => ref.slice(ref.indexOf("/") + 1)),
|
|
361
|
+
]);
|
|
362
|
+
const colon = modelID.lastIndexOf(":");
|
|
363
|
+
if (colon > 0) modelCandidates.add(modelID.slice(0, colon));
|
|
364
|
+
|
|
365
|
+
const wildcardFacts: Record<string, WindowOverlayFact> = {};
|
|
366
|
+
const specificFacts: Record<string, WindowOverlayFact> = {};
|
|
367
|
+
for (const cell of overlay.cells) {
|
|
368
|
+
if (!providerCandidates.has(cell.provider_id)) continue;
|
|
369
|
+
if (cell.model_id === "*") Object.assign(wildcardFacts, cell.facts);
|
|
370
|
+
else if (modelCandidates.has(cell.model_id)) Object.assign(specificFacts, cell.facts);
|
|
371
|
+
}
|
|
372
|
+
const facts = { ...wildcardFacts, ...specificFacts };
|
|
373
|
+
return Object.keys(facts).length > 0 ? { facts } : undefined;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function numericOverlayFact(
|
|
377
|
+
overlay: ResolvedWindowOverlayFacts | undefined,
|
|
378
|
+
key: string,
|
|
379
|
+
): number | undefined {
|
|
380
|
+
const fact = overlay?.facts[key];
|
|
381
|
+
return fact ? scalarizeFact(fact.value) : undefined;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Three-state geometry resolution from the overlay. The absent-vs-unknown
|
|
386
|
+
* distinction is ratified contract semantics: a fact ABSENT from the cell was
|
|
387
|
+
* never considered (our static provider table still applies), while a fact
|
|
388
|
+
* present with kind "unknown" was considered and has no answer — the dataset
|
|
389
|
+
* owner checked the primary source and found the usual inference unsupported
|
|
390
|
+
* (e.g. Google's own docs contradict the separate-quota reading), so the
|
|
391
|
+
* static assumption built on that same inference must NOT apply either.
|
|
392
|
+
*/
|
|
393
|
+
function overlayGeometry(
|
|
394
|
+
overlay: ResolvedWindowOverlayFacts | undefined,
|
|
395
|
+
): { kind: "stated"; value: WindowGeometry } | { kind: "unknown" } | undefined {
|
|
396
|
+
const fact = overlay?.facts.geometry;
|
|
397
|
+
if (fact === undefined) return undefined;
|
|
398
|
+
if (fact.value.kind === "unknown") return { kind: "unknown" };
|
|
399
|
+
if (fact.value.kind !== "stated") return undefined;
|
|
400
|
+
const value = fact.value.value;
|
|
401
|
+
return value === "shared_upfront" || value === "shared_truncating" || value === "separate"
|
|
402
|
+
? { kind: "stated", value }
|
|
403
|
+
: undefined;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/** Placeholder filtering is deliberately per output field, never a row-level rejection. */
|
|
407
|
+
export function placeholderFilteredOutput(
|
|
408
|
+
output: number | undefined,
|
|
409
|
+
context: number | undefined,
|
|
410
|
+
): number | undefined {
|
|
411
|
+
if (!isFinitePositive(output)) return undefined;
|
|
412
|
+
if (isFinitePositive(context) && output >= context) return undefined;
|
|
413
|
+
return output;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function mergePositive(
|
|
417
|
+
overlayValue: number | undefined,
|
|
418
|
+
providerValue: number | undefined,
|
|
419
|
+
): number | undefined {
|
|
420
|
+
return isFinitePositive(providerValue) ? providerValue : overlayValue;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function logGeometryClampOnce(key: string, message: string, log?: (message: string) => void): void {
|
|
424
|
+
if (geometryClampLogSeen.has(key)) return;
|
|
425
|
+
geometryClampLogSeen.add(key);
|
|
426
|
+
(log ?? ((entry) => sessionLog("global", `window-geometry: ${entry}`)))(message);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
export function deriveWindowGeometry(
|
|
430
|
+
providerID: string,
|
|
431
|
+
modelID: string,
|
|
432
|
+
catalogLimit: ModelLimit | undefined,
|
|
433
|
+
options: DeriveWindowGeometryOptions = {},
|
|
434
|
+
): WindowGeometryResult | undefined {
|
|
435
|
+
if (!catalogLimit && !options.providerLimit) return undefined;
|
|
436
|
+
const providerLimit = options.providerLimit;
|
|
437
|
+
const catalogContext = isFinitePositive(catalogLimit?.context)
|
|
438
|
+
? catalogLimit.context
|
|
439
|
+
: undefined;
|
|
440
|
+
const advertised = numericOverlayFact(options.overlay, "window.advertised");
|
|
441
|
+
const enforced = numericOverlayFact(options.overlay, "window.enforced");
|
|
442
|
+
let softContext = mergePositive(
|
|
443
|
+
enforced ?? advertised ?? catalogContext,
|
|
444
|
+
providerLimit?.context,
|
|
445
|
+
);
|
|
446
|
+
let hardContext = mergePositive(enforced ?? softContext, providerLimit?.context);
|
|
447
|
+
if (isFinitePositive(options.contextCap)) {
|
|
448
|
+
softContext = isFinitePositive(softContext)
|
|
449
|
+
? Math.min(softContext, options.contextCap)
|
|
450
|
+
: options.contextCap;
|
|
451
|
+
hardContext = isFinitePositive(hardContext)
|
|
452
|
+
? Math.min(hardContext, options.contextCap)
|
|
453
|
+
: options.contextCap;
|
|
454
|
+
}
|
|
455
|
+
const input = mergePositive(
|
|
456
|
+
isFinitePositive(catalogLimit?.input) ? catalogLimit.input : undefined,
|
|
457
|
+
providerLimit?.input,
|
|
458
|
+
);
|
|
459
|
+
if (!isFinitePositive(softContext) && !isFinitePositive(input)) return undefined;
|
|
460
|
+
|
|
461
|
+
const catalogOutput =
|
|
462
|
+
options.overlay === undefined && options.providerLimit === undefined
|
|
463
|
+
? isFinitePositive(catalogLimit?.output)
|
|
464
|
+
? catalogLimit.output
|
|
465
|
+
: undefined
|
|
466
|
+
: placeholderFilteredOutput(catalogLimit?.output, softContext);
|
|
467
|
+
const overlayOutput = placeholderFilteredOutput(
|
|
468
|
+
numericOverlayFact(options.overlay, "output.enforced") ??
|
|
469
|
+
numericOverlayFact(options.overlay, "output.default") ??
|
|
470
|
+
numericOverlayFact(options.overlay, "output.advertised"),
|
|
471
|
+
softContext,
|
|
472
|
+
);
|
|
473
|
+
const providerOutput = placeholderFilteredOutput(providerLimit?.output, softContext);
|
|
474
|
+
const output = providerOutput ?? overlayOutput ?? catalogOutput;
|
|
475
|
+
const geometryFact = overlayGeometry(options.overlay);
|
|
476
|
+
// Considered-unknown demotes to shared_upfront — the conservative geometry
|
|
477
|
+
// in both directions (largest soft reserve, lowest hard wall) — until a
|
|
478
|
+
// measurement settles the cell. Absence falls through to the static table.
|
|
479
|
+
const geometry =
|
|
480
|
+
geometryFact?.kind === "stated"
|
|
481
|
+
? geometryFact.value
|
|
482
|
+
: geometryFact?.kind === "unknown"
|
|
483
|
+
? "shared_upfront"
|
|
484
|
+
: (PROVIDER_GEOMETRY[providerID] ?? "shared_upfront");
|
|
485
|
+
const geometryOverride = geometryFact?.kind === "stated" ? geometryFact.value : undefined;
|
|
486
|
+
|
|
487
|
+
const preCarvedInput =
|
|
488
|
+
isFinitePositive(input) && (!isFinitePositive(softContext) || input < softContext);
|
|
489
|
+
const outputReserveOverride =
|
|
490
|
+
typeof options.outputReserveOverride === "number" &&
|
|
491
|
+
Number.isFinite(options.outputReserveOverride) &&
|
|
492
|
+
options.outputReserveOverride >= 0
|
|
493
|
+
? options.outputReserveOverride
|
|
494
|
+
: undefined;
|
|
495
|
+
let derivationWindow = softContext ?? input;
|
|
496
|
+
let usableSoft: number;
|
|
497
|
+
let softReserve = 0;
|
|
498
|
+
let reserveSource: WindowReserveSource = "none";
|
|
499
|
+
if (outputReserveOverride !== undefined) {
|
|
500
|
+
// An explicit user reserve owns the usable-window carve. When the
|
|
501
|
+
// provider also publishes a smaller input cap, use that cap as the
|
|
502
|
+
// window; treating the cap as final would silently ignore the config.
|
|
503
|
+
const reserveWindow = preCarvedInput ? input : (softContext ?? input);
|
|
504
|
+
if (!isFinitePositive(reserveWindow)) return undefined;
|
|
505
|
+
derivationWindow = reserveWindow;
|
|
506
|
+
softReserve = outputReserveOverride;
|
|
507
|
+
reserveSource = "output_config";
|
|
508
|
+
const floor = Math.max(MIN_PLAUSIBLE_CONTEXT_LIMIT, reserveWindow * 0.5);
|
|
509
|
+
const flooredReserve = Math.min(softReserve, Math.max(0, reserveWindow - floor));
|
|
510
|
+
if (flooredReserve < softReserve) {
|
|
511
|
+
logGeometryClampOnce(
|
|
512
|
+
`soft-floor|${providerID}/${modelID}|${softReserve}|${flooredReserve}`,
|
|
513
|
+
`output reserve clamped by the half-window floor for ${providerID}/${modelID}: reserve ${softReserve} → ${flooredReserve}`,
|
|
514
|
+
options.log,
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
softReserve = flooredReserve;
|
|
518
|
+
usableSoft = Math.floor(reserveWindow - softReserve);
|
|
519
|
+
} else if (preCarvedInput) {
|
|
520
|
+
usableSoft = input;
|
|
521
|
+
if (isFinitePositive(softContext)) {
|
|
522
|
+
softReserve = Math.max(0, softContext - input);
|
|
523
|
+
reserveSource = "output_catalog";
|
|
524
|
+
}
|
|
525
|
+
} else if (isFinitePositive(softContext)) {
|
|
526
|
+
if (
|
|
527
|
+
geometry === "separate" &&
|
|
528
|
+
(options.overlay === undefined ||
|
|
529
|
+
options.harness === "pi" ||
|
|
530
|
+
geometryOverride !== undefined)
|
|
531
|
+
) {
|
|
532
|
+
softReserve = 0;
|
|
533
|
+
reserveSource = "none";
|
|
534
|
+
} else {
|
|
535
|
+
softReserve = output ?? 0;
|
|
536
|
+
reserveSource = output === undefined ? "none" : "output_catalog";
|
|
537
|
+
const cap = softContext * OUTPUT_RESERVE_CAP_RATIO;
|
|
538
|
+
softReserve = Math.min(
|
|
539
|
+
softReserve,
|
|
540
|
+
options.harness === "pi" || options.overlay === undefined
|
|
541
|
+
? cap
|
|
542
|
+
: Math.min(cap, OPENCODE_OUTPUT_CAP),
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
const floor = Math.max(MIN_PLAUSIBLE_CONTEXT_LIMIT, softContext * 0.5);
|
|
546
|
+
const flooredReserve = Math.min(softReserve, Math.max(0, softContext - floor));
|
|
547
|
+
if (flooredReserve < softReserve) {
|
|
548
|
+
// A reserve large enough to hit the half-window floor means the
|
|
549
|
+
// catalog's context/output pair contradicts itself (93 live rows
|
|
550
|
+
// publish output > context — fusiform's negative-window detector).
|
|
551
|
+
// The floor keeps the window functional; the log keeps the
|
|
552
|
+
// degradation visible instead of silently halving the window.
|
|
553
|
+
logGeometryClampOnce(
|
|
554
|
+
`soft-floor|${providerID}/${modelID}|${softReserve}|${flooredReserve}`,
|
|
555
|
+
`output reserve clamped by the half-window floor for ${providerID}/${modelID}: reserve ${softReserve} → ${flooredReserve} (catalog context/output pair is contradictory)`,
|
|
556
|
+
options.log,
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
softReserve = flooredReserve;
|
|
560
|
+
usableSoft = Math.floor(softContext - softReserve);
|
|
561
|
+
} else {
|
|
562
|
+
usableSoft = input as number;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const hardWindow = hardContext ?? softContext ?? input;
|
|
566
|
+
if (!isFinitePositive(hardWindow)) return undefined;
|
|
567
|
+
let usableHard: number;
|
|
568
|
+
if (geometry === "separate") {
|
|
569
|
+
usableHard = hardWindow;
|
|
570
|
+
} else if (geometry === "shared_truncating") {
|
|
571
|
+
usableHard = hardWindow - PROMPT_WALL_MARGIN;
|
|
572
|
+
} else if (options.harness === "pi" && providerID !== "openai-codex") {
|
|
573
|
+
usableHard = hardWindow - PI_OUTPUT_FLOOR;
|
|
574
|
+
} else if (options.harness === "pi") {
|
|
575
|
+
usableHard = hardWindow - (output ?? OPENCODE_OUTPUT_CAP);
|
|
576
|
+
} else {
|
|
577
|
+
const requestedOutput = Math.min(output ?? OPENCODE_OUTPUT_CAP, OPENCODE_OUTPUT_CAP);
|
|
578
|
+
usableHard = hardWindow - requestedOutput;
|
|
579
|
+
}
|
|
580
|
+
usableHard = Math.max(MIN_PLAUSIBLE_CONTEXT_LIMIT, Math.floor(usableHard));
|
|
581
|
+
if (usableHard < usableSoft) {
|
|
582
|
+
logGeometryClampOnce(
|
|
583
|
+
`${providerID}/${modelID}|${usableSoft}|${usableHard}`,
|
|
584
|
+
`usable hard limit clamped for ${providerID}/${modelID}: ${usableHard} → ${usableSoft} (overlay/provider inversion)`,
|
|
585
|
+
options.log,
|
|
586
|
+
);
|
|
587
|
+
usableHard = usableSoft;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
const resolvedWindow = derivationWindow ?? usableSoft;
|
|
591
|
+
return {
|
|
592
|
+
usableSoft,
|
|
593
|
+
usableHard,
|
|
594
|
+
geometry,
|
|
595
|
+
derivation: {
|
|
596
|
+
window: Math.floor(resolvedWindow),
|
|
597
|
+
reserve: Math.floor(Math.max(0, resolvedWindow - usableSoft)),
|
|
598
|
+
reserveSource,
|
|
599
|
+
geometry,
|
|
600
|
+
},
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export function formatWindowDerivationLine(
|
|
605
|
+
inputTokens: number,
|
|
606
|
+
result: WindowGeometryResult,
|
|
607
|
+
): string {
|
|
608
|
+
const percentage = result.usableSoft > 0 ? (inputTokens / result.usableSoft) * 100 : 0;
|
|
609
|
+
const reserveLabel =
|
|
610
|
+
result.derivation.reserveSource === "wall_margin"
|
|
611
|
+
? "wall margin"
|
|
612
|
+
: result.derivation.reserveSource === "none"
|
|
613
|
+
? "reserve"
|
|
614
|
+
: "output reserve";
|
|
615
|
+
return `Context: ${formatCompactTokens(inputTokens)} / ${formatCompactTokens(result.usableSoft)} usable (${percentage.toFixed(1)}%) — window ${formatCompactTokens(result.derivation.window)} − ${formatCompactTokens(result.derivation.reserve)} ${reserveLabel} [${result.geometry}]`;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
export function formatCompactTokens(value: number): string {
|
|
619
|
+
if (Math.abs(value) >= 1_000_000) {
|
|
620
|
+
return `${(value / 1_000_000).toFixed(1).replace(/\.0$/, "")}m`;
|
|
621
|
+
}
|
|
622
|
+
if (Math.abs(value) >= 1_000) {
|
|
623
|
+
return `${(value / 1_000).toFixed(1).replace(/\.0$/, "")}k`;
|
|
624
|
+
}
|
|
625
|
+
return Math.round(value).toLocaleString();
|
|
626
|
+
}
|
|
@@ -204,6 +204,11 @@ export async function loadStatusDetail(
|
|
|
204
204
|
compressionBudget: null,
|
|
205
205
|
compressionUsage: null,
|
|
206
206
|
toastDurationMs: 5000,
|
|
207
|
+
loggerDiagnostics: {
|
|
208
|
+
swallowedWriteCount: 0,
|
|
209
|
+
lastErrorMessage: null,
|
|
210
|
+
lastErrorTime: null,
|
|
211
|
+
},
|
|
207
212
|
storage_versions: {
|
|
208
213
|
context_db_schema_version: null,
|
|
209
214
|
plugin_supported_version: 0,
|