refactor: rename sisyphus_task to delegate_task
- Rename directories: sisyphus-task → delegate-task - Rename types: SisyphusTaskArgs → DelegateTaskArgs, etc. - Rename functions: createSisyphusTask → createDelegateTask - Rename constants: SISYPHUS_TASK_* → DELEGATE_TASK_* - Update tool name: sisyphus_task → delegate_task - Update all prompts, docs, and tests
This commit is contained in:
@@ -96,7 +96,7 @@ oh-my-opencode/
|
||||
- **Over-exploration**: Stop searching when sufficient context found
|
||||
- **High temperature**: Don't use >0.3 for code-related agents
|
||||
- **Broad tool access**: Prefer explicit `include` over unrestricted access
|
||||
- **Sequential agent calls**: Use `sisyphus_task` for parallel execution
|
||||
- **Sequential agent calls**: Use `delegate_task` for parallel execution
|
||||
- **Heavy PreToolUse logic**: Slows every tool call
|
||||
- **Self-planning for complex tasks**: Spawn planning agent (Prometheus) instead
|
||||
- **Trust agent self-reports**: ALWAYS verify results independently
|
||||
|
||||
14
README.md
14
README.md
@@ -583,7 +583,7 @@ Hand your best tools to your best colleagues. Now they can properly refactor, na
|
||||
- **ast_grep_search**: AST-aware code pattern search (25 languages)
|
||||
- **ast_grep_replace**: AST-aware code replacement
|
||||
- **call_omo_agent**: Spawn specialized explore/librarian agents. Supports `run_in_background` parameter for async execution.
|
||||
- **sisyphus_task**: Category-based task delegation with specialized agents. Supports pre-configured categories (visual, business-logic) or direct agent targeting. Use `background_output` to retrieve results and `background_cancel` to cancel tasks. See [Categories](#categories).
|
||||
- **delegate_task**: Category-based task delegation with specialized agents. Supports pre-configured categories (visual, business-logic) or direct agent targeting. Use `background_output` to retrieve results and `background_cancel` to cancel tasks. See [Categories](#categories).
|
||||
|
||||
#### Session Management
|
||||
|
||||
@@ -922,7 +922,7 @@ Available agents: `oracle`, `librarian`, `explore`, `frontend-ui-ux-engineer`, `
|
||||
Oh My OpenCode includes built-in skills that provide additional capabilities:
|
||||
|
||||
- **playwright**: Browser automation with Playwright MCP. Use for web scraping, testing, screenshots, and browser interactions.
|
||||
- **git-master**: Git expert for atomic commits, rebase/squash, and history search (blame, bisect, log -S). STRONGLY RECOMMENDED: Use with `sisyphus_task(category='quick', skills=['git-master'], ...)` to save context.
|
||||
- **git-master**: Git expert for atomic commits, rebase/squash, and history search (blame, bisect, log -S). STRONGLY RECOMMENDED: Use with `delegate_task(category='quick', skills=['git-master'], ...)` to save context.
|
||||
|
||||
Disable built-in skills via `disabled_skills` in `~/.config/opencode/oh-my-opencode.json` or `.opencode/oh-my-opencode.json`:
|
||||
|
||||
@@ -1061,7 +1061,7 @@ Configure concurrency limits for background agent tasks. This controls how many
|
||||
|
||||
### Categories
|
||||
|
||||
Categories enable domain-specific task delegation via the `sisyphus_task` tool. Each category applies runtime presets (model, temperature, prompt additions) when calling the `Sisyphus-Junior` agent.
|
||||
Categories enable domain-specific task delegation via the `delegate_task` tool. Each category applies runtime presets (model, temperature, prompt additions) when calling the `Sisyphus-Junior` agent.
|
||||
|
||||
**Default Categories:**
|
||||
|
||||
@@ -1073,12 +1073,12 @@ Categories enable domain-specific task delegation via the `sisyphus_task` tool.
|
||||
**Usage:**
|
||||
|
||||
```
|
||||
// Via sisyphus_task tool
|
||||
sisyphus_task(category="visual", prompt="Create a responsive dashboard component")
|
||||
sisyphus_task(category="business-logic", prompt="Design the payment processing flow")
|
||||
// Via delegate_task tool
|
||||
delegate_task(category="visual", prompt="Create a responsive dashboard component")
|
||||
delegate_task(category="business-logic", prompt="Design the payment processing flow")
|
||||
|
||||
// Or target a specific agent directly
|
||||
sisyphus_task(agent="oracle", prompt="Review this architecture")
|
||||
delegate_task(agent="oracle", prompt="Review this architecture")
|
||||
```
|
||||
|
||||
**Custom Categories:**
|
||||
|
||||
@@ -580,7 +580,7 @@ gh repo star code-yeongyu/oh-my-opencode
|
||||
- **ast_grep_search**:AST 感知的代码模式搜索(25 种语言)
|
||||
- **ast_grep_replace**:AST 感知的代码替换
|
||||
- **call_omo_agent**:生成专业的 explore/librarian 智能体。支持 `run_in_background` 参数进行异步执行。
|
||||
- **sisyphus_task**:基于类别的任务委派,使用专业智能体。支持预配置的类别(visual、business-logic)或直接指定智能体。使用 `background_output` 检索结果,使用 `background_cancel` 取消任务。参见[类别](#类别)。
|
||||
- **delegate_task**:基于类别的任务委派,使用专业智能体。支持预配置的类别(visual、business-logic)或直接指定智能体。使用 `background_output` 检索结果,使用 `background_cancel` 取消任务。参见[类别](#类别)。
|
||||
|
||||
#### 会话管理
|
||||
|
||||
@@ -931,7 +931,7 @@ Oh My OpenCode 从以下位置读取和执行钩子:
|
||||
Oh My OpenCode 包含提供额外功能的内置技能:
|
||||
|
||||
- **playwright**:使用 Playwright MCP 进行浏览器自动化。用于网页抓取、测试、截图和浏览器交互。
|
||||
- **git-master**:Git 专家,用于原子提交、rebase/squash 和历史搜索(blame、bisect、log -S)。**强烈推荐**:与 `sisyphus_task(category='quick', skills=['git-master'], ...)` 一起使用以节省上下文。
|
||||
- **git-master**:Git 专家,用于原子提交、rebase/squash 和历史搜索(blame、bisect、log -S)。**强烈推荐**:与 `delegate_task(category='quick', skills=['git-master'], ...)` 一起使用以节省上下文。
|
||||
|
||||
通过 `~/.config/opencode/oh-my-opencode.json` 或 `.opencode/oh-my-opencode.json` 中的 `disabled_skills` 禁用内置技能:
|
||||
|
||||
@@ -1070,7 +1070,7 @@ Oh My OpenCode 包含提供额外功能的内置技能:
|
||||
|
||||
### 类别
|
||||
|
||||
类别通过 `sisyphus_task` 工具实现领域特定的任务委派。每个类别预配置一个专业的 `Sisyphus-Junior-{category}` 智能体,带有优化的模型设置和提示。
|
||||
类别通过 `delegate_task` 工具实现领域特定的任务委派。每个类别预配置一个专业的 `Sisyphus-Junior-{category}` 智能体,带有优化的模型设置和提示。
|
||||
|
||||
**默认类别:**
|
||||
|
||||
@@ -1082,12 +1082,12 @@ Oh My OpenCode 包含提供额外功能的内置技能:
|
||||
**使用方法:**
|
||||
|
||||
```
|
||||
// 通过 sisyphus_task 工具
|
||||
sisyphus_task(category="visual", prompt="创建一个响应式仪表板组件")
|
||||
sisyphus_task(category="business-logic", prompt="设计支付处理流程")
|
||||
// 通过 delegate_task 工具
|
||||
delegate_task(category="visual", prompt="创建一个响应式仪表板组件")
|
||||
delegate_task(category="business-logic", prompt="设计支付处理流程")
|
||||
|
||||
// 或直接指定特定智能体
|
||||
sisyphus_task(agent="oracle", prompt="审查这个架构")
|
||||
delegate_task(agent="oracle", prompt="审查这个架构")
|
||||
```
|
||||
|
||||
**自定义类别:**
|
||||
|
||||
@@ -9,7 +9,7 @@ Instead of delegating everything to a single AI agent, it's far more efficient t
|
||||
- **Category**: "What kind of work is this?" (determines model, temperature, prompt mindset)
|
||||
- **Skill**: "What tools and knowledge are needed?" (injects specialized knowledge, MCP tools, workflows)
|
||||
|
||||
By combining these two concepts, you can generate optimal agents through `sisyphus_task`.
|
||||
By combining these two concepts, you can generate optimal agents through `delegate_task`.
|
||||
|
||||
---
|
||||
|
||||
@@ -30,10 +30,10 @@ A Category is an agent configuration preset optimized for specific domains.
|
||||
|
||||
### Usage
|
||||
|
||||
Specify the `category` parameter when invoking the `sisyphus_task` tool.
|
||||
Specify the `category` parameter when invoking the `delegate_task` tool.
|
||||
|
||||
```typescript
|
||||
sisyphus_task(
|
||||
delegate_task(
|
||||
category="visual-engineering",
|
||||
prompt="Add a responsive chart component to the dashboard page"
|
||||
)
|
||||
@@ -72,7 +72,7 @@ A Skill is a mechanism that injects **specialized knowledge (Context)** and **to
|
||||
Add desired skill names to the `skills` array.
|
||||
|
||||
```typescript
|
||||
sisyphus_task(
|
||||
delegate_task(
|
||||
category="quick",
|
||||
skills=["git-master"],
|
||||
prompt="Commit current changes. Follow commit message style."
|
||||
@@ -124,7 +124,7 @@ You can create powerful specialized agents by combining Categories and Skills.
|
||||
|
||||
---
|
||||
|
||||
## 5. sisyphus_task Prompt Guide
|
||||
## 5. delegate_task Prompt Guide
|
||||
|
||||
When delegating, **clear and specific** prompts are essential. Include these 7 elements:
|
||||
|
||||
|
||||
@@ -149,4 +149,4 @@ You can control related features in `oh-my-opencode.json`.
|
||||
|
||||
1. **Don't Rush**: Invest sufficient time in the interview with Prometheus. The more perfect the plan, the faster the execution.
|
||||
2. **Single Plan Principle**: No matter how large the task, contain all TODOs in one plan file (`.md`). This prevents context fragmentation.
|
||||
3. **Active Delegation**: During execution, delegate to specialized agents via `sisyphus_task` rather than modifying code directly.
|
||||
3. **Active Delegation**: During execution, delegate to specialized agents via `delegate_task` rather than modifying code directly.
|
||||
|
||||
@@ -53,7 +53,7 @@ agents/
|
||||
## ANTI-PATTERNS
|
||||
- **Trusting reports**: NEVER trust subagent self-reports; always verify outputs.
|
||||
- **High temp**: Don't use >0.3 for code agents (Sisyphus/Prometheus use 0.1).
|
||||
- **Sequential calls**: Prefer `sisyphus_task` with `run_in_background` for parallelism.
|
||||
- **Sequential calls**: Prefer `delegate_task` with `run_in_background` for parallelism.
|
||||
|
||||
## SHARED PROMPTS
|
||||
- **build-prompt.ts**: Unified base for Sisyphus and Builder variants.
|
||||
|
||||
@@ -29,7 +29,7 @@ export function createExploreAgent(model: string = DEFAULT_MODEL): AgentConfig {
|
||||
"write",
|
||||
"edit",
|
||||
"task",
|
||||
"sisyphus_task",
|
||||
"delegate_task",
|
||||
"call_omo_agent",
|
||||
])
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ export function createLibrarianAgent(model: string = DEFAULT_MODEL): AgentConfig
|
||||
"write",
|
||||
"edit",
|
||||
"task",
|
||||
"sisyphus_task",
|
||||
"delegate_task",
|
||||
"call_omo_agent",
|
||||
])
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ const metisRestrictions = createAgentToolRestrictions([
|
||||
"write",
|
||||
"edit",
|
||||
"task",
|
||||
"sisyphus_task",
|
||||
"delegate_task",
|
||||
])
|
||||
|
||||
const DEFAULT_MODEL = "anthropic/claude-opus-4-5"
|
||||
|
||||
@@ -353,7 +353,7 @@ export function createMomusAgent(model: string = DEFAULT_MODEL): AgentConfig {
|
||||
"write",
|
||||
"edit",
|
||||
"task",
|
||||
"sisyphus_task",
|
||||
"delegate_task",
|
||||
])
|
||||
|
||||
const base = {
|
||||
|
||||
@@ -102,7 +102,7 @@ export function createOracleAgent(model: string = DEFAULT_MODEL): AgentConfig {
|
||||
"write",
|
||||
"edit",
|
||||
"task",
|
||||
"sisyphus_task",
|
||||
"delegate_task",
|
||||
])
|
||||
|
||||
const base = {
|
||||
|
||||
@@ -2,13 +2,13 @@ import type { AgentConfig } from "@opencode-ai/sdk"
|
||||
import type { AgentPromptMetadata } from "./types"
|
||||
import type { AvailableAgent, AvailableSkill } from "./sisyphus-prompt-builder"
|
||||
import type { CategoryConfig } from "../config/schema"
|
||||
import { DEFAULT_CATEGORIES, CATEGORY_DESCRIPTIONS } from "../tools/sisyphus-task/constants"
|
||||
import { DEFAULT_CATEGORIES, CATEGORY_DESCRIPTIONS } from "../tools/delegate-task/constants"
|
||||
import { createAgentToolRestrictions } from "../shared/permission-compat"
|
||||
|
||||
/**
|
||||
* Orchestrator Sisyphus - Master Orchestrator Agent
|
||||
*
|
||||
* Orchestrates work via sisyphus_task() to complete ALL tasks in a todo list until fully done
|
||||
* Orchestrates work via delegate_task() to complete ALL tasks in a todo list until fully done
|
||||
* You are the conductor of a symphony of specialized agents.
|
||||
*/
|
||||
|
||||
@@ -65,8 +65,8 @@ Categories spawn \`Sisyphus-Junior-{category}\` with optimized settings:
|
||||
${categoryRows.join("\n")}
|
||||
|
||||
\`\`\`typescript
|
||||
sisyphus_task(category="visual-engineering", prompt="...") // UI/frontend work
|
||||
sisyphus_task(category="ultrabrain", prompt="...") // Backend/strategic work
|
||||
delegate_task(category="visual-engineering", prompt="...") // UI/frontend work
|
||||
delegate_task(category="ultrabrain", prompt="...") // Backend/strategic work
|
||||
\`\`\``
|
||||
}
|
||||
|
||||
@@ -95,9 +95,9 @@ ${skillRows.join("\n")}
|
||||
|
||||
**Usage:**
|
||||
\`\`\`typescript
|
||||
sisyphus_task(category="visual-engineering", skills=["frontend-ui-ux"], prompt="...")
|
||||
sisyphus_task(category="general", skills=["playwright"], prompt="...") // Browser testing
|
||||
sisyphus_task(category="visual-engineering", skills=["frontend-ui-ux", "playwright"], prompt="...") // UI with browser testing
|
||||
delegate_task(category="visual-engineering", skills=["frontend-ui-ux"], prompt="...")
|
||||
delegate_task(category="general", skills=["playwright"], prompt="...") // Browser testing
|
||||
delegate_task(category="visual-engineering", skills=["frontend-ui-ux", "playwright"], prompt="...") // UI with browser testing
|
||||
\`\`\`
|
||||
|
||||
**IMPORTANT:**
|
||||
@@ -297,8 +297,8 @@ Search **external references** (docs, OSS, web). Fire proactively when unfamilia
|
||||
**ANTI-PATTERN (DO NOT DO THIS):**
|
||||
\`\`\`typescript
|
||||
// ❌ WRONG: Background for simple searches
|
||||
sisyphus_task(agent="explore", prompt="Find where X is defined") // Just use grep!
|
||||
sisyphus_task(agent="librarian", prompt="How to use Y") // Just use context7!
|
||||
delegate_task(agent="explore", prompt="Find where X is defined") // Just use grep!
|
||||
delegate_task(agent="librarian", prompt="How to use Y") // Just use context7!
|
||||
|
||||
// ✅ CORRECT: Direct tools for most cases
|
||||
grep(pattern="functionName", path="src/")
|
||||
@@ -310,8 +310,8 @@ context7_query-docs(libraryId, query)
|
||||
\`\`\`typescript
|
||||
// Only for massive parallel research with 5+ independent queries
|
||||
// AND you have other implementation work to do simultaneously
|
||||
sisyphus_task(agent="explore", prompt="...") // Query 1
|
||||
sisyphus_task(agent="explore", prompt="...") // Query 2
|
||||
delegate_task(agent="explore", prompt="...") // Query 1
|
||||
delegate_task(agent="explore", prompt="...") // Query 2
|
||||
// ... continue implementing other code while these run
|
||||
\`\`\`
|
||||
|
||||
@@ -690,10 +690,10 @@ If the user's approach seems problematic:
|
||||
</Constraints>
|
||||
|
||||
<role>
|
||||
You are the MASTER ORCHESTRATOR - the conductor of a symphony of specialized agents via \`sisyphus_task()\`. Your sole mission is to ensure EVERY SINGLE TASK in a todo list gets completed to PERFECTION.
|
||||
You are the MASTER ORCHESTRATOR - the conductor of a symphony of specialized agents via \`delegate_task()\`. Your sole mission is to ensure EVERY SINGLE TASK in a todo list gets completed to PERFECTION.
|
||||
|
||||
## CORE MISSION
|
||||
Orchestrate work via \`sisyphus_task()\` to complete ALL tasks in a given todo list until fully done.
|
||||
Orchestrate work via \`delegate_task()\` to complete ALL tasks in a given todo list until fully done.
|
||||
|
||||
## IDENTITY & PHILOSOPHY
|
||||
|
||||
@@ -709,16 +709,16 @@ You do NOT execute tasks yourself. You DELEGATE, COORDINATE, and VERIFY. Think o
|
||||
- ✅ YOU CAN: Read files, run commands, verify results, check tests, inspect outputs
|
||||
- ❌ YOU MUST DELEGATE: Code writing, file modification, bug fixes, test creation
|
||||
2. **VERIFY OBSESSIVELY**: Subagents LIE. Always verify their claims with your own tools (Read, Bash, lsp_diagnostics).
|
||||
3. **PARALLELIZE WHEN POSSIBLE**: If tasks are independent (no dependencies, no file conflicts), invoke multiple \`sisyphus_task()\` calls in PARALLEL.
|
||||
4. **ONE TASK PER CALL**: Each \`sisyphus_task()\` call handles EXACTLY ONE task. Never batch multiple tasks.
|
||||
5. **CONTEXT IS KING**: Pass COMPLETE, DETAILED context in every \`sisyphus_task()\` prompt.
|
||||
3. **PARALLELIZE WHEN POSSIBLE**: If tasks are independent (no dependencies, no file conflicts), invoke multiple \`delegate_task()\` calls in PARALLEL.
|
||||
4. **ONE TASK PER CALL**: Each \`delegate_task()\` call handles EXACTLY ONE task. Never batch multiple tasks.
|
||||
5. **CONTEXT IS KING**: Pass COMPLETE, DETAILED context in every \`delegate_task()\` prompt.
|
||||
6. **WISDOM ACCUMULATES**: Gather learnings from each task and pass to the next.
|
||||
|
||||
### CRITICAL: DETAILED PROMPTS ARE MANDATORY
|
||||
|
||||
**The #1 cause of agent failure is VAGUE PROMPTS.**
|
||||
|
||||
When calling \`sisyphus_task()\`, your prompt MUST be:
|
||||
When calling \`delegate_task()\`, your prompt MUST be:
|
||||
- **EXHAUSTIVELY DETAILED**: Include EVERY piece of context the agent needs
|
||||
- **EXPLICITLY STRUCTURED**: Use the 7-section format (TASK, EXPECTED OUTCOME, REQUIRED SKILLS, REQUIRED TOOLS, MUST DO, MUST NOT DO, CONTEXT)
|
||||
- **CONCRETE, NOT ABSTRACT**: Exact file paths, exact commands, exact expected outputs
|
||||
@@ -726,12 +726,12 @@ When calling \`sisyphus_task()\`, your prompt MUST be:
|
||||
|
||||
**BAD (will fail):**
|
||||
\`\`\`
|
||||
sisyphus_task(category="ultrabrain", prompt="Fix the auth bug")
|
||||
delegate_task(category="ultrabrain", prompt="Fix the auth bug")
|
||||
\`\`\`
|
||||
|
||||
**GOOD (will succeed):**
|
||||
\`\`\`
|
||||
sisyphus_task(
|
||||
delegate_task(
|
||||
category="ultrabrain",
|
||||
prompt="""
|
||||
## TASK
|
||||
@@ -875,7 +875,7 @@ Before processing sequentially, check if there are PARALLELIZABLE tasks:
|
||||
1. **Identify parallelizable task group** from the parallelization map (from Step 1)
|
||||
2. **If parallelizable group found** (e.g., Tasks 2, 3, 4 can run simultaneously):
|
||||
- Prepare DETAILED execution prompts for ALL tasks in the group
|
||||
- Invoke multiple \`sisyphus_task()\` calls IN PARALLEL (single message, multiple calls)
|
||||
- Invoke multiple \`delegate_task()\` calls IN PARALLEL (single message, multiple calls)
|
||||
- Wait for ALL to complete
|
||||
- Process ALL responses and update wisdom repository
|
||||
- Mark ALL completed tasks
|
||||
@@ -889,16 +889,16 @@ Before processing sequentially, check if there are PARALLELIZABLE tasks:
|
||||
- Extract the EXACT task text
|
||||
- Analyze the task nature
|
||||
|
||||
#### 3.2: Choose Category or Agent for sisyphus_task()
|
||||
#### 3.2: Choose Category or Agent for delegate_task()
|
||||
|
||||
**sisyphus_task() has TWO modes - choose ONE:**
|
||||
**delegate_task() has TWO modes - choose ONE:**
|
||||
|
||||
{CATEGORY_SECTION}
|
||||
|
||||
\`\`\`typescript
|
||||
sisyphus_task(agent="oracle", prompt="...") // Expert consultation
|
||||
sisyphus_task(agent="explore", prompt="...") // Codebase search
|
||||
sisyphus_task(agent="librarian", prompt="...") // External research
|
||||
delegate_task(agent="oracle", prompt="...") // Expert consultation
|
||||
delegate_task(agent="explore", prompt="...") // Codebase search
|
||||
delegate_task(agent="librarian", prompt="...") // External research
|
||||
\`\`\`
|
||||
|
||||
{AGENT_SECTION}
|
||||
@@ -970,7 +970,7 @@ STRATEGIC CATEGORY JUSTIFICATION (MANDATORY):
|
||||
|
||||
---
|
||||
|
||||
**BEFORE invoking sisyphus_task(), you MUST state:**
|
||||
**BEFORE invoking delegate_task(), you MUST state:**
|
||||
|
||||
\`\`\`
|
||||
Category: [general OR specific-category]
|
||||
@@ -987,7 +987,7 @@ Justification: [Brief for general, EXTENSIVE for strategic/most-capable]
|
||||
|
||||
#### 3.3: Prepare Execution Directive (DETAILED PROMPT IS EVERYTHING)
|
||||
|
||||
**CRITICAL: The quality of your \`sisyphus_task()\` prompt determines success or failure.**
|
||||
**CRITICAL: The quality of your \`delegate_task()\` prompt determines success or failure.**
|
||||
|
||||
**RULE: If your prompt is short, YOU WILL FAIL. Make it EXHAUSTIVELY DETAILED.**
|
||||
|
||||
@@ -1063,7 +1063,7 @@ NOTEPAD PATH: .sisyphus/notepads/{plan-name}/ (READ for wisdom, WRITE findings)
|
||||
PLAN PATH: .sisyphus/plans/{plan-name}.md (READ ONLY - NEVER MODIFY)
|
||||
|
||||
### Inherited Wisdom from Notepad (READ BEFORE EVERY DELEGATION)
|
||||
[Extract from .sisyphus/notepads/{plan-name}/*.md before calling sisyphus_task]
|
||||
[Extract from .sisyphus/notepads/{plan-name}/*.md before calling delegate_task]
|
||||
- Conventions discovered: [from learnings.md]
|
||||
- Successful approaches: [from learnings.md]
|
||||
- Failed approaches to avoid: [from issues.md]
|
||||
@@ -1082,12 +1082,12 @@ PLAN PATH: .sisyphus/plans/{plan-name}.md (READ ONLY - NEVER MODIFY)
|
||||
|
||||
**PROMPT LENGTH CHECK**: Your prompt should be 50-200 lines. If it's under 20 lines, it's TOO SHORT.
|
||||
|
||||
#### 3.4: Invoke via sisyphus_task()
|
||||
#### 3.4: Invoke via delegate_task()
|
||||
|
||||
**CRITICAL: Pass the COMPLETE 7-section directive from 3.3. SHORT PROMPTS = FAILURE.**
|
||||
|
||||
\`\`\`typescript
|
||||
sisyphus_task(
|
||||
delegate_task(
|
||||
agent="[selected-agent-name]", // Agent you chose in step 3.2
|
||||
background=false, // ALWAYS false for task delegation - wait for completion
|
||||
prompt=\`
|
||||
@@ -1153,7 +1153,7 @@ Task N: [exact task description]
|
||||
**⚠️ CRITICAL: SUBAGENTS LIE. NEVER trust their claims. ALWAYS verify yourself.**
|
||||
**⚠️ YOU ARE THE QA GATE. If you don't verify, NO ONE WILL.**
|
||||
|
||||
After \`sisyphus_task()\` completes, you MUST perform COMPREHENSIVE QA:
|
||||
After \`delegate_task()\` completes, you MUST perform COMPREHENSIVE QA:
|
||||
|
||||
**STEP 1: PROJECT-LEVEL CODE VERIFICATION (MANDATORY)**
|
||||
1. **Run \`lsp_diagnostics\` at DIRECTORY or PROJECT level**:
|
||||
@@ -1203,12 +1203,12 @@ After \`sisyphus_task()\` completes, you MUST perform COMPREHENSIVE QA:
|
||||
If task reports FAILED or BLOCKED:
|
||||
- **THINK**: "What information or help is needed to fix this?"
|
||||
- **IDENTIFY**: Which agent is best suited to provide that help?
|
||||
- **INVOKE**: via \`sisyphus_task()\` with MORE DETAILED prompt including failure context
|
||||
- **INVOKE**: via \`delegate_task()\` with MORE DETAILED prompt including failure context
|
||||
- **RE-ATTEMPT**: Re-invoke with new insights/guidance and EXPANDED context
|
||||
- If external blocker: Document and continue to next independent task
|
||||
- Maximum 3 retry attempts per task
|
||||
|
||||
**NEVER try to analyze or fix failures yourself. Always delegate via \`sisyphus_task()\`.**
|
||||
**NEVER try to analyze or fix failures yourself. Always delegate via \`delegate_task()\`.**
|
||||
|
||||
**FAILURE RECOVERY PROMPT EXPANSION**: When retrying, your prompt MUST include:
|
||||
- What was attempted
|
||||
@@ -1256,7 +1256,7 @@ TOTAL TIME: [duration]
|
||||
### THE GOLDEN RULE
|
||||
**YOU ORCHESTRATE, YOU DO NOT EXECUTE.**
|
||||
|
||||
Every time you're tempted to write code, STOP and ask: "Should I delegate this via \`sisyphus_task()\`?"
|
||||
Every time you're tempted to write code, STOP and ask: "Should I delegate this via \`delegate_task()\`?"
|
||||
The answer is almost always YES.
|
||||
|
||||
### WHAT YOU CAN DO vs WHAT YOU MUST DELEGATE
|
||||
@@ -1278,11 +1278,11 @@ The answer is almost always YES.
|
||||
- [X] Git commits (delegate to git-master)
|
||||
|
||||
**DELEGATION TARGETS:**
|
||||
- \`sisyphus_task(category="ultrabrain", background=false)\` → backend/logic implementation
|
||||
- \`sisyphus_task(category="visual-engineering", background=false)\` → frontend/UI implementation
|
||||
- \`sisyphus_task(agent="git-master", background=false)\` → ALL git commits
|
||||
- \`sisyphus_task(agent="document-writer", background=false)\` → documentation
|
||||
- \`sisyphus_task(agent="debugging-master", background=false)\` → complex debugging
|
||||
- \`delegate_task(category="ultrabrain", background=false)\` → backend/logic implementation
|
||||
- \`delegate_task(category="visual-engineering", background=false)\` → frontend/UI implementation
|
||||
- \`delegate_task(agent="git-master", background=false)\` → ALL git commits
|
||||
- \`delegate_task(agent="document-writer", background=false)\` → documentation
|
||||
- \`delegate_task(agent="debugging-master", background=false)\` → complex debugging
|
||||
|
||||
**⚠️ CRITICAL: background=false is MANDATORY for all task delegations.**
|
||||
|
||||
@@ -1352,8 +1352,8 @@ All learnings, decisions, and insights MUST be recorded in the notepad system fo
|
||||
\`\`\`
|
||||
|
||||
**Usage Protocol:**
|
||||
1. **BEFORE each sisyphus_task() call** → Read notepad files to gather accumulated wisdom
|
||||
2. **INCLUDE in every sisyphus_task() prompt** → Pass relevant notepad content as "INHERITED WISDOM" section
|
||||
1. **BEFORE each delegate_task() call** → Read notepad files to gather accumulated wisdom
|
||||
2. **INCLUDE in every delegate_task() prompt** → Pass relevant notepad content as "INHERITED WISDOM" section
|
||||
3. After each task completion → Instruct subagent to append findings to appropriate category
|
||||
4. When encountering issues → Document in issues.md or problems.md
|
||||
|
||||
@@ -1366,7 +1366,7 @@ All learnings, decisions, and insights MUST be recorded in the notepad system fo
|
||||
|
||||
**READING NOTEPAD BEFORE DELEGATION (MANDATORY):**
|
||||
|
||||
Before EVERY \`sisyphus_task()\` call, you MUST:
|
||||
Before EVERY \`delegate_task()\` call, you MUST:
|
||||
|
||||
1. Check if notepad exists: \`glob(".sisyphus/notepads/{plan-name}/*.md")\`
|
||||
2. If exists, read recent entries (use Read tool, focus on recent ~50 lines per file)
|
||||
@@ -1380,7 +1380,7 @@ Read(".sisyphus/notepads/my-plan/learnings.md")
|
||||
Read(".sisyphus/notepads/my-plan/issues.md")
|
||||
Read(".sisyphus/notepads/my-plan/decisions.md")
|
||||
|
||||
# Then include in sisyphus_task prompt:
|
||||
# Then include in delegate_task prompt:
|
||||
## INHERITED WISDOM FROM PREVIOUS TASKS
|
||||
- Pattern discovered: Use kebab-case for file names (learnings.md)
|
||||
- Avoid: Direct DOM manipulation - use React refs instead (issues.md)
|
||||
@@ -1395,11 +1395,11 @@ Read(".sisyphus/notepads/my-plan/decisions.md")
|
||||
|
||||
1. **Executing tasks yourself**: NEVER write implementation code, NEVER read/write/edit files directly
|
||||
2. **Ignoring parallelizability**: If tasks CAN run in parallel, they SHOULD run in parallel
|
||||
3. **Batch delegation**: NEVER send multiple tasks to one \`sisyphus_task()\` call (one task per call)
|
||||
3. **Batch delegation**: NEVER send multiple tasks to one \`delegate_task()\` call (one task per call)
|
||||
4. **Losing context**: ALWAYS pass accumulated wisdom in EVERY prompt
|
||||
5. **Giving up early**: RETRY failed tasks (max 3 attempts)
|
||||
6. **Rushing**: Quality over speed - but parallelize when possible
|
||||
7. **Direct file operations**: NEVER use Read/Write/Edit/Bash for file operations - ALWAYS use \`sisyphus_task()\`
|
||||
7. **Direct file operations**: NEVER use Read/Write/Edit/Bash for file operations - ALWAYS use \`delegate_task()\`
|
||||
8. **SHORT PROMPTS**: If your prompt is under 30 lines, it's TOO SHORT. EXPAND IT.
|
||||
9. **Wrong category/agent**: Match task type to category/agent systematically (see Decision Matrix)
|
||||
|
||||
@@ -1441,7 +1441,7 @@ If task cannot be completed after 3 attempts:
|
||||
You are the MASTER ORCHESTRATOR. Your job is to:
|
||||
1. **CREATE TODO** to track overall progress
|
||||
2. **READ** the todo list (check for parallelizability)
|
||||
3. **DELEGATE** via \`sisyphus_task()\` with DETAILED prompts (parallel when possible)
|
||||
3. **DELEGATE** via \`delegate_task()\` with DETAILED prompts (parallel when possible)
|
||||
4. **⚠️ QA VERIFY** - Run project-level \`lsp_diagnostics\`, build, and tests after EVERY delegation
|
||||
5. **ACCUMULATE** wisdom from completions
|
||||
6. **REPORT** final status
|
||||
@@ -1449,9 +1449,9 @@ You are the MASTER ORCHESTRATOR. Your job is to:
|
||||
**CRITICAL REMINDERS:**
|
||||
- NEVER execute tasks yourself
|
||||
- NEVER read/write/edit files directly
|
||||
- ALWAYS use \`sisyphus_task(category=...)\` or \`sisyphus_task(agent=...)\`
|
||||
- ALWAYS use \`delegate_task(category=...)\` or \`delegate_task(agent=...)\`
|
||||
- PARALLELIZE when tasks are independent
|
||||
- One task per \`sisyphus_task()\` call (never batch)
|
||||
- One task per \`delegate_task()\` call (never batch)
|
||||
- Pass COMPLETE context in EVERY prompt (50+ lines minimum)
|
||||
- Accumulate and forward all learnings
|
||||
- **⚠️ RUN lsp_diagnostics AT PROJECT/DIRECTORY LEVEL after EVERY delegation**
|
||||
@@ -1489,7 +1489,7 @@ export function createOrchestratorSisyphusAgent(ctx?: OrchestratorContext): Agen
|
||||
])
|
||||
return {
|
||||
description:
|
||||
"Orchestrates work via sisyphus_task() to complete ALL tasks in a todo list until fully done",
|
||||
"Orchestrates work via delegate_task() to complete ALL tasks in a todo list until fully done",
|
||||
mode: "primary" as const,
|
||||
model: ctx?.model ?? DEFAULT_MODEL,
|
||||
temperature: 0.1,
|
||||
|
||||
@@ -291,8 +291,8 @@ Or should I just note down this single fix?"
|
||||
|
||||
**Research First:**
|
||||
\`\`\`typescript
|
||||
sisyphus_task(agent="explore", prompt="Find all usages of [target] using lsp_find_references pattern...", background=true)
|
||||
sisyphus_task(agent="explore", prompt="Find test coverage for [affected code]...", background=true)
|
||||
delegate_task(agent="explore", prompt="Find all usages of [target] using lsp_find_references pattern...", background=true)
|
||||
delegate_task(agent="explore", prompt="Find test coverage for [affected code]...", background=true)
|
||||
\`\`\`
|
||||
|
||||
**Interview Focus:**
|
||||
@@ -315,9 +315,9 @@ sisyphus_task(agent="explore", prompt="Find test coverage for [affected code]...
|
||||
**Pre-Interview Research (MANDATORY):**
|
||||
\`\`\`typescript
|
||||
// Launch BEFORE asking user questions
|
||||
sisyphus_task(agent="explore", prompt="Find similar implementations in codebase...", background=true)
|
||||
sisyphus_task(agent="explore", prompt="Find project patterns for [feature type]...", background=true)
|
||||
sisyphus_task(agent="librarian", prompt="Find best practices for [technology]...", background=true)
|
||||
delegate_task(agent="explore", prompt="Find similar implementations in codebase...", background=true)
|
||||
delegate_task(agent="explore", prompt="Find project patterns for [feature type]...", background=true)
|
||||
delegate_task(agent="librarian", prompt="Find best practices for [technology]...", background=true)
|
||||
\`\`\`
|
||||
|
||||
**Interview Focus** (AFTER research):
|
||||
@@ -356,7 +356,7 @@ Based on your stack, I'd recommend NextAuth.js - it integrates well with Next.js
|
||||
|
||||
Run this check:
|
||||
\`\`\`typescript
|
||||
sisyphus_task(agent="explore", prompt="Find test infrastructure: package.json test scripts, test config files (jest.config, vitest.config, pytest.ini, etc.), existing test files (*.test.*, *.spec.*, test_*). Report: 1) Does test infra exist? 2) What framework? 3) Example test file patterns.", background=true)
|
||||
delegate_task(agent="explore", prompt="Find test infrastructure: package.json test scripts, test config files (jest.config, vitest.config, pytest.ini, etc.), existing test files (*.test.*, *.spec.*, test_*). Report: 1) Does test infra exist? 2) What framework? 3) Example test file patterns.", background=true)
|
||||
\`\`\`
|
||||
|
||||
#### Step 2: Ask the Test Question (MANDATORY)
|
||||
@@ -445,13 +445,13 @@ Add to draft immediately:
|
||||
|
||||
**Research First:**
|
||||
\`\`\`typescript
|
||||
sisyphus_task(agent="explore", prompt="Find current system architecture and patterns...", background=true)
|
||||
sisyphus_task(agent="librarian", prompt="Find architectural best practices for [domain]...", background=true)
|
||||
delegate_task(agent="explore", prompt="Find current system architecture and patterns...", background=true)
|
||||
delegate_task(agent="librarian", prompt="Find architectural best practices for [domain]...", background=true)
|
||||
\`\`\`
|
||||
|
||||
**Oracle Consultation** (recommend when stakes are high):
|
||||
\`\`\`typescript
|
||||
sisyphus_task(agent="oracle", prompt="Architecture consultation needed: [context]...", background=false)
|
||||
delegate_task(agent="oracle", prompt="Architecture consultation needed: [context]...", background=false)
|
||||
\`\`\`
|
||||
|
||||
**Interview Focus:**
|
||||
@@ -468,9 +468,9 @@ sisyphus_task(agent="oracle", prompt="Architecture consultation needed: [context
|
||||
|
||||
**Parallel Investigation:**
|
||||
\`\`\`typescript
|
||||
sisyphus_task(agent="explore", prompt="Find how X is currently handled...", background=true)
|
||||
sisyphus_task(agent="librarian", prompt="Find official docs for Y...", background=true)
|
||||
sisyphus_task(agent="librarian", prompt="Find OSS implementations of Z...", background=true)
|
||||
delegate_task(agent="explore", prompt="Find how X is currently handled...", background=true)
|
||||
delegate_task(agent="librarian", prompt="Find official docs for Y...", background=true)
|
||||
delegate_task(agent="librarian", prompt="Find OSS implementations of Z...", background=true)
|
||||
\`\`\`
|
||||
|
||||
**Interview Focus:**
|
||||
@@ -496,17 +496,17 @@ sisyphus_task(agent="librarian", prompt="Find OSS implementations of Z...", back
|
||||
|
||||
**For Understanding Codebase:**
|
||||
\`\`\`typescript
|
||||
sisyphus_task(agent="explore", prompt="Find all files related to [topic]. Show patterns, conventions, and structure.", background=true)
|
||||
delegate_task(agent="explore", prompt="Find all files related to [topic]. Show patterns, conventions, and structure.", background=true)
|
||||
\`\`\`
|
||||
|
||||
**For External Knowledge:**
|
||||
\`\`\`typescript
|
||||
sisyphus_task(agent="librarian", prompt="Find official documentation for [library]. Focus on [specific feature] and best practices.", background=true)
|
||||
delegate_task(agent="librarian", prompt="Find official documentation for [library]. Focus on [specific feature] and best practices.", background=true)
|
||||
\`\`\`
|
||||
|
||||
**For Implementation Examples:**
|
||||
\`\`\`typescript
|
||||
sisyphus_task(agent="librarian", prompt="Find open source implementations of [feature]. Look for production-quality examples.", background=true)
|
||||
delegate_task(agent="librarian", prompt="Find open source implementations of [feature]. Look for production-quality examples.", background=true)
|
||||
\`\`\`
|
||||
|
||||
## Interview Mode Anti-Patterns
|
||||
@@ -599,7 +599,7 @@ todoWrite([
|
||||
**BEFORE generating the plan**, summon Metis to catch what you might have missed:
|
||||
|
||||
\`\`\`typescript
|
||||
sisyphus_task(
|
||||
delegate_task(
|
||||
agent="Metis (Plan Consultant)",
|
||||
prompt=\`Review this planning session before I generate the work plan:
|
||||
|
||||
@@ -750,7 +750,7 @@ If no, the plan is ready. Run \`/start-work\` to begin."
|
||||
\`\`\`typescript
|
||||
// After generating initial plan
|
||||
while (true) {
|
||||
const result = sisyphus_task(
|
||||
const result = delegate_task(
|
||||
agent="Momus (Plan Reviewer)",
|
||||
prompt=".sisyphus/plans/{name}.md",
|
||||
background=false
|
||||
|
||||
@@ -138,13 +138,13 @@ describe("createSisyphusJuniorAgentWithOverrides", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("tool safety (task/sisyphus_task blocked, call_omo_agent allowed)", () => {
|
||||
test("task and sisyphus_task remain blocked, call_omo_agent is allowed via tools format", () => {
|
||||
describe("tool safety (task/delegate_task blocked, call_omo_agent allowed)", () => {
|
||||
test("task and delegate_task remain blocked, call_omo_agent is allowed via tools format", () => {
|
||||
// #given
|
||||
const override = {
|
||||
tools: {
|
||||
task: true,
|
||||
sisyphus_task: true,
|
||||
delegate_task: true,
|
||||
call_omo_agent: true,
|
||||
read: true,
|
||||
},
|
||||
@@ -158,25 +158,25 @@ describe("createSisyphusJuniorAgentWithOverrides", () => {
|
||||
const permission = result.permission as Record<string, string> | undefined
|
||||
if (tools) {
|
||||
expect(tools.task).toBe(false)
|
||||
expect(tools.sisyphus_task).toBe(false)
|
||||
expect(tools.delegate_task).toBe(false)
|
||||
// call_omo_agent is NOW ALLOWED for subagents to spawn explore/librarian
|
||||
expect(tools.call_omo_agent).toBe(true)
|
||||
expect(tools.read).toBe(true)
|
||||
}
|
||||
if (permission) {
|
||||
expect(permission.task).toBe("deny")
|
||||
expect(permission.sisyphus_task).toBe("deny")
|
||||
expect(permission.delegate_task).toBe("deny")
|
||||
// call_omo_agent is NOW ALLOWED for subagents to spawn explore/librarian
|
||||
expect(permission.call_omo_agent).toBe("allow")
|
||||
}
|
||||
})
|
||||
|
||||
test("task and sisyphus_task remain blocked when using permission format override", () => {
|
||||
test("task and delegate_task remain blocked when using permission format override", () => {
|
||||
// #given
|
||||
const override = {
|
||||
permission: {
|
||||
task: "allow",
|
||||
sisyphus_task: "allow",
|
||||
delegate_task: "allow",
|
||||
call_omo_agent: "allow",
|
||||
read: "allow",
|
||||
},
|
||||
@@ -185,17 +185,17 @@ describe("createSisyphusJuniorAgentWithOverrides", () => {
|
||||
// #when
|
||||
const result = createSisyphusJuniorAgentWithOverrides(override as Parameters<typeof createSisyphusJuniorAgentWithOverrides>[0])
|
||||
|
||||
// #then - task/sisyphus_task blocked, but call_omo_agent allowed for explore/librarian spawning
|
||||
// #then - task/delegate_task blocked, but call_omo_agent allowed for explore/librarian spawning
|
||||
const tools = result.tools as Record<string, boolean> | undefined
|
||||
const permission = result.permission as Record<string, string> | undefined
|
||||
if (tools) {
|
||||
expect(tools.task).toBe(false)
|
||||
expect(tools.sisyphus_task).toBe(false)
|
||||
expect(tools.delegate_task).toBe(false)
|
||||
expect(tools.call_omo_agent).toBe(true)
|
||||
}
|
||||
if (permission) {
|
||||
expect(permission.task).toBe("deny")
|
||||
expect(permission.sisyphus_task).toBe("deny")
|
||||
expect(permission.delegate_task).toBe("deny")
|
||||
expect(permission.call_omo_agent).toBe("allow")
|
||||
}
|
||||
})
|
||||
|
||||
@@ -14,7 +14,7 @@ Execute tasks directly. NEVER delegate or spawn other agents.
|
||||
<Critical_Constraints>
|
||||
BLOCKED ACTIONS (will fail if attempted):
|
||||
- task tool: BLOCKED
|
||||
- sisyphus_task tool: BLOCKED
|
||||
- delegate_task tool: BLOCKED
|
||||
|
||||
ALLOWED: call_omo_agent - You CAN spawn explore/librarian agents for research.
|
||||
You work ALONE for implementation. No delegation of implementation tasks.
|
||||
@@ -75,7 +75,7 @@ function buildSisyphusJuniorPrompt(promptAppend?: string): string {
|
||||
|
||||
// Core tools that Sisyphus-Junior must NEVER have access to
|
||||
// Note: call_omo_agent is ALLOWED so subagents can spawn explore/librarian
|
||||
const BLOCKED_TOOLS = ["task", "sisyphus_task"]
|
||||
const BLOCKED_TOOLS = ["task", "delegate_task"]
|
||||
|
||||
export const SISYPHUS_JUNIOR_DEFAULTS = {
|
||||
model: "anthropic/claude-sonnet-4-5",
|
||||
|
||||
@@ -122,7 +122,7 @@ IMPORTANT: If codebase appears undisciplined, verify before assuming:
|
||||
|
||||
const SISYPHUS_PRE_DELEGATION_PLANNING = `### Pre-Delegation Planning (MANDATORY)
|
||||
|
||||
**BEFORE every \`sisyphus_task\` call, EXPLICITLY declare your reasoning.**
|
||||
**BEFORE every \`delegate_task\` call, EXPLICITLY declare your reasoning.**
|
||||
|
||||
#### Step 1: Identify Task Requirements
|
||||
|
||||
@@ -160,27 +160,27 @@ Ask yourself:
|
||||
**MANDATORY FORMAT:**
|
||||
|
||||
\`\`\`
|
||||
I will use sisyphus_task with:
|
||||
I will use delegate_task with:
|
||||
- **Category/Agent**: [name]
|
||||
- **Reason**: [why this choice fits the task]
|
||||
- **Skills** (if any): [skill names]
|
||||
- **Expected Outcome**: [what success looks like]
|
||||
\`\`\`
|
||||
|
||||
**Then** make the sisyphus_task call.
|
||||
**Then** make the delegate_task call.
|
||||
|
||||
#### Examples
|
||||
|
||||
**✅ CORRECT: Explicit Pre-Declaration**
|
||||
|
||||
\`\`\`
|
||||
I will use sisyphus_task with:
|
||||
I will use delegate_task with:
|
||||
- **Category**: visual
|
||||
- **Reason**: This task requires building a responsive dashboard UI with animations - visual design is the core requirement
|
||||
- **Skills**: ["frontend-ui-ux"]
|
||||
- **Expected Outcome**: Fully styled, responsive dashboard component with smooth transitions
|
||||
|
||||
sisyphus_task(
|
||||
delegate_task(
|
||||
category="visual",
|
||||
skills=["frontend-ui-ux"],
|
||||
prompt="Create a responsive dashboard component with..."
|
||||
@@ -190,13 +190,13 @@ sisyphus_task(
|
||||
**✅ CORRECT: Agent-Specific Delegation**
|
||||
|
||||
\`\`\`
|
||||
I will use sisyphus_task with:
|
||||
I will use delegate_task with:
|
||||
- **Agent**: oracle
|
||||
- **Reason**: This architectural decision involves trade-offs between scalability and complexity - requires high-IQ strategic analysis
|
||||
- **Skills**: []
|
||||
- **Expected Outcome**: Clear recommendation with pros/cons analysis
|
||||
|
||||
sisyphus_task(
|
||||
delegate_task(
|
||||
agent="oracle",
|
||||
skills=[],
|
||||
prompt="Evaluate this microservices architecture proposal..."
|
||||
@@ -206,13 +206,13 @@ sisyphus_task(
|
||||
**✅ CORRECT: Background Exploration**
|
||||
|
||||
\`\`\`
|
||||
I will use sisyphus_task with:
|
||||
I will use delegate_task with:
|
||||
- **Agent**: explore
|
||||
- **Reason**: Need to find all authentication implementations across the codebase - this is contextual grep
|
||||
- **Skills**: []
|
||||
- **Expected Outcome**: List of files containing auth patterns
|
||||
|
||||
sisyphus_task(
|
||||
delegate_task(
|
||||
agent="explore",
|
||||
background=true,
|
||||
prompt="Find all authentication implementations in the codebase"
|
||||
@@ -223,7 +223,7 @@ sisyphus_task(
|
||||
|
||||
\`\`\`
|
||||
// Immediately calling without explicit reasoning
|
||||
sisyphus_task(category="visual", prompt="Build a dashboard")
|
||||
delegate_task(category="visual", prompt="Build a dashboard")
|
||||
\`\`\`
|
||||
|
||||
**❌ WRONG: Vague Reasoning**
|
||||
@@ -231,12 +231,12 @@ sisyphus_task(category="visual", prompt="Build a dashboard")
|
||||
\`\`\`
|
||||
I'll use visual category because it's frontend work.
|
||||
|
||||
sisyphus_task(category="visual", ...)
|
||||
delegate_task(category="visual", ...)
|
||||
\`\`\`
|
||||
|
||||
#### Enforcement
|
||||
|
||||
**BLOCKING VIOLATION**: If you call \`sisyphus_task\` without the 4-part declaration, you have violated protocol.
|
||||
**BLOCKING VIOLATION**: If you call \`delegate_task\` without the 4-part declaration, you have violated protocol.
|
||||
|
||||
**Recovery**: Stop, declare explicitly, then proceed.`
|
||||
|
||||
@@ -247,11 +247,11 @@ const SISYPHUS_PARALLEL_EXECUTION = `### Parallel Execution (DEFAULT behavior)
|
||||
\`\`\`typescript
|
||||
// CORRECT: Always background, always parallel
|
||||
// Contextual Grep (internal)
|
||||
sisyphus_task(agent="explore", prompt="Find auth implementations in our codebase...")
|
||||
sisyphus_task(agent="explore", prompt="Find error handling patterns here...")
|
||||
delegate_task(agent="explore", prompt="Find auth implementations in our codebase...")
|
||||
delegate_task(agent="explore", prompt="Find error handling patterns here...")
|
||||
// Reference Grep (external)
|
||||
sisyphus_task(agent="librarian", prompt="Find JWT best practices in official docs...")
|
||||
sisyphus_task(agent="librarian", prompt="Find how production apps handle auth in Express...")
|
||||
delegate_task(agent="librarian", prompt="Find JWT best practices in official docs...")
|
||||
delegate_task(agent="librarian", prompt="Find how production apps handle auth in Express...")
|
||||
// Continue working immediately. Collect with background_output when needed.
|
||||
|
||||
// WRONG: Sequential or blocking
|
||||
@@ -274,7 +274,7 @@ Pass \`resume=session_id\` to continue previous agent with FULL CONTEXT PRESERVE
|
||||
|
||||
**Example:**
|
||||
\`\`\`
|
||||
sisyphus_task(resume="ses_abc123", prompt="The previous search missed X. Also look for Y.")
|
||||
delegate_task(resume="ses_abc123", prompt="The previous search missed X. Also look for Y.")
|
||||
\`\`\`
|
||||
|
||||
### Search Stop Conditions
|
||||
|
||||
@@ -13,7 +13,7 @@ import { createOrchestratorSisyphusAgent, orchestratorSisyphusAgent } from "./or
|
||||
import { createMomusAgent } from "./momus"
|
||||
import type { AvailableAgent } from "./sisyphus-prompt-builder"
|
||||
import { deepMerge } from "../shared"
|
||||
import { DEFAULT_CATEGORIES } from "../tools/sisyphus-task/constants"
|
||||
import { DEFAULT_CATEGORIES } from "../tools/delegate-task/constants"
|
||||
import { resolveMultipleSkills } from "../features/opencode-skill-loader/skill-content"
|
||||
|
||||
type AgentSource = AgentFactory | AgentConfig
|
||||
|
||||
@@ -84,7 +84,7 @@ export const HookNameSchema = z.enum([
|
||||
"claude-code-hooks",
|
||||
"auto-slash-command",
|
||||
"edit-error-recovery",
|
||||
"sisyphus-task-retry",
|
||||
"delegate-task-retry",
|
||||
"prometheus-md-only",
|
||||
"start-work",
|
||||
"sisyphus-orchestrator",
|
||||
|
||||
@@ -61,7 +61,7 @@ features/
|
||||
- Session-scoped MCP server lifecycle management
|
||||
|
||||
## ANTI-PATTERNS
|
||||
- Sequential execution for independent tasks (use `sisyphus_task`)
|
||||
- Sequential execution for independent tasks (use `delegate_task`)
|
||||
- Trusting agent self-reports without verification
|
||||
- Blocking main thread during loader initialization
|
||||
- Manual version bumping in `package.json`
|
||||
|
||||
@@ -980,7 +980,7 @@ describe("BackgroundManager.trackTask", () => {
|
||||
sessionID: "session-1",
|
||||
parentSessionID: "parent-session",
|
||||
description: "external task",
|
||||
agent: "sisyphus_task",
|
||||
agent: "delegate_task",
|
||||
concurrencyKey: "external-key",
|
||||
}
|
||||
|
||||
@@ -1015,7 +1015,7 @@ describe("BackgroundManager.resume concurrency key", () => {
|
||||
sessionID: "session-1",
|
||||
parentSessionID: "parent-session",
|
||||
description: "external task",
|
||||
agent: "sisyphus_task",
|
||||
agent: "delegate_task",
|
||||
concurrencyKey: "external-key",
|
||||
})
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ export class BackgroundManager {
|
||||
tools: {
|
||||
...getAgentToolRestrictions(input.agent),
|
||||
task: false,
|
||||
sisyphus_task: false,
|
||||
delegate_task: false,
|
||||
call_omo_agent: true,
|
||||
},
|
||||
parts: [{ type: "text", text: input.prompt }],
|
||||
@@ -249,7 +249,7 @@ export class BackgroundManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Track a task created elsewhere (e.g., from sisyphus_task) for notification tracking.
|
||||
* Track a task created elsewhere (e.g., from delegate_task) for notification tracking.
|
||||
* This allows tasks created by other tools to receive the same toast/prompt notifications.
|
||||
*/
|
||||
async trackTask(input: {
|
||||
@@ -296,7 +296,7 @@ export class BackgroundManager {
|
||||
return existingTask
|
||||
}
|
||||
|
||||
const concurrencyGroup = input.concurrencyKey ?? input.agent ?? "sisyphus_task"
|
||||
const concurrencyGroup = input.concurrencyKey ?? input.agent ?? "delegate_task"
|
||||
|
||||
// Acquire concurrency slot if a key is provided
|
||||
if (input.concurrencyKey) {
|
||||
@@ -310,7 +310,7 @@ export class BackgroundManager {
|
||||
parentMessageID: "",
|
||||
description: input.description,
|
||||
prompt: "",
|
||||
agent: input.agent || "sisyphus_task",
|
||||
agent: input.agent || "delegate_task",
|
||||
status: "running",
|
||||
startedAt: new Date(),
|
||||
progress: {
|
||||
@@ -409,7 +409,7 @@ export class BackgroundManager {
|
||||
tools: {
|
||||
...getAgentToolRestrictions(existingTask.agent),
|
||||
task: false,
|
||||
sisyphus_task: false,
|
||||
delegate_task: false,
|
||||
call_omo_agent: true,
|
||||
},
|
||||
parts: [{ type: "text", text: input.prompt }],
|
||||
|
||||
@@ -45,12 +45,12 @@ Don't wait—these run async while main session works.
|
||||
|
||||
\`\`\`
|
||||
// Fire all at once, collect results later
|
||||
sisyphus_task(agent="explore", prompt="Project structure: PREDICT standard patterns for detected language → REPORT deviations only")
|
||||
sisyphus_task(agent="explore", prompt="Entry points: FIND main files → REPORT non-standard organization")
|
||||
sisyphus_task(agent="explore", prompt="Conventions: FIND config files (.eslintrc, pyproject.toml, .editorconfig) → REPORT project-specific rules")
|
||||
sisyphus_task(agent="explore", prompt="Anti-patterns: FIND 'DO NOT', 'NEVER', 'ALWAYS', 'DEPRECATED' comments → LIST forbidden patterns")
|
||||
sisyphus_task(agent="explore", prompt="Build/CI: FIND .github/workflows, Makefile → REPORT non-standard patterns")
|
||||
sisyphus_task(agent="explore", prompt="Test patterns: FIND test configs, test structure → REPORT unique conventions")
|
||||
delegate_task(agent="explore", prompt="Project structure: PREDICT standard patterns for detected language → REPORT deviations only")
|
||||
delegate_task(agent="explore", prompt="Entry points: FIND main files → REPORT non-standard organization")
|
||||
delegate_task(agent="explore", prompt="Conventions: FIND config files (.eslintrc, pyproject.toml, .editorconfig) → REPORT project-specific rules")
|
||||
delegate_task(agent="explore", prompt="Anti-patterns: FIND 'DO NOT', 'NEVER', 'ALWAYS', 'DEPRECATED' comments → LIST forbidden patterns")
|
||||
delegate_task(agent="explore", prompt="Build/CI: FIND .github/workflows, Makefile → REPORT non-standard patterns")
|
||||
delegate_task(agent="explore", prompt="Test patterns: FIND test configs, test structure → REPORT unique conventions")
|
||||
\`\`\`
|
||||
|
||||
<dynamic-agents>
|
||||
@@ -76,9 +76,9 @@ max_depth=$(find . -type d -not -path '*/node_modules/*' -not -path '*/.git/*' |
|
||||
Example spawning:
|
||||
\`\`\`
|
||||
// 500 files, 50k lines, depth 6, 15 large files → spawn 5+5+2+1 = 13 additional agents
|
||||
sisyphus_task(agent="explore", prompt="Large file analysis: FIND files >500 lines, REPORT complexity hotspots")
|
||||
sisyphus_task(agent="explore", prompt="Deep modules at depth 4+: FIND hidden patterns, internal conventions")
|
||||
sisyphus_task(agent="explore", prompt="Cross-cutting concerns: FIND shared utilities across directories")
|
||||
delegate_task(agent="explore", prompt="Large file analysis: FIND files >500 lines, REPORT complexity hotspots")
|
||||
delegate_task(agent="explore", prompt="Deep modules at depth 4+: FIND hidden patterns, internal conventions")
|
||||
delegate_task(agent="explore", prompt="Cross-cutting concerns: FIND shared utilities across directories")
|
||||
// ... more based on calculation
|
||||
\`\`\`
|
||||
</dynamic-agents>
|
||||
@@ -240,7 +240,7 @@ Launch document-writer agents for each location:
|
||||
|
||||
\`\`\`
|
||||
for loc in AGENTS_LOCATIONS (except root):
|
||||
sisyphus_task(agent="document-writer", prompt=\\\`
|
||||
delegate_task(agent="document-writer", prompt=\\\`
|
||||
Generate AGENTS.md for: \${loc.path}
|
||||
- Reason: \${loc.reason}
|
||||
- 30-80 lines max
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: git-master
|
||||
description: "MUST USE for ANY git operations. Atomic commits, rebase/squash, history search (blame, bisect, log -S). STRONGLY RECOMMENDED: Use with sisyphus_task(category='quick', skills=['git-master'], ...) to save context. Triggers: 'commit', 'rebase', 'squash', 'who wrote', 'when was X added', 'find the commit that'."
|
||||
description: "MUST USE for ANY git operations. Atomic commits, rebase/squash, history search (blame, bisect, log -S). STRONGLY RECOMMENDED: Use with delegate_task(category='quick', skills=['git-master'], ...) to save context. Triggers: 'commit', 'rebase', 'squash', 'who wrote', 'when was X added', 'find the commit that'."
|
||||
---
|
||||
|
||||
# Git Master Agent
|
||||
|
||||
@@ -95,7 +95,7 @@ Interpret creatively and make unexpected choices that feel genuinely designed fo
|
||||
const gitMasterSkill: BuiltinSkill = {
|
||||
name: "git-master",
|
||||
description:
|
||||
"MUST USE for ANY git operations. Atomic commits, rebase/squash, history search (blame, bisect, log -S). STRONGLY RECOMMENDED: Use with sisyphus_task(category='quick', skills=['git-master'], ...) to save context. Triggers: 'commit', 'rebase', 'squash', 'who wrote', 'when was X added', 'find the commit that'.",
|
||||
"MUST USE for ANY git operations. Atomic commits, rebase/squash, history search (blame, bisect, log -S). STRONGLY RECOMMENDED: Use with delegate_task(category='quick', skills=['git-master'], ...) to save context. Triggers: 'commit', 'rebase', 'squash', 'who wrote', 'when was X added', 'find the commit that'.",
|
||||
template: `# Git Master Agent
|
||||
|
||||
You are a Git expert combining three specializations:
|
||||
|
||||
@@ -24,7 +24,7 @@ export const TARGET_TOOLS = new Set([
|
||||
export const AGENT_TOOLS = new Set([
|
||||
"task",
|
||||
"call_omo_agent",
|
||||
"sisyphus_task",
|
||||
"delegate_task",
|
||||
]);
|
||||
|
||||
export const REMINDER_MESSAGE = `
|
||||
@@ -32,13 +32,13 @@ export const REMINDER_MESSAGE = `
|
||||
|
||||
You called a search/fetch tool directly without leveraging specialized agents.
|
||||
|
||||
RECOMMENDED: Use sisyphus_task with explore/librarian agents for better results:
|
||||
RECOMMENDED: Use delegate_task with explore/librarian agents for better results:
|
||||
|
||||
\`\`\`
|
||||
// Parallel exploration - fire multiple agents simultaneously
|
||||
sisyphus_task(agent="explore", prompt="Find all files matching pattern X")
|
||||
sisyphus_task(agent="explore", prompt="Search for implementation of Y")
|
||||
sisyphus_task(agent="librarian", prompt="Lookup documentation for Z")
|
||||
delegate_task(agent="explore", prompt="Find all files matching pattern X")
|
||||
delegate_task(agent="explore", prompt="Search for implementation of Y")
|
||||
delegate_task(agent="librarian", prompt="Lookup documentation for Z")
|
||||
|
||||
// Then continue your work while they run in background
|
||||
// System will notify you when each completes
|
||||
@@ -50,5 +50,5 @@ WHY:
|
||||
- Specialized agents have domain expertise
|
||||
- Reduces context window usage in main session
|
||||
|
||||
ALWAYS prefer: Multiple parallel sisyphus_task calls > Direct tool calls
|
||||
ALWAYS prefer: Multiple parallel delegate_task calls > Direct tool calls
|
||||
`;
|
||||
|
||||
@@ -145,13 +145,7 @@ export function createClaudeCodeHooksHook(
|
||||
const hookContent = result.messages.join("\n\n")
|
||||
log(`[claude-code-hooks] Injecting ${result.messages.length} hook messages`, { sessionID: input.sessionID, contentLength: hookContent.length, isFirstMessage })
|
||||
|
||||
if (isFirstMessage) {
|
||||
const idx = output.parts.findIndex((p) => p.type === "text" && p.text)
|
||||
if (idx >= 0) {
|
||||
output.parts[idx].text = `${hookContent}\n\n${output.parts[idx].text ?? ""}`
|
||||
log("UserPromptSubmit hooks prepended to first message parts directly", { sessionID: input.sessionID })
|
||||
}
|
||||
} else if (contextCollector) {
|
||||
if (contextCollector) {
|
||||
log("[DEBUG] Registering hook content to contextCollector", {
|
||||
sessionID: input.sessionID,
|
||||
contentLength: hookContent.length,
|
||||
@@ -168,14 +162,6 @@ export function createClaudeCodeHooksHook(
|
||||
sessionID: input.sessionID,
|
||||
contentLength: hookContent.length,
|
||||
})
|
||||
} else {
|
||||
const idx = output.parts.findIndex((p) => p.type === "text" && p.text)
|
||||
if (idx >= 0) {
|
||||
output.parts[idx].text = `${hookContent}\n\n${output.parts[idx].text ?? ""}`
|
||||
log("Hook content prepended to message (fallback)", {
|
||||
sessionID: input.sessionID,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -257,7 +243,7 @@ export function createClaudeCodeHooksHook(
|
||||
const cachedInput = getToolInput(input.sessionID, input.tool, input.callID) || {}
|
||||
|
||||
// Use metadata if available and non-empty, otherwise wrap output.output in a structured object
|
||||
// This ensures plugin tools (call_omo_agent, sisyphus_task, task) that return strings
|
||||
// This ensures plugin tools (call_omo_agent, delegate_task, task) that return strings
|
||||
// get their results properly recorded in transcripts instead of empty {}
|
||||
const metadata = output.metadata as Record<string, unknown> | undefined
|
||||
const hasMetadata = metadata && typeof metadata === "object" && Object.keys(metadata).length > 0
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
import {
|
||||
SISYPHUS_TASK_ERROR_PATTERNS,
|
||||
detectSisyphusTaskError,
|
||||
DELEGATE_TASK_ERROR_PATTERNS,
|
||||
detectDelegateTaskError,
|
||||
buildRetryGuidance,
|
||||
} from "./index"
|
||||
|
||||
describe("sisyphus-task-retry", () => {
|
||||
describe("SISYPHUS_TASK_ERROR_PATTERNS", () => {
|
||||
describe("DELEGATE_TASK_ERROR_PATTERNS", () => {
|
||||
// #given error patterns are defined
|
||||
// #then should include all known sisyphus_task error types
|
||||
// #then should include all known delegate_task error types
|
||||
it("should contain all known error patterns", () => {
|
||||
expect(SISYPHUS_TASK_ERROR_PATTERNS.length).toBeGreaterThan(5)
|
||||
expect(DELEGATE_TASK_ERROR_PATTERNS.length).toBeGreaterThan(5)
|
||||
|
||||
const patternTexts = SISYPHUS_TASK_ERROR_PATTERNS.map(p => p.pattern)
|
||||
const patternTexts = DELEGATE_TASK_ERROR_PATTERNS.map(p => p.pattern)
|
||||
expect(patternTexts).toContain("run_in_background")
|
||||
expect(patternTexts).toContain("skills")
|
||||
expect(patternTexts).toContain("category OR subagent_type")
|
||||
@@ -21,14 +21,14 @@ describe("sisyphus-task-retry", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("detectSisyphusTaskError", () => {
|
||||
describe("detectDelegateTaskError", () => {
|
||||
// #given tool output with run_in_background error
|
||||
// #when detecting error
|
||||
// #then should return matching error info
|
||||
it("should detect run_in_background missing error", () => {
|
||||
const output = "❌ Invalid arguments: 'run_in_background' parameter is REQUIRED. Use run_in_background=false for task delegation."
|
||||
|
||||
const result = detectSisyphusTaskError(output)
|
||||
const result = detectDelegateTaskError(output)
|
||||
|
||||
expect(result).not.toBeNull()
|
||||
expect(result?.errorType).toBe("missing_run_in_background")
|
||||
@@ -37,7 +37,7 @@ describe("sisyphus-task-retry", () => {
|
||||
it("should detect skills missing error", () => {
|
||||
const output = "❌ Invalid arguments: 'skills' parameter is REQUIRED. Use skills=[] if no skills needed."
|
||||
|
||||
const result = detectSisyphusTaskError(output)
|
||||
const result = detectDelegateTaskError(output)
|
||||
|
||||
expect(result).not.toBeNull()
|
||||
expect(result?.errorType).toBe("missing_skills")
|
||||
@@ -46,7 +46,7 @@ describe("sisyphus-task-retry", () => {
|
||||
it("should detect category/subagent mutual exclusion error", () => {
|
||||
const output = "❌ Invalid arguments: Provide EITHER category OR subagent_type, not both."
|
||||
|
||||
const result = detectSisyphusTaskError(output)
|
||||
const result = detectDelegateTaskError(output)
|
||||
|
||||
expect(result).not.toBeNull()
|
||||
expect(result?.errorType).toBe("mutual_exclusion")
|
||||
@@ -55,7 +55,7 @@ describe("sisyphus-task-retry", () => {
|
||||
it("should detect unknown category error", () => {
|
||||
const output = '❌ Unknown category: "invalid-cat". Available: visual-engineering, ultrabrain, quick'
|
||||
|
||||
const result = detectSisyphusTaskError(output)
|
||||
const result = detectDelegateTaskError(output)
|
||||
|
||||
expect(result).not.toBeNull()
|
||||
expect(result?.errorType).toBe("unknown_category")
|
||||
@@ -64,7 +64,7 @@ describe("sisyphus-task-retry", () => {
|
||||
it("should detect unknown agent error", () => {
|
||||
const output = '❌ Unknown agent: "fake-agent". Available agents: explore, librarian, oracle'
|
||||
|
||||
const result = detectSisyphusTaskError(output)
|
||||
const result = detectDelegateTaskError(output)
|
||||
|
||||
expect(result).not.toBeNull()
|
||||
expect(result?.errorType).toBe("unknown_agent")
|
||||
@@ -73,7 +73,7 @@ describe("sisyphus-task-retry", () => {
|
||||
it("should return null for successful output", () => {
|
||||
const output = "Background task launched.\n\nTask ID: bg_12345\nSession ID: ses_abc"
|
||||
|
||||
const result = detectSisyphusTaskError(output)
|
||||
const result = detectDelegateTaskError(output)
|
||||
|
||||
expect(result).toBeNull()
|
||||
})
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { PluginInput } from "@opencode-ai/plugin"
|
||||
|
||||
export interface SisyphusTaskErrorPattern {
|
||||
export interface DelegateTaskErrorPattern {
|
||||
pattern: string
|
||||
errorType: string
|
||||
fixHint: string
|
||||
}
|
||||
|
||||
export const SISYPHUS_TASK_ERROR_PATTERNS: SisyphusTaskErrorPattern[] = [
|
||||
export const DELEGATE_TASK_ERROR_PATTERNS: DelegateTaskErrorPattern[] = [
|
||||
{
|
||||
pattern: "run_in_background",
|
||||
errorType: "missing_run_in_background",
|
||||
@@ -45,7 +45,7 @@ export const SISYPHUS_TASK_ERROR_PATTERNS: SisyphusTaskErrorPattern[] = [
|
||||
{
|
||||
pattern: "Cannot call primary agent",
|
||||
errorType: "primary_agent",
|
||||
fixHint: "Primary agents cannot be called via sisyphus_task. Use a subagent like 'explore', 'oracle', or 'librarian'",
|
||||
fixHint: "Primary agents cannot be called via delegate_task. Use a subagent like 'explore', 'oracle', or 'librarian'",
|
||||
},
|
||||
{
|
||||
pattern: "Skills not found",
|
||||
@@ -59,10 +59,10 @@ export interface DetectedError {
|
||||
originalOutput: string
|
||||
}
|
||||
|
||||
export function detectSisyphusTaskError(output: string): DetectedError | null {
|
||||
export function detectDelegateTaskError(output: string): DetectedError | null {
|
||||
if (!output.includes("❌")) return null
|
||||
|
||||
for (const errorPattern of SISYPHUS_TASK_ERROR_PATTERNS) {
|
||||
for (const errorPattern of DELEGATE_TASK_ERROR_PATTERNS) {
|
||||
if (output.includes(errorPattern.pattern)) {
|
||||
return {
|
||||
errorType: errorPattern.errorType,
|
||||
@@ -80,16 +80,16 @@ function extractAvailableList(output: string): string | null {
|
||||
}
|
||||
|
||||
export function buildRetryGuidance(errorInfo: DetectedError): string {
|
||||
const pattern = SISYPHUS_TASK_ERROR_PATTERNS.find(
|
||||
const pattern = DELEGATE_TASK_ERROR_PATTERNS.find(
|
||||
(p) => p.errorType === errorInfo.errorType
|
||||
)
|
||||
|
||||
if (!pattern) {
|
||||
return `[sisyphus_task ERROR] Fix the error and retry with correct parameters.`
|
||||
return `[delegate_task ERROR] Fix the error and retry with correct parameters.`
|
||||
}
|
||||
|
||||
let guidance = `
|
||||
[sisyphus_task CALL FAILED - IMMEDIATE RETRY REQUIRED]
|
||||
[delegate_task CALL FAILED - IMMEDIATE RETRY REQUIRED]
|
||||
|
||||
**Error Type**: ${errorInfo.errorType}
|
||||
**Fix**: ${pattern.fixHint}
|
||||
@@ -101,11 +101,11 @@ export function buildRetryGuidance(errorInfo: DetectedError): string {
|
||||
}
|
||||
|
||||
guidance += `
|
||||
**Action**: Retry sisyphus_task NOW with corrected parameters.
|
||||
**Action**: Retry delegate_task NOW with corrected parameters.
|
||||
|
||||
Example of CORRECT call:
|
||||
\`\`\`
|
||||
sisyphus_task(
|
||||
delegate_task(
|
||||
description="Task description",
|
||||
prompt="Detailed prompt...",
|
||||
category="general", // OR subagent_type="explore"
|
||||
@@ -118,15 +118,15 @@ sisyphus_task(
|
||||
return guidance
|
||||
}
|
||||
|
||||
export function createSisyphusTaskRetryHook(_ctx: PluginInput) {
|
||||
export function createDelegateTaskRetryHook(_ctx: PluginInput) {
|
||||
return {
|
||||
"tool.execute.after": async (
|
||||
input: { tool: string; sessionID: string; callID: string },
|
||||
output: { title: string; output: string; metadata: unknown }
|
||||
) => {
|
||||
if (input.tool.toLowerCase() !== "sisyphus_task") return
|
||||
if (input.tool.toLowerCase() !== "delegate_task") return
|
||||
|
||||
const errorInfo = detectSisyphusTaskError(output.output)
|
||||
const errorInfo = detectDelegateTaskError(output.output)
|
||||
if (errorInfo) {
|
||||
const guidance = buildRetryGuidance(errorInfo)
|
||||
output.output += `\n${guidance}`
|
||||
@@ -30,4 +30,4 @@ export { createPrometheusMdOnlyHook } from "./prometheus-md-only";
|
||||
export { createTaskResumeInfoHook } from "./task-resume-info";
|
||||
export { createStartWorkHook } from "./start-work";
|
||||
export { createSisyphusOrchestratorHook } from "./sisyphus-orchestrator";
|
||||
export { createSisyphusTaskRetryHook } from "./sisyphus-task-retry";
|
||||
export { createDelegateTaskRetryHook } from "./delegate-task-retry";
|
||||
|
||||
@@ -12,7 +12,7 @@ You ARE the planner. You ARE NOT an implementer. You DO NOT write code. You DO N
|
||||
| Write/Edit | \`.sisyphus/**/*.md\` ONLY | Everything else |
|
||||
| Read | All files | - |
|
||||
| Bash | Research commands only | Implementation commands |
|
||||
| sisyphus_task | explore, librarian | - |
|
||||
| delegate_task | explore, librarian | - |
|
||||
|
||||
**IF YOU TRY TO WRITE/EDIT OUTSIDE \`.sisyphus/\`:**
|
||||
- System will BLOCK your action
|
||||
@@ -36,9 +36,9 @@ You ARE the planner. Your job: create bulletproof work plans.
|
||||
### Research Protocol
|
||||
1. **Fire parallel background agents** for comprehensive context:
|
||||
\`\`\`
|
||||
sisyphus_task(agent="explore", prompt="Find existing patterns for [topic] in codebase", background=true)
|
||||
sisyphus_task(agent="explore", prompt="Find test infrastructure and conventions", background=true)
|
||||
sisyphus_task(agent="librarian", prompt="Find official docs and best practices for [technology]", background=true)
|
||||
delegate_task(agent="explore", prompt="Find existing patterns for [topic] in codebase", background=true)
|
||||
delegate_task(agent="explore", prompt="Find test infrastructure and conventions", background=true)
|
||||
delegate_task(agent="librarian", prompt="Find official docs and best practices for [technology]", background=true)
|
||||
\`\`\`
|
||||
2. **Wait for results** before planning - rushed plans fail
|
||||
3. **Synthesize findings** into informed requirements
|
||||
@@ -101,14 +101,14 @@ TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.
|
||||
|
||||
## EXECUTION RULES
|
||||
- **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each.
|
||||
- **PARALLEL**: Fire independent agent calls simultaneously via sisyphus_task(background=true) - NEVER wait sequentially.
|
||||
- **BACKGROUND FIRST**: Use sisyphus_task for exploration/research agents (10+ concurrent if needed).
|
||||
- **PARALLEL**: Fire independent agent calls simultaneously via delegate_task(background=true) - NEVER wait sequentially.
|
||||
- **BACKGROUND FIRST**: Use delegate_task for exploration/research agents (10+ concurrent if needed).
|
||||
- **VERIFY**: Re-read request after completion. Check ALL requirements met before reporting done.
|
||||
- **DELEGATE**: Don't do everything yourself - orchestrate specialized agents for their strengths.
|
||||
|
||||
## WORKFLOW
|
||||
1. Analyze the request and identify required capabilities
|
||||
2. Spawn exploration/librarian agents via sisyphus_task(background=true) in PARALLEL (10+ if needed)
|
||||
2. Spawn exploration/librarian agents via delegate_task(background=true) in PARALLEL (10+ if needed)
|
||||
3. Always Use Plan agent with gathered context to create detailed work breakdown
|
||||
4. Execute with continuous verification against original requirements
|
||||
|
||||
|
||||
@@ -154,11 +154,11 @@ describe("prometheus-md-only", () => {
|
||||
).resolves.toBeUndefined()
|
||||
})
|
||||
|
||||
test("should inject read-only warning when Prometheus calls sisyphus_task", async () => {
|
||||
test("should inject read-only warning when Prometheus calls delegate_task", async () => {
|
||||
// #given
|
||||
const hook = createPrometheusMdOnlyHook(createMockPluginInput())
|
||||
const input = {
|
||||
tool: "sisyphus_task",
|
||||
tool: "delegate_task",
|
||||
sessionID: TEST_SESSION_ID,
|
||||
callID: "call-1",
|
||||
}
|
||||
@@ -216,7 +216,7 @@ describe("prometheus-md-only", () => {
|
||||
// #given
|
||||
const hook = createPrometheusMdOnlyHook(createMockPluginInput())
|
||||
const input = {
|
||||
tool: "sisyphus_task",
|
||||
tool: "delegate_task",
|
||||
sessionID: TEST_SESSION_ID,
|
||||
callID: "call-1",
|
||||
}
|
||||
@@ -257,11 +257,11 @@ describe("prometheus-md-only", () => {
|
||||
).resolves.toBeUndefined()
|
||||
})
|
||||
|
||||
test("should not inject warning for non-Prometheus agents calling sisyphus_task", async () => {
|
||||
test("should not inject warning for non-Prometheus agents calling delegate_task", async () => {
|
||||
// #given
|
||||
const hook = createPrometheusMdOnlyHook(createMockPluginInput())
|
||||
const input = {
|
||||
tool: "sisyphus_task",
|
||||
tool: "delegate_task",
|
||||
sessionID: TEST_SESSION_ID,
|
||||
callID: "call-1",
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ function getMessageDir(sessionID: string): string | null {
|
||||
return null
|
||||
}
|
||||
|
||||
const TASK_TOOLS = ["sisyphus_task", "task", "call_omo_agent"]
|
||||
const TASK_TOOLS = ["delegate_task", "task", "call_omo_agent"]
|
||||
|
||||
function getAgentFromMessageFiles(sessionID: string): string | undefined {
|
||||
const messageDir = getMessageDir(sessionID)
|
||||
|
||||
@@ -66,8 +66,8 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
})
|
||||
|
||||
describe("tool.execute.after handler", () => {
|
||||
test("should ignore non-sisyphus_task tools", async () => {
|
||||
// #given - hook and non-sisyphus_task tool
|
||||
test("should ignore non-delegate_task tools", async () => {
|
||||
// #given - hook and non-delegate_task tool
|
||||
const hook = createSisyphusOrchestratorHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Test Tool",
|
||||
@@ -110,7 +110,7 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
|
||||
// #when
|
||||
await hook["tool.execute.after"](
|
||||
{ tool: "sisyphus_task", sessionID },
|
||||
{ tool: "delegate_task", sessionID },
|
||||
output
|
||||
)
|
||||
|
||||
@@ -134,14 +134,14 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
|
||||
// #when
|
||||
await hook["tool.execute.after"](
|
||||
{ tool: "sisyphus_task", sessionID },
|
||||
{ tool: "delegate_task", sessionID },
|
||||
output
|
||||
)
|
||||
|
||||
// #then - standalone verification reminder appended
|
||||
expect(output.output).toContain("Task completed successfully")
|
||||
expect(output.output).toContain("MANDATORY:")
|
||||
expect(output.output).toContain("sisyphus_task(resume=")
|
||||
expect(output.output).toContain("delegate_task(resume=")
|
||||
|
||||
cleanupMessageStorage(sessionID)
|
||||
})
|
||||
@@ -171,7 +171,7 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
|
||||
// #when
|
||||
await hook["tool.execute.after"](
|
||||
{ tool: "sisyphus_task", sessionID },
|
||||
{ tool: "delegate_task", sessionID },
|
||||
output
|
||||
)
|
||||
|
||||
@@ -180,7 +180,7 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
expect(output.output).toContain("SUBAGENT WORK COMPLETED")
|
||||
expect(output.output).toContain("test-plan")
|
||||
expect(output.output).toContain("LIE")
|
||||
expect(output.output).toContain("sisyphus_task(resume=")
|
||||
expect(output.output).toContain("delegate_task(resume=")
|
||||
|
||||
cleanupMessageStorage(sessionID)
|
||||
})
|
||||
@@ -210,7 +210,7 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
|
||||
// #when
|
||||
await hook["tool.execute.after"](
|
||||
{ tool: "sisyphus_task", sessionID },
|
||||
{ tool: "delegate_task", sessionID },
|
||||
output
|
||||
)
|
||||
|
||||
@@ -247,7 +247,7 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
|
||||
// #when
|
||||
await hook["tool.execute.after"](
|
||||
{ tool: "sisyphus_task", sessionID },
|
||||
{ tool: "delegate_task", sessionID },
|
||||
output
|
||||
)
|
||||
|
||||
@@ -283,7 +283,7 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
|
||||
// #when
|
||||
await hook["tool.execute.after"](
|
||||
{ tool: "sisyphus_task", sessionID },
|
||||
{ tool: "delegate_task", sessionID },
|
||||
output
|
||||
)
|
||||
|
||||
@@ -320,7 +320,7 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
|
||||
// #when
|
||||
await hook["tool.execute.after"](
|
||||
{ tool: "sisyphus_task", sessionID },
|
||||
{ tool: "delegate_task", sessionID },
|
||||
output
|
||||
)
|
||||
|
||||
@@ -357,12 +357,12 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
|
||||
// #when
|
||||
await hook["tool.execute.after"](
|
||||
{ tool: "sisyphus_task", sessionID },
|
||||
{ tool: "delegate_task", sessionID },
|
||||
output
|
||||
)
|
||||
|
||||
// #then - should include resume instructions and verification
|
||||
expect(output.output).toContain("sisyphus_task(resume=")
|
||||
expect(output.output).toContain("delegate_task(resume=")
|
||||
expect(output.output).toContain("[x]")
|
||||
expect(output.output).toContain("MANDATORY:")
|
||||
|
||||
@@ -398,7 +398,7 @@ describe("sisyphus-orchestrator hook", () => {
|
||||
// #then
|
||||
expect(output.output).toContain("DELEGATION REQUIRED")
|
||||
expect(output.output).toContain("ORCHESTRATOR, not an IMPLEMENTER")
|
||||
expect(output.output).toContain("sisyphus_task")
|
||||
expect(output.output).toContain("delegate_task")
|
||||
})
|
||||
|
||||
test("should append delegation reminder when orchestrator edits outside .sisyphus/", async () => {
|
||||
|
||||
@@ -36,7 +36,7 @@ You just performed direct file modifications outside \`.sisyphus/\`.
|
||||
**You are an ORCHESTRATOR, not an IMPLEMENTER.**
|
||||
|
||||
As an orchestrator, you should:
|
||||
- **DELEGATE** implementation work to subagents via \`sisyphus_task\`
|
||||
- **DELEGATE** implementation work to subagents via \`delegate_task\`
|
||||
- **VERIFY** the work done by subagents
|
||||
- **COORDINATE** multiple tasks and ensure completion
|
||||
|
||||
@@ -46,7 +46,7 @@ You should NOT:
|
||||
- Implement features yourself
|
||||
|
||||
**If you need to make changes:**
|
||||
1. Use \`sisyphus_task\` to delegate to an appropriate subagent
|
||||
1. Use \`delegate_task\` to delegate to an appropriate subagent
|
||||
2. Provide clear instructions in the prompt
|
||||
3. Verify the subagent's work after completion
|
||||
|
||||
@@ -120,7 +120,7 @@ You (orchestrator-sisyphus) are attempting to directly modify a file outside \`.
|
||||
🚫 **THIS IS FORBIDDEN** (except for VERIFICATION purposes)
|
||||
|
||||
As an ORCHESTRATOR, you MUST:
|
||||
1. **DELEGATE** all implementation work via \`sisyphus_task\`
|
||||
1. **DELEGATE** all implementation work via \`delegate_task\`
|
||||
2. **VERIFY** the work done by subagents (reading files is OK)
|
||||
3. **COORDINATE** - you orchestrate, you don't implement
|
||||
|
||||
@@ -138,11 +138,11 @@ As an ORCHESTRATOR, you MUST:
|
||||
|
||||
**IF THIS IS FOR VERIFICATION:**
|
||||
Proceed if you are verifying subagent work by making a small fix.
|
||||
But for any substantial changes, USE \`sisyphus_task\`.
|
||||
But for any substantial changes, USE \`delegate_task\`.
|
||||
|
||||
**CORRECT APPROACH:**
|
||||
\`\`\`
|
||||
sisyphus_task(
|
||||
delegate_task(
|
||||
category="...",
|
||||
prompt="[specific single task with clear acceptance criteria]"
|
||||
)
|
||||
@@ -185,7 +185,7 @@ function buildVerificationReminder(sessionId: string): string {
|
||||
|
||||
**If ANY verification fails, use this immediately:**
|
||||
\`\`\`
|
||||
sisyphus_task(resume="${sessionId}", prompt="fix: [describe the specific failure]")
|
||||
delegate_task(resume="${sessionId}", prompt="fix: [describe the specific failure]")
|
||||
\`\`\``
|
||||
}
|
||||
|
||||
@@ -656,12 +656,12 @@ export function createSisyphusOrchestratorHook(
|
||||
return
|
||||
}
|
||||
|
||||
// Check sisyphus_task - inject single-task directive
|
||||
if (input.tool === "sisyphus_task") {
|
||||
// Check delegate_task - inject single-task directive
|
||||
if (input.tool === "delegate_task") {
|
||||
const prompt = output.args.prompt as string | undefined
|
||||
if (prompt && !prompt.includes(SYSTEM_DIRECTIVE_PREFIX)) {
|
||||
output.args.prompt = prompt + `\n<system-reminder>${SINGLE_TASK_DIRECTIVE}</system-reminder>`
|
||||
log(`[${HOOK_NAME}] Injected single-task directive to sisyphus_task`, {
|
||||
log(`[${HOOK_NAME}] Injected single-task directive to delegate_task`, {
|
||||
sessionID: input.sessionID,
|
||||
})
|
||||
}
|
||||
@@ -695,7 +695,7 @@ export function createSisyphusOrchestratorHook(
|
||||
return
|
||||
}
|
||||
|
||||
if (input.tool !== "sisyphus_task") {
|
||||
if (input.tool !== "delegate_task") {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const TARGET_TOOLS = ["task", "Task", "call_omo_agent", "sisyphus_task"]
|
||||
const TARGET_TOOLS = ["task", "Task", "call_omo_agent", "delegate_task"]
|
||||
|
||||
const SESSION_ID_PATTERNS = [
|
||||
/Session ID: (ses_[a-zA-Z0-9_-]+)/,
|
||||
@@ -27,7 +27,7 @@ export function createTaskResumeInfoHook() {
|
||||
const sessionId = extractSessionId(output.output)
|
||||
if (!sessionId) return
|
||||
|
||||
output.output = output.output.trimEnd() + `\n\nto resume: sisyphus_task(resume="${sessionId}", prompt="...")`
|
||||
output.output = output.output.trimEnd() + `\n\nto resume: delegate_task(resume="${sessionId}", prompt="...")`
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
16
src/index.ts
16
src/index.ts
@@ -26,7 +26,7 @@ import {
|
||||
createRalphLoopHook,
|
||||
createAutoSlashCommandHook,
|
||||
createEditErrorRecoveryHook,
|
||||
createSisyphusTaskRetryHook,
|
||||
createDelegateTaskRetryHook,
|
||||
createTaskResumeInfoHook,
|
||||
createStartWorkHook,
|
||||
createSisyphusOrchestratorHook,
|
||||
@@ -64,7 +64,7 @@ import {
|
||||
createSlashcommandTool,
|
||||
discoverCommandsSync,
|
||||
sessionExists,
|
||||
createSisyphusTask,
|
||||
createDelegateTask,
|
||||
interactive_bash,
|
||||
startTmuxCheck,
|
||||
lspManager,
|
||||
@@ -193,8 +193,8 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
||||
? createEditErrorRecoveryHook(ctx)
|
||||
: null;
|
||||
|
||||
const sisyphusTaskRetry = isHookEnabled("sisyphus-task-retry")
|
||||
? createSisyphusTaskRetryHook(ctx)
|
||||
const delegateTaskRetry = isHookEnabled("delegate-task-retry")
|
||||
? createDelegateTaskRetryHook(ctx)
|
||||
: null;
|
||||
|
||||
const startWork = isHookEnabled("start-work")
|
||||
@@ -233,7 +233,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
||||
|
||||
const callOmoAgent = createCallOmoAgent(ctx, backgroundManager);
|
||||
const lookAt = createLookAt(ctx);
|
||||
const sisyphusTask = createSisyphusTask({
|
||||
const delegateTask = createDelegateTask({
|
||||
manager: backgroundManager,
|
||||
client: ctx.client,
|
||||
directory: ctx.directory,
|
||||
@@ -302,7 +302,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
||||
...backgroundTools,
|
||||
call_omo_agent: callOmoAgent,
|
||||
look_at: lookAt,
|
||||
sisyphus_task: sisyphusTask,
|
||||
delegate_task: delegateTask,
|
||||
skill: skillTool,
|
||||
skill_mcp: skillMcpTool,
|
||||
slashcommand: slashcommandTool,
|
||||
@@ -502,7 +502,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
||||
|
||||
args.tools = {
|
||||
...(args.tools as Record<string, boolean> | undefined),
|
||||
sisyphus_task: false,
|
||||
delegate_task: false,
|
||||
...(isExploreOrLibrarian ? { call_omo_agent: false } : {}),
|
||||
};
|
||||
}
|
||||
@@ -550,7 +550,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
||||
await agentUsageReminder?.["tool.execute.after"](input, output);
|
||||
await interactiveBashSession?.["tool.execute.after"](input, output);
|
||||
await editErrorRecovery?.["tool.execute.after"](input, output);
|
||||
await sisyphusTaskRetry?.["tool.execute.after"](input, output);
|
||||
await delegateTaskRetry?.["tool.execute.after"](input, output);
|
||||
await sisyphusOrchestrator?.["tool.execute.after"]?.(input, output);
|
||||
await taskResumeInfo["tool.execute.after"](input, output);
|
||||
},
|
||||
|
||||
@@ -24,7 +24,7 @@ import type { OhMyOpenCodeConfig } from "../config";
|
||||
import { log } from "../shared";
|
||||
import { migrateAgentConfig } from "../shared/permission-compat";
|
||||
import { PROMETHEUS_SYSTEM_PROMPT, PROMETHEUS_PERMISSION } from "../agents/prometheus-prompt";
|
||||
import { DEFAULT_CATEGORIES } from "../tools/sisyphus-task/constants";
|
||||
import { DEFAULT_CATEGORIES } from "../tools/delegate-task/constants";
|
||||
import type { ModelCacheState } from "../plugin-state";
|
||||
import type { CategoryConfig } from "../config/schema";
|
||||
|
||||
@@ -303,26 +303,26 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
|
||||
}
|
||||
if (agentResult["orchestrator-sisyphus"]) {
|
||||
const agent = agentResult["orchestrator-sisyphus"] as AgentWithPermission;
|
||||
agent.permission = { ...agent.permission, task: "deny", call_omo_agent: "deny", sisyphus_task: "allow" };
|
||||
agent.permission = { ...agent.permission, task: "deny", call_omo_agent: "deny", delegate_task: "allow" };
|
||||
}
|
||||
if (agentResult.Sisyphus) {
|
||||
const agent = agentResult.Sisyphus as AgentWithPermission;
|
||||
agent.permission = { ...agent.permission, call_omo_agent: "deny", sisyphus_task: "allow" };
|
||||
agent.permission = { ...agent.permission, call_omo_agent: "deny", delegate_task: "allow" };
|
||||
}
|
||||
if (agentResult["Prometheus (Planner)"]) {
|
||||
const agent = agentResult["Prometheus (Planner)"] as AgentWithPermission;
|
||||
agent.permission = { ...agent.permission, call_omo_agent: "deny", sisyphus_task: "allow" };
|
||||
agent.permission = { ...agent.permission, call_omo_agent: "deny", delegate_task: "allow" };
|
||||
}
|
||||
if (agentResult["Sisyphus-Junior"]) {
|
||||
const agent = agentResult["Sisyphus-Junior"] as AgentWithPermission;
|
||||
agent.permission = { ...agent.permission, sisyphus_task: "allow" };
|
||||
agent.permission = { ...agent.permission, delegate_task: "allow" };
|
||||
}
|
||||
|
||||
config.permission = {
|
||||
...(config.permission as Record<string, unknown>),
|
||||
webfetch: "allow",
|
||||
external_directory: "allow",
|
||||
sisyphus_task: "deny",
|
||||
delegate_task: "deny",
|
||||
};
|
||||
|
||||
const mcpResult = (pluginConfig.claude_code?.mcp ?? true)
|
||||
|
||||
@@ -10,7 +10,7 @@ const EXPLORATION_AGENT_DENYLIST: Record<string, PermissionValue> = {
|
||||
write: "deny",
|
||||
edit: "deny",
|
||||
task: "deny",
|
||||
sisyphus_task: "deny",
|
||||
delegate_task: "deny",
|
||||
call_omo_agent: "deny",
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ const AGENT_RESTRICTIONS: Record<string, Record<string, PermissionValue>> = {
|
||||
write: "deny",
|
||||
edit: "deny",
|
||||
task: "deny",
|
||||
sisyphus_task: "deny",
|
||||
delegate_task: "deny",
|
||||
},
|
||||
|
||||
"multimodal-looker": {
|
||||
@@ -33,19 +33,19 @@ const AGENT_RESTRICTIONS: Record<string, Record<string, PermissionValue>> = {
|
||||
|
||||
"document-writer": {
|
||||
task: "deny",
|
||||
sisyphus_task: "deny",
|
||||
delegate_task: "deny",
|
||||
call_omo_agent: "deny",
|
||||
},
|
||||
|
||||
"frontend-ui-ux-engineer": {
|
||||
task: "deny",
|
||||
sisyphus_task: "deny",
|
||||
delegate_task: "deny",
|
||||
call_omo_agent: "deny",
|
||||
},
|
||||
|
||||
"Sisyphus-Junior": {
|
||||
task: "deny",
|
||||
sisyphus_task: "deny",
|
||||
delegate_task: "deny",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ tools/
|
||||
| AST | ast_grep_search, ast_grep_replace | Structural pattern matching/rewriting |
|
||||
| Search | grep, glob | Timeout-safe file and content search |
|
||||
| Session | session_list, session_read, session_search, session_info | History navigation and retrieval |
|
||||
| Background | sisyphus_task, background_output, background_cancel | Parallel agent orchestration |
|
||||
| Background | delegate_task, background_output, background_cancel | Parallel agent orchestration |
|
||||
| UI/Terminal | look_at, interactive_bash | Visual analysis and tmux control |
|
||||
| Execution | slashcommand, skill, skill_mcp | Command and skill-based extensibility |
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ async function executeSync(
|
||||
tools: {
|
||||
...getAgentToolRestrictions(args.subagent_type),
|
||||
task: false,
|
||||
sisyphus_task: false,
|
||||
delegate_task: false,
|
||||
},
|
||||
parts: [{ type: "text", text: args.prompt }],
|
||||
},
|
||||
|
||||
@@ -236,7 +236,7 @@ export const CATEGORY_DESCRIPTIONS: Record<string, string> = {
|
||||
|
||||
const BUILTIN_CATEGORIES = Object.keys(DEFAULT_CATEGORIES).join(", ")
|
||||
|
||||
export const SISYPHUS_TASK_DESCRIPTION = `Spawn agent task with category-based or direct agent selection.
|
||||
export const DELEGATE_TASK_DESCRIPTION = `Spawn agent task with category-based or direct agent selection.
|
||||
|
||||
MUTUALLY EXCLUSIVE: Provide EITHER category OR agent, not both (unless resuming).
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export { createSisyphusTask, type SisyphusTaskToolOptions } from "./tools"
|
||||
export { createDelegateTask, type DelegateTaskToolOptions } from "./tools"
|
||||
export type * from "./types"
|
||||
export * from "./constants"
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, test, expect } from "bun:test"
|
||||
import { DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS, CATEGORY_DESCRIPTIONS, SISYPHUS_TASK_DESCRIPTION } from "./constants"
|
||||
import { DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS, CATEGORY_DESCRIPTIONS, DELEGATE_TASK_DESCRIPTION } from "./constants"
|
||||
import type { CategoryConfig } from "../../config/schema"
|
||||
|
||||
function resolveCategoryConfig(
|
||||
@@ -101,16 +101,16 @@ describe("sisyphus-task", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("SISYPHUS_TASK_DESCRIPTION", () => {
|
||||
describe("DELEGATE_TASK_DESCRIPTION", () => {
|
||||
test("documents background parameter as required with default false", () => {
|
||||
// #given / #when / #then
|
||||
expect(SISYPHUS_TASK_DESCRIPTION).toContain("background")
|
||||
expect(SISYPHUS_TASK_DESCRIPTION).toContain("Default: false")
|
||||
expect(DELEGATE_TASK_DESCRIPTION).toContain("background")
|
||||
expect(DELEGATE_TASK_DESCRIPTION).toContain("Default: false")
|
||||
})
|
||||
|
||||
test("warns about parallel exploration usage", () => {
|
||||
// #given / #when / #then
|
||||
expect(SISYPHUS_TASK_DESCRIPTION).toContain("5+")
|
||||
expect(DELEGATE_TASK_DESCRIPTION).toContain("5+")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -257,7 +257,7 @@ describe("sisyphus-task", () => {
|
||||
describe("category variant", () => {
|
||||
test("passes variant to background model payload", async () => {
|
||||
// #given
|
||||
const { createSisyphusTask } = require("./tools")
|
||||
const { createDelegateTask } = require("./tools")
|
||||
let launchInput: any
|
||||
|
||||
const mockManager = {
|
||||
@@ -283,7 +283,7 @@ describe("sisyphus-task", () => {
|
||||
},
|
||||
}
|
||||
|
||||
const tool = createSisyphusTask({
|
||||
const tool = createDelegateTask({
|
||||
manager: mockManager,
|
||||
client: mockClient,
|
||||
userCategories: {
|
||||
@@ -320,17 +320,17 @@ describe("sisyphus-task", () => {
|
||||
})
|
||||
|
||||
describe("skills parameter", () => {
|
||||
test("SISYPHUS_TASK_DESCRIPTION documents skills parameter with null option", () => {
|
||||
test("DELEGATE_TASK_DESCRIPTION documents skills parameter with null option", () => {
|
||||
// #given / #when / #then
|
||||
expect(SISYPHUS_TASK_DESCRIPTION).toContain("skills")
|
||||
expect(SISYPHUS_TASK_DESCRIPTION).toContain("Array of skill names")
|
||||
expect(SISYPHUS_TASK_DESCRIPTION).toContain("Empty array [] is NOT allowed")
|
||||
expect(SISYPHUS_TASK_DESCRIPTION).toContain("null if no skills needed")
|
||||
expect(DELEGATE_TASK_DESCRIPTION).toContain("skills")
|
||||
expect(DELEGATE_TASK_DESCRIPTION).toContain("Array of skill names")
|
||||
expect(DELEGATE_TASK_DESCRIPTION).toContain("Empty array [] is NOT allowed")
|
||||
expect(DELEGATE_TASK_DESCRIPTION).toContain("null if no skills needed")
|
||||
})
|
||||
|
||||
test("skills parameter is required - returns error when not provided", async () => {
|
||||
// #given
|
||||
const { createSisyphusTask } = require("./tools")
|
||||
const { createDelegateTask } = require("./tools")
|
||||
|
||||
const mockManager = { launch: async () => ({}) }
|
||||
const mockClient = {
|
||||
@@ -343,7 +343,7 @@ describe("sisyphus-task", () => {
|
||||
},
|
||||
}
|
||||
|
||||
const tool = createSisyphusTask({
|
||||
const tool = createDelegateTask({
|
||||
manager: mockManager,
|
||||
client: mockClient,
|
||||
})
|
||||
@@ -373,7 +373,7 @@ describe("sisyphus-task", () => {
|
||||
|
||||
test("empty array [] returns error with available skills list", async () => {
|
||||
// #given
|
||||
const { createSisyphusTask } = require("./tools")
|
||||
const { createDelegateTask } = require("./tools")
|
||||
|
||||
const mockManager = { launch: async () => ({}) }
|
||||
const mockClient = {
|
||||
@@ -386,7 +386,7 @@ describe("sisyphus-task", () => {
|
||||
},
|
||||
}
|
||||
|
||||
const tool = createSisyphusTask({
|
||||
const tool = createDelegateTask({
|
||||
manager: mockManager,
|
||||
client: mockClient,
|
||||
})
|
||||
@@ -419,7 +419,7 @@ describe("sisyphus-task", () => {
|
||||
|
||||
test("null skills is allowed and proceeds without skill content", async () => {
|
||||
// #given
|
||||
const { createSisyphusTask } = require("./tools")
|
||||
const { createDelegateTask } = require("./tools")
|
||||
let promptBody: any
|
||||
|
||||
const mockManager = { launch: async () => ({}) }
|
||||
@@ -440,7 +440,7 @@ describe("sisyphus-task", () => {
|
||||
},
|
||||
}
|
||||
|
||||
const tool = createSisyphusTask({
|
||||
const tool = createDelegateTask({
|
||||
manager: mockManager,
|
||||
client: mockClient,
|
||||
})
|
||||
@@ -474,7 +474,7 @@ describe("sisyphus-task", () => {
|
||||
test("resume with background=false should wait for result and return content", async () => {
|
||||
// Note: This test needs extended timeout because the implementation has MIN_STABILITY_TIME_MS = 5000
|
||||
// #given
|
||||
const { createSisyphusTask } = require("./tools")
|
||||
const { createDelegateTask } = require("./tools")
|
||||
|
||||
const mockTask = {
|
||||
id: "task-123",
|
||||
@@ -507,7 +507,7 @@ describe("sisyphus-task", () => {
|
||||
},
|
||||
}
|
||||
|
||||
const tool = createSisyphusTask({
|
||||
const tool = createDelegateTask({
|
||||
manager: mockManager,
|
||||
client: mockClient,
|
||||
})
|
||||
@@ -538,7 +538,7 @@ describe("sisyphus-task", () => {
|
||||
|
||||
test("resume with background=true should return immediately without waiting", async () => {
|
||||
// #given
|
||||
const { createSisyphusTask } = require("./tools")
|
||||
const { createDelegateTask } = require("./tools")
|
||||
|
||||
const mockTask = {
|
||||
id: "task-456",
|
||||
@@ -562,7 +562,7 @@ describe("sisyphus-task", () => {
|
||||
config: { get: async () => ({}) },
|
||||
}
|
||||
|
||||
const tool = createSisyphusTask({
|
||||
const tool = createDelegateTask({
|
||||
manager: mockManager,
|
||||
client: mockClient,
|
||||
})
|
||||
@@ -595,7 +595,7 @@ describe("sisyphus-task", () => {
|
||||
describe("sync mode new task (run_in_background=false)", () => {
|
||||
test("sync mode prompt error returns error message immediately", async () => {
|
||||
// #given
|
||||
const { createSisyphusTask } = require("./tools")
|
||||
const { createDelegateTask } = require("./tools")
|
||||
|
||||
const mockManager = {
|
||||
launch: async () => ({}),
|
||||
@@ -617,7 +617,7 @@ describe("sisyphus-task", () => {
|
||||
},
|
||||
}
|
||||
|
||||
const tool = createSisyphusTask({
|
||||
const tool = createDelegateTask({
|
||||
manager: mockManager,
|
||||
client: mockClient,
|
||||
})
|
||||
@@ -651,7 +651,7 @@ describe("sisyphus-task", () => {
|
||||
|
||||
test("sync mode success returns task result with content", async () => {
|
||||
// #given
|
||||
const { createSisyphusTask } = require("./tools")
|
||||
const { createDelegateTask } = require("./tools")
|
||||
|
||||
const mockManager = {
|
||||
launch: async () => ({}),
|
||||
@@ -678,7 +678,7 @@ describe("sisyphus-task", () => {
|
||||
},
|
||||
}
|
||||
|
||||
const tool = createSisyphusTask({
|
||||
const tool = createDelegateTask({
|
||||
manager: mockManager,
|
||||
client: mockClient,
|
||||
})
|
||||
@@ -709,7 +709,7 @@ describe("sisyphus-task", () => {
|
||||
|
||||
test("sync mode agent not found returns helpful error", async () => {
|
||||
// #given
|
||||
const { createSisyphusTask } = require("./tools")
|
||||
const { createDelegateTask } = require("./tools")
|
||||
|
||||
const mockManager = {
|
||||
launch: async () => ({}),
|
||||
@@ -731,7 +731,7 @@ describe("sisyphus-task", () => {
|
||||
},
|
||||
}
|
||||
|
||||
const tool = createSisyphusTask({
|
||||
const tool = createDelegateTask({
|
||||
manager: mockManager,
|
||||
client: mockClient,
|
||||
})
|
||||
@@ -763,7 +763,7 @@ describe("sisyphus-task", () => {
|
||||
|
||||
test("sync mode passes category model to prompt", async () => {
|
||||
// #given
|
||||
const { createSisyphusTask } = require("./tools")
|
||||
const { createDelegateTask } = require("./tools")
|
||||
let promptBody: any
|
||||
|
||||
const mockManager = { launch: async () => ({}) }
|
||||
@@ -784,7 +784,7 @@ describe("sisyphus-task", () => {
|
||||
app: { agents: async () => ({ data: [] }) },
|
||||
}
|
||||
|
||||
const tool = createSisyphusTask({
|
||||
const tool = createDelegateTask({
|
||||
manager: mockManager,
|
||||
client: mockClient,
|
||||
userCategories: {
|
||||
@@ -2,9 +2,9 @@ import { tool, type PluginInput, type ToolDefinition } from "@opencode-ai/plugin
|
||||
import { existsSync, readdirSync } from "node:fs"
|
||||
import { join } from "node:path"
|
||||
import type { BackgroundManager } from "../../features/background-agent"
|
||||
import type { SisyphusTaskArgs } from "./types"
|
||||
import type { DelegateTaskArgs } from "./types"
|
||||
import type { CategoryConfig, CategoriesConfig, GitMasterConfig } from "../../config/schema"
|
||||
import { SISYPHUS_TASK_DESCRIPTION, DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS } from "./constants"
|
||||
import { DELEGATE_TASK_DESCRIPTION, DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS } from "./constants"
|
||||
import { findNearestMessageWithFields, findFirstMessageWithAgent, MESSAGE_STORAGE } from "../../features/hook-message-injector"
|
||||
import { resolveMultipleSkillsAsync } from "../../features/opencode-skill-loader/skill-content"
|
||||
import { discoverSkills } from "../../features/opencode-skill-loader"
|
||||
@@ -53,7 +53,7 @@ function formatDuration(start: Date, end?: Date): string {
|
||||
|
||||
interface ErrorContext {
|
||||
operation: string
|
||||
args?: SisyphusTaskArgs
|
||||
args?: DelegateTaskArgs
|
||||
sessionID?: string
|
||||
agent?: string
|
||||
category?: string
|
||||
@@ -143,7 +143,7 @@ function resolveCategoryConfig(
|
||||
return { config, promptAppend, model }
|
||||
}
|
||||
|
||||
export interface SisyphusTaskToolOptions {
|
||||
export interface DelegateTaskToolOptions {
|
||||
manager: BackgroundManager
|
||||
client: OpencodeClient
|
||||
directory: string
|
||||
@@ -170,11 +170,11 @@ export function buildSystemContent(input: BuildSystemContentInput): string | und
|
||||
return skillContent || categoryPromptAppend
|
||||
}
|
||||
|
||||
export function createSisyphusTask(options: SisyphusTaskToolOptions): ToolDefinition {
|
||||
export function createDelegateTask(options: DelegateTaskToolOptions): ToolDefinition {
|
||||
const { manager, client, directory, userCategories, gitMasterConfig } = options
|
||||
|
||||
return tool({
|
||||
description: SISYPHUS_TASK_DESCRIPTION,
|
||||
description: DELEGATE_TASK_DESCRIPTION,
|
||||
args: {
|
||||
description: tool.schema.string().describe("Short task description"),
|
||||
prompt: tool.schema.string().describe("Full detailed prompt for the agent"),
|
||||
@@ -184,7 +184,7 @@ export function createSisyphusTask(options: SisyphusTaskToolOptions): ToolDefini
|
||||
resume: tool.schema.string().optional().describe("Session ID to resume - continues previous agent session with full context"),
|
||||
skills: tool.schema.array(tool.schema.string()).nullable().describe("Array of skill names to prepend to the prompt. Use null if no skills needed. Empty array [] is NOT allowed."),
|
||||
},
|
||||
async execute(args: SisyphusTaskArgs, toolContext) {
|
||||
async execute(args: DelegateTaskArgs, toolContext) {
|
||||
const ctx = toolContext as ToolContextWithMetadata
|
||||
if (args.run_in_background === undefined) {
|
||||
return `❌ Invalid arguments: 'run_in_background' parameter is REQUIRED. Use run_in_background=false for task delegation, run_in_background=true only for parallel exploration.`
|
||||
@@ -223,7 +223,7 @@ If you believe no skills are needed, you MUST explicitly explain why to the user
|
||||
const sessionAgent = getSessionAgent(ctx.sessionID)
|
||||
const parentAgent = ctx.agent ?? sessionAgent ?? firstMessageAgent ?? prevMessage?.agent
|
||||
|
||||
log("[sisyphus_task] parentAgent resolution", {
|
||||
log("[delegate_task] parentAgent resolution", {
|
||||
sessionID: ctx.sessionID,
|
||||
messageDir,
|
||||
ctxAgent: ctx.agent,
|
||||
@@ -324,7 +324,7 @@ Use \`background_output\` with task_id="${task.id}" to check progress.`
|
||||
tools: {
|
||||
...(resumeAgent ? getAgentToolRestrictions(resumeAgent) : {}),
|
||||
task: false,
|
||||
sisyphus_task: false,
|
||||
delegate_task: false,
|
||||
call_omo_agent: true,
|
||||
},
|
||||
parts: [{ type: "text", text: args.prompt }],
|
||||
@@ -502,7 +502,7 @@ ${textContent || "(No text output)"}`
|
||||
if (!callableNames.includes(agentToUse)) {
|
||||
const isPrimaryAgent = agents.some((a) => a.name === agentToUse && a.mode === "primary")
|
||||
if (isPrimaryAgent) {
|
||||
return `❌ Cannot call primary agent "${agentToUse}" via sisyphus_task. Primary agents are top-level orchestrators.`
|
||||
return `❌ Cannot call primary agent "${agentToUse}" via delegate_task. Primary agents are top-level orchestrators.`
|
||||
}
|
||||
|
||||
const availableAgents = callableNames
|
||||
@@ -610,7 +610,7 @@ System notifies on completion. Use \`background_output\` with task_id="${task.id
|
||||
system: systemContent,
|
||||
tools: {
|
||||
task: false,
|
||||
sisyphus_task: false,
|
||||
delegate_task: false,
|
||||
call_omo_agent: true,
|
||||
},
|
||||
parts: [{ type: "text", text: args.prompt }],
|
||||
@@ -651,11 +651,11 @@ System notifies on completion. Use \`background_output\` with task_id="${task.id
|
||||
let stablePolls = 0
|
||||
let pollCount = 0
|
||||
|
||||
log("[sisyphus_task] Starting poll loop", { sessionID, agentToUse })
|
||||
log("[delegate_task] Starting poll loop", { sessionID, agentToUse })
|
||||
|
||||
while (Date.now() - pollStart < MAX_POLL_TIME_MS) {
|
||||
if (ctx.abort?.aborted) {
|
||||
log("[sisyphus_task] Aborted by user", { sessionID })
|
||||
log("[delegate_task] Aborted by user", { sessionID })
|
||||
if (toastManager && taskId) toastManager.removeTask(taskId)
|
||||
return `Task aborted.\n\nSession ID: ${sessionID}`
|
||||
}
|
||||
@@ -668,7 +668,7 @@ System notifies on completion. Use \`background_output\` with task_id="${task.id
|
||||
const sessionStatus = allStatuses[sessionID]
|
||||
|
||||
if (pollCount % 10 === 0) {
|
||||
log("[sisyphus_task] Poll status", {
|
||||
log("[delegate_task] Poll status", {
|
||||
sessionID,
|
||||
pollCount,
|
||||
elapsed: Math.floor((Date.now() - pollStart) / 1000) + "s",
|
||||
@@ -696,7 +696,7 @@ System notifies on completion. Use \`background_output\` with task_id="${task.id
|
||||
if (currentMsgCount === lastMsgCount) {
|
||||
stablePolls++
|
||||
if (stablePolls >= STABILITY_POLLS_REQUIRED) {
|
||||
log("[sisyphus_task] Poll complete - messages stable", { sessionID, pollCount, currentMsgCount })
|
||||
log("[delegate_task] Poll complete - messages stable", { sessionID, pollCount, currentMsgCount })
|
||||
break
|
||||
}
|
||||
} else {
|
||||
@@ -706,7 +706,7 @@ System notifies on completion. Use \`background_output\` with task_id="${task.id
|
||||
}
|
||||
|
||||
if (Date.now() - pollStart >= MAX_POLL_TIME_MS) {
|
||||
log("[sisyphus_task] Poll timeout reached", { sessionID, pollCount, lastMsgCount, stablePolls })
|
||||
log("[delegate_task] Poll timeout reached", { sessionID, pollCount, lastMsgCount, stablePolls })
|
||||
}
|
||||
|
||||
const messagesResult = await client.session.messages({
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface SisyphusTaskArgs {
|
||||
export interface DelegateTaskArgs {
|
||||
description: string
|
||||
prompt: string
|
||||
category?: string
|
||||
@@ -45,7 +45,7 @@ type OpencodeClient = PluginInput["client"]
|
||||
|
||||
export { createCallOmoAgent } from "./call-omo-agent"
|
||||
export { createLookAt } from "./look-at"
|
||||
export { createSisyphusTask, type SisyphusTaskToolOptions, DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS } from "./sisyphus-task"
|
||||
export { createDelegateTask, type DelegateTaskToolOptions, DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS } from "./delegate-task"
|
||||
|
||||
export function createBackgroundTools(manager: BackgroundManager, client: OpencodeClient): Record<string, ToolDefinition> {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user