@zvada/agent-server 0.3.4 → 0.3.6
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,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.6
|
|
4
|
+
|
|
5
|
+
- Unsupported Codex app-server requests now receive an explicit protocol error.
|
|
6
|
+
Previously, requests such as MCP elicitations were treated as file-edit
|
|
7
|
+
approvals and could leave a turn waiting in the permission broker. Command
|
|
8
|
+
and file approvals and host-managed credential refresh keep their existing behavior.
|
|
9
|
+
|
|
10
|
+
## 0.3.5
|
|
11
|
+
|
|
12
|
+
- Switching Codex ChatGPT accounts or API keys now recreates the native process
|
|
13
|
+
and resumes the same conversation. Native Codex keeps model WebSockets
|
|
14
|
+
authenticated as the account that opened them, so a login update alone could
|
|
15
|
+
keep using the previous account. Renewing a token for the same account remains
|
|
16
|
+
warm; no credential fields are added to the public protocol.
|
|
17
|
+
|
|
3
18
|
## 0.3.4
|
|
4
19
|
|
|
5
20
|
- Update the managed Codex CLI and development SDK to 0.153.4. This clears
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zvada/agent-server",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
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",
|
|
@@ -39,8 +39,8 @@ export interface AppServerSession {
|
|
|
39
39
|
sandbox: string;
|
|
40
40
|
systemPromptAppend?: string;
|
|
41
41
|
envFingerprint: string;
|
|
42
|
-
/** Native
|
|
43
|
-
|
|
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.
|
|
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
|
-
|
|
232
|
-
//
|
|
233
|
-
//
|
|
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.
|
|
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
|
-
|
|
296
|
+
authFingerprint: identity,
|
|
288
297
|
turn,
|
|
289
298
|
};
|
|
290
299
|
this.bindRequests(session);
|
|
@@ -386,6 +395,16 @@ export class CodexAppServerAgent extends BaseAgent {
|
|
|
386
395
|
chatgptPlanType: tokens.chatgptPlanType ?? null,
|
|
387
396
|
};
|
|
388
397
|
}
|
|
398
|
+
// Elicitations and other server requests have their own response shapes.
|
|
399
|
+
// Sending them to the approval broker can leave a turn waiting forever.
|
|
400
|
+
if (
|
|
401
|
+
method !== "item/commandExecution/requestApproval" &&
|
|
402
|
+
method !== "item/fileChange/requestApproval" &&
|
|
403
|
+
method !== "execCommandApproval" &&
|
|
404
|
+
method !== "applyPatchApproval"
|
|
405
|
+
) {
|
|
406
|
+
throw new Error(`Unsupported Codex server request: ${method}`);
|
|
407
|
+
}
|
|
389
408
|
const requestThread = params.threadId ?? params.conversationId;
|
|
390
409
|
const v2 = method.startsWith("item/");
|
|
391
410
|
const decline = v2 ? { decision: "decline" } : { decision: "denied" };
|