@nightlab-agent/subagent-spend 0.8.2 → 0.8.3
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +7 -0
- package/hooks/cap.ts +59 -0
- package/package.json +2 -1
- package/subagent_spend.py +1 -1
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"name": "subagent-spend",
|
|
9
9
|
"source": "./",
|
|
10
10
|
"description": "A spend cap for interactive sessions, and per-subagent tokens, rate-limit windows, context fill, cost, steps, tool calls and tool errors of a Claude Code session, in a notice under the prompt, local files and panes (the usage pane not yet seen on a screen).",
|
|
11
|
-
"version": "0.8.
|
|
11
|
+
"version": "0.8.3",
|
|
12
12
|
"category": "productivity"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "subagent-spend",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "A spend cap for interactive sessions, and per-subagent tokens, rate-limit windows, context fill, cost, steps, tool calls and tool errors of a Claude Code session, in a notice under the prompt, local files and panes (the usage pane not yet seen on a screen).",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Nightlab"
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
The form is Keep a Changelog; versions follow SemVer.
|
|
4
4
|
|
|
5
|
+
## 0.8.3 - 2026-11-03
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- The npm package left out hooks/cap.ts, which hooks/register.tsx imports, so an install from npm failed to load
|
|
9
|
+
from 0.8.0 on. The marketplace install was not affected. The checklist now fails when a packed hook imports a
|
|
10
|
+
file the package leaves out.
|
|
11
|
+
|
|
5
12
|
## 0.8.2 - 2026-11-03
|
|
6
13
|
|
|
7
14
|
### Changed
|
package/hooks/cap.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// The spend cap (option `capUsd`, off at 0): what the session may cost, by Claude Code's own
|
|
2
|
+
// estimate (`session.measure`'s `cost.usd`, the figure `--max-budget-usd` checks in print mode).
|
|
3
|
+
// At WARN_AT of the cap a toast says so, once; at the cap every model step, the main loop's and
|
|
4
|
+
// each subagent's, is answered by the mod with no request made, until /spend-cap raises or lifts it.
|
|
5
|
+
// A step already running finishes: its cost can pass the cap, so leave headroom.
|
|
6
|
+
|
|
7
|
+
export const WARN_AT = 0.8
|
|
8
|
+
|
|
9
|
+
export const cap = {
|
|
10
|
+
/** The cap in dollars; null is off. */
|
|
11
|
+
usd: null as number | null,
|
|
12
|
+
/** The session's cost so far, from the newest measurement; null before the first. */
|
|
13
|
+
spent: null as number | null,
|
|
14
|
+
warned: false,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** The option's value as a cap: a positive number of dollars, anything else off. */
|
|
18
|
+
export function capOf(v: unknown): number | null {
|
|
19
|
+
const n = typeof v === 'number' ? v : typeof v === 'string' && v.trim() !== '' ? Number(v.trim().replace(/^\$/, '')) : NaN
|
|
20
|
+
return Number.isFinite(n) && n > 0 ? n : null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const money = (n: number) => `$${n.toFixed(2)}`
|
|
24
|
+
|
|
25
|
+
/** Whether the next step is held: a cap is set and the cost has reached it. */
|
|
26
|
+
export const reached = () => cap.usd !== null && cap.spent !== null && cap.spent >= cap.usd
|
|
27
|
+
|
|
28
|
+
/** The warning's text once the cost first reaches WARN_AT of the cap (and stays under it), else null; said once per cap. */
|
|
29
|
+
export function warnNow(): string | null {
|
|
30
|
+
if (cap.warned || cap.usd === null || cap.spent === null || reached() || cap.spent < cap.usd * WARN_AT) return null
|
|
31
|
+
cap.warned = true
|
|
32
|
+
return `Spend cap: ${money(cap.spent)} of ${money(cap.usd)} used`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** What a held step answers in the chat. */
|
|
36
|
+
export const heldText = () =>
|
|
37
|
+
`Spend cap reached: this session has cost ${money(cap.spent ?? 0)} of the ${money(cap.usd ?? 0)} cap ` +
|
|
38
|
+
`(Claude Code's own estimate), so subagent-spend sent no request. ` +
|
|
39
|
+
`To go on, raise it with /spend-cap <dollars>, or lift it with /spend-cap off.`
|
|
40
|
+
|
|
41
|
+
/** `/spend-cap` with its args: a number sets the cap, `off` lifts it, nothing shows it. The reply's text. */
|
|
42
|
+
export function capCommand(args: string): string {
|
|
43
|
+
const a = args.trim().toLowerCase()
|
|
44
|
+
if (a === 'off') {
|
|
45
|
+
cap.usd = null
|
|
46
|
+
cap.warned = false
|
|
47
|
+
return `Spend cap off for this session. ${spentText()}`
|
|
48
|
+
}
|
|
49
|
+
if (a !== '') {
|
|
50
|
+
const n = capOf(a)
|
|
51
|
+
if (n === null) return `Not a cap: "${args.trim()}". Give dollars, like /spend-cap 5, or /spend-cap off.`
|
|
52
|
+
cap.usd = n
|
|
53
|
+
cap.warned = false
|
|
54
|
+
return `Spend cap set to ${money(n)} for this session. ${spentText()}`
|
|
55
|
+
}
|
|
56
|
+
return cap.usd === null ? `No spend cap. ${spentText()}` : `Spend cap ${money(cap.usd)}. ${spentText()}`
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const spentText = () => (cap.spent === null ? 'No cost reading yet.' : `Cost so far ${money(cap.spent)}.`)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nightlab-agent/subagent-spend",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Claude Code plugin: a spend cap for interactive sessions, and per-subagent tokens, rate-limit windows, context fill, cost, steps, tool calls and tool errors of a session, in a notice under the prompt, local files and panes (the usage pane not yet seen on a screen).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
".claude-plugin/",
|
|
27
27
|
"hooks/hooks.json",
|
|
28
28
|
"hooks/register.tsx",
|
|
29
|
+
"hooks/cap.ts",
|
|
29
30
|
"hooks/spend.ts",
|
|
30
31
|
"hooks/turns.ts",
|
|
31
32
|
"hooks/usage.ts",
|
package/subagent_spend.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""subagent-spend 0.8.
|
|
2
|
+
"""subagent-spend 0.8.3: attribute Claude Code token usage to each subagent.
|
|
3
3
|
|
|
4
4
|
subagent_spend.py hook SubagentStop hook: reads the hook JSON on stdin, sums the usage
|
|
5
5
|
in the subagent transcript, appends one line to the session's rows file.
|