token-optimizer-opencode 1.0.3
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 +127 -0
- package/dist/activity/intel.d.ts +10 -0
- package/dist/activity/intel.d.ts.map +1 -0
- package/dist/activity/intel.js +26 -0
- package/dist/activity/intel.js.map +1 -0
- package/dist/activity/tracker.d.ts +12 -0
- package/dist/activity/tracker.d.ts.map +1 -0
- package/dist/activity/tracker.js +101 -0
- package/dist/activity/tracker.js.map +1 -0
- package/dist/compaction/checkpoint.d.ts +17 -0
- package/dist/compaction/checkpoint.d.ts.map +1 -0
- package/dist/compaction/checkpoint.js +82 -0
- package/dist/compaction/checkpoint.js.map +1 -0
- package/dist/compaction/dynamic-instructions.d.ts +3 -0
- package/dist/compaction/dynamic-instructions.d.ts.map +1 -0
- package/dist/compaction/dynamic-instructions.js +54 -0
- package/dist/compaction/dynamic-instructions.js.map +1 -0
- package/dist/continuity/matcher.d.ts +14 -0
- package/dist/continuity/matcher.d.ts.map +1 -0
- package/dist/continuity/matcher.js +57 -0
- package/dist/continuity/matcher.js.map +1 -0
- package/dist/continuity/restore.d.ts +4 -0
- package/dist/continuity/restore.d.ts.map +1 -0
- package/dist/continuity/restore.js +53 -0
- package/dist/continuity/restore.js.map +1 -0
- package/dist/dashboard/generator.d.ts +8 -0
- package/dist/dashboard/generator.d.ts.map +1 -0
- package/dist/dashboard/generator.js +282 -0
- package/dist/dashboard/generator.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +447 -0
- package/dist/index.js.map +1 -0
- package/dist/nudges/loop-detection.d.ts +6 -0
- package/dist/nudges/loop-detection.d.ts.map +1 -0
- package/dist/nudges/loop-detection.js +56 -0
- package/dist/nudges/loop-detection.js.map +1 -0
- package/dist/nudges/quality-nudge.d.ts +7 -0
- package/dist/nudges/quality-nudge.d.ts.map +1 -0
- package/dist/nudges/quality-nudge.js +28 -0
- package/dist/nudges/quality-nudge.js.map +1 -0
- package/dist/nudges/tool-call-warn.d.ts +7 -0
- package/dist/nudges/tool-call-warn.d.ts.map +1 -0
- package/dist/nudges/tool-call-warn.js +20 -0
- package/dist/nudges/tool-call-warn.js.map +1 -0
- package/dist/plugin.d.ts +9 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +5 -0
- package/dist/plugin.js.map +1 -0
- package/dist/quality/curves.d.ts +5 -0
- package/dist/quality/curves.d.ts.map +1 -0
- package/dist/quality/curves.js +102 -0
- package/dist/quality/curves.js.map +1 -0
- package/dist/quality/scoring.d.ts +39 -0
- package/dist/quality/scoring.d.ts.map +1 -0
- package/dist/quality/scoring.js +239 -0
- package/dist/quality/scoring.js.map +1 -0
- package/dist/quality/signals.d.ts +23 -0
- package/dist/quality/signals.d.ts.map +1 -0
- package/dist/quality/signals.js +100 -0
- package/dist/quality/signals.js.map +1 -0
- package/dist/storage/session-store.d.ts +73 -0
- package/dist/storage/session-store.d.ts.map +1 -0
- package/dist/storage/session-store.js +259 -0
- package/dist/storage/session-store.js.map +1 -0
- package/dist/storage/trends.d.ts +28 -0
- package/dist/storage/trends.d.ts.map +1 -0
- package/dist/storage/trends.js +125 -0
- package/dist/storage/trends.js.map +1 -0
- package/dist/tools/dashboard.d.ts +3 -0
- package/dist/tools/dashboard.d.ts.map +1 -0
- package/dist/tools/dashboard.js +45 -0
- package/dist/tools/dashboard.js.map +1 -0
- package/dist/tools/token-status.d.ts +9 -0
- package/dist/tools/token-status.d.ts.map +1 -0
- package/dist/tools/token-status.js +51 -0
- package/dist/tools/token-status.js.map +1 -0
- package/dist/util/context-window.d.ts +2 -0
- package/dist/util/context-window.d.ts.map +1 -0
- package/dist/util/context-window.js +83 -0
- package/dist/util/context-window.js.map +1 -0
- package/dist/util/env.d.ts +23 -0
- package/dist/util/env.d.ts.map +1 -0
- package/dist/util/env.js +63 -0
- package/dist/util/env.js.map +1 -0
- package/dist/util/grade.d.ts +4 -0
- package/dist/util/grade.d.ts.map +1 -0
- package/dist/util/grade.js +32 -0
- package/dist/util/grade.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,EAAE,6BAA6B,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,CAAC;;;;;AAChC,wBAA2E"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,CAAC,MAAM,EAAE,GAAG,0BAA0B,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE,oBAAoB,EAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curves.d.ts","sourceRoot":"","sources":["../../src/quality/curves.ts"],"names":[],"mappings":"AAsGA,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,GACrB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAYxC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Anthropic default (fill fraction 0-1)
|
|
2
|
+
const ANTHROPIC_MRCR = [
|
|
3
|
+
[0.0, 98],
|
|
4
|
+
[0.10, 96],
|
|
5
|
+
[0.25, 93],
|
|
6
|
+
[0.50, 88],
|
|
7
|
+
[0.60, 84],
|
|
8
|
+
[0.70, 80],
|
|
9
|
+
[0.80, 78],
|
|
10
|
+
[0.90, 77],
|
|
11
|
+
[1.0, 76],
|
|
12
|
+
];
|
|
13
|
+
// OpenAI GPT-5.5 (absolute tokens)
|
|
14
|
+
const OPENAI_GPT55_MRCR = [
|
|
15
|
+
[0, 98],
|
|
16
|
+
[8_000, 98],
|
|
17
|
+
[16_000, 96],
|
|
18
|
+
[32_000, 94],
|
|
19
|
+
[64_000, 90],
|
|
20
|
+
[128_000, 86],
|
|
21
|
+
[256_000, 84],
|
|
22
|
+
[512_000, 81],
|
|
23
|
+
[1_000_000, 74],
|
|
24
|
+
];
|
|
25
|
+
// OpenAI GPT-5 family fallback (absolute tokens)
|
|
26
|
+
const OPENAI_GPT5_MRCR = [
|
|
27
|
+
[0, 98],
|
|
28
|
+
[32_000, 94],
|
|
29
|
+
[64_000, 90],
|
|
30
|
+
[128_000, 85],
|
|
31
|
+
[256_000, 80],
|
|
32
|
+
[512_000, 72],
|
|
33
|
+
[1_000_000, 64],
|
|
34
|
+
];
|
|
35
|
+
// GPT-4.1 family (1M window, extrapolated from GPT-5 shape)
|
|
36
|
+
const OPENAI_GPT41_MRCR = [
|
|
37
|
+
[0, 98],
|
|
38
|
+
[32_000, 95],
|
|
39
|
+
[64_000, 92],
|
|
40
|
+
[128_000, 88],
|
|
41
|
+
[256_000, 82],
|
|
42
|
+
[512_000, 74],
|
|
43
|
+
[1_000_000, 66],
|
|
44
|
+
];
|
|
45
|
+
// Gemini (steepest degradation among frontier models)
|
|
46
|
+
const GEMINI_MRCR = [
|
|
47
|
+
[0, 98],
|
|
48
|
+
[8_000, 97],
|
|
49
|
+
[32_000, 95],
|
|
50
|
+
[64_000, 92],
|
|
51
|
+
[128_000, 85],
|
|
52
|
+
[256_000, 72],
|
|
53
|
+
[512_000, 50],
|
|
54
|
+
[1_000_000, 26],
|
|
55
|
+
[2_000_000, 15],
|
|
56
|
+
];
|
|
57
|
+
function interpolate(curve, x) {
|
|
58
|
+
if (curve.length === 0)
|
|
59
|
+
return 76;
|
|
60
|
+
if (x <= curve[0][0])
|
|
61
|
+
return curve[0][1];
|
|
62
|
+
if (x >= curve[curve.length - 1][0])
|
|
63
|
+
return curve[curve.length - 1][1];
|
|
64
|
+
for (let i = 1; i < curve.length; i++) {
|
|
65
|
+
if (x <= curve[i][0]) {
|
|
66
|
+
const [x0, y0] = curve[i - 1];
|
|
67
|
+
const [x1, y1] = curve[i];
|
|
68
|
+
const t = (x - x0) / (x1 - x0);
|
|
69
|
+
return y0 + t * (y1 - y0);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return curve[curve.length - 1][1];
|
|
73
|
+
}
|
|
74
|
+
function selectCurve(model) {
|
|
75
|
+
const m = (model ?? "").toLowerCase();
|
|
76
|
+
if (m.includes("gemini")) {
|
|
77
|
+
return { family: "google-gemini", curve: GEMINI_MRCR, mode: "absolute_tokens" };
|
|
78
|
+
}
|
|
79
|
+
if (m.includes("gpt-5.5") || m.includes("gpt-5.4")) {
|
|
80
|
+
return { family: "openai-gpt-5.5", curve: OPENAI_GPT55_MRCR, mode: "absolute_tokens" };
|
|
81
|
+
}
|
|
82
|
+
if (m.includes("gpt-4.1")) {
|
|
83
|
+
return { family: "openai-gpt-4.1", curve: OPENAI_GPT41_MRCR, mode: "absolute_tokens" };
|
|
84
|
+
}
|
|
85
|
+
if (m.includes("gpt-5") || m.includes("gpt-4")) {
|
|
86
|
+
return { family: "openai-gpt-5", curve: OPENAI_GPT5_MRCR, mode: "absolute_tokens" };
|
|
87
|
+
}
|
|
88
|
+
return { family: "anthropic-default", curve: ANTHROPIC_MRCR, mode: "fill_fraction" };
|
|
89
|
+
}
|
|
90
|
+
export function estimateQualityFromFill(fillPct, model, contextWindow) {
|
|
91
|
+
const fill = Math.max(0, Math.min(1, fillPct));
|
|
92
|
+
const { family, curve, mode } = selectCurve(model);
|
|
93
|
+
let quality;
|
|
94
|
+
if (mode === "absolute_tokens" && contextWindow) {
|
|
95
|
+
quality = interpolate(curve, fill * contextWindow);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
quality = interpolate(curve, fill);
|
|
99
|
+
}
|
|
100
|
+
return { quality: Math.round(quality), curveName: family };
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=curves.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curves.js","sourceRoot":"","sources":["../../src/quality/curves.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { SessionStore } from "../storage/session-store.js";
|
|
2
|
+
import type { TokenOptimizerConfig } from "../util/env.js";
|
|
3
|
+
export interface QualityResult {
|
|
4
|
+
score: number;
|
|
5
|
+
grade: string;
|
|
6
|
+
resourceHealth: number;
|
|
7
|
+
resourceHealthGrade: string;
|
|
8
|
+
sessionEfficiency: number;
|
|
9
|
+
sessionEfficiencyGrade: string;
|
|
10
|
+
signals: Record<string, number>;
|
|
11
|
+
breakdown: Record<string, SignalBreakdown>;
|
|
12
|
+
fillWarning: FillWarning | null;
|
|
13
|
+
toolCallWarning: ToolCallWarning | null;
|
|
14
|
+
regimeChange: RegimeChange | null;
|
|
15
|
+
toolCalls: number;
|
|
16
|
+
fillPct: number;
|
|
17
|
+
}
|
|
18
|
+
export interface SignalBreakdown {
|
|
19
|
+
score: number;
|
|
20
|
+
detail: string;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
export interface FillWarning {
|
|
24
|
+
level: string;
|
|
25
|
+
fillPct: number;
|
|
26
|
+
message: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ToolCallWarning {
|
|
29
|
+
level: string;
|
|
30
|
+
toolCalls: number;
|
|
31
|
+
message: string;
|
|
32
|
+
}
|
|
33
|
+
export interface RegimeChange {
|
|
34
|
+
fillPct: number;
|
|
35
|
+
message: string;
|
|
36
|
+
}
|
|
37
|
+
export declare function computeQualityScore(store: SessionStore, fillPct: number, model: string | undefined, contextWindow: number, config: TokenOptimizerConfig): QualityResult;
|
|
38
|
+
export declare function enforceMonotonicity(newResult: QualityResult, cachedResourceHealth: number | null, cachedCompactions: number, currentCompactions: number): QualityResult;
|
|
39
|
+
//# sourceMappingURL=scoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.d.ts","sourceRoot":"","sources":["../../src/quality/scoring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAShE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAoB3D,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC3C,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AASD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,oBAAoB,GAC3B,aAAa,CAuMf;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,aAAa,EACxB,oBAAoB,EAAE,MAAM,GAAG,IAAI,EACnC,iBAAiB,EAAE,MAAM,EACzB,kBAAkB,EAAE,MAAM,GACzB,aAAa,CAcf"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { scoreToGrade, degradationBand } from "../util/grade.js";
|
|
2
|
+
import { estimateQualityFromFill } from "./curves.js";
|
|
3
|
+
import { detectStaleReads, detectBloatedResults, computeDecisionDensity, computeAgentEfficiency, } from "./signals.js";
|
|
4
|
+
const RESOURCE_HEALTH_WEIGHTS = {
|
|
5
|
+
context_fill_degradation: 0.5,
|
|
6
|
+
compaction_depth: 0.3,
|
|
7
|
+
absolute_waste_tokens: 0.2,
|
|
8
|
+
};
|
|
9
|
+
const SESSION_EFFICIENCY_WEIGHTS = {
|
|
10
|
+
stale_reads: 0.3,
|
|
11
|
+
bloated_results: 0.3,
|
|
12
|
+
decision_density: 0.2,
|
|
13
|
+
agent_efficiency: 0.2,
|
|
14
|
+
};
|
|
15
|
+
const FILL_WARN_THRESHOLDS = [
|
|
16
|
+
[0.85, "CRITICAL", "85% context fill, compact now"],
|
|
17
|
+
[0.75, "WARNING", "75% context fill, consider compacting"],
|
|
18
|
+
];
|
|
19
|
+
function scaledToolCallThresholds(contextWindow, config) {
|
|
20
|
+
const scale = Math.max(1.0, (contextWindow / 200_000) ** 1.3);
|
|
21
|
+
const warn = Math.max(1, config.toolCallWarnThreshold ?? Math.floor(25 * scale));
|
|
22
|
+
const critical = Math.max(1, config.toolCallCriticalThreshold ?? Math.floor(40 * scale));
|
|
23
|
+
return { warn, critical };
|
|
24
|
+
}
|
|
25
|
+
export function computeQualityScore(store, fillPct, model, contextWindow, config) {
|
|
26
|
+
const window = config.qualityWindow;
|
|
27
|
+
// Signal 0: Context fill degradation (MRCR-based)
|
|
28
|
+
const { quality: fillQuality, curveName } = estimateQualityFromFill(fillPct, model, contextWindow);
|
|
29
|
+
const fillScore = Math.max(0, Math.min(100, ((fillQuality - 76) / (98 - 76)) * 100));
|
|
30
|
+
// Signal 1: Stale reads (rolling window)
|
|
31
|
+
const staleData = detectStaleReads(store, window);
|
|
32
|
+
const recentReads = store.getRecentReads(window);
|
|
33
|
+
let staleScore;
|
|
34
|
+
if (recentReads.length > 0) {
|
|
35
|
+
const staleRatio = Math.min(1, staleData.count / recentReads.length);
|
|
36
|
+
staleScore = Math.max(0, Math.min(100, 100 - staleRatio * 100));
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
staleScore = 100;
|
|
40
|
+
}
|
|
41
|
+
// Signal 2: Bloated results (rolling window)
|
|
42
|
+
const bloatedData = detectBloatedResults(store, window);
|
|
43
|
+
const recentResults = store.getRecentToolResults(window);
|
|
44
|
+
let bloatedScore;
|
|
45
|
+
if (recentResults.length > 0) {
|
|
46
|
+
const bloatedRatio = Math.min(1, bloatedData.count / recentResults.length);
|
|
47
|
+
bloatedScore = Math.max(0, Math.min(100, 100 - bloatedRatio * 300));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
bloatedScore = 100;
|
|
51
|
+
}
|
|
52
|
+
// Signal 3: Compaction depth
|
|
53
|
+
const compactions = store.getCompactionCount();
|
|
54
|
+
let compactionScore;
|
|
55
|
+
if (compactions === 0)
|
|
56
|
+
compactionScore = 100;
|
|
57
|
+
else if (compactions === 1)
|
|
58
|
+
compactionScore = 75;
|
|
59
|
+
else if (compactions === 2)
|
|
60
|
+
compactionScore = 45;
|
|
61
|
+
else
|
|
62
|
+
compactionScore = 20;
|
|
63
|
+
// Signal 4: Decision density (rolling window)
|
|
64
|
+
const densityData = computeDecisionDensity(store, window);
|
|
65
|
+
const densityScore = densityData.total > 0 ? Math.min(100, densityData.ratio * 200) : 50;
|
|
66
|
+
// Signal 5: Agent efficiency (rolling window)
|
|
67
|
+
const agentData = computeAgentEfficiency(store, window);
|
|
68
|
+
const agentScore = agentData.dispatches > 0 ? Math.min(100, agentData.efficiency * 150) : 80;
|
|
69
|
+
// Signal 6: Absolute waste tokens
|
|
70
|
+
const totalWaste = staleData.estimatedWasteTokens + bloatedData.estimatedWasteTokens;
|
|
71
|
+
const wasteFraction = contextWindow > 0 ? totalWaste / contextWindow : 0;
|
|
72
|
+
const wasteScore = Math.max(0, Math.min(100, 100 - wasteFraction * 1000));
|
|
73
|
+
const signals = {
|
|
74
|
+
context_fill_degradation: round1(fillScore),
|
|
75
|
+
stale_reads: round1(staleScore),
|
|
76
|
+
bloated_results: round1(bloatedScore),
|
|
77
|
+
compaction_depth: round1(compactionScore),
|
|
78
|
+
decision_density: round1(densityScore),
|
|
79
|
+
agent_efficiency: round1(agentScore),
|
|
80
|
+
absolute_waste_tokens: round1(wasteScore),
|
|
81
|
+
};
|
|
82
|
+
// Dual composite
|
|
83
|
+
const resourceHealth = signals.context_fill_degradation * RESOURCE_HEALTH_WEIGHTS.context_fill_degradation +
|
|
84
|
+
signals.compaction_depth * RESOURCE_HEALTH_WEIGHTS.compaction_depth +
|
|
85
|
+
signals.absolute_waste_tokens * RESOURCE_HEALTH_WEIGHTS.absolute_waste_tokens;
|
|
86
|
+
const sessionEfficiency = signals.stale_reads * SESSION_EFFICIENCY_WEIGHTS.stale_reads +
|
|
87
|
+
signals.bloated_results * SESSION_EFFICIENCY_WEIGHTS.bloated_results +
|
|
88
|
+
signals.decision_density * SESSION_EFFICIENCY_WEIGHTS.decision_density +
|
|
89
|
+
signals.agent_efficiency * SESSION_EFFICIENCY_WEIGHTS.agent_efficiency;
|
|
90
|
+
// Compaction loss estimate
|
|
91
|
+
let compactionLossPct = 0;
|
|
92
|
+
if (compactions === 1)
|
|
93
|
+
compactionLossPct = 65;
|
|
94
|
+
else if (compactions === 2)
|
|
95
|
+
compactionLossPct = 88;
|
|
96
|
+
else if (compactions >= 3)
|
|
97
|
+
compactionLossPct = 95;
|
|
98
|
+
const bandName = degradationBand(fillPct);
|
|
99
|
+
const breakdown = {
|
|
100
|
+
context_fill_degradation: {
|
|
101
|
+
score: signals.context_fill_degradation,
|
|
102
|
+
fillPct: round1(fillPct * 100),
|
|
103
|
+
qualityEstimate: fillQuality,
|
|
104
|
+
qualityCurve: curveName,
|
|
105
|
+
model: model ?? "unknown",
|
|
106
|
+
modelContextWindow: contextWindow,
|
|
107
|
+
band: bandName,
|
|
108
|
+
detail: `${Math.round(fillPct * 100)}% fill, ${bandName.toLowerCase()} (${curveName})`,
|
|
109
|
+
},
|
|
110
|
+
stale_reads: {
|
|
111
|
+
score: signals.stale_reads,
|
|
112
|
+
count: staleData.count,
|
|
113
|
+
windowReads: recentReads.length,
|
|
114
|
+
estimatedWasteTokens: staleData.estimatedWasteTokens,
|
|
115
|
+
detail: staleData.count > 0
|
|
116
|
+
? `${staleData.count} stale file reads (${recentReads.length} in window)`
|
|
117
|
+
: "No stale reads",
|
|
118
|
+
},
|
|
119
|
+
bloated_results: {
|
|
120
|
+
score: signals.bloated_results,
|
|
121
|
+
count: bloatedData.count,
|
|
122
|
+
windowResults: recentResults.length,
|
|
123
|
+
estimatedWasteTokens: bloatedData.estimatedWasteTokens,
|
|
124
|
+
detail: bloatedData.count > 0
|
|
125
|
+
? `${bloatedData.count} bloated results (${recentResults.length} in window)`
|
|
126
|
+
: "No bloated results",
|
|
127
|
+
},
|
|
128
|
+
compaction_depth: {
|
|
129
|
+
score: signals.compaction_depth,
|
|
130
|
+
compactions,
|
|
131
|
+
cumulativeLossPct: compactionLossPct,
|
|
132
|
+
detail: compactions > 0
|
|
133
|
+
? `${compactions} compaction(s) (~${compactionLossPct}% cumulative context loss)`
|
|
134
|
+
: "No compactions",
|
|
135
|
+
},
|
|
136
|
+
decision_density: {
|
|
137
|
+
score: signals.decision_density,
|
|
138
|
+
substantiveMessages: densityData.substantive,
|
|
139
|
+
windowMessages: densityData.total,
|
|
140
|
+
ratio: round2(densityData.ratio),
|
|
141
|
+
detail: densityData.total > 0
|
|
142
|
+
? `${Math.round(densityData.ratio * 100)}% substantive (${densityData.total} in window)`
|
|
143
|
+
: "No messages",
|
|
144
|
+
},
|
|
145
|
+
agent_efficiency: {
|
|
146
|
+
score: signals.agent_efficiency,
|
|
147
|
+
dispatchCount: agentData.dispatches,
|
|
148
|
+
detail: agentData.dispatches > 0
|
|
149
|
+
? `${agentData.dispatches} agent dispatches`
|
|
150
|
+
: "No agents used",
|
|
151
|
+
},
|
|
152
|
+
absolute_waste_tokens: {
|
|
153
|
+
score: signals.absolute_waste_tokens,
|
|
154
|
+
totalWasteTokens: totalWaste,
|
|
155
|
+
wasteFraction: round4(wasteFraction),
|
|
156
|
+
detail: totalWaste > 0
|
|
157
|
+
? `${totalWaste} waste tokens (${round1(wasteFraction * 100)}% of window)`
|
|
158
|
+
: "No measurable waste",
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
// Fill warnings (independent of composite)
|
|
162
|
+
let fillWarning = null;
|
|
163
|
+
for (const [threshold, level, message] of FILL_WARN_THRESHOLDS) {
|
|
164
|
+
if (fillPct >= threshold) {
|
|
165
|
+
fillWarning = { level, fillPct: round1(fillPct * 100), message };
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Tool call fatigue (gated on fill >= 50%)
|
|
170
|
+
const toolCalls = store.getToolCallCount();
|
|
171
|
+
let toolCallWarning = null;
|
|
172
|
+
if (fillPct >= 0.5) {
|
|
173
|
+
const { warn, critical } = scaledToolCallThresholds(contextWindow, config);
|
|
174
|
+
if (toolCalls >= critical) {
|
|
175
|
+
toolCallWarning = {
|
|
176
|
+
level: "CRITICAL",
|
|
177
|
+
toolCalls,
|
|
178
|
+
message: `${critical}+ tool calls, instruction adherence severely degraded`,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
else if (toolCalls >= warn) {
|
|
182
|
+
toolCallWarning = {
|
|
183
|
+
level: "WARNING",
|
|
184
|
+
toolCalls,
|
|
185
|
+
message: `${warn}+ tool calls, consider a fresh session`,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// 50% fill regime change
|
|
190
|
+
let regimeChange = null;
|
|
191
|
+
if (fillPct > 0.5) {
|
|
192
|
+
regimeChange = {
|
|
193
|
+
fillPct: round1(fillPct * 100),
|
|
194
|
+
message: "System prompt erosion accelerating, middle content at highest risk",
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
const rhRounded = round1(resourceHealth);
|
|
198
|
+
const seRounded = round1(sessionEfficiency);
|
|
199
|
+
return {
|
|
200
|
+
score: rhRounded,
|
|
201
|
+
grade: scoreToGrade(Math.round(resourceHealth)),
|
|
202
|
+
resourceHealth: rhRounded,
|
|
203
|
+
resourceHealthGrade: scoreToGrade(Math.round(resourceHealth)),
|
|
204
|
+
sessionEfficiency: seRounded,
|
|
205
|
+
sessionEfficiencyGrade: scoreToGrade(Math.round(sessionEfficiency)),
|
|
206
|
+
signals,
|
|
207
|
+
breakdown,
|
|
208
|
+
fillWarning,
|
|
209
|
+
toolCallWarning,
|
|
210
|
+
regimeChange,
|
|
211
|
+
toolCalls,
|
|
212
|
+
fillPct,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
export function enforceMonotonicity(newResult, cachedResourceHealth, cachedCompactions, currentCompactions) {
|
|
216
|
+
if (cachedResourceHealth === null)
|
|
217
|
+
return newResult;
|
|
218
|
+
if (currentCompactions > cachedCompactions)
|
|
219
|
+
return newResult;
|
|
220
|
+
if (newResult.resourceHealth > cachedResourceHealth) {
|
|
221
|
+
const clamped = { ...newResult };
|
|
222
|
+
clamped.resourceHealth = cachedResourceHealth;
|
|
223
|
+
clamped.score = cachedResourceHealth;
|
|
224
|
+
clamped.grade = scoreToGrade(Math.round(cachedResourceHealth));
|
|
225
|
+
clamped.resourceHealthGrade = clamped.grade;
|
|
226
|
+
return clamped;
|
|
227
|
+
}
|
|
228
|
+
return newResult;
|
|
229
|
+
}
|
|
230
|
+
function round1(n) {
|
|
231
|
+
return Math.round(n * 10) / 10;
|
|
232
|
+
}
|
|
233
|
+
function round2(n) {
|
|
234
|
+
return Math.round(n * 100) / 100;
|
|
235
|
+
}
|
|
236
|
+
function round4(n) {
|
|
237
|
+
return Math.round(n * 10000) / 10000;
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=scoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.js","sourceRoot":"","sources":["../../src/quality/scoring.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SessionStore } from "../storage/session-store.js";
|
|
2
|
+
export interface StaleReadResult {
|
|
3
|
+
count: number;
|
|
4
|
+
estimatedWasteTokens: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function detectStaleReads(store: SessionStore, limit: number): StaleReadResult;
|
|
7
|
+
export interface BloatedResultsResult {
|
|
8
|
+
count: number;
|
|
9
|
+
estimatedWasteTokens: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function detectBloatedResults(store: SessionStore, limit: number): BloatedResultsResult;
|
|
12
|
+
export interface DecisionDensityResult {
|
|
13
|
+
substantive: number;
|
|
14
|
+
total: number;
|
|
15
|
+
ratio: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function computeDecisionDensity(store: SessionStore, windowSize: number): DecisionDensityResult;
|
|
18
|
+
export interface AgentEfficiencyResult {
|
|
19
|
+
dispatches: number;
|
|
20
|
+
efficiency: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function computeAgentEfficiency(store: SessionStore, windowSize: number): AgentEfficiencyResult;
|
|
23
|
+
//# sourceMappingURL=signals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../../src/quality/signals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAMhE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAkDpF;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAiC7F;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,qBAAqB,CAMrG;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,qBAAqB,CAerG"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const STALE_READ_DISTANCE_THRESHOLD = 120;
|
|
2
|
+
const BLOAT_THRESHOLD_CHARS = 4000;
|
|
3
|
+
const CHARS_PER_TOKEN = 4;
|
|
4
|
+
export function detectStaleReads(store, limit) {
|
|
5
|
+
const reads = store.getRecentReads(limit);
|
|
6
|
+
const writes = store.getRecentWrites(limit * 2);
|
|
7
|
+
// The DB returns rows DESC by id. Group ascending by operation index so that
|
|
8
|
+
// `laterWrites[0]` below is the FIRST write after a read, not the last.
|
|
9
|
+
writes.sort((a, b) => a.idx - b.idx);
|
|
10
|
+
const writesByPath = new Map();
|
|
11
|
+
for (const w of writes) {
|
|
12
|
+
const arr = writesByPath.get(w.path) ?? [];
|
|
13
|
+
arr.push(w.idx);
|
|
14
|
+
writesByPath.set(w.path, arr);
|
|
15
|
+
}
|
|
16
|
+
const readsByPath = new Map();
|
|
17
|
+
for (const r of reads) {
|
|
18
|
+
const arr = readsByPath.get(r.path) ?? [];
|
|
19
|
+
arr.push(r.idx);
|
|
20
|
+
readsByPath.set(r.path, arr);
|
|
21
|
+
}
|
|
22
|
+
let staleCount = 0;
|
|
23
|
+
let wasteTokens = 0;
|
|
24
|
+
const AVG_READ_TOKENS = 2000;
|
|
25
|
+
for (const r of reads) {
|
|
26
|
+
const pathWrites = writesByPath.get(r.path);
|
|
27
|
+
if (!pathWrites || pathWrites.length === 0)
|
|
28
|
+
continue;
|
|
29
|
+
const priorWrites = pathWrites.filter((w) => w < r.idx);
|
|
30
|
+
if (priorWrites.length > 0) {
|
|
31
|
+
staleCount++;
|
|
32
|
+
wasteTokens += AVG_READ_TOKENS;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const laterWrites = pathWrites.filter((w) => w > r.idx);
|
|
36
|
+
if (laterWrites.length === 0)
|
|
37
|
+
continue;
|
|
38
|
+
const firstLaterWrite = laterWrites[0];
|
|
39
|
+
if (firstLaterWrite - r.idx > STALE_READ_DISTANCE_THRESHOLD) {
|
|
40
|
+
const laterReads = (readsByPath.get(r.path) ?? []).filter((lr) => lr > r.idx);
|
|
41
|
+
if (laterReads.length === 0) {
|
|
42
|
+
staleCount++;
|
|
43
|
+
wasteTokens += AVG_READ_TOKENS / 2;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { count: staleCount, estimatedWasteTokens: wasteTokens };
|
|
48
|
+
}
|
|
49
|
+
export function detectBloatedResults(store, limit) {
|
|
50
|
+
const results = store.getRecentToolResults(limit);
|
|
51
|
+
const messages = store.getRecentMessages(limit);
|
|
52
|
+
// Sort ascending by idx so the early-break on idx > r.idx + 10 works correctly
|
|
53
|
+
// (DB returns DESC by id, but we need ASC by operation index for lookahead).
|
|
54
|
+
// `results` order does not affect the per-result scan, but sort it too so the
|
|
55
|
+
// two arrays share one ordering invariant and future edits stay correct.
|
|
56
|
+
messages.sort((a, b) => a.idx - b.idx);
|
|
57
|
+
results.sort((a, b) => a.idx - b.idx);
|
|
58
|
+
let bloatedCount = 0;
|
|
59
|
+
let wasteTokens = 0;
|
|
60
|
+
for (const r of results) {
|
|
61
|
+
if (r.result_size < BLOAT_THRESHOLD_CHARS)
|
|
62
|
+
continue;
|
|
63
|
+
let wasReferenced = false;
|
|
64
|
+
for (const m of messages) {
|
|
65
|
+
if (m.idx > r.idx && m.role === "assistant" && m.is_substantive) {
|
|
66
|
+
wasReferenced = true;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
if (m.idx > r.idx + 10)
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
if (!wasReferenced) {
|
|
73
|
+
bloatedCount++;
|
|
74
|
+
wasteTokens += Math.floor(r.result_size / CHARS_PER_TOKEN);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return { count: bloatedCount, estimatedWasteTokens: wasteTokens };
|
|
78
|
+
}
|
|
79
|
+
export function computeDecisionDensity(store, windowSize) {
|
|
80
|
+
const messages = store.getRecentMessages(windowSize);
|
|
81
|
+
const substantive = messages.filter((m) => m.is_substantive).length;
|
|
82
|
+
const total = messages.length;
|
|
83
|
+
const ratio = total > 0 ? substantive / total : 0;
|
|
84
|
+
return { substantive, total, ratio };
|
|
85
|
+
}
|
|
86
|
+
export function computeAgentEfficiency(store, windowSize) {
|
|
87
|
+
const dispatches = store.getRecentAgentDispatches(windowSize);
|
|
88
|
+
if (dispatches.length === 0) {
|
|
89
|
+
return { dispatches: 0, efficiency: 0.8 };
|
|
90
|
+
}
|
|
91
|
+
const totalPrompt = dispatches.reduce((s, d) => s + d.prompt_size, 0);
|
|
92
|
+
const totalResult = dispatches.reduce((s, d) => s + d.result_size, 0);
|
|
93
|
+
if (totalPrompt <= 0) {
|
|
94
|
+
return { dispatches: dispatches.length, efficiency: 0.8 };
|
|
95
|
+
}
|
|
96
|
+
const total = totalPrompt + totalResult;
|
|
97
|
+
const efficiency = total > 0 ? totalResult / total : 0.5;
|
|
98
|
+
return { dispatches: dispatches.length, efficiency };
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=signals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../src/quality/signals.ts"],"names":[],"mappings":"AAEA,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAC1C,MAAM,qBAAqB,GAAG,IAAI,CAAC;AACnC,MAAM,eAAe,GAAG,CAAC,CAAC;AAO1B,MAAM,UAAU,gBAAgB,CAAC,KAAmB,EAAE,KAAa;IACjE,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,eAAe,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAEhD,6EAA6E;IAC7E,wEAAwE;IACxE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAErC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC3C,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChB,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAC;IAChD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1C,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChB,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,MAAM,eAAe,GAAG,IAAI,CAAC;IAE7B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAErD,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACxD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,UAAU,EAAE,CAAC;YACb,WAAW,IAAI,eAAe,CAAC;YAC/B,SAAS;QACX,CAAC;QAED,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACxD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACvC,MAAM,eAAe,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,eAAe,GAAG,CAAC,CAAC,GAAG,GAAG,6BAA6B,EAAE,CAAC;YAC5D,MAAM,UAAU,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YAC9E,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5B,UAAU,EAAE,CAAC;gBACb,WAAW,IAAI,eAAe,GAAG,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC;AAClE,CAAC;AAOD,MAAM,UAAU,oBAAoB,CAAC,KAAmB,EAAE,KAAa;IACrE,MAAM,OAAO,GAAG,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAEhD,+EAA+E;IAC/E,6EAA6E;IAC7E,8EAA8E;IAC9E,yEAAyE;IACzE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAEtC,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,WAAW,GAAG,qBAAqB;YAAE,SAAS;QAEpD,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;gBAChE,aAAa,GAAG,IAAI,CAAC;gBACrB,MAAM;YACR,CAAC;YACD,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE;gBAAE,MAAM;QAChC,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,YAAY,EAAE,CAAC;YACf,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,GAAG,eAAe,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC;AACpE,CAAC;AAQD,MAAM,UAAU,sBAAsB,CAAC,KAAmB,EAAE,UAAkB;IAC5E,MAAM,QAAQ,GAAG,KAAK,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACrD,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC;IACpE,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC9B,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACvC,CAAC;AAOD,MAAM,UAAU,sBAAsB,CAAC,KAAmB,EAAE,UAAkB;IAC5E,MAAM,UAAU,GAAG,KAAK,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACtE,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACtE,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;IAC5D,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,GAAG,WAAW,CAAC;IACxC,MAAM,UAAU,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAEzD,OAAO,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
|
+
/** Reduce a session id to the charset used for its DB filename and for echoing
|
|
3
|
+
* the id into checkpoint content. Single source of truth for all three callers. */
|
|
4
|
+
export declare function sanitizeSessionId(id: string): string;
|
|
5
|
+
export declare class SessionStore {
|
|
6
|
+
private db;
|
|
7
|
+
private dbPath;
|
|
8
|
+
constructor(dataDir: string, sessionId: string);
|
|
9
|
+
connect(): Database;
|
|
10
|
+
close(): void;
|
|
11
|
+
getMeta(key: string): string | undefined;
|
|
12
|
+
setMeta(key: string, value: string): void;
|
|
13
|
+
getQualityCache(): QualityCacheRow | null;
|
|
14
|
+
writeQualityCache(cache: Omit<QualityCacheRow, "id" | "updated_at">): void;
|
|
15
|
+
recordRead(idx: number, path: string): void;
|
|
16
|
+
recordWrite(idx: number, path: string): void;
|
|
17
|
+
recordToolResult(idx: number, toolName: string, resultSize: number, isFailure: boolean): void;
|
|
18
|
+
recordMessage(idx: number, role: string, textLength: number, isSubstantive: boolean): void;
|
|
19
|
+
recordAgentDispatch(idx: number, promptSize: number, resultSize: number): void;
|
|
20
|
+
getRecentReads(limit: number): Array<{
|
|
21
|
+
idx: number;
|
|
22
|
+
path: string;
|
|
23
|
+
}>;
|
|
24
|
+
getRecentWrites(limit: number): Array<{
|
|
25
|
+
idx: number;
|
|
26
|
+
path: string;
|
|
27
|
+
}>;
|
|
28
|
+
getRecentToolResults(limit: number): Array<{
|
|
29
|
+
idx: number;
|
|
30
|
+
tool_name: string;
|
|
31
|
+
result_size: number;
|
|
32
|
+
is_failure: number;
|
|
33
|
+
}>;
|
|
34
|
+
getRecentMessages(limit: number): Array<{
|
|
35
|
+
idx: number;
|
|
36
|
+
role: string;
|
|
37
|
+
text_length: number;
|
|
38
|
+
is_substantive: number;
|
|
39
|
+
}>;
|
|
40
|
+
getRecentAgentDispatches(limit: number): Array<{
|
|
41
|
+
idx: number;
|
|
42
|
+
prompt_size: number;
|
|
43
|
+
result_size: number;
|
|
44
|
+
}>;
|
|
45
|
+
private safeParseInt;
|
|
46
|
+
private atomicIncrement;
|
|
47
|
+
/**
|
|
48
|
+
* Cap each per-session signal table to its most recent `maxRows` rows.
|
|
49
|
+
* Without this, a long session that never compacts grows these tables
|
|
50
|
+
* unbounded. Table names are a fixed allowlist, never user input.
|
|
51
|
+
*/
|
|
52
|
+
capSignalTables(maxRows: number): void;
|
|
53
|
+
getCompactionCount(): number;
|
|
54
|
+
incrementCompaction(): number;
|
|
55
|
+
getToolCallCount(): number;
|
|
56
|
+
incrementToolCallCount(): number;
|
|
57
|
+
getOperationIndex(): number;
|
|
58
|
+
incrementOperationIndex(): number;
|
|
59
|
+
resetSignalAccumulators(): void;
|
|
60
|
+
}
|
|
61
|
+
export interface QualityCacheRow {
|
|
62
|
+
id: number;
|
|
63
|
+
resource_health: number | null;
|
|
64
|
+
session_efficiency: number | null;
|
|
65
|
+
fill_pct: number | null;
|
|
66
|
+
compactions: number;
|
|
67
|
+
tool_calls: number;
|
|
68
|
+
last_nudge_time: number;
|
|
69
|
+
nudge_count: number;
|
|
70
|
+
data: string | null;
|
|
71
|
+
updated_at: number;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=session-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/storage/session-store.ts"],"names":[],"mappings":"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"}
|