Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Euno5AmwoFEvBTdWH8C8S
65 lines
2.7 KiB
PowerShell
65 lines
2.7 KiB
PowerShell
# context_watch.ps1 - cat context ocupa sesiunea curenta Claude Code.
|
|
# Citeste ultimul "usage" din transcriptul JSONL al sesiunii (input + cache_read + cache_creation).
|
|
# Utilizare:
|
|
# - ca hook (PostToolUse): primeste pe stdin JSON-ul hook-ului, cu transcript_path;
|
|
# - manual: powershell -File context_watch.ps1 [-TranscriptPath <cale.jsonl>] [-Prag 250000]
|
|
# Iese cu 2 si scrie pe stderr cand contextul depaseste pragul (asa ajunge mesajul la agent).
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$TranscriptPath,
|
|
[int]$Prag = 250000,
|
|
[int]$PragMax = 275000,
|
|
[switch]$Intotdeauna,
|
|
[switch]$Stdout # UserPromptSubmit: mesajul se scrie pe stdout si se iese cu 0
|
|
)
|
|
|
|
if (-not $TranscriptPath) {
|
|
$stdin = [Console]::In.ReadToEnd()
|
|
if ($stdin) {
|
|
try { $TranscriptPath = (ConvertFrom-Json $stdin).transcript_path } catch { }
|
|
}
|
|
}
|
|
# la primul mesaj al unei sesiuni noi transcriptul inca nu e creat: fara fallback, ca sa nu raporteze alta sesiune
|
|
if ($TranscriptPath -and -not (Test-Path $TranscriptPath)) { exit 0 }
|
|
if (-not $TranscriptPath) {
|
|
$dir = Join-Path $env:USERPROFILE ".claude\projects\$((Get-Location).Path -replace '[:\\/]','-')"
|
|
if (Test-Path $dir) {
|
|
$f = Get-ChildItem "$dir\*.jsonl" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
|
if ($f) { $TranscriptPath = $f.FullName }
|
|
}
|
|
}
|
|
if (-not $TranscriptPath -or -not (Test-Path $TranscriptPath)) { exit 0 }
|
|
|
|
# doar coada fisierului - transcriptul poate avea zeci de MB
|
|
$fs = [IO.File]::Open($TranscriptPath, 'Open', 'Read', 'ReadWrite')
|
|
try {
|
|
$len = [Math]::Min(400KB, $fs.Length)
|
|
$fs.Seek(-$len, 'End') | Out-Null
|
|
$buf = New-Object byte[] $len
|
|
$fs.Read($buf, 0, $len) | Out-Null
|
|
} finally { $fs.Close() }
|
|
$coada = [Text.Encoding]::UTF8.GetString($buf)
|
|
|
|
$m = [regex]::Matches($coada, '"usage":\{.*?"output_tokens":\d+')
|
|
if ($m.Count -eq 0) { exit 0 }
|
|
$ultim = $m[$m.Count - 1].Value
|
|
$total = 0
|
|
foreach ($camp in @('input_tokens', 'cache_creation_input_tokens', 'cache_read_input_tokens')) {
|
|
if ($ultim -match ('"' + $camp + '":(\d+)')) { $total += [int]$Matches[1] }
|
|
}
|
|
$k = [Math]::Round($total / 1000)
|
|
|
|
$mesaj = ''
|
|
if ($total -ge $PragMax) {
|
|
$mesaj = "CONTEXT ${k}k - peste limita de $([Math]::Round($PragMax/1000))k (regula 9): scrie handoff-ul in docs\progres.md si preda sesiunea acum."
|
|
} elseif ($total -ge $Prag) {
|
|
$mesaj = "CONTEXT ${k}k - peste $([Math]::Round($Prag/1000))k (regula 9): actualizeaza docs\progres.md si pregateste predarea; deleaga la subagenti ce mai ai de citit/testat."
|
|
}
|
|
if ($mesaj) {
|
|
if ($Stdout) { Write-Output $mesaj; exit 0 }
|
|
[Console]::Error.WriteLine($mesaj)
|
|
exit 2
|
|
}
|
|
if ($Intotdeauna) { Write-Output "CONTEXT ${k}k" }
|
|
exit 0
|