[codex] fix gateway runtime flow follow-ups#69584
[codex] fix gateway runtime flow follow-ups#69584mmy4shadow wants to merge 19 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes several follow-up issues in the gateway runtime and setup wizard flow: it adds a summary-only fast path for
Confidence Score: 4/5Mergeable after resolving the dead One P1 structural bug (always-false src/wizard/setup.finalize.ts —
|
| const opened = await params.openUrl(url); | ||
| if (opened === false) { | ||
| params.spin.update( | ||
| "Could not open a browser automatically. Open the URL below, then paste the redirect URL here…", | ||
| ); | ||
| params.runtime.log(`\nOpen this URL in your browser:\n\n${url}\n`); | ||
| manualCodePromise = ensureManualPrompt(); | ||
| return; | ||
| } | ||
| params.runtime.log(`Open: ${url}`); |
There was a problem hiding this comment.
openUrl throw not caught — fallback only handles false return
createVpsAwareOAuthHandlers falls back to manual entry only when openUrl returns exactly false. If an openUrl implementation throws instead (which extensions/minimax/oauth.ts guards against with a try/catch around the same call), the exception propagates out of onAuth and aborts the OAuth flow with no graceful recovery. Given the PR intent is to "add safer OAuth browser-open fallback behavior and align provider openUrl contracts", consider adding a try/catch here too:
let opened: unknown;
try {
opened = await params.openUrl(url);
} catch {
opened = false;
}
if (opened === false) {
// ... existing fallback
}Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugins/provider-oauth-flow.ts
Line: 41-50
Comment:
**`openUrl` throw not caught — fallback only handles `false` return**
`createVpsAwareOAuthHandlers` falls back to manual entry only when `openUrl` returns exactly `false`. If an `openUrl` implementation throws instead (which `extensions/minimax/oauth.ts` guards against with a try/catch around the same call), the exception propagates out of `onAuth` and aborts the OAuth flow with no graceful recovery. Given the PR intent is to "add safer OAuth browser-open fallback behavior and align provider `openUrl` contracts", consider adding a try/catch here too:
```ts
let opened: unknown;
try {
opened = await params.openUrl(url);
} catch {
opened = false;
}
if (opened === false) {
// ... existing fallback
}
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8d9b8f6f9c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ); | ||
| } | ||
| } else if (installDaemon) { | ||
| if (!gatewayProbe.ok && installDaemon) { |
There was a problem hiding this comment.
Treat a successful gateway probe as a success path
When waitForGatewayReachable succeeds (gatewayProbe.ok === true), this condition falls through to the else branch and still shows the "Gateway not detected yet" note. That means normal successful onboarding with --skip-health off now reports a false negative to users, which is confusing and can trigger unnecessary troubleshooting even though the gateway is reachable.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6ff15f62fb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } finally { | ||
| restoreTerminalState("post-setup tui", { resumeStdinIfPaused: true }); | ||
| } | ||
| await runTui({ |
There was a problem hiding this comment.
Keep setup TUI out of the onboarding process
Calling runTui(...) here makes the onboarding flow non-returning for the TUI path: runTui drives its own lifecycle and exits the process (process.exit(0)) when the user leaves TUI, so control never reliably returns to finish the remaining setup steps in this function (shell completion, final notes/outro, and clean finalize behavior). This is a regression from the previous child-process launch behavior and affects any user choosing “Hatch in TUI”.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5ab5a80f64
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } catch { | ||
| opened = false; | ||
| } | ||
| if (opened === false) { |
There was a problem hiding this comment.
Treat undefined browser-open result as open failure
The new fallback only triggers when openUrl returns false, but several auth call paths pass wrappers that await openUrl(url) without returning its boolean (src/plugins/provider-auth-choice.ts:143 and src/commands/models/auth.ts:303), so opened becomes undefined and this branch is skipped even when browser launch fails. In local/headless environments this regresses the intended manual OAuth fallback and leaves users without the immediate paste-redirect prompt.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 04c38d8ae9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| token: settings.authMode === "token" ? settings.gatewayToken : undefined, | ||
| password: settings.authMode === "password" ? resolvedGatewayPassword : "", |
There was a problem hiding this comment.
Avoid passing gateway secrets through TUI argv
This onboarding path now forwards the gateway token/password directly into launchTuiCli, which turns them into --token/--password command-line args (src/tui/tui-launch.ts). On multi-user systems (or any environment where process args are inspectable/logged), that exposes live gateway credentials in plaintext via process listings and telemetry. The previous config-auth launch path avoided argv secret exposure, so this is a security regression for users choosing “Hatch in TUI”.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: af12ba777f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| continue; | ||
| } | ||
| if (isCmdControlFlowLine(lower)) { |
There was a problem hiding this comment.
Preserve env setup when skipping batch control-flow lines
Do not unconditionally skip if/for lines here, because readScheduledTaskCommand then drops environment assignments performed inside control-flow wrappers (for example loading OPENCLAW_GATEWAY_TOKEN from a .env loop). In the fallback path, launchFallbackTaskScript uses the parsed programArguments directly, so that skipped setup block is never executed by cmd.exe, and the relaunched gateway can start without required auth/env values.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0df037ff13
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const defaultAccount = await buildChannelAccountSnapshot({ | ||
| plugin, | ||
| cfg, | ||
| accountId: defaultAccountId, | ||
| runtime: runtimeSnapshot, |
There was a problem hiding this comment.
Preserve activity/probe fields in summary-only channel snapshots
The new includeAccounts: false path builds snapshot directly with buildChannelAccountSnapshot, which skips the extra enrichment done in buildAccountSnapshot (notably lastProbeAt and getChannelActivity fallbacks for lastInboundAt/lastOutboundAt). As a result, channels.status can now return different channel summaries depending on includeAccounts, and summary builders that read those fields (for example WhatsApp’s buildChannelSummary using snapshot.lastInboundAt) can regress to null/stale values in overview requests even when recent activity exists.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e3948d98a3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (hatchChoice === "tui") { | ||
| restoreTerminalState("pre-setup tui", { resumeStdinIfPaused: true }); | ||
| try { | ||
| await launchTuiCli( | ||
| { | ||
| // Safety: setup TUI should not auto-deliver to lastProvider/lastTo. | ||
| deliver: false, | ||
| message: hasBootstrap ? "Wake up, my friend!" : undefined, | ||
| }, | ||
| { | ||
| authSource: "config", | ||
| gatewayUrl: links.wsUrl, | ||
| }, | ||
| ); | ||
| } finally { | ||
| restoreTerminalState("post-setup tui", { resumeStdinIfPaused: true }); | ||
| } | ||
| await launchTuiCli({ | ||
| url: links.wsUrl, |
There was a problem hiding this comment.
Restore terminal state after failed TUI hatch
This branch now calls launchTuiCli(...) without a post-launch cleanup, so if the TUI exits non-zero (or via signal) onboarding throws before restoring terminal modes. In that failure path, launchTuiCli only resumes stdin, which can leave raw mode/TTY state dirty and break the user’s shell session after onboarding aborts. Please add a guaranteed terminal restore on the error path (e.g., a finally around the launch call).
Useful? React with 👍 / 👎.
| const launchToken = env[TUI_LAUNCH_GATEWAY_TOKEN_ENV]; | ||
| const launchPassword = env[TUI_LAUNCH_GATEWAY_PASSWORD_ENV]; |
There was a problem hiding this comment.
Clear one-shot TUI auth env vars after reading
The new launch auth handoff reads OPENCLAW_TUI_LAUNCH_GATEWAY_TOKEN/PASSWORD from process.env, but never scrubs them. That leaves live gateway credentials in the TUI process environment for the entire session, so plugin/tool code and spawned child processes can inherit or inspect them; this is a credential exposure regression, especially when setup resolved a password SecretRef just for bootstrapping TUI auth. These env vars should be deleted immediately after extracting their values.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e9fb303e0d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const res = await state.client.request<ChannelsStatusSnapshot | null>("channels.status", { | ||
| probe, | ||
| probe: request.probe, | ||
| includeAccounts: request.includeAccounts, |
There was a problem hiding this comment.
Omit default includeAccounts from channels.status requests
Avoid always sending includeAccounts here: when this UI talks to an older gateway that still validates channels.status params without that field (with additionalProperties: false), the request is rejected as invalid and channel status fails entirely. This only needs to be sent for the non-default optimization path (includeAccounts: false), so omitting it when true preserves backward compatibility for mixed-version dashboard/gateway setups.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cacdce423c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ]); | ||
| buildAttentionItems(app); | ||
| void Promise.allSettled([ | ||
| loadChannels(app, false, { includeAccounts: false }), |
There was a problem hiding this comment.
Retry channels overview fetch without includeAccounts flag
The overview path now always calls loadChannels(..., { includeAccounts: false }), which sends a new request field that older gateways do not understand. In mixed-version setups (new UI bundle against an older gateway), this causes channels.status to fail on every overview refresh even though the legacy request shape would succeed; loadChannels currently surfaces the error instead of falling back. Add a compatibility retry that reissues the request without includeAccounts when the gateway rejects unknown params.
Useful? React with 👍 / 👎.
| cfg, | ||
| accountIds, | ||
| }); | ||
| const account = plugin.config.resolveAccount(cfg, defaultAccountId); |
There was a problem hiding this comment.
Build summary-only channel status from an effective account
The summary-only path resolves and probes only defaultAccountId directly, but that id can be stale/missing in config. The full-account path explicitly falls back to the first available account snapshot, while this new lightweight path does not, so includeAccounts: false responses can report a channel as unconfigured/offline even when another account is active. Mirror the full-path fallback before building/probing the summary snapshot.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ae3c1f00b3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const defaultAccountId = resolveEffectiveDefaultAccountId({ | ||
| accountIds, | ||
| defaultAccountId: configuredDefaultAccountId, | ||
| }); |
There was a problem hiding this comment.
Keep start/logout default account resolution aligned
channels.status now rewrites stale defaults to the first live account via resolveEffectiveDefaultAccountId, so the payload can advertise channelDefaultAccountId as a different account than config. However, channels.start/channels.logout still resolve omitted accountId through resolveChannelGatewayAccountId (which prefers the stale configured default first), so clients that omit accountId can now act on a different account than the one status reports and hit avoidable start/logout failures when the configured default is stale.
Useful? React with 👍 / 👎.
|
Maintainer review: please split/fix before merge. There are useful changes here, but the PR is too broad and includes a risky plugin-loader regression mixed into unrelated gateway/UI/OAuth/onboarding work. Main blocker:
Suggested path:
Not a close; there are good pieces here. It just needs decomposition and the loader regression removed. |
|
Closing this as duplicate or superseded after Codex automated review. #69584 should close as superseded. The original PR is an unsafe mixed branch that maintainer review asked to split before merge, and the canonical replacement is open PR #70474, which explicitly says it is the reviewable split extracted from #69584. Current main also still preserves the plugin-loader runtime-dependency repair that the maintainer called out as required, so the broad original should not be merged as-is. Best possible solution: Close #69584 as superseded by the narrower #70474 review path. Continue review and fixes on #70474, and use additional small PRs for any remaining slices rather than merging the original broad branch with the loader regression risk. What I checked:
So I’m closing this here and keeping the remaining discussion on the canonical linked item. Codex Review notes: model gpt-5.5, reasoning high; reviewed against 9a529ca78bfa. |
Summary
openUrlcontractsValidation
pnpm test src/daemon/schtasks.test.ts src/gateway/server-methods/channels.status.test.ts src/plugins/provider-openai-codex-oauth.test.ts src/wizard/setup.plugin-config.test.ts src/wizard/setup.test.ts ui/src/ui/app-settings.overview.node.test.ts ui/src/ui/app-settings.test.tspnpm test ui/src/ui/app-chat.test.tspnpm tsgo:core:test