@gabrihhh/jarvis 2.6.0 → 2.6.1
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 +20 -1
- package/bin/jarvis.js +24 -1
- package/package.json +1 -1
- package/src/calculator.js +12 -0
- package/src/statusline.js +30 -6
- package/src/theme.js +1 -0
package/README.md
CHANGED
|
@@ -31,9 +31,13 @@ Reinicie o Claude Code após o setup.
|
|
|
31
31
|
| `jarvis --trigger prompt` | Hook de memória roda a cada prompt |
|
|
32
32
|
| `jarvis --trigger off` | Desativa o carregamento automático de memória |
|
|
33
33
|
| `jarvis --theme` | Mostra o tema atual da status bar |
|
|
34
|
-
| `jarvis --theme <name>:<#hex>` | Define a cor de um box (`context`, `trigger`, `memory`) |
|
|
34
|
+
| `jarvis --theme <name>:<#hex>` | Define a cor de um box (`context`, `trigger`, `memory`, `tokens`) |
|
|
35
35
|
| `jarvis --theme <name>:reset` | Reseta a cor de um box para o padrão |
|
|
36
36
|
| `jarvis --theme reset` | Reseta todas as cores para o padrão |
|
|
37
|
+
| `jarvis --token` | Mostra o modo de exibição de tokens atual |
|
|
38
|
+
| `jarvis --token on` | Ativa box com total de tokens do último turno (`◈`) |
|
|
39
|
+
| `jarvis --token complete` | Ativa box `◈` + linha de breakdown abaixo da status bar |
|
|
40
|
+
| `jarvis --token off` | Desativa exibição de tokens |
|
|
37
41
|
| `jarvis --line` | Saída de uma linha usada internamente pela status bar |
|
|
38
42
|
| `jarvis --help` | Lista todos os comandos |
|
|
39
43
|
|
|
@@ -79,3 +83,18 @@ Reinicie o Claude Code após o setup.
|
|
|
79
83
|
│ CONTEXT ████░░░░ 52% │
|
|
80
84
|
╰──────────────────────╯
|
|
81
85
|
```
|
|
86
|
+
|
|
87
|
+
**Status bar com `--token on`** (box com total de tokens do último turno):
|
|
88
|
+
```
|
|
89
|
+
╭──────────────────────╮╭──────────╮
|
|
90
|
+
│ CONTEXT ████░░░░ 52% ││ ◈ 50.0K │
|
|
91
|
+
╰──────────────────────╯╰──────────╯
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Status bar com `--token complete`** (box + breakdown detalhado):
|
|
95
|
+
```
|
|
96
|
+
╭──────────────────────╮╭──────────╮
|
|
97
|
+
│ CONTEXT ████░░░░ 52% ││ ◈ 50.0K │
|
|
98
|
+
╰──────────────────────╯╰──────────╯
|
|
99
|
+
INPUT 800 │ HISTORY 45.0K │ CACHE 1.2K │ RESPONSE 3.2K
|
|
100
|
+
```
|
package/bin/jarvis.js
CHANGED
|
@@ -78,9 +78,13 @@ if (args.includes('--help') || args.includes('-h')) {
|
|
|
78
78
|
jarvis --trigger prompt Hook runs on every prompt
|
|
79
79
|
jarvis --trigger off Disable automatic memory loading
|
|
80
80
|
jarvis --theme Show current statusline theme
|
|
81
|
-
jarvis --theme <name>:<hex> Set a box color (context, trigger, memory)
|
|
81
|
+
jarvis --theme <name>:<hex> Set a box color (context, trigger, memory, tokens)
|
|
82
82
|
jarvis --theme <name>:reset Reset a single box to default color
|
|
83
83
|
jarvis --theme reset Reset all colors to default
|
|
84
|
+
jarvis --token Show current token display mode
|
|
85
|
+
jarvis --token on Show total tokens box (◈)
|
|
86
|
+
jarvis --token complete Show token box + INPUT/HISTORY/CACHE/RESPONSE breakdown
|
|
87
|
+
jarvis --token off Disable token display
|
|
84
88
|
jarvis --help Show this help
|
|
85
89
|
|
|
86
90
|
Slash commands (inside Claude Code):
|
|
@@ -253,6 +257,25 @@ if (args.includes('--graph')) {
|
|
|
253
257
|
writeTheme(theme);
|
|
254
258
|
console.log(`\n ✓ ${name} set to ${chalk.hex(color).bold(color)}\n`);
|
|
255
259
|
process.exit(0);
|
|
260
|
+
} else if (args.includes('--token')) {
|
|
261
|
+
const value = args[args.indexOf('--token') + 1];
|
|
262
|
+
const validValues = ['on', 'off', 'complete'];
|
|
263
|
+
|
|
264
|
+
if (!value || !validValues.includes(value)) {
|
|
265
|
+
const cfg = loadMemoryConfig();
|
|
266
|
+
const current = cfg.tokenDisplay || 'off';
|
|
267
|
+
console.log(`\n Token display: ${current}\n`);
|
|
268
|
+
console.log(` Usage: jarvis --token <on|complete|off>\n`);
|
|
269
|
+
process.exit(0);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const cfg = loadMemoryConfig();
|
|
273
|
+
cfg.tokenDisplay = value === 'on' ? 'simple' : value;
|
|
274
|
+
saveMemoryConfig(cfg);
|
|
275
|
+
|
|
276
|
+
const labels = { simple: 'on (◈ total tokens)', off: 'off', complete: 'complete (breakdown)' };
|
|
277
|
+
console.log(`\n ✓ Token display set to: ${labels[cfg.tokenDisplay]}\n`);
|
|
278
|
+
process.exit(0);
|
|
256
279
|
} else if (args.includes('--query')) {
|
|
257
280
|
try {
|
|
258
281
|
const { queryByPath } = await import('../src/memory/query-by-path.js');
|
package/package.json
CHANGED
package/src/calculator.js
CHANGED
|
@@ -109,6 +109,18 @@ export function formatTokens(n) {
|
|
|
109
109
|
return `${n}`;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
export function getLastTurnTokens(entries) {
|
|
113
|
+
if (!entries.length) return null;
|
|
114
|
+
const last = entries[entries.length - 1];
|
|
115
|
+
return {
|
|
116
|
+
input: last.inputTokens,
|
|
117
|
+
history: last.cacheReadTokens,
|
|
118
|
+
cache: last.cacheWriteTokens,
|
|
119
|
+
response: last.outputTokens,
|
|
120
|
+
total: last.inputTokens + last.outputTokens + last.cacheReadTokens + last.cacheWriteTokens,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
112
124
|
export function formatCost(n) {
|
|
113
125
|
if (n >= 1) return `$${n.toFixed(2)}`;
|
|
114
126
|
if (n >= 0.01) return `$${n.toFixed(3)}`;
|
package/src/statusline.js
CHANGED
|
@@ -3,7 +3,7 @@ import { readFileSync, existsSync, unlinkSync } from 'fs';
|
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import { homedir, tmpdir } from 'os';
|
|
5
5
|
import { readAllUsage, getCurrentSessionFile, readCurrentSessionUsage } from './reader.js';
|
|
6
|
-
import { aggregateStats, aggregateSession } from './calculator.js';
|
|
6
|
+
import { aggregateStats, aggregateSession, getLastTurnTokens, formatTokens } from './calculator.js';
|
|
7
7
|
import { readTheme } from './theme.js';
|
|
8
8
|
|
|
9
9
|
const chalk = new Chalk({ level: 3 });
|
|
@@ -21,6 +21,13 @@ function readTriggerMode() {
|
|
|
21
21
|
} catch { return 'off'; }
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
function readTokenMode() {
|
|
25
|
+
try {
|
|
26
|
+
const cfg = JSON.parse(readFileSync(join(homedir(), '.claude-memory.json'), 'utf8'));
|
|
27
|
+
return cfg.tokenDisplay || 'off';
|
|
28
|
+
} catch { return 'off'; }
|
|
29
|
+
}
|
|
30
|
+
|
|
24
31
|
function buildBox(inner, color, width = inner.length) {
|
|
25
32
|
return [
|
|
26
33
|
chalk.hex(color).bold(`╭${'─'.repeat(width)}╮`),
|
|
@@ -54,6 +61,7 @@ function isMemoryLoaded(sessionId) {
|
|
|
54
61
|
|
|
55
62
|
export function renderLine() {
|
|
56
63
|
const mode = readTriggerMode();
|
|
64
|
+
const tokenMode = readTokenMode();
|
|
57
65
|
const theme = readTheme();
|
|
58
66
|
|
|
59
67
|
const sessionMeta = getCurrentSessionFile();
|
|
@@ -63,28 +71,44 @@ export function renderLine() {
|
|
|
63
71
|
|
|
64
72
|
const allEntries = readAllUsage();
|
|
65
73
|
|
|
66
|
-
const
|
|
74
|
+
const buildOutput = (contextBox, turnTokens) => {
|
|
67
75
|
const toJoin = [contextBox];
|
|
68
76
|
if (mode !== 'off') toJoin.push(buildBox(` TRIGGER ${mode.toUpperCase()} `, theme.trigger));
|
|
69
77
|
if (loadedBox) toJoin.push(loadedBox);
|
|
70
|
-
|
|
78
|
+
if (turnTokens) toJoin.push(buildBox(` ◈ ${formatTokens(turnTokens.total)} `, theme.tokens));
|
|
79
|
+
|
|
80
|
+
let out = joinBoxes(...toJoin);
|
|
81
|
+
|
|
82
|
+
if (tokenMode === 'complete' && turnTokens) {
|
|
83
|
+
const col = (s) => chalk.hex(theme.tokens).bold(s);
|
|
84
|
+
const parts = [
|
|
85
|
+
`INPUT ${formatTokens(turnTokens.input)}`,
|
|
86
|
+
`HISTORY ${formatTokens(turnTokens.history)}`,
|
|
87
|
+
`CACHE ${formatTokens(turnTokens.cache)}`,
|
|
88
|
+
`RESPONSE ${formatTokens(turnTokens.response)}`,
|
|
89
|
+
];
|
|
90
|
+
out += '\n' + parts.map(col).join(col(' │ '));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return out;
|
|
71
94
|
};
|
|
72
95
|
|
|
73
96
|
if (!allEntries.length) {
|
|
74
97
|
const contextBox = buildBox(` CONTEXT ${'░'.repeat(8)} 0% `, theme.context);
|
|
75
|
-
process.stdout.write(
|
|
98
|
+
process.stdout.write(buildOutput(contextBox, null));
|
|
76
99
|
return;
|
|
77
100
|
}
|
|
78
101
|
|
|
79
102
|
const sessionEntries = sessionId ? readCurrentSessionUsage(sessionId) : [];
|
|
80
103
|
const session = aggregateSession(sessionEntries);
|
|
104
|
+
const turnTokens = tokenMode !== 'off' ? getLastTurnTokens(sessionEntries) : null;
|
|
81
105
|
|
|
82
106
|
if (!session) {
|
|
83
107
|
const contextBox = buildBox(` CONTEXT ${'░'.repeat(8)} 0% `, theme.context);
|
|
84
|
-
process.stdout.write(
|
|
108
|
+
process.stdout.write(buildOutput(contextBox, turnTokens));
|
|
85
109
|
return;
|
|
86
110
|
}
|
|
87
111
|
|
|
88
112
|
const contextBox = buildBox(` CONTEXT ${bar(session.percent)} ${session.percent}% `, theme.context);
|
|
89
|
-
process.stdout.write(
|
|
113
|
+
process.stdout.write(buildOutput(contextBox, turnTokens));
|
|
90
114
|
}
|