@specship/specship-win32-arm64 0.11.3 → 0.11.5
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/lib/dist/statusline/index.d.ts.map +1 -1
- package/lib/dist/statusline/index.js +16 -1
- package/lib/dist/statusline/index.js.map +1 -1
- package/lib/dist/statusline/render.d.ts +19 -1
- package/lib/dist/statusline/render.d.ts.map +1 -1
- package/lib/dist/statusline/render.js +44 -1
- package/lib/dist/statusline/render.js.map +1 -1
- package/lib/dist/statusline/types.d.ts +24 -0
- package/lib/dist/statusline/types.d.ts.map +1 -1
- package/lib/dist/statusline/usage-limits.d.ts +52 -0
- package/lib/dist/statusline/usage-limits.d.ts.map +1 -0
- package/lib/dist/statusline/usage-limits.js +184 -0
- package/lib/dist/statusline/usage-limits.js.map +1 -0
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/statusline/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/statusline/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,YAAY,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAgCzC;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,UAAyB,GAAG,MAAM,CAkCvF"}
|
|
@@ -53,6 +53,7 @@ const directory_1 = require("../directory");
|
|
|
53
53
|
const cache_1 = require("./cache");
|
|
54
54
|
const session_marker_1 = require("./session-marker");
|
|
55
55
|
const active_run_1 = require("./active-run");
|
|
56
|
+
const usage_limits_1 = require("./usage-limits");
|
|
56
57
|
const render_1 = require("./render");
|
|
57
58
|
__exportStar(require("./types"), exports);
|
|
58
59
|
var cache_2 = require("./cache");
|
|
@@ -114,14 +115,28 @@ function buildSegment(rawStdin, noColor = !!process.env.NO_COLOR) {
|
|
|
114
115
|
catch {
|
|
115
116
|
root = null;
|
|
116
117
|
}
|
|
118
|
+
// Usage limits are account-wide (not per-project), so resolve them regardless
|
|
119
|
+
// of whether we found a SpecShip project. Primary source is Claude's own
|
|
120
|
+
// status-line `rate_limits` on stdin (real, includes reset times); an external
|
|
121
|
+
// file is an optional override for setups where stdin lacks them. `now`
|
|
122
|
+
// formats reset times in local time.
|
|
123
|
+
const usage = (0, usage_limits_1.usageFromStatuslineInput)(rawStdin) ?? (0, usage_limits_1.readUsageLimits)();
|
|
124
|
+
const now = Date.now();
|
|
125
|
+
// Context-usage element (REQ-STATUSLINE-009) — from the same stdin.
|
|
126
|
+
const context = (0, usage_limits_1.contextFromStatuslineInput)(rawStdin);
|
|
127
|
+
const ctxWarnPct = (0, usage_limits_1.resolveCtxWarnPct)();
|
|
117
128
|
if (!root) {
|
|
118
129
|
// No SpecShip project here — render the idle degraded line.
|
|
119
|
-
return (0, render_1.renderSegment)({ cache: null, marker: null, run: null, noColor });
|
|
130
|
+
return (0, render_1.renderSegment)({ cache: null, marker: null, run: null, usage, now, context, ctxWarnPct, noColor });
|
|
120
131
|
}
|
|
121
132
|
return (0, render_1.renderSegment)({
|
|
122
133
|
cache: (0, cache_1.readStatuslineCache)(root),
|
|
123
134
|
marker: (0, session_marker_1.readSessionMarker)(root),
|
|
124
135
|
run: (0, active_run_1.readActiveRun)(root),
|
|
136
|
+
usage,
|
|
137
|
+
now,
|
|
138
|
+
context,
|
|
139
|
+
ctxWarnPct,
|
|
125
140
|
noColor,
|
|
126
141
|
});
|
|
127
142
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/statusline/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/statusline/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,11 +9,29 @@
|
|
|
9
9
|
* tokens/cost "saved" figure. The call count is the only usage signal, framed
|
|
10
10
|
* as "N calls" — what specship was asked, not a fabricated counterfactual.
|
|
11
11
|
*/
|
|
12
|
-
import { StatuslineCache, SessionMarker, ActiveRun } from './types';
|
|
12
|
+
import { StatuslineCache, SessionMarker, ActiveRun, UsageLimits } from './types';
|
|
13
13
|
export interface RenderInput {
|
|
14
14
|
cache: StatuslineCache | null;
|
|
15
15
|
marker: SessionMarker | null;
|
|
16
16
|
run: ActiveRun | null;
|
|
17
|
+
/**
|
|
18
|
+
* Real Claude Code usage limits from the external usage file (REQ-STATUSLINE-008),
|
|
19
|
+
* or null/undefined to omit the usage sub-segment entirely. SpecShip never
|
|
20
|
+
* estimates these — null in, nothing rendered.
|
|
21
|
+
*/
|
|
22
|
+
usage?: UsageLimits | null;
|
|
23
|
+
/**
|
|
24
|
+
* Current time (ms epoch) used ONLY to format `usage` reset times in local
|
|
25
|
+
* time; keeps this function pure (no clock). Required when `usage` is present.
|
|
26
|
+
*/
|
|
27
|
+
now?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Claude's `context_window.used_percentage` (0-100) from stdin, or null/undefined
|
|
30
|
+
* to omit the CTX element (REQ-STATUSLINE-009). SpecShip never fabricates it.
|
|
31
|
+
*/
|
|
32
|
+
context?: number | null;
|
|
33
|
+
/** Context-usage warning threshold (percent); CTX escalates at/above it. */
|
|
34
|
+
ctxWarnPct?: number;
|
|
17
35
|
/** When true, emit no ANSI escapes. */
|
|
18
36
|
noColor: boolean;
|
|
19
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;CAClB;AA+CD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CA6DxD"}
|
|
@@ -12,6 +12,28 @@
|
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.renderSegment = renderSegment;
|
|
15
|
+
/** A 5-cell art-deco bar (`❮▰▱❯`) depicting `pct` (0-100) capacity used. */
|
|
16
|
+
function bar(pct) {
|
|
17
|
+
const cells = 5;
|
|
18
|
+
const filled = Math.max(0, Math.min(cells, Math.round((pct / 100) * cells)));
|
|
19
|
+
return `❮${'▰'.repeat(filled)}${'▱'.repeat(cells - filled)}❯`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Format a reset instant in the machine's local timezone: time-only when it
|
|
23
|
+
* falls on the same local day as `now` (e.g. `(4pm)`), date + time otherwise
|
|
24
|
+
* (e.g. `(6/29, 2pm)`). Minutes shown only when non-zero.
|
|
25
|
+
*/
|
|
26
|
+
function formatReset(resetMs, nowMs) {
|
|
27
|
+
const r = new Date(resetMs);
|
|
28
|
+
const n = new Date(nowMs);
|
|
29
|
+
const h = r.getHours();
|
|
30
|
+
const m = r.getMinutes();
|
|
31
|
+
const ampm = h < 12 ? 'am' : 'pm';
|
|
32
|
+
const h12 = h % 12 || 12;
|
|
33
|
+
const time = m === 0 ? `${h12}${ampm}` : `${h12}:${String(m).padStart(2, '0')}${ampm}`;
|
|
34
|
+
const sameDay = r.getFullYear() === n.getFullYear() && r.getMonth() === n.getMonth() && r.getDate() === n.getDate();
|
|
35
|
+
return sameDay ? `(${time})` : `(${r.getMonth() + 1}/${r.getDate()}, ${time})`;
|
|
36
|
+
}
|
|
15
37
|
const ESC = '\u001b';
|
|
16
38
|
// ANSI 256-color palette — the gold deco family, matching the bars.
|
|
17
39
|
const COLOR = {
|
|
@@ -35,7 +57,7 @@ function paint(noColor, code, s) {
|
|
|
35
57
|
* a minimal `◈ specship … ◈` when caches are absent rather than erroring.
|
|
36
58
|
*/
|
|
37
59
|
function renderSegment(input) {
|
|
38
|
-
const { cache, marker, run, noColor } = input;
|
|
60
|
+
const { cache, marker, run, usage, now, context, ctxWarnPct, noColor } = input;
|
|
39
61
|
const c = (code, s) => paint(noColor, code, s);
|
|
40
62
|
const orn = c(COLOR.orn, '◈');
|
|
41
63
|
const sep = c(COLOR.frame, ' ◆ ');
|
|
@@ -67,6 +89,27 @@ function renderSegment(input) {
|
|
|
67
89
|
const label = run.specId ? `${run.specId}·${run.status}` : run.status;
|
|
68
90
|
parts.push(c(COLOR.run, label));
|
|
69
91
|
}
|
|
92
|
+
// Context-usage element (REQ-STATUSLINE-009) — Claude's real context %, with
|
|
93
|
+
// an escalating compaction warning past the threshold. Advisory only;
|
|
94
|
+
// SpecShip cannot compact. Omitted when no real percentage is available.
|
|
95
|
+
if (context != null && Number.isFinite(context)) {
|
|
96
|
+
const warn = context >= (ctxWarnPct ?? 80);
|
|
97
|
+
const color = warn ? COLOR.pending : COLOR.calls; // amber when high, else gold
|
|
98
|
+
const hint = warn ? ' ⚠ compact' : '';
|
|
99
|
+
parts.push(c(color, `CTX ${bar(context)} ${Math.round(context)}%${hint}`));
|
|
100
|
+
}
|
|
101
|
+
// Usage-limit sub-segment (REQ-STATUSLINE-008) — ONLY for windows with real
|
|
102
|
+
// numbers; SpecShip never estimates. `now` formats reset times in local time.
|
|
103
|
+
if (usage && now != null) {
|
|
104
|
+
const win = (label, w) => {
|
|
105
|
+
if (!w)
|
|
106
|
+
return;
|
|
107
|
+
const reset = Number.isFinite(w.resetAt) ? ` ${formatReset(w.resetAt, now)}` : '';
|
|
108
|
+
parts.push(c(COLOR.calls, `${label} ${bar(w.pctUsed)} ${Math.round(w.pctUsed)}%${reset}`));
|
|
109
|
+
};
|
|
110
|
+
win('5h', usage.session);
|
|
111
|
+
win('7d', usage.weekly);
|
|
112
|
+
}
|
|
70
113
|
return `${orn} ${brand}${sep}${parts.join(sep)} ${orn}`;
|
|
71
114
|
}
|
|
72
115
|
//# sourceMappingURL=render.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -54,6 +54,30 @@ export interface SessionMarker {
|
|
|
54
54
|
/** ms epoch of the most recent call, or null before the first call. */
|
|
55
55
|
lastAt: number | null;
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* A single rolling-window usage limit, as written by the external usage tool
|
|
59
|
+
* (REQ-STATUSLINE-008). SpecShip never computes these — it reflects the file.
|
|
60
|
+
*/
|
|
61
|
+
export interface UsageWindow {
|
|
62
|
+
/** 0-100, percent of this window's capacity consumed (Claude's `used_percentage`). */
|
|
63
|
+
pctUsed: number;
|
|
64
|
+
/** ms epoch when this window resets (from `resets_at` epoch-s / the file's ISO `resetAt`). */
|
|
65
|
+
resetAt: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Validated usage-limit data. The primary source is Claude Code's status-line
|
|
69
|
+
* stdin `rate_limits` object; an external file (`$SPECSHIP_USAGE_FILE` /
|
|
70
|
+
* `~/.specship/usage-limits.json`) is an optional override. Either window may be
|
|
71
|
+
* independently absent (the docs note `five_hour`/`seven_day` can each be
|
|
72
|
+
* missing); a window is `null` when its data isn't present. The whole object is
|
|
73
|
+
* null when neither window is available, and the segment omits the sub-segment.
|
|
74
|
+
*/
|
|
75
|
+
export interface UsageLimits {
|
|
76
|
+
/** The 5-hour rolling session window, or null when absent. */
|
|
77
|
+
session: UsageWindow | null;
|
|
78
|
+
/** The weekly (7-day) window, or null when absent. */
|
|
79
|
+
weekly: UsageWindow | null;
|
|
80
|
+
}
|
|
57
81
|
/** The active (or most recent) workflow run for the project. */
|
|
58
82
|
export interface ActiveRun {
|
|
59
83
|
v: 1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/statusline/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,CAAC,EAAE,CAAC,CAAC;IACL,yDAAyD;IACzD,WAAW,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,CAAC,CAAC;IACL,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uEAAuE;IACvE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,gEAAgE;AAChE,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,CAAC,CAAC;IACL,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/statusline/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,CAAC,EAAE,CAAC,CAAC;IACL,yDAAyD;IACzD,WAAW,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,CAAC,CAAC;IACL,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uEAAuE;IACvE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,8DAA8D;IAC9D,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,sDAAsD;IACtD,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5B;AAED,gEAAgE;AAChE,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,CAAC,CAAC;IACL,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage-limit reader (REQ-STATUSLINE-008).
|
|
3
|
+
*
|
|
4
|
+
* The PRIMARY source is Claude Code's status-line stdin `rate_limits` object,
|
|
5
|
+
* which carries real per-window `used_percentage` and `resets_at` (Unix epoch
|
|
6
|
+
* seconds) for `five_hour` and `seven_day` (Pro/Max only, after the first API
|
|
7
|
+
* response; windows independently optional) — see `usageFromStatuslineInput`.
|
|
8
|
+
*
|
|
9
|
+
* An external file (`$SPECSHIP_USAGE_FILE` / `~/.specship/usage-limits.json`) is
|
|
10
|
+
* an OPTIONAL override read by `readUsageLimits`, for setups where the stdin
|
|
11
|
+
* `rate_limits` aren't present.
|
|
12
|
+
*
|
|
13
|
+
* Either way SpecShip never estimates: a window with no real data is null and
|
|
14
|
+
* the segment omits it. Read path only — bounded reads, no database, no
|
|
15
|
+
* subprocess, no network (same budget as REQ-STATUSLINE-002).
|
|
16
|
+
*/
|
|
17
|
+
import { UsageLimits } from './types';
|
|
18
|
+
/**
|
|
19
|
+
* Parse Claude Code's status-line stdin JSON into usage limits. Maps each
|
|
20
|
+
* window's `used_percentage` to percent-REMAINING and `resets_at` (epoch
|
|
21
|
+
* seconds) to ms. Returns null when `rate_limits` is absent or unparseable;
|
|
22
|
+
* either window may be independently null.
|
|
23
|
+
*/
|
|
24
|
+
export declare function usageFromStatuslineInput(raw: string): UsageLimits | null;
|
|
25
|
+
/**
|
|
26
|
+
* Parse Claude Code's status-line stdin JSON for context-window usage
|
|
27
|
+
* (REQ-STATUSLINE-009). Returns `context_window.used_percentage` (0-100) or null
|
|
28
|
+
* when it's absent, null (early session), or unparseable.
|
|
29
|
+
*/
|
|
30
|
+
export declare function contextFromStatuslineInput(raw: string): number | null;
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the context-usage warning threshold from `SPECSHIP_CTX_WARN_PCT`
|
|
33
|
+
* (REQ-STATUSLINE-009), falling back to the default when unset, non-numeric, or
|
|
34
|
+
* out of the 0-100 range.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveCtxWarnPct(raw?: string | undefined): number;
|
|
37
|
+
export interface ReadUsageOptions {
|
|
38
|
+
/** Override the file path (defaults to `$SPECSHIP_USAGE_FILE` or `~/.specship/usage-limits.json`). */
|
|
39
|
+
file?: string;
|
|
40
|
+
/** Current time in ms epoch (defaults to `Date.now()`); injectable for tests. */
|
|
41
|
+
now?: number;
|
|
42
|
+
/** Freshness window in ms (defaults to 15 minutes). */
|
|
43
|
+
freshnessMs?: number;
|
|
44
|
+
}
|
|
45
|
+
/** The well-known usage file an external tool writes. */
|
|
46
|
+
export declare function usageFilePath(): string;
|
|
47
|
+
/**
|
|
48
|
+
* Read + validate the usage file. Returns validated, fresh limits, or null when
|
|
49
|
+
* the data is not real (absent / unreadable / bad JSON / missing field / stale).
|
|
50
|
+
*/
|
|
51
|
+
export declare function readUsageLimits(opts?: ReadUsageOptions): UsageLimits | null;
|
|
52
|
+
//# sourceMappingURL=usage-limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-limits.d.ts","sourceRoot":"","sources":["../../src/statusline/usage-limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,EAAE,WAAW,EAAe,MAAM,SAAS,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAcxE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrE;AAKD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,GAAG,SAA6C,GAAG,MAAM,CAKrG;AAiBD,MAAM,WAAW,gBAAgB;IAC/B,sGAAsG;IACtG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,yDAAyD;AACzD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAYD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,gBAAqB,GAAG,WAAW,GAAG,IAAI,CA4B/E"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Usage-limit reader (REQ-STATUSLINE-008).
|
|
4
|
+
*
|
|
5
|
+
* The PRIMARY source is Claude Code's status-line stdin `rate_limits` object,
|
|
6
|
+
* which carries real per-window `used_percentage` and `resets_at` (Unix epoch
|
|
7
|
+
* seconds) for `five_hour` and `seven_day` (Pro/Max only, after the first API
|
|
8
|
+
* response; windows independently optional) — see `usageFromStatuslineInput`.
|
|
9
|
+
*
|
|
10
|
+
* An external file (`$SPECSHIP_USAGE_FILE` / `~/.specship/usage-limits.json`) is
|
|
11
|
+
* an OPTIONAL override read by `readUsageLimits`, for setups where the stdin
|
|
12
|
+
* `rate_limits` aren't present.
|
|
13
|
+
*
|
|
14
|
+
* Either way SpecShip never estimates: a window with no real data is null and
|
|
15
|
+
* the segment omits it. Read path only — bounded reads, no database, no
|
|
16
|
+
* subprocess, no network (same budget as REQ-STATUSLINE-002).
|
|
17
|
+
*/
|
|
18
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
21
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
22
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
23
|
+
}
|
|
24
|
+
Object.defineProperty(o, k2, desc);
|
|
25
|
+
}) : (function(o, m, k, k2) {
|
|
26
|
+
if (k2 === undefined) k2 = k;
|
|
27
|
+
o[k2] = m[k];
|
|
28
|
+
}));
|
|
29
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
30
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
31
|
+
}) : function(o, v) {
|
|
32
|
+
o["default"] = v;
|
|
33
|
+
});
|
|
34
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
35
|
+
var ownKeys = function(o) {
|
|
36
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
37
|
+
var ar = [];
|
|
38
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
39
|
+
return ar;
|
|
40
|
+
};
|
|
41
|
+
return ownKeys(o);
|
|
42
|
+
};
|
|
43
|
+
return function (mod) {
|
|
44
|
+
if (mod && mod.__esModule) return mod;
|
|
45
|
+
var result = {};
|
|
46
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
47
|
+
__setModuleDefault(result, mod);
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
})();
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.usageFromStatuslineInput = usageFromStatuslineInput;
|
|
53
|
+
exports.contextFromStatuslineInput = contextFromStatuslineInput;
|
|
54
|
+
exports.resolveCtxWarnPct = resolveCtxWarnPct;
|
|
55
|
+
exports.usageFilePath = usageFilePath;
|
|
56
|
+
exports.readUsageLimits = readUsageLimits;
|
|
57
|
+
const fs = __importStar(require("fs"));
|
|
58
|
+
const os = __importStar(require("os"));
|
|
59
|
+
const path = __importStar(require("path"));
|
|
60
|
+
/**
|
|
61
|
+
* Parse Claude Code's status-line stdin JSON into usage limits. Maps each
|
|
62
|
+
* window's `used_percentage` to percent-REMAINING and `resets_at` (epoch
|
|
63
|
+
* seconds) to ms. Returns null when `rate_limits` is absent or unparseable;
|
|
64
|
+
* either window may be independently null.
|
|
65
|
+
*/
|
|
66
|
+
function usageFromStatuslineInput(raw) {
|
|
67
|
+
let json;
|
|
68
|
+
try {
|
|
69
|
+
json = JSON.parse(raw);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const rl = json.rate_limits;
|
|
75
|
+
if (!rl || typeof rl !== 'object')
|
|
76
|
+
return null;
|
|
77
|
+
const rec = rl;
|
|
78
|
+
const session = windowFromRateLimit(rec.five_hour);
|
|
79
|
+
const weekly = windowFromRateLimit(rec.seven_day);
|
|
80
|
+
if (!session && !weekly)
|
|
81
|
+
return null;
|
|
82
|
+
return { session, weekly };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Parse Claude Code's status-line stdin JSON for context-window usage
|
|
86
|
+
* (REQ-STATUSLINE-009). Returns `context_window.used_percentage` (0-100) or null
|
|
87
|
+
* when it's absent, null (early session), or unparseable.
|
|
88
|
+
*/
|
|
89
|
+
function contextFromStatuslineInput(raw) {
|
|
90
|
+
let json;
|
|
91
|
+
try {
|
|
92
|
+
json = JSON.parse(raw);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const cw = json.context_window;
|
|
98
|
+
if (!cw || typeof cw !== 'object')
|
|
99
|
+
return null;
|
|
100
|
+
const used = cw.used_percentage;
|
|
101
|
+
if (typeof used !== 'number' || !Number.isFinite(used))
|
|
102
|
+
return null;
|
|
103
|
+
return Math.max(0, Math.min(100, used));
|
|
104
|
+
}
|
|
105
|
+
/** Default context-usage warning threshold (percent). */
|
|
106
|
+
const DEFAULT_CTX_WARN_PCT = 80;
|
|
107
|
+
/**
|
|
108
|
+
* Resolve the context-usage warning threshold from `SPECSHIP_CTX_WARN_PCT`
|
|
109
|
+
* (REQ-STATUSLINE-009), falling back to the default when unset, non-numeric, or
|
|
110
|
+
* out of the 0-100 range.
|
|
111
|
+
*/
|
|
112
|
+
function resolveCtxWarnPct(raw = process.env.SPECSHIP_CTX_WARN_PCT) {
|
|
113
|
+
if (raw == null || raw.trim() === '')
|
|
114
|
+
return DEFAULT_CTX_WARN_PCT;
|
|
115
|
+
const n = Number(raw);
|
|
116
|
+
if (!Number.isFinite(n) || n < 0 || n > 100)
|
|
117
|
+
return DEFAULT_CTX_WARN_PCT;
|
|
118
|
+
return n;
|
|
119
|
+
}
|
|
120
|
+
/** One `rate_limits.{five_hour,seven_day}` entry → a remaining-capacity window. */
|
|
121
|
+
function windowFromRateLimit(w) {
|
|
122
|
+
if (!w || typeof w !== 'object')
|
|
123
|
+
return null;
|
|
124
|
+
const rec = w;
|
|
125
|
+
const used = rec.used_percentage;
|
|
126
|
+
if (typeof used !== 'number' || !Number.isFinite(used))
|
|
127
|
+
return null;
|
|
128
|
+
const pctUsed = Math.max(0, Math.min(100, used));
|
|
129
|
+
// resets_at is Unix epoch SECONDS; may be absent → NaN (bar shows, reset omitted).
|
|
130
|
+
const resetAt = typeof rec.resets_at === 'number' && Number.isFinite(rec.resets_at) ? rec.resets_at * 1000 : NaN;
|
|
131
|
+
return { pctUsed, resetAt };
|
|
132
|
+
}
|
|
133
|
+
/** Default freshness window: data older than this is treated as not-real. */
|
|
134
|
+
const DEFAULT_FRESHNESS_MS = 15 * 60 * 1000;
|
|
135
|
+
/** The well-known usage file an external tool writes. */
|
|
136
|
+
function usageFilePath() {
|
|
137
|
+
return process.env.SPECSHIP_USAGE_FILE || path.join(os.homedir(), '.specship', 'usage-limits.json');
|
|
138
|
+
}
|
|
139
|
+
function parseWindow(w) {
|
|
140
|
+
if (!w || typeof w !== 'object')
|
|
141
|
+
return null;
|
|
142
|
+
const rec = w;
|
|
143
|
+
const pct = rec.pctUsed;
|
|
144
|
+
if (typeof pct !== 'number' || !Number.isFinite(pct) || pct < 0 || pct > 100)
|
|
145
|
+
return null;
|
|
146
|
+
const reset = typeof rec.resetAt === 'string' ? Date.parse(rec.resetAt) : NaN;
|
|
147
|
+
if (!Number.isFinite(reset))
|
|
148
|
+
return null;
|
|
149
|
+
return { pctUsed: pct, resetAt: reset };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Read + validate the usage file. Returns validated, fresh limits, or null when
|
|
153
|
+
* the data is not real (absent / unreadable / bad JSON / missing field / stale).
|
|
154
|
+
*/
|
|
155
|
+
function readUsageLimits(opts = {}) {
|
|
156
|
+
const file = opts.file ?? usageFilePath();
|
|
157
|
+
const now = opts.now ?? Date.now();
|
|
158
|
+
const freshnessMs = opts.freshnessMs ?? DEFAULT_FRESHNESS_MS;
|
|
159
|
+
let raw;
|
|
160
|
+
try {
|
|
161
|
+
raw = fs.readFileSync(file, 'utf8');
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return null; // absent / unreadable
|
|
165
|
+
}
|
|
166
|
+
let json;
|
|
167
|
+
try {
|
|
168
|
+
json = JSON.parse(raw);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return null; // not valid JSON
|
|
172
|
+
}
|
|
173
|
+
const updated = typeof json.updatedAt === 'string' ? Date.parse(json.updatedAt) : NaN;
|
|
174
|
+
if (!Number.isFinite(updated))
|
|
175
|
+
return null;
|
|
176
|
+
if (now - updated > freshnessMs)
|
|
177
|
+
return null; // stale
|
|
178
|
+
const session = parseWindow(json.session);
|
|
179
|
+
const weekly = parseWindow(json.weekly);
|
|
180
|
+
if (!session || !weekly)
|
|
181
|
+
return null; // incomplete
|
|
182
|
+
return { session, weekly };
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=usage-limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-limits.js","sourceRoot":"","sources":["../../src/statusline/usage-limits.ts"],"names":[],"mappings":"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"}
|
package/lib/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@specship/specship",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.5",
|
|
4
4
|
"description": "Supercharge Claude Code with semantic code intelligence. 94% fewer tool calls • 77% faster exploration • 100% local.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|