Skip to content

opencode: find the dispatcher wherever the plugin is installed - #229

Open
Have-Purple wants to merge 1 commit into
microsoft:mainfrom
Have-Purple:fix/opencode-dispatcher-path
Open

Have-Purple wants to merge 1 commit into
microsoft:mainfrom
Have-Purple:fix/opencode-dispatcher-path

Conversation

@Have-Purple

@Have-Purple Have-Purple commented Nov 14, 2026 •

Copy link
Copy Markdown

Fixes #228.

Problem

The opencode plugin assumed its launchers live at <plugin dir>/../scripts:

const SCRIPTS = join(HERE, "..", "scripts");

That is true in the checkout, but not for the copy opencode loads from ~/.config/opencode/plugins, where it resolves to ~/.config/opencode/scripts — which does not exist. Every hook then failed to spawn its dispatcher, and the fail-open path answered {}, so there was no fold, no injection, no loop guard, and no log entry to notice. Details and repro: #228.

Change

Resolve the dispatcher instead of assuming a layout, first hit wins:

  1. TE_PLUGIN_ROOT → <root>/scripts
  2. TE_CORE_PATH → <root>/plugin/scripts (the checkout pointer the bootstrap already documents)
  3. an ancestor walk from the plugin's own directory (scripts, ../scripts, ../../scripts, plugin/scripts)
  4. the state-root launcher: ~/.tokeneconomizer/bin/te is exec '<plugin>/scripts/te' "$@", so its directory is the dispatcher's

The old expression remains the last resort. No other behaviour changes.

Tests

In tests/test_opencode_plugin.py (run by the existing opencode CI job):

  • an installed copy with no launchers beside it resolves through TE_CORE_PATH and writes dispatcher state;
  • the existing bundle layout (launchers + lib beside the plugin) still resolves with TE_CORE_PATH unset;
  • with no anchor at all the session still runs and the dispatcher starts nothing (fail-open).

The assertion is dispatcher state, not hook-process count: a hook that cannot find te_bootstrap.py still starts a Python, which would make a process-count test pass with the bug.

Verification

opencode 2.3.0 on Windows; the branch applies cleanly to main 7042ea8. Removing the resolver makes the installed-copy test red while the bundle control stays green. Full offline suite locally: 910 passed, 34 skipped.

The plugin assumed its launchers sit at <plugin dir>/../scripts. That holds in the checkout,
but not for the copy opencode loads from ~/.config/opencode/plugins, where it resolves to
~/.config/opencode/scripts -- which does not exist. Every hook then failed to spawn, and the
fail-open path answered {}, so there was no fold, no injection, no loop guard, and no log to
notice.

Resolve instead: TE_PLUGIN_ROOT, TE_CORE_PATH (the checkout pointer the bootstrap already
reads), an ancestor walk from the plugin's own directory, and the state-root launcher
(~/.tokeneconomizer/bin/te -> <plugin>/scripts/te). The old expression stays as the last
resort.

Tests assert dispatcher state, not hook-process count: a hook that cannot find
te_bootstrap.py still starts a Python, so counting processes would pass with the bug.
@Have-Purple

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

@Have-Purple Have-Purple reopened this Nov 14, 2026
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.

opencode: plugin loads but nothing fires when installed as a copy (dispatcher path)

1 participant