codex-multi-auth 2.22.0 → 2.24.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.
- package/.codex-plugin/plugin.json +9 -9
- package/LICENSE +21 -21
- package/README.md +159 -150
- package/assets/codex-multi-auth-icon.svg +39 -39
- package/assets/readme-hero.svg +31 -31
- package/config/README.md +31 -31
- package/config/codex-legacy.json +1021 -1021
- package/config/codex-modern.json +347 -347
- package/config/minimal-codex.json +15 -15
- package/config/schema/config.schema.json +8 -0
- package/dist/index.js +33 -10
- package/dist/lib/account-policy.d.ts +2 -0
- package/dist/lib/account-policy.js +3 -1
- package/dist/lib/accounts/rate-limits.d.ts +6 -0
- package/dist/lib/accounts/rate-limits.js +14 -1
- package/dist/lib/accounts.d.ts +6 -1
- package/dist/lib/accounts.js +33 -8
- package/dist/lib/api-route-store.d.ts +1 -0
- package/dist/lib/api-route-store.js +2 -1
- package/dist/lib/auth/account-access.js +2 -1
- package/dist/lib/auth/auth.js +3 -2
- package/dist/lib/auth/device-auth.js +2 -1
- package/dist/lib/auth/http.d.ts +1 -0
- package/dist/lib/auth/http.js +1 -0
- package/dist/lib/auth/token-utils.d.ts +5 -0
- package/dist/lib/auth/token-utils.js +10 -0
- package/dist/lib/codex-manager/account-manager-commands.js +1 -0
- package/dist/lib/codex-manager/commands/account.js +15 -0
- package/dist/lib/codex-manager/commands/locale.d.ts +12 -0
- package/dist/lib/codex-manager/commands/locale.js +25 -0
- package/dist/lib/codex-manager/commands/resets.js +18 -5
- package/dist/lib/codex-manager/commands/status.d.ts +4 -0
- package/dist/lib/codex-manager/commands/status.js +476 -5
- package/dist/lib/codex-manager/commands/workspace.d.ts +4 -2
- package/dist/lib/codex-manager/commands/workspace.js +33 -2
- package/dist/lib/codex-manager/help.js +5 -3
- package/dist/lib/codex-manager.js +112 -30
- package/dist/lib/config.js +3 -0
- package/dist/lib/constants.d.ts +2 -0
- package/dist/lib/constants.js +2 -0
- package/dist/lib/context-budget-response.js +8 -8
- package/dist/lib/context-overflow.js +10 -10
- package/dist/lib/locale.d.ts +7 -0
- package/dist/lib/locale.js +35 -0
- package/dist/lib/oauth-success.html +125 -125
- package/dist/lib/policy/runtime-policy-cache.js +1 -1
- package/dist/lib/policy/runtime-policy.d.ts +1 -0
- package/dist/lib/policy/runtime-policy.js +4 -0
- package/dist/lib/preemptive-quota-scheduler.js +12 -3
- package/dist/lib/prompts/codex-host-bridge.js +138 -138
- package/dist/lib/prompts/codex.js +79 -79
- package/dist/lib/quota-cache.d.ts +4 -0
- package/dist/lib/quota-probe.js +2 -1
- package/dist/lib/quota-readiness.d.ts +1 -1
- package/dist/lib/quota-readiness.js +9 -2
- package/dist/lib/request/proxy-fetch.d.ts +5 -0
- package/dist/lib/request/proxy-fetch.js +37 -0
- package/dist/lib/request/rate-limit-decision.js +1 -1
- package/dist/lib/request/url-rewriting.js +17 -0
- package/dist/lib/runtime/account-model-catalog.d.ts +2 -0
- package/dist/lib/runtime/account-model-catalog.js +7 -2
- package/dist/lib/runtime/account-reset-credits.d.ts +11 -2
- package/dist/lib/runtime/account-reset-credits.js +35 -12
- package/dist/lib/runtime/app-bind.d.ts +4 -1
- package/dist/lib/runtime/app-bind.js +63 -3
- package/dist/lib/runtime/automatic-account-checks.js +6 -5
- package/dist/lib/runtime/automatic-subscription-checks.js +4 -3
- package/dist/lib/runtime/model-discovery-status.js +2 -2
- package/dist/lib/runtime/reset-credit-routing.d.ts +11 -3
- package/dist/lib/runtime/reset-credit-routing.js +66 -21
- package/dist/lib/runtime/reset-credits.d.ts +31 -7
- package/dist/lib/runtime/reset-credits.js +135 -28
- package/dist/lib/runtime/responses-websocket.d.ts +30 -0
- package/dist/lib/runtime/responses-websocket.js +243 -29
- package/dist/lib/runtime/rotation-account-selection.d.ts +5 -4
- package/dist/lib/runtime/rotation-proxy-state.d.ts +3 -0
- package/dist/lib/runtime/rotation-server-types.d.ts +4 -1
- package/dist/lib/runtime/subscription-quota-order.d.ts +1 -0
- package/dist/lib/runtime/subscription-quota-order.js +7 -3
- package/dist/lib/runtime/workspace-model-scopes.d.ts +2 -0
- package/dist/lib/runtime/workspace-model-scopes.js +14 -4
- package/dist/lib/runtime-rotation-proxy.js +138 -38
- package/dist/lib/schemas.d.ts +5 -0
- package/dist/lib/schemas.js +1 -0
- package/dist/lib/storage/snapshot-merge.js +15 -4
- package/dist/lib/web-dashboard-html.d.ts +1 -0
- package/dist/lib/web-dashboard-html.js +66 -0
- package/dist/lib/web-dashboard.d.ts +36 -0
- package/dist/lib/web-dashboard.js +322 -0
- package/node_modules/@codex-ai/plugin/dist/index.d.ts +2 -2
- package/node_modules/@codex-ai/plugin/dist/index.js +2 -2
- package/node_modules/@codex-ai/plugin/dist/tool.d.ts +42 -42
- package/node_modules/@codex-ai/plugin/dist/tool.js +29 -29
- package/node_modules/@codex-ai/plugin/package.json +9 -9
- package/node_modules/@codex-ai/sdk/dist/index.d.ts +4 -4
- package/node_modules/@codex-ai/sdk/dist/index.js +2 -2
- package/node_modules/@codex-ai/sdk/package.json +8 -8
- package/package.json +209 -207
- package/scripts/codex-app-launcher.js +653 -653
- package/scripts/codex-app-router.js +446 -402
- package/scripts/codex-bin-resolver.js +332 -332
- package/scripts/codex-multi-auth.js +65 -65
- package/scripts/codex-routing.js +63 -62
- package/scripts/codex.js +7143 -7006
- package/scripts/install-codex-auth-utils.js +213 -213
- package/scripts/mcodex.js +367 -367
- package/scripts/postinstall.js +114 -114
- package/scripts/preuninstall.js +265 -265
- package/skills/codex-auth-setup/SKILL.md +73 -73
- package/vendor/codex-ai-plugin/dist/index.d.ts +2 -2
- package/vendor/codex-ai-plugin/dist/index.js +2 -2
- package/vendor/codex-ai-plugin/dist/tool.d.ts +42 -42
- package/vendor/codex-ai-plugin/dist/tool.js +29 -29
- package/vendor/codex-ai-plugin/package.json +9 -9
- package/vendor/codex-ai-sdk/dist/index.d.ts +4 -4
- package/vendor/codex-ai-sdk/dist/index.js +2 -2
- package/vendor/codex-ai-sdk/package.json +8 -8
|
@@ -25,6 +25,7 @@ export interface RuntimePolicyDecision {
|
|
|
25
25
|
blockedAccountReasons?: Record<number, string>;
|
|
26
26
|
scoreBoostByAccount: Record<number, number>;
|
|
27
27
|
priorityByAccount?: Record<number, number>;
|
|
28
|
+
emergencyAccountIndexes?: Set<number>;
|
|
28
29
|
budgetEvaluations: BudgetGuardEvaluation[];
|
|
29
30
|
}
|
|
30
31
|
export interface RuntimePolicyState {
|
|
@@ -101,6 +101,7 @@ export async function evaluateRuntimePolicy(input) {
|
|
|
101
101
|
const blockedAccountReasons = {};
|
|
102
102
|
const scoreBoostByAccount = {};
|
|
103
103
|
const priorityByAccount = {};
|
|
104
|
+
const emergencyAccountIndexes = new Set();
|
|
104
105
|
const profile = input.state.project.profile;
|
|
105
106
|
if (profile?.modelDenylist.length && matchesModel(profile.modelDenylist, input.model)) {
|
|
106
107
|
reasons.push("routing profile denies requested model");
|
|
@@ -131,6 +132,8 @@ export async function evaluateRuntimePolicy(input) {
|
|
|
131
132
|
}, account.index);
|
|
132
133
|
const accountPolicy = input.state.accountPolicies.accounts[accountKey];
|
|
133
134
|
priorityByAccount[account.index] = accountPolicy?.priority ?? 1;
|
|
135
|
+
if (accountPolicy?.emergencyOnly)
|
|
136
|
+
emergencyAccountIndexes.add(account.index);
|
|
134
137
|
let boost = 0;
|
|
135
138
|
if (accountPolicy?.paused) {
|
|
136
139
|
blockedAccountIndexes.add(account.index);
|
|
@@ -186,6 +189,7 @@ export async function evaluateRuntimePolicy(input) {
|
|
|
186
189
|
blockedAccountReasons,
|
|
187
190
|
scoreBoostByAccount,
|
|
188
191
|
priorityByAccount,
|
|
192
|
+
emergencyAccountIndexes,
|
|
189
193
|
budgetEvaluations,
|
|
190
194
|
};
|
|
191
195
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MAX_RATE_LIMIT_DELAY_MS } from "./constants.js";
|
|
1
|
+
import { MAX_RATE_LIMIT_DELAY_MS, RATE_LIMIT_CACHE_TTL_MS } from "./constants.js";
|
|
2
2
|
import { quotaLeftPercentFromUsed } from "./quota-readiness.js";
|
|
3
3
|
const DEFAULT_REMAINING_PERCENT_THRESHOLD = 5;
|
|
4
4
|
const DEFAULT_MAX_DEFERRAL_MS = 2 * 60 * 60_000;
|
|
@@ -219,6 +219,11 @@ export class PreemptiveQuotaScheduler {
|
|
|
219
219
|
const snapshot = this.snapshots.get(key);
|
|
220
220
|
if (!snapshot)
|
|
221
221
|
return { defer: false, waitMs: 0 };
|
|
222
|
+
const cacheRemainingMs = snapshot.updatedAt + RATE_LIMIT_CACHE_TTL_MS - now;
|
|
223
|
+
if (cacheRemainingMs <= 0) {
|
|
224
|
+
this.snapshots.delete(key);
|
|
225
|
+
return { defer: false, waitMs: 0 };
|
|
226
|
+
}
|
|
222
227
|
// For a 429 deferral, only count a window whose reset is genuinely a
|
|
223
228
|
// rate-limit / exhaustion window. A window carrying a healthy usedPercent
|
|
224
229
|
// (e.g. a weekly secondary at 30% from a prior 200 snapshot) is NOT the
|
|
@@ -239,7 +244,7 @@ export class PreemptiveQuotaScheduler {
|
|
|
239
244
|
.filter((value) => value > 0);
|
|
240
245
|
const longestWait = waitCandidates.length > 0 ? Math.max(...waitCandidates) : 0;
|
|
241
246
|
if (snapshot.status === 429 && longestWait > 0) {
|
|
242
|
-
const bounded = Math.min(longestWait, this.maxDeferralMs);
|
|
247
|
+
const bounded = Math.min(longestWait, this.maxDeferralMs, cacheRemainingMs);
|
|
243
248
|
if (bounded > 0) {
|
|
244
249
|
return { defer: true, waitMs: bounded, reason: "rate-limit" };
|
|
245
250
|
}
|
|
@@ -260,7 +265,11 @@ export class PreemptiveQuotaScheduler {
|
|
|
260
265
|
? getNearExhaustedWait(snapshot.secondary)
|
|
261
266
|
: 0);
|
|
262
267
|
if (nearExhaustedWait > 0) {
|
|
263
|
-
return {
|
|
268
|
+
return {
|
|
269
|
+
defer: true,
|
|
270
|
+
waitMs: Math.min(nearExhaustedWait, cacheRemainingMs),
|
|
271
|
+
reason: "quota-near-exhaustion",
|
|
272
|
+
};
|
|
264
273
|
}
|
|
265
274
|
return { defer: false, waitMs: 0 };
|
|
266
275
|
}
|
|
@@ -7,142 +7,142 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Token Count: ~450 tokens (~90% reduction vs full host prompt)
|
|
9
9
|
*/
|
|
10
|
-
export const CODEX_HOST_BRIDGE = `# Codex Host Bridge
|
|
11
|
-
|
|
12
|
-
You are running Codex through a host terminal coding runtime. The host provides specific tools to help you work efficiently.
|
|
13
|
-
|
|
14
|
-
## CRITICAL: Tool Usage
|
|
15
|
-
|
|
16
|
-
<critical_rule priority="0">
|
|
17
|
-
apply_patch/applyPatch are Codex names, but host tool names vary by version.
|
|
18
|
-
- Inspect the actual tool list before editing.
|
|
19
|
-
- If \`edit\` exists: use \`edit\` for precise in-place string replacements and hashline edits.
|
|
20
|
-
- If \`edit\` is absent and \`apply_patch\` exists: use \`apply_patch\` for those precise/hashline edits in this plugin.
|
|
21
|
-
- For diff-style or multi-line structural edits: use \`patch\` if available, otherwise use \`apply_patch\`.
|
|
22
|
-
- In this plugin, \`edit\` / \`apply_patch\` also support hashline refs (\`lineRef\`, \`endLineRef\`, \`operation\`, \`content\`)
|
|
23
|
-
</critical_rule>
|
|
24
|
-
|
|
25
|
-
<critical_rule priority="0">
|
|
26
|
-
UPDATE_PLAN DOES NOT EXIST -> USE "todowrite" INSTEAD
|
|
27
|
-
- NEVER use: update_plan, updatePlan, read_plan, readPlan
|
|
28
|
-
- ALWAYS use: todowrite for task/plan updates, todoread to read plans
|
|
29
|
-
- Before plan operations: Verify you're using "todowrite", NOT "update_plan"
|
|
30
|
-
</critical_rule>
|
|
31
|
-
|
|
32
|
-
## Available Host Tools
|
|
33
|
-
|
|
34
|
-
**File Operations:**
|
|
35
|
-
- \`write\` - Create new files
|
|
36
|
-
- Overwriting existing files requires a prior Read in this session; default to ASCII unless the file already uses Unicode.
|
|
37
|
-
- \`edit\` - Modify existing files with string replacement (version-dependent)
|
|
38
|
-
- Requires a prior Read in this session; preserve exact indentation; ensure \`oldString\` uniquely matches or use \`replaceAll\`; edit fails if ambiguous or missing.
|
|
39
|
-
- Never pass unresolved template placeholders in \`oldString\` (e.g. \`\${TARGET_SNIPPET}\`); \`oldString\` must be literal text copied from the current file.
|
|
40
|
-
- For complex multi-line changes: break into multiple sequential edit calls, each with unique oldString context.
|
|
41
|
-
- \`apply_patch\` - May be the edit/patch tool name in newer host builds (version-dependent)
|
|
42
|
-
- In this plugin, \`apply_patch\` also accepts hashline edit args (\`path\`, \`lineRef\`, \`endLineRef\`, \`operation\`, \`content\`) when \`edit\` is not available.
|
|
43
|
-
- \`hashline_read\` - Read file with hashline refs (\`L<line>#<hash>\`) for deterministic edits
|
|
44
|
-
- \`patch\` - Apply diff-style patches for multi-line updates (version-dependent)
|
|
45
|
-
- \`read\` - Read file contents
|
|
46
|
-
|
|
47
|
-
Note: Tool naming is version-dependent. If \`edit\` is unavailable but \`apply_patch\` exists, use \`apply_patch\`.
|
|
48
|
-
|
|
49
|
-
When available, prefer hashline workflow for reliability:
|
|
50
|
-
1. Call \`hashline_read\` for target file and capture refs.
|
|
51
|
-
2. Call \`edit\` or \`apply_patch\` with \`lineRef\` (and optional \`endLineRef\`) plus \`operation\` and \`content\`.
|
|
52
|
-
3. Use legacy \`oldString\` / \`newString\` only when hashline refs are unavailable, and only with literal file text (no template placeholders).
|
|
53
|
-
|
|
54
|
-
**Search/Discovery:**
|
|
55
|
-
- \`grep\` - Search file contents (tool, not bash grep); use \`include\` to filter patterns; set \`path\` only when not searching workspace root; for cross-file match counts use bash with \`rg\`.
|
|
56
|
-
- \`glob\` - Find files by pattern; defaults to workspace cwd unless \`path\` is set.
|
|
57
|
-
- \`list\` - List directories (requires absolute paths)
|
|
58
|
-
|
|
59
|
-
**Execution:**
|
|
60
|
-
- \`bash\` - Run shell commands
|
|
61
|
-
- No workdir parameter; do not include it in tool calls.
|
|
62
|
-
- Always include a short description for the command.
|
|
63
|
-
- Do not use cd; use absolute paths in commands.
|
|
64
|
-
- Quote paths containing spaces with double quotes.
|
|
65
|
-
- Chain multiple commands with ';' or '&&'; avoid newlines.
|
|
66
|
-
- Use Grep/Glob tools for searches; only use bash with \`rg\` when you need counts or advanced features.
|
|
67
|
-
- Do not use \`ls\`/\`cat\` in bash; use \`list\`/\`read\` tools instead.
|
|
68
|
-
- For deletions (rm), verify by listing parent dir with \`list\`.
|
|
69
|
-
|
|
70
|
-
**Network:**
|
|
71
|
-
- \`webfetch\` - Fetch web content
|
|
72
|
-
- Use fully-formed URLs (http/https; http auto-upgrades to https).
|
|
73
|
-
- Always set \`format\` to one of: text | markdown | html; prefer markdown unless otherwise required.
|
|
74
|
-
- Read-only; short cache window.
|
|
75
|
-
|
|
76
|
-
**Task Management:**
|
|
77
|
-
- \`todowrite\` - Manage tasks/plans (REPLACES update_plan)
|
|
78
|
-
- \`todoread\` - Read current plan
|
|
79
|
-
|
|
80
|
-
## Substitution Rules
|
|
81
|
-
|
|
82
|
-
Base instruction says: You MUST use instead:
|
|
83
|
-
apply_patch -> patch (preferred if available), otherwise edit/apply_patch based on actual tool list
|
|
84
|
-
update_plan -> todowrite
|
|
85
|
-
read_plan -> todoread
|
|
86
|
-
|
|
87
|
-
**Path Usage:** Use per-tool conventions to avoid conflicts:
|
|
88
|
-
- Tool calls: \`read\`, \`edit\`, \`write\`, \`list\` require absolute paths.
|
|
89
|
-
- Searches: \`grep\`/\`glob\` default to the workspace cwd; prefer relative include patterns; set \`path\` only when a different root is needed.
|
|
90
|
-
- Presentation: In assistant messages, show workspace-relative paths; use absolute paths only inside tool calls.
|
|
91
|
-
- Tool schema overrides general path preferences-do not convert required absolute paths to relative.
|
|
92
|
-
|
|
93
|
-
## Verification Checklist
|
|
94
|
-
|
|
95
|
-
Before file/plan modifications:
|
|
96
|
-
1. Am I using the actual available edit tool name (\`edit\`, \`patch\`, or \`apply_patch\`)?
|
|
97
|
-
2. Am I using "todowrite" NOT "update_plan"?
|
|
98
|
-
3. Is this tool in the approved list above?
|
|
99
|
-
4. Am I following each tool's path requirements?
|
|
100
|
-
|
|
101
|
-
If ANY answer is NO -> STOP and correct before proceeding.
|
|
102
|
-
|
|
103
|
-
## Host Working Style
|
|
104
|
-
|
|
105
|
-
**Communication:**
|
|
106
|
-
- Send brief preambles (8-12 words) before tool calls, building on prior context
|
|
107
|
-
- Provide progress updates during longer tasks
|
|
108
|
-
|
|
109
|
-
**Execution:**
|
|
110
|
-
- Keep working autonomously until query is fully resolved before yielding
|
|
111
|
-
- Don't return to user with partial solutions
|
|
112
|
-
|
|
113
|
-
**Code Approach:**
|
|
114
|
-
- New projects: Be ambitious and creative
|
|
115
|
-
- Existing codebases: Surgical precision - modify only what's requested unless explicitly instructed to do otherwise
|
|
116
|
-
|
|
117
|
-
**Testing:**
|
|
118
|
-
- If tests exist: Start specific to your changes, then broader validation
|
|
119
|
-
|
|
120
|
-
## Advanced Tools
|
|
121
|
-
|
|
122
|
-
**Task Tool (Sub-Agents):**
|
|
123
|
-
- Use the Task tool (functions.task) to launch sub-agents
|
|
124
|
-
- Check the Task tool description for current agent types and their capabilities
|
|
125
|
-
- Useful for complex analysis, specialized workflows, or tasks requiring isolated context
|
|
126
|
-
- The agent list is dynamically generated - refer to tool schema for available agents
|
|
127
|
-
|
|
128
|
-
**Parallelization:**
|
|
129
|
-
- When multiple independent tool calls are needed, use multi_tool_use.parallel to run them concurrently.
|
|
130
|
-
- Reserve sequential calls for ordered or data-dependent steps.
|
|
131
|
-
|
|
132
|
-
**MCP Tools:**
|
|
133
|
-
- Model Context Protocol servers provide additional capabilities
|
|
134
|
-
- MCP tools are prefixed: \`mcp__<server-name>__<tool-name>\`
|
|
135
|
-
- Check your available tools for MCP integrations
|
|
136
|
-
- Use when the tool's functionality matches your task needs
|
|
137
|
-
|
|
138
|
-
## What Remains from Codex
|
|
139
|
-
|
|
140
|
-
Sandbox policies, approval mechanisms, final answer formatting, git commit protocols, and file reference formats all follow Codex instructions. In approval policy "never", never request escalations.
|
|
141
|
-
|
|
142
|
-
## Approvals & Safety
|
|
143
|
-
- Assume workspace-write filesystem, network enabled, approval on-failure unless explicitly stated otherwise.
|
|
144
|
-
- When a command fails due to sandboxing or permissions, retry with escalated permissions if allowed by policy, including a one-line justification.
|
|
145
|
-
- Treat destructive commands (e.g., \`rm\`, \`git reset --hard\`) as requiring explicit user request or approval.
|
|
146
|
-
- Never run \`git reset --hard\`, \`git checkout --\`, or force deletes unless the user explicitly asked for that exact action.
|
|
147
|
-
- \`request_user_input\` is Plan-mode only; do not call it in Default mode.
|
|
10
|
+
export const CODEX_HOST_BRIDGE = `# Codex Host Bridge
|
|
11
|
+
|
|
12
|
+
You are running Codex through a host terminal coding runtime. The host provides specific tools to help you work efficiently.
|
|
13
|
+
|
|
14
|
+
## CRITICAL: Tool Usage
|
|
15
|
+
|
|
16
|
+
<critical_rule priority="0">
|
|
17
|
+
apply_patch/applyPatch are Codex names, but host tool names vary by version.
|
|
18
|
+
- Inspect the actual tool list before editing.
|
|
19
|
+
- If \`edit\` exists: use \`edit\` for precise in-place string replacements and hashline edits.
|
|
20
|
+
- If \`edit\` is absent and \`apply_patch\` exists: use \`apply_patch\` for those precise/hashline edits in this plugin.
|
|
21
|
+
- For diff-style or multi-line structural edits: use \`patch\` if available, otherwise use \`apply_patch\`.
|
|
22
|
+
- In this plugin, \`edit\` / \`apply_patch\` also support hashline refs (\`lineRef\`, \`endLineRef\`, \`operation\`, \`content\`)
|
|
23
|
+
</critical_rule>
|
|
24
|
+
|
|
25
|
+
<critical_rule priority="0">
|
|
26
|
+
UPDATE_PLAN DOES NOT EXIST -> USE "todowrite" INSTEAD
|
|
27
|
+
- NEVER use: update_plan, updatePlan, read_plan, readPlan
|
|
28
|
+
- ALWAYS use: todowrite for task/plan updates, todoread to read plans
|
|
29
|
+
- Before plan operations: Verify you're using "todowrite", NOT "update_plan"
|
|
30
|
+
</critical_rule>
|
|
31
|
+
|
|
32
|
+
## Available Host Tools
|
|
33
|
+
|
|
34
|
+
**File Operations:**
|
|
35
|
+
- \`write\` - Create new files
|
|
36
|
+
- Overwriting existing files requires a prior Read in this session; default to ASCII unless the file already uses Unicode.
|
|
37
|
+
- \`edit\` - Modify existing files with string replacement (version-dependent)
|
|
38
|
+
- Requires a prior Read in this session; preserve exact indentation; ensure \`oldString\` uniquely matches or use \`replaceAll\`; edit fails if ambiguous or missing.
|
|
39
|
+
- Never pass unresolved template placeholders in \`oldString\` (e.g. \`\${TARGET_SNIPPET}\`); \`oldString\` must be literal text copied from the current file.
|
|
40
|
+
- For complex multi-line changes: break into multiple sequential edit calls, each with unique oldString context.
|
|
41
|
+
- \`apply_patch\` - May be the edit/patch tool name in newer host builds (version-dependent)
|
|
42
|
+
- In this plugin, \`apply_patch\` also accepts hashline edit args (\`path\`, \`lineRef\`, \`endLineRef\`, \`operation\`, \`content\`) when \`edit\` is not available.
|
|
43
|
+
- \`hashline_read\` - Read file with hashline refs (\`L<line>#<hash>\`) for deterministic edits
|
|
44
|
+
- \`patch\` - Apply diff-style patches for multi-line updates (version-dependent)
|
|
45
|
+
- \`read\` - Read file contents
|
|
46
|
+
|
|
47
|
+
Note: Tool naming is version-dependent. If \`edit\` is unavailable but \`apply_patch\` exists, use \`apply_patch\`.
|
|
48
|
+
|
|
49
|
+
When available, prefer hashline workflow for reliability:
|
|
50
|
+
1. Call \`hashline_read\` for target file and capture refs.
|
|
51
|
+
2. Call \`edit\` or \`apply_patch\` with \`lineRef\` (and optional \`endLineRef\`) plus \`operation\` and \`content\`.
|
|
52
|
+
3. Use legacy \`oldString\` / \`newString\` only when hashline refs are unavailable, and only with literal file text (no template placeholders).
|
|
53
|
+
|
|
54
|
+
**Search/Discovery:**
|
|
55
|
+
- \`grep\` - Search file contents (tool, not bash grep); use \`include\` to filter patterns; set \`path\` only when not searching workspace root; for cross-file match counts use bash with \`rg\`.
|
|
56
|
+
- \`glob\` - Find files by pattern; defaults to workspace cwd unless \`path\` is set.
|
|
57
|
+
- \`list\` - List directories (requires absolute paths)
|
|
58
|
+
|
|
59
|
+
**Execution:**
|
|
60
|
+
- \`bash\` - Run shell commands
|
|
61
|
+
- No workdir parameter; do not include it in tool calls.
|
|
62
|
+
- Always include a short description for the command.
|
|
63
|
+
- Do not use cd; use absolute paths in commands.
|
|
64
|
+
- Quote paths containing spaces with double quotes.
|
|
65
|
+
- Chain multiple commands with ';' or '&&'; avoid newlines.
|
|
66
|
+
- Use Grep/Glob tools for searches; only use bash with \`rg\` when you need counts or advanced features.
|
|
67
|
+
- Do not use \`ls\`/\`cat\` in bash; use \`list\`/\`read\` tools instead.
|
|
68
|
+
- For deletions (rm), verify by listing parent dir with \`list\`.
|
|
69
|
+
|
|
70
|
+
**Network:**
|
|
71
|
+
- \`webfetch\` - Fetch web content
|
|
72
|
+
- Use fully-formed URLs (http/https; http auto-upgrades to https).
|
|
73
|
+
- Always set \`format\` to one of: text | markdown | html; prefer markdown unless otherwise required.
|
|
74
|
+
- Read-only; short cache window.
|
|
75
|
+
|
|
76
|
+
**Task Management:**
|
|
77
|
+
- \`todowrite\` - Manage tasks/plans (REPLACES update_plan)
|
|
78
|
+
- \`todoread\` - Read current plan
|
|
79
|
+
|
|
80
|
+
## Substitution Rules
|
|
81
|
+
|
|
82
|
+
Base instruction says: You MUST use instead:
|
|
83
|
+
apply_patch -> patch (preferred if available), otherwise edit/apply_patch based on actual tool list
|
|
84
|
+
update_plan -> todowrite
|
|
85
|
+
read_plan -> todoread
|
|
86
|
+
|
|
87
|
+
**Path Usage:** Use per-tool conventions to avoid conflicts:
|
|
88
|
+
- Tool calls: \`read\`, \`edit\`, \`write\`, \`list\` require absolute paths.
|
|
89
|
+
- Searches: \`grep\`/\`glob\` default to the workspace cwd; prefer relative include patterns; set \`path\` only when a different root is needed.
|
|
90
|
+
- Presentation: In assistant messages, show workspace-relative paths; use absolute paths only inside tool calls.
|
|
91
|
+
- Tool schema overrides general path preferences-do not convert required absolute paths to relative.
|
|
92
|
+
|
|
93
|
+
## Verification Checklist
|
|
94
|
+
|
|
95
|
+
Before file/plan modifications:
|
|
96
|
+
1. Am I using the actual available edit tool name (\`edit\`, \`patch\`, or \`apply_patch\`)?
|
|
97
|
+
2. Am I using "todowrite" NOT "update_plan"?
|
|
98
|
+
3. Is this tool in the approved list above?
|
|
99
|
+
4. Am I following each tool's path requirements?
|
|
100
|
+
|
|
101
|
+
If ANY answer is NO -> STOP and correct before proceeding.
|
|
102
|
+
|
|
103
|
+
## Host Working Style
|
|
104
|
+
|
|
105
|
+
**Communication:**
|
|
106
|
+
- Send brief preambles (8-12 words) before tool calls, building on prior context
|
|
107
|
+
- Provide progress updates during longer tasks
|
|
108
|
+
|
|
109
|
+
**Execution:**
|
|
110
|
+
- Keep working autonomously until query is fully resolved before yielding
|
|
111
|
+
- Don't return to user with partial solutions
|
|
112
|
+
|
|
113
|
+
**Code Approach:**
|
|
114
|
+
- New projects: Be ambitious and creative
|
|
115
|
+
- Existing codebases: Surgical precision - modify only what's requested unless explicitly instructed to do otherwise
|
|
116
|
+
|
|
117
|
+
**Testing:**
|
|
118
|
+
- If tests exist: Start specific to your changes, then broader validation
|
|
119
|
+
|
|
120
|
+
## Advanced Tools
|
|
121
|
+
|
|
122
|
+
**Task Tool (Sub-Agents):**
|
|
123
|
+
- Use the Task tool (functions.task) to launch sub-agents
|
|
124
|
+
- Check the Task tool description for current agent types and their capabilities
|
|
125
|
+
- Useful for complex analysis, specialized workflows, or tasks requiring isolated context
|
|
126
|
+
- The agent list is dynamically generated - refer to tool schema for available agents
|
|
127
|
+
|
|
128
|
+
**Parallelization:**
|
|
129
|
+
- When multiple independent tool calls are needed, use multi_tool_use.parallel to run them concurrently.
|
|
130
|
+
- Reserve sequential calls for ordered or data-dependent steps.
|
|
131
|
+
|
|
132
|
+
**MCP Tools:**
|
|
133
|
+
- Model Context Protocol servers provide additional capabilities
|
|
134
|
+
- MCP tools are prefixed: \`mcp__<server-name>__<tool-name>\`
|
|
135
|
+
- Check your available tools for MCP integrations
|
|
136
|
+
- Use when the tool's functionality matches your task needs
|
|
137
|
+
|
|
138
|
+
## What Remains from Codex
|
|
139
|
+
|
|
140
|
+
Sandbox policies, approval mechanisms, final answer formatting, git commit protocols, and file reference formats all follow Codex instructions. In approval policy "never", never request escalations.
|
|
141
|
+
|
|
142
|
+
## Approvals & Safety
|
|
143
|
+
- Assume workspace-write filesystem, network enabled, approval on-failure unless explicitly stated otherwise.
|
|
144
|
+
- When a command fails due to sandboxing or permissions, retry with escalated permissions if allowed by policy, including a one-line justification.
|
|
145
|
+
- Treat destructive commands (e.g., \`rm\`, \`git reset --hard\`) as requiring explicit user request or approval.
|
|
146
|
+
- Never run \`git reset --hard\`, \`git checkout --\`, or force deletes unless the user explicitly asked for that exact action.
|
|
147
|
+
- \`request_user_input\` is Plan-mode only; do not call it in Default mode.
|
|
148
148
|
- When uncertain, prefer non-destructive verification first (e.g., confirm file existence with \`list\`, then delete with \`bash\`).`;
|
|
@@ -381,83 +381,83 @@ export function prewarmCodexInstructions(models = []) {
|
|
|
381
381
|
/**
|
|
382
382
|
* Tool remapping instructions for host runtime tools
|
|
383
383
|
*/
|
|
384
|
-
export const TOOL_REMAP_MESSAGE = `<user_instructions priority="0">
|
|
385
|
-
<environment_override priority="0">
|
|
386
|
-
YOU ARE IN A DIFFERENT ENVIRONMENT. These instructions override ALL previous tool references.
|
|
387
|
-
</environment_override>
|
|
388
|
-
|
|
389
|
-
<tool_replacements priority="0">
|
|
390
|
-
<critical_rule priority="0">
|
|
391
|
-
apply_patch/applyPatch are Codex names, but host tool names vary by version.
|
|
392
|
-
- Inspect the actual tool list before editing.
|
|
393
|
-
- If edit exists: use edit for precise in-place string replacements and hashline edits.
|
|
394
|
-
- If edit is absent and apply_patch exists: use apply_patch for those precise/hashline edits in this plugin.
|
|
395
|
-
- For diff-style or multi-line structural edits: use patch if available, otherwise use apply_patch.
|
|
396
|
-
- In this plugin, edit/apply_patch support hashline refs (lineRef, endLineRef, operation, content)
|
|
397
|
-
</critical_rule>
|
|
398
|
-
|
|
399
|
-
<critical_rule priority="0">
|
|
400
|
-
UPDATE_PLAN DOES NOT EXIST -> USE "todowrite" INSTEAD
|
|
401
|
-
- NEVER use: update_plan, updatePlan
|
|
402
|
-
- ALWAYS use: todowrite for ALL task/plan operations
|
|
403
|
-
- Use todoread to read current plan
|
|
404
|
-
- Before plan operations: Verify you're using "todowrite", NOT "update_plan"
|
|
405
|
-
</critical_rule>
|
|
406
|
-
</tool_replacements>
|
|
407
|
-
|
|
408
|
-
<available_tools priority="0">
|
|
409
|
-
File Operations:
|
|
410
|
-
- write - Create new files (if available)
|
|
411
|
-
- edit - Modify existing files with string replacement (version-dependent)
|
|
412
|
-
- oldString must be literal text from the current file; never pass unresolved placeholders like \${TARGET_SNIPPET}
|
|
413
|
-
- apply_patch - May be the edit/patch tool name in newer host builds (version-dependent)
|
|
414
|
-
- hashline_read - Read lines with hashline refs (L<line>#<hash>) for deterministic edits
|
|
415
|
-
- patch - Apply diff patches (version-dependent)
|
|
416
|
-
- read - Read file contents
|
|
417
|
-
|
|
418
|
-
Search/Discovery:
|
|
419
|
-
- grep - Search file contents
|
|
420
|
-
- glob - Find files by pattern
|
|
421
|
-
- list - List directories (if available)
|
|
422
|
-
|
|
423
|
-
Execution:
|
|
424
|
-
- bash - Run shell commands
|
|
425
|
-
|
|
426
|
-
Network:
|
|
427
|
-
- webfetch - Fetch web content
|
|
428
|
-
|
|
429
|
-
Task Management:
|
|
430
|
-
- todowrite - Manage tasks/plans (REPLACES update_plan)
|
|
431
|
-
- todoread - Read current plan
|
|
432
|
-
</available_tools>
|
|
433
|
-
|
|
434
|
-
<substitution_rules priority="0">
|
|
435
|
-
Base instruction says: You MUST use instead:
|
|
436
|
-
apply_patch -> patch (preferred if available), otherwise edit/apply_patch based on actual tool list
|
|
437
|
-
update_plan -> todowrite
|
|
438
|
-
read_plan -> todoread
|
|
439
|
-
absolute paths -> relative paths
|
|
440
|
-
</substitution_rules>
|
|
441
|
-
|
|
442
|
-
<verification_checklist priority="0">
|
|
443
|
-
Before file/plan modifications:
|
|
444
|
-
1. Am I using the actual available edit tool name (edit, patch, or apply_patch)?
|
|
445
|
-
2. Am I using "todowrite" NOT "update_plan"?
|
|
446
|
-
3. Is this tool in the approved list above?
|
|
447
|
-
4. Am I using relative paths?
|
|
448
|
-
|
|
449
|
-
If ANY answer is NO -> STOP and correct before proceeding.
|
|
450
|
-
</verification_checklist>
|
|
451
|
-
|
|
452
|
-
<hashline_workflow priority="0">
|
|
453
|
-
When hashline_read is available:
|
|
454
|
-
1. call hashline_read on the file
|
|
455
|
-
2. edit/apply_patch using lineRef/endLineRef + operation + content
|
|
456
|
-
3. use oldString/newString only as fallback, and only with literal file text (no template placeholders)
|
|
457
|
-
</hashline_workflow>
|
|
458
|
-
|
|
459
|
-
<safety_rules priority="0">
|
|
460
|
-
- Never run destructive git commands (\`git reset --hard\`, \`git checkout --\`) unless explicitly requested by the user.
|
|
461
|
-
- Never call \`request_user_input\` unless collaboration mode is explicitly Plan mode.
|
|
462
|
-
</safety_rules>
|
|
384
|
+
export const TOOL_REMAP_MESSAGE = `<user_instructions priority="0">
|
|
385
|
+
<environment_override priority="0">
|
|
386
|
+
YOU ARE IN A DIFFERENT ENVIRONMENT. These instructions override ALL previous tool references.
|
|
387
|
+
</environment_override>
|
|
388
|
+
|
|
389
|
+
<tool_replacements priority="0">
|
|
390
|
+
<critical_rule priority="0">
|
|
391
|
+
apply_patch/applyPatch are Codex names, but host tool names vary by version.
|
|
392
|
+
- Inspect the actual tool list before editing.
|
|
393
|
+
- If edit exists: use edit for precise in-place string replacements and hashline edits.
|
|
394
|
+
- If edit is absent and apply_patch exists: use apply_patch for those precise/hashline edits in this plugin.
|
|
395
|
+
- For diff-style or multi-line structural edits: use patch if available, otherwise use apply_patch.
|
|
396
|
+
- In this plugin, edit/apply_patch support hashline refs (lineRef, endLineRef, operation, content)
|
|
397
|
+
</critical_rule>
|
|
398
|
+
|
|
399
|
+
<critical_rule priority="0">
|
|
400
|
+
UPDATE_PLAN DOES NOT EXIST -> USE "todowrite" INSTEAD
|
|
401
|
+
- NEVER use: update_plan, updatePlan
|
|
402
|
+
- ALWAYS use: todowrite for ALL task/plan operations
|
|
403
|
+
- Use todoread to read current plan
|
|
404
|
+
- Before plan operations: Verify you're using "todowrite", NOT "update_plan"
|
|
405
|
+
</critical_rule>
|
|
406
|
+
</tool_replacements>
|
|
407
|
+
|
|
408
|
+
<available_tools priority="0">
|
|
409
|
+
File Operations:
|
|
410
|
+
- write - Create new files (if available)
|
|
411
|
+
- edit - Modify existing files with string replacement (version-dependent)
|
|
412
|
+
- oldString must be literal text from the current file; never pass unresolved placeholders like \${TARGET_SNIPPET}
|
|
413
|
+
- apply_patch - May be the edit/patch tool name in newer host builds (version-dependent)
|
|
414
|
+
- hashline_read - Read lines with hashline refs (L<line>#<hash>) for deterministic edits
|
|
415
|
+
- patch - Apply diff patches (version-dependent)
|
|
416
|
+
- read - Read file contents
|
|
417
|
+
|
|
418
|
+
Search/Discovery:
|
|
419
|
+
- grep - Search file contents
|
|
420
|
+
- glob - Find files by pattern
|
|
421
|
+
- list - List directories (if available)
|
|
422
|
+
|
|
423
|
+
Execution:
|
|
424
|
+
- bash - Run shell commands
|
|
425
|
+
|
|
426
|
+
Network:
|
|
427
|
+
- webfetch - Fetch web content
|
|
428
|
+
|
|
429
|
+
Task Management:
|
|
430
|
+
- todowrite - Manage tasks/plans (REPLACES update_plan)
|
|
431
|
+
- todoread - Read current plan
|
|
432
|
+
</available_tools>
|
|
433
|
+
|
|
434
|
+
<substitution_rules priority="0">
|
|
435
|
+
Base instruction says: You MUST use instead:
|
|
436
|
+
apply_patch -> patch (preferred if available), otherwise edit/apply_patch based on actual tool list
|
|
437
|
+
update_plan -> todowrite
|
|
438
|
+
read_plan -> todoread
|
|
439
|
+
absolute paths -> relative paths
|
|
440
|
+
</substitution_rules>
|
|
441
|
+
|
|
442
|
+
<verification_checklist priority="0">
|
|
443
|
+
Before file/plan modifications:
|
|
444
|
+
1. Am I using the actual available edit tool name (edit, patch, or apply_patch)?
|
|
445
|
+
2. Am I using "todowrite" NOT "update_plan"?
|
|
446
|
+
3. Is this tool in the approved list above?
|
|
447
|
+
4. Am I using relative paths?
|
|
448
|
+
|
|
449
|
+
If ANY answer is NO -> STOP and correct before proceeding.
|
|
450
|
+
</verification_checklist>
|
|
451
|
+
|
|
452
|
+
<hashline_workflow priority="0">
|
|
453
|
+
When hashline_read is available:
|
|
454
|
+
1. call hashline_read on the file
|
|
455
|
+
2. edit/apply_patch using lineRef/endLineRef + operation + content
|
|
456
|
+
3. use oldString/newString only as fallback, and only with literal file text (no template placeholders)
|
|
457
|
+
</hashline_workflow>
|
|
458
|
+
|
|
459
|
+
<safety_rules priority="0">
|
|
460
|
+
- Never run destructive git commands (\`git reset --hard\`, \`git checkout --\`) unless explicitly requested by the user.
|
|
461
|
+
- Never call \`request_user_input\` unless collaboration mode is explicitly Plan mode.
|
|
462
|
+
</safety_rules>
|
|
463
463
|
</user_instructions>`;
|
|
@@ -4,6 +4,10 @@ export interface QuotaCacheWindow {
|
|
|
4
4
|
resetAtMs?: number;
|
|
5
5
|
}
|
|
6
6
|
export interface QuotaCacheEntry {
|
|
7
|
+
/** Account-validated native usage permission; never inferred from percentages. */
|
|
8
|
+
ordinaryUsageAllowed?: boolean | null;
|
|
9
|
+
/** Native permission timestamp; header refreshes must not extend its lifetime. */
|
|
10
|
+
ordinaryUsageCheckedAt?: number;
|
|
7
11
|
primingCompleted?: boolean;
|
|
8
12
|
/** Completion/failure time, independent of the quota header observation. */
|
|
9
13
|
primingObservedAt?: number;
|
package/dist/lib/quota-probe.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CODEX_BASE_URL, MAX_RATE_LIMIT_DELAY_MS } from "./constants.js";
|
|
2
|
+
import { fetchWithProxy } from "./request/proxy-fetch.js";
|
|
2
3
|
import { createCodexHeaders, getUnsupportedCodexModelInfo } from "./request/fetch-helpers.js";
|
|
3
4
|
import { QUOTA_PROBE_MODEL_CHAIN, resolveProbeReasoningEffort, } from "./request/helpers/model-map.js";
|
|
4
5
|
import { CodexUnavailableError, isCodexUnavailableError } from "./errors.js";
|
|
@@ -367,7 +368,7 @@ export async function fetchCodexQuotaSnapshot(options) {
|
|
|
367
368
|
snapshot.diagnosticProbeRequests += 1;
|
|
368
369
|
snapshot.runtimeMetrics.diagnosticProbeRequests += 1;
|
|
369
370
|
});
|
|
370
|
-
response = await
|
|
371
|
+
response = await fetchWithProxy(`${CODEX_BASE_URL}/codex/responses`, {
|
|
371
372
|
method: "POST",
|
|
372
373
|
headers,
|
|
373
374
|
body: JSON.stringify(probeBody),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { QuotaCacheData, QuotaCacheEntry } from "./quota-cache.js";
|
|
2
2
|
import type { AccountMetadataV3 } from "./storage.js";
|
|
3
|
-
export type QuotaCacheAccountRef = Pick<AccountMetadataV3, "accountId" | "email" | "recordId" | "workspaces" | "currentWorkspaceIndex"> & Partial<Pick<AccountMetadataV3, "refreshToken" | "addedAt" | "accessToken">>;
|
|
3
|
+
export type QuotaCacheAccountRef = Pick<AccountMetadataV3, "accountId" | "email" | "recordId" | "workspaces" | "currentWorkspaceIndex"> & Partial<Pick<AccountMetadataV3, "refreshToken" | "addedAt" | "accessToken" | "codexCliMirror">>;
|
|
4
4
|
export declare function normalizeQuotaAccountId(value: string | undefined): string | null;
|
|
5
5
|
export declare function normalizeQuotaEmail(value: string | undefined): string | null;
|
|
6
6
|
export declare function hasUniqueQuotaAccountId(accounts: readonly QuotaCacheAccountRef[], account: QuotaCacheAccountRef): boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RATE_LIMIT_CACHE_TTL_MS } from "./constants.js";
|
|
2
|
+
import { extractAccountId, nativeWorkspaceIdentity } from "./auth/token-utils.js";
|
|
2
3
|
import { createHash } from "node:crypto";
|
|
3
4
|
import { resolveAccountRecordId } from "./storage/record-identity.js";
|
|
4
5
|
export function normalizeQuotaAccountId(value) {
|
|
@@ -89,6 +90,11 @@ export function isQuotaCacheEntryExhausted(entry, now = Date.now()) {
|
|
|
89
90
|
// Codex quota windows are cumulative gates: a 0% remaining active window blocks use
|
|
90
91
|
// even if another window still has quota left.
|
|
91
92
|
const updatedAt = entry?.updatedAt;
|
|
93
|
+
// Stale usage is unknown, not proof that the server still rejects requests.
|
|
94
|
+
if (typeof updatedAt === "number" &&
|
|
95
|
+
Number.isFinite(updatedAt) &&
|
|
96
|
+
now >= updatedAt + RATE_LIMIT_CACHE_TTL_MS)
|
|
97
|
+
return false;
|
|
92
98
|
return (quotaWindowIsExhausted(entry?.primary, now, updatedAt) ||
|
|
93
99
|
quotaWindowIsExhausted(entry?.secondary, now, updatedAt));
|
|
94
100
|
}
|
|
@@ -100,9 +106,10 @@ export function quotaWorkspaceKey(account, workspaceId) {
|
|
|
100
106
|
}
|
|
101
107
|
/** Display the selected workspace; callers routing another scope must pass that exact workspace. */
|
|
102
108
|
export function quotaWorkspaceId(account) {
|
|
103
|
-
|
|
109
|
+
const selectedId = account.workspaces?.length
|
|
104
110
|
? account.workspaces[account.currentWorkspaceIndex ?? 0]?.id.trim()
|
|
105
111
|
: account.accountId?.trim() || extractAccountId(account.accessToken);
|
|
112
|
+
return nativeWorkspaceIdentity({ access: account.accessToken, codexCliMirror: account.codexCliMirror }, selectedId);
|
|
106
113
|
}
|
|
107
114
|
/** Read exact-workspace quota, using legacy binding entries only for that binding. */
|
|
108
115
|
export function findQuotaCacheEntryForAccount(cache, account, accounts, emailFallbackState = buildQuotaEmailFallbackState(accounts), workspaceId = quotaWorkspaceId(account)) {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
type FetchInput = Parameters<typeof globalThis.fetch>[0];
|
|
2
|
+
type FetchInit = Parameters<typeof globalThis.fetch>[1];
|
|
3
|
+
export declare function setProxyFetchImpl(impl: typeof globalThis.fetch | null): void;
|
|
4
|
+
export declare function fetchWithProxy(input: FetchInput, init?: FetchInit): ReturnType<typeof globalThis.fetch>;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { fetch as undiciFetch } from "undici";
|
|
2
|
+
import { applyProxyCompatibleInit, extractRequestUrl, } from "./url-rewriting.js";
|
|
3
|
+
// Transport selection contract, in precedence order:
|
|
4
|
+
// 1. An implementation registered via setProxyFetchImpl (embedding contract;
|
|
5
|
+
// works regardless of when the host installs it).
|
|
6
|
+
// 2. A global fetch replaced after this module loaded, or a test double.
|
|
7
|
+
// 3. A global fetch installed before module load — honored when it is
|
|
8
|
+
// distinguishable from the platform fetch (Node's built-in is named
|
|
9
|
+
// "fetch"); hosts needing guaranteed interception use setProxyFetchImpl.
|
|
10
|
+
// 4. The package's Undici fetch, but only when the request carries a proxy
|
|
11
|
+
// dispatcher: Node 22's built-in fetch rejects the Undici 8 handler
|
|
12
|
+
// contract, so a proxied call needs the matching implementation.
|
|
13
|
+
// 5. The ambient global fetch for ordinary direct requests.
|
|
14
|
+
const initialGlobalFetch = globalThis.fetch;
|
|
15
|
+
let overrideFetch = null;
|
|
16
|
+
export function setProxyFetchImpl(impl) {
|
|
17
|
+
overrideFetch = impl;
|
|
18
|
+
}
|
|
19
|
+
function isTestDouble(fetchImpl) {
|
|
20
|
+
const candidate = fetchImpl;
|
|
21
|
+
return candidate._isMockFunction === true || candidate.mock !== undefined;
|
|
22
|
+
}
|
|
23
|
+
function isPlatformFetch(fetchImpl) {
|
|
24
|
+
return fetchImpl.name === "fetch" && !isTestDouble(fetchImpl);
|
|
25
|
+
}
|
|
26
|
+
export function fetchWithProxy(input, init) {
|
|
27
|
+
const url = extractRequestUrl(input);
|
|
28
|
+
const proxiedInit = applyProxyCompatibleInit(url, init);
|
|
29
|
+
const currentGlobalFetch = globalThis.fetch;
|
|
30
|
+
const baseFetch = overrideFetch ??
|
|
31
|
+
(currentGlobalFetch !== initialGlobalFetch || !isPlatformFetch(currentGlobalFetch)
|
|
32
|
+
? currentGlobalFetch
|
|
33
|
+
: proxiedInit.dispatcher
|
|
34
|
+
? undiciFetch
|
|
35
|
+
: currentGlobalFetch);
|
|
36
|
+
return baseFetch(input, proxiedInit);
|
|
37
|
+
}
|
|
@@ -181,7 +181,7 @@ const DEADLINE_SENTENCES = {
|
|
|
181
181
|
"available-again": (resetAt) => `the account is expected to be available again at ${resetAt}`,
|
|
182
182
|
"next-attempt": (resetAt) => `the next attempt is allowed at ${resetAt}`,
|
|
183
183
|
"cooldown-ends": (resetAt) => `the cooldown ends at ${resetAt}`,
|
|
184
|
-
"rate-limit-reset": (resetAt) => `the rate limit
|
|
184
|
+
"rate-limit-reset": (resetAt) => `the cached rate limit will be rechecked at ${resetAt}`,
|
|
185
185
|
};
|
|
186
186
|
/**
|
|
187
187
|
* Every cooldown variant is bounded by the same `coolingDownUntil` field, so
|