Skip to content
Merged
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
71 changes: 71 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# AGENTS.md

## What This Project Is

**opencode-otel** — an OpenCode npm plugin that forwards runtime stderr logs to any OTLP-compatible log collector via gRPC or HTTP. Business-level observability (session traces, tool calls) is handled separately by opencode-plugin-langfuse; this plugin only ships runtime logs and correlates them to sessions via traceId.

## Commands

```bash
bun install # install deps (uses bun.lock)
bun test # run all unit tests
bun run build # tsup → dist/index.js (ESM + .d.ts)
```

There is no linter, formatter, or typecheck script configured. The build command is the only verification beyond tests. `prepublishOnly` runs the build automatically.

## Tech Stack

- **TypeScript 5.5+** on **Bun** runtime — not Node
- **tsup** builds ESM only; configured inline in `package.json` (no tsup.config file)
- `@opencode-ai/plugin@>=1.1.0` is a **peer dependency** — must be external in builds
- `tsconfig.json` uses `"noEmit": true` with strict mode; the build is handled entirely by tsup
- No `.eslintrc`, `.prettierrc`, or `biome.json` exists

## Architecture

```text
src/index.ts ← plugin entry, orchestration only (returns {event} hook)
src/config.ts ← env vars > otel.json config file > defaults
src/provider.ts ← LoggerProvider (gRPC or HTTP) + BasicTracerProvider (gRPC only)
src/interceptor.ts ← monkey-patch process.stderr.write, line buffering, severity parsing
src/session.ts ← Map<sessionId, Span> for log-to-session trace correlation
src/shutdown.ts ← graceful flush on beforeExit/SIGTERM/SIGINT
src/version.ts ← reads version from package.json at runtime (never hard-coded)
```

## Key Constraints

- **Cannot modify OpenCode source** — integration via npm plugin `event` hook only
- **Monkey-patch `process.stderr.write`** — interceptor has a recursion guard (`inEmit` flag); if emit callback writes to stderr it is silently skipped
- **Session tracking uses a module-level Map, not AsyncLocalStorage** — `session.ts` tracks the active session via a plain variable (`activeSessionId`); concurrent session interleaving will mis-tag logs
- **Trace exporter only supports gRPC** — if a non-gRPC traces protocol is configured, trace export is disabled with a warning
- **Plugin stays inactive** if `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` is not set — logs a status message via the app logger but does not install the interceptor

## Config Precedence

For most settings: **env var → otel.json config file → default**

`service.name` has a deeper chain: `OTEL_SERVICE_NAME` → `OTEL_RESOURCE_ATTRIBUTES[service.name]` → `otel.json serviceName` → `PAAS_APP_APPID` → `"opencode-agent"`

Config file default path: `~/.config/opencode/plugins/otel.json` (override with `OTEL_PLUGIN_CONFIG_PATH`). The config file supports `${ENV_VAR}` placeholders.

## Testing

- Tests live in `tests/unit/` — three files covering config, provider, and interceptor
- Tests manipulate `process.env` directly; they run in Bun's test runner (`bun test`)
- Provider tests validate the candidate-based resource attribute resolution and BAT runtime metadata backfilling
- No integration tests, no test services, no fixtures needed

## CI / Publishing

- **publish.yml**: triggered by `v*` tags → `bun install` → `bun test` → `bun run build` → `npm publish` (requires `NPM_TOKEN` secret)
- Two Claude Code review workflows exist for PR automation (read-only)

## Specs

Design documents are in `specs/`. Key references:
- `specs/constitution.md` — project principles
- `specs/010-stderr-log-forwarder/` — current feature spec
- `specs/011-align-bat-otel/` — BAT OTEL alignment spec
- Directory-level `CLAUDE.md` files throughout the repo define ownership boundaries for Claude Code sessions
Loading