Affected area
Agent runtime / ACP (Codex sign-in flow in the desktop app, executed by the embedded CLI daemon)
Installation method
Desktop release (analysis performed on a source checkout at commit 0a98b773)
Lody version or commit
0.93.3 (commit 0a98b773)
Operating system
macOS 15.7.4 arm64
What happened?
Two related defects in the Codex ("Sign in with ChatGPT") flow:
-
The Cancel button cannot stop an in-progress sign-in. Start Codex sign-in; the browser opens the OpenAI device authorization page (auth.openai.com/codex/device). If that page never completes (e.g. device-code login is not enabled for the account, the tab is closed, or the network blocks the callback), clicking Cancel in the sign-in panel has no effect: the spawned codex login --device-auth process is not terminated and the panel keeps waiting until the daemon's built-in 285 s timeout fires.
-
A failed sign-in attempt surfaces as an ACP runtime download error and a re-download prompt. If the managed Codex runtime is not yet installed (or its cache is stale), starting sign-in silently downloads the runtime first. When that download fails, the failure is reported as a sign-in error, and the agent settings dialog then shows the runtime as not installed / download failed with a "Download Agent / Retry download" prompt. One underlying failure (typically network) therefore produces two confusing errors, and the user is told to re-download acp-codex even though they only tried to log in.
What did you expect?
- Cancel promptly terminates the login process and resets the sign-in UI.
- Sign-in failures and runtime download failures are distinguished and reported separately; a runtime download triggered by sign-in shows progress and is cancellable.
- A stale/mismatched runtime cache self-heals by reinstalling instead of dead-ending on an error that even "Retry download" cannot get past.
How can we reproduce it?
- Ensure the managed Codex runtime is not installed (fresh install, or remove
<lody-data-dir>/agent-binaries/codex).
- In the desktop app, open the agent provider settings and start Codex "Sign in with ChatGPT".
- Let the browser open the OpenAI authorization page, but never complete it (close the tab, or use an account without device-code login enabled).
- Click Cancel in the sign-in panel. Observe: nothing happens; the flow only unwinds after the ~285 s daemon timeout.
- Separately, with the runtime not installed and the runtime download host unreachable, start sign-in. Observe: the sign-in fails, and the settings dialog then reports the runtime as missing / download failed and asks to re-download acp-codex.
How often does it happen?
Every time, under the conditions above (runtime not pre-installed and/or authorization page never completes).
Root cause analysis
Bug 1 — the cancel message is serialized behind the start message in the daemon's local control queue.
MessageProcessor.extractQueueKey assigns dedicated lanes only to session/* messages; all machine/* messages — including machine/acp-authenticate start and cancel — fall through to default and return null (apps/cli/src/lib/message-processor.ts:203-221).
ConcurrentQueue.enqueue maps a null key to a single shared '__default__' serial chain (apps/cli/src/lib/concurrent-queue.ts:24), so start and cancel execute strictly in order.
- The start task occupies that lane until
handler.handleMessage returns (apps/cli/src/lib/machine-runtime.ts:280,335), which awaits the spawned codex login --device-auth process exit or the 285 s timeout (apps/cli/src/agent/acp-authentication.ts:656-665 and :581-591).
AcpAuthenticationManager.cancel() itself is correctly implemented — sets the cancelled flag, aborts, SIGTERMs the process group, escalates to SIGKILL (acp-authentication.ts:700-716, :1123-1140) — but it is never dispatched while the start is still running. The renderer's cancel is also fire-and-forget with no optimistic UI update (packages/components/src/hooks/use-machine-acp-authentication.ts:47-58).
- Suggested fix: assign
machine/acp-authenticate messages a lane keyed by action (e.g. machine:acp-auth:<action>) so cancel/submit bypass the in-flight start; optionally update the UI optimistically on cancel. Small, localized change plus a queue test. (This also unblocks other machine/* control messages that currently stall behind a running login on the same lane.)
Bug 2 — the sign-in path silently owns the managed-runtime download, and a stale cache dead-ends.
authenticate() resolves the launch via resolveBuiltinAuthenticationProcessLaunch({ action: 'login' }) (acp-authentication.ts:599-604) → resolveManagedRuntimeForLaunch('codex') (apps/cli/src/agent/setting.ts:551) → resolveRuntimeForLaunch, which downloads on the spot when the runtime is missing (apps/cli/src/agent/managed-agent-runtime.ts:880-899).
- Unlike the status-probe path (
acp-authentication.ts:410-417), the login path passes neither signal nor onManagedRuntimeProgress: the UI shows no download progress, and neither cancel nor the 285 s timeout can interrupt the download (interruption is only checked after launch resolution, :608-609).
- A download failure throws
ManagedRuntimeError("Failed to install managed runtime codex: …") (managed-agent-runtime.ts:990-998), which the authenticate() catch reports as the sign-in error (acp-authentication.ts:680-685). The settings dialog's runtime status check then reports not-installed and prompts to download/retry — the "login failed, now re-download acp-codex" sequence.
- Compounding issue: when a cached install's metadata no longer matches the pinned manifest (archive sha256/size/cmd),
readCurrentInstallation throws (managed-agent-runtime.ts:790-799) instead of treating the cache as absent; because ensureCurrentRuntime performs the same check before downloading (:957), the dialog's "Retry download" fails again — only manually deleting agent-binaries/codex recovers.
- Suggested fixes: (a) pass
signal and an onManagedRuntimeProgress callback on the login path and surface download progress in the sign-in UI; (b) downgrade a metadata mismatch to "clean and reinstall" instead of throwing, so retry actually works.
Both fixes are small and localized (tens of lines each plus tests): Bug 1 is a queue-key change in message-processor.ts; Bug 2 is option plumbing in acp-authentication.ts plus a fallback branch in managed-agent-runtime.ts.
Relevant log output
# No crash log; the daemon stays blocked in the authenticate call until its 285 s timeout:
# "ChatGPT authentication timed out. Please try again."
Before submitting
Affected area
Agent runtime / ACP (Codex sign-in flow in the desktop app, executed by the embedded CLI daemon)
Installation method
Desktop release (analysis performed on a source checkout at commit
0a98b773)Lody version or commit
0.93.3 (commit
0a98b773)Operating system
macOS 15.7.4 arm64
What happened?
Two related defects in the Codex ("Sign in with ChatGPT") flow:
The Cancel button cannot stop an in-progress sign-in. Start Codex sign-in; the browser opens the OpenAI device authorization page (
auth.openai.com/codex/device). If that page never completes (e.g. device-code login is not enabled for the account, the tab is closed, or the network blocks the callback), clicking Cancel in the sign-in panel has no effect: the spawnedcodex login --device-authprocess is not terminated and the panel keeps waiting until the daemon's built-in 285 s timeout fires.A failed sign-in attempt surfaces as an ACP runtime download error and a re-download prompt. If the managed Codex runtime is not yet installed (or its cache is stale), starting sign-in silently downloads the runtime first. When that download fails, the failure is reported as a sign-in error, and the agent settings dialog then shows the runtime as not installed / download failed with a "Download Agent / Retry download" prompt. One underlying failure (typically network) therefore produces two confusing errors, and the user is told to re-download acp-codex even though they only tried to log in.
What did you expect?
How can we reproduce it?
<lody-data-dir>/agent-binaries/codex).How often does it happen?
Every time, under the conditions above (runtime not pre-installed and/or authorization page never completes).
Root cause analysis
Bug 1 — the cancel message is serialized behind the start message in the daemon's local control queue.
MessageProcessor.extractQueueKeyassigns dedicated lanes only tosession/*messages; allmachine/*messages — includingmachine/acp-authenticatestart and cancel — fall through todefaultand returnnull(apps/cli/src/lib/message-processor.ts:203-221).ConcurrentQueue.enqueuemaps anullkey to a single shared'__default__'serial chain (apps/cli/src/lib/concurrent-queue.ts:24), so start and cancel execute strictly in order.handler.handleMessagereturns (apps/cli/src/lib/machine-runtime.ts:280,335), which awaits the spawnedcodex login --device-authprocess exit or the 285 s timeout (apps/cli/src/agent/acp-authentication.ts:656-665and:581-591).AcpAuthenticationManager.cancel()itself is correctly implemented — sets the cancelled flag, aborts, SIGTERMs the process group, escalates to SIGKILL (acp-authentication.ts:700-716,:1123-1140) — but it is never dispatched while the start is still running. The renderer's cancel is also fire-and-forget with no optimistic UI update (packages/components/src/hooks/use-machine-acp-authentication.ts:47-58).machine/acp-authenticatemessages a lane keyed by action (e.g.machine:acp-auth:<action>) so cancel/submit bypass the in-flight start; optionally update the UI optimistically on cancel. Small, localized change plus a queue test. (This also unblocks othermachine/*control messages that currently stall behind a running login on the same lane.)Bug 2 — the sign-in path silently owns the managed-runtime download, and a stale cache dead-ends.
authenticate()resolves the launch viaresolveBuiltinAuthenticationProcessLaunch({ action: 'login' })(acp-authentication.ts:599-604) →resolveManagedRuntimeForLaunch('codex')(apps/cli/src/agent/setting.ts:551) →resolveRuntimeForLaunch, which downloads on the spot when the runtime is missing (apps/cli/src/agent/managed-agent-runtime.ts:880-899).acp-authentication.ts:410-417), the login path passes neithersignalnoronManagedRuntimeProgress: the UI shows no download progress, and neither cancel nor the 285 s timeout can interrupt the download (interruption is only checked after launch resolution,:608-609).ManagedRuntimeError("Failed to install managed runtime codex: …")(managed-agent-runtime.ts:990-998), which theauthenticate()catch reports as the sign-in error (acp-authentication.ts:680-685). The settings dialog's runtime status check then reports not-installed and prompts to download/retry — the "login failed, now re-download acp-codex" sequence.readCurrentInstallationthrows (managed-agent-runtime.ts:790-799) instead of treating the cache as absent; becauseensureCurrentRuntimeperforms the same check before downloading (:957), the dialog's "Retry download" fails again — only manually deletingagent-binaries/codexrecovers.signaland anonManagedRuntimeProgresscallback on the login path and surface download progress in the sign-in UI; (b) downgrade a metadata mismatch to "clean and reinstall" instead of throwing, so retry actually works.Both fixes are small and localized (tens of lines each plus tests): Bug 1 is a queue-key change in
message-processor.ts; Bug 2 is option plumbing inacp-authentication.tsplus a fallback branch inmanaged-agent-runtime.ts.Relevant log output
Before submitting