1. 前言
不同的LLM有自己所擅长的边界,就目前三个常用的前沿LLM来看,都能找到自己的甜品区,没有谁全方面碾压谁的说法。
Opus4.6在推理方面弱于Codex且经常多做多错,但它算是六边形战士,整体能力体现在社区一边骂A社一边又不得不捏着鼻子忍着就可见一班。缺点嘛就是除了封大陆的号+歧视国人,A社的费用也是不得不品鉴的一环,除非公司有Business套餐,不然一般不会考虑作为主力模型。Codex5.3 xhigh/high在推理方面很强,代码修改与执行几乎可以一次成型,但是总结的文档这一块惨不忍睹,经常给些人类看不懂的描述。虽然比起GPT-5.2已经有足够的进步,但执行速度还是较慢。前端界面上做的不太好,弱于Opus4.6较多。这段时间OpenAI在推广其Codex Plan让其变得经济实惠,第三方中转站缓存做的好的性价比非常高。Gemini 3.1 Pro,又称哈基米,Coding这块除了前端以外比不上前面那俩,多模态能力极强但我用不上,遵循指令稳定性相对于Codex5.3来说还是稍差一丢丢。幻觉对比其智商有点过于严重,这也是为什么Coding不如前面两个,一次成型的前端界面更适合它的发挥。
前面我折腾过Codex在Claude Code CLI下面跑,只开启必要的skill、mcp、rule后,表现也还行。
不过在深度使用它们一段时间后,偶然间看到OpenCode以及社区提到的multiple agents方案,遂尝试一下,开篇博客做一做记录。
2. 环境
系统:Linux KUbuntu 24.04 LTS
内核版本:6.17.0-14-generic #14~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC
3. LLM
| 名称 | 来源 | 作用 |
|---|---|---|
| GPT-5.3-Codex xhigh / high | Right Code | 阅读上下文、分派Sub Agents、所有逻辑实现(包括前端逻辑),主力。 |
| Claude Code Opus-4-6 Thinking | Antigravity反代 | 编排Plan、文档总结,不做任何的代码阅读,仅靠Codex提供的Context。 |
| Gemini 3.1 Pro | Antigravity反代 | 仅负责前端界面的组件排布以及CSS,别的就不劳烦哈基米了。 |
| GPT-5.3-Codex medium | Right Code | 执行一些简单的任务,比如说标题提取,简单注释等轻量级工作。本来想使用Gemini 2.5 Flash Lite,但思来想去对比反代出来的模型,Codex的中转便宜且可靠性强,还是Codex吧。 |
4. OpenCode安装
直接使用官方推荐的方式:
curl -fsSL https://opencode.ai/install | bash具体配置请参考官方文档。
5. OpenCode配置示例
注意,不同的provider有不同的要求,请在OpenCode或者对应的第三方中转站供应商那边获取对接OpenCode的参数,这里仅代表我个人的参数。
请善用MiroThinker总结社区讨论,选择符合自己情况的配置。
具体配置的含义请参考官方文档
{ "$schema": "https://opencode.ai/config.json", "provider": { "RCode_OpenAI": { "npm": "@ai-sdk/openai", "name": "RCode_OpenAI", "options": { "setCacheKey": true, "baseURL": "{env:RCODE_OPENAI_BASE_URL}", "apiKey": "{env:RCODE_OPENAI_API_KEY}" }, "models": { "gpt-5.3-codex": { "name": "GPT-5.3 Codex", "attachment": true, "reasoning": true, "tool_call": true, "temperature": false, "cost": { "input": 1.75, "output": 14, "cache_read": 0.175 }, "limit": { "context": 272000, "output": 128000 }, "options": { "store": false, "reasoningEffort": "high", "textVerbosity": "low", "reasoningSummary": "auto", "promptCacheKey": "opencode-stable-user", "include": [ "reasoning.encrypted_content" ] }, "headers": { "x-session-id": "opencode-stable-user", "conversation_id": "opencode-stable-user", "session_id": "opencode-stable-user" }, "variants": { "xhigh": { "reasoningEffort": "xhigh", "textVerbosity": "low", "reasoningSummary": "auto" }, "high": { "reasoningEffort": "high", "textVerbosity": "low", "reasoningSummary": "auto" }, "medium": { "reasoningEffort": "medium", "textVerbosity": "low", "reasoningSummary": "auto" }, "low": { "reasoningEffort": "low", "textVerbosity": "low", "reasoningSummary": "auto" } } } } },200 collapsed lines
"antigravity-manager": { "name": "Antigravity Manager", "npm": "@ai-sdk/anthropic", "models": { "gemini-3.1-pro-high": { "name": "Gemini 3 Pro High", "reasoning": true, "limit": { "context": 1048576, "output": 65535 }, "modalities": { "input": [ "text", "image", "pdf" ], "output": [ "text", "image" ] }, "variants": { "low": { "thinkingLevel": "low" }, "high": { "thinkingLevel": "high" } } }, "gemini-2.5-flash": { "name": "Gemini 2.5 Flash", "limit": { "context": 1048576, "output": 65536 }, "modalities": { "input": [ "text", "image", "pdf" ], "output": [ "text" ] } }, "claude-opus-4-6-thinking": { "name": "Antigravity Opus 4.6 Thinking", "reasoning": true, "limit": { "context": 200000, "output": 64000 }, "modalities": { "input": [ "text", "image", "pdf" ], "output": [ "text" ] }, "variants": { "low": { "thinkingConfig": { "thinkingBudget": 8192 }, "thinking": { "type": "enabled", "budgetTokens": 8192 } }, "medium": { "thinkingConfig": { "thinkingBudget": 16384 }, "thinking": { "type": "enabled", "budgetTokens": 16384 } }, "high": { "thinkingConfig": { "thinkingBudget": 24576 }, "thinking": { "type": "enabled", "budgetTokens": 24576 } }, "max": { "thinkingConfig": { "thinkingBudget": 32768 }, "thinking": { "type": "enabled", "budgetTokens": 32768 } } } }, "gemini-2.5-flash-lite": { "name": "Gemini 2.5 Flash Lite", "limit": { "context": 1048576, "output": 65536 }, "modalities": { "input": [ "text", "image", "pdf" ], "output": [ "text" ] } }, "claude-sonnet-4-5": { "name": "Antigravity Sonnet 4.5", "limit": { "context": 200000, "output": 64000 }, "modalities": { "input": [ "text", "image", "pdf" ], "output": [ "text" ] } }, "claude-sonnet-4-5-thinking": { "name": "Antigravity Sonnet 4.5 Thinking", "reasoning": true, "limit": { "context": 200000, "output": 64000 }, "modalities": { "input": [ "text", "image", "pdf" ], "output": [ "text" ] }, "variants": { "low": { "thinkingConfig": { "thinkingBudget": 8192 }, "thinking": { "type": "enabled", "budgetTokens": 8192 } }, "medium": { "thinkingConfig": { "thinkingBudget": 16384 }, "thinking": { "type": "enabled", "budgetTokens": 16384 } }, "high": { "thinkingConfig": { "thinkingBudget": 24576 }, "thinking": { "type": "enabled", "budgetTokens": 24576 } }, "max": { "thinkingConfig": { "thinkingBudget": 32768 }, "thinking": { "type": "enabled", "budgetTokens": 32768 } } } } }, "options": { "apiKey": "{env:ANTIGRAVITY_MANAGER_API_KEY}", "baseURL": "http://127.0.0.1:8045/v1" } } }, "model": "RCode_OpenAI/gpt-5.3-codex", "small_model": "antigravity-manager/gemini-2.5-flash-lite", "agent": { "general": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "medium" }, "doc-updater": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "medium" }, "go-build-resolver": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "xhigh" } }, "skills": { "paths": [ "/home/meteor/.config/opencode/skills" ] }, "instructions": [ "/home/meteor/.config/opencode/rules/core.md", "/home/meteor/.config/opencode/rules/ddd-hard-constraints.md" ], "mcp": { "context7": { "type": "local", "command": [ "node", "/home/meteor/.config/opencode/scripts/mcp/local-runner.js", "context7" ], "enabled": true }, "sequential-thinking": { "type": "local", "command": [ "pnpm", "dlx", "@modelcontextprotocol/server-sequential-thinking" ], "enabled": false }, "github": { "type": "local", "command": [ "node", "/home/meteor/.config/opencode/scripts/mcp/local-runner.js", "github" ], "enabled": true, "environment": { "GITHUB_PERSONAL_ACCESS_TOKEN": "{env:GITHUB_PERSONAL_ACCESS_TOKEN}" } }, "playwright": { "type": "local", "command": [ "pnpm", "exec", "playwright-mcp" ], "enabled": false } }, "plugin": [ "oh-my-opencode" ], "disabled_providers": []}6. Oh-My-OpenCode插件
这是一个社区增强版的插件,主要用于编排LLM Agent的任务分配,详见文档。
当然,按照官方的说法,其实人类不需要亲自观看这个文档,让LLM看并且执行即可。
那我的作用是什么呢?
Read this and tell me why it's not just another boilerplate: https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/refs/heads/dev/README.md原来我只是给LLM大人的签名跟提权的 :(
这是经过集合社区讨论以及自身需求编排后的oh-my-opencode.jsonc配置
简单地来说,就是:
Codex5.3阅读代码,发送Context给Opus4.6。Opus4.6根据上下文拟定Plan返回给Codex5.3。Codex5.3将Plan拆成多个Sub Agents执行互相独立的任务分配给不同的角色。- 前端纯界面交给
Gemini 3.1 Pro,逻辑则是Codex视情况给自己创建Sub Agents执行,执行完后如果有生成文档的需求则将Context交给Opus4.6。 - 这些任务有些可以并行,有些会依赖于其它任务的结果,这些都不需要你去操心,在下方的
Prompt中已经规定了边界。 - 分任务的前提条件:3个及以上独立子任务/跨层级修改(同时修改UI+业务逻辑+单测)/执行时间超过5min/有明显的并行处理依赖关系。
- 默认情况下走单模型完成任务(简单情况下),文档我做了权重优先,有明确文档需求的会走
Opus4.6,如果不喜欢这样的行为,你也可以自行对Prompt进行调整。
当然,你也可以选择手动挡分配,如果你更信任自己的话,可以命令式调用Agent,这个就不细节展开了。
{ // 参考配置:Codex 总控 + Opus 规划/文档 + 前端逻辑走 Codex、纯界面走 Gemini "$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json", // agents:定义各角色模型与行为约束 "agents": { // atlas:总控调度者(先读代码并打包 Context Pack,再交给 sisyphus 规划) "atlas": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "medium", "reasoningEffort": "medium", "prompt_append": "You are the orchestrator. Default to solo execution and minimal process. Delegate only when there are at least 3 independent workstreams, clear cross-layer coupling, or estimated time above 15 minutes. Exception: when the user explicitly asks for a report/summary document, always route documentation generation to an Opus-based agent (prefer sisyphus or librarian) regardless task size. For solo tasks, skip Context Pack and planning ceremony, read only relevant files, implement directly, and keep output concise. For delegated tasks, create a short Context Pack, call sisyphus only when requirements/architecture risk is high, then dispatch logic work to hephaestus and pure UI work to multimodal-looker. Always output one line: Dispatch Decision: mode, reason, waves, agent_count." }, // sisyphus:只做规划与文档,不直接读仓库和写代码 "sisyphus": { "model": "antigravity-manager/claude-opus-4-6-thinking", "variant": "medium", "prompt_append": "You are responsible only for planning, task decomposition, acceptance criteria, and post-task documentation. Work strictly from the Context Pack provided by atlas. Do not read workspace code, do not run commands, and do not browse the repository yourself. Output contract: in PLAN_MODE, output exactly one result type: either 'Plan' or 'Missing Info Checklist' (and nothing else). In DOC_MODE, output a human-friendly, blog-style 'Work Report' that explains what was implemented, why it was done, key file-level changes, validation results, and known risks/next steps. If context is insufficient, output only 'Missing Info Checklist' and wait for atlas to refresh the Context Pack. Do not produce large code implementations and do not modify project files.", "fallback_models": [ "RCode_OpenAI/gpt-5.3-codex" ] }, "sisyphus-junior": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "high" }, "hephaestus": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "high", "reasoningEffort": "high", "prompt_append": "You own engineering implementation and logic: backend, frontend business logic, state management, data flow, API integration, form validation, tests, refactoring, and bug fixes. Do not own pure visual design/styling work; route those to multimodal-looker." }, // multimodal-looker:仅负责纯界面与视觉层(走 Gemini 3.1 Pro High) "multimodal-looker": { "model": "antigravity-manager/gemini-3.1-pro-high", "variant": "high", "prompt_append": "You own only pure UI and visual layer work: layout, styling, motion, accessibility, and responsive behavior. Do not implement business logic, API calls, complex state management, or domain rules; route those tasks back to hephaestus.", "fallback_models": [ "RCode_OpenAI/gpt-5.3-codex" ] },70 collapsed lines
"oracle": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "high", "prompt_append": "You are responsible for code review, regression risk checks, and test recommendations." }, "momus": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "medium" }, "librarian": { "model": "antigravity-manager/claude-opus-4-6-thinking", "variant": "low", "prompt_append": "You are responsible for documentation curation, change summaries, and external-facing explanation drafts.", "fallback_models": [ "RCode_OpenAI/gpt-5.3-codex" ] }, "explore": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "high", "fallback_models": [ "RCode_OpenAI/gpt-5.3-codex" ] } }, // categories:按任务类型选择默认模型 "categories": { // planning:默认交给 Opus;writing:文档走 Opus "planning": { "model": "antigravity-manager/claude-opus-4-6-thinking", "variant": "medium", "fallback_models": [ "RCode_OpenAI/gpt-5.3-codex" ] }, "writing": { "model": "antigravity-manager/claude-opus-4-6-thinking", "variant": "low", "fallback_models": [ "RCode_OpenAI/gpt-5.3-codex" ] }, "writing-fast": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "medium" }, "visual-engineering": { "model": "antigravity-manager/gemini-3.1-pro-high", "variant": "high", "fallback_models": [ "RCode_OpenAI/gpt-5.3-codex" ] }, "frontend-logic": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "xhigh" }, "deep": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "xhigh" }, "quick": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "medium" }, "unspecified-low": { "model": "RCode_OpenAI/gpt-5.3-codex", "variant": "medium" } }, // runtime_fallback:运行时失败回退策略 "runtime_fallback": { "enabled": true, "max_fallback_attempts": 2, "timeout_seconds": 60, "notify_on_fallback": true }, // background_task:并发控制(总并发 + provider 并发) "background_task": { "defaultConcurrency": 6, "providerConcurrency": { "RCode_OpenAI": 12, "antigravity-manager": 4 }, "modelConcurrency": { "RCode_OpenAI/gpt-5.3-codex": 10, "antigravity-manager/gemini-3.1-pro-high": 3 } }, // 关闭claude_code兼容,全部使用opencode本身的模块。 "claude_code": { "mcp": false, "commands": false, "skills": false, "agents": false, "hooks": false, "plugins": false }}7. 实战效果
[analyze-mode]ANALYSIS MODE. Gather context before diving deep:
CONTEXT GATHERING (parallel):- 1-2 explore agents (codebase patterns, implementations)- 1-2 librarian agents (if external library involved)- Direct tools: Grep, AST-grep, LSP for targeted searches
IF COMPLEX - DO NOT STRUGGLE ALONE. Consult specialists:- **Oracle**: Conventional problems (architecture, debugging, complex logic)- **Artistry**: Non-conventional problems (different approach needed)
SYNTHESIZE findings before proceeding.
---
检查一下整个项目,需要加上: 模块的Agent.md,模块的Readme.md,通用模块的Agent.md以及Readme.md。最后,加上一个最简短的项目级的Rule.md。
Thinking: Planning comprehensive context gathering→ Read .✱ Glob "**/*Agent.md" in .✱ Glob "**/*README.md" in .✱ Glob "**/*Readme.md" in .Thinking: Establishing preliminary todo step# Todos[•]Complete ALL tasks in work plan[ ]Analyze repository modules and documentation gaps[ ]Create module-level Agent.md and Readme.md files[ ]Create common module Agent.md and Readme.md files[ ]Add minimal project-level Rule.md[ ]Run verification and report changesThinking: Launching parallel explore agents# Explore TaskMap repository module directories (47 toolcalls)136 collapsed lines
└ Globctrl+x right view subagents# Explore TaskFind existing architecture and documentation conventions (53 toolcalls)└ Globctrl+x right view subagentsThinking: Planning targeted parallel searches→ Read src→ Read docs→ Read README.md✱ Grep "\b(common|shared|utils|modules?)\b" in srcThinking: Narrowing module discovery scope→ Read src/modulesThinking: Planning module subdirectory scan→ Read src/modules/access→ Read src/modules/approval→ Read src/modules/captcha→ Read src/modules/file→ Read src/modules/invitation→ Read src/modules/service-agreement→ Read src/modules/shared→ Read src/modules/user→ Read src/modules/work-orderThinking: Fetching background task outputs⚙ background_output [task_id=bg_6a034697, block=true, timeout=120000]⚙ background_output [task_id=bg_6fd1138b, block=true, timeout=120000]Thinking: Adjusting polling for task completion⚙ background_output [task_id=bg_6a034697, block=true, timeout=120000]⚙ background_output [task_id=bg_6fd1138b, block=true, timeout=120000]Thinking: Planning targeted file search✱ Glob "**/Agent.md" in src/modules✱ Glob "**/Readme.md" in src/modules✱ Glob "**/README.md" in src/modules✱ Glob "**/Rule.md" in .✱ Glob "**/RULES.md" in .Thinking: Planning module doc strategy✱ Glob ".sisyphus/**" in .Thinking: Planning directory creation and code exploration✱ Grep "@/modules/" in src⚙ ast_grep_search [lang=typescript, pattern=import $IMPORT from "$PATH"]⚙ lsp_symbols [filePath=/home/meteor/DEV/projects/test/contract-frontend/src/main.ts, scope=workspace, query=module, limit=50]Thinking: Planning module documentation creation# Todos[•]Complete ALL tasks in work plan[•]Analyze repository modules and documentation gaps[ ]Create module-level Agent.md and Readme.md files[ ]Create common module Agent.md and Readme.md files[ ]Add minimal project-level Rule.md[ ]Run verification and report changesThinking: Initiating plan directory setup# Verify project root exists before creating notepad$ lsCHANGELOG_LOCAL_2026-02-09.mdCHANGELOG_LOCAL_2026-02-11.mdCHANGELOG_LOCAL_2026-02-17.mddistdocse2eenv.d.tseslint.config.tsindex.htmlnode_modules…Click to expandThinking: Creating initial directory and files# Create notepad directories and files$ mkdir -p .sisyphus/notepads/module-docs .sisyphus/plans && touch .sisyphus/notepads/module-docs/learnings.md .sisyphus/notepads/module-docs/decisions.md .sisyphus/notepads/module-docs/issues.md .sisyphus/notepads/module-docs/problems.mdThinking: Deciding internal plan file creation→ Read .sisyphus/notepads/module-docs/learnings.md→ Read .sisyphus/notepads/module-docs/issues.md<system-reminder>[BACKGROUND TASK COMPLETED]**ID:** `bg_6a034697`**Description:** Map repository module directories**Duration:** 1m 34s**1 task still in progress.** You WILL be notified when ALL complete.Do NOT poll - continue productive work.Use `background_output(task_id="bg_6a034697")` to retrieve this result when ready.</system-reminder><!-- OMO_INTERNAL_INITIATOR -->Thinking: Fetching completed background task output⚙ background_output [task_id=bg_6a034697, full_session=true, include_tool_results=true]Thinking: Planning modular doc delegation✱ Glob "*/index.ts" in src/modulesThinking: Identifying glob pattern limitations with relative paths✱ Glob "src/modules/*/index.ts" in .Thinking: Planning module doc structure✱ Glob "**/AGENTS.md" in .<system-reminder>[ALL BACKGROUND TASKS COMPLETE]**Completed:**- `bg_6a034697`: Map repository module directories- `bg_6fd1138b`: Find existing architecture and documentation conventionsUse `background_output(task_id="<id>")` to retrieve each result.</system-reminder><!-- OMO_INTERNAL_INITIATOR -->Thinking: Synthesizing context for planning⚙ background_output [task_id=bg_6fd1138b, full_session=true, include_tool_results=true]Thinking: Interpreting doc file scope# Todos[•]Complete ALL tasks in work plan[✓]Analyze repository modules and documentation gaps[ ]Create module-level Agent.md and Readme.md files[ ]Create common module Agent.md and Readme.md files[ ]Add minimal project-level Rule.md[ ]Run verification and report changesThinking: Drafting detailed planning task# Sisyphus-Junior TaskGenerate execution plan from context pack (0 toolcalls)ctrl+x right view subagentsThinking: Planning multi-wave delegation# Todos[•]Complete ALL tasks in work plan[✓]Analyze repository modules and documentation gaps[ ]Create module-level Agent.md and Readme.md files[ ]Create common module Agent.md and Readme.md files[•]Add minimal project-level Rule.md[ ]Run verification and report changesThinking: Preparing brief user updateDispatch Decision: mode=delegated, reason=需要新增 19 个文档文件(10 个原子任务)且可分波并行,estimated task count=10,planned waves=4,chosen subagent count=1→4(按依赖逐波提升)。我已完成上下文收集与方案拆解:会先落地最短 Rule.md,再做 shared,最后并行补齐其余模块的 Agent.md / Readme.md,每波后做严格校验。▣ Atlas (Plan Executor) · gpt-5.3-codex · 2m 55s91 collapsed lines
[SYSTEM DIRECTIVE: OH-MY-OPENCODE - TODO CONTINUATION]Incomplete tasks remain in your todo list. Continue working on the next pending task.- Proceed without asking for permission- Mark each task complete when finished- Do not stop until all tasks are done[Status: 1/6 completed, 5 remaining]Remaining tasks:- [in_progress] Complete ALL tasks in work plan- [pending] Create module-level Agent.md and Readme.md files- [pending] Create common module Agent.md and Readme.md files- [in_progress] Add minimal project-level Rule.md- [pending] Run verification and report changes<!-- OMO_INTERNAL_INITIATOR -->Thinking: Preparing baseline git status# Check working tree before delegations$ export CI=true DEBIAN_FRONTEND=noninteractive GIT_TERMINAL_PROMPT=0 GCM_INTERACTIVE=never HOMEBREW_NO_AUTO_UPDATE=1 GIT_EDITOR=: EDITOR=: VISUAL='' GIT_SEQUENCE_EDITOR=: GIT_MERGE_AUTOEDIT=no GIT_PAGER=cat PAGER=cat npm_config_yes=true PIP_NO_INPUT=1 YARN_ENABLE_IMMUTABLE_INSTALLS=false; git status --shortM src/_utils/discrete_naive_api/index.ts M src/_utils/i18n/en.ts M src/_utils/i18n/zh.ts M src/app/plugins/__tests__/useRequestPlugin.spec.ts M src/app/plugins/useRequestPlugin.ts M src/app/presentation/theme/hooks/__tests__/useTheme.spec.ts M src/app/presentation/theme/hooks/useTheme.ts M src/modules/access/application/__tests__/ability.spec.ts M src/modules/access/application/ability.ts M src/modules/shared/infrastructure/api/api-prefix-generator.ts…Click to expandThinking: Planning first delegation task# Sisyphus-Junior TaskCreate minimal project-level Rule.md (23 toolcalls)└ Todowrite 0 todosctrl+x right view subagentsThinking: Verifying recent code changes# Inspect changed files after Rule delegation$ export CI=true DEBIAN_FRONTEND=noninteractive GIT_TERMINAL_PROMPT=0 GCM_INTERACTIVE=never HOMEBREW_NO_AUTO_UPDATE=1 GIT_EDITOR=: EDITOR=: VISUAL='' GIT_SEQUENCE_EDITOR=: GIT_MERGE_AUTOEDIT=no GIT_PAGER=cat PAGER=cat npm_config_yes=true PIP_NO_INPUT=1 YARN_ENABLE_IMMUTABLE_INSTALLS=false; git diff --statsrc/_utils/discrete_naive_api/index.ts | 18 ++- src/_utils/i18n/en.ts | 46 ++++-- src/_utils/i18n/zh.ts | 31 +++- src/app/plugins/__tests__/useRequestPlugin.spec.ts | 40 +++++ src/app/plugins/useRequestPlugin.ts | 45 ++++++ .../theme/hooks/__tests__/useTheme.spec.ts | 15 +- src/app/presentation/theme/hooks/useTheme.ts | 72 +++++---- .../access/application/__tests__/ability.spec.ts | 16 ++ src/modules/access/application/ability.ts | 92 +++++++++-- .../infrastructure/api/api-prefix-generator.ts | 4 +-…Click to expandThinking: Checking untracked files# Check untracked files including Rule.md$ export CI=true DEBIAN_FRONTEND=noninteractive GIT_TERMINAL_PROMPT=0 GCM_INTERACTIVE=never HOMEBREW_NO_AUTO_UPDATE=1 GIT_EDITOR=: EDITOR=: VISUAL='' GIT_SEQUENCE_EDITOR=: GIT_MERGE_AUTOEDIT=no GIT_PAGER=cat PAGER=cat npm_config_yes=true PIP_NO_INPUT=1 YARN_ENABLE_IMMUTABLE_INSTALLS=false; git status --shortM src/_utils/discrete_naive_api/index.ts M src/_utils/i18n/en.ts M src/_utils/i18n/zh.ts M src/app/plugins/__tests__/useRequestPlugin.spec.ts M src/app/plugins/useRequestPlugin.ts M src/app/presentation/theme/hooks/__tests__/useTheme.spec.ts M src/app/presentation/theme/hooks/useTheme.ts M src/modules/access/application/__tests__/ability.spec.ts M src/modules/access/application/ability.ts M src/modules/shared/infrastructure/api/api-prefix-generator.ts…Click to expandThinking: Planning retry with session context→ Read .sisyphus/notepads/module-docs/learnings.md→ Read .sisyphus/notepads/module-docs/issues.mdThinking: Retrying previous session# Sisyphus-Junior TaskFix missing Rule.md creation (23 toolcalls)└ Todowrite 0 todosctrl+x right view subagentsThinking: Verifying patch application and file changes# Check whether Rule.md was created$ export CI=true DEBIAN_FRONTEND=noninteractive GIT_TERMINAL_PROMPT=0 GCM_INTERACTIVE=never HOMEBREW_NO_AUTO_UPDATE=1 GIT_EDITOR=: EDITOR=: VISUAL='' GIT_SEQUENCE_EDITOR=: GIT_MERGE_AUTOEDIT=no GIT_PAGER=cat PAGER=cat npm_config_yes=true PIP_NO_INPUT=1 YARN_ENABLE_IMMUTABLE_INSTALLS=false; git status --shortM src/_utils/discrete_naive_api/index.ts M src/_utils/i18n/en.ts M src/_utils/i18n/zh.ts M src/app/plugins/__tests__/useRequestPlugin.spec.ts M src/app/plugins/useRequestPlugin.ts M src/app/presentation/theme/hooks/__tests__/useTheme.spec.ts M src/app/presentation/theme/hooks/useTheme.ts M src/modules/access/application/__tests__/ability.spec.ts M src/modules/access/application/ability.ts M src/modules/shared/infrastructure/api/api-prefix-generator.ts…Click to expandThinking: Planning file reads and diagnostics→ Read Rule.md→ Read .sisyphus/notepads/module-docs/learnings.md✱ Grep "TODO|FIXME|HACK|xxx" in Rule.md
.............中间省略,TL;DR
# Todos[✓]Complete ALL tasks in work plan[✓]Analyze repository modules and documentation gaps[✓]Create module-level Agent.md and Readme.md files[✓]Create common module Agent.md and Readme.md files[✓]Add minimal project-level Rule.md[✓]Run verification and report changesThinking: Planning final detailed report已按你要求补齐了项目级和模块级文档:项目根新增最简 Rule.md,9 个模块(含 shared)都新增了 Agent.md 和 Readme.md。我只新增文档文件,没有改你现有业务代码文件。- 项目级规则:Rule.md- access:src/modules/access/Agent.md,src/modules/access/Readme.md- approval:src/modules/approval/Agent.md,src/modules/approval/Readme.md- captcha:src/modules/captcha/Agent.md,src/modules/captcha/Readme.md- file:src/modules/file/Agent.md,src/modules/file/Readme.md- invitation:src/modules/invitation/Agent.md,src/modules/invitation/Readme.md- service-agreement:src/modules/service-agreement/Agent.md,src/modules/service-agreement/Readme.md- shared(通用模块):src/modules/shared/Agent.md,src/modules/shared/Readme.md- user:src/modules/user/Agent.md,src/modules/user/Readme.md- work-order:src/modules/work-order/Agent.md,src/modules/work-order/Readme.md验证结果:- 文件存在性检查通过(上述所有目标文件都存在)。- wc -l 显示 Rule.md 为 16 行,满足“最简短”。- 构建检查 pnpm -s build 失败,但报错均在你现有 TS 代码(如 src/modules/access/*、src/modules/user/*、src/modules/approval/*),与本次新增 Markdown 文档无关。如果你要,我可以继续做两件事:1. 把各模块 Readme.md 再统一压缩成更短版本(保留核心信息)。2. 直接帮你把这批文档整理成一个 commit。8. Hooks、Skills、Rules之类的配置相关
提到这个主要是留个引子方便阅读文章的朋友自行搜索。
比如说有些第三方中转站需要js plugin来实现缓存命中+节省token的功能,这些在不同的CLI工具里面理念是一样的,但是放的地方可能会不太一样。
你的第三方中转站,或者说类似于everything-claude-code这样的Configuration,或许会有hooks的参与。
需要注意的是不同CLI工具的Skill、Hooks、Rules也并非是通用的,会有一定的格式兼容问题,比如说有些表达在Claude Code CLI中支持数组,在OpenCode里面就不支持。
以及配置项的key也会有所不同(如thinkingBudget与think_budget)。
.opencode/settings.json
{ "hooks": { "PreToolUse": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "node ~/.config/opencode/scripts/hooks/delegation-observer.js" } ] } ],22 collapsed lines
"PostToolUse": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "node ~/.config/opencode/scripts/hooks/delegation-observer.js" } ] } ], "Stop": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "node ~/.config/opencode/scripts/hooks/delegation-observer.js stop" } ] } ], "SessionStart": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "node ~/.config/opencode/scripts/hooks/session-start.js" } ] } ] }}主要使用了两个hooks:一个是针对委派任务的观察(delegation-observer.ts),一个是我的第三方中转站给到的缓存命中(session-start.js)。
第三方中转站的缓存命中hooks不展开说明,换个中转站可能就得改的东西没有普适性。
详细介绍一下delegation-observer.ts:
#!/usr/bin/env node/** * delegation 观测 Hook * * 作用: * 1) 在 PreToolUse / PostToolUse 阶段记录是否调用了delegation,说人话就是有没有把任务拆给sub agents。 * 2) 在 Stop 阶段按 session 汇总:本轮是否发生delegation、delegation调用次数。 * * 当前hook用于记录: * - 这次会话到底有没有触发sub agents? * - 触发了几次delegation tools? */
const path = require("path");const { getOpenCodeDir, ensureDir, readFile, appendFile, readStdinJson, log,} = require("../lib/utils");
// 观测日志持久化到 opencode 的 sessions 目录,便于统一审计。const OBS_DIR: string = path.join(getOpenCodeDir(), "sessions");const OBS_FILE: string = path.join(OBS_DIR, "delegation-events.jsonl");
// 委派相关工具名白名单 + 下方 endsWith('task') 兜底匹配。const DELEGATION_TOOLS: Set<string> = new Set([ "task", "background_task", "delegate", "subagent",]);
44 collapsed lines
function toJsonLine(obj: unknown): string { return `${JSON.stringify(obj)}\n`;}
// 为了可读性与日志体积可控,对输入做长度截断。function truncate(value: unknown, max = 1600): string | null { if (value == null) return null; const str = typeof value === "string" ? value : JSON.stringify(value); return str.length > max ? `${str.slice(0, max)}...` : str;}
function normalizeToolName(payload: Record<string, unknown>): string { return String(payload.tool_name || payload.tool || "") .trim() .toLowerCase();}
function normalizeSessionId(payload: Record<string, unknown>): string { return String( payload.session_id || process.env.OPENCODE_SESSION_ID || "unknown", );}
// 读取某个 session 的 delegation_tool 事件,用于 Stop 阶段汇总。function readSessionEvents(sessionId: string): Array<Record<string, unknown>> { const content = readFile(OBS_FILE); if (!content) return []; return content .split("\n") .filter(Boolean) .map((line: string) => { try { return JSON.parse(line); } catch { return null; } }) .filter( (event: Record<string, unknown> | null) => !!event && event.sessionId === sessionId && event.type === "delegation_tool", ) as Array<Record<string, unknown>>;}
async function main(): Promise<void> { ensureDir(OBS_DIR);
let payload: Record<string, unknown> = {}; try { payload = await readStdinJson(); } catch { payload = {}; }
const mode = (process.argv[2] || "").toLowerCase(); const hookType = String(payload.hook_type || mode || "unknown"); const sessionId = normalizeSessionId(payload); const now = new Date().toISOString();
// Stop 阶段:写入本轮会话汇总,快速判断是否发生过委派(delegate)。 if (mode === "stop" || hookType === "Stop") { const events = readSessionEvents(sessionId); const summary = { ts: now, type: "session_summary", sessionId, delegated: events.length > 0, delegationCalls: events.length, }; appendFile(OBS_FILE, toJsonLine(summary)); log( `[DelegationObserver] session=${sessionId.slice(-10)} delegated=${summary.delegated ? "yes" : "no"} calls=${summary.delegationCalls}`, ); process.exit(0); }
// 非 ToolUse 事件直接跳过;当前hook只关注工具调用层面的委派记录。 if (!hookType.includes("ToolUse")) { process.exit(0); }
const toolName = normalizeToolName(payload);
// 同时支持白名单精确匹配和 task 后缀宽松匹配。 const likelyDelegationTool = DELEGATION_TOOLS.has(toolName) || toolName.endsWith("task");
if (!likelyDelegationTool) { process.exit(0); }
10 collapsed lines
// 每次命中delegation tool时写一条log。 const record = { ts: now, type: "delegation_tool", hookType, sessionId, toolName, input: truncate(payload.tool_input || payload.input), };
appendFile(OBS_FILE, toJsonLine(record)); log( `[DelegationObserver] session=${sessionId.slice(-10)} tool=${toolName} hook=${hookType}`, ); process.exit(0);}
main().catch((err: Error) => { console.error("[DelegationObserver] Error:", err.message); process.exit(0);});有了这个hook之后,你可以很直观地看到是否进行了delegation,当然,如果任务足够简单,Codex认为自己一把梭更快的时候,不执行delegation以及multiple agents合作也是常态。