mirror of
https://github.com/mksglu/context-mode.git
synced 2026-10-02 04:14:38 +08:00
fix(stats): 'With context-mode' = retrieval-tool returns only, not sandbox work-output
Refines 6d667348. The earlier fold counted ALL tool_calls.bytes_returned into 'With context-mode', including ctx_execute/batch/file sandbox stdout — work-output the model would see regardless. That crushed the redirect-savings bar to a false ~43%. Now folds ONLY retrieval returns (ctx_search + ctx_fetch_and_index) = the bytes the model paid to ACCESS the kept-out content. Empirical on this session: avoided 2.5 MB vs retrieval 125 KB = 95% kept out (vs the absurd '1 B / 100%' bug and the wrong '43%'). TDD: 8.1b now seeds a work tool (excluded) + two retrieval tools (included).
This commit is contained in:
@@ -1275,13 +1275,14 @@ export function getRealBytesStats(opts: {
|
||||
if (snap?.bytes) snapshotBytes += Number(snap.bytes);
|
||||
} catch { /* old schema */ }
|
||||
try {
|
||||
// MCP tool returns (ctx_execute/ctx_search stdout, redirect stubs)
|
||||
// land in tool_calls.bytes_returned via incrementToolCall, NOT in
|
||||
// session_events.bytes_returned (which carries snapshot-replay only).
|
||||
// Folding them here is what the "With context-mode" bar measures;
|
||||
// without it a tool-heavy session rendered a false "1 B / 100%".
|
||||
// "With context-mode" = the bytes the model paid to ACCESS the
|
||||
// kept-out content: ctx_search (query the index) + ctx_fetch_and_index
|
||||
// (fetch + index a URL). Sandbox compute (ctx_execute/batch/file) is
|
||||
// work-output the model would see regardless — NOT redirect savings —
|
||||
// so it is excluded; folding it crushed the bar to a false ~43%.
|
||||
const tc = sdb.prepare(
|
||||
"SELECT COALESCE(SUM(bytes_returned), 0) AS bytes FROM tool_calls WHERE session_id = ?",
|
||||
`SELECT COALESCE(SUM(bytes_returned), 0) AS bytes FROM tool_calls
|
||||
WHERE session_id = ? AND tool IN ('ctx_search', 'ctx_fetch_and_index')`,
|
||||
).get(opts.sessionId) as { bytes: number } | undefined;
|
||||
if (tc?.bytes) bytesReturned += Number(tc.bytes);
|
||||
} catch { /* old schema: no tool_calls table */ }
|
||||
@@ -1324,7 +1325,8 @@ export function getRealBytesStats(opts: {
|
||||
FROM tool_calls
|
||||
WHERE session_id IN (
|
||||
SELECT session_id FROM session_meta WHERE project_dir = ?
|
||||
)`,
|
||||
)
|
||||
AND tool IN ('ctx_search', 'ctx_fetch_and_index')`,
|
||||
).get(opts.projectDir) as { bytes: number } | undefined;
|
||||
if (tc?.bytes) bytesReturned += Number(tc.bytes);
|
||||
} catch { /* old schema: no tool_calls table */ }
|
||||
@@ -1351,7 +1353,8 @@ export function getRealBytesStats(opts: {
|
||||
} catch { /* old schema */ }
|
||||
try {
|
||||
const tc = sdb.prepare(
|
||||
"SELECT COALESCE(SUM(bytes_returned), 0) AS bytes FROM tool_calls",
|
||||
`SELECT COALESCE(SUM(bytes_returned), 0) AS bytes FROM tool_calls
|
||||
WHERE tool IN ('ctx_search', 'ctx_fetch_and_index')`,
|
||||
).get() as { bytes: number } | undefined;
|
||||
if (tc?.bytes) bytesReturned += Number(tc.bytes);
|
||||
} catch { /* old schema: no tool_calls table */ }
|
||||
|
||||
@@ -130,12 +130,13 @@ describe("getRealBytesStats (Phase 8 renderer source-of-truth)", () => {
|
||||
expect(r.totalSavedTokens).toBeGreaterThan(9_000); // ≈ 9_500
|
||||
});
|
||||
|
||||
test("8.1b conversation tier: folds tool_calls.bytes_returned (MCP returns) into bytesReturned", () => {
|
||||
// Production reality: ctx_execute / ctx_search return bytes to context via
|
||||
// the tool_calls counter (incrementToolCall / persistToolCallCounter), NOT
|
||||
// session_events.bytes_returned. A session with real MCP returns but no
|
||||
// snapshot replay reported bytesReturned=0 before this fix, rendering the
|
||||
// Section 1 bar as "With context-mode: 1 B / 100% kept out" — false.
|
||||
test("8.1b conversation tier: 'With context-mode' folds ONLY retrieval tool returns, not sandbox work-output", () => {
|
||||
// "With context-mode" = the bytes the model paid to ACCESS kept-out content
|
||||
// (ctx_search / ctx_fetch_and_index), via the tool_calls counter — NOT
|
||||
// session_events.bytes_returned (snapshot-replay only, ~0). Sandbox compute
|
||||
// (ctx_execute) is work-output the model would see regardless, so it is
|
||||
// EXCLUDED. Before this fix bytesReturned was 0 ("1 B / 100%"); an earlier
|
||||
// over-broad fold counted ctx_execute too, crushing the bar to a false ~43%.
|
||||
const dir = mkSessionsDir();
|
||||
const sid = `sess-${randomUUID()}`;
|
||||
const dbPath = dbPathFor(dir, "cafebabecafebabe");
|
||||
@@ -144,13 +145,18 @@ describe("getRealBytesStats (Phase 8 renderer source-of-truth)", () => {
|
||||
sid,
|
||||
[{ type: "tool_use", category: "file", data: "src/app.ts", bytesAvoided: 90_000, bytesReturned: 0 }],
|
||||
undefined,
|
||||
[{ tool: "ctx_execute", bytesReturned: 8_000 }, { tool: "ctx_search", bytesReturned: 2_000 }],
|
||||
[
|
||||
{ tool: "ctx_execute", bytesReturned: 800_000 }, // work-output → EXCLUDED
|
||||
{ tool: "ctx_search", bytesReturned: 2_000 }, // retrieval → INCLUDED
|
||||
{ tool: "ctx_fetch_and_index", bytesReturned: 1_500 }, // retrieval → INCLUDED
|
||||
],
|
||||
);
|
||||
|
||||
const r = getRealBytesStats({ sessionId: sid, sessionsDir: dir });
|
||||
|
||||
// 8_000 + 2_000 from tool_calls — the bytes that actually entered context.
|
||||
expect(r.bytesReturned).toBe(10_000);
|
||||
// Only the two retrieval tools (2_000 + 1_500); the 800 KB ctx_execute
|
||||
// work-output is NOT redirect savings and must not enter "With context-mode".
|
||||
expect(r.bytesReturned).toBe(3_500);
|
||||
expect(r.bytesAvoided).toBe(90_000);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user