Skip to content

fix: improve plugin system robustness — agent/command resolution, async errors, hook timing, two-phase init - #18280

Merged
rekram1-node merged 7 commits into
anomalyco:devfrom
ryanskidmore:fix/plugin-system-robustness
Mar 24, 2026
Merged

fix: improve plugin system robustness — agent/command resolution, async errors, hook timing, two-phase init#18280
rekram1-node merged 7 commits into
anomalyco:devfrom
ryanskidmore:fix/plugin-system-robustness

Conversation

@ryanskidmore

@ryanskidmore ryanskidmore commented Mar 19, 2026

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #18310

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Agent.get() and Command.get() return undefined for unknown names, but five call sites in prompt.ts dereference the result without null checks — producing a raw TypeError instead of a useful error. The prompt_async route drops errors silently because the detached SessionPrompt.prompt() call has no .catch(). Plugin config hooks aren't error-isolated, so one throwing hook kills the rest. The command.execute.before hook fires after template parts are merged with caller parts, making clean template replacement fragile. And plugins added by a config hook aren't loaded in the same startup pass because Plugin.state() is already cached.

Fixes:

  1. Agent/command null guards — Added null checks at all five Agent.get()/Command.get() call sites (createUserMessage, loop normal + subtask, shell, command). On missing agent/command, throws NamedError.Unknown with the list of available names and publishes Session.Event.Error. Follows the existing guard pattern already at line 1858 of prompt.ts. Empty-string agent falls back to Agent.defaultAgent() instead of looking up "".

  2. prompt_async error handling — Added .catch() on the detached SessionPrompt.prompt() call in the prompt_async route that logs the error and publishes Session.Event.Error. The route still returns 204 immediately — the fire-and-forget semantics are preserved, errors are just no longer invisible.

  3. Config hook error isolation — Wrapped each individual hook.config?.() call in Plugin.init() with try/catch so a failing hook is logged but doesn't prevent others from running.

  4. Command hook timing — Moved Plugin.trigger("command.execute.before") to fire before template parts are merged with input.parts. Plugins now receive template-only parts in output.parts and can replace template content cleanly. input.parts are merged after the hook returns. Subtask path unchanged. No hook type signature change.

  5. Two-phase plugin init — After config hooks fire in Plugin.init(), the code now diffs config.plugin against what was originally loaded, imports any newly-added plugins using the same install/import path as state(), runs their config hooks once, and pushes them into the shared hooks array. One extra pass only — no recursive loading.

How did you verify your code works?

7 new test cases added to existing test files, all passing:

  • test/session/prompt.test.ts — unknown agent throws NamedError.Unknown (not TypeError), error includes available names, empty agent falls back to default, unknown command throws with names; command hook receives template-only parts before input merge
  • test/server/session-messages.test.ts — structural test verifying .catch() + Bus.publish(Session.Event.Error) on prompt_async route
  • test/plugin/auth-override.test.ts — two-phase plugin loading structure verified, config hooks individually error-isolated with try/catch

bun typecheck clean across all 13 packages. bun test passes.

Screenshots / recordings

N/A — no UI changes.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR
@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. contributor and removed needs:compliance This means the issue will auto-close after 2 hours. labels Mar 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@ryanskidmore
ryanskidmore force-pushed the fix/plugin-system-robustness branch from d8866cb to cc07261 Compare March 19, 2026 23:44
…nc error handling, hook timing, and two-phase init

- Guard against undefined Agent.get()/Command.get() at all call sites with
  typed NamedError and available-name hints instead of silent TypeErrors
- Add .catch() on prompt_async route to surface detached prompt failures
  via Session.Event.Error instead of silently swallowing them
- Isolate plugin config hook errors with per-hook try/catch so one failing
  hook no longer kills the entire bootstrap
- Move command.execute.before hook to fire before template parts are merged
  with input parts, giving plugins access to raw template content
- Add two-phase plugin initialization so plugins injected by config hooks
  are loaded and initialized in the same startup pass
- Add tests for agent/command resolution errors, async error handling,
  command hook timing, and plugin config hook ordering
@rekram1-node

Copy link
Copy Markdown
Collaborator

lgtm, just need to resolve merge conflicts

@rekram1-node
rekram1-node self-requested a review March 23, 2026 18:41
@rekram1-node
rekram1-node merged commit 814a515 into anomalyco:dev Mar 24, 2026
8 checks passed
Andres77872 pushed a commit to Andres77872/opencode that referenced this pull request Mar 26, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
dzianisv pushed a commit to dzianisv/opencode that referenced this pull request Mar 26, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
dzianisv pushed a commit to dzianisv/opencode that referenced this pull request Apr 2, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
balcsida pushed a commit to balcsida/opencode that referenced this pull request Apr 8, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
dzianisv pushed a commit to dzianisv/opencode that referenced this pull request Apr 9, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
xywsxp pushed a commit to xywsxp/opencode that referenced this pull request Apr 24, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Rwanbt pushed a commit to Rwanbt/unifia that referenced this pull request May 5, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
AIALRA-0 pushed a commit to AIALRA-0/opencode-turn-engine that referenced this pull request Jun 10, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
AIALRA-0 pushed a commit to AIALRA-0/opencode-turn-engine that referenced this pull request Jun 10, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
avion23 pushed a commit to avion23/opencode that referenced this pull request Jun 10, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Rwanbt pushed a commit to Rwanbt/unifia that referenced this pull request Jun 14, 2026
…nc errors, hook timing, two-phase init (anomalyco#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
rustybret added a commit to rustybret/opencode that referenced this pull request Jul 10, 2026
Reset to upstream dev:
- plugin/index.ts (upstream anomalyco#18280 rewrote plugin error handling)
- cli/error.ts (upstream anomalyco#27803 reworked TUI error rendering)
- session-data.ts (upstream error typing changes)
- session/prompt.ts (massive upstream refactor)
- cli/cmd/tui/worker.ts (restored — was deleted by stale merge)

Removed dead artifacts:
- script/patch-aft-lsp.sh (targets deleted worker.ts architecture)
- session-ses_1d10.md, sessions.jsonl (stale session dumps)

Backup: fork/local-backup
MarsQiu007 referenced this pull request in MarsQiu007/openNovel Jul 31, 2026
…nc errors, hook timing, two-phase init (#18280)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

2 participants