claude-token-saver 3.4.0 → 3.4.2
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/package.json +1 -1
- package/src/model-rules.js +5 -1
- package/src/session-records.js +19 -1
package/package.json
CHANGED
package/src/model-rules.js
CHANGED
|
@@ -35,6 +35,10 @@ import { homedir } from 'node:os';
|
|
|
35
35
|
// Post-promotion delegated-category error rate above this flags the rule
|
|
36
36
|
// for review (rule-health). Calibrated against local T0 avg error incidence.
|
|
37
37
|
export const HEALTH_ERR_RATE = 0.2;
|
|
38
|
+
// Below this many shape-eligible episodes in the window the error rate is
|
|
39
|
+
// noise (1 error in 4 episodes = 25% — instant flag), so the review flag is
|
|
40
|
+
// withheld until the sample is large enough to mean something.
|
|
41
|
+
export const HEALTH_MIN_SAMPLE = 10;
|
|
38
42
|
|
|
39
43
|
function stateDir() {
|
|
40
44
|
if (process.platform === 'win32') {
|
|
@@ -214,7 +218,7 @@ export function refreshModelRules(episodeStats, { now } = {}) {
|
|
|
214
218
|
r.count = s.count;
|
|
215
219
|
r.errRate = s.epCount > 0 ? s.errCount / s.epCount : 0;
|
|
216
220
|
r.lastSeen = now || r.lastSeen;
|
|
217
|
-
r.status = r.errRate > HEALTH_ERR_RATE ? 'review' : 'active';
|
|
221
|
+
r.status = r.errRate > HEALTH_ERR_RATE && s.epCount >= HEALTH_MIN_SAMPLE ? 'review' : 'active';
|
|
218
222
|
changed = true;
|
|
219
223
|
}
|
|
220
224
|
if (changed) {
|
package/src/session-records.js
CHANGED
|
@@ -32,6 +32,24 @@ function contentText(content) {
|
|
|
32
32
|
const MUTATING_TOOLS = new Set(['Edit', 'Write', 'NotebookEdit', 'Bash']);
|
|
33
33
|
const DELEGATION_TOOLS = new Set(['Task', 'Agent']);
|
|
34
34
|
|
|
35
|
+
// Permission rejections and harness policy denials arrive as is_error
|
|
36
|
+
// tool_results, but they encode the user's choice / the permission system's
|
|
37
|
+
// policy, not task difficulty — counting them poisons the rule-health error
|
|
38
|
+
// rate. Measured on a 14-day window: 6 user rejections + ~29 auto-mode
|
|
39
|
+
// classifier denials out of 142 is_error results (~25% of the numerator).
|
|
40
|
+
const REJECTION_RE = /doesn't want to proceed|tool use was rejected|doesn't want to take this action|denied by the claude code auto mode classifier|permission for this action was denied|requires approval/i;
|
|
41
|
+
|
|
42
|
+
function toolResultText(content) {
|
|
43
|
+
if (typeof content === 'string') return content;
|
|
44
|
+
if (!Array.isArray(content)) return '';
|
|
45
|
+
return content.map((b) => (b && typeof b.text === 'string' ? b.text : '')).join(' ');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function isRealToolError(block) {
|
|
49
|
+
return block && block.type === 'tool_result' && block.is_error &&
|
|
50
|
+
!REJECTION_RE.test(toolResultText(block.content));
|
|
51
|
+
}
|
|
52
|
+
|
|
35
53
|
export async function collectSessionRecords(filePath, { includeContent = true } = {}) {
|
|
36
54
|
const records = new Map();
|
|
37
55
|
let depth = 0;
|
|
@@ -62,7 +80,7 @@ export async function collectSessionRecords(filePath, { includeContent = true }
|
|
|
62
80
|
// follows the assistant call — attribute them to that call's record.
|
|
63
81
|
if (lastRecord && Array.isArray(msg.content)) {
|
|
64
82
|
for (const b of msg.content) {
|
|
65
|
-
if (b
|
|
83
|
+
if (isRealToolError(b)) lastRecord.toolErrors += 1;
|
|
66
84
|
}
|
|
67
85
|
}
|
|
68
86
|
continue;
|