Skip to content

Re-emit chat config after plugin resolution#553

Merged
ericdallo merged 2 commits into
editor-code-assistant:masterfrom
rschmukler:rs/fix-plugin-loading-race
Jul 23, 2026
Merged

Re-emit chat config after plugin resolution#553
ericdallo merged 2 commits into
editor-code-assistant:masterfrom
rschmukler:rs/fix-plugin-loading-race

Conversation

@rschmukler

Copy link
Copy Markdown
Contributor

Plugin-provided agents (and anything from installed plugins) can be missing from
the editor's agent picker, even though the server has loaded them correctly.
Symptom: the editor shows only built-in agents (code, plan) plus any
project-local .eca/agents/* agents, while plugin MCP servers still show up as
available. Querying the server's /api/v1/session shows the full agent list, so
the agents are loaded — the editor just never gets told about them.

Root cause

At initialized, two independent futures run:

  1. Model sync — on completion it sends a config/updated notification that
    carries the agent list (:agents (primary-agent-names …)).
  2. Plugin resolutionreset!s plugin-components*, which is what makes
    plugin agents visible to config/all.

These race. When model sync finishes before plugin resolution, it advertises
the pre-plugin agent list, and nothing re-emits it afterward — so plugin agents
never reach the editor. This is reliably hit with providers configured with
"fetchModels": false, since model sync then returns almost instantly and
always wins the race. (It also explains selectAgent falling back to code
when the configured defaultAgent is a plugin agent.)

Fix

  • Extract the config/updated payload building into notify-chat-config-state!.
  • The model-sync callback calls it (unchanged behavior — it already re-reads
    config/all).
  • Call it again right after config/deliver-plugins-resolved! in the plugin
    future.

notify-fields-changed-only! diffs against the session-level mirror, so the
extra call only emits the newly-resolved agents and is a no-op when plugins won
the race. Either ordering now converges on the full agent list.

Testing

  • clj-kondo clean (0 errors / 0 warnings).

  • Namespace compiles.

  • eca.handlers-test (12 tests / 78 assertions) and
    eca.features.plugins-test + eca.config-test + eca.server-test
    (32 tests / 260 assertions) pass.

  • I added a entry in changelog under unreleased section.

  • This is not an AI slop.

…ch the editor

Plugin resolution and model sync run as independent startup futures. The
model-sync callback notifies the editor's agent list, but when it finishes
before plugin resolution (reliably so with providers using fetchModels:
false), it advertises the pre-plugin agent list and nothing refreshes it
afterward, so plugin-provided agents never appear in the editor.

Extract the notification into notify-chat-config-state! and call it again
after deliver-plugins-resolved!. notify-fields-changed-only! diffs against
the session mirror, so the extra call only emits the newly-resolved agents
and is a no-op when plugins won the race.

@ericdallo ericdallo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thank you!

@ericdallo
ericdallo merged commit 2883c33 into editor-code-assistant:master Jul 23, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants