mirror of
https://github.com/anomalyco/opencode.git
synced 2026-04-24 23:04:55 +00:00
6.8 KiB
6.8 KiB
AGENTS.md
Guide for coding agents working in this repository. Use this file for build/test commands and coding conventions.
Project Snapshot
- Stack: Bun + TypeScript (ESM, strict mode)
- App: Discord bot that provisions Daytona sandboxes
- Persistence: SQLite (
discord.sqlite, tablediscord_sessions) - Runtime flow: Discord thread -> sandbox -> OpenCode session
- Ops: structured JSON logs +
/healthzand/readyz
Repository Map
src/index.ts: startup, wiring, graceful shutdownsrc/config.ts: env schema and parsing (Zod)src/discord/: Discord client + handlers + routing logicsrc/sandbox/: sandbox lifecycle + OpenCode transportsrc/sessions/store.ts: SQLite-backed session storesrc/db/init.ts: idempotent DB schema initializationsrc/http/health.ts: health/readiness HTTP server.env.example: env contract
Setup and Run Commands
Install
bun install
First-time local setup
cp .env.example .env- Fill required secrets in
.env - Initialize schema:
bun run db:init
Development run
- Watch mode:
bun run dev - Normal run:
bun run start - Dev bootstrap helper:
bun run dev:setup
Static checks
- Typecheck:
bun run typecheck - Build:
bun run build - Combined check:
bun run check
Health checks
curl -s http://127.0.0.1:8787/healthzcurl -i http://127.0.0.1:8787/readyz
Testing Commands
There is no first-party test suite in src/ yet.
Use Bun test commands for new tests.
- Run all tests (if present):
bun test - Run a single test file:
bun test path/to/file.test.ts - Run one file in watch mode:
bun test --watch path/to/file.test.tsWhen adding tests, prefer colocated*.test.tsnear implementation files.
Cursor / Copilot Rules
Checked these paths:
.cursor/rules/.cursorrules.github/copilot-instructions.mdNo Cursor/Copilot rule files currently exist in this repo. If added later, update this file and follow those rules.
Code Style
TypeScript and modules
- Keep code strict-TypeScript compatible.
- Use ESM imports/exports only.
- Prefer named exports over default exports.
- Add explicit return types on exported functions.
Imports
- Group imports as: external first, then internal.
- Use
import typefor type-only imports. - Keep import paths consistent with existing relative style.
Formatting
- Match existing style:
- double quotes
- semicolons
- trailing commas where appropriate
- Keep functions small and focused.
- Avoid comments unless logic is non-obvious.
Naming
camelCase: variables/functionsPascalCase: classes/interfaces/type aliasesUPPER_SNAKE_CASE: env keys and constants- Log events should be stable (
domain.action.result).
Types and contracts
- Reuse shared types from
src/types.ts. - Preserve
SessionStatussemantics when adding new states. - Prefer
unknownoveranyat untrusted boundaries. - Narrow and validate external data before use.
Error Handling and Logging
- Use
loggerfromsrc/observability/logger.ts. - Do not add raw
console.login app paths. - Include context fields when available:
threadIdchannelIdguildIdsandboxIdsessionId
- Fail fast on invalid config in
src/config.ts. - Wrap network/process operations in contextual
try/catch. - Separate recoverable errors from terminal errors.
- Never log secret values.
Environment and Secrets
- Read env only through
getEnv(). - Update
.env.examplefor env schema changes. - Keep auth tokens out of command strings and logs.
- Pass runtime secrets via environment variables.
Domain-Specific Rules
Session lifecycle
- Session mapping (
thread_id,sandbox_id,session_id) is authoritative. - Resume existing sandbox/session before creating replacements.
- Recreate only when sandbox is unavailable/destroyed.
- If session changes, replay Discord thread history as fallback context.
Daytona behavior
stop()clears running processes but keeps filesystem state.start()requires process bootstrap (opencode serve).- Keep lifecycle transitions deterministic and observable.
OpenCode transport
- Keep preview token separate from persisted URL when possible.
- Send token using
x-daytona-preview-tokenheader. - Keep retry loops bounded and configurable.
Discord handler behavior
- Ignore bot/self chatter and respect mention/role gating.
- Preserve thread ownership checks for bot-managed threads.
- Keep outbound messages chunked for Discord size limits.
Non-Obvious Discoveries
OpenCode session persistence
- Sessions are disk-persistent JSON files in
~/.local/share/opencode/storage/session/<projectID>/ - Sessions survive
opencode serverestarts if filesystem intact AND process restarts from same git repo directory - Sessions are scoped by
projectID= git root commit hash (or"global"for non-git dirs) - After
daytona.start(), processes are guaranteed dead - always restartopencode serveimmediately, don't wait for health first (src/sandbox/manager.ts:400-420)
Session reattach debugging
- If
sessionExists()returns false but sandbox filesystem is intact, search by title (Discord thread <threadId>) vialistSessions()- session may exist under different ID due to OpenCode internal state changes - Thread lock per
threadIdprevents concurrent create/resume races (src/sandbox/manager.ts:614-632) - Never fall back to new sandbox when
daytona.start()succeeds - filesystem is intact, only OpenCode process needs restart
Discord + multiple processes
- Multiple bot processes with same
DISCORD_TOKENcause race conditions - one succeeds, others fail withDiscordAPIError[160004](thread already created) - PTY sessions with
exec bash -lstay alive after command exits, leading to duplicate bot runtimes if not cleaned up
Sandbox runtime auth
- Pass
GITHUB_TOKENas process env toopencode serveviasandbox.process.executeCommand()envparameter - Never interpolate tokens into command strings - use
envparameter inexec()options (src/sandbox/manager.ts:27-72)
Agent Workflow Checklist
Before coding
- Read related modules and follow existing patterns.
- Prefer narrow, minimal changes over broad refactors.
During coding
- Keep behavior backwards-compatible unless intentionally changing it.
- Keep changes cohesive (schema + store + manager together).
- Add/update logs for important lifecycle branches.
After coding
- Run
bun run typecheck - Run
bun run build - Run
bun run db:initfor schema-affecting changes - Smoke-check health endpoints if bootstrap/runtime changed
Git/PR Safety for Agents
- Do not commit or push unless explicitly requested.
- Do not amend commits unless explicitly requested.
- Avoid destructive git commands unless explicitly requested.
- Summaries should cite changed files and operational impact.