claude-token-saver 3.8.1 → 3.8.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/README.en.md +5 -0
- package/README.md +5 -0
- package/package.json +1 -1
- package/src/brief.js +27 -11
package/README.en.md
CHANGED
|
@@ -263,6 +263,11 @@ Also update `statusLine.command` in `~/.claude/settings.json` to `claude-token-s
|
|
|
263
263
|
|
|
264
264
|
## Release notes
|
|
265
265
|
|
|
266
|
+
### v3.8.2 (2026-08-01)
|
|
267
|
+
- **Fixed: the context tier never came back down after compaction** — the tier was kept as a high-water mark, so a session that compacted at 80% stayed at tier 1 even though its context had just been emptied, and it refilled to the cap with no signal at all. The tier now follows the measurement down and warns again on the next climb.
|
|
268
|
+
- **Both windows are named** — with `autoCompactWindow` at 400k the briefing measured against 400k (80%) while Claude Code's own display measured against 1M (33%); two irreconcilable numbers for one session. The text now reads `자동 압축 창(400k)의 80% (… 화면의 1M 창 기준으로는 33%)`.
|
|
269
|
+
- **No "start a new session" advice when a compact window is set** — that threshold is exactly where compaction runs on its own, so the briefing suggests writing decisions and next steps to a file instead.
|
|
270
|
+
|
|
266
271
|
### v3.8.1 (2026-07-31)
|
|
267
272
|
- **Fixed: 1M sessions were judged against a 200k window** — the briefing inferred the window from the largest request seen so far, so a 1M session counted as 200k until it had already grown past 250k. At 160k of input it announced "past 80% of the 200k window" — really 16%. The window now comes from the configured model id, and when `autoCompactWindow` is set that is where the session actually turns over, so the percentage is measured against it (the text says `(autoCompactWindow 기준)`). The observed-size heuristic remains only as the fallback for an unreadable model id.
|
|
268
273
|
|
package/README.md
CHANGED
|
@@ -220,6 +220,11 @@ npm uninstall -g claude-cache-monitor && npm i -g claude-token-saver
|
|
|
220
220
|
|
|
221
221
|
## 릴리스 노트
|
|
222
222
|
|
|
223
|
+
### v3.8.2 (2026-08-01)
|
|
224
|
+
- **압축 뒤에도 경고 티어가 안 내려가던 문제 수정** — 컨텍스트 티어를 최고치로만 기억해서, 80%에서 자동 압축이 돌아 컨텍스트가 다시 비어도 티어가 1로 남았습니다. 그 세션은 창을 다시 꽉 채워도 아무 신호를 못 받았습니다. 이제 측정치가 내려가면 티어도 같이 내려가고, 다시 차오르면 정상적으로 경고합니다.
|
|
225
|
+
- **두 가지 창 표기 혼선 정리** — `autoCompactWindow`를 40만으로 잡으면 브리핑은 40만 기준(80%)인데 Claude Code 화면은 1M 기준(33%)이라, 같은 세션의 두 숫자가 서로 안 맞아 보였습니다. 이제 `자동 압축 창(400k)의 80%(… 화면의 1M 창 기준으로는 33%)`처럼 둘 다 적습니다.
|
|
226
|
+
- **압축 창이 설정돼 있으면 "새 세션 시작" 권고를 하지 않습니다** — 그 지점은 압축이 자동으로 처리하는 지점이라, 대신 결정·다음 할 일을 파일에 남기라고 안내합니다.
|
|
227
|
+
|
|
223
228
|
### v3.8.1 (2026-07-31)
|
|
224
229
|
- **1M 세션을 200k 창으로 오판하던 브리핑 버그 수정** — 세션 창을 "지금까지 본 가장 큰 요청"으로 추정해서, 1M 세션이라도 25만 토큰을 넘기 전까지는 200k로 취급했습니다. 그래서 입력 160k에서 "200k 창의 80%를 넘었습니다" 경고가 떴습니다(실제로는 16%). 이제 설정된 모델 ID로 창을 판정하고, `autoCompactWindow`가 잡혀 있으면 그 값이 실제로 세션이 넘어가는 지점이므로 그쪽을 기준으로 %를 계산합니다(문구에도 `(autoCompactWindow 기준)` 표기). 모델 ID를 못 읽는 경우에만 기존 관측치 추정으로 되돌아갑니다.
|
|
225
230
|
|
package/package.json
CHANGED
package/src/brief.js
CHANGED
|
@@ -85,18 +85,19 @@ function saveState(state, now) {
|
|
|
85
85
|
* is unreadable (env override, settings we do not resolve).
|
|
86
86
|
*/
|
|
87
87
|
export function ctxWindowFor(observedMax = 0, root = process.cwd()) {
|
|
88
|
-
let
|
|
88
|
+
let modelWindow = observedMax > WINDOW_1M_MIN_INPUT ? 1_000_000 : 200_000;
|
|
89
|
+
let window = modelWindow;
|
|
89
90
|
let compactCapped = false;
|
|
90
91
|
try {
|
|
91
92
|
const { model } = resolveModelId(root);
|
|
92
|
-
if (isOneMillionModel(model)) window = 1_000_000;
|
|
93
|
+
if (isOneMillionModel(model)) modelWindow = window = 1_000_000;
|
|
93
94
|
const cap = effectiveWindow(root).value;
|
|
94
95
|
if (cap !== null && cap < window) {
|
|
95
96
|
window = cap;
|
|
96
97
|
compactCapped = true;
|
|
97
98
|
}
|
|
98
99
|
} catch { /* settings unreadable — the observed-size fallback still holds */ }
|
|
99
|
-
return { window, compactCapped };
|
|
100
|
+
return { window, modelWindow, compactCapped };
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
/**
|
|
@@ -129,8 +130,8 @@ export function sessionCtx(transcriptPath, { root = process.cwd() } = {}) {
|
|
|
129
130
|
if (total > 0) { input = total; maxInput = Math.max(maxInput, total); }
|
|
130
131
|
}
|
|
131
132
|
if (input == null) return null;
|
|
132
|
-
const { window, compactCapped } = ctxWindowFor(maxInput, root);
|
|
133
|
-
return { input, window, compactCapped, pct: input / window };
|
|
133
|
+
const { window, modelWindow, compactCapped } = ctxWindowFor(maxInput, root);
|
|
134
|
+
return { input, window, modelWindow, compactCapped, pct: input / window };
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
function ctxTierOf(pct) {
|
|
@@ -175,15 +176,30 @@ export async function runBrief({ sessionId, transcriptPath, now = Date.now() })
|
|
|
175
176
|
const ctx = transcriptPath ? sessionCtx(transcriptPath) : null;
|
|
176
177
|
if (ctx) {
|
|
177
178
|
const tier = ctxTierOf(ctx.pct);
|
|
179
|
+
// The tier is not monotonic: auto-compaction drops the live context back to
|
|
180
|
+
// a fraction of the window, which starts a new fill cycle. Holding the old
|
|
181
|
+
// high-water tier meant a session that compacted at 80% was never warned
|
|
182
|
+
// again — it silently refilled to the cap with no signal at all.
|
|
183
|
+
if (tier < (s.ctxTier || 0)) s.ctxTier = tier;
|
|
178
184
|
if (tier > (s.ctxTier || 0)) {
|
|
179
|
-
// Name
|
|
180
|
-
//
|
|
181
|
-
//
|
|
185
|
+
// Name both denominators when they differ. Claude Code's own UI counts
|
|
186
|
+
// against the model window, so a bare "400k 창의 80%" reads as wrong to
|
|
187
|
+
// anyone looking at a statusline that says 32% of 1M — same session,
|
|
188
|
+
// two different windows, no way to reconcile them from the text alone.
|
|
182
189
|
const winLabel = ctx.window >= 1_000_000 ? '1M' : fmtK(ctx.window);
|
|
183
|
-
const
|
|
190
|
+
const modelPct = Math.round((ctx.input / ctx.modelWindow) * 100);
|
|
191
|
+
const modelLabel = ctx.modelWindow >= 1_000_000 ? '1M' : fmtK(ctx.modelWindow);
|
|
192
|
+
const capNote = ctx.compactCapped ? `, 화면의 ${modelLabel} 창 기준으로는 ${modelPct}%` : '';
|
|
193
|
+
// With autoCompactWindow set, crossing the threshold means compaction is
|
|
194
|
+
// about to run on its own. Telling the user to start a new session there
|
|
195
|
+
// would be advice for a problem the setting already handles.
|
|
184
196
|
items.push(tier === 2
|
|
185
|
-
?
|
|
186
|
-
|
|
197
|
+
? (ctx.compactCapped
|
|
198
|
+
? `이 세션의 컨텍스트가 자동 압축 창(${winLabel})의 95%를 넘었습니다(직전 요청 입력 ${fmtK(ctx.input)}${capNote}). 곧 자동 압축이 돌아 이전 대화가 요약으로 바뀝니다 — 지금 단계를 마무리하고 이어서 할 일은 파일에 적어두면 압축 뒤에도 안전합니다.`
|
|
199
|
+
: `이 세션의 컨텍스트가 ${winLabel} 창의 95%를 넘었습니다(직전 요청 입력 ${fmtK(ctx.input)}). 곧 자동 압축으로 맥락 손실이 생길 수 있으니, 진행 중인 작업을 일단락하고 새 세션을 시작하는 편이 좋습니다.`)
|
|
200
|
+
: (ctx.compactCapped
|
|
201
|
+
? `이 세션의 컨텍스트가 자동 압축 창(${winLabel})의 80%를 넘었습니다(직전 요청 입력 ${fmtK(ctx.input)}${capNote}). 설정해 둔 압축 지점이 가까워졌습니다 — 압축은 알아서 돌아가니 새 세션을 서두를 필요는 없고, 여기까지의 결정과 다음 할 일만 파일에 남겨두면 됩니다.`
|
|
202
|
+
: `이 세션의 컨텍스트가 ${winLabel} 창의 80%를 넘었습니다(직전 요청 입력 ${fmtK(ctx.input)}). 이후 요청은 비용이 커지는 구간입니다 — 작업이 일단락되면 새 세션 시작을 권합니다.`));
|
|
187
203
|
s.ctxTier = tier;
|
|
188
204
|
}
|
|
189
205
|
}
|