Skip to content

fix: plugin dynamic import path resolution breaks in Docker/container environments#26

Merged
htafolla merged 1 commit intomasterfrom
fix/plugin-docker-path-resolution
Mar 30, 2026
Merged

fix: plugin dynamic import path resolution breaks in Docker/container environments#26
htafolla merged 1 commit intomasterfrom
fix/plugin-docker-path-resolution

Conversation

@htafolla
Copy link
Copy Markdown
Owner

Problem

All dynamic import() calls in strray-codex-injection.js use relative paths that resolve from process.cwd(), not the plugin file location. JavaScript dynamic import() resolves relative to cwd, not the calling file. The plugin lives at .opencode/plugin/ but when opencode spawns agents with cwd: "/app", imports resolve to wrong paths like /node_modules/strray-ai/dist/... (missing /app/ prefix).

Impact: The entire StringRay processor pipeline (30+ processors: codex compliance, test auto-creation, test execution, coverage analysis, TypeScript compilation) has never executed in Docker/container environments. Zero validation across 250+ phases.

Root Causes

Issue Impact
Relative import() from process.cwd() All 10 dynamic imports fail in Docker
globalThis cache shared across sessions Stale ProcessorManager breaks subsequent sessions
No typeof guard on processor methods not a function errors crash silently
resolveStateDir() crash propagates StrRayStateManager init failure kills processor block

Changes

  1. resolvePluginImport(relativePath) — Resolves from plugin file location via import.meta.url + fileURLToPath with Docker-aware fallbacks (/app/node_modules/, /app/backend/node_modules/)
  2. findStrrayDistDir() — Locates strray-ai dist via fs.existsSync across 4 candidates
  3. All 10 dynamic imports replacedloadFrameworkLogger, loadConfigPaths, importSystemPromptGenerator, loadStrRayComponents, routingOutcomeTracker, inferenceTuner
  4. Session-scoped globalThis cacheprocess.pid key prevents cross-session pollution
  5. Processor method typeof guards — Clears stale cache gracefully instead of crashing
  6. resolveStateDir() fallback — try/catch with directory arg fallback

Testing

  • Syntax validated, all imports tested from production Docker layout
  • Deployed to production Jelly instance (strray-ai 1.15.35, Docker)
  • Plugin loads, quality gates fire, processor pipeline initializes
  • +105 lines, -48 lines

… environments

All dynamic import() calls in strray-codex-injection.js use relative paths
that resolve from process.cwd() instead of the plugin file location. In
Docker/container setups where cwd differs from the plugin directory,
every import() fails silently, causing the entire processor pipeline
(30+ processors) to never load.

Changes:
- Add resolvePluginImport() using import.meta.url + fileURLToPath for
  file-relative resolution with Docker-aware fallback paths
- Add findStrrayDistDir() to locate strray-ai dist via fs.existsSync
  across multiple candidate paths (standard, Docker /app, backend subdir)
- Fix all 10 dynamic imports: loadFrameworkLogger, loadConfigPaths,
  importSystemPromptGenerator, loadStrRayComponents, outcome-tracker,
  inference-tuner
- Session-scope globalThis cache using process.pid to prevent
  cross-opencode-session ProcessorManager pollution
- Add typeof guards on executePreProcessors/executePostProcessors
  with automatic stale cache clearing
- Wrap resolveStateDir() in try/catch with fallback to directory arg

Tested in production Docker deployment with strray-ai 1.15.35.
@htafolla htafolla merged commit 518a67a into master Mar 30, 2026
7 checks passed
@htafolla htafolla deleted the fix/plugin-docker-path-resolution branch March 30, 2026 22:35
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.

1 participant