@cortexkit/opencode-magic-context 0.37.0 → 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/{derive-budgets-0f8xpyw2.js → derive-budgets-da4yg3tz.js} +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/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/reclaim-protection.d.ts +13 -0
- package/dist/features/magic-context/reclaim-protection.d.ts.map +1 -0
- package/dist/features/magic-context/storage-db.d.ts +6 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +7 -6
- package/dist/features/magic-context/storage-meta-persisted.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/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/execute-status.d.ts +2 -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/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/rust-mode-transform.d.ts +4 -2
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +10 -8
- 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 +3 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-q0t189ay.js → index-9zhhvr4w.js} +27 -35
- package/dist/{index-0ze9p983.js → index-mmvhrqqb.js} +1428 -191
- package/dist/index.js +604 -763
- 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-c3ff16k7.js → recomp-orchestrator-jsde4ygw.js} +2 -2
- package/dist/shared/models-dev-cache.d.ts +2 -0
- package/dist/shared/models-dev-cache.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +15 -0
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/rpc-utils.d.ts +9 -0
- 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 +3 -2
- package/dist/shared/window-geometry.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/config/schema/magic-context.ts +2 -2
- package/src/shared/models-dev-cache.test.ts +25 -0
- package/src/shared/models-dev-cache.ts +5 -4
- package/src/shared/rpc-server.ts +1 -0
- package/src/shared/rpc-types.ts +16 -0
- package/src/shared/rpc-utils.test.ts +25 -0
- package/src/shared/rpc-utils.ts +80 -0
- package/src/shared/tail-hygiene-status.ts +57 -0
- package/src/shared/window-geometry.test.ts +34 -1
- package/src/shared/window-geometry.ts +37 -40
- package/src/tui/index.tsx +11 -1
- package/src/tui/slots/sidebar-content.tsx +17 -5
- package/src/tui-compiled/index.tsx +311 -289
- package/src/tui-compiled/slots/sidebar-content.tsx +316 -287
|
@@ -2,7 +2,7 @@ import { afterEach, describe, expect, test } from "bun:test";
|
|
|
2
2
|
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
import { resolveLimit } from "./models-dev-cache";
|
|
5
|
+
import { resolveLimit, resolveOutputReserve } from "./models-dev-cache";
|
|
6
6
|
import {
|
|
7
7
|
deriveWindowGeometry,
|
|
8
8
|
formatWindowDerivationLine,
|
|
@@ -240,6 +240,39 @@ describe("window geometry", () => {
|
|
|
240
240
|
expect(result?.usableSoft).toBe(1_016_576);
|
|
241
241
|
});
|
|
242
242
|
|
|
243
|
+
test("output_reserve forms override a pre-carved input and overlay output facts", () => {
|
|
244
|
+
const data = overlay("openai-codex", "gpt-5.6-sol", {
|
|
245
|
+
"output.enforced": fact({ kind: "stated", value: 68_000 }),
|
|
246
|
+
});
|
|
247
|
+
const cases = [
|
|
248
|
+
16_384,
|
|
249
|
+
{ default: 16_384 },
|
|
250
|
+
{ default: 32_000, "openai-codex/gpt-5.6-sol": 16_384 },
|
|
251
|
+
] as const;
|
|
252
|
+
|
|
253
|
+
for (const reserveConfig of cases) {
|
|
254
|
+
const result = deriveWindowGeometry(
|
|
255
|
+
"openai-codex",
|
|
256
|
+
"gpt-5.6-sol",
|
|
257
|
+
{ context: 400_000, input: 272_000, output: 128_000 },
|
|
258
|
+
{
|
|
259
|
+
overlay: resolveWindowOverlayFacts("openai-codex", "gpt-5.6-sol", data),
|
|
260
|
+
outputReserveOverride: resolveOutputReserve(
|
|
261
|
+
"openai-codex",
|
|
262
|
+
"gpt-5.6-sol",
|
|
263
|
+
reserveConfig,
|
|
264
|
+
),
|
|
265
|
+
},
|
|
266
|
+
);
|
|
267
|
+
expect(result?.usableSoft).toBe(272_000 - 16_384);
|
|
268
|
+
expect(result?.derivation).toMatchObject({
|
|
269
|
+
window: 272_000,
|
|
270
|
+
reserve: 16_384,
|
|
271
|
+
reserveSource: "output_config",
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
243
276
|
test("provider hook wins over overlay, while overlay beats catalog", () => {
|
|
244
277
|
const data = overlay("provider", "model", {
|
|
245
278
|
"window.enforced": fact({ kind: "stated", value: 300_000 }),
|
|
@@ -3,7 +3,7 @@ import { join } from "node:path";
|
|
|
3
3
|
import { getDataDir } from "./data-path";
|
|
4
4
|
import { modelRefLookupOrder } from "./harness-provider-map";
|
|
5
5
|
import { sessionLog } from "./logger";
|
|
6
|
-
import type { ModelLimit
|
|
6
|
+
import type { ModelLimit } from "./models-dev-cache";
|
|
7
7
|
|
|
8
8
|
export const WINDOW_OVERLAY_SCHEMA = "fusiform-window-overlay/v1";
|
|
9
9
|
export const PROMPT_WALL_MARGIN = 4_096;
|
|
@@ -88,7 +88,8 @@ export interface DeriveWindowGeometryOptions {
|
|
|
88
88
|
overlay?: ResolvedWindowOverlayFacts;
|
|
89
89
|
/** A provider/auth hook has higher precedence than the overlay, field by field. */
|
|
90
90
|
providerLimit?: ModelLimit;
|
|
91
|
-
|
|
91
|
+
/** Resolved user override; higher precedence than catalog, overlay, and geometry defaults. */
|
|
92
|
+
outputReserveOverride?: number;
|
|
92
93
|
harness?: "opencode" | "pi";
|
|
93
94
|
/** Detected overflow remains the final downward cap regardless of other sources. */
|
|
94
95
|
contextCap?: number;
|
|
@@ -139,32 +140,6 @@ function isFinitePositive(value: unknown): value is number {
|
|
|
139
140
|
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
140
141
|
}
|
|
141
142
|
|
|
142
|
-
function modelKeyLookupOrder(providerID: string, modelID: string): string[] {
|
|
143
|
-
const candidates = [...modelRefLookupOrder(`${providerID}/${modelID}`), modelID];
|
|
144
|
-
const colon = modelID.lastIndexOf(":");
|
|
145
|
-
if (colon > 0) {
|
|
146
|
-
const bareModel = modelID.slice(0, colon);
|
|
147
|
-
candidates.push(...modelRefLookupOrder(`${providerID}/${bareModel}`), bareModel);
|
|
148
|
-
}
|
|
149
|
-
return [...new Set(candidates)];
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function configuredOutputReserve(
|
|
153
|
-
config: OutputReserveConfig | undefined,
|
|
154
|
-
providerID: string,
|
|
155
|
-
modelID: string,
|
|
156
|
-
): number | undefined {
|
|
157
|
-
if (typeof config === "number") {
|
|
158
|
-
return Number.isFinite(config) && config >= 0 ? config : undefined;
|
|
159
|
-
}
|
|
160
|
-
if (!config) return undefined;
|
|
161
|
-
for (const candidate of modelKeyLookupOrder(providerID, modelID)) {
|
|
162
|
-
const value = config[candidate];
|
|
163
|
-
if (typeof value === "number" && Number.isFinite(value) && value >= 0) return value;
|
|
164
|
-
}
|
|
165
|
-
return Number.isFinite(config.default) && config.default >= 0 ? config.default : undefined;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
143
|
/** Convert the ratified tagged numeric union into the conservative scalar used by derivation. */
|
|
169
144
|
export function scalarizeFact(value: WindowOverlayFactValue): number | undefined {
|
|
170
145
|
if (value.kind === "stated") return isFinitePositive(value.value) ? value.value : undefined;
|
|
@@ -509,25 +484,46 @@ export function deriveWindowGeometry(
|
|
|
509
484
|
: (PROVIDER_GEOMETRY[providerID] ?? "shared_upfront");
|
|
510
485
|
const geometryOverride = geometryFact?.kind === "stated" ? geometryFact.value : undefined;
|
|
511
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;
|
|
512
496
|
let usableSoft: number;
|
|
513
497
|
let softReserve = 0;
|
|
514
498
|
let reserveSource: WindowReserveSource = "none";
|
|
515
|
-
if (
|
|
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) {
|
|
516
520
|
usableSoft = input;
|
|
517
521
|
if (isFinitePositive(softContext)) {
|
|
518
522
|
softReserve = Math.max(0, softContext - input);
|
|
519
523
|
reserveSource = "output_catalog";
|
|
520
524
|
}
|
|
521
525
|
} else if (isFinitePositive(softContext)) {
|
|
522
|
-
|
|
523
|
-
options.reserveConfig,
|
|
524
|
-
providerID,
|
|
525
|
-
modelID,
|
|
526
|
-
);
|
|
527
|
-
if (configuredReserve !== undefined) {
|
|
528
|
-
softReserve = configuredReserve;
|
|
529
|
-
reserveSource = "output_config";
|
|
530
|
-
} else if (
|
|
526
|
+
if (
|
|
531
527
|
geometry === "separate" &&
|
|
532
528
|
(options.overlay === undefined ||
|
|
533
529
|
options.harness === "pi" ||
|
|
@@ -591,13 +587,14 @@ export function deriveWindowGeometry(
|
|
|
591
587
|
usableHard = usableSoft;
|
|
592
588
|
}
|
|
593
589
|
|
|
590
|
+
const resolvedWindow = derivationWindow ?? usableSoft;
|
|
594
591
|
return {
|
|
595
592
|
usableSoft,
|
|
596
593
|
usableHard,
|
|
597
594
|
geometry,
|
|
598
595
|
derivation: {
|
|
599
|
-
window: Math.floor(
|
|
600
|
-
reserve: Math.floor(Math.max(0,
|
|
596
|
+
window: Math.floor(resolvedWindow),
|
|
597
|
+
reserve: Math.floor(Math.max(0, resolvedWindow - usableSoft)),
|
|
601
598
|
reserveSource,
|
|
602
599
|
geometry,
|
|
603
600
|
},
|
package/src/tui/index.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import packageJson from "../../package.json"
|
|
|
11
11
|
import { closeRpc, dismissUpgradeReminder, getAnnouncement, getCompartmentCount, getRpcGeneration, initRpcClient, loadEmbedDetail, loadStatusDetail, loadToastDurationMs, markAnnounced, requestRecomp, requestUpgrade, type EmbedDetail, type StatusDetail } from "./data/context-db"
|
|
12
12
|
import { startNotificationSocket, stopNotificationSocket, type SocketNotification } from "./data/notification-socket"
|
|
13
13
|
import { formatThresholdPercent } from "../shared/format-threshold"
|
|
14
|
+
import { formatTailHygiene } from "../shared/tail-hygiene-status"
|
|
14
15
|
import { formatWindowDerivationLine } from "../shared/window-geometry"
|
|
15
16
|
import { compactionOffSidebarRows, nativeCompactionContextLabel } from "./compaction-off"
|
|
16
17
|
import { isCompactionEnabled } from "../config/agent-disable"
|
|
@@ -202,7 +203,7 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
|
|
|
202
203
|
segs.push({ label: "User Profile", tokens: d.profileTokens, color: COLORS.profile })
|
|
203
204
|
|
|
204
205
|
if (d.conversationTokens > 0)
|
|
205
|
-
segs.push({ label: "Conversation", tokens: d.conversationTokens, color: COLORS.conversation })
|
|
206
|
+
segs.push({ label: "Conversation*", tokens: d.conversationTokens, color: COLORS.conversation })
|
|
206
207
|
if (d.toolCallTokens > 0)
|
|
207
208
|
segs.push({ label: "Tool Calls", tokens: d.toolCallTokens, color: COLORS.toolCalls })
|
|
208
209
|
if (d.toolDefinitionTokens > 0)
|
|
@@ -271,6 +272,15 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
|
|
|
271
272
|
</box>
|
|
272
273
|
)
|
|
273
274
|
})}
|
|
275
|
+
<text fg={t().textMuted}>* Conversation includes Reasoning; hygiene excludes it</text>
|
|
276
|
+
{s().tailHygiene !== undefined && (
|
|
277
|
+
<R
|
|
278
|
+
t={t()}
|
|
279
|
+
l="Hygiene"
|
|
280
|
+
v={formatTailHygiene(s().tailHygiene!)}
|
|
281
|
+
fg={s().tailHygiene!.evaluable ? t().accent : t().warning}
|
|
282
|
+
/>
|
|
283
|
+
)}
|
|
274
284
|
</box>
|
|
275
285
|
|
|
276
286
|
{/* Recomp / session-upgrade live progress (full width, only while
|
|
@@ -5,6 +5,7 @@ import packageJson from "../../../package.json"
|
|
|
5
5
|
import { badgeTextColor } from '../badge-contrast';
|
|
6
6
|
import { loadSidebarSnapshot, type SidebarSnapshot } from "../data/context-db"
|
|
7
7
|
import { formatThresholdPercent } from "../../shared/format-threshold"
|
|
8
|
+
import { formatTailHygiene } from "../../shared/tail-hygiene-status"
|
|
8
9
|
import { compactionOffSidebarRows, nativeCompactionContextLabel } from "../compaction-off"
|
|
9
10
|
import {
|
|
10
11
|
computeEffectiveOrder,
|
|
@@ -239,7 +240,7 @@ const TokenBreakdown = (props: {
|
|
|
239
240
|
key: "conv",
|
|
240
241
|
tokens: s.conversationTokens,
|
|
241
242
|
color: COLORS.conversation,
|
|
242
|
-
label: "Conversation",
|
|
243
|
+
label: "Conversation*",
|
|
243
244
|
})
|
|
244
245
|
|
|
245
246
|
// Tool Calls = tool_use/tool_result/tool/tool-invocation parts in messages
|
|
@@ -320,6 +321,7 @@ const TokenBreakdown = (props: {
|
|
|
320
321
|
</box>
|
|
321
322
|
)
|
|
322
323
|
})}
|
|
324
|
+
<text fg={props.theme.textMuted}>* includes Reasoning; hygiene excludes it</text>
|
|
323
325
|
</box>
|
|
324
326
|
)}
|
|
325
327
|
</box>
|
|
@@ -787,16 +789,26 @@ const SidebarContent = (props: {
|
|
|
787
789
|
<b>{s()!.usagePercentage.toFixed(1)}%</b> / {formatThresholdPercent(s()!.executeThreshold)}%{s()!.executeThresholdClamped ? "*" : ""}
|
|
788
790
|
</text>
|
|
789
791
|
)}
|
|
790
|
-
{/* Right: absolute token usage
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
much headroom remains beyond compaction). */}
|
|
792
|
+
{/* Right: absolute token usage against the usable
|
|
793
|
+
scheduler window — the same denominator as the
|
|
794
|
+
percentage and nudge/trigger scheduling. */}
|
|
794
795
|
<text fg={contextSummaryColor()}>
|
|
795
796
|
{compactTokens(s()!.inputTokens)} / {compactTokens(s()!.contextLimit)}
|
|
796
797
|
</text>
|
|
797
798
|
</box>
|
|
798
799
|
)}
|
|
799
800
|
<TokenBreakdown theme={props.theme} snapshot={s()!} collapsed={collapsed()} />
|
|
801
|
+
{!collapsed() && (
|
|
802
|
+
<text fg={props.theme.textMuted}>Conversation includes reasoning estimates; hygiene excludes reasoning.</text>
|
|
803
|
+
)}
|
|
804
|
+
{s()!.tailHygiene !== undefined && (
|
|
805
|
+
<StatRow
|
|
806
|
+
theme={props.theme}
|
|
807
|
+
label="Hygiene"
|
|
808
|
+
value={formatTailHygiene(s()!.tailHygiene!)}
|
|
809
|
+
warning={!s()!.tailHygiene!.evaluable}
|
|
810
|
+
/>
|
|
811
|
+
)}
|
|
800
812
|
</box>
|
|
801
813
|
)}
|
|
802
814
|
|