Files
openclaw/extensions/codex/src/app-server/thread-resume.ts
Peter Steinberger 96f0983a85 fix(onboarding): skip setup for configured gateways and require inference first (#102883)
* fix(crestodian): keep onboarding RPCs restart-safe

* fix(profiles): isolate approval state migrations

* fix(crestodian): bypass configured gateway setup

* test(crestodian): type onboarding mocks

* fix(onboarding): require inference before Crestodian

* fix(onboarding): enforce verified inference handoff

* fix(macos): reset setup on gateway endpoint edits

* chore(i18n): refresh native source inventory

* fix(gateway): keep socket on request cancellation

* test(packaging): require workspace templates

* fix(onboarding): bind setup to verified inference

* fix(onboarding): align inference gate contracts

* fix(crestodian): classify concurrent policy rejection

* test(crestodian): expect registry restoration

* fix(onboarding): bind setup to configured gateways

* fix(codex): preserve startup phase deadlines

* test(crestodian): match fail-closed policy ordering

* test(onboarding): assert bound gateway handoff

* fix(codex): bind runtime resolution to spawn cwd

* test(crestodian): assert policy rejection order

* fix(cli): preserve gateway routing across restarts

* fix(macos): fail closed during gateway edits

* test(macos): cover gateway route generation races

* chore: keep release notes out of onboarding PR

* fix(ci): refresh onboarding generated checks

* style(swift): align gateway channel formatting

* fix(ci): refresh plugin SDK surface budgets

* fix(ci): resync native string inventory

* refactor(swift): split gateway channel support

* test(doctor): isolate plugin compatibility registry

* test(macos): isolate gateway onboarding fixtures

* test(macos): assert gateway lease health ordering

* fix(codex): reconcile computer-use startup changes
2026-07-11 10:25:14 -07:00

65 lines
2.3 KiB
TypeScript

/** Owns Codex thread/resume subscription safety. */
import {
assertCodexThreadResumeSubscription,
CodexAppServerUnsafeSubscriptionError,
} from "./attempt-client-cleanup.js";
import {
CodexAppServerRpcError,
isCodexAppServerPrewriteRequestCancellationError,
type CodexAppServerClient,
} from "./client.js";
import { assertCodexThreadResumeResponse } from "./protocol-validators.js";
import type { CodexThreadResumeParams, CodexThreadResumeResponse } from "./protocol.js";
import { isCodexAppServerStartSelectionChangedError } from "./shared-client.js";
/** Resumes one thread and retires the physical client when acceptance is indeterminate. */
export async function resumeCodexAppServerThread(params: {
client: CodexAppServerClient;
abandonClient: () => Promise<void>;
request: CodexThreadResumeParams;
timeoutMs?: number;
signal?: AbortSignal;
}): Promise<CodexThreadResumeResponse> {
const threadId = params.request.threadId;
let response: CodexThreadResumeResponse;
try {
response = assertCodexThreadResumeResponse(
await params.client.request("thread/resume", params.request, {
...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs } : {}),
...(params.signal ? { signal: params.signal } : {}),
}),
);
assertCodexThreadResumeSubscription(threadId, response.thread.id);
} catch (error) {
if (
isCodexAppServerStartSelectionChangedError(error) ||
isCodexAppServerPrewriteRequestCancellationError(error)
) {
throw error;
}
if (error instanceof CodexAppServerRpcError) {
// A structured RPC error proves Codex rejected the resume, so the client
// holds no hidden subscription and can safely stay in the shared pool.
throw error;
}
try {
await params.abandonClient();
} catch (abandonError) {
throw new CodexAppServerUnsafeSubscriptionError(
`Codex thread/resume client could not be retired for ${threadId}`,
{ cause: abandonError },
);
}
if (error instanceof CodexAppServerUnsafeSubscriptionError) {
throw error;
}
throw new CodexAppServerUnsafeSubscriptionError(
error instanceof Error
? error.message
: `Codex thread/resume outcome is indeterminate for ${threadId}`,
{ cause: error },
);
}
return response;
}