PROJECT KNOWLEDGE BASE
Generated: 2026-02-12 Commit: acf2f08 Branch: feat/tests
OVERVIEW
OpenPrism — OpenCode plugin providing 3-tier drawing: Mermaid diagrams (Tier 1), Matplotlib plots (Tier 2), AIGC image generation (Tier 3). TypeScript, ESM-only, @opencode-ai/plugin compatible.
STRUCTURE
OpenPrism/
├── src/
│ ├── index.ts # Plugin entry — wires tools + hooks, creates FileManager
│ ├── types.ts # All shared types + DEFAULT_CONFIG
│ ├── hooks/
│ │ ├── mermaid-renderer.ts # tool.execute.after — auto-renders ```mermaid blocks
│ │ ├── system-prompt.ts # chat.system.transform — injects tier guidance
│ │ └── session-compaction.ts # session.compacting — preserves asset summaries
│ ├── renderers/
│ │ ├── mermaid-ssr.ts # mmdc wrapper: renderMermaid, validateMermaidSyntax, extractMermaidBlocks
│ │ └── matplotlib-bridge.ts # Python subprocess: renderMatplotlib, detectPythonEnvironment, wrapScript
│ ├── tools/
│ │ ├── render-mermaid.ts # Tier 1: explicit Mermaid render
│ │ ├── analyze-structure.ts # Tier 1: project dir → Mermaid diagram
│ │ ├── plot-data.ts # Tier 2: Matplotlib execution
│ │ └── generate-image.ts # Tier 3: AIGC via MCP guidance
│ └── utils/
│ ├── file-manager.ts # FileManager class — manifest-based asset CRUD, cleanup, size monitoring
│ └── terminal-image.ts # Kitty/iTerm2/Sixel image display protocols
├── tests/ # Vitest — 40 tests, mirrors src/ structure
├── docs/plan.md # Original project plan (Chinese)
├── .opencode/plugins/ # Local plugin loader for E2E testing
└── dist/ # tsc output — do not edit
WHERE TO LOOK
| Task | Location | Notes |
|---|---|---|
| Add new tool | src/tools/ + register in src/index.ts | Follow createXxxTool(fileManager) pattern |
| Add new hook | src/hooks/ + register in src/index.ts | Hook type from Hooks in @opencode-ai/plugin |
| Change output format | src/renderers/ | Mermaid: mmdc args. Matplotlib: wrapScript preamble |
| Asset management | src/utils/file-manager.ts | Manifest at {outputDir}/openprism-manifest.json |
| Config defaults | src/types.ts → DEFAULT_CONFIG | outputDir, tier toggles, cleanup thresholds |
| Type definitions | src/types.ts | All render options, results, asset records |
| Test a module | tests/{module}.test.ts | Real subprocess calls, temp dirs, no mocks |
CODE MAP
| Symbol | Type | Location | Role |
|---|---|---|---|
OpenPrismPlugin | Plugin (async fn) | src/index.ts:15 | Entry point — returns tools + hooks |
FileManager | Class | src/utils/file-manager.ts:25 | Central asset tracker, used by all tools/hooks |
renderMermaid | Function | src/renderers/mermaid-ssr.ts:44 | Calls mmdc, returns {filePath, format, size} |
renderMatplotlib | Function | src/renderers/matplotlib-bridge.ts:57 | Python subprocess, Agg backend injection |
extractMermaidBlocks | Function | src/renderers/mermaid-ssr.ts:99 | Regex extraction from markdown |
validateMermaidSyntax | Function | src/renderers/mermaid-ssr.ts:112 | Checks first line against valid diagram types |
detectPythonEnvironment | Function | src/renderers/matplotlib-bridge.ts:101 | Finds venv/conda/system Python |
wrapScript | Function | src/renderers/matplotlib-bridge.ts:36 | Injects Agg backend + savefig, strips plt.show() |
DEFAULT_CONFIG | Const | src/types.ts:186 | .opencode/plots, all tiers on, 500MB limit, 30d cleanup |
CONVENTIONS
- ESM only —
"type": "module", all imports use.jsextensions in compiled output import type— Use type-only imports for@opencode-ai/plugintypes (avoids runtime ESM resolution bug in that package)- Factory pattern — Tools:
createXxxTool(fileManager). Hooks:createXxxHook(fileManager | config) - No mocks in tests — Tests use real mmdc, real Python, real temp directories.
beforeEachcreates tmpdir,afterEachcleans up - Strict TypeScript —
noUnusedLocals,noUnusedParameters,strict: true. Noas anyor@ts-ignore - Vitest inline dep —
@opencode-ai/pluginmust be inlined in vitest config (broken internal./toolESM import)
ANTI-PATTERNS (THIS PROJECT)
- No
as any,@ts-ignore,@ts-expect-error— type safety is non-negotiable - No mocking in tests — real subprocess calls or skip the test
- No
plt.show()ormatplotlib.use()in user scripts —wrapScripthandles both - Do not edit
dist/— generated bytsc
COMMANDS
npm run build # tsc → dist/
npm run typecheck # tsc --noEmit
npm test # vitest run (40 tests, ~5s)
npm run test:watch # vitest (watch mode)
NOTES
@opencode-ai/pluginESM bug: Package'sdist/index.jsdoesexport * from "./tool"without.jsextension. Works at runtime in OpenCode (Bun), but fails in Node/vitest ESM. Workaround:server.deps.inlinein vitest config.- mmdc requires Chromium: First run of mermaid-cli downloads Puppeteer's Chromium. Tests may be slow on first execution.
- Python detection order: venv → conda (
CONDA_PREFIX) → system.detectPythonEnvironmentchecks{projectDir}/.venv/bin/python3first. - GitLab
mainis protected: Push to feature branches, not main. Remote:git@gitlab.mondorobotics.com:BrainholeCenter/openprism.git - OpenCode local plugin: Place
.tsfile in.opencode/plugins/to load. Already configured at.opencode/plugins/openprism.ts. - Asset manifest: JSON at
.opencode/plots/openprism-manifest.json. FileManager auto-persists onrecordAsset, lazy-loads ongetAssets.