Skip to content

Configure: defer channel status until selection#68007

Merged
gumadeiras merged 10 commits into
mainfrom
codex/configure-lazy-channel-status
Apr 17, 2026
Merged

Configure: defer channel status until selection#68007
gumadeiras merged 10 commits into
mainfrom
codex/configure-lazy-channel-status

Conversation

@gumadeiras
Copy link
Copy Markdown
Member

Summary

  • Problem: openclaw config eagerly probed every channel before the channel picker, causing slow startup and duplicate/stale status output; remove mode could also show no channels when plugins were not loaded.
  • Why it matters: configuring channels should reach the picker quickly, and removing config should work from the config file itself.
  • What changed: defer channel status/plugin loading until a channel is selected, sort channel choices alphabetically, and list remove choices directly from openclaw.json.
  • What did NOT change (scope boundary): no guessed setup hints before probing; no credential/session files are deleted by remove.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: configure called channel status collection before showing the picker, and remove listed loaded channel plugins instead of configured channel keys.
  • Missing detection / guardrail: no regression covered the lazy picker path or remove behavior with no loaded plugins.
  • Contributing context (if known): setup plugin loading can execute expensive channel-specific module startup work.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/flows/channel-setup.test.ts, src/flows/channel-setup.status.test.ts, src/commands/configure.channels.test.ts, src/commands/configure.wizard.test.ts
  • Scenario the test should lock in: configure defers status/plugin loads until selection; channel picker sorts alphabetically; remove lists configured channel keys from config.
  • Why this is the smallest reliable guardrail: it covers the command/flow seams without loading real channel runtimes.
  • Existing test that already covers this (if any): N/A
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

  • openclaw config reaches the channel picker without probing every channel first.
  • Channel picker entries are alphabetized.
  • Remove mode lists configured channel blocks from openclaw.json, including unknown/legacy keys.

Diagram (if applicable)

Before:
openclaw config -> channels -> probe all setup adapters -> show picker
remove -> loaded plugin registry -> maybe no choices

After:
openclaw config -> channels -> show picker -> probe selected channel
remove -> openclaw.json channel keys -> choices

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local Node/pnpm
  • Model/provider: N/A
  • Integration/channel (if any): channel setup/configure
  • Relevant config (redacted): existing openclaw.json with channel config blocks

Steps

  1. Run openclaw config.
  2. Select channels.
  3. Select configure/link or remove.

Expected

  • Configure/link shows the channel picker quickly and probes only after selection.
  • Remove lists configured channel blocks.

Actual

  • Before this fix, configure/link performed all channel status probes before the picker, and remove could show no configured channels.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: scoped tests, lint, full build, commit hook pnpm check.
  • Edge cases checked: no loaded plugins in remove mode; unknown configured channel key; no guessed hints before status.
  • What you did not verify: live channel setup against every external service.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: a channel without loaded setup metadata has fewer pre-selection hints.
    • Mitigation: hints are still shown after the selected channel is probed; no guessed fallback hints are introduced.

Copilot AI review requested due to automatic review settings April 17, 2026 06:19
@openclaw-barnacle openclaw-barnacle Bot added commands Command implementations size: M maintainer Maintainer-authored PR labels Apr 17, 2026
@gumadeiras gumadeiras self-assigned this Apr 17, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the openclaw config channel configuration UX by avoiding expensive channel probing/plugin loading before the channel picker is shown, and by making channel removal operate purely off configured openclaw.json keys.

Changes:

  • Defer channel status collection and setup-plugin preloading until after a channel is selected.
  • Alphabetize channel picker entries by their displayed label.
  • In remove mode, list removable channels directly from openclaw.json (cfg.channels) rather than the loaded plugin registry, including unknown/legacy keys.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/flows/channel-setup.ts Adds deferStatusUntilSelection behavior to avoid eager status/plugin preloads before prompting.
src/flows/channel-setup.test.ts Adds a regression test asserting deferred mode avoids status checks and plugin loading before selection.
src/flows/channel-setup.status.ts Sorts picker contributions alphabetically and avoids repeated listChatChannels() scans.
src/flows/channel-setup.status.test.ts Adds tests for alphabetical sorting and hint behavior when status is absent/present.
src/commands/configure.wizard.ts Switches the wizard to use deferred channel setup (no pre-picker status note).
src/commands/configure.wizard.test.ts Verifies the wizard passes deferStatusUntilSelection: true into setupChannels.
src/commands/configure.channels.ts Removes channel configs by enumerating cfg.channels keys instead of loaded plugins.
src/commands/configure.channels.test.ts Adds tests ensuring remove mode lists configured keys and deletes selected blocks.
src/channels/plugins/setup-wizard-types.ts Extends SetupChannelsOptions with deferStatusUntilSelection.

Comment thread src/flows/channel-setup.ts Outdated
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 17, 2026

Greptile Summary

This PR defers channel status collection and plugin loading in openclaw config until after a channel is selected, eliminating the eager probe-all-channels startup cost. It also fixes the remove mode to list configured channel keys directly from openclaw.json (rather than from the loaded plugin registry, which could be empty), and alphabetizes both the channel picker and the remove list.

Confidence Score: 5/5

Safe to merge — no P0/P1 issues; all remaining findings are P2 suggestions.

The core deferral logic is correct and well-tested for the fast-exit path. The remove-wizard rewrite directly solves the empty-channel-list bug. Both sorting implementations are correct and match each other. The two P2 notes (bundled-channel config mutation in deferred mode and missing post-selection test) are worth addressing in a follow-up but do not block this change.

src/flows/channel-setup.ts (post-selection deferred path), src/flows/channel-setup.test.ts (missing selection-path coverage)

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/flows/channel-setup.ts
Line: 514

Comment:
**Bundled catalog entries silently re-routed to `enableBundledPluginForSetup`**

The `origin !== "bundled"` guard changes the non-deferred path too: a bundled `installedCatalogEntry` that previously went through `loadScopedChannelPlugin(channel, installedCatalogEntry.pluginId)` now falls through to `enableBundledPluginForSetup`. In non-deferred mode this is functionally equivalent (the plugin is already visible via `getChannelSetupPlugin`, so `enableBundledPluginForSetup` exits early after `refreshStatus`), but in deferred mode the `enablePluginInConfig(next, channel)` call runs before the plugin is loaded, which may write an explicit `enabled: true` entry to the in-progress config for an already-enabled bundled plugin. Worth adding a test that selects a bundled channel in deferred mode and asserts the resulting config shape.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/flows/channel-setup.test.ts
Line: 193-228

Comment:
**Test only covers the fast-exit (no-selection) path**

The new deferred test verifies that status/plugins are not loaded when the user exits immediately with `__done__`. The complementary path — user actually selects a channel in deferred mode and runs through setup — is not covered. That path exercises `enableBundledPluginForSetup` + `loadScopedChannelPlugin` + `refreshStatus` under the deferred constraint and is the riskiest code branch introduced here. A follow-up test that selects a channel (returning `"telegram"` from `select`) and then checks that `loadChannelSetupPluginRegistrySnapshotForChannel` and `getChannelSetupPlugin` are called only for that channel would lock in the intended lazy-load behaviour.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Configure: defer channel status until se..." | Re-trigger Greptile

Comment thread src/flows/channel-setup.ts Outdated
Comment thread src/flows/channel-setup.test.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75d153b16c

ℹ️ 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".

Comment thread src/commands/configure.channels.ts
@gumadeiras gumadeiras force-pushed the codex/configure-lazy-channel-status branch 3 times, most recently from 670ee66 to 9cf0545 Compare April 17, 2026 06:59
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9dfa0e79ea

ℹ️ 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".

Comment thread src/flows/channel-setup.ts
@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot Bot commented Apr 17, 2026

🔒 Aisle Security Analysis

We found 1 potential security issue(s) in this PR:

# Severity Title
1 🟡 Medium Terminal escape/control-sequence injection via unsanitized channel ID in setup notes
1. 🟡 Terminal escape/control-sequence injection via unsanitized channel ID in setup notes
Property Value
Severity Medium
CWE CWE-150
Location src/flows/channel-setup.ts:334-340

Description

User-controlled/untrusted channel identifiers are interpolated directly into strings rendered via prompter.note(...).

  • ChannelChoice is an alias of ChannelId, which allows arbitrary strings (ChatChannelId | (string & {})).
  • Channel IDs can originate from config keys and plugin/registry metadata, which may be influenced by external plugins/catalogs.
  • Rendering these values without sanitization permits ANSI escape sequences and control characters (e.g., \x1b[2K, newlines) to manipulate terminal output/logs (phishing/spoofing).

Vulnerable code:

await prompter.note(
  `${channel} cannot be configured while ${disabledHint}. Enable it before setup.`,
  "Channel setup",
);

Recommendation

Sanitize any untrusted text before rendering to terminal, and prefer displaying trusted labels over raw IDs.

Example fix using existing helper:

import { sanitizeTerminalText } from "../terminal/safe-text.js";

const safeChannel = sanitizeTerminalText(String(channel));
const safeHint = sanitizeTerminalText(String(disabledHint));

await prompter.note(
  `${safeChannel} cannot be configured while ${safeHint}. Enable it before setup.`,
  "Channel setup",
);

Apply the same treatment to other prompter.note messages that interpolate ${channel} (and other plugin-sourced strings) in this flow.


Analyzed PR: #68007 at commit 24cafcd

Last updated on: 2026-04-17T17:35:54Z

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b0f73b0d8

ℹ️ 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".

Comment thread src/flows/channel-setup.ts
Comment thread src/flows/channel-setup.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f645baddba

ℹ️ 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".

Comment thread src/flows/channel-setup.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 48e5d51a26

ℹ️ 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".

Comment thread src/commands/configure.channels.ts
@gumadeiras gumadeiras force-pushed the codex/configure-lazy-channel-status branch from c31b7cd to 24cafcd Compare April 17, 2026 17:33
@gumadeiras gumadeiras merged commit 9bcf8f8 into main Apr 17, 2026
25 of 26 checks passed
@gumadeiras gumadeiras deleted the codex/configure-lazy-channel-status branch April 17, 2026 17:34
@gumadeiras
Copy link
Copy Markdown
Member Author

Merged via squash.

Thanks @gumadeiras!

kvnkho pushed a commit to kvnkho/openclaw that referenced this pull request Apr 17, 2026
Merged via squash.

Prepared head SHA: 24cafcd
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
Mquarmoc pushed a commit to Mquarmoc/openclaw that referenced this pull request Apr 20, 2026
Merged via squash.

Prepared head SHA: 24cafcd
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
Merged via squash.

Prepared head SHA: 24cafcd
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
Merged via squash.

Prepared head SHA: 24cafcd
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Merged via squash.

Prepared head SHA: 24cafcd
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
globalcaos pushed a commit to globalcaos/tinkerclaw that referenced this pull request May 13, 2026
Merged via squash.

Prepared head SHA: 24cafcd
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
Merged via squash.

Prepared head SHA: 24cafcd
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands Command implementations maintainer Maintainer-authored PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants