@evermore.work/adapter-codex-local 2026.509.0-canary.0

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.
Files changed (107) hide show
  1. package/dist/cli/format-event.d.ts +2 -0
  2. package/dist/cli/format-event.d.ts.map +1 -0
  3. package/dist/cli/format-event.js +213 -0
  4. package/dist/cli/format-event.js.map +1 -0
  5. package/dist/cli/index.d.ts +2 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +2 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/cli/quota-probe.d.ts +3 -0
  10. package/dist/cli/quota-probe.d.ts.map +1 -0
  11. package/dist/cli/quota-probe.js +97 -0
  12. package/dist/cli/quota-probe.js.map +1 -0
  13. package/dist/index.d.ts +17 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +83 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/server/codex-args.d.ts +11 -0
  18. package/dist/server/codex-args.d.ts.map +1 -0
  19. package/dist/server/codex-args.js +55 -0
  20. package/dist/server/codex-args.js.map +1 -0
  21. package/dist/server/codex-args.test.d.ts +2 -0
  22. package/dist/server/codex-args.test.d.ts.map +1 -0
  23. package/dist/server/codex-args.test.js +63 -0
  24. package/dist/server/codex-args.test.js.map +1 -0
  25. package/dist/server/codex-home.d.ts +15 -0
  26. package/dist/server/codex-home.d.ts.map +1 -0
  27. package/dist/server/codex-home.js +107 -0
  28. package/dist/server/codex-home.js.map +1 -0
  29. package/dist/server/execute.d.ts +15 -0
  30. package/dist/server/execute.d.ts.map +1 -0
  31. package/dist/server/execute.js +669 -0
  32. package/dist/server/execute.js.map +1 -0
  33. package/dist/server/execute.remote.test.d.ts +2 -0
  34. package/dist/server/execute.remote.test.d.ts.map +1 -0
  35. package/dist/server/execute.remote.test.js +382 -0
  36. package/dist/server/execute.remote.test.js.map +1 -0
  37. package/dist/server/index.d.ts +8 -0
  38. package/dist/server/index.d.ts.map +1 -0
  39. package/dist/server/index.js +57 -0
  40. package/dist/server/index.js.map +1 -0
  41. package/dist/server/parse.d.ts +22 -0
  42. package/dist/server/parse.d.ts.map +1 -0
  43. package/dist/server/parse.js +213 -0
  44. package/dist/server/parse.js.map +1 -0
  45. package/dist/server/parse.test.d.ts +2 -0
  46. package/dist/server/parse.test.d.ts.map +1 -0
  47. package/dist/server/parse.test.js +107 -0
  48. package/dist/server/parse.test.js.map +1 -0
  49. package/dist/server/quota-spawn-error.test.d.ts +2 -0
  50. package/dist/server/quota-spawn-error.test.d.ts.map +1 -0
  51. package/dist/server/quota-spawn-error.test.js +77 -0
  52. package/dist/server/quota-spawn-error.test.js.map +1 -0
  53. package/dist/server/quota.d.ts +64 -0
  54. package/dist/server/quota.d.ts.map +1 -0
  55. package/dist/server/quota.js +432 -0
  56. package/dist/server/quota.js.map +1 -0
  57. package/dist/server/skills.d.ts +8 -0
  58. package/dist/server/skills.d.ts.map +1 -0
  59. package/dist/server/skills.js +65 -0
  60. package/dist/server/skills.js.map +1 -0
  61. package/dist/server/test.d.ts +3 -0
  62. package/dist/server/test.d.ts.map +1 -0
  63. package/dist/server/test.js +259 -0
  64. package/dist/server/test.js.map +1 -0
  65. package/dist/ui/build-config.d.ts +3 -0
  66. package/dist/ui/build-config.d.ts.map +1 -0
  67. package/dist/ui/build-config.js +113 -0
  68. package/dist/ui/build-config.js.map +1 -0
  69. package/dist/ui/build-config.test.d.ts +2 -0
  70. package/dist/ui/build-config.test.d.ts.map +1 -0
  71. package/dist/ui/build-config.test.js +49 -0
  72. package/dist/ui/build-config.test.js.map +1 -0
  73. package/dist/ui/index.d.ts +3 -0
  74. package/dist/ui/index.d.ts.map +1 -0
  75. package/dist/ui/index.js +3 -0
  76. package/dist/ui/index.js.map +1 -0
  77. package/dist/ui/parse-stdout.d.ts +3 -0
  78. package/dist/ui/parse-stdout.d.ts.map +1 -0
  79. package/dist/ui/parse-stdout.js +261 -0
  80. package/dist/ui/parse-stdout.js.map +1 -0
  81. package/dist/ui/parse-stdout.test.d.ts +2 -0
  82. package/dist/ui/parse-stdout.test.d.ts.map +1 -0
  83. package/dist/ui/parse-stdout.test.js +77 -0
  84. package/dist/ui/parse-stdout.test.js.map +1 -0
  85. package/package.json +55 -0
  86. package/skills/diagnose-why-work-stopped/SKILL.md +161 -0
  87. package/skills/evermore/SKILL.md +366 -0
  88. package/skills/evermore/references/api-reference.md +899 -0
  89. package/skills/evermore/references/company-skills.md +193 -0
  90. package/skills/evermore/references/issue-workspaces.md +80 -0
  91. package/skills/evermore/references/routines.md +187 -0
  92. package/skills/evermore/references/workflows.md +141 -0
  93. package/skills/evermore-converting-plans-to-tasks/SKILL.md +42 -0
  94. package/skills/evermore-create-agent/SKILL.md +163 -0
  95. package/skills/evermore-create-agent/references/agent-instruction-templates.md +123 -0
  96. package/skills/evermore-create-agent/references/agents/coder.md +64 -0
  97. package/skills/evermore-create-agent/references/agents/qa.md +88 -0
  98. package/skills/evermore-create-agent/references/agents/securityengineer.md +135 -0
  99. package/skills/evermore-create-agent/references/agents/uxdesigner.md +115 -0
  100. package/skills/evermore-create-agent/references/api-reference.md +110 -0
  101. package/skills/evermore-create-agent/references/baseline-role-guide.md +168 -0
  102. package/skills/evermore-create-agent/references/draft-review-checklist.md +95 -0
  103. package/skills/evermore-create-plugin/SKILL.md +101 -0
  104. package/skills/evermore-dev/SKILL.md +267 -0
  105. package/skills/para-memory-files/SKILL.md +104 -0
  106. package/skills/para-memory-files/references/schemas.md +35 -0
  107. package/skills/terminal-bench-loop/SKILL.md +236 -0
@@ -0,0 +1,213 @@
1
+ import { asString, asNumber, parseObject, parseJson, } from "@evermore.work/adapter-utils/server-utils";
2
+ const CODEX_TRANSIENT_UPSTREAM_RE = /(?:we(?:'|’)re\s+currently\s+experiencing\s+high\s+demand|temporary\s+errors|rate[-\s]?limit(?:ed)?|too\s+many\s+requests|\b429\b|server\s+overloaded|service\s+unavailable|try\s+again\s+later)/i;
3
+ const CODEX_REMOTE_COMPACTION_RE = /remote\s+compact\s+task/i;
4
+ const CODEX_USAGE_LIMIT_RE = /you(?:'|’)ve hit your usage limit for .+\.\s+switch to another model now,\s+or try again at\s+([^.!\n]+)(?:[.!]|\n|$)/i;
5
+ export function parseCodexJsonl(stdout) {
6
+ let sessionId = null;
7
+ let finalMessage = null;
8
+ let errorMessage = null;
9
+ const usage = {
10
+ inputTokens: 0,
11
+ cachedInputTokens: 0,
12
+ outputTokens: 0,
13
+ };
14
+ for (const rawLine of stdout.split(/\r?\n/)) {
15
+ const line = rawLine.trim();
16
+ if (!line)
17
+ continue;
18
+ const event = parseJson(line);
19
+ if (!event)
20
+ continue;
21
+ const type = asString(event.type, "");
22
+ if (type === "thread.started") {
23
+ sessionId = asString(event.thread_id, sessionId ?? "") || sessionId;
24
+ continue;
25
+ }
26
+ if (type === "error") {
27
+ const msg = asString(event.message, "").trim();
28
+ if (msg)
29
+ errorMessage = msg;
30
+ continue;
31
+ }
32
+ if (type === "item.completed") {
33
+ const item = parseObject(event.item);
34
+ if (asString(item.type, "") === "agent_message") {
35
+ const text = asString(item.text, "");
36
+ if (text)
37
+ finalMessage = text;
38
+ }
39
+ continue;
40
+ }
41
+ if (type === "turn.completed") {
42
+ const usageObj = parseObject(event.usage);
43
+ usage.inputTokens = asNumber(usageObj.input_tokens, usage.inputTokens);
44
+ usage.cachedInputTokens = asNumber(usageObj.cached_input_tokens, usage.cachedInputTokens);
45
+ usage.outputTokens = asNumber(usageObj.output_tokens, usage.outputTokens);
46
+ continue;
47
+ }
48
+ if (type === "turn.failed") {
49
+ const err = parseObject(event.error);
50
+ const msg = asString(err.message, "").trim();
51
+ if (msg)
52
+ errorMessage = msg;
53
+ }
54
+ }
55
+ return {
56
+ sessionId,
57
+ summary: finalMessage?.trim() ?? "",
58
+ usage,
59
+ errorMessage,
60
+ };
61
+ }
62
+ export function isCodexUnknownSessionError(stdout, stderr) {
63
+ const haystack = `${stdout}\n${stderr}`
64
+ .split(/\r?\n/)
65
+ .map((line) => line.trim())
66
+ .filter(Boolean)
67
+ .join("\n");
68
+ return /unknown (session|thread)|session .* not found|thread .* not found|conversation .* not found|missing rollout path for thread|state db missing rollout path|no rollout found for thread id/i.test(haystack);
69
+ }
70
+ function buildCodexErrorHaystack(input) {
71
+ return [
72
+ input.errorMessage ?? "",
73
+ input.stdout ?? "",
74
+ input.stderr ?? "",
75
+ ]
76
+ .join("\n")
77
+ .split(/\r?\n/)
78
+ .map((line) => line.trim())
79
+ .filter(Boolean)
80
+ .join("\n");
81
+ }
82
+ function readTimeZoneParts(date, timeZone) {
83
+ const values = new Map(new Intl.DateTimeFormat("en-US", {
84
+ timeZone,
85
+ hourCycle: "h23",
86
+ year: "numeric",
87
+ month: "2-digit",
88
+ day: "2-digit",
89
+ hour: "2-digit",
90
+ minute: "2-digit",
91
+ }).formatToParts(date).map((part) => [part.type, part.value]));
92
+ return {
93
+ year: Number.parseInt(values.get("year") ?? "", 10),
94
+ month: Number.parseInt(values.get("month") ?? "", 10),
95
+ day: Number.parseInt(values.get("day") ?? "", 10),
96
+ hour: Number.parseInt(values.get("hour") ?? "", 10),
97
+ minute: Number.parseInt(values.get("minute") ?? "", 10),
98
+ };
99
+ }
100
+ function normalizeResetTimeZone(timeZoneHint) {
101
+ const normalized = timeZoneHint?.trim();
102
+ if (!normalized)
103
+ return null;
104
+ if (/^(?:utc|gmt)$/i.test(normalized))
105
+ return "UTC";
106
+ try {
107
+ new Intl.DateTimeFormat("en-US", { timeZone: normalized }).format(new Date(0));
108
+ return normalized;
109
+ }
110
+ catch {
111
+ return null;
112
+ }
113
+ }
114
+ function dateFromTimeZoneWallClock(input) {
115
+ let candidate = new Date(Date.UTC(input.year, input.month - 1, input.day, input.hour, input.minute, 0, 0));
116
+ const targetUtc = Date.UTC(input.year, input.month - 1, input.day, input.hour, input.minute, 0, 0);
117
+ for (let attempt = 0; attempt < 4; attempt += 1) {
118
+ const actual = readTimeZoneParts(candidate, input.timeZone);
119
+ const actualUtc = Date.UTC(actual.year, actual.month - 1, actual.day, actual.hour, actual.minute, 0, 0);
120
+ const offsetMs = targetUtc - actualUtc;
121
+ if (offsetMs === 0)
122
+ break;
123
+ candidate = new Date(candidate.getTime() + offsetMs);
124
+ }
125
+ const verified = readTimeZoneParts(candidate, input.timeZone);
126
+ if (verified.year !== input.year ||
127
+ verified.month !== input.month ||
128
+ verified.day !== input.day ||
129
+ verified.hour !== input.hour ||
130
+ verified.minute !== input.minute) {
131
+ return null;
132
+ }
133
+ return candidate;
134
+ }
135
+ function nextClockTimeInTimeZone(input) {
136
+ const timeZone = normalizeResetTimeZone(input.timeZoneHint);
137
+ if (!timeZone)
138
+ return null;
139
+ const nowParts = readTimeZoneParts(input.now, timeZone);
140
+ let retryAt = dateFromTimeZoneWallClock({
141
+ year: nowParts.year,
142
+ month: nowParts.month,
143
+ day: nowParts.day,
144
+ hour: input.hour,
145
+ minute: input.minute,
146
+ timeZone,
147
+ });
148
+ if (!retryAt)
149
+ return null;
150
+ if (retryAt.getTime() <= input.now.getTime()) {
151
+ const nextDay = new Date(Date.UTC(nowParts.year, nowParts.month - 1, nowParts.day + 1, 0, 0, 0, 0));
152
+ retryAt = dateFromTimeZoneWallClock({
153
+ year: nextDay.getUTCFullYear(),
154
+ month: nextDay.getUTCMonth() + 1,
155
+ day: nextDay.getUTCDate(),
156
+ hour: input.hour,
157
+ minute: input.minute,
158
+ timeZone,
159
+ });
160
+ }
161
+ return retryAt;
162
+ }
163
+ function parseLocalClockTime(clockText, now) {
164
+ const normalized = clockText.trim();
165
+ const match = normalized.match(/^(\d{1,2})(?::(\d{2}))?\s*([ap])\.?\s*m\.?(?:\s*\(([^)]+)\)|\s+([A-Z]{2,5}))?$/i);
166
+ if (!match)
167
+ return null;
168
+ const hour12 = Number.parseInt(match[1] ?? "", 10);
169
+ const minute = Number.parseInt(match[2] ?? "0", 10);
170
+ if (!Number.isInteger(hour12) || hour12 < 1 || hour12 > 12)
171
+ return null;
172
+ if (!Number.isInteger(minute) || minute < 0 || minute > 59)
173
+ return null;
174
+ let hour24 = hour12 % 12;
175
+ if ((match[3] ?? "").toLowerCase() === "p")
176
+ hour24 += 12;
177
+ const timeZoneHint = match[4] ?? match[5];
178
+ if (timeZoneHint) {
179
+ const explicitRetryAt = nextClockTimeInTimeZone({
180
+ now,
181
+ hour: hour24,
182
+ minute,
183
+ timeZoneHint,
184
+ });
185
+ if (explicitRetryAt)
186
+ return explicitRetryAt;
187
+ }
188
+ const retryAt = new Date(now);
189
+ retryAt.setHours(hour24, minute, 0, 0);
190
+ if (retryAt.getTime() <= now.getTime()) {
191
+ retryAt.setDate(retryAt.getDate() + 1);
192
+ }
193
+ return retryAt;
194
+ }
195
+ export function extractCodexRetryNotBefore(input, now = new Date()) {
196
+ const haystack = buildCodexErrorHaystack(input);
197
+ const usageLimitMatch = haystack.match(CODEX_USAGE_LIMIT_RE);
198
+ if (!usageLimitMatch)
199
+ return null;
200
+ return parseLocalClockTime(usageLimitMatch[1] ?? "", now);
201
+ }
202
+ export function isCodexTransientUpstreamError(input) {
203
+ const haystack = buildCodexErrorHaystack(input);
204
+ if (extractCodexRetryNotBefore(input) != null)
205
+ return true;
206
+ if (!CODEX_TRANSIENT_UPSTREAM_RE.test(haystack))
207
+ return false;
208
+ // Keep automatic retries scoped to the observed remote-compaction/high-demand
209
+ // failure shape, plus explicit usage-limit windows that tell us when retrying
210
+ // becomes safe again.
211
+ return CODEX_REMOTE_COMPACTION_RE.test(haystack) || /high\s+demand|temporary\s+errors/i.test(haystack);
212
+ }
213
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/server/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parse.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.test.d.ts","sourceRoot":"","sources":["../../src/server/parse.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,107 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { extractCodexRetryNotBefore, isCodexTransientUpstreamError, isCodexUnknownSessionError, parseCodexJsonl, } from "./parse.js";
3
+ describe("parseCodexJsonl", () => {
4
+ it("captures session id, assistant summary, usage, and error message", () => {
5
+ const stdout = [
6
+ JSON.stringify({ type: "thread.started", thread_id: "thread_123" }),
7
+ JSON.stringify({
8
+ type: "item.completed",
9
+ item: { type: "agent_message", text: "Recovered response" },
10
+ }),
11
+ JSON.stringify({
12
+ type: "turn.completed",
13
+ usage: { input_tokens: 10, cached_input_tokens: 2, output_tokens: 4 },
14
+ }),
15
+ JSON.stringify({ type: "turn.failed", error: { message: "resume failed" } }),
16
+ ].join("\n");
17
+ expect(parseCodexJsonl(stdout)).toEqual({
18
+ sessionId: "thread_123",
19
+ summary: "Recovered response",
20
+ usage: {
21
+ inputTokens: 10,
22
+ cachedInputTokens: 2,
23
+ outputTokens: 4,
24
+ },
25
+ errorMessage: "resume failed",
26
+ });
27
+ });
28
+ it("uses the last agent message as the summary when commentary updates precede the final answer", () => {
29
+ const stdout = [
30
+ JSON.stringify({ type: "thread.started", thread_id: "thread_123" }),
31
+ JSON.stringify({
32
+ type: "item.completed",
33
+ item: { type: "reasoning", text: "Checking the heartbeat procedure" },
34
+ }),
35
+ JSON.stringify({
36
+ type: "item.completed",
37
+ item: { type: "agent_message", text: "I’m checking out the issue and reading the docs now." },
38
+ }),
39
+ JSON.stringify({
40
+ type: "item.completed",
41
+ item: { type: "agent_message", text: "Fixed the issue and verified the targeted tests pass." },
42
+ }),
43
+ JSON.stringify({
44
+ type: "turn.completed",
45
+ usage: { input_tokens: 10, cached_input_tokens: 2, output_tokens: 4 },
46
+ }),
47
+ ].join("\n");
48
+ expect(parseCodexJsonl(stdout)).toEqual({
49
+ sessionId: "thread_123",
50
+ summary: "Fixed the issue and verified the targeted tests pass.",
51
+ usage: {
52
+ inputTokens: 10,
53
+ cachedInputTokens: 2,
54
+ outputTokens: 4,
55
+ },
56
+ errorMessage: null,
57
+ });
58
+ });
59
+ });
60
+ describe("isCodexUnknownSessionError", () => {
61
+ it("detects the current missing-rollout thread error", () => {
62
+ expect(isCodexUnknownSessionError("", "Error: thread/resume: thread/resume failed: no rollout found for thread id d448e715-7607-4bcc-91fc-7a3c0c5a9632")).toBe(true);
63
+ });
64
+ it("still detects existing stale-session wordings", () => {
65
+ expect(isCodexUnknownSessionError("unknown thread id", "")).toBe(true);
66
+ expect(isCodexUnknownSessionError("", "state db missing rollout path for thread abc")).toBe(true);
67
+ });
68
+ it("does not classify unrelated Codex failures as stale sessions", () => {
69
+ expect(isCodexUnknownSessionError("", "model overloaded")).toBe(false);
70
+ });
71
+ });
72
+ describe("isCodexTransientUpstreamError", () => {
73
+ it("classifies the remote-compaction high-demand failure as transient upstream", () => {
74
+ expect(isCodexTransientUpstreamError({
75
+ errorMessage: "Error running remote compact task: We're currently experiencing high demand, which may cause temporary errors.",
76
+ })).toBe(true);
77
+ expect(isCodexTransientUpstreamError({
78
+ stderr: "We're currently experiencing high demand, which may cause temporary errors.",
79
+ })).toBe(true);
80
+ });
81
+ it("classifies usage-limit windows as transient and extracts the retry time", () => {
82
+ const errorMessage = "You've hit your usage limit for GPT-5.3-Codex-Spark. Switch to another model now, or try again at 11:31 PM.";
83
+ const now = new Date(2026, 3, 22, 22, 29, 2);
84
+ expect(isCodexTransientUpstreamError({ errorMessage })).toBe(true);
85
+ expect(extractCodexRetryNotBefore({ errorMessage }, now)?.getTime()).toBe(new Date(2026, 3, 22, 23, 31, 0, 0).getTime());
86
+ });
87
+ it("parses explicit timezone hints on usage-limit retry windows", () => {
88
+ const errorMessage = "You've hit your usage limit for GPT-5.3-Codex-Spark. Switch to another model now, or try again at 11:31 PM (America/Chicago).";
89
+ const now = new Date("2026-04-23T03:29:02.000Z");
90
+ expect(extractCodexRetryNotBefore({ errorMessage }, now)?.toISOString()).toBe("2026-04-23T04:31:00.000Z");
91
+ });
92
+ it("does not classify deterministic compaction errors as transient", () => {
93
+ expect(isCodexTransientUpstreamError({
94
+ errorMessage: [
95
+ "Error running remote compact task: {",
96
+ ' "error": {',
97
+ ' "message": "Unknown parameter: \'prompt_cache_retention\'.",',
98
+ ' "type": "invalid_request_error",',
99
+ ' "param": "prompt_cache_retention",',
100
+ ' "code": "unknown_parameter"',
101
+ " }",
102
+ "}",
103
+ ].join("\n"),
104
+ })).toBe(false);
105
+ });
106
+ });
107
+ //# sourceMappingURL=parse.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.test.js","sourceRoot":"","sources":["../../src/server/parse.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=quota-spawn-error.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-spawn-error.test.d.ts","sourceRoot":"","sources":["../../src/server/quota-spawn-error.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ import { EventEmitter } from "node:events";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
6
+ const { mockSpawn } = vi.hoisted(() => ({
7
+ mockSpawn: vi.fn(),
8
+ }));
9
+ vi.mock("node:child_process", async (importOriginal) => {
10
+ const cp = await importOriginal();
11
+ return {
12
+ ...cp,
13
+ spawn: (...args) => mockSpawn(...args),
14
+ };
15
+ });
16
+ import { getQuotaWindows } from "./quota.js";
17
+ function createChildThatErrorsOnMicrotask(err) {
18
+ const child = new EventEmitter();
19
+ const stream = Object.assign(new EventEmitter(), {
20
+ setEncoding: () => { },
21
+ });
22
+ Object.assign(child, {
23
+ stdout: stream,
24
+ stderr: Object.assign(new EventEmitter(), { setEncoding: () => { } }),
25
+ stdin: { write: vi.fn(), end: vi.fn() },
26
+ kill: vi.fn(),
27
+ });
28
+ queueMicrotask(() => {
29
+ child.emit("error", err);
30
+ });
31
+ return child;
32
+ }
33
+ describe("CodexRpcClient spawn failures", () => {
34
+ let previousCodexHome;
35
+ let isolatedCodexHome;
36
+ beforeEach(() => {
37
+ mockSpawn.mockReset();
38
+ // After the RPC path fails, getQuotaWindows() calls readCodexToken() which
39
+ // reads $CODEX_HOME/auth.json (default ~/.codex). Point CODEX_HOME at an
40
+ // empty temp directory so we never hit real host auth or the WHAM network.
41
+ previousCodexHome = process.env.CODEX_HOME;
42
+ isolatedCodexHome = fs.mkdtempSync(path.join(os.tmpdir(), "evermore-codex-spawn-test-"));
43
+ process.env.CODEX_HOME = isolatedCodexHome;
44
+ });
45
+ afterEach(() => {
46
+ if (isolatedCodexHome) {
47
+ try {
48
+ fs.rmSync(isolatedCodexHome, { recursive: true, force: true });
49
+ }
50
+ catch {
51
+ /* ignore */
52
+ }
53
+ isolatedCodexHome = undefined;
54
+ }
55
+ if (previousCodexHome === undefined) {
56
+ delete process.env.CODEX_HOME;
57
+ }
58
+ else {
59
+ process.env.CODEX_HOME = previousCodexHome;
60
+ }
61
+ });
62
+ it("does not crash the process when codex is missing; getQuotaWindows returns ok: false", async () => {
63
+ const enoent = Object.assign(new Error("spawn codex ENOENT"), {
64
+ code: "ENOENT",
65
+ errno: -2,
66
+ syscall: "spawn codex",
67
+ path: "codex",
68
+ });
69
+ mockSpawn.mockImplementation(() => createChildThatErrorsOnMicrotask(enoent));
70
+ const result = await getQuotaWindows();
71
+ expect(result.ok).toBe(false);
72
+ expect(result.windows).toEqual([]);
73
+ expect(result.error).toContain("Codex app-server");
74
+ expect(result.error).toContain("spawn codex ENOENT");
75
+ });
76
+ });
77
+ //# sourceMappingURL=quota-spawn-error.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-spawn-error.test.js","sourceRoot":"","sources":["../../src/server/quota-spawn-error.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import type { ProviderQuotaResult, QuotaWindow } from "@evermore.work/adapter-utils";
2
+ export declare function codexHomeDir(): string;
3
+ export interface CodexAuthInfo {
4
+ accessToken: string;
5
+ accountId: string | null;
6
+ refreshToken: string | null;
7
+ idToken: string | null;
8
+ email: string | null;
9
+ planType: string | null;
10
+ lastRefresh: string | null;
11
+ }
12
+ export declare function readCodexAuthInfo(codexHome?: string): Promise<CodexAuthInfo | null>;
13
+ export declare function readCodexToken(): Promise<{
14
+ token: string;
15
+ accountId: string | null;
16
+ } | null>;
17
+ /**
18
+ * Map a window duration in seconds to a human-readable label.
19
+ * Falls back to the provided fallback string when seconds is null/undefined.
20
+ */
21
+ export declare function secondsToWindowLabel(seconds: number | null | undefined, fallback: string): string;
22
+ /** fetch with an abort-based timeout so a hanging provider api doesn't block the response indefinitely */
23
+ export declare function fetchWithTimeout(url: string, init: RequestInit, ms?: number): Promise<Response>;
24
+ export declare function fetchCodexQuota(token: string, accountId: string | null): Promise<QuotaWindow[]>;
25
+ interface CodexRpcWindow {
26
+ usedPercent?: number | null;
27
+ windowDurationMins?: number | null;
28
+ resetsAt?: number | null;
29
+ }
30
+ interface CodexRpcCredits {
31
+ hasCredits?: boolean | null;
32
+ unlimited?: boolean | null;
33
+ balance?: string | number | null;
34
+ }
35
+ interface CodexRpcLimit {
36
+ limitId?: string | null;
37
+ limitName?: string | null;
38
+ primary?: CodexRpcWindow | null;
39
+ secondary?: CodexRpcWindow | null;
40
+ credits?: CodexRpcCredits | null;
41
+ planType?: string | null;
42
+ }
43
+ interface CodexRpcRateLimitsResult {
44
+ rateLimits?: CodexRpcLimit | null;
45
+ rateLimitsByLimitId?: Record<string, CodexRpcLimit> | null;
46
+ }
47
+ interface CodexRpcAccountResult {
48
+ account?: {
49
+ type?: string | null;
50
+ email?: string | null;
51
+ planType?: string | null;
52
+ } | null;
53
+ requiresOpenaiAuth?: boolean | null;
54
+ }
55
+ export interface CodexRpcQuotaSnapshot {
56
+ windows: QuotaWindow[];
57
+ email: string | null;
58
+ planType: string | null;
59
+ }
60
+ export declare function mapCodexRpcQuota(result: CodexRpcRateLimitsResult, account?: CodexRpcAccountResult | null): CodexRpcQuotaSnapshot;
61
+ export declare function fetchCodexRpcQuota(): Promise<CodexRpcQuotaSnapshot>;
62
+ export declare function getQuotaWindows(): Promise<ProviderQuotaResult>;
63
+ export {};
64
+ //# sourceMappingURL=quota.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota.d.ts","sourceRoot":"","sources":["../../src/server/quota.ts"],"names":[],"mappings":"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"}