mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-09 00:49:41 +02:00
fix: enable token tracking for both interactive and one-shot modes
- Add --output-format stream-json to runPrompt() for JSON output with token usage data - Add parseTokensFromStatusLine() to parse tokens from Claude's status line display in interactive mode (e.g., "123.4k tokens") - Token parsing supports numeric, k (thousands), and M (millions) suffixes - Estimates input/output split (60/40) for interactive mode since only total is displayed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -361,6 +361,9 @@ export class Session extends EventEmitter {
|
|||||||
this.emit('terminal', data);
|
this.emit('terminal', data);
|
||||||
this.emit('output', data);
|
this.emit('output', data);
|
||||||
|
|
||||||
|
// Parse token count from status line (e.g., "123.4k tokens" or "5234 tokens")
|
||||||
|
this.parseTokensFromStatusLine(data);
|
||||||
|
|
||||||
// Detect if Claude is working or at prompt
|
// Detect if Claude is working or at prompt
|
||||||
// The prompt line contains "❯" when waiting for input
|
// The prompt line contains "❯" when waiting for input
|
||||||
if (data.includes('❯') || data.includes('\u276f')) {
|
if (data.includes('❯') || data.includes('\u276f')) {
|
||||||
@@ -524,6 +527,7 @@ export class Session extends EventEmitter {
|
|||||||
this.ptyProcess = pty.spawn('claude', [
|
this.ptyProcess = pty.spawn('claude', [
|
||||||
'-p',
|
'-p',
|
||||||
'--dangerously-skip-permissions',
|
'--dangerously-skip-permissions',
|
||||||
|
'--output-format', 'stream-json',
|
||||||
prompt
|
prompt
|
||||||
], {
|
], {
|
||||||
name: 'xterm-256color',
|
name: 'xterm-256color',
|
||||||
@@ -661,6 +665,43 @@ export class Session extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse token count from Claude's status line in interactive mode
|
||||||
|
// Matches patterns like "123.4k tokens", "5234 tokens", "1.2M tokens"
|
||||||
|
private parseTokensFromStatusLine(data: string): void {
|
||||||
|
// Remove ANSI escape codes for cleaner parsing
|
||||||
|
const cleanData = data.replace(/\x1b\[[0-9;]*m/g, '');
|
||||||
|
|
||||||
|
// Match patterns: "123.4k tokens", "5234 tokens", "1.2M tokens"
|
||||||
|
// The status line typically shows total tokens like "1.2k tokens" near the prompt
|
||||||
|
const tokenMatch = cleanData.match(/(\d+(?:\.\d+)?)\s*([kKmM])?\s*tokens/);
|
||||||
|
|
||||||
|
if (tokenMatch) {
|
||||||
|
let tokenCount = parseFloat(tokenMatch[1]);
|
||||||
|
const suffix = tokenMatch[2]?.toLowerCase();
|
||||||
|
|
||||||
|
// Convert k/M suffix to actual number
|
||||||
|
if (suffix === 'k') {
|
||||||
|
tokenCount *= 1000;
|
||||||
|
} else if (suffix === 'm') {
|
||||||
|
tokenCount *= 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only update if the new count is higher (tokens only increase within a session)
|
||||||
|
// We use total tokens as an estimate - Claude shows combined input+output
|
||||||
|
const currentTotal = this._totalInputTokens + this._totalOutputTokens;
|
||||||
|
if (tokenCount > currentTotal) {
|
||||||
|
// Estimate: split roughly 60% input, 40% output (common ratio)
|
||||||
|
// This is an approximation since interactive mode doesn't give us the breakdown
|
||||||
|
const delta = tokenCount - currentTotal;
|
||||||
|
this._totalInputTokens += Math.round(delta * 0.6);
|
||||||
|
this._totalOutputTokens += Math.round(delta * 0.4);
|
||||||
|
|
||||||
|
// Check if we should auto-clear
|
||||||
|
this.checkAutoClear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we should auto-clear based on token threshold
|
// Check if we should auto-clear based on token threshold
|
||||||
private checkAutoClear(): void {
|
private checkAutoClear(): void {
|
||||||
if (!this._autoClearEnabled || this._isClearing) return;
|
if (!this._autoClearEnabled || this._isClearing) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user