@zvada/agent-server 0.3.3 → 0.3.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.5
4
+
5
+ - Switching Codex ChatGPT accounts or API keys now recreates the native process
6
+ and resumes the same conversation. Native Codex keeps model WebSockets
7
+ authenticated as the account that opened them, so a login update alone could
8
+ keep using the previous account. Renewing a token for the same account remains
9
+ warm; no credential fields are added to the public protocol.
10
+
11
+ ## 0.3.4
12
+
13
+ - Update the managed Codex CLI and development SDK to 0.153.4. This clears
14
+ Astra's minimum CLI requirement (0.153.0); model access still depends on
15
+ the selected OpenAI account. The generated app-server protocol remains
16
+ compatible with host-managed ChatGPT authentication and the engine's
17
+ existing conversation, approval, and usage handling.
18
+
3
19
  ## 0.3.3
4
20
 
5
21
  - Embedded hosts can resolve Codex API keys or externally managed ChatGPT
package/docs/harnesses.md CHANGED
@@ -66,7 +66,7 @@ fresh access credentials, the callback must return the same ChatGPT account;
66
66
  the engine rejects mismatched identities and refreshes that outlive their turn.
67
67
  An absent previous-account hint resolves to the turn's selected account. No
68
68
  credentials or callbacks are added to `RunConfig` or the engine's public wire.
69
- The protocol was checked against Codex CLI 0.146.1 and the
69
+ The protocol was checked against Codex CLI 0.153.4 and the
70
70
  [official app-server authentication documentation](https://learn.chatgpt.com/docs/app-server#3c-log-in-with-externally-managed-chatgpt-tokens-chatgptauthtokens).
71
71
 
72
72
  ## Payload notes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zvada/agent-server",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Harness-agnostic agent execution engine: run Claude Code, Codex (SDK/CLI + app-server), and any ACP agent behind one interface with a normalized event stream, multi-turn sessions, and resume. Root export is the wire contract; /core, /server, /client are the seats.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -101,7 +101,7 @@
101
101
  "devDependencies": {
102
102
  "@agentclientprotocol/sdk": "^1.2.1",
103
103
  "@anthropic-ai/claude-agent-sdk": "0.3.220",
104
- "@openai/codex-sdk": "^0.146.1",
104
+ "@openai/codex-sdk": "0.153.4",
105
105
  "@types/bun": "^1.2.0"
106
106
  }
107
107
  }
@@ -39,8 +39,8 @@ export interface AppServerSession {
39
39
  sandbox: string;
40
40
  systemPromptAppend?: string;
41
41
  envFingerprint: string;
42
- /** Native CLI auth and externally managed tokens cannot share a warm process. */
43
- authMode?: CodexAppServerAuth["type"];
42
+ /** Native model connections retain the identity used at their first handshake. */
43
+ authFingerprint?: string;
44
44
  /** Credentials and permission broker belong only to the current execute. */
45
45
  turn?: AppServerTurn;
46
46
  idleTimer?: ReturnType<typeof setTimeout>;
@@ -169,6 +169,13 @@ export interface CodexChatGptAuth {
169
169
 
170
170
  export type CodexAppServerAuth = { type: "apiKey"; apiKey: string } | CodexChatGptAuth;
171
171
 
172
+ function authFingerprint(auth: CodexAppServerAuth | undefined): string | undefined {
173
+ if (!auth) return undefined;
174
+ return configFingerprint(
175
+ auth.type === "apiKey" ? auth : { type: auth.type, accountId: auth.tokens.chatgptAccountId },
176
+ );
177
+ }
178
+
172
179
  export interface CodexAppServerAgentOptions {
173
180
  createClient?: (options: CodexAppServerClientOptions) => CodexAppServerClient;
174
181
  idleTimeoutMs?: number;
@@ -186,7 +193,8 @@ export interface CodexAppServerAgentOptions {
186
193
  * Resolve the selected API key or ChatGPT account before EVERY turn, including warm
187
194
  * sessions. Operator-only: neither callbacks nor tokens belong in RunConfig.
188
195
  * Return undefined to select native CLI auth; throw when the selected external
189
- * account is unavailable. Switching back to native auth recreates the process.
196
+ * account is unavailable. Changing accounts, API keys, or auth modes recreates
197
+ * the process and resumes the same conversation.
190
198
  */
191
199
  resolveAuth?: (sessionId: string) => Promise<CodexAppServerAuth | undefined>;
192
200
  }
@@ -228,12 +236,13 @@ export class CodexAppServerAgent extends BaseAgent {
228
236
  const approvalPolicy = approvalPolicyFor(options);
229
237
  const sandbox = mapSandbox(options.permissionMode);
230
238
  const existing = this.sessions.get(options.sessionId);
231
- // Reuse a warm subprocess only when its (immutable) approval posture
232
- // matches; otherwise recreate it, resuming the same thread so context
233
- // survives. `resumeThreadId` carries that over to the spawn below.
239
+ const identity = authFingerprint(turn.auth);
240
+ // Codex caches an authenticated model WebSocket across turns. Login alone
241
+ // cannot switch its identity: restart on account/key changes and resume
242
+ // the same thread. Same-account token renewal can keep the process warm.
234
243
  let resumeThreadId = options.resumeSessionId;
235
244
  if (existing && !existing.client.closed) {
236
- if (appServerSessionCompatible(existing, options) && existing.authMode === turn.auth?.type) {
245
+ if (appServerSessionCompatible(existing, options) && existing.authFingerprint === identity) {
237
246
  this.sessions.clearIdle(existing);
238
247
  existing.turn = turn;
239
248
  const onAbort = () => existing.client.close();
@@ -284,7 +293,7 @@ export class CodexAppServerAgent extends BaseAgent {
284
293
  sandbox,
285
294
  systemPromptAppend: options.systemPromptAppend,
286
295
  envFingerprint: configFingerprint(options.env),
287
- authMode: turn.auth?.type,
296
+ authFingerprint: identity,
288
297
  turn,
289
298
  };
290
299
  this.bindRequests(session);
@@ -32,10 +32,10 @@ export const DEFAULT_PINS: Record<CliTool, string> = {
32
32
  // streams token-estimate placeholders instead — bump only after verifying
33
33
  // thinking summaries still flow (see options.ts extraArgs).
34
34
  claude: "0.3.220",
35
- // 0.146.1 re-verified 2026-08-06: generate-ts snapshot carries our full
36
- // surface unchanged (thread/turn/item methods, tokenUsage w/ window,
37
- // approvals) and a live turn ran clean incl. the gpt-5.6-sol default.
38
- codex: "0.146.1",
35
+ // 0.153.4 re-verified 2026-09-08 against generate-ts: host-managed
36
+ // ChatGPT auth, thread/turn/item methods, token usage, and approvals
37
+ // remain compatible. Astra requires CLI 0.153.0 or newer.
38
+ codex: "0.153.4",
39
39
  };
40
40
 
41
41
  /**