instar 1.3.122 → 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/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +16 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts +10 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +34 -2
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/providers/adapters/openai-codex/observability/codexModelSwapPolicy.d.ts +83 -0
- package/dist/providers/adapters/openai-codex/observability/codexModelSwapPolicy.d.ts.map +1 -0
- package/dist/providers/adapters/openai-codex/observability/codexModelSwapPolicy.js +93 -0
- package/dist/providers/adapters/openai-codex/observability/codexModelSwapPolicy.js.map +1 -0
- package/dist/providers/adapters/openai-codex/observability/codexRateLimitReader.d.ts +95 -0
- package/dist/providers/adapters/openai-codex/observability/codexRateLimitReader.d.ts.map +1 -0
- package/dist/providers/adapters/openai-codex/observability/codexRateLimitReader.js +170 -0
- package/dist/providers/adapters/openai-codex/observability/codexRateLimitReader.js.map +1 -0
- 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/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +5 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +11 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +31 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates.ts +5 -0
- package/upgrades/1.3.123.md +105 -0
- package/upgrades/1.3.124.md +53 -0
- package/upgrades/side-effects/codex-model-swap.md +134 -0
- package/upgrades/side-effects/codex-rollout-scan-perf.md +64 -0
- package/upgrades/side-effects/codex-usage-visibility.md +107 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex rate-limit model-swap policy.
|
|
3
|
+
*
|
|
4
|
+
* Justin's ask (2026-05-30): "swap to GPT-5.3-Codex-Spark when the other usage
|
|
5
|
+
* hits the limit." Codex's primary model (e.g. gpt-5.5) and a fallback like
|
|
6
|
+
* Codex-Spark draw on SEPARATE account quota buckets, so when the main model's
|
|
7
|
+
* weekly window is exhausted, launching the next session on the fallback keeps
|
|
8
|
+
* the agent working instead of stalling on a depleted window.
|
|
9
|
+
*
|
|
10
|
+
* This module is the DECISION; it holds no authority of its own. The pure
|
|
11
|
+
* `resolveCodexLaunchModel` takes a usage snapshot (from `readLatestCodexUsage`,
|
|
12
|
+
* the authoritative on-disk rate-limit reader) and the operator config and
|
|
13
|
+
* returns which model the NEXT codex session should launch with. A running
|
|
14
|
+
* session can't change model mid-turn, so the swap naturally applies at launch.
|
|
15
|
+
*
|
|
16
|
+
* Safe-by-default: ships DARK. With `enabled` false (the default) or no
|
|
17
|
+
* `fallbackModel` set, it is a no-op and adds zero overhead to the spawn path.
|
|
18
|
+
* The fallback model id is OPERATOR CONFIG — never hardcoded — because the exact
|
|
19
|
+
* Codex-Spark `--model` string + its subscription availability is the account
|
|
20
|
+
* owner's to confirm (it is not in instar's probed model list).
|
|
21
|
+
*
|
|
22
|
+
* RULE 3.1 RATIONALE
|
|
23
|
+
* Criticality: medium (cost-routing; never blocks a launch)
|
|
24
|
+
* Frequency: per codex session launch, only when enabled
|
|
25
|
+
* Stability: stable (pure decision over a structured snapshot)
|
|
26
|
+
* Fallback: no swap (launch with the requested model) on any uncertainty
|
|
27
|
+
* Verdict: pure policy + best-effort usage read; unit-tested both sides
|
|
28
|
+
*/
|
|
29
|
+
import { readLatestCodexUsage } from './codexRateLimitReader.js';
|
|
30
|
+
export const DEFAULT_WEEKLY_REMAINING_THRESHOLD = 10;
|
|
31
|
+
/**
|
|
32
|
+
* Pure decision: given the framework, the requested model, the operator config,
|
|
33
|
+
* and the current codex usage snapshot, return which model to launch with.
|
|
34
|
+
* Never throws. Returns the requested model unchanged on any reason not to swap.
|
|
35
|
+
*/
|
|
36
|
+
export function resolveCodexLaunchModel(params) {
|
|
37
|
+
const { framework, requestedModel, config, usage } = params;
|
|
38
|
+
const noSwap = { model: requestedModel, swapped: false, reason: null };
|
|
39
|
+
if (framework !== 'codex-cli')
|
|
40
|
+
return noSwap;
|
|
41
|
+
if (!config?.enabled)
|
|
42
|
+
return noSwap;
|
|
43
|
+
const fallback = config.fallbackModel;
|
|
44
|
+
if (!fallback)
|
|
45
|
+
return noSwap; // nothing to swap to — operator hasn't set the id
|
|
46
|
+
// Already on the fallback → don't re-swap (no-op / avoids a confusing log).
|
|
47
|
+
if (requestedModel && requestedModel === fallback)
|
|
48
|
+
return noSwap;
|
|
49
|
+
if (!usage)
|
|
50
|
+
return noSwap; // couldn't read usage → conservative: launch as requested
|
|
51
|
+
const threshold = config.weeklyRemainingThreshold ?? DEFAULT_WEEKLY_REMAINING_THRESHOLD;
|
|
52
|
+
const reached = usage.rateLimitReachedType; // authoritative "a window is hit NOW"
|
|
53
|
+
const weeklyRemaining = usage.secondary?.remainingPercent;
|
|
54
|
+
const reachedHit = reached !== null && reached !== undefined;
|
|
55
|
+
const weeklyLow = typeof weeklyRemaining === 'number' && weeklyRemaining <= threshold;
|
|
56
|
+
if (!reachedHit && !weeklyLow)
|
|
57
|
+
return noSwap;
|
|
58
|
+
return {
|
|
59
|
+
model: fallback,
|
|
60
|
+
swapped: true,
|
|
61
|
+
reason: reachedHit
|
|
62
|
+
? `codex rate_limit_reached_type=${reached}; swapping launch model to ${fallback}`
|
|
63
|
+
: `codex weekly window at ${weeklyRemaining}% remaining (<= ${threshold}%); swapping launch model to ${fallback}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Best-effort async wrapper used on the spawn path. Reads the current codex
|
|
68
|
+
* usage (only when the feature is enabled — disabled = zero disk I/O) and
|
|
69
|
+
* applies {@link resolveCodexLaunchModel}. NEVER throws and NEVER blocks a
|
|
70
|
+
* launch: any read failure resolves to "no swap" (launch with the requested
|
|
71
|
+
* model). `readUsage` is injectable for tests.
|
|
72
|
+
*/
|
|
73
|
+
export async function resolveCodexLaunchModelWithUsage(params) {
|
|
74
|
+
const { framework, requestedModel, config, codexHome } = params;
|
|
75
|
+
const noSwap = { model: requestedModel, swapped: false, reason: null };
|
|
76
|
+
// Fast paths that avoid any disk read when the feature can't act.
|
|
77
|
+
if (framework !== 'codex-cli')
|
|
78
|
+
return noSwap;
|
|
79
|
+
if (!config?.enabled || !config.fallbackModel)
|
|
80
|
+
return noSwap;
|
|
81
|
+
if (requestedModel && requestedModel === config.fallbackModel)
|
|
82
|
+
return noSwap;
|
|
83
|
+
const read = params.readUsage ?? readLatestCodexUsage;
|
|
84
|
+
let usage = null;
|
|
85
|
+
try {
|
|
86
|
+
usage = await read({ codexHome });
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return noSwap; // best-effort: never block a launch on a usage read
|
|
90
|
+
}
|
|
91
|
+
return resolveCodexLaunchModel({ framework, requestedModel, config, usage });
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=codexModelSwapPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexModelSwapPolicy.js","sourceRoot":"","sources":["../../../../../src/providers/adapters/openai-codex/observability/codexModelSwapPolicy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AA6BjE,MAAM,CAAC,MAAM,kCAAkC,GAAG,EAAE,CAAC;AAErD;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAKvC;IACC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAC5D,MAAM,MAAM,GAA2B,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAE/F,IAAI,SAAS,KAAK,WAAW;QAAE,OAAO,MAAM,CAAC;IAC7C,IAAI,CAAC,MAAM,EAAE,OAAO;QAAE,OAAO,MAAM,CAAC;IACpC,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC;IACtC,IAAI,CAAC,QAAQ;QAAE,OAAO,MAAM,CAAC,CAAC,kDAAkD;IAChF,4EAA4E;IAC5E,IAAI,cAAc,IAAI,cAAc,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IACjE,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC,CAAC,0DAA0D;IAErF,MAAM,SAAS,GAAG,MAAM,CAAC,wBAAwB,IAAI,kCAAkC,CAAC;IACxF,MAAM,OAAO,GAAG,KAAK,CAAC,oBAAoB,CAAC,CAAC,sCAAsC;IAClF,MAAM,eAAe,GAAG,KAAK,CAAC,SAAS,EAAE,gBAAgB,CAAC;IAE1D,MAAM,UAAU,GAAG,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,CAAC;IAC7D,MAAM,SAAS,GAAG,OAAO,eAAe,KAAK,QAAQ,IAAI,eAAe,IAAI,SAAS,CAAC;IACtF,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS;QAAE,OAAO,MAAM,CAAC;IAE7C,OAAO;QACL,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,UAAU;YAChB,CAAC,CAAC,iCAAiC,OAAO,8BAA8B,QAAQ,EAAE;YAClF,CAAC,CAAC,0BAA0B,eAAe,mBAAmB,SAAS,gCAAgC,QAAQ,EAAE;KACpH,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAC,MAMtD;IACC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAChE,MAAM,MAAM,GAA2B,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAE/F,kEAAkE;IAClE,IAAI,SAAS,KAAK,WAAW;QAAE,OAAO,MAAM,CAAC;IAC7C,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa;QAAE,OAAO,MAAM,CAAC;IAC7D,IAAI,cAAc,IAAI,cAAc,KAAK,MAAM,CAAC,aAAa;QAAE,OAAO,MAAM,CAAC;IAE7E,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,IAAI,oBAAoB,CAAC;IACtD,IAAI,KAAK,GAA8B,IAAI,CAAC;IAC5C,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,CAAC,oDAAoD;IACrE,CAAC;IACD,OAAO,uBAAuB,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the codex CLI's `/status`-equivalent rate-limit usage from the
|
|
3
|
+
* on-disk rollout JSONL stream — WITHOUT the interactive TUI.
|
|
4
|
+
*
|
|
5
|
+
* Codex has no public usage endpoint (the UsageMeterProvider falls back to
|
|
6
|
+
* local token accounting and reports isAuthoritative()=false). But the codex
|
|
7
|
+
* CLI DOES persist the authoritative account rate-limit windows it gets back
|
|
8
|
+
* from OpenAI: every turn it appends a `token_count` event to the session
|
|
9
|
+
* rollout whose `payload.rate_limits` carries the same primary (5h) /
|
|
10
|
+
* secondary (weekly) windows the TUI's `/status` shows:
|
|
11
|
+
*
|
|
12
|
+
* { "type": "event_msg",
|
|
13
|
+
* "payload": {
|
|
14
|
+
* "type": "token_count",
|
|
15
|
+
* "rate_limits": {
|
|
16
|
+
* "limit_id": "codex",
|
|
17
|
+
* "primary": { "used_percent": 13, "window_minutes": 300, "resets_at": 1780171524 },
|
|
18
|
+
* "secondary": { "used_percent": 93, "window_minutes": 10080, "resets_at": 1780174809 },
|
|
19
|
+
* "plan_type": "prolite",
|
|
20
|
+
* "rate_limit_reached_type": null } } }
|
|
21
|
+
*
|
|
22
|
+
* This reader finds the newest rollout(s), reads only the tail (rate-limit
|
|
23
|
+
* events are appended per-turn, so the freshest is near the end), and returns
|
|
24
|
+
* the most recent snapshot. It is read-only and never mutates any session
|
|
25
|
+
* state — the same discipline as the rest of the codex observability layer.
|
|
26
|
+
*
|
|
27
|
+
* RULE 3.1 RATIONALE
|
|
28
|
+
* Criticality: high (cost-routing / model-swap input)
|
|
29
|
+
* Frequency: per-poll / on-demand (route hit)
|
|
30
|
+
* Stability: semi-stable (codex rollout layout changes occasionally —
|
|
31
|
+
* shared with sessionPaths, covered by codexSessionLayoutCanary)
|
|
32
|
+
* Fallback: return null when no rollout / no token_count event is found
|
|
33
|
+
* Verdict: deterministic tail-scan; canary covers the layout
|
|
34
|
+
*/
|
|
35
|
+
/** A single rate-limit window (5h primary or weekly secondary). */
|
|
36
|
+
export interface CodexRateWindow {
|
|
37
|
+
/** Percent of the window's budget consumed (0-100). */
|
|
38
|
+
usedPercent: number;
|
|
39
|
+
/** Convenience: 100 - usedPercent, clamped to [0, 100]. */
|
|
40
|
+
remainingPercent: number;
|
|
41
|
+
/** Window length in minutes (300 = 5h, 10080 = weekly). */
|
|
42
|
+
windowMinutes: number;
|
|
43
|
+
/** Absolute reset time, unix epoch seconds (as codex reports it). */
|
|
44
|
+
resetsAt: number;
|
|
45
|
+
/** Derived ISO-8601 of `resetsAt`, or null if `resetsAt` is missing/invalid. */
|
|
46
|
+
resetsAtIso: string | null;
|
|
47
|
+
/** Seconds until reset relative to the provided clock, or null when no clock. */
|
|
48
|
+
resetsInSeconds: number | null;
|
|
49
|
+
}
|
|
50
|
+
/** A point-in-time snapshot of codex account rate-limit usage. */
|
|
51
|
+
export interface CodexUsageSnapshot {
|
|
52
|
+
source: 'codex-rollout';
|
|
53
|
+
/** The rollout file the snapshot was read from. */
|
|
54
|
+
rolloutPath: string;
|
|
55
|
+
/** Thread UUID parsed from the rollout filename, or null. */
|
|
56
|
+
threadId: string | null;
|
|
57
|
+
/** Timestamp of the token_count event the snapshot came from (ISO), or null. */
|
|
58
|
+
capturedAt: string | null;
|
|
59
|
+
/** Model in effect at capture (best-effort from the latest turn_context), or null. */
|
|
60
|
+
model: string | null;
|
|
61
|
+
/** Plan tier codex reports (e.g. "plus", "prolite"), or null. */
|
|
62
|
+
planType: string | null;
|
|
63
|
+
/**
|
|
64
|
+
* Which window (if any) is currently exhausted. codex sets this to e.g.
|
|
65
|
+
* "primary" / "secondary" when a limit is hit; null when usage is fine.
|
|
66
|
+
* This is the authoritative "we are rate-limited" signal.
|
|
67
|
+
*/
|
|
68
|
+
rateLimitReachedType: string | null;
|
|
69
|
+
/** The 5h rolling window (window_minutes 300), or null if absent. */
|
|
70
|
+
primary: CodexRateWindow | null;
|
|
71
|
+
/** The weekly rolling window (window_minutes 10080), or null if absent. */
|
|
72
|
+
secondary: CodexRateWindow | null;
|
|
73
|
+
}
|
|
74
|
+
export interface ReadCodexUsageOptions {
|
|
75
|
+
/** Override $CODEX_HOME (defaults to ~/.codex). */
|
|
76
|
+
codexHome?: string;
|
|
77
|
+
/** Clock for deriving `resetsInSeconds` (defaults to Date.now()). */
|
|
78
|
+
nowMs?: number;
|
|
79
|
+
/** How many newest rollouts to scan for a token_count event (default 8). */
|
|
80
|
+
maxRolloutsScanned?: number;
|
|
81
|
+
/** Tail size to read from each rollout (default 512 KiB). */
|
|
82
|
+
tailBytes?: number;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Read the freshest codex rate-limit snapshot from disk. Returns null when
|
|
86
|
+
* there is no codex rollout with a rate-limit-bearing token_count event
|
|
87
|
+
* (e.g. a pure-Claude agent, or a session that has not completed a turn yet).
|
|
88
|
+
*/
|
|
89
|
+
export declare function readLatestCodexUsage(opts?: ReadCodexUsageOptions): Promise<CodexUsageSnapshot | null>;
|
|
90
|
+
/**
|
|
91
|
+
* Parse the freshest rate-limit snapshot out of a rollout tail. Exported for
|
|
92
|
+
* unit tests so they can exercise the parser without touching disk.
|
|
93
|
+
*/
|
|
94
|
+
export declare function parseUsageFromTail(tail: string, rolloutPath: string, nowMs: number): CodexUsageSnapshot | null;
|
|
95
|
+
//# sourceMappingURL=codexRateLimitReader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexRateLimitReader.d.ts","sourceRoot":"","sources":["../../../../../src/providers/adapters/openai-codex/observability/codexRateLimitReader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAKH,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,gBAAgB,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iFAAiF;IACjF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,eAAe,CAAC;IACxB,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,gFAAgF;IAChF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,sFAAsF;IACtF,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,qEAAqE;IACrE,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,2EAA2E;IAC3E,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,qBAAqB;IACpC,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,GAAE,qBAA0B,GAC/B,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAiBpC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ,kBAAkB,GAAG,IAAI,CA8C3B"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the codex CLI's `/status`-equivalent rate-limit usage from the
|
|
3
|
+
* on-disk rollout JSONL stream — WITHOUT the interactive TUI.
|
|
4
|
+
*
|
|
5
|
+
* Codex has no public usage endpoint (the UsageMeterProvider falls back to
|
|
6
|
+
* local token accounting and reports isAuthoritative()=false). But the codex
|
|
7
|
+
* CLI DOES persist the authoritative account rate-limit windows it gets back
|
|
8
|
+
* from OpenAI: every turn it appends a `token_count` event to the session
|
|
9
|
+
* rollout whose `payload.rate_limits` carries the same primary (5h) /
|
|
10
|
+
* secondary (weekly) windows the TUI's `/status` shows:
|
|
11
|
+
*
|
|
12
|
+
* { "type": "event_msg",
|
|
13
|
+
* "payload": {
|
|
14
|
+
* "type": "token_count",
|
|
15
|
+
* "rate_limits": {
|
|
16
|
+
* "limit_id": "codex",
|
|
17
|
+
* "primary": { "used_percent": 13, "window_minutes": 300, "resets_at": 1780171524 },
|
|
18
|
+
* "secondary": { "used_percent": 93, "window_minutes": 10080, "resets_at": 1780174809 },
|
|
19
|
+
* "plan_type": "prolite",
|
|
20
|
+
* "rate_limit_reached_type": null } } }
|
|
21
|
+
*
|
|
22
|
+
* This reader finds the newest rollout(s), reads only the tail (rate-limit
|
|
23
|
+
* events are appended per-turn, so the freshest is near the end), and returns
|
|
24
|
+
* the most recent snapshot. It is read-only and never mutates any session
|
|
25
|
+
* state — the same discipline as the rest of the codex observability layer.
|
|
26
|
+
*
|
|
27
|
+
* RULE 3.1 RATIONALE
|
|
28
|
+
* Criticality: high (cost-routing / model-swap input)
|
|
29
|
+
* Frequency: per-poll / on-demand (route hit)
|
|
30
|
+
* Stability: semi-stable (codex rollout layout changes occasionally —
|
|
31
|
+
* shared with sessionPaths, covered by codexSessionLayoutCanary)
|
|
32
|
+
* Fallback: return null when no rollout / no token_count event is found
|
|
33
|
+
* Verdict: deterministic tail-scan; canary covers the layout
|
|
34
|
+
*/
|
|
35
|
+
import { promises as fs } from 'node:fs';
|
|
36
|
+
import { listAllRollouts } from './sessionPaths.js';
|
|
37
|
+
const DEFAULT_TAIL_BYTES = 512 * 1024;
|
|
38
|
+
const DEFAULT_MAX_ROLLOUTS = 8;
|
|
39
|
+
const UUID_RE = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i;
|
|
40
|
+
/**
|
|
41
|
+
* Read the freshest codex rate-limit snapshot from disk. Returns null when
|
|
42
|
+
* there is no codex rollout with a rate-limit-bearing token_count event
|
|
43
|
+
* (e.g. a pure-Claude agent, or a session that has not completed a turn yet).
|
|
44
|
+
*/
|
|
45
|
+
export async function readLatestCodexUsage(opts = {}) {
|
|
46
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
47
|
+
const tailBytes = opts.tailBytes ?? DEFAULT_TAIL_BYTES;
|
|
48
|
+
const maxRollouts = opts.maxRolloutsScanned ?? DEFAULT_MAX_ROLLOUTS;
|
|
49
|
+
const rollouts = await listAllRollouts(opts.codexHome, maxRollouts);
|
|
50
|
+
for (const { path: rolloutPath } of rollouts) {
|
|
51
|
+
let tail;
|
|
52
|
+
try {
|
|
53
|
+
tail = await readTail(rolloutPath, tailBytes);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const snapshot = parseUsageFromTail(tail, rolloutPath, nowMs);
|
|
59
|
+
if (snapshot)
|
|
60
|
+
return snapshot;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Parse the freshest rate-limit snapshot out of a rollout tail. Exported for
|
|
66
|
+
* unit tests so they can exercise the parser without touching disk.
|
|
67
|
+
*/
|
|
68
|
+
export function parseUsageFromTail(tail, rolloutPath, nowMs) {
|
|
69
|
+
const lines = tail.split('\n');
|
|
70
|
+
let rateLimits = null;
|
|
71
|
+
let capturedAt = null;
|
|
72
|
+
let model = null;
|
|
73
|
+
for (const line of lines) {
|
|
74
|
+
if (!line || line[0] !== '{')
|
|
75
|
+
continue;
|
|
76
|
+
// Cheap pre-filter before the JSON.parse cost.
|
|
77
|
+
const hasRate = line.includes('"rate_limits"');
|
|
78
|
+
const hasModel = line.includes('"turn_context"') && line.includes('"model"');
|
|
79
|
+
if (!hasRate && !hasModel)
|
|
80
|
+
continue;
|
|
81
|
+
let obj;
|
|
82
|
+
try {
|
|
83
|
+
obj = JSON.parse(line);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const payload = obj.payload;
|
|
89
|
+
if (!payload)
|
|
90
|
+
continue;
|
|
91
|
+
if (payload.type === 'token_count' && payload.rate_limits) {
|
|
92
|
+
rateLimits = payload.rate_limits;
|
|
93
|
+
capturedAt = typeof obj.timestamp === 'string' ? obj.timestamp : capturedAt;
|
|
94
|
+
}
|
|
95
|
+
else if (payload.type === undefined && obj.type === 'turn_context') {
|
|
96
|
+
// turn_context nests its fields directly under payload.
|
|
97
|
+
const m = payload.model;
|
|
98
|
+
if (typeof m === 'string' && m)
|
|
99
|
+
model = m;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (!rateLimits)
|
|
103
|
+
return null;
|
|
104
|
+
return {
|
|
105
|
+
source: 'codex-rollout',
|
|
106
|
+
rolloutPath,
|
|
107
|
+
threadId: parseThreadId(rolloutPath),
|
|
108
|
+
capturedAt,
|
|
109
|
+
model,
|
|
110
|
+
planType: typeof rateLimits.plan_type === 'string' ? rateLimits.plan_type : null,
|
|
111
|
+
rateLimitReachedType: typeof rateLimits.rate_limit_reached_type === 'string'
|
|
112
|
+
? rateLimits.rate_limit_reached_type
|
|
113
|
+
: null,
|
|
114
|
+
primary: parseWindow(rateLimits.primary, nowMs),
|
|
115
|
+
secondary: parseWindow(rateLimits.secondary, nowMs),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function parseWindow(raw, nowMs) {
|
|
119
|
+
if (!raw || typeof raw !== 'object')
|
|
120
|
+
return null;
|
|
121
|
+
const w = raw;
|
|
122
|
+
const usedPercent = typeof w.used_percent === 'number' ? w.used_percent : null;
|
|
123
|
+
const windowMinutes = typeof w.window_minutes === 'number' ? w.window_minutes : null;
|
|
124
|
+
const resetsAt = typeof w.resets_at === 'number' ? w.resets_at : null;
|
|
125
|
+
if (usedPercent === null || windowMinutes === null || resetsAt === null)
|
|
126
|
+
return null;
|
|
127
|
+
const validReset = Number.isFinite(resetsAt) && resetsAt > 0;
|
|
128
|
+
return {
|
|
129
|
+
usedPercent,
|
|
130
|
+
remainingPercent: clampPercent(100 - usedPercent),
|
|
131
|
+
windowMinutes,
|
|
132
|
+
resetsAt,
|
|
133
|
+
resetsAtIso: validReset ? new Date(resetsAt * 1000).toISOString() : null,
|
|
134
|
+
resetsInSeconds: validReset ? Math.round((resetsAt * 1000 - nowMs) / 1000) : null,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function clampPercent(n) {
|
|
138
|
+
if (n < 0)
|
|
139
|
+
return 0;
|
|
140
|
+
if (n > 100)
|
|
141
|
+
return 100;
|
|
142
|
+
return n;
|
|
143
|
+
}
|
|
144
|
+
function parseThreadId(rolloutPath) {
|
|
145
|
+
const m = UUID_RE.exec(rolloutPath);
|
|
146
|
+
return m ? m[1] : null;
|
|
147
|
+
}
|
|
148
|
+
async function readTail(filePath, maxBytes) {
|
|
149
|
+
const handle = await fs.open(filePath, 'r');
|
|
150
|
+
try {
|
|
151
|
+
const { size } = await handle.stat();
|
|
152
|
+
const start = size > maxBytes ? size - maxBytes : 0;
|
|
153
|
+
const length = size - start;
|
|
154
|
+
if (length <= 0)
|
|
155
|
+
return '';
|
|
156
|
+
const buf = Buffer.alloc(length);
|
|
157
|
+
await handle.read(buf, 0, length, start);
|
|
158
|
+
let text = buf.toString('utf8');
|
|
159
|
+
if (start > 0) {
|
|
160
|
+
// The first line is likely partial — drop up to the first newline.
|
|
161
|
+
const nl = text.indexOf('\n');
|
|
162
|
+
text = nl >= 0 ? text.slice(nl + 1) : '';
|
|
163
|
+
}
|
|
164
|
+
return text;
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
await handle.close();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=codexRateLimitReader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexRateLimitReader.js","sourceRoot":"","sources":["../../../../../src/providers/adapters/openai-codex/observability/codexRateLimitReader.ts"],"names":[],"mappings":"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"}
|
|
@@ -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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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/scaffold/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAgG/D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CA2E/F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiBvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA2B1D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,OAAO,EACpB,WAAW,GAAE,OAAe,EAC5B,WAAW,GAAE,OAAe,GAC3B,MAAM,
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/scaffold/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAgG/D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CA2E/F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiBvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA2B1D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,OAAO,EACpB,WAAW,GAAE,OAAe,EAC5B,WAAW,GAAE,OAAe,GAC3B,MAAM,CAisCR;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,OAAO,EACpB,WAAW,GAAE,OAAe,GAC3B,MAAM,CAuSR"}
|
|
@@ -589,6 +589,11 @@ This routes feedback to the Instar maintainers automatically. Valid types: \`bug
|
|
|
589
589
|
- **Auto-sync**: Search automatically syncs before querying, so results are always current.
|
|
590
590
|
- **When to use**: When looking for something you know you wrote but can't remember where. When a user asks "didn't we discuss X?" When building context for a task from past learnings.
|
|
591
591
|
|
|
592
|
+
**Codex Usage** — Check where codex account usage sits (the codex \`/status\` rate-limit windows) without the interactive TUI. Reads the authoritative primary (5h) + secondary (weekly) windows the codex CLI persists into its session rollout files.
|
|
593
|
+
- Check: \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/codex/usage\`
|
|
594
|
+
- Returns \`{ available, usage: { primary, secondary, model, planType, rateLimitReachedType } }\` where each window has \`usedPercent\`, \`remainingPercent\`, \`windowMinutes\`, \`resetsAt\`/\`resetsAtIso\`, \`resetsInSeconds\`. \`available:false\` means no codex session data on disk yet (e.g. a pure-Claude agent).
|
|
595
|
+
- **When to use**: when asked "how much codex usage is left?" / "am I near the limit?", before scheduling heavy codex work, or to drive a model-swap when a window is exhausted (\`rateLimitReachedType\` is non-null, or \`secondary.remainingPercent\` is low).
|
|
596
|
+
|
|
592
597
|
**Git Sync** — Automatic version-control and multi-machine synchronization of your state.
|
|
593
598
|
- **How it works**: The \`git-sync\` job runs hourly, commits local changes, pulls remote changes, and pushes — all automatically. It uses a gate script to skip when nothing has changed (zero-token cost).
|
|
594
599
|
- **Project-bound agents**: Your state (\`.instar/\`) lives inside the parent project's git repo. The git-sync job uses this repo directly — no separate repo needed. Just make sure the parent repo has a remote configured (\`git remote -v\`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/scaffold/templates.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/scaffold/templates.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CapabilityIndex.d.ts","sourceRoot":"","sources":["../../src/server/CapabilityIndex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,yEAAyE;AACzE,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,YAAY,CAAC;IAClB,iFAAiF;IACjF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kFAAkF;IAClF,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC;CAC1D;AAID,eAAO,MAAM,gBAAgB,EAAE,SAAS,eAAe,
|
|
1
|
+
{"version":3,"file":"CapabilityIndex.d.ts","sourceRoot":"","sources":["../../src/server/CapabilityIndex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,yEAAyE;AACzE,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,YAAY,CAAC;IAClB,iFAAiF;IACjF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kFAAkF;IAClF,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC;CAC1D;AAID,eAAO,MAAM,gBAAgB,EAAE,SAAS,eAAe,EA4rBtD,CAAC;AAsCF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CA0D/E,CAAC;AAIF;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAUzD;AAED,mEAAmE;AACnE,wBAAgB,sBAAsB,IAAI,GAAG,CAAC,MAAM,CAAC,CAEpD;AAED,sEAAsE;AACtE,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,oBAAoB,GAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMzB"}
|
|
@@ -469,6 +469,17 @@ export const CAPABILITY_INDEX = [
|
|
|
469
469
|
],
|
|
470
470
|
}),
|
|
471
471
|
},
|
|
472
|
+
{
|
|
473
|
+
key: 'codexUsage',
|
|
474
|
+
prefixes: ['/codex'],
|
|
475
|
+
description: 'Codex usage — the codex `/status` rate-limit windows (5h + weekly) read from the on-disk rollout stream; no interactive TUI. Read-only.',
|
|
476
|
+
build: () => ({
|
|
477
|
+
enabled: true,
|
|
478
|
+
endpoints: [
|
|
479
|
+
'GET /codex/usage — freshest codex account rate-limit snapshot (primary 5h + secondary weekly windows; used/remaining percent, resets, plan, reached-type)',
|
|
480
|
+
],
|
|
481
|
+
}),
|
|
482
|
+
},
|
|
472
483
|
{
|
|
473
484
|
key: 'frameworkIssues',
|
|
474
485
|
prefixes: ['/framework-issues'],
|