instar 1.3.123 → 1.3.124
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/dist/providers/adapters/openai-codex/observability/sessionPaths.d.ts +23 -1
- package/dist/providers/adapters/openai-codex/observability/sessionPaths.d.ts.map +1 -1
- package/dist/providers/adapters/openai-codex/observability/sessionPaths.js +102 -5
- package/dist/providers/adapters/openai-codex/observability/sessionPaths.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.124.md +53 -0
- package/upgrades/side-effects/codex-rollout-scan-perf.md +64 -0
|
@@ -25,7 +25,29 @@ export declare function findRolloutFile(threadId: string, codexHome?: string): P
|
|
|
25
25
|
* Claude agent) returns null fast — `readdirSync` throws and is caught.
|
|
26
26
|
*/
|
|
27
27
|
export declare function findRolloutFileSync(threadId: string, codexHome?: string): string | null;
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* List rollout files under $CODEX_HOME/sessions, newest first (by mtime).
|
|
30
|
+
*
|
|
31
|
+
* Codex partitions rollouts by date: `sessions/YYYY/MM/DD/rollout-*.jsonl`. A
|
|
32
|
+
* busy account accumulates tens of thousands of these over time (one real
|
|
33
|
+
* machine: 14k files / 1.4 GB). The previous implementation walked AND
|
|
34
|
+
* `stat`ed EVERY file on every call before slicing to `limit`, which made
|
|
35
|
+
* callers like `GET /codex/usage` and the TokenLedger scan take tens of
|
|
36
|
+
* seconds (the route timed out) on a large history.
|
|
37
|
+
*
|
|
38
|
+
* This walks the date-partition directories in DESCENDING date order and
|
|
39
|
+
* `stat`s only the rollout files in the newest partitions, stopping once it has
|
|
40
|
+
* `limit` candidates (after covering >= MIN_PARTITIONS_SCANNED non-empty
|
|
41
|
+
* partitions, so a day is never cut mid-way and the cross-midnight boundary is
|
|
42
|
+
* covered). Work is bounded to the most-recent partitions instead of the entire
|
|
43
|
+
* history. Trade-off: "newest by mtime" becomes "newest among the most-recent
|
|
44
|
+
* date partitions, then by mtime" — for the rate-limit reader this is exact
|
|
45
|
+
* (the account-wide windows are identical across any recently-active session),
|
|
46
|
+
* and for the resume/token-ledger callers a session older than the scanned
|
|
47
|
+
* partitions yet still the single most-recently-touched file is the only miss,
|
|
48
|
+
* which is vanishingly rare in practice. A non-date-partitioned layout falls
|
|
49
|
+
* back to the original full walk (correctness over speed).
|
|
50
|
+
*/
|
|
29
51
|
export declare function listAllRollouts(codexHome?: string, limit?: number): Promise<ReadonlyArray<{
|
|
30
52
|
path: string;
|
|
31
53
|
mtime: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionPaths.d.ts","sourceRoot":"","sources":["../../../../../src/providers/adapters/openai-codex/observability/sessionPaths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,wBAAgB,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,4EAA4E;AAC5E,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIvF;
|
|
1
|
+
{"version":3,"file":"sessionPaths.d.ts","sourceRoot":"","sources":["../../../../../src/providers/adapters/openai-codex/observability/sessionPaths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,wBAAgB,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,4EAA4E;AAC5E,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIvF;AAyDD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,eAAe,CACnC,SAAS,CAAC,EAAE,MAAM,EAClB,KAAK,SAAM,GACV,OAAO,CAAC,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CA0CzD"}
|
|
@@ -96,13 +96,110 @@ async function walkForUuid(root, uuid) {
|
|
|
96
96
|
}
|
|
97
97
|
return null;
|
|
98
98
|
}
|
|
99
|
-
|
|
99
|
+
// Always cover at least this many newest non-empty day-partitions before an
|
|
100
|
+
// early break, so the cross-midnight boundary (and a session that started
|
|
101
|
+
// "yesterday" but is still the most recently active) is not missed.
|
|
102
|
+
const MIN_PARTITIONS_SCANNED = 2;
|
|
103
|
+
/**
|
|
104
|
+
* List rollout files under $CODEX_HOME/sessions, newest first (by mtime).
|
|
105
|
+
*
|
|
106
|
+
* Codex partitions rollouts by date: `sessions/YYYY/MM/DD/rollout-*.jsonl`. A
|
|
107
|
+
* busy account accumulates tens of thousands of these over time (one real
|
|
108
|
+
* machine: 14k files / 1.4 GB). The previous implementation walked AND
|
|
109
|
+
* `stat`ed EVERY file on every call before slicing to `limit`, which made
|
|
110
|
+
* callers like `GET /codex/usage` and the TokenLedger scan take tens of
|
|
111
|
+
* seconds (the route timed out) on a large history.
|
|
112
|
+
*
|
|
113
|
+
* This walks the date-partition directories in DESCENDING date order and
|
|
114
|
+
* `stat`s only the rollout files in the newest partitions, stopping once it has
|
|
115
|
+
* `limit` candidates (after covering >= MIN_PARTITIONS_SCANNED non-empty
|
|
116
|
+
* partitions, so a day is never cut mid-way and the cross-midnight boundary is
|
|
117
|
+
* covered). Work is bounded to the most-recent partitions instead of the entire
|
|
118
|
+
* history. Trade-off: "newest by mtime" becomes "newest among the most-recent
|
|
119
|
+
* date partitions, then by mtime" — for the rate-limit reader this is exact
|
|
120
|
+
* (the account-wide windows are identical across any recently-active session),
|
|
121
|
+
* and for the resume/token-ledger callers a session older than the scanned
|
|
122
|
+
* partitions yet still the single most-recently-touched file is the only miss,
|
|
123
|
+
* which is vanishingly rare in practice. A non-date-partitioned layout falls
|
|
124
|
+
* back to the original full walk (correctness over speed).
|
|
125
|
+
*/
|
|
100
126
|
export async function listAllRollouts(codexHome, limit = 100) {
|
|
101
127
|
const root = path.join(codexHomeFromConfig(codexHome), 'sessions');
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
128
|
+
const dayDirs = await listDayPartitionsDescending(root);
|
|
129
|
+
if (dayDirs === null) {
|
|
130
|
+
// Unexpected/flat layout — fall back to the full walk so we never silently
|
|
131
|
+
// miss files just because the date partitions weren't where we expected.
|
|
132
|
+
const all = [];
|
|
133
|
+
await walkCollect(root, all);
|
|
134
|
+
all.sort((a, b) => b.mtime - a.mtime);
|
|
135
|
+
return all.slice(0, limit);
|
|
136
|
+
}
|
|
137
|
+
const out = [];
|
|
138
|
+
let partitionsWithFiles = 0;
|
|
139
|
+
for (const dir of dayDirs) {
|
|
140
|
+
let entries;
|
|
141
|
+
try {
|
|
142
|
+
entries = await fs.readdir(dir);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
let had = false;
|
|
148
|
+
for (const entry of entries) {
|
|
149
|
+
if (!entry.startsWith('rollout-') || !entry.endsWith('.jsonl'))
|
|
150
|
+
continue;
|
|
151
|
+
const full = path.join(dir, entry);
|
|
152
|
+
let stat;
|
|
153
|
+
try {
|
|
154
|
+
stat = await fs.stat(full);
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (stat.isFile()) {
|
|
160
|
+
out.push({ path: full, mtime: stat.mtimeMs });
|
|
161
|
+
had = true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (had)
|
|
165
|
+
partitionsWithFiles++;
|
|
166
|
+
if (out.length >= limit && partitionsWithFiles >= MIN_PARTITIONS_SCANNED)
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
out.sort((a, b) => b.mtime - a.mtime);
|
|
170
|
+
return out.slice(0, limit);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Enumerate the `sessions/YYYY/MM/DD` day-partition directories in descending
|
|
174
|
+
* date order WITHOUT statting their contents. Returns null when no
|
|
175
|
+
* date-partitioned structure is present (so the caller can fall back to a full
|
|
176
|
+
* walk). Numeric-name sort (zero-padded YYYY/MM/DD) is lexicographic-correct.
|
|
177
|
+
*/
|
|
178
|
+
async function listDayPartitionsDescending(root) {
|
|
179
|
+
const dirs = [];
|
|
180
|
+
const years = await readNamesDesc(root, /^\d{4}$/);
|
|
181
|
+
for (const y of years) {
|
|
182
|
+
const yPath = path.join(root, y);
|
|
183
|
+
const months = await readNamesDesc(yPath, /^\d{2}$/);
|
|
184
|
+
for (const m of months) {
|
|
185
|
+
const mPath = path.join(yPath, m);
|
|
186
|
+
const days = await readNamesDesc(mPath, /^\d{2}$/);
|
|
187
|
+
for (const d of days)
|
|
188
|
+
dirs.push(path.join(mPath, d));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return dirs.length > 0 ? dirs : null;
|
|
192
|
+
}
|
|
193
|
+
/** readdir + filter by name pattern + descending sort. [] on any read error. */
|
|
194
|
+
async function readNamesDesc(dir, pattern) {
|
|
195
|
+
let entries;
|
|
196
|
+
try {
|
|
197
|
+
entries = await fs.readdir(dir);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
return entries.filter((e) => pattern.test(e)).sort().reverse();
|
|
106
203
|
}
|
|
107
204
|
async function walkCollect(dir, out) {
|
|
108
205
|
let entries;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionPaths.js","sourceRoot":"","sources":["../../../../../src/providers/adapters/openai-codex/observability/sessionPaths.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"sessionPaths.js","sourceRoot":"","sources":["../../../../../src/providers/adapters/openai-codex/observability/sessionPaths.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-05-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-05-30T21:48:31.075Z",
|
|
5
|
+
"instarVersion": "1.3.124",
|
|
6
6
|
"entryCount": 193,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Instar Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- bump: patch -->
|
|
4
|
+
|
|
5
|
+
## What Changed
|
|
6
|
+
|
|
7
|
+
**Fixed: `GET /codex/usage` (and the codex TokenLedger / resume scans) timed out
|
|
8
|
+
on a large codex history.** The shared helper `listAllRollouts` walked the ENTIRE
|
|
9
|
+
`$CODEX_HOME/sessions` tree and `stat`-ed every rollout file before slicing to
|
|
10
|
+
the newest few. On a real account that history is large — one machine measured
|
|
11
|
+
14,277 files / 1.4 GB — so the full walk plus ~14k sequential `stat`s, under
|
|
12
|
+
live server load, made `GET /codex/usage` (shipped in v1.3.123) return a
|
|
13
|
+
connection timeout. It now walks the date-partition directories
|
|
14
|
+
(`sessions/YYYY/MM/DD/`) newest-first and `stat`s only the newest partitions
|
|
15
|
+
(at least two, until it has `limit` candidates), with a full-walk fallback for
|
|
16
|
+
any non-date-partitioned layout. The returned newest-N is unchanged; only the
|
|
17
|
+
scan is bounded. This one change fixes all four callers of the helper (the
|
|
18
|
+
codex-usage reader, the TokenLedger codex scan, the session-resume index, and
|
|
19
|
+
the layout canary).
|
|
20
|
+
|
|
21
|
+
## Summary of New Capabilities
|
|
22
|
+
|
|
23
|
+
- No new capability — a performance fix. `listAllRollouts` is now bounded to the
|
|
24
|
+
most-recent date partitions (helpers `listDayPartitionsDescending` +
|
|
25
|
+
`readNamesDesc`), so codex usage/ledger/resume reads stay fast regardless of
|
|
26
|
+
how much rollout history has accumulated.
|
|
27
|
+
|
|
28
|
+
## What to Tell Your User
|
|
29
|
+
|
|
30
|
+
The codex usage check now answers instantly even on a heavy account. Before this
|
|
31
|
+
fix, on an account with a very large codex history, asking how much codex usage
|
|
32
|
+
was left could hang and time out, because the check was reading through the
|
|
33
|
+
entire history to find the most recent record. It now looks only at the most
|
|
34
|
+
recent day or two of records, so it returns right away. Nothing else changes.
|
|
35
|
+
|
|
36
|
+
## Evidence
|
|
37
|
+
|
|
38
|
+
**Reproduction.** On a real codex account with 14,277 rollout files (1.4 GB)
|
|
39
|
+
under `~/.codex/sessions`, hitting `GET /codex/usage` on the running server
|
|
40
|
+
returned a connection timeout — curl reported status 000 after a 30-second
|
|
41
|
+
`--max-time`, while `GET /health` on the same server responded normally. Root
|
|
42
|
+
cause confirmed by reading the code: `listAllRollouts` recursively walked the
|
|
43
|
+
whole tree and awaited an `fs.stat` on every one of the 14k files before
|
|
44
|
+
sorting and slicing.
|
|
45
|
+
|
|
46
|
+
**Before / after.** The old full-walk timed out at 30 s+ under load. The fixed
|
|
47
|
+
date-partition walk, run against the same live 14,277-file tree, completed in
|
|
48
|
+
**59 ms** (it scanned the two newest day-partitions, found the newest rollout,
|
|
49
|
+
and stopped) — returning the same newest record. A unit test with 206 fixture
|
|
50
|
+
files across 42 partitions uses an `fs.stat` spy to assert fewer than 20 stats
|
|
51
|
+
occur (only the newest partitions), versus 206 before. All three test tiers for
|
|
52
|
+
the codex-usage feature plus the TokenLedger / resume / canary suites stay
|
|
53
|
+
green.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Side-Effects Review — bound the codex rollout scan to the newest partitions
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `codex-rollout-scan-perf`
|
|
4
|
+
**Date:** 2026-05-30
|
|
5
|
+
**Author:** Echo (instar-dev agent)
|
|
6
|
+
**Second-pass reviewer:** not required (pure read-path perf optimization; no block/allow/lifecycle/decision surface)
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
`listAllRollouts` (`src/providers/adapters/openai-codex/observability/sessionPaths.ts`)
|
|
11
|
+
no longer walks + `stat`s the ENTIRE `$CODEX_HOME/sessions` tree to return the
|
|
12
|
+
newest-N rollouts. It now walks date-partition dirs newest-first and stats only
|
|
13
|
+
the newest partitions (>= 2, until `limit` candidates), with a full-walk
|
|
14
|
+
fallback for non-date-partitioned layouts. Fixes the `GET /codex/usage` timeout
|
|
15
|
+
(and the shared TokenLedger / resume-index cost) on a large codex history
|
|
16
|
+
(measured 14,277 files / 1.4 GB → route timed out at 30 s; now 59 ms).
|
|
17
|
+
|
|
18
|
+
## Decision-point inventory
|
|
19
|
+
|
|
20
|
+
- No decision point. `listAllRollouts` returns data (a list of file paths +
|
|
21
|
+
mtimes). The change is purely the disk-scan strategy used to produce that
|
|
22
|
+
list; the returned newest-N is unchanged for the common case.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 1. Over-block
|
|
27
|
+
No block/allow surface — not applicable. It returns a file list; it rejects
|
|
28
|
+
nothing.
|
|
29
|
+
|
|
30
|
+
## 2. Under-block
|
|
31
|
+
Not applicable. The closest "miss" is the documented trade-off: a session OLDER
|
|
32
|
+
than the scanned partitions yet still the single most-recently-touched file on
|
|
33
|
+
disk would not be in the candidate set. For the rate-limit reader this changes
|
|
34
|
+
nothing (account-wide windows are identical across any recently-active session);
|
|
35
|
+
for the resume/token-ledger callers it is a vanishingly rare miss (sessions are
|
|
36
|
+
not active for days) and `MIN_PARTITIONS_SCANNED = 2` covers the common
|
|
37
|
+
cross-midnight case.
|
|
38
|
+
|
|
39
|
+
## 3. Level-of-abstraction fit
|
|
40
|
+
Correct layer — the fix is in the shared helper, so all four callers
|
|
41
|
+
(codex-usage reader, TokenLedger scan, resume index, layout canary) get the
|
|
42
|
+
speedup from one change rather than each re-implementing a bounded scan.
|
|
43
|
+
|
|
44
|
+
## 4. Signal vs authority compliance
|
|
45
|
+
Compliant — no authority at all. A read helper that returns data; it gates,
|
|
46
|
+
blocks, and decides nothing (`docs/signal-vs-authority.md` n/a beyond "this is
|
|
47
|
+
not a decision point").
|
|
48
|
+
|
|
49
|
+
## 5. Interactions
|
|
50
|
+
- **Shared helper:** all callers benefit; none depend on the *full* unbounded
|
|
51
|
+
list (every caller passes a `limit` and wants newest-N). Verified the four
|
|
52
|
+
call sites pass a finite limit.
|
|
53
|
+
- **No races / no writes:** read-only; opens + closes its own dir/file handles.
|
|
54
|
+
- **Canary:** `codexSessionLayoutCanary` uses date-partitioned fixtures → hits
|
|
55
|
+
the fast path → stays green (verified).
|
|
56
|
+
|
|
57
|
+
## 6. External surfaces
|
|
58
|
+
- Makes `GET /codex/usage` actually responsive on a heavy account (it returns
|
|
59
|
+
fast instead of timing out). No change to the response shape or semantics.
|
|
60
|
+
- No new route, no message, no change visible to other agents.
|
|
61
|
+
|
|
62
|
+
## 7. Rollback cost
|
|
63
|
+
Trivial. Revert the `listAllRollouts` rewrite + the two private helpers + the new
|
|
64
|
+
test. No data, no migration, no behavior to repair — only the scan strategy.
|