@scemoon/cdh 1.0.0 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cdh/__pycache__/__main__.cpython-314.pyc +0 -0
- package/cdh/__pycache__/cli.cpython-314.pyc +0 -0
- package/cdh/__pycache__/scaffold.cpython-314.pyc +0 -0
- package/cdh/cli.py +473 -87
- package/cdh/scaffold.py +386 -121
- package/onecode/__pycache__/cli.cpython-314.pyc +0 -0
- package/onecode/__pycache__/commands.cpython-314.pyc +0 -0
- package/onecode/__pycache__/config.cpython-314.pyc +0 -0
- package/onecode/__pycache__/config_screen.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/cdh_loader.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/engine.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/onecode_agent_acp.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/session.cpython-314.pyc +0 -0
- package/onecode/agent/agents/__pycache__/types.cpython-314.pyc +0 -0
- package/onecode/agent/agents/types.py +123 -79
- package/onecode/agent/cdh_loader.py +26 -13
- package/onecode/agent/engine.py +426 -235
- package/onecode/agent/onecode_agent_acp.py +200 -73
- package/onecode/agent/session.py +8 -13
- package/onecode/agent/tools/__pycache__/agent_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/task_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/todo_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/agent_tools.py +4 -4
- package/onecode/agent/tools/todo_tools.py +188 -0
- package/onecode/cli.py +3 -3
- package/onecode/commands.py +439 -194
- package/onecode/config.py +3 -3
- package/onecode/config_screen.py +4 -2
- package/onecode/models/__pycache__/errors.cpython-314.pyc +0 -0
- package/onecode/models/__pycache__/messages.cpython-314.pyc +0 -0
- package/onecode/models/__pycache__/provider.cpython-314.pyc +0 -0
- package/onecode/models/errors.py +11 -1
- package/onecode/models/messages.py +35 -16
- package/onecode/models/provider.py +243 -12
- package/onecode/models/providers/__pycache__/anthropic_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/deepseek_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/glm_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/minimax_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/minimaxi_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/ollama_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/openai_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/anthropic_provider.py +4 -2
- package/onecode/models/providers/deepseek_provider.py +2 -0
- package/onecode/models/providers/glm_provider.py +2 -1
- package/onecode/models/providers/minimax_provider.py +2 -1
- package/onecode/models/providers/minimaxi_provider.py +76 -25
- package/onecode/models/providers/ollama_provider.py +2 -1
- package/onecode/models/providers/openai_provider.py +4 -0
- package/onecode/skills/__pycache__/manager.cpython-314.pyc +0 -0
- package/onecode/tasks/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/tasks/__pycache__/manager.cpython-314.pyc +0 -0
- package/onecode/tasks/__pycache__/models.cpython-314.pyc +0 -0
- package/onecode/tasks/manager.py +1 -1
- package/package.json +1 -1
- package/pyproject.toml +10 -0
- package/run.js +24 -7
- package/tui/__pycache__/app.cpython-314.pyc +0 -0
- package/tui/__pycache__/cli.cpython-314.pyc +0 -0
- package/tui/__pycache__/db.cpython-314.pyc +0 -0
- package/tui/__pycache__/directory_suggester.cpython-314.pyc +0 -0
- package/tui/__pycache__/directory_watcher.cpython-314.pyc +0 -0
- package/tui/__pycache__/messages.cpython-314.pyc +0 -0
- package/tui/__pycache__/paths.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
- package/tui/acp/agent.py +60 -11
- package/tui/acp/api.py +6 -0
- package/tui/acp/messages.py +11 -0
- package/tui/acp/prompt.py +1 -1
- package/tui/acp/protocol.py +31 -0
- package/tui/app.py +60 -8
- package/tui/db.py +23 -0
- package/tui/directory_watcher.py +35 -1
- package/tui/messages.py +4 -1
- package/tui/paths.py +3 -3
- package/tui/screens/__pycache__/agent_modal.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/component_picker.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/log.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/projects_app.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/projects_screen.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/settings.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/store.cpython-314.pyc +0 -0
- package/tui/screens/component_picker.py +148 -0
- package/tui/screens/main.py +47 -95
- package/tui/screens/projects.tcss +10 -0
- package/tui/screens/projects_app.py +33 -5
- package/tui/screens/projects_screen.py +171 -9
- package/tui/widgets/__pycache__/acp_content.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/ask_user.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/directory_input.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/mandelbrot.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/project_directory_tree.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/project_grid_select.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/question.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/subagent.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/subagent_screen.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
- package/tui/widgets/ask_user.py +1 -1
- package/tui/widgets/conversation.py +99 -42
- package/tui/widgets/modified_files.py +155 -23
- package/tui/widgets/plan.py +22 -0
- package/tui/widgets/project_directory_tree.py +22 -10
- package/tui/widgets/project_grid_select.py +23 -1
- package/tui/widgets/question.py +1 -1
- package/tui/widgets/subagent.py +202 -36
- package/tui/widgets/subagent_screen.py +186 -0
- package/tui/widgets/tool_call.py +5 -8
- package/onecode/agent/tools/task_tools.py +0 -249
|
@@ -114,7 +114,12 @@ class BuildAgent(AgentConfig):
|
|
|
114
114
|
def __init__(self):
|
|
115
115
|
super().__init__(
|
|
116
116
|
name="build",
|
|
117
|
-
description=
|
|
117
|
+
description=(
|
|
118
|
+
"Full development agent with all tools enabled. Edits and shell "
|
|
119
|
+
"commands require user approval. Uses CoT reasoning + ReAct loop "
|
|
120
|
+
"with routing by complexity: simple work → TodoCreate, complex "
|
|
121
|
+
"work → Spawn subagent."
|
|
122
|
+
),
|
|
118
123
|
mode=AgentMode.PRIMARY,
|
|
119
124
|
permission_edit=AgentPermission.ASK,
|
|
120
125
|
permission_bash=AgentPermission.ASK,
|
|
@@ -131,7 +136,13 @@ class PlanAgent(AgentConfig):
|
|
|
131
136
|
def __init__(self):
|
|
132
137
|
super().__init__(
|
|
133
138
|
name="plan",
|
|
134
|
-
description=
|
|
139
|
+
description=(
|
|
140
|
+
"Plan mode: CoT + ReAct (思考→行动→观察) agent with hard plan "
|
|
141
|
+
"gate. Creates a todo plan first via TodoCreate, presents for "
|
|
142
|
+
"user review, then routes execution by complexity: simple todos "
|
|
143
|
+
"run directly, complex todos are delegated to Spawn subagents. "
|
|
144
|
+
"Human-in-the-loop."
|
|
145
|
+
),
|
|
135
146
|
mode=AgentMode.PRIMARY,
|
|
136
147
|
permission_edit=AgentPermission.ASK,
|
|
137
148
|
permission_bash=AgentPermission.ASK,
|
|
@@ -148,7 +159,12 @@ class SoloAgent(AgentConfig):
|
|
|
148
159
|
def __init__(self):
|
|
149
160
|
super().__init__(
|
|
150
161
|
name="solo",
|
|
151
|
-
description=
|
|
162
|
+
description=(
|
|
163
|
+
"Independent agent that plans first, then acts with full tool "
|
|
164
|
+
"access. Uses CoT reasoning + ReAct loop with routing by "
|
|
165
|
+
"complexity: simple work → TodoCreate, complex work → Spawn "
|
|
166
|
+
"subagent. Shell commands require user approval."
|
|
167
|
+
),
|
|
152
168
|
mode=AgentMode.PRIMARY,
|
|
153
169
|
permission_edit=AgentPermission.ALLOW,
|
|
154
170
|
permission_bash=AgentPermission.ASK,
|
|
@@ -165,13 +181,19 @@ class GeneralAgent(AgentConfig):
|
|
|
165
181
|
def __init__(self):
|
|
166
182
|
super().__init__(
|
|
167
183
|
name="general",
|
|
168
|
-
description=
|
|
184
|
+
description=(
|
|
185
|
+
"General-purpose subagent for complex multi-step tasks. Executes "
|
|
186
|
+
"focused work delegated by parent agent via Spawn tool. Uses "
|
|
187
|
+
"CoT + ReAct internally."
|
|
188
|
+
),
|
|
169
189
|
mode=AgentMode.SUBAGENT,
|
|
170
190
|
permission_edit=AgentPermission.ALLOW,
|
|
171
191
|
permission_bash=AgentPermission.ALLOW,
|
|
172
192
|
permission_read=AgentPermission.ALLOW,
|
|
193
|
+
permission_task=AgentPermission.DENY,
|
|
194
|
+
permission_question=AgentPermission.DENY,
|
|
173
195
|
permission_todowrite=AgentPermission.DENY,
|
|
174
|
-
|
|
196
|
+
disallowed_tools=["Spawn", "Agent", "AskUser"],
|
|
175
197
|
)
|
|
176
198
|
|
|
177
199
|
|
|
@@ -184,8 +206,11 @@ class ExploreAgent(AgentConfig):
|
|
|
184
206
|
permission_edit=AgentPermission.DENY,
|
|
185
207
|
permission_bash=AgentPermission.DENY,
|
|
186
208
|
permission_read=AgentPermission.ALLOW,
|
|
209
|
+
permission_task=AgentPermission.DENY,
|
|
210
|
+
permission_question=AgentPermission.DENY,
|
|
211
|
+
permission_todowrite=AgentPermission.DENY,
|
|
212
|
+
disallowed_tools=["Spawn", "Agent", "AskUser"],
|
|
187
213
|
hidden=True,
|
|
188
|
-
tools=[],
|
|
189
214
|
)
|
|
190
215
|
|
|
191
216
|
|
|
@@ -200,8 +225,11 @@ class ScoutAgent(AgentConfig):
|
|
|
200
225
|
permission_read=AgentPermission.ALLOW,
|
|
201
226
|
permission_webfetch=AgentPermission.ALLOW,
|
|
202
227
|
permission_websearch=AgentPermission.ALLOW,
|
|
228
|
+
permission_task=AgentPermission.DENY,
|
|
229
|
+
permission_question=AgentPermission.DENY,
|
|
230
|
+
permission_todowrite=AgentPermission.DENY,
|
|
231
|
+
disallowed_tools=["Spawn", "Agent", "AskUser"],
|
|
203
232
|
hidden=True,
|
|
204
|
-
tools=[],
|
|
205
233
|
)
|
|
206
234
|
|
|
207
235
|
|
|
@@ -291,6 +319,19 @@ def get_agent_by_name(name: str) -> Optional[AgentConfig]:
|
|
|
291
319
|
return None
|
|
292
320
|
|
|
293
321
|
|
|
322
|
+
SUBAGENT_CONSTRAINTS = """
|
|
323
|
+
### Constraints (subagent)
|
|
324
|
+
You are running as a subagent spawned by a parent agent via the Spawn tool.
|
|
325
|
+
- You CANNOT spawn subagents (Spawn tool is disabled).
|
|
326
|
+
- You CANNOT execute batched tool calls (Agent tool is disabled).
|
|
327
|
+
- You CANNOT manage task plans (TodoCreate/TodoUpdate/TodoStop are disabled).
|
|
328
|
+
- You CANNOT interact with the user (AskUser is disabled).
|
|
329
|
+
- You are a leaf node in the agent hierarchy. Execute the task in your prompt
|
|
330
|
+
and return a structured SUMMARY/CHANGES/EVIDENCE/RISKS/BLOCKERS response.
|
|
331
|
+
- Do not narrate "I will now..." in visible text; all reasoning in <thinking>.
|
|
332
|
+
"""
|
|
333
|
+
|
|
334
|
+
|
|
294
335
|
def get_system_prompt(agent_type: str) -> str:
|
|
295
336
|
agent = create_agent(agent_type)
|
|
296
337
|
lines = [
|
|
@@ -303,6 +344,9 @@ def get_system_prompt(agent_type: str) -> str:
|
|
|
303
344
|
if agent.should_ask_for_bash():
|
|
304
345
|
lines.append("- Shell commands require user approval")
|
|
305
346
|
|
|
347
|
+
if agent.mode == AgentMode.SUBAGENT:
|
|
348
|
+
lines.append(SUBAGENT_CONSTRAINTS)
|
|
349
|
+
|
|
306
350
|
return "\n".join(lines)
|
|
307
351
|
|
|
308
352
|
|
|
@@ -426,15 +470,13 @@ Rules:
|
|
|
426
470
|
- **ConfigWrite**: config_write(key, value) - Set allowed configuration values (does NOT expose secrets).
|
|
427
471
|
|
|
428
472
|
### Tasks & Planning (CDH)
|
|
429
|
-
- **
|
|
430
|
-
- **
|
|
431
|
-
- **
|
|
432
|
-
- **
|
|
433
|
-
- **
|
|
434
|
-
- **
|
|
435
|
-
- **
|
|
436
|
-
- **TodoList**: todo_list() - List all todos.
|
|
437
|
-
- **TodoComplete**: todo_complete(todo_id) - Mark a todo as complete.
|
|
473
|
+
- **TodoCreate**: todo_create(subject, description, activeForm="", metadata={}) - Create a task. Returns task id.
|
|
474
|
+
- **TodoGet**: todo_get(taskId) - Retrieve a task by ID.
|
|
475
|
+
- **TodoList**: todo_list() - List all tasks with status, owner, and blockers.
|
|
476
|
+
- **TodoUpdate**: todo_update(taskId, subject, description, activeForm, status, owner, addBlocks, addBlockedBy, metadata, output) - Update task fields and dependencies.
|
|
477
|
+
- **TodoOutput**: todo_output(task_id) - Get output from a task.
|
|
478
|
+
- **TodoStop**: todo_stop(task_id) - Stop a running task.
|
|
479
|
+
- **Spawn**: spawn(agent_type, prompt) - Delegate a subtask to a specialized subagent.
|
|
438
480
|
"""
|
|
439
481
|
|
|
440
482
|
def filter_tool_descriptions(
|
|
@@ -498,29 +540,31 @@ Before any action, reason step by step inside `<thinking>`:
|
|
|
498
540
|
1. **Current state**: What do I know? What has been done? What are the results?
|
|
499
541
|
2. **Goal**: What needs to be accomplished next?
|
|
500
542
|
3. **Plan**: How should I approach it? What's the smallest next step?
|
|
501
|
-
4. **
|
|
502
|
-
- **
|
|
503
|
-
|
|
504
|
-
-
|
|
543
|
+
4. **Routing — choose by complexity**:
|
|
544
|
+
- **Simple / single-step** → use a direct read/search/exec tool, optionally
|
|
545
|
+
track with `TodoCreate` so the sidebar shows progress.
|
|
546
|
+
- **Complex / multi-step** → use `Spawn(agent_type, prompt)` to delegate to
|
|
547
|
+
a focused subagent.
|
|
548
|
+
- **Multi-file refactor / new feature** → ALWAYS use `Spawn`.
|
|
505
549
|
|
|
506
550
|
### Action Phase (行动阶段)
|
|
507
551
|
Execute the chosen action. **Action types (in priority order)**:
|
|
508
|
-
1. **Delegate via
|
|
509
|
-
2. **
|
|
510
|
-
3. **Research**: `Read()` / `Grep()` / `Glob()` / `WebFetch()` / `WebSearch()` for information
|
|
511
|
-
4. **Direct execute**: Only for trivial single-step operations that cannot justify a subagent.
|
|
552
|
+
1. **Delegate via Spawn** (complex work): `Spawn(agent_type="general"|"explore"|"scout", prompt="...")`.
|
|
553
|
+
2. **Track via Todo** (simple work): `TodoCreate(subject, description, activeForm, metadata)` and `TodoUpdate(...)`. The sidebar shows progress to the user.
|
|
554
|
+
3. **Research directly**: `Read()` / `Grep()` / `Glob()` / `WebFetch()` / `WebSearch()` for single-step information needs.
|
|
555
|
+
4. **Direct execute**: Only for trivial single-step operations that cannot justify a subagent or a todo.
|
|
512
556
|
|
|
513
557
|
### Observation Phase (观察阶段)
|
|
514
558
|
The tool result IS your observation. Process it:
|
|
515
|
-
- **Success**: Note key outputs, update
|
|
559
|
+
- **Success**: Note key outputs, update todo status via `TodoUpdate(status="completed")`, move to next step
|
|
516
560
|
- **Error**: Diagnose root cause, decide: retry with fix | modify plan | ask user
|
|
517
561
|
- **Partial**: Extract what worked, adjust approach for remaining work
|
|
518
562
|
|
|
519
563
|
### Core Rules
|
|
520
564
|
- **ALL reasoning goes in `<thinking>`**: Never narrate "I will now..." in visible text
|
|
521
|
-
- **
|
|
522
|
-
- **One responsibility per
|
|
523
|
-
- **Pass context**: Include relevant context (file paths, findings) in
|
|
565
|
+
- **Route by complexity**: Simple → Todo, complex → Spawn. Never blindly use Spawn for trivial work.
|
|
566
|
+
- **One responsibility per Spawn / Todo**: Each unit should have a clear, focused goal
|
|
567
|
+
- **Pass context**: Include relevant context (file paths, findings) in Spawn prompts and Todo descriptions
|
|
524
568
|
- **CoT every cycle**: Every turn starts with `<thinking>` reasoning before any action
|
|
525
569
|
"""
|
|
526
570
|
|
|
@@ -528,26 +572,25 @@ PLAN_INSTRUCTIONS = """
|
|
|
528
572
|
## ReAct Workflow (Thought → Action → Observation)
|
|
529
573
|
|
|
530
574
|
The agent is a **ReAct** implementation: each cycle is **Thought → Action → Observation**.
|
|
531
|
-
**Action always delegates to `Task` subagents for any substantial work.**
|
|
532
575
|
**Human-in-the-loop** means you involve the user at key decision points.
|
|
533
576
|
|
|
534
577
|
```
|
|
535
578
|
Loop:
|
|
536
579
|
Thought → Reason step by step (CoT) inside <thinking>
|
|
537
|
-
Always ask: "
|
|
538
|
-
Action →
|
|
539
|
-
|
|
580
|
+
Always ask: "Is this simple (Todo) or complex (Spawn)?"
|
|
581
|
+
Action → Simple → TodoCreate + direct tool
|
|
582
|
+
Complex → Spawn(agent_type, prompt)
|
|
540
583
|
Observation → Incorporate results into the next Thought
|
|
541
584
|
```
|
|
542
585
|
|
|
543
|
-
Plan/Build/Solo are different configurations of this same ReAct engine
|
|
544
|
-
|
|
545
|
-
- **
|
|
546
|
-
- **build**/**solo** mode: soft gate — execution allowed but planning encouraged
|
|
586
|
+
Plan/Build/Solo are different configurations of this same ReAct engine:
|
|
587
|
+
- **plan** mode: hard gate — execution tools blocked until a todo plan exists.
|
|
588
|
+
- **build**/**solo** mode: soft gate — execution allowed but planning encouraged.
|
|
547
589
|
|
|
548
|
-
**
|
|
549
|
-
file
|
|
550
|
-
|
|
590
|
+
**Routing principle**:
|
|
591
|
+
- **Simple todo** = 1 tool call, 1 file, ≤2 lines of code change, single Read/Glob. Use `TodoCreate` + direct tool.
|
|
592
|
+
- **Complex work** = >1 tool call, multi-file, research, refactor, new feature. Use `Spawn(agent_type, prompt)`.
|
|
593
|
+
- When in doubt, choose `Spawn`. Subagents encapsulate work cleanly; todos are for visible progress on the main agent's own work.
|
|
551
594
|
|
|
552
595
|
---
|
|
553
596
|
|
|
@@ -556,57 +599,58 @@ file modification MUST be delegated to a `Task` subagent. Direct execution
|
|
|
556
599
|
Analyze the request with step-by-step reasoning before any action.
|
|
557
600
|
|
|
558
601
|
- Wrap ALL reasoning in `<thinking>...</thinking>` — visible text is for the user only
|
|
559
|
-
- Think step by step: What's the goal? What's the current state?
|
|
560
|
-
- **
|
|
602
|
+
- Think step by step: What's the goal? What's the current state? Is this simple or complex?
|
|
603
|
+
- **Decide routing**:
|
|
604
|
+
- For simple work → proceed to `TodoCreate` then act directly.
|
|
605
|
+
- For complex work → proceed to spawn subagents.
|
|
561
606
|
- Read relevant files, grep for patterns, glob for structure
|
|
562
607
|
- Use `webfetch`/`websearch` for external APIs or docs
|
|
563
|
-
- Delegate deep research to `explore`/`scout` subagents via `
|
|
564
|
-
- Ask the user via `
|
|
565
|
-
- Do NOT create
|
|
608
|
+
- Delegate deep research to `explore`/`scout` subagents via `Spawn`
|
|
609
|
+
- Ask the user via `AskUser` if requirements are ambiguous
|
|
610
|
+
- Do NOT create todos yet — first understand what is needed
|
|
566
611
|
|
|
567
612
|
---
|
|
568
613
|
|
|
569
|
-
### Step 2: Act (Plan) — Create the
|
|
614
|
+
### Step 2: Act (Plan) — Create the Todo Plan
|
|
570
615
|
|
|
571
|
-
Once you understand the work, create a complete
|
|
616
|
+
Once you understand the work, create a complete todo plan via `TodoCreate()`.
|
|
572
617
|
|
|
573
|
-
**
|
|
574
|
-
- One
|
|
575
|
-
- Each
|
|
576
|
-
-
|
|
577
|
-
-
|
|
618
|
+
**Routing Granularity Rules**
|
|
619
|
+
- One todo = one focused unit of work (file, function, or concern).
|
|
620
|
+
- Each todo: decide at creation time whether it should be done by the main agent or delegated to a Spawn subagent.
|
|
621
|
+
- Mark delegatable todos with `metadata={"delegate_to": "general"}` so the main agent knows to use `Spawn` for that item.
|
|
622
|
+
- Simple todos (1 tool call) stay with the main agent.
|
|
623
|
+
- If a todo needs >5 tool calls, split it into smaller todos.
|
|
578
624
|
|
|
579
|
-
**Creating
|
|
625
|
+
**Creating Todos**
|
|
580
626
|
```
|
|
581
|
-
|
|
582
|
-
|
|
627
|
+
TodoCreate(subject="<verb + noun>", description="<what + acceptance criteria>",
|
|
628
|
+
metadata={"priority": "high|medium|low",
|
|
629
|
+
"effort": "small|medium|large",
|
|
630
|
+
"delegate_to": "general|explore|scout|main"})
|
|
583
631
|
```
|
|
584
|
-
- Set `addBlockedBy` on dependent
|
|
585
|
-
- **Create ALL
|
|
632
|
+
- Set `addBlockedBy` on dependent todos so the dependency DAG is clear
|
|
633
|
+
- **Create ALL todos upfront** before presenting the plan to the user
|
|
586
634
|
|
|
587
635
|
**Present Plan for Review (Human-in-the-loop)**
|
|
588
|
-
After creating all
|
|
589
|
-
|
|
590
|
-
```
|
|
591
|
-
send_message("Plan: 1. Setup DB model 2. Add API endpoint 3. Write tests")
|
|
592
|
-
ask_user("Shall I proceed with executing this plan?")
|
|
593
|
-
```
|
|
636
|
+
After creating all todos, use `AskUser` to summarize the plan and get approval
|
|
637
|
+
before executing.
|
|
594
638
|
Wait for user approval before moving to execution.
|
|
595
639
|
|
|
596
640
|
---
|
|
597
641
|
|
|
598
|
-
### Step 3: Act (Execute) —
|
|
642
|
+
### Step 3: Act (Execute) — Route by Complexity
|
|
599
643
|
|
|
600
|
-
Execute
|
|
644
|
+
Execute each todo using the right tool for the work:
|
|
601
645
|
|
|
602
|
-
- **
|
|
603
|
-
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
-
|
|
608
|
-
|
|
609
|
-
- After each
|
|
646
|
+
- **Simple todos** (single tool call): execute directly with `Read`/`Edit`/`Bash`, then `TodoUpdate(status="completed")`.
|
|
647
|
+
- **Complex todos** (multi-step, multi-file, research):
|
|
648
|
+
`Spawn(agent_type="general", prompt="Detailed instructions with context...")`.
|
|
649
|
+
Wait for the subagent's SUMMARY/CHANGES/EVIDENCE/RISKS/BLOCKERS output, then
|
|
650
|
+
`TodoUpdate(status="completed")`.
|
|
651
|
+
- Use `general` subagent for implementation, `explore` for code search, `scout` for research
|
|
652
|
+
- Pass enough context in the Spawn prompt: relevant file paths, code snippets, requirements
|
|
653
|
+
- After each todo, advance its status: `pending` → `in_progress` → `completed`
|
|
610
654
|
|
|
611
655
|
---
|
|
612
656
|
|
|
@@ -614,20 +658,20 @@ Execute by **delegating to Task subagents** rather than using direct tools.
|
|
|
614
658
|
|
|
615
659
|
After every Action, the tool result is your **Observation**. Use it to inform the
|
|
616
660
|
next Thought:
|
|
617
|
-
-
|
|
618
|
-
-
|
|
661
|
+
- Spawn subagent completed → review SUMMARY/CHANGES/EVIDENCE/RISKS/BLOCKERS sections
|
|
662
|
+
- TodoCreate succeeded → proceed to present plan or execute the next todo
|
|
619
663
|
- Error occurred → diagnose and decide: retry, modify plan, or ask the user
|
|
620
|
-
- User denied an action → adapt the
|
|
664
|
+
- User denied an action → adapt the todo plan accordingly
|
|
621
665
|
|
|
622
666
|
---
|
|
623
667
|
|
|
624
668
|
### Rules
|
|
625
669
|
|
|
626
|
-
- **No top-level planning prose**: All planning goes through
|
|
670
|
+
- **No top-level planning prose**: All planning goes through `TodoCreate`/`TodoUpdate` so the sidebar renders it.
|
|
627
671
|
- **CoT in `<thinking>`**: Every turn starts with chain-of-thought reasoning inside `<thinking>`. Never narrate "I will now…" in visible text.
|
|
628
|
-
- **
|
|
629
|
-
- **
|
|
630
|
-
- **No execution without a plan**: Write/Edit/Insert/ApplyPatch/Bash require
|
|
672
|
+
- **Route by complexity**: Simple → Todo + direct tool. Complex → Spawn.
|
|
673
|
+
- **Todo status discipline**: `pending` → `in_progress` → `completed`. Every todo transitions through all three.
|
|
674
|
+
- **No execution without a plan**: Write/Edit/Insert/ApplyPatch/Bash require todos. Create todos first.
|
|
631
675
|
- **Human at key decisions**: Present the plan, get approval, then execute. Report progress as you go.
|
|
632
676
|
"""
|
|
633
677
|
|
|
@@ -11,7 +11,7 @@ def _walk_up_parents(workspace_root: Path):
|
|
|
11
11
|
"""Yield workspace root, then git root.
|
|
12
12
|
|
|
13
13
|
Unlike :class:`~onecode.skills.loader.SkillLoader` we deliberately do
|
|
14
|
-
**not** yield ``Path.home()`` — the global ``~/.
|
|
14
|
+
**not** yield ``Path.home()`` — the global ``~/.cdh/`` is the onecode
|
|
15
15
|
user-config directory, not a project-level ``.cdh/``, so including it
|
|
16
16
|
would cause false-positive matches.
|
|
17
17
|
"""
|
|
@@ -41,8 +41,9 @@ class CdhProjectLoader:
|
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
43
|
CDH_DIRNAME = ".cdh"
|
|
44
|
+
STATE_FILENAME = "state.json"
|
|
44
45
|
LAST_SESSION_FILENAME = "last_session.json"
|
|
45
|
-
|
|
46
|
+
TODOS_FILENAME = "todos.json"
|
|
46
47
|
PERMISSIONS_FILENAME = "permissions.json"
|
|
47
48
|
|
|
48
49
|
# ── discovery ──────────────────────────────────────────────
|
|
@@ -82,7 +83,7 @@ class CdhProjectLoader:
|
|
|
82
83
|
@staticmethod
|
|
83
84
|
def load_project_state(cdh_dir: Path) -> dict:
|
|
84
85
|
"""Read ``.cdh/state.json``."""
|
|
85
|
-
state_path = cdh_dir /
|
|
86
|
+
state_path = cdh_dir / CdhProjectLoader.STATE_FILENAME
|
|
86
87
|
if state_path.exists():
|
|
87
88
|
try:
|
|
88
89
|
return json.loads(state_path.read_text(encoding="utf-8"))
|
|
@@ -90,6 +91,15 @@ class CdhProjectLoader:
|
|
|
90
91
|
pass
|
|
91
92
|
return {}
|
|
92
93
|
|
|
94
|
+
@staticmethod
|
|
95
|
+
def save_state(cdh_dir: Path, state_data: dict) -> None:
|
|
96
|
+
"""Save project state to ``.cdh/state.json``."""
|
|
97
|
+
path = cdh_dir / CdhProjectLoader.STATE_FILENAME
|
|
98
|
+
path.write_text(
|
|
99
|
+
json.dumps(state_data, ensure_ascii=False, indent=2),
|
|
100
|
+
encoding="utf-8",
|
|
101
|
+
)
|
|
102
|
+
|
|
93
103
|
@staticmethod
|
|
94
104
|
def get_skill_content(cdh_dir: Path) -> str:
|
|
95
105
|
"""Read ``.cdh/SKILL.md`` if it exists."""
|
|
@@ -123,21 +133,24 @@ class CdhProjectLoader:
|
|
|
123
133
|
pass
|
|
124
134
|
return {}
|
|
125
135
|
|
|
126
|
-
# ──
|
|
136
|
+
# ── todo persistence ───────────────────────────────────────
|
|
127
137
|
|
|
128
138
|
@staticmethod
|
|
129
|
-
def
|
|
130
|
-
"""Save
|
|
131
|
-
path = cdh_dir / CdhProjectLoader.
|
|
139
|
+
def save_todos(cdh_dir: Path, todos_data: dict) -> None:
|
|
140
|
+
"""Save todos to ``.cdh/todos.json``."""
|
|
141
|
+
path = cdh_dir / CdhProjectLoader.TODOS_FILENAME
|
|
132
142
|
path.write_text(
|
|
133
|
-
json.dumps(
|
|
143
|
+
json.dumps(todos_data, ensure_ascii=False, indent=2),
|
|
134
144
|
encoding="utf-8",
|
|
135
145
|
)
|
|
136
146
|
|
|
137
147
|
@staticmethod
|
|
138
|
-
def
|
|
139
|
-
"""Load
|
|
140
|
-
|
|
148
|
+
def load_todos(cdh_dir: Path) -> dict:
|
|
149
|
+
"""Load todos from ``.cdh/todos.json``.
|
|
150
|
+
|
|
151
|
+
Returns an empty dict if the file is missing or unreadable.
|
|
152
|
+
"""
|
|
153
|
+
path = cdh_dir / CdhProjectLoader.TODOS_FILENAME
|
|
141
154
|
if path.exists():
|
|
142
155
|
try:
|
|
143
156
|
return json.loads(path.read_text(encoding="utf-8"))
|
|
@@ -247,8 +260,8 @@ class CdhProjectLoader:
|
|
|
247
260
|
config_path = cdh_dir / "config.yaml"
|
|
248
261
|
config_path.write_text(yaml.dump(config, default_flow_style=False), encoding="utf-8")
|
|
249
262
|
|
|
250
|
-
state = {"current_phase": phase}
|
|
251
|
-
state_path = cdh_dir /
|
|
263
|
+
state = {"current_phase": phase, "completed_phases": [], "gate_results": {}}
|
|
264
|
+
state_path = cdh_dir / CdhProjectLoader.STATE_FILENAME
|
|
252
265
|
state_path.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
|
|
253
266
|
|
|
254
267
|
skill_path = cdh_dir / "SKILL.md"
|