diff --git a/src/features/mcp-oauth/AGENTS.md b/src/features/mcp-oauth/AGENTS.md new file mode 100644 index 000000000..bca00331f --- /dev/null +++ b/src/features/mcp-oauth/AGENTS.md @@ -0,0 +1,54 @@ +# src/features/mcp-oauth/ — OAuth 2.0 + PKCE + DCR for MCP Servers + +**Generated:** 2026-02-19 + +## OVERVIEW + +18 files. Full OAuth 2.0 authorization flow for MCP servers requiring authentication. Implements PKCE (RFC 7636), Dynamic Client Registration (DCR, RFC 7591), and resource indicators (RFC 8707). Used by `bunx oh-my-opencode mcp-oauth login`. + +## AUTHORIZATION FLOW + +``` +1. discovery.ts → fetch /.well-known/oauth-authorization-server +2. dcr.ts → Dynamic Client Registration (if server supports it) +3. oauth-authorization-flow.ts → generate PKCE verifier/challenge +4. callback-server.ts → local HTTP server on random port for redirect +5. Open browser → authorization URL +6. callback-server.ts → receive code + state +7. provider.ts → exchange code for token (with PKCE verifier) +8. storage.ts → persist token to ~/.config/opencode/mcp-oauth/ +9. step-up.ts → handle step-up auth if initial token insufficient +``` + +## KEY FILES + +| File | Purpose | +|------|---------| +| `oauth-authorization-flow.ts` | PKCE helpers: `generateCodeVerifier()`, `generateCodeChallenge()`, `buildAuthorizationUrl()` | +| `callback-server.ts` | Local HTTP redirect server — listens for OAuth callback | +| `provider.ts` | `OAuthProvider` — token exchange, refresh, revoke | +| `discovery.ts` | Fetch + parse OAuth server metadata from well-known endpoint | +| `dcr.ts` | Dynamic Client Registration — register this app with OAuth server | +| `resource-indicator.ts` | RFC 8707 resource indicator handling | +| `step-up.ts` | Handle step-up authentication challenges | +| `storage.ts` | Persist tokens to `~/.config/opencode/mcp-oauth/{server-hash}.json` | +| `schema.ts` | Zod schemas for OAuth server metadata, token response, DCR | + +## PKCE IMPLEMENTATION + +- Code verifier: 32 random bytes → base64url (no padding) +- Code challenge: SHA-256(verifier) → base64url +- Method: `S256` + +## TOKEN STORAGE + +Location: `~/.config/opencode/mcp-oauth/` — one JSON file per MCP server (keyed by server URL hash). +Fields: `access_token`, `refresh_token`, `expires_at`, `client_id`. + +## CLI COMMANDS + +```bash +bunx oh-my-opencode mcp-oauth login # Full PKCE flow +bunx oh-my-opencode mcp-oauth logout # Revoke + delete token +bunx oh-my-opencode mcp-oauth status # List stored tokens +``` diff --git a/src/hooks/atlas/AGENTS.md b/src/hooks/atlas/AGENTS.md new file mode 100644 index 000000000..f541acf4c --- /dev/null +++ b/src/hooks/atlas/AGENTS.md @@ -0,0 +1,64 @@ +# src/hooks/atlas/ — Master Boulder Orchestrator + +**Generated:** 2026-02-19 + +## OVERVIEW + +17 files (~1976 LOC). The `atlasHook` — Continuation Tier hook that monitors session.idle events and forces continuation when boulder sessions (ralph-loop, task-spawned agents) have incomplete work. Also enforces write/edit policies for subagent sessions. + +## WHAT ATLAS DOES + +Atlas is the "keeper of sessions" — it tracks every session and decides: +1. Should this session be forced to continue? (if boulder session with incomplete todos) +2. Should write/edit be blocked? (policy enforcement for certain session types) +3. Should a verification reminder be injected? (after tool execution) + +## DECISION GATE (session.idle) + +``` +session.idle event + → Is this a boulder/ralph/atlas session? (session-last-agent.ts) + → Is there an abort signal? (is-abort-error.ts) + → Failure count < max? (state.promptFailureCount) + → No running background tasks? + → Agent matches expected? (recent-model-resolver.ts) + → Plan complete? (todo status) + → Cooldown passed? (5s between injections) + → Inject continuation prompt (boulder-continuation-injector.ts) +``` + +## KEY FILES + +| File | Purpose | +|------|---------| +| `atlas-hook.ts` | `createAtlasHook()` — composes event + tool handlers, maintains session state | +| `event-handler.ts` | `createAtlasEventHandler()` — decision gate for session.idle events | +| `boulder-continuation-injector.ts` | Build + inject continuation prompt into session | +| `system-reminder-templates.ts` | Templates for continuation reminder messages | +| `tool-execute-before.ts` | Block write/edit based on session policy | +| `tool-execute-after.ts` | Inject verification reminders post-tool | +| `write-edit-tool-policy.ts` | Policy: which sessions can write/edit? | +| `verification-reminders.ts` | Reminder content for verifying work | +| `session-last-agent.ts` | Determine which agent owns the session | +| `recent-model-resolver.ts` | Resolve model used in recent messages | +| `subagent-session-id.ts` | Detect if session is a subagent session | +| `sisyphus-path.ts` | Resolve `.sisyphus/` directory path | +| `is-abort-error.ts` | Detect abort signals in session output | +| `types.ts` | `SessionState`, `AtlasHookOptions`, `AtlasContext` | + +## STATE PER SESSION + +```typescript +interface SessionState { + promptFailureCount: number // Increments on failed continuations + // Resets on successful continuation +} +``` + +Max consecutive failures before 5min pause: 5 (exponential backoff in todo-continuation-enforcer). + +## RELATIONSHIP TO OTHER HOOKS + +- **atlasHook** (Continuation Tier): Master orchestrator, handles boulder sessions +- **todoContinuationEnforcer** (Continuation Tier): "Boulder" mechanism for main Sisyphus sessions +- Both inject into session.idle but serve different session types diff --git a/src/hooks/rules-injector/AGENTS.md b/src/hooks/rules-injector/AGENTS.md new file mode 100644 index 000000000..70a13b2c5 --- /dev/null +++ b/src/hooks/rules-injector/AGENTS.md @@ -0,0 +1,53 @@ +# src/hooks/rules-injector/ — Conditional Rules Injection + +**Generated:** 2026-02-19 + +## OVERVIEW + +19 files (~1604 LOC). The `rulesInjectorHook` — Tool Guard Tier hook that auto-injects AGENTS.md (and similar rule files) into context when a file in a directory is read, written, or edited. Proximity-based: closest rule file to the target path wins. + +## HOW IT WORKS + +``` +tool.execute.after (read/write/edit/multiedit) + → Extract file path from tool output + → Find rule files near that path (finder.ts) + → Already injected this session? (cache.ts) + → Inject rule content into tool output (injector.ts) +``` + +## TRACKED TOOLS + +`["read", "write", "edit", "multiedit"]` — triggers only on file manipulation tools. + +## KEY FILES + +| File | Purpose | +|------|---------| +| `hook.ts` | `createRulesInjectorHook()` — wires cache + injector, handles tool events | +| `injector.ts` | `createRuleInjectionProcessor()` — orchestrates find → cache → inject | +| `finder.ts` | `findRuleFiles()` + `calculateDistance()` — locate AGENTS.md near target path | +| `rule-file-finder.ts` | Walk directory tree to find AGENTS.md / .rules files | +| `rule-file-scanner.ts` | Scan for rule files in a directory | +| `matcher.ts` | Match file paths against rule file scope | +| `rule-distance.ts` | Calculate path distance between file and rule file | +| `project-root-finder.ts` | Find project root (stops at .git, package.json) | +| `output-path.ts` | Extract file paths from tool output text | +| `cache.ts` | `createSessionCacheStore()` — per-session injection dedup | +| `storage.ts` | Persist injected paths across tool calls | +| `parser.ts` | Parse rule file content | +| `constants.ts` | Rule file names: `AGENTS.md`, `.rules`, `CLAUDE.md` | +| `types.ts` | `RuleFile`, `InjectionResult`, `RuleFileScope` | + +## RULE FILE DISCOVERY + +Priority (closest → farthest from target file): +1. Same directory as target file +2. Parent directories up to project root +3. Project root itself + +Same-distance tie: all injected. Per-session dedup prevents re-injection. + +## TRUNCATION + +Uses `DynamicTruncator` — adapts injection size based on model context window (1M context models get full content, smaller models get truncated summaries). diff --git a/src/tools/background-task/AGENTS.md b/src/tools/background-task/AGENTS.md new file mode 100644 index 000000000..ee7404d94 --- /dev/null +++ b/src/tools/background-task/AGENTS.md @@ -0,0 +1,53 @@ +# src/tools/background-task/ — Background Task Tool Wrappers + +**Generated:** 2026-02-19 + +## OVERVIEW + +18 files. Tool-layer wrappers for `background_output` and `background_cancel`. Does NOT implement the background execution engine — that lives in `src/features/background-agent/`. This directory provides the LLM-facing tool interface. + +## THREE TOOLS + +| Tool | Factory | Purpose | +|------|---------|---------| +| `background_output` | `createBackgroundOutput` | Get results from a running/completed background task | +| `background_cancel` | `createBackgroundCancel` | Cancel running task(s) | +| `createBackgroundTask` | internal | Shared factory used by both | + +## KEY FILES + +| File | Purpose | +|------|---------| +| `create-background-output.ts` | `background_output` tool: fetch task results by task_id | +| `create-background-cancel.ts` | `background_cancel` tool: cancel by taskId or all=true | +| `create-background-task.ts` | Shared tool factory with common params | +| `clients.ts` | Client interfaces for background output and cancel | +| `session-messages.ts` | Fetch session messages from OpenCode | +| `full-session-format.ts` | Format full session output (messages, thinking blocks) | +| `task-result-format.ts` | Format task result for LLM consumption | +| `task-status-format.ts` | Format task status (running/completed/error) | +| `message-dir.ts` | Temp directory for message exchange | +| `truncate-text.ts` | Truncate large output to fit context | +| `time-format.ts` | Human-readable duration formatting | +| `delay.ts` | Polling delay utility | +| `types.ts` | `BackgroundTaskOptions`, result/status types | +| `constants.ts` | Timeout defaults, polling intervals | + +## BACKGROUND OUTPUT MODES + +``` +background_output(task_id, block=false) → check current status/result +background_output(task_id, block=true) → wait until complete (timeout default: 120s) +background_output(task_id, full_session=true) → return full session transcript +background_output(task_id, message_limit=N) → last N messages only +background_output(task_id, include_thinking=true) → include thinking blocks +``` + +## RELATIONSHIP TO BACKGROUND ENGINE + +``` +tools/background-task/ ← LLM tool interface +features/background-agent/ ← execution engine (BackgroundManager) +``` + +`createBackgroundOutput` queries `BackgroundManager.getTask(task_id)` — it does not manage task state. diff --git a/src/tools/call-omo-agent/AGENTS.md b/src/tools/call-omo-agent/AGENTS.md new file mode 100644 index 000000000..8fc796fe7 --- /dev/null +++ b/src/tools/call-omo-agent/AGENTS.md @@ -0,0 +1,51 @@ +# src/tools/call-omo-agent/ — Direct Agent Invocation Tool + +**Generated:** 2026-02-19 + +## OVERVIEW + +23 files. The `call_omo_agent` tool — direct invocation of named agents (explore, librarian only). Distinct from `delegate-task`: no category system, no skill loading, no model selection. Fixed agent set, same execution modes (background/sync). + +## DISTINCTION FROM delegate-task + +| Aspect | `call_omo_agent` | `delegate-task` (`task`) | +|--------|-----------------|--------------------------| +| Agent selection | Named agent (explore/librarian) | Category or subagent_type | +| Skill loading | None | `load_skills[]` supported | +| Model selection | From agent's fallback chain | From category config | +| Use case | Quick contextual grep | Full delegation with skills | + +## ALLOWED AGENTS + +Only `explore` and `librarian` — enforced via `ALLOWED_AGENTS` constant in `constants.ts`. Case-insensitive validation. + +## EXECUTION MODES + +Same two modes as delegate-task: + +| Mode | File | Description | +|------|------|-------------| +| **Background** | `background-agent-executor.ts` | Async via `BackgroundManager` | +| **Sync** | `sync-executor.ts` | Create session → wait for idle → return result | + +## KEY FILES + +| File | Purpose | +|------|---------| +| `tools.ts` | `createCallOmoAgent()` factory — validates agent, routes to executor | +| `background-executor.ts` | Routes to background or sync based on `run_in_background` | +| `background-agent-executor.ts` | Launch via `BackgroundManager.launch()` | +| `sync-executor.ts` | Synchronous session: create → send prompt → poll → fetch result | +| `session-creator.ts` | Create OpenCode session for sync execution | +| `subagent-session-creator.ts` | Create session with agent-specific config | +| `subagent-session-prompter.ts` | Inject prompt into session | +| `completion-poller.ts` | Poll until session idle | +| `session-completion-poller.ts` | Session-specific completion check | +| `session-message-output-extractor.ts` | Extract last assistant message as result | +| `message-processor.ts` | Process raw message content | +| `message-dir.ts` + `message-storage-directory.ts` | Temp storage for message exchange | +| `types.ts` | `CallOmoAgentArgs`, `AllowedAgentType`, `ToolContextWithMetadata` | + +## SESSION CONTINUATION + +Pass `session_id` to resume an existing session rather than create a new one — handled in both executors. diff --git a/src/tools/lsp/AGENTS.md b/src/tools/lsp/AGENTS.md new file mode 100644 index 000000000..9045bcf88 --- /dev/null +++ b/src/tools/lsp/AGENTS.md @@ -0,0 +1,70 @@ +# src/tools/lsp/ — LSP Tool Implementations + +**Generated:** 2026-02-19 + +## OVERVIEW + +32 files. Full LSP (Language Server Protocol) client stack exposed as 6 tools. Custom implementation that manages server processes, opens files, and forwards requests — does NOT delegate to OpenCode's built-in LSP. + +## TOOL EXPOSURE + +| Tool | File | What It Does | +|------|------|--------------| +| `lsp_goto_definition` | `goto-definition-tool.ts` | Jump to symbol definition | +| `lsp_find_references` | `find-references-tool.ts` | All usages of a symbol | +| `lsp_symbols` | `symbols-tool.ts` | Document outline or workspace symbol search | +| `lsp_diagnostics` | `diagnostics-tool.ts` | Errors/warnings from language server | +| `lsp_prepare_rename` | `rename-tools.ts` | Validate rename before applying | +| `lsp_rename` | `rename-tools.ts` | Apply safe rename across workspace | + +All 6 are direct `ToolDefinition` objects (not factory functions) — registered directly in `tool-registry.ts`. + +## ARCHITECTURE + +``` +tools.ts (6 ToolDefinition exports) + ↓ uses +LspClientWrapper (lsp-client-wrapper.ts) + ↓ wraps +LSPClient (lsp-client.ts) extends LSPClientConnection (lsp-client-connection.ts) + ↓ communicates via +LSPClientTransport (lsp-client-transport.ts) + ↓ talks to +LSPProcess (lsp-process.ts) — spawns server binary +``` + +## KEY FILES + +| File | Purpose | +|------|---------| +| `lsp-client-wrapper.ts` | High-level entry: resolves server, opens file, runs request | +| `lsp-client.ts` | `LSPClient` — file tracking, document sync (`didOpen`/`didChange`) | +| `lsp-client-connection.ts` | JSON-RPC request/response/notification layer | +| `lsp-client-transport.ts` | stdin/stdout byte-stream framing | +| `lsp-process.ts` | Spawn + cleanup of LSP server process | +| `lsp-manager-process-cleanup.ts` | Reap orphan LSP processes on exit | +| `lsp-manager-temp-directory-cleanup.ts` | Clean temp dirs used by some servers | +| `server-definitions.ts` | 40+ builtin servers synced from OpenCode's `server.ts` | +| `server-config-loader.ts` | Load custom server config from `.opencode/lsp.json` | +| `server-resolution.ts` | Resolve which server handles a file extension | +| `server-installation.ts` | Detect missing binaries, surface install hints | +| `language-mappings.ts` | Extension → language ID mapping | +| `lsp-formatters.ts` | Format LSP responses into human-readable strings | +| `workspace-edit.ts` | Apply `WorkspaceEdit` results to disk (for rename) | +| `types.ts` | `LSPServerConfig`, `Position`, `Range`, `Location`, `Diagnostic` etc. | + +## SERVER RESOLUTION + +``` +file.ts → extension (.ts) → language-mappings → server ID (typescript) + → server-resolution: check user config (.opencode/lsp.json) → fall back to server-definitions.ts + → server-installation: verify binary exists (warn with install hint if not) + → LSPProcess.spawn(command[]) +``` + +## NOTES + +- File must be opened via `didOpen` before any LSP request — `LSPClient.openFile()` handles this +- 1s delay after `didOpen` for server initialization before sending requests +- `lsp_servers` tool was removed — duplicates OpenCode's built-in `LspServers` tool +- Synced with OpenCode's `server.ts` — when adding servers, check upstream first