#20415: fix(extensions): use dist/ import paths for bundled extensions
extensions: llm-task
channel: twitch
size: XS
Cluster:
Plugin Fixes and Enhancements
## Summary
- **Problem:** Two bundled extensions (`twitch` and `llm-task`) import runtime values from `../../../src/` paths that don't exist in npm/brew-installed builds, causing `Cannot find module` errors
- **Why it matters:** The twitch extension and llm-task tool are completely broken for all non-source-checkout users (npm, brew, global installs) since at least 2026.2.12
- **What changed:** Runtime value imports now use the proper export surfaces (`openclaw/plugin-sdk/account-id` alias for twitch, `dist/extensionAPI.js` dynamic fallback for llm-task)
- **What did NOT change:** `import type` statements still point to `src/` — these are erased at compile time and cause no runtime errors. No behavior, config, or API changes.
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [x] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [x] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Fixes #20548
- Closes #19053
- Closes #18846
- Closes #16182
- Related #15686
## User-visible / Behavior Changes
- Twitch extension loads successfully on npm/brew installs (was crashing on import)
- `llm-task` tool works on npm/brew installs (was failing with "Cannot find module")
## 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`
## Repro + Verification
### Environment
- OS: Any
- Runtime/container: Node.js (npm/brew global install)
- Model/provider: N/A
- Integration/channel: Twitch, llm-task
### Steps
1. `npm install -g openclaw@latest`
2. Configure twitch channel or call `llm-task` tool
3. Observe `Cannot find module '../../../src/routing/session-key.js'` (twitch) or `Cannot find module '../../../src/agents/pi-embedded-runner.js'` (llm-task)
### Expected
- Extensions load and function correctly
### Actual
- Both extensions crash with module-not-found errors
## Evidence
- [x] Failing test/log before + passing after
- [x] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
Error logs from issues #19053, #18846, #16182 all show identical `Cannot find module` errors. After fix: both extensions load without errors.
**Root cause in `llm-task-tool.ts`** — the "fallback" import path (line 28) is identical to the primary path (line 17). Both try `../../../src/agents/pi-embedded-runner.js`. This is a copy-paste bug. The correct fallback is `dist/extensionAPI.js` which exports `runEmbeddedPiAgent`.
**Root cause in `token.ts`** — static import from `../../../src/routing/session-key.js` which doesn't exist in production builds. The `openclaw/plugin-sdk/account-id` alias re-exports the same symbols and resolves correctly in both dev and production.
## Human Verification (required)
- Verified scenarios: Confirmed `dist/plugin-sdk/index.js` exports `DEFAULT_ACCOUNT_ID` and `normalizeAccountId`; confirmed `dist/extensionAPI.js` exports `runEmbeddedPiAgent`; confirmed `import type` statements are erased at compile time. Both extensions load and initialize successfully after the fix.
- Edge cases checked: Dev environment (src/ path still works as primary for llm-task), type-only imports unaffected, `openclaw/plugin-sdk/account-id` alias resolves via package.json exports at runtime and tsconfig paths at type-check time
- What you did **not** verify: Full integration test on npm global install (verified by code inspection and issue reports)
## Compatibility / Migration
- Backward compatible? `Yes`
- Config/env changes? `No`
- Migration needed? `No`
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly: `git revert <commit>`
- Files/config to restore: `extensions/twitch/src/token.ts`, `extensions/llm-task/src/llm-task-tool.ts`
- Known bad symptoms reviewers should watch for: Module resolution errors mentioning `plugin-sdk/account-id` or `dist/extensionAPI`
## Risks and Mitigations
- Risk: `openclaw/plugin-sdk/account-id` alias or `dist/extensionAPI.js` could be renamed in a future refactor
- Mitigation: These are public API surfaces used by many extensions (googlechat, IRC, voice-call). Renaming would break all extensions, not just these two.
**Note:** The same `src/`-import pattern may affect other extensions (see #15686 which reports memory-core, telegram, voice-call, whatsapp). A follow-up lint rule to flag non-type imports from `src/` in `extensions/` could prevent recurrence.
## AI-assisted
This PR was AI-assisted. The code is understood, tested, and verified against the live codebase.
Most Similar PRs
#13176: fix: resolve llm-task module import for global installs
by striking · 2026-02-10
77.6%
#12844: fix(llm-task): use correct import path for built/npm installs
by scout-wolfe · 2026-02-09
77.0%
#21732: fix(plugin-sdk): re-export missing plugin authoring types
by jylkim · 2026-02-20
76.0%
#19061: fix(llm-task): correct fallback import path from src/ to dist/
by Operative-001 · 2026-02-17
73.8%
#22692: fix(memory-lancedb): [P1] add missing runtime deps — plugin broken ...
by mahsumaktas · 2026-02-21
73.4%
#16684: fix:(antigravity): align Antigravity OAuth project discovery header...
by vincentkoc · 2026-02-15
72.6%
#21054: fix(cli): fix memory search hang — close undici pool + destroy QMD ...
by BinHPdev · 2026-02-19
72.1%
#11454: fix(plugins): remove workspace:* from extension dependencies
by AnonO6 · 2026-02-07
70.9%
#17237: fix(update): guard post-install imports after npm global update
by tdjackey · 2026-02-15
70.6%
#19807: fix: apply #19779 Docker/TS strict-build fixes
by dalefrieswthat · 2026-02-18
70.3%