@agentchatham/cli 2.39.0 → 2.40.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/CLAUDE.md CHANGED
@@ -103,6 +103,40 @@ Rules:
103
103
  7. Create `src/providers/<name>/errors.ts` — export `create<Name>ErrorTracker()`,
104
104
  wire it into the adapter, and add the harness to `test/errors/conformance.test.ts`
105
105
 
106
+ ## File-backed credentials
107
+
108
+ Most harnesses take their credential as an env var and nothing else. A harness
109
+ whose credential is a *file* implements `ProviderAdapter.prepareCredentials(env)`,
110
+ which is called on every agent start (before `checkAuth`, so the preflight
111
+ inspects what a turn will actually use) and again before bootstrap scripts run —
112
+ with the child env there, not `process.env`, which is why it takes an env rather
113
+ than reading the ambient one.
114
+
115
+ Codex is the only one today (`providers/codex/authFile.ts`). Three rules its
116
+ implementation exists to keep, and any future one should copy:
117
+
118
+ - **Write on every start.** A start after a cold boot must not depend on a file
119
+ an earlier run left behind.
120
+ - **Remove what you wrote, and only that.** A credential disconnected in the
121
+ console must not leave the agent working off a stale file; a developer's own
122
+ `codex login` on their own host must survive. A marker file next to the
123
+ credential is what tells the two apart.
124
+ - **Decide precedence in one place.** `planCodexAuth` answers "which credential
125
+ would a turn use" for the writer, the preflight and the adapter alike — they
126
+ cannot disagree about it, and the adapter withholds `apiKey` on the strength of
127
+ the same answer that put the file on disk.
128
+
129
+ **Bumping `@openai/codex-sdk` requires re-measuring the harness.** Four
130
+ behaviours of the codex binary are load-bearing here and none of them is
131
+ guaranteed by an API: which credential wins when both are present, that an
132
+ expired `auth.json` still beats an API key, that Codex never writes back over
133
+ `auth.json`, and which fields the file must carry to load at all. Two of them
134
+ fail *silently and dangerously* if a future version changes them — a credential
135
+ that keeps working after the user disconnected it, or one that can no longer be
136
+ removed. `test/providers/codex/harnessAssumptions.test.ts` pins the version and
137
+ lists how to re-verify each; it fails when the pin moves, so the check happens at
138
+ the one moment someone is certainly looking.
139
+
106
140
  ## Error classification
107
141
 
108
142
  Each harness classifies its own errors in `src/providers/<name>/errors.ts`, because
package/README.md CHANGED
@@ -143,7 +143,29 @@ so land here too, tagged `[sdk]`.
143
143
 
144
144
  ### Codex
145
145
 
146
- Requires an OpenAI API key. Either set `OPENAI_API_KEY` or run `codex login` once (writes `~/.codex/auth.json`).
146
+ Two credentials, and an unexpired **Codex Token** wins over an API key.
147
+
148
+ - **`CODEX_AUTH_JSON` — the Codex Token.** The contents of a `~/.codex/auth.json`
149
+ produced by `codex login`, connected on the console's Models page, which
150
+ sanitises it in the browser and delivers it here as an ordinary secret. The CLI
151
+ writes it to `${CODEX_HOME:-~/.codex}/auth.json` (`0600`, in a `0700`
152
+ directory, atomically) on every agent start and before bootstrap runs, and
153
+ removes the file it wrote once the secret is gone or the token has expired —
154
+ otherwise the agent goes on working off a credential the user disconnected.
155
+ It runs Codex on the user's ChatGPT subscription instead of billing per token.
156
+
157
+ Its access token lives about 10 days and **is never refreshed**: the refresh
158
+ token is dropped in the browser before encryption, so we cannot rotate it even
159
+ by accident — a rotation is single-use and would invalidate every other copy,
160
+ including the one on the user's own laptop. The expiry is read from the access
161
+ token's own `exp`, and the last 5 minutes count as expired (Codex spends them
162
+ attempting a refresh that cannot succeed). When it lapses, the user re-pastes.
163
+
164
+ - **`OPENAI_API_KEY`** — used when no Codex Token is connected, or once it has
165
+ expired. Billed per request.
166
+
167
+ Locally, `codex login` on this host still works and is honoured when neither of
168
+ the two is set. A file the CLI did not write is never deleted.
147
169
 
148
170
  ### Claude
149
171