Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 62 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,66 @@
# opencode-trace

This is a plugin designed to capture the raw json requests sent to the LLM, and the raw responses back (after streaming-delta consolidation). It saves them into ~/opencode-trace

## Usage
- End users should install it as an npm plugin via `"plugin": ["@ljw1004/opencode-trace"]` in `~/.config/opencode/opencode.json`.
- For development: `npm install` once, and change the plugin line to `["/path/to/opencode-trace/index.ts"]`. Then each time you edit, `npm run typecheck` and `npm run lint` and then exercise it `opencode run --dangerously-skip-permissions "why is the sky blue?"`. (It's using the existing opencode configuration to pick up your already-configured auth).
- For iterating on the viewer, you can copy `viewer.js` into your ~/opencode-trace directory, or copy examples into this directory, and they'll preferentially pick up `viewer.js` over their embedded viewer code.
- To deploy, bump version, `npm login`, `npm publish --dry-run`, `npm publish`. Verify with `npm view "@ljw1004/opencode-trace"`, then test it by installing as above.
- Traces are interactive `.html` files in `~/opencode-trace/`. Open them directly in a browser (works via `file://`).

## Enhanced Viewer
The viewer (embedded inline in each trace HTML or loaded from a sibling `viewer.js`) offers two modes:

### Enhanced Mode (default)
- **Top bar**: session meta, mode toggle (Enhanced/Classic), theme toggle (dark/light)
- **Summary bar**: token counts (input, output, cache read), tool calls, turns, errors
- **Tabs**:
- **Conversation**: collapsible turn cards with per-turn token chips (input/output/cache/ tools), tool-use callouts, error highlights
- **System**: auto-split system prompt by markdown headers (`^#` / `^##`) and `<available_skills>` blocks; skills rendered as structured list with name, description, location
- **Tools**: all declared tools with JSON schema previews
- **Usage**: stat cards + per-turn bar chart (input/cache_read/output) + system-section bar chart (by char count)
- **Raw**: collapsible JSON tree per raw event
- **LocalStorage persistence**: mode preference, theme preference

### Classic Mode
Legacy tree renderer (the original `<details>`-based tree). Access via the mode toggle in the top bar, or from the floating "Switch to Enhanced" button that appears in Classic mode.

## Development

```bash
npm install
npm run typecheck
npm run lint
```

- Change the plugin line to `["/path/to/opencode-trace/index.ts"]` in your opencode config.
- Exercise it: `opencode run --dangerously-skip-permissions "why is the sky blue?"`
- New traces will embed whatever `viewer.js` is current in the repo.

### Viewer iteration (no opencode restart needed)
1. Copy `viewer.js` into `~/opencode-trace/` — it will be loaded in preference to the embedded version
2. Refresh the trace HTML file in your browser to see changes instantly

### Testing the viewer
The viewer is tested with Playwright against real trace files. A test server is needed because Playwright doesn't support `file://`:

```bash
python3 -m http.server 8765 -d ~/opencode-trace
```

Then run test scripts that load `http://127.0.0.1:8765/<filename>.html` and verify tabs, turns, tools, etc. via Playwright selectors.

### Architecture
- `index.ts` (Node plugin): captures LLM request/response via fetch interception, writes traces as HTML with JSONL trailing comment
- `viewer.js`: standalone plain JS (no build step, no dependencies, no modules), read via `readFileSync` at trace-creation time and inlined in the HTML preamble
- CSS is injected via JS (`<style id="otv-styles">`) so the viewer works both embedded and as an external script
- JSONL is extracted from `document.lastChild` (`Node.COMMENT_NODE`), the trailing unterminated `<!--` comment

### Key implementation details
- Requests with `_purpose === "[meta]"` (title generation, etc.) are excluded from the main view (tools, system, firstUser)
- Streaming deltas are consolidated server-side in `index.ts` (SSE → JSON for Anthropic, OpenAI chat/responses formats)
- Classical mode defines `window.buildNode` for backward compatibility with the first-generation viewer

## Deployment
- Bump version in `package.json`
- `npm login`, `npm publish --dry-run`, `npm publish`
- Verify with `npm view "@ljw1004/opencode-trace"`
- Test by installing as described above
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,20 @@ Add the package to your OpenCode config:

Restart OpenCode and you'll see each transcript stored in `~/opencode-trace`.

## Viewer

Open any trace `.html` file directly in a browser (works via `file://`). The viewer offers two modes:

### Enhanced Mode (default)
- **Conversation tab**: collapsible turn cards with per-turn token chips (input, output, cache), tool-use callouts, error highlights
- **System tab**: system prompt auto-split by sections (markdown headers, skill definitions); skills shown as structured list
- **Tools tab**: all tool declarations with JSON schema previews
- **Usage tab**: stat cards + per-turn bar charts + system-section breakdown
- **Raw tab**: full JSON tree per raw event
- **Dark/light theme** toggle (persisted)
- **Mode toggle** to switch between Enhanced and Classic views (persisted)

### Classic Mode
The original `<details>`-based tree renderer. Access via the mode toggle.

That installation path by default uses `@latest`, which opencode currently does't refresh when latest changes. You can force a refresh with `rm -rf ~/.cache/opencode/packages/@ljw1004/opencode-trace@latest`
8 changes: 2 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading