diff --git a/AGENTS.md b/AGENTS.md index d31189a9e..afc6d07d1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,12 +1,24 @@ # PROJECT KNOWLEDGE BASE -**Generated:** 2026-01-25T13:10:00+09:00 -**Commit:** 043b1a33 +**Generated:** 2026-01-25T18:08:00+09:00 +**Commit:** 1d68757f **Branch:** dev +--- + +## **IMPORTANT: PULL REQUEST TARGET BRANCH** + +> **ALL PULL REQUESTS MUST TARGET THE `dev` BRANCH.** +> +> **DO NOT CREATE PULL REQUESTS TARGETING `master` BRANCH.** +> +> PRs to `master` will be automatically rejected by CI. + +--- + ## OVERVIEW -OpenCode plugin: multi-model agent orchestration (Claude Opus 4.5, GPT-5.2, Gemini 3 Flash, Grok Code, GLM-4.7). 31 lifecycle hooks, 20+ tools (LSP, AST-Grep, delegation), 10 specialized agents, full Claude Code compatibility. "oh-my-zsh" for OpenCode. +OpenCode plugin: multi-model agent orchestration (Claude Opus 4.5, GPT-5.2, Gemini 3 Flash, Grok Code). 32 lifecycle hooks, 20+ tools (LSP, AST-Grep, delegation), 10 specialized agents, full Claude Code compatibility. "oh-my-zsh" for OpenCode. ## STRUCTURE @@ -14,14 +26,14 @@ OpenCode plugin: multi-model agent orchestration (Claude Opus 4.5, GPT-5.2, Gemi oh-my-opencode/ ├── src/ │ ├── agents/ # 10 AI agents - see src/agents/AGENTS.md -│ ├── hooks/ # 31 lifecycle hooks - see src/hooks/AGENTS.md +│ ├── hooks/ # 32 lifecycle hooks - see src/hooks/AGENTS.md │ ├── tools/ # 20+ tools - see src/tools/AGENTS.md │ ├── features/ # Background agents, Claude Code compat - see src/features/AGENTS.md -│ ├── shared/ # 50 cross-cutting utilities - see src/shared/AGENTS.md +│ ├── shared/ # 55 cross-cutting utilities - see src/shared/AGENTS.md │ ├── cli/ # CLI installer, doctor - see src/cli/AGENTS.md │ ├── mcp/ # Built-in MCPs - see src/mcp/AGENTS.md │ ├── config/ # Zod schema, TypeScript types -│ └── index.ts # Main plugin entry (601 lines) +│ └── index.ts # Main plugin entry (669 lines) ├── script/ # build-schema.ts, build-binaries.ts ├── packages/ # 7 platform-specific binaries └── dist/ # Build output (ESM + .d.ts) @@ -38,8 +50,8 @@ oh-my-opencode/ | Add skill | `src/features/builtin-skills/` | Create dir with SKILL.md | | Add command | `src/features/builtin-commands/` | Add template + register in commands.ts | | Config schema | `src/config/schema.ts` | Zod schema, run `bun run build:schema` | -| Background agents | `src/features/background-agent/` | manager.ts (1335 lines) | -| Orchestrator | `src/hooks/atlas/` | Main orchestration hook (773 lines) | +| Background agents | `src/features/background-agent/` | manager.ts (1377 lines) | +| Orchestrator | `src/hooks/atlas/` | Main orchestration hook (752 lines) | ## TDD (Test-Driven Development) @@ -51,8 +63,8 @@ oh-my-opencode/ **Rules:** - NEVER write implementation before test - NEVER delete failing tests - fix the code -- Test file: `*.test.ts` alongside source -- BDD comments: `#given`, `#when`, `#then` +- Test file: `*.test.ts` alongside source (100 test files) +- BDD comments: `//#given`, `//#when`, `//#then` ## CONVENTIONS @@ -61,7 +73,7 @@ oh-my-opencode/ - **Build**: `bun build` (ESM) + `tsc --emitDeclarationOnly` - **Exports**: Barrel pattern via index.ts - **Naming**: kebab-case dirs, `createXXXHook`/`createXXXTool` factories -- **Testing**: BDD comments, 95 test files +- **Testing**: BDD comments, 100 test files - **Temperature**: 0.1 for code agents, max 0.3 ## ANTI-PATTERNS @@ -100,7 +112,7 @@ oh-my-opencode/ bun run typecheck # Type check bun run build # ESM + declarations + schema bun run rebuild # Clean + Build -bun test # 95 test files +bun test # 100 test files ``` ## DEPLOYMENT @@ -114,16 +126,14 @@ bun test # 95 test files | File | Lines | Description | |------|-------|-------------| -| `src/features/background-agent/manager.ts` | 1335 | Task lifecycle, concurrency | -| `src/features/builtin-skills/skills.ts` | 1203 | Skill definitions | +| `src/features/builtin-skills/skills.ts` | 1729 | Skill definitions | +| `src/features/background-agent/manager.ts` | 1377 | Task lifecycle, concurrency | | `src/agents/prometheus-prompt.ts` | 1196 | Planning agent | -| `src/tools/delegate-task/tools.ts` | 1039 | Category-based delegation | -| `src/hooks/atlas/index.ts` | 773 | Orchestrator hook | +| `src/tools/delegate-task/tools.ts` | 1070 | Category-based delegation | +| `src/hooks/atlas/index.ts` | 752 | Orchestrator hook | | `src/cli/config-manager.ts` | 664 | JSONC config parsing | +| `src/index.ts` | 669 | Main plugin entry | | `src/features/builtin-commands/templates/refactor.ts` | 619 | Refactor command template | -| `src/index.ts` | 601 | Main plugin entry | -| `src/tools/lsp/client.ts` | 596 | LSP JSON-RPC client | -| `src/agents/atlas.ts` | 572 | Atlas orchestrator agent | ## MCP ARCHITECTURE diff --git a/src/agents/AGENTS.md b/src/agents/AGENTS.md index ba74dcc41..950c70c5d 100644 --- a/src/agents/AGENTS.md +++ b/src/agents/AGENTS.md @@ -1,31 +1,27 @@ # AGENTS KNOWLEDGE BASE ## OVERVIEW - 10 AI agents for multi-model orchestration. Sisyphus (primary), Atlas (orchestrator), oracle, librarian, explore, multimodal-looker, Prometheus, Metis, Momus, Sisyphus-Junior. ## STRUCTURE - ``` agents/ -├── atlas.ts # Master Orchestrator (572 lines) -├── sisyphus.ts # Main prompt (450 lines) -├── sisyphus-junior.ts # Delegated task executor (135 lines) -├── dynamic-agent-prompt-builder.ts # Dynamic prompt generation (359 lines) +├── atlas.ts # Master Orchestrator (holds todo list) +├── sisyphus.ts # Main prompt (SF Bay Area engineer identity) +├── sisyphus-junior.ts # Delegated task executor (category-spawned) ├── oracle.ts # Strategic advisor (GPT-5.2) -├── librarian.ts # Multi-repo research (326 lines) -├── explore.ts # Fast grep (Grok Code) +├── librarian.ts # Multi-repo research (GitHub CLI, Context7) +├── explore.ts # Fast contextual grep (Grok Code) ├── multimodal-looker.ts # Media analyzer (Gemini 3 Flash) -├── prometheus-prompt.ts # Planning (1196 lines) -├── metis.ts # Plan consultant (315 lines) -├── momus.ts # Plan reviewer (444 lines) +├── prometheus-prompt.ts # Planning (Interview/Consultant mode, 1196 lines) +├── metis.ts # Pre-planning analysis (Gap detection) +├── momus.ts # Plan reviewer (Ruthless fault-finding) ├── types.ts # AgentModelConfig, AgentPromptMetadata ├── utils.ts # createBuiltinAgents(), resolveModelWithFallback() └── index.ts # builtinAgents export ``` ## AGENT MODELS - | Agent | Model | Temp | Purpose | |-------|-------|------|---------| | Sisyphus | anthropic/claude-opus-4-5 | 0.1 | Primary orchestrator | @@ -40,14 +36,12 @@ agents/ | Sisyphus-Junior | anthropic/claude-sonnet-4-5 | 0.1 | Category-spawned executor | ## HOW TO ADD - -1. Create `src/agents/my-agent.ts` exporting factory + metadata -2. Add to `agentSources` in `src/agents/utils.ts` -3. Update `AgentNameSchema` in `src/config/schema.ts` -4. Register in `src/index.ts` initialization +1. Create `src/agents/my-agent.ts` exporting factory + metadata. +2. Add to `agentSources` in `src/agents/utils.ts`. +3. Update `AgentNameSchema` in `src/config/schema.ts`. +4. Register in `src/index.ts` initialization. ## TOOL RESTRICTIONS - | Agent | Denied Tools | |-------|-------------| | oracle | write, edit, task, delegate_task | @@ -57,14 +51,13 @@ agents/ | Sisyphus-Junior | task, delegate_task | ## PATTERNS - -- **Factory**: `createXXXAgent(model?: string): AgentConfig` -- **Metadata**: `XXX_PROMPT_METADATA` with category, cost, triggers -- **Tool restrictions**: `createAgentToolRestrictions(tools)` or `createAgentToolAllowlist(tools)` -- **Thinking**: 32k budget tokens for Sisyphus, Oracle, Prometheus, Atlas +- **Factory**: `createXXXAgent(model: string): AgentConfig` +- **Metadata**: `XXX_PROMPT_METADATA` with category, cost, triggers. +- **Tool restrictions**: `createAgentToolRestrictions(tools)` or `createAgentToolAllowlist(tools)`. +- **Thinking**: 32k budget tokens for Sisyphus, Oracle, Prometheus, Atlas. ## ANTI-PATTERNS - -- **Trust reports**: NEVER trust "I'm done" - verify outputs -- **High temp**: Don't use >0.3 for code agents -- **Sequential calls**: Use `delegate_task` with `run_in_background` +- **Trust reports**: NEVER trust "I'm done" - verify outputs. +- **High temp**: Don't use >0.3 for code agents. +- **Sequential calls**: Use `delegate_task` with `run_in_background` for exploration. +- **Prometheus writing code**: Planner only - never implements. diff --git a/src/cli/AGENTS.md b/src/cli/AGENTS.md index fcd9d8131..4adc3a0d0 100644 --- a/src/cli/AGENTS.md +++ b/src/cli/AGENTS.md @@ -8,7 +8,7 @@ CLI entry: `bunx oh-my-opencode`. Interactive installer, doctor diagnostics. Com ``` cli/ -├── index.ts # Commander.js entry +├── index.ts # Commander.js entry (4 commands) ├── install.ts # Interactive TUI (520 lines) ├── config-manager.ts # JSONC parsing (664 lines) ├── types.ts # InstallArgs, InstallConfig @@ -18,7 +18,7 @@ cli/ │ ├── runner.ts # Check orchestration │ ├── formatter.ts # Colored output │ ├── constants.ts # Check IDs, symbols -│ ├── types.ts # CheckResult, CheckDefinition +│ ├── types.ts # CheckResult, CheckDefinition (114 lines) │ └── checks/ # 14 checks, 21 files │ ├── version.ts # OpenCode + plugin version │ ├── config.ts # JSONC validity, Zod @@ -38,36 +38,37 @@ cli/ | Command | Purpose | |---------|---------| -| `install` | Interactive setup | -| `doctor` | 14 health checks | -| `run` | Launch session | -| `get-local-version` | Version check | +| `install` | Interactive setup with provider selection | +| `doctor` | 14 health checks for diagnostics | +| `run` | Launch session with todo enforcement | +| `get-local-version` | Version detection and update check | -## DOCTOR CATEGORIES +## DOCTOR CATEGORIES (14 Checks) | Category | Checks | |----------|--------| | installation | opencode, plugin | -| configuration | config validity, Zod | +| configuration | config validity, Zod, model-resolution | | authentication | anthropic, openai, google | -| dependencies | ast-grep, comment-checker | +| dependencies | ast-grep, comment-checker, gh-cli | | tools | LSP, MCP | | updates | version comparison | ## HOW TO ADD CHECK 1. Create `src/cli/doctor/checks/my-check.ts` -2. Export from `checks/index.ts` -3. Add to `getAllCheckDefinitions()` +2. Export `getXXXCheckDefinition()` factory returning `CheckDefinition` +3. Add to `getAllCheckDefinitions()` in `checks/index.ts` ## TUI FRAMEWORK -- **@clack/prompts**: `select()`, `spinner()`, `intro()` -- **picocolors**: Terminal colors -- **Symbols**: ✓ (pass), ✗ (fail), ⚠ (warn) +- **@clack/prompts**: `select()`, `spinner()`, `intro()`, `outro()` +- **picocolors**: Terminal colors for status and headers +- **Symbols**: ✓ (pass), ✗ (fail), ⚠ (warn), ℹ (info) ## ANTI-PATTERNS -- **Blocking in non-TTY**: Check `process.stdout.isTTY` -- **Direct JSON.parse**: Use `parseJsonc()` -- **Silent failures**: Return warn/fail in doctor +- **Blocking in non-TTY**: Always check `process.stdout.isTTY` +- **Direct JSON.parse**: Use `parseJsonc()` from shared utils +- **Silent failures**: Return `warn` or `fail` in doctor instead of throwing +- **Hardcoded paths**: Use `getOpenCodeConfigPaths()` from `config-manager.ts` diff --git a/src/features/AGENTS.md b/src/features/AGENTS.md index 76e0f5db4..debfd9b50 100644 --- a/src/features/AGENTS.md +++ b/src/features/AGENTS.md @@ -2,24 +2,18 @@ ## OVERVIEW -Core feature modules + Claude Code compatibility layer. Background agents, skill MCP, builtin skills/commands, 5 loaders. +Core feature modules + Claude Code compatibility layer. Orchestrates background agents, skill MCPs, builtin skills/commands, and 16 feature modules. ## STRUCTURE ``` features/ -├── background-agent/ # Task lifecycle (1335 lines) +├── background-agent/ # Task lifecycle (1377 lines) │ ├── manager.ts # Launch → poll → complete -│ ├── concurrency.ts # Per-provider limits -│ └── types.ts # BackgroundTask, LaunchInput -├── skill-mcp-manager/ # MCP client lifecycle (520 lines) -│ ├── manager.ts # Lazy loading, cleanup -│ └── types.ts # SkillMcpConfig -├── builtin-skills/ # Playwright, git-master, frontend-ui-ux -│ └── skills.ts # 1203 lines -├── builtin-commands/ # ralph-loop, refactor, init-deep, start-work, remove-deadcode -│ ├── commands.ts # Command registry -│ └── templates/ # Command templates (4 files) +│ └── concurrency.ts # Per-provider limits +├── builtin-skills/ # Core skills (1729 lines) +│ └── skills.ts # agent-browser, dev-browser, frontend-ui-ux, git-master, typescript-programmer +├── builtin-commands/ # ralph-loop, refactor, ulw-loop, init-deep ├── claude-code-agent-loader/ # ~/.claude/agents/*.md ├── claude-code-command-loader/ # ~/.claude/commands/*.md ├── claude-code-mcp-loader/ # .mcp.json @@ -29,7 +23,10 @@ features/ ├── context-injector/ # AGENTS.md/README.md injection ├── boulder-state/ # Todo state persistence ├── hook-message-injector/ # Message injection -└── task-toast-manager/ # Background task notifications +├── task-toast-manager/ # Background task notifications +├── skill-mcp-manager/ # MCP client lifecycle (520 lines) +├── tmux-subagent/ # Tmux session management +└── ... (16 modules total) ``` ## LOADER PRIORITY @@ -44,8 +41,9 @@ features/ - **Lifecycle**: `launch` → `poll` (2s) → `complete` - **Stability**: 3 consecutive polls = idle -- **Concurrency**: Per-provider/model limits +- **Concurrency**: Per-provider/model limits via `ConcurrencyManager` - **Cleanup**: 30m TTL, 3m stale timeout +- **State**: Per-session Maps, cleaned on `session.deleted` ## SKILL MCP @@ -58,3 +56,4 @@ features/ - **Sequential delegation**: Use `delegate_task` parallel - **Trust self-reports**: ALWAYS verify - **Main thread blocks**: No heavy I/O in loader init +- **Direct state mutation**: Use managers for boulder/session state diff --git a/src/hooks/AGENTS.md b/src/hooks/AGENTS.md index 3eb01829e..d6a6ed588 100644 --- a/src/hooks/AGENTS.md +++ b/src/hooks/AGENTS.md @@ -1,16 +1,14 @@ # HOOKS KNOWLEDGE BASE ## OVERVIEW - -31 lifecycle hooks intercepting/modifying agent behavior. Events: PreToolUse, PostToolUse, UserPromptSubmit, Stop, onSummarize. +32 lifecycle hooks intercepting/modifying agent behavior. Events: PreToolUse, PostToolUse, UserPromptSubmit, Stop, onSummarize. ## STRUCTURE - ``` hooks/ -├── atlas/ # Main orchestration (773 lines) -├── anthropic-context-window-limit-recovery/ # Auto-summarize -├── todo-continuation-enforcer.ts # Force TODO completion (489 lines) +├── atlas/ # Main orchestration (752 lines) +├── anthropic-context-window-limit-recovery/ # Auto-summarize +├── todo-continuation-enforcer.ts # Force TODO completion ├── ralph-loop/ # Self-referential dev loop ├── claude-code-hooks/ # settings.json compat layer - see AGENTS.md ├── comment-checker/ # Prevents AI slop @@ -35,45 +33,63 @@ hooks/ ├── non-interactive-env/ # Non-TTY environment handling ├── start-work/ # Sisyphus work session starter ├── task-resume-info/ # Resume info for cancelled tasks -├── question-label-truncator/ # Auto-truncates question labels >30 chars +├── question-label-truncator/ # Auto-truncates question labels +├── category-skill-reminder/ # Reminds of category skills +├── empty-task-response-detector.ts # Detects empty responses +├── sisyphus-junior-notepad/ # Sisyphus Junior notepad └── index.ts # Hook aggregation + registration ``` ## HOOK EVENTS - | Event | Timing | Can Block | Use Case | |-------|--------|-----------|----------| -| PreToolUse | Before tool | Yes | Validate/modify inputs | -| PostToolUse | After tool | No | Append warnings, truncate | -| UserPromptSubmit | On prompt | Yes | Keyword detection | -| Stop | Session idle | No | Auto-continue | -| onSummarize | Compaction | No | Preserve state | +| UserPromptSubmit | `chat.message` | Yes | Keyword detection, slash commands | +| PreToolUse | `tool.execute.before` | Yes | Validate/modify inputs, inject context | +| PostToolUse | `tool.execute.after` | No | Truncate output, error recovery | +| Stop | `event` (session.stop) | No | Auto-continue, notifications | +| onSummarize | Compaction | No | Preserve state, inject summary context | ## EXECUTION ORDER +- **UserPromptSubmit**: keywordDetector → claudeCodeHooks → autoSlashCommand → startWork +- **PreToolUse**: questionLabelTruncator → claudeCodeHooks → nonInteractiveEnv → commentChecker → directoryAgentsInjector → directoryReadmeInjector → rulesInjector → prometheusMdOnly → sisyphusJuniorNotepad → atlasHook +- **PostToolUse**: claudeCodeHooks → toolOutputTruncator → contextWindowMonitor → commentChecker → directoryAgentsInjector → directoryReadmeInjector → rulesInjector → emptyTaskResponseDetector → agentUsageReminder → interactiveBashSession → editErrorRecovery → delegateTaskRetry → atlasHook → taskResumeInfo -**chat.message**: keywordDetector → claudeCodeHooks → autoSlashCommand → startWork → ralphLoop +## CRITICAL DEPENDENCIES -**tool.execute.before**: claudeCodeHooks → nonInteractiveEnv → commentChecker → directoryAgentsInjector → rulesInjector - -**tool.execute.after**: editErrorRecovery → delegateTaskRetry → commentChecker → toolOutputTruncator → claudeCodeHooks +| Hook | Depends On | State Sharing | +|------|------------|---------------| +| todo-continuation-enforcer | session-recovery callbacks | `isRecovering` flag | +| atlas | backgroundManager | Running task checks | +| start-work | boulder state file | `.sisyphus/boulder.json` | +| directory-*-injector | per-session caches | `sessionCaches` Map | ## HOW TO ADD - 1. Create `src/hooks/name/` with `index.ts` exporting `createMyHook(ctx)` 2. Add hook name to `HookNameSchema` in `src/config/schema.ts` -3. Register in `src/index.ts`: - ```typescript - const myHook = isHookEnabled("my-hook") ? createMyHook(ctx) : null - ``` +3. Register in `src/index.ts` and add to relevant lifecycle methods -## PATTERNS +## HOOK PATTERNS -- **Session-scoped state**: `Map>` -- **Conditional execution**: Check `input.tool` before processing -- **Output modification**: `output.output += "\n${REMINDER}"` +**Simple Single-Event**: +```typescript +export function createToolOutputTruncatorHook(ctx) { + return { "tool.execute.after": async (input, output) => { ... } } +} +``` + +**Multi-Event with State**: +```typescript +export function createThinkModeHook() { + const state = new Map() + return { + "chat.params": async (output, sessionID) => { ... }, + "event": async ({ event }) => { /* cleanup */ } + } +} +``` ## ANTI-PATTERNS - - **Blocking non-critical**: Use PostToolUse warnings instead -- **Heavy computation**: Keep PreToolUse light -- **Redundant injection**: Track injected files +- **Heavy computation**: Keep PreToolUse light to avoid latency +- **Redundant injection**: Track injected files to avoid context bloat +- **Direct state mutation**: Use `output.output +=` instead of replacing diff --git a/src/hooks/claude-code-hooks/AGENTS.md b/src/hooks/claude-code-hooks/AGENTS.md index 7e3496fc5..27ff024b9 100644 --- a/src/hooks/claude-code-hooks/AGENTS.md +++ b/src/hooks/claude-code-hooks/AGENTS.md @@ -1,51 +1,48 @@ # CLAUDE CODE HOOKS COMPATIBILITY ## OVERVIEW - -Full Claude Code settings.json hook compatibility. 5 lifecycle events: PreToolUse, PostToolUse, UserPromptSubmit, Stop, PreCompact. +Full Claude Code `settings.json` hook compatibility layer. Intercepts OpenCode events to execute external scripts/commands defined in Claude Code configuration. ## STRUCTURE - ``` claude-code-hooks/ ├── index.ts # Main factory (401 lines) ├── config.ts # Loads ~/.claude/settings.json -├── config-loader.ts # Extended config +├── config-loader.ts # Extended config (disabledHooks) ├── pre-tool-use.ts # PreToolUse executor ├── post-tool-use.ts # PostToolUse executor ├── user-prompt-submit.ts # UserPromptSubmit executor -├── stop.ts # Stop hook executor +├── stop.ts # Stop hook executor (with active state tracking) ├── pre-compact.ts # PreCompact executor ├── transcript.ts # Tool use recording -├── tool-input-cache.ts # Pre→post caching -├── types.ts # Hook types -└── todo.ts # Todo JSON fix +├── tool-input-cache.ts # Pre→post input caching +└── types.ts # Hook & IO type definitions ``` ## HOOK LIFECYCLE - -| Event | When | Can Block | Context | -|-------|------|-----------|---------| -| PreToolUse | Before tool | Yes | sessionId, toolName, toolInput | -| PostToolUse | After tool | Warn | + toolOutput, transcriptPath | -| UserPromptSubmit | On message | Yes | sessionId, prompt, parts | -| Stop | Session idle | inject | sessionId, parentSessionId | -| PreCompact | Before summarize | No | sessionId | +| Event | Timing | Can Block | Context Provided | +|-------|--------|-----------|------------------| +| PreToolUse | Before tool exec | Yes | sessionId, toolName, toolInput, cwd | +| PostToolUse | After tool exec | Warn | + toolOutput, transcriptPath | +| UserPromptSubmit | On message send | Yes | sessionId, prompt, parts, cwd | +| Stop | Session idle/end | Inject | sessionId, parentSessionId, cwd | +| PreCompact | Before summarize | No | sessionId, cwd | ## CONFIG SOURCES - Priority (highest first): -1. `.claude/settings.json` (project) -2. `~/.claude/settings.json` (user) +1. `.claude/settings.json` (Project-local) +2. `~/.claude/settings.json` (Global user) ## HOOK EXECUTION - -1. Hooks loaded from settings.json -2. Matchers filter by tool name -3. Commands via subprocess with `$SESSION_ID`, `$TOOL_NAME` -4. Exit codes: 0=pass, 1=warn, 2=block +- **Matchers**: Hooks filter by tool name or event type via regex/glob. +- **Commands**: Executed via subprocess with env vars (`$SESSION_ID`, `$TOOL_NAME`). +- **Exit Codes**: + - `0`: Pass (Success) + - `1`: Warn (Continue with system message) + - `2`: Block (Abort operation/prompt) ## ANTI-PATTERNS - -- **Heavy PreToolUse**: Runs before EVERY tool call -- **Blocking non-critical**: Use PostToolUse warnings +- **Heavy PreToolUse**: Runs before EVERY tool; keep logic light to avoid latency. +- **Blocking non-critical**: Prefer PostToolUse warnings for non-fatal issues. +- **Direct state mutation**: Use `updatedInput` in PreToolUse instead of side effects. +- **Ignoring Exit Codes**: Ensure scripts return `2` to properly block sensitive tools. diff --git a/src/mcp/AGENTS.md b/src/mcp/AGENTS.md index a9dceae96..9d38a1b29 100644 --- a/src/mcp/AGENTS.md +++ b/src/mcp/AGENTS.md @@ -2,7 +2,7 @@ ## OVERVIEW -3 remote MCP servers: web search, documentation, code search. HTTP/SSE transport. +3 remote MCP servers: web search, documentation, code search. HTTP/SSE transport. Part of three-tier MCP system. ## STRUCTURE @@ -20,10 +20,16 @@ mcp/ | Name | URL | Purpose | Auth | |------|-----|---------|------| -| websearch | mcp.exa.ai | Real-time web search | EXA_API_KEY | -| context7 | mcp.context7.com | Library docs | None | +| websearch | mcp.exa.ai/mcp?tools=web_search_exa | Real-time web search | EXA_API_KEY | +| context7 | mcp.context7.com/mcp | Library docs | None | | grep_app | mcp.grep.app | GitHub code search | None | +## THREE-TIER MCP SYSTEM + +1. **Built-in** (this directory): websearch, context7, grep_app +2. **Claude Code compat**: `.mcp.json` with `${VAR}` expansion +3. **Skill-embedded**: YAML frontmatter in skills (handled by skill-mcp-manager) + ## CONFIG PATTERN ```typescript @@ -54,5 +60,5 @@ const mcps = createBuiltinMcps(["websearch"]) // Disable specific ## NOTES - **Remote only**: HTTP/SSE, no stdio -- **Disable**: User can set `disabled_mcps: ["name"]` +- **Disable**: User can set `disabled_mcps: ["name"]` in config - **Exa**: Requires `EXA_API_KEY` env var diff --git a/src/shared/AGENTS.md b/src/shared/AGENTS.md index 14fb875e8..5808b55ff 100644 --- a/src/shared/AGENTS.md +++ b/src/shared/AGENTS.md @@ -1,81 +1,78 @@ # SHARED UTILITIES KNOWLEDGE BASE ## OVERVIEW - -34 cross-cutting utilities: path resolution, token truncation, config parsing, model resolution, agent display names. +55 cross-cutting utilities: path resolution, token truncation, config parsing, model resolution. ## STRUCTURE - ``` shared/ -├── logger.ts # File-based logging -├── permission-compat.ts # Agent tool restrictions -├── dynamic-truncator.ts # Token-aware truncation -├── frontmatter.ts # YAML frontmatter -├── jsonc-parser.ts # JSON with Comments -├── data-path.ts # XDG-compliant storage -├── opencode-config-dir.ts # ~/.config/opencode -├── claude-config-dir.ts # ~/.claude -├── migration.ts # Legacy config migration -├── opencode-version.ts # Version comparison -├── external-plugin-detector.ts # OAuth spoofing detection -├── model-requirements.ts # Agent/Category requirements -├── model-availability.ts # Models fetch + fuzzy match -├── model-resolver.ts # 3-step resolution -├── model-sanitizer.ts # Model ID normalization -├── shell-env.ts # Cross-platform shell -├── agent-display-names.ts # Agent display name mapping -├── agent-tool-restrictions.ts # Tool restriction helpers -├── agent-variant.ts # Agent variant detection -├── command-executor.ts # Subprocess execution -├── config-errors.ts # Config error types -├── deep-merge.ts # Deep object merge -├── file-reference-resolver.ts # File path resolution -├── file-utils.ts # File utilities -├── hook-disabled.ts # Hook enable/disable check -├── pattern-matcher.ts # Glob pattern matching -├── session-cursor.ts # Session cursor tracking -├── snake-case.ts # String case conversion -├── system-directive.ts # System prompt helpers -├── tool-name.ts # Tool name constants -├── zip-extractor.ts # ZIP file extraction -├── index.ts # Barrel export -└── *.test.ts # Colocated tests +├── tmux/ # Tmux TUI integration (types, utils, constants) +├── logger.ts # File-based logging (/tmp/oh-my-opencode.log) +├── dynamic-truncator.ts # Token-aware context window management (194 lines) +├── model-resolver.ts # 3-step resolution (Override → Fallback → Default) +├── model-requirements.ts # Agent/category model fallback chains (132 lines) +├── model-availability.ts # Provider model fetching & fuzzy matching (154 lines) +├── jsonc-parser.ts # JSONC parsing with comment support +├── frontmatter.ts # YAML frontmatter extraction (JSON_SCHEMA only) +├── data-path.ts # XDG-compliant storage resolution +├── opencode-config-dir.ts # ~/.config/opencode resolution (143 lines) +├── claude-config-dir.ts # ~/.claude resolution +├── migration.ts # Legacy config migration logic (231 lines) +├── opencode-version.ts # Semantic version comparison +├── permission-compat.ts # Agent tool restriction enforcement +├── system-directive.ts # Unified system message prefix & types +├── session-utils.ts # Session cursor, orchestrator detection +├── shell-env.ts # Cross-platform shell environment +├── agent-variant.ts # Agent variant from config +├── zip-extractor.ts # Binary/Resource ZIP extraction +├── deep-merge.ts # Recursive object merging (proto-pollution safe, MAX_DEPTH=50) +├── case-insensitive.ts # Case-insensitive object lookups +├── session-cursor.ts # Session message cursor tracking +├── command-executor.ts # Shell command execution (225 lines) +└── index.ts # Barrel export for all utilities ``` -## WHEN TO USE +## MOST IMPORTED +| Utility | Users | Purpose | +|---------|-------|---------| +| logger.ts | 16+ | Background task visibility | +| system-directive.ts | 8+ | Message filtering | +| opencode-config-dir.ts | 8+ | Path resolution | +| permission-compat.ts | 6+ | Tool restrictions | +## WHEN TO USE | Task | Utility | |------|---------| -| Debug logging | `log(message, data)` | -| Limit context | `dynamicTruncate(ctx, sessionId, output)` | -| Parse frontmatter | `parseFrontmatter(content)` | -| Load JSONC | `parseJsonc(text)` or `readJsoncFile(path)` | -| Restrict tools | `createAgentToolAllowlist(tools)` | -| Resolve paths | `getOpenCodeConfigDir()` | -| Compare versions | `isOpenCodeVersionAtLeast("1.1.0")` | -| Resolve model | `resolveModelWithFallback()` | -| Agent display name | `getAgentDisplayName(agentName)` | +| Path Resolution | `getOpenCodeConfigDir()`, `getDataPath()` | +| Token Truncation | `dynamicTruncate(ctx, sessionId, output)` | +| Config Parsing | `readJsoncFile(path)`, `parseJsonc(text)` | +| Model Resolution | `resolveModelWithFallback(client, reqs, override)` | +| Version Gating | `isOpenCodeVersionAtLeast(version)` | +| YAML Metadata | `parseFrontmatter(content)` | +| Tool Security | `createAgentToolAllowlist(tools)` | +| System Messages | `createSystemDirective(type)`, `isSystemDirective(msg)` | +| Deep Merge | `deepMerge(target, source)` | -## PATTERNS +## KEY PATTERNS +**3-Step Resolution** (Override → Fallback → Default): ```typescript -// Token-aware truncation -const { result } = await dynamicTruncate(ctx, sessionID, buffer) +const model = resolveModelWithFallback({ + userModel: config.agents.sisyphus.model, + fallbackChain: AGENT_MODEL_REQUIREMENTS.sisyphus.fallbackChain, + availableModels: fetchedModels, +}) +``` -// JSONC config -const settings = readJsoncFile(configPath) - -// Version-gated -if (isOpenCodeVersionAtLeast("1.1.0")) { /* ... */ } - -// Model resolution -const model = await resolveModelWithFallback(client, requirements, override) +**System Directive Filtering**: +```typescript +if (isSystemDirective(message)) return // Skip system-generated +const directive = createSystemDirective("TODO CONTINUATION") ``` ## ANTI-PATTERNS - -- **Raw JSON.parse**: Use `jsonc-parser.ts` -- **Hardcoded paths**: Use `*-config-dir.ts` -- **console.log**: Use `logger.ts` for background -- **Unbounded output**: Use `dynamic-truncator.ts` +- **Raw JSON.parse**: Use `jsonc-parser.ts` for comment support +- **Hardcoded Paths**: Use `*-config-dir.ts` or `data-path.ts` +- **console.log**: Use `logger.ts` for background task visibility +- **Unbounded Output**: Use `dynamic-truncator.ts` to prevent overflow +- **Manual Version Check**: Use `opencode-version.ts` for semver safety diff --git a/src/tools/AGENTS.md b/src/tools/AGENTS.md index 17a17aa5b..dcbc4e7e5 100644 --- a/src/tools/AGENTS.md +++ b/src/tools/AGENTS.md @@ -10,12 +10,12 @@ tools/ ├── [tool-name]/ │ ├── index.ts # Barrel export -│ ├── tools.ts # ToolDefinition +│ ├── tools.ts # ToolDefinition or factory │ ├── types.ts # Zod schemas │ └── constants.ts # Fixed values -├── lsp/ # 6 tools: definition, references, symbols, diagnostics, rename +├── lsp/ # 6 tools: definition, references, symbols, diagnostics, rename (client.ts 596 lines) ├── ast-grep/ # 2 tools: search, replace (25 languages) -├── delegate-task/ # Category-based routing (1039 lines) +├── delegate-task/ # Category-based routing (1070 lines, 302 nesting levels) ├── session-manager/ # 4 tools: list, read, search, info ├── grep/ # Custom grep with timeout ├── glob/ # 60s timeout, 100 file limit @@ -30,32 +30,46 @@ tools/ ## TOOL CATEGORIES -| Category | Tools | Purpose | +| Category | Tools | Pattern | |----------|-------|---------| -| LSP | lsp_goto_definition, lsp_find_references, lsp_symbols, lsp_diagnostics, lsp_prepare_rename, lsp_rename | Semantic code intelligence | -| Search | ast_grep_search, ast_grep_replace, grep, glob | Pattern discovery | -| Session | session_list, session_read, session_search, session_info | History navigation | -| Agent | delegate_task, call_omo_agent, background_output, background_cancel | Task orchestration | -| System | interactive_bash, look_at | CLI, multimodal | -| Skill | skill, skill_mcp, slashcommand | Skill execution | +| LSP | lsp_goto_definition, lsp_find_references, lsp_symbols, lsp_diagnostics, lsp_prepare_rename, lsp_rename | Direct | +| Search | ast_grep_search, ast_grep_replace, grep, glob | Direct | +| Session | session_list, session_read, session_search, session_info | Direct | +| Agent | delegate_task, call_omo_agent | Factory | +| Background | background_output, background_cancel | Factory | +| System | interactive_bash, look_at | Mixed | +| Skill | skill, skill_mcp, slashcommand | Factory | ## HOW TO ADD 1. Create `src/tools/[name]/` with standard files 2. Use `tool()` from `@opencode-ai/plugin/tool` 3. Export from `src/tools/index.ts` -4. Add to `builtinTools` object +4. Static tools → `builtinTools`, Factory → separate export -## LSP SPECIFICS +## TOOL PATTERNS -- **Client**: `client.ts` manages stdio, JSON-RPC (596 lines) -- **Singleton**: `LSPServerManager` with ref counting -- **Capabilities**: definition, references, symbols, diagnostics, rename +**Direct ToolDefinition**: +```typescript +export const grep: ToolDefinition = tool({ + description: "...", + args: { pattern: tool.schema.string() }, + execute: async (args) => result, +}) +``` -## AST-GREP SPECIFICS +**Factory Function** (context-dependent): +```typescript +export function createDelegateTask(ctx, manager): ToolDefinition { + return tool({ execute: async (args) => { /* uses ctx */ } }) +} +``` -- **Engine**: `@ast-grep/napi` for 25+ languages -- **Patterns**: `$VAR` (single), `$$$` (multiple) +## NAMING + +- **Tool names**: snake_case (`lsp_goto_definition`) +- **Functions**: camelCase (`createDelegateTask`) +- **Directories**: kebab-case (`delegate-task/`) ## ANTI-PATTERNS