sourcebot 0.1.0__py3-none-any.whl
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.
- sourcebot/__init__.py +9 -0
- sourcebot/__main__.py +17 -0
- sourcebot/bus/__init__.py +4 -0
- sourcebot/bus/channel_adapter.py +21 -0
- sourcebot/bus/event_bus.py +15 -0
- sourcebot/bus/message_models.py +33 -0
- sourcebot/bus/outbound_dispatcher.py +15 -0
- sourcebot/bus/session_manager.py +20 -0
- sourcebot/cli/commands/core/__init__.py +3 -0
- sourcebot/cli/commands/core/command_line.py +26 -0
- sourcebot/cli/commands/init_commands/__init__.py +3 -0
- sourcebot/cli/commands/init_commands/init_global_config.py +30 -0
- sourcebot/cli/commands/init_commands/init_workspace_config.py +18 -0
- sourcebot/cli/commands/run_commands/__init__.py +3 -0
- sourcebot/cli/commands/run_commands/command_line_tool.py +345 -0
- sourcebot/cli/commands/run_commands/safe_runner.py +47 -0
- sourcebot/cli/main.py +28 -0
- sourcebot/config/__init__.py +15 -0
- sourcebot/config/base.py +13 -0
- sourcebot/config/config_manager.py +367 -0
- sourcebot/config/exceptions.py +4 -0
- sourcebot/config/global_config.py +55 -0
- sourcebot/config/provider_config.py +62 -0
- sourcebot/config/workspace_config.py +106 -0
- sourcebot/context/__init__.py +5 -0
- sourcebot/context/context_builder.py +78 -0
- sourcebot/context/identity.py +19 -0
- sourcebot/context/message_builder.py +154 -0
- sourcebot/context/skill/__init__.py +7 -0
- sourcebot/context/skill/skill.py +11 -0
- sourcebot/context/skill/skill_context.py +10 -0
- sourcebot/context/skill/skill_loader.py +57 -0
- sourcebot/context/skill/skill_metadata.py +27 -0
- sourcebot/context/skill/skill_requirements.py +25 -0
- sourcebot/context/skill/skill_summary.py +31 -0
- sourcebot/conversation/__init__.py +2 -0
- sourcebot/conversation/service.py +191 -0
- sourcebot/docker_sandbox/__init__.py +3 -0
- sourcebot/docker_sandbox/docker_sandbox.py +113 -0
- sourcebot/llm/__init__.py +3 -0
- sourcebot/llm/anthropic/__init__.py +2 -0
- sourcebot/llm/anthropic/adapter.py +30 -0
- sourcebot/llm/anthropic/anthropic_llm_client.py +38 -0
- sourcebot/llm/anthropic/converter.py +59 -0
- sourcebot/llm/core/adapter.py +16 -0
- sourcebot/llm/core/client.py +16 -0
- sourcebot/llm/core/delta.py +12 -0
- sourcebot/llm/core/message.py +53 -0
- sourcebot/llm/core/message_converter.py +33 -0
- sourcebot/llm/core/response.py +30 -0
- sourcebot/llm/core/tool.py +7 -0
- sourcebot/llm/core/tool_converter.py +30 -0
- sourcebot/llm/core/tool_delta_aggregator.py +38 -0
- sourcebot/llm/llm_client_factory.py +13 -0
- sourcebot/llm/openai/__init__.py +2 -0
- sourcebot/llm/openai/adapter.py +27 -0
- sourcebot/llm/openai/converter.py +53 -0
- sourcebot/llm/openai/openai_llm_client.py +47 -0
- sourcebot/logging/__init__.py +3 -0
- sourcebot/logging/setup.py +33 -0
- sourcebot/memory/__init__.py +5 -0
- sourcebot/memory/file_store.py +23 -0
- sourcebot/memory/llm_consolidator.py +79 -0
- sourcebot/memory/service.py +116 -0
- sourcebot/memory/window_policy.py +36 -0
- sourcebot/prompt/__init__.py +4 -0
- sourcebot/prompt/deeomposer_prompt.py +420 -0
- sourcebot/prompt/identity_prompt.py +98 -0
- sourcebot/prompt/subagent_prompt.py +25 -0
- sourcebot/runtime/__init__.py +3 -0
- sourcebot/runtime/agent/__init__.py +3 -0
- sourcebot/runtime/agent/agent.py +130 -0
- sourcebot/runtime/agent/agent_factory.py +83 -0
- sourcebot/runtime/dag/planner/__init__.py +3 -0
- sourcebot/runtime/dag/planner/dag_planner.py +26 -0
- sourcebot/runtime/dag/planner/execution_scheduler.py +35 -0
- sourcebot/runtime/dag/planner/parallelism_optimizer.py +44 -0
- sourcebot/runtime/dag/planner/task_decomposer.py +37 -0
- sourcebot/runtime/dag/scheduler/__init__.py +3 -0
- sourcebot/runtime/dag/scheduler/dag_scheduler.py +319 -0
- sourcebot/runtime/dag/scheduler/retry_policy.py +27 -0
- sourcebot/runtime/dag/scheduler/run_store.py +58 -0
- sourcebot/runtime/dag/scheduler/state_store.py +40 -0
- sourcebot/runtime/dag/scheduler/task_graph.py +29 -0
- sourcebot/runtime/init_system.py +182 -0
- sourcebot/runtime/tool_executor.py +30 -0
- sourcebot/security/policy.py +23 -0
- sourcebot/session/__init__.py +4 -0
- sourcebot/session/jsonl_repository.py +142 -0
- sourcebot/session/repository.py +19 -0
- sourcebot/session/service.py +44 -0
- sourcebot/session/session.py +53 -0
- sourcebot/storage/__init__.py +3 -0
- sourcebot/storage/rules_loader.py +72 -0
- sourcebot/storage/skill_storage.py +51 -0
- sourcebot/tools/__init__.py +7 -0
- sourcebot/tools/base.py +182 -0
- sourcebot/tools/registry.py +81 -0
- sourcebot/tools/rule_detail.py +70 -0
- sourcebot/tools/rule_list.py +57 -0
- sourcebot/tools/shell.py +93 -0
- sourcebot/tools/skill_detail.py +61 -0
- sourcebot/tools/skill_list.py +68 -0
- sourcebot/utils/__init__.py +2 -0
- sourcebot/utils/output.py +79 -0
- sourcebot-0.1.0.dist-info/METADATA +318 -0
- sourcebot-0.1.0.dist-info/RECORD +110 -0
- sourcebot-0.1.0.dist-info/WHEEL +5 -0
- sourcebot-0.1.0.dist-info/entry_points.txt +2 -0
- sourcebot-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from sourcebot.memory.file_store import FileMemoryStore
|
|
2
|
+
from sourcebot.memory.service import MemoryService
|
|
3
|
+
from sourcebot.memory.llm_consolidator import LLMConsolidator
|
|
4
|
+
from sourcebot.memory.window_policy import WindowMemoryPolicy
|
|
5
|
+
__all__ = ["FileMemoryStore", "MemoryService", "LLMConsolidator", "WindowMemoryPolicy"]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# sourcebot/memory/file_store.py
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class FileMemoryStore:
|
|
6
|
+
def __init__(self, workspace: Path):
|
|
7
|
+
self.memory_dir = workspace / "memory"
|
|
8
|
+
self.memory_file = self.memory_dir / "MEMORY.md"
|
|
9
|
+
self.history_file = self.memory_dir / "HISTORY.md"
|
|
10
|
+
|
|
11
|
+
self.memory_dir.mkdir(parents=True, exist_ok=True)
|
|
12
|
+
|
|
13
|
+
def read_long_term(self) -> str:
|
|
14
|
+
if self.memory_file.exists():
|
|
15
|
+
return self.memory_file.read_text(encoding="utf-8")
|
|
16
|
+
return ""
|
|
17
|
+
|
|
18
|
+
def write_long_term(self, content: str) -> None:
|
|
19
|
+
self.memory_file.write_text(content, encoding="utf-8")
|
|
20
|
+
|
|
21
|
+
def append_history(self, entry: str) -> None:
|
|
22
|
+
with open(self.history_file, "a", encoding="utf-8") as f:
|
|
23
|
+
f.write(entry.rstrip() + "\n\n")
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# sourcebot/memory/llm_consolidator.py
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
logger = logging.getLogger(__name__)
|
|
5
|
+
from sourcebot.llm.core.message import Message
|
|
6
|
+
class LLMConsolidator:
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
llm
|
|
10
|
+
):
|
|
11
|
+
self.llm = llm
|
|
12
|
+
|
|
13
|
+
async def consolidate(self, current_memory: str, lines: list[str]):
|
|
14
|
+
"""
|
|
15
|
+
Returns:
|
|
16
|
+
(history_entry, updated_memory)
|
|
17
|
+
or None if skipped
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
if not lines:
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
conversation_chunk = "\n".join(lines)
|
|
24
|
+
|
|
25
|
+
prompt = f"""
|
|
26
|
+
You are a memory consolidation engine.
|
|
27
|
+
|
|
28
|
+
Current long-term memory:
|
|
29
|
+
-------------------------
|
|
30
|
+
{current_memory}
|
|
31
|
+
|
|
32
|
+
New conversation chunk:
|
|
33
|
+
-------------------------
|
|
34
|
+
{conversation_chunk}
|
|
35
|
+
|
|
36
|
+
Task:
|
|
37
|
+
1. Extract important facts, preferences, decisions, architecture insights.
|
|
38
|
+
2. Merge them into long-term memory.
|
|
39
|
+
3. Avoid duplication.
|
|
40
|
+
4. Return TWO SECTIONS:
|
|
41
|
+
|
|
42
|
+
=== HISTORY_ENTRY ===
|
|
43
|
+
Short 1-2 paragraph summary of what happened.
|
|
44
|
+
|
|
45
|
+
=== UPDATED_MEMORY ===
|
|
46
|
+
Full updated long-term memory document.
|
|
47
|
+
"""
|
|
48
|
+
response = await self.conversation_summary(prompt)
|
|
49
|
+
|
|
50
|
+
if "=== HISTORY_ENTRY ===" not in response:
|
|
51
|
+
logger.warning("Consolidation format invalid.")
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
history = response.split("=== HISTORY_ENTRY ===")[1] \
|
|
56
|
+
.split("=== UPDATED_MEMORY ===")[0] \
|
|
57
|
+
.strip()
|
|
58
|
+
|
|
59
|
+
updated = response.split("=== UPDATED_MEMORY ===")[1].strip()
|
|
60
|
+
|
|
61
|
+
return history, updated
|
|
62
|
+
|
|
63
|
+
except Exception:
|
|
64
|
+
logger.exception("Failed to parse consolidation result.")
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
async def conversation_summary(
|
|
68
|
+
self,
|
|
69
|
+
prompt: str,
|
|
70
|
+
) -> str:
|
|
71
|
+
messages = [
|
|
72
|
+
Message(role = "system", content = "You are a memory consolidation engine."),
|
|
73
|
+
Message(role = "user", content = prompt),
|
|
74
|
+
]
|
|
75
|
+
response = await self.llm.complete(
|
|
76
|
+
messages,
|
|
77
|
+
tools = None,
|
|
78
|
+
)
|
|
79
|
+
return response.content
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# sourcebot/memory/service.py
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
logger = logging.getLogger(__name__)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MemoryService:
|
|
8
|
+
|
|
9
|
+
def __init__(self, store, policy, consolidator):
|
|
10
|
+
self.store = store
|
|
11
|
+
self.policy = policy
|
|
12
|
+
self.consolidator = consolidator
|
|
13
|
+
|
|
14
|
+
self._consolidating: set[str] = set()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
async def maybe_consolidate(
|
|
18
|
+
self,
|
|
19
|
+
session,
|
|
20
|
+
memory_window: int = 50,
|
|
21
|
+
):
|
|
22
|
+
"""
|
|
23
|
+
Decide whether consolidation should run.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
if len(session.messages) <= memory_window:
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
if session.key in self._consolidating:
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
self._consolidating.add(session.key)
|
|
33
|
+
|
|
34
|
+
async def _task():
|
|
35
|
+
try:
|
|
36
|
+
await self.consolidate(session, memory_window)
|
|
37
|
+
finally:
|
|
38
|
+
self._consolidating.discard(session.key)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
await _task()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# The actual compression logic is executed.
|
|
45
|
+
|
|
46
|
+
async def consolidate(
|
|
47
|
+
self,
|
|
48
|
+
session,
|
|
49
|
+
memory_window = 50,
|
|
50
|
+
archive_all = True,
|
|
51
|
+
):
|
|
52
|
+
|
|
53
|
+
old_messages, new_last = self.policy.select_messages(
|
|
54
|
+
session.messages,
|
|
55
|
+
session.last_consolidated,
|
|
56
|
+
memory_window,
|
|
57
|
+
archive_all,
|
|
58
|
+
)
|
|
59
|
+
if not old_messages:
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
lines = []
|
|
63
|
+
for m in old_messages:
|
|
64
|
+
if not m.content:
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
tools_used = m.metadata.get("tools_used", [])
|
|
68
|
+
|
|
69
|
+
tools = (
|
|
70
|
+
f" [tools: {', '.join(tools_used)}]"
|
|
71
|
+
if tools_used
|
|
72
|
+
else ""
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
ts = m.metadata.get("timestamp", "?")
|
|
76
|
+
|
|
77
|
+
lines.append(
|
|
78
|
+
f"[{ts[:16]}] "
|
|
79
|
+
f"{m.role.upper()}{tools}: {m.content}"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
current_memory = self.store.read_long_term()
|
|
83
|
+
|
|
84
|
+
result = await self.consolidator.consolidate(
|
|
85
|
+
current_memory,
|
|
86
|
+
lines,
|
|
87
|
+
)
|
|
88
|
+
if not result:
|
|
89
|
+
logger.warning("Memory consolidation skipped.")
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
history_entry, memory_update = result
|
|
93
|
+
self.store.append_history(history_entry)
|
|
94
|
+
|
|
95
|
+
if memory_update != current_memory:
|
|
96
|
+
self.store.write_long_term(memory_update)
|
|
97
|
+
session.last_consolidated = new_last
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# /new Dedicated mandatory archiving
|
|
102
|
+
async def consolidate_archived(
|
|
103
|
+
self,
|
|
104
|
+
session_key: str,
|
|
105
|
+
archived_messages: list[dict],
|
|
106
|
+
):
|
|
107
|
+
"""
|
|
108
|
+
Used by /new command to archive everything.
|
|
109
|
+
"""
|
|
110
|
+
from sourcebot.session import Session
|
|
111
|
+
temp = Session(key = session_key)
|
|
112
|
+
temp.messages = archived_messages
|
|
113
|
+
await self.consolidate(
|
|
114
|
+
temp,
|
|
115
|
+
archive_all = True,
|
|
116
|
+
)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# sourcebot/memory/window_policy.py
|
|
2
|
+
from sourcebot.llm.core.message import Message
|
|
3
|
+
class WindowMemoryPolicy:
|
|
4
|
+
"""
|
|
5
|
+
A simple strategy based on window size:
|
|
6
|
+
- Retain the most recent `memory_window` messages
|
|
7
|
+
- Compress the rest
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
def select_messages(
|
|
11
|
+
self,
|
|
12
|
+
messages: list[Message],
|
|
13
|
+
last_consolidated: int,
|
|
14
|
+
memory_window: int,
|
|
15
|
+
archive_all: bool,
|
|
16
|
+
):
|
|
17
|
+
total = len(messages)
|
|
18
|
+
|
|
19
|
+
if total <= last_consolidated:
|
|
20
|
+
return [], last_consolidated
|
|
21
|
+
|
|
22
|
+
if archive_all:
|
|
23
|
+
old_messages = messages[last_consolidated:]
|
|
24
|
+
return old_messages, total
|
|
25
|
+
|
|
26
|
+
keep_from = max(total - memory_window, 0)
|
|
27
|
+
|
|
28
|
+
start = last_consolidated
|
|
29
|
+
end = min(keep_from, total)
|
|
30
|
+
|
|
31
|
+
if start >= end:
|
|
32
|
+
return [], last_consolidated
|
|
33
|
+
|
|
34
|
+
old_messages = messages[start:end]
|
|
35
|
+
|
|
36
|
+
return old_messages, end
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
# sourcebot/prompt/decomposer_prompt.py
|
|
2
|
+
|
|
3
|
+
DECOMPOSER_PROMPT = """You are an advanced software engineering planning agent.
|
|
4
|
+
|
|
5
|
+
Your role is to transform a high-level user request into a structured execution plan
|
|
6
|
+
that can be executed by multiple autonomous agents in parallel.
|
|
7
|
+
|
|
8
|
+
The system executing your plan is a distributed AI engineering runtime similar to:
|
|
9
|
+
|
|
10
|
+
- Devin
|
|
11
|
+
- OpenAI DeepResearch
|
|
12
|
+
- Autonomous IDE agents
|
|
13
|
+
|
|
14
|
+
Your plan must be optimized for reliability, parallel execution, and fault recovery.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
--------------------------------------------------
|
|
18
|
+
PRIMARY OBJECTIVE
|
|
19
|
+
--------------------------------------------------
|
|
20
|
+
|
|
21
|
+
Convert the user request into a Directed Acyclic Graph (DAG) of tasks.
|
|
22
|
+
|
|
23
|
+
Each task must be:
|
|
24
|
+
|
|
25
|
+
- atomic
|
|
26
|
+
- independently executable
|
|
27
|
+
- deterministic
|
|
28
|
+
- testable
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
--------------------------------------------------
|
|
32
|
+
AVAILABLE RULES AND SKILLS
|
|
33
|
+
--------------------------------------------------
|
|
34
|
+
|
|
35
|
+
The following rules and skills are available to guide task execution:
|
|
36
|
+
|
|
37
|
+
{rules}
|
|
38
|
+
|
|
39
|
+
Available skills for agents:
|
|
40
|
+
{skills_summary}
|
|
41
|
+
|
|
42
|
+
--------------------------------------------------
|
|
43
|
+
PLANNING PRINCIPLES
|
|
44
|
+
--------------------------------------------------
|
|
45
|
+
|
|
46
|
+
Follow these principles strictly.
|
|
47
|
+
|
|
48
|
+
1. ATOMIC TASKS
|
|
49
|
+
|
|
50
|
+
Each task should perform exactly ONE concrete action.
|
|
51
|
+
|
|
52
|
+
Good examples:
|
|
53
|
+
|
|
54
|
+
- locate authentication module
|
|
55
|
+
- implement rate limiting middleware
|
|
56
|
+
- write unit tests for login handler
|
|
57
|
+
- run pytest for authentication module
|
|
58
|
+
|
|
59
|
+
Bad examples:
|
|
60
|
+
|
|
61
|
+
- analyze system
|
|
62
|
+
- improve architecture
|
|
63
|
+
- fix bugs
|
|
64
|
+
- refactor code
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
2. PARALLEL EXECUTION
|
|
68
|
+
|
|
69
|
+
Maximize tasks that can run in parallel.
|
|
70
|
+
|
|
71
|
+
Avoid unnecessary dependencies.
|
|
72
|
+
|
|
73
|
+
Only add dependencies when strictly required.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
3. DAG STRUCTURE
|
|
77
|
+
|
|
78
|
+
The output must form a Directed Acyclic Graph.
|
|
79
|
+
|
|
80
|
+
Each task should specify its dependencies explicitly.
|
|
81
|
+
|
|
82
|
+
Use task IDs to define dependencies.
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
4. ENGINEERING ACTIONS
|
|
86
|
+
|
|
87
|
+
Tasks should correspond to real engineering operations such as:
|
|
88
|
+
|
|
89
|
+
- searching code
|
|
90
|
+
- modifying files
|
|
91
|
+
- implementing features
|
|
92
|
+
- writing tests
|
|
93
|
+
- running tests
|
|
94
|
+
- verifying behavior
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
5. REPOSITORY AWARENESS
|
|
98
|
+
|
|
99
|
+
The system has access to:
|
|
100
|
+
|
|
101
|
+
- repository semantic index
|
|
102
|
+
- code search
|
|
103
|
+
- file editor
|
|
104
|
+
- test runner
|
|
105
|
+
- sandbox execution environment
|
|
106
|
+
|
|
107
|
+
Therefore tasks may include:
|
|
108
|
+
|
|
109
|
+
- search repository
|
|
110
|
+
- inspect implementation
|
|
111
|
+
- modify specific files
|
|
112
|
+
- run tests
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
6. FAILURE TOLERANCE
|
|
116
|
+
|
|
117
|
+
Your plan must tolerate failures.
|
|
118
|
+
|
|
119
|
+
When possible:
|
|
120
|
+
|
|
121
|
+
- isolate risky tasks
|
|
122
|
+
- ensure later tasks can retry safely
|
|
123
|
+
- avoid cascading failures
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
7. RETRY STRATEGY
|
|
127
|
+
|
|
128
|
+
Some tasks may fail due to:
|
|
129
|
+
|
|
130
|
+
- syntax errors
|
|
131
|
+
- failing tests
|
|
132
|
+
- runtime issues
|
|
133
|
+
|
|
134
|
+
For tasks that involve execution or testing:
|
|
135
|
+
|
|
136
|
+
- include retry-friendly structure
|
|
137
|
+
- ensure fixes can be applied without rerunning the entire plan
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
--------------------------------------------------
|
|
141
|
+
TASK DESIGN RULES
|
|
142
|
+
--------------------------------------------------
|
|
143
|
+
|
|
144
|
+
Each task must include the following fields:
|
|
145
|
+
|
|
146
|
+
id
|
|
147
|
+
title
|
|
148
|
+
description
|
|
149
|
+
depends_on
|
|
150
|
+
parallelizable
|
|
151
|
+
retryable
|
|
152
|
+
context
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
Field definitions:
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
id
|
|
159
|
+
|
|
160
|
+
Unique task identifier.
|
|
161
|
+
|
|
162
|
+
Example:
|
|
163
|
+
|
|
164
|
+
task_1
|
|
165
|
+
task_2
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
title
|
|
169
|
+
|
|
170
|
+
Short summary of the task.
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
description
|
|
174
|
+
|
|
175
|
+
Detailed description of the action that the execution agent must perform.
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
depends_on
|
|
179
|
+
|
|
180
|
+
List of task IDs that must complete before this task runs.
|
|
181
|
+
|
|
182
|
+
Example:
|
|
183
|
+
|
|
184
|
+
[]
|
|
185
|
+
|
|
186
|
+
or
|
|
187
|
+
|
|
188
|
+
["task_1"]
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
parallelizable
|
|
192
|
+
|
|
193
|
+
Boolean value.
|
|
194
|
+
|
|
195
|
+
true → task can run in parallel with others
|
|
196
|
+
false → task must run sequentially
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
retryable
|
|
200
|
+
|
|
201
|
+
Boolean value.
|
|
202
|
+
|
|
203
|
+
true → task can be safely retried
|
|
204
|
+
false → retry may cause inconsistent state
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
context
|
|
208
|
+
|
|
209
|
+
Object containing task-specific execution context with the following structure:
|
|
210
|
+
|
|
211
|
+
{{
|
|
212
|
+
"rules": [
|
|
213
|
+
"List of specific rules from the global ruleset that apply to this task",
|
|
214
|
+
"Each rule should be directly relevant to the task's execution"
|
|
215
|
+
],
|
|
216
|
+
"skills": [
|
|
217
|
+
"List of specific skills needed to execute this task",
|
|
218
|
+
"Skills should be selected from the available skills_sum"
|
|
219
|
+
],
|
|
220
|
+
"environment": {{
|
|
221
|
+
"required_tools": ["List of tools needed", "e.g., python", "go", "docker"],
|
|
222
|
+
"working_dir": "Suggested working directory if applicable",
|
|
223
|
+
"env_vars": {{
|
|
224
|
+
"KEY": "Environment variables needed"
|
|
225
|
+
}}
|
|
226
|
+
}},
|
|
227
|
+
"inherited_context": {{
|
|
228
|
+
"project_type": "Type of project (e.g., go_module, python_package)",
|
|
229
|
+
"quality_standards": ["List of quality standards to apply"],
|
|
230
|
+
"critical_files": ["Files that are critical to this task"]
|
|
231
|
+
}}
|
|
232
|
+
}}
|
|
233
|
+
|
|
234
|
+
When selecting rules and skills:
|
|
235
|
+
- Choose rules that directly constrain or guide the task execution
|
|
236
|
+
- Select skills that are essential for completing the task
|
|
237
|
+
- Include only the most relevant items, not everything from the global list
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
--------------------------------------------------
|
|
241
|
+
SELF VALIDATION
|
|
242
|
+
--------------------------------------------------
|
|
243
|
+
|
|
244
|
+
Before returning the plan, validate the following:
|
|
245
|
+
|
|
246
|
+
1. The plan must not contain cycles.
|
|
247
|
+
|
|
248
|
+
2. Tasks should be atomic.
|
|
249
|
+
|
|
250
|
+
3. Parallelizable tasks should not depend on each other unnecessarily.
|
|
251
|
+
|
|
252
|
+
4. Tasks that modify the same files should generally not run in parallel.
|
|
253
|
+
|
|
254
|
+
5. Execution tasks should depend on implementation tasks.
|
|
255
|
+
|
|
256
|
+
6. Testing tasks should depend on code changes.
|
|
257
|
+
|
|
258
|
+
7. Each task must have appropriate rules and skills assigned in its context.
|
|
259
|
+
|
|
260
|
+
8. The assigned rules and skills must be relevant to the task description.
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
--------------------------------------------------
|
|
264
|
+
PLAN OPTIMIZATION
|
|
265
|
+
--------------------------------------------------
|
|
266
|
+
|
|
267
|
+
You should optimize the plan for:
|
|
268
|
+
|
|
269
|
+
- minimal execution time
|
|
270
|
+
- maximal parallelism
|
|
271
|
+
- safe retry
|
|
272
|
+
- deterministic behavior
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
--------------------------------------------------
|
|
276
|
+
OUTPUT FORMAT
|
|
277
|
+
--------------------------------------------------
|
|
278
|
+
|
|
279
|
+
Return ONLY valid JSON.
|
|
280
|
+
|
|
281
|
+
Do not include explanations.
|
|
282
|
+
|
|
283
|
+
The JSON must follow this structure:
|
|
284
|
+
|
|
285
|
+
{{
|
|
286
|
+
"tasks": [
|
|
287
|
+
{{
|
|
288
|
+
"id": "task_1",
|
|
289
|
+
"title": "Locate authentication module",
|
|
290
|
+
"description": "Search the repository to identify files responsible for authentication logic",
|
|
291
|
+
"depends_on": [],
|
|
292
|
+
"parallelizable": true,
|
|
293
|
+
"retryable": true,
|
|
294
|
+
"context": {{
|
|
295
|
+
"rules": ["Always use semantic search for code location", "Document found files"],
|
|
296
|
+
"skills": ["code_search", "file_system"],
|
|
297
|
+
"environment": {{
|
|
298
|
+
"required_tools": ["git"],
|
|
299
|
+
"working_dir": "/repo"
|
|
300
|
+
}},
|
|
301
|
+
"inherited_context": {{
|
|
302
|
+
"project_type": "web_application",
|
|
303
|
+
"critical_files": ["auth.py", "routes.py"]
|
|
304
|
+
}}
|
|
305
|
+
}}
|
|
306
|
+
}},
|
|
307
|
+
{{
|
|
308
|
+
"id": "task_2",
|
|
309
|
+
"title": "Inspect login endpoint",
|
|
310
|
+
"description": "Locate the login endpoint implementation and analyze how authentication is handled",
|
|
311
|
+
"depends_on": ["task_1"],
|
|
312
|
+
"parallelizable": false,
|
|
313
|
+
"retryable": true,
|
|
314
|
+
"context": {{
|
|
315
|
+
"rules": ["Analyze code for security vulnerabilities", "Document authentication flow"],
|
|
316
|
+
"skills": ["code_analysis", "security_review"],
|
|
317
|
+
"environment": {{
|
|
318
|
+
"required_tools": ["python"],
|
|
319
|
+
"working_dir": "/repo"
|
|
320
|
+
}},
|
|
321
|
+
"inherited_context": {{
|
|
322
|
+
"project_type": "web_application",
|
|
323
|
+
"quality_standards": ["security_review_required"]
|
|
324
|
+
}}
|
|
325
|
+
}}
|
|
326
|
+
}}
|
|
327
|
+
]
|
|
328
|
+
}}
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
--------------------------------------------------
|
|
332
|
+
EXAMPLE PLAN
|
|
333
|
+
--------------------------------------------------
|
|
334
|
+
|
|
335
|
+
User request:
|
|
336
|
+
|
|
337
|
+
"Add rate limiting to the login endpoint"
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
Available rules:
|
|
341
|
+
- "Always add tests for new functionality"
|
|
342
|
+
- "Use built-in framework middleware when available"
|
|
343
|
+
- "Document all API changes"
|
|
344
|
+
|
|
345
|
+
Available skills:
|
|
346
|
+
- code_search: Search and locate code files
|
|
347
|
+
- file_editor: Create and modify files
|
|
348
|
+
- test_runner: Execute test suites
|
|
349
|
+
- middleware_implementer: Add middleware to web frameworks
|
|
350
|
+
|
|
351
|
+
Example output:
|
|
352
|
+
|
|
353
|
+
{{
|
|
354
|
+
"tasks": [
|
|
355
|
+
{{
|
|
356
|
+
"id": "task_1",
|
|
357
|
+
"title": "Locate authentication module",
|
|
358
|
+
"description": "Search the repository to identify files responsible for authentication logic",
|
|
359
|
+
"depends_on": [],
|
|
360
|
+
"parallelizable": true,
|
|
361
|
+
"retryable": true,
|
|
362
|
+
"context": {{
|
|
363
|
+
"rules": ["Use built-in framework middleware when available"],
|
|
364
|
+
"skills": ["code_search"],
|
|
365
|
+
"environment": {{
|
|
366
|
+
"required_tools": ["git"],
|
|
367
|
+
"working_dir": "/repo"
|
|
368
|
+
}},
|
|
369
|
+
"inherited_context": {{
|
|
370
|
+
"project_type": "web_application",
|
|
371
|
+
"critical_files": ["auth.py", "routes.py"]
|
|
372
|
+
}}
|
|
373
|
+
}}
|
|
374
|
+
}},
|
|
375
|
+
{{
|
|
376
|
+
"id": "task_2",
|
|
377
|
+
"title": "Implement rate limiting middleware",
|
|
378
|
+
"description": "Add middleware to limit repeated login attempts using the framework's built-in rate limiting",
|
|
379
|
+
"depends_on": ["task_1"],
|
|
380
|
+
"parallelizable": false,
|
|
381
|
+
"retryable": true,
|
|
382
|
+
"context": {{
|
|
383
|
+
"rules": ["Always add tests for new functionality", "Document all API changes"],
|
|
384
|
+
"skills": ["file_editor", "middleware_implementer"],
|
|
385
|
+
"environment": {{
|
|
386
|
+
"required_tools": ["python", "flask"],
|
|
387
|
+
"working_dir": "/repo",
|
|
388
|
+
"env_vars": {{
|
|
389
|
+
"RATE_LIMIT": "5/minute"
|
|
390
|
+
}}
|
|
391
|
+
}},
|
|
392
|
+
"inherited_context": {{
|
|
393
|
+
"project_type": "flask_application",
|
|
394
|
+
"quality_standards": ["test_coverage_required"]
|
|
395
|
+
}}
|
|
396
|
+
}}
|
|
397
|
+
}},
|
|
398
|
+
{{
|
|
399
|
+
"id": "task_3",
|
|
400
|
+
"title": "Write tests for rate limiting",
|
|
401
|
+
"description": "Create unit tests verifying login rate limiting behavior with multiple failed attempts",
|
|
402
|
+
"depends_on": ["task_2"],
|
|
403
|
+
"parallelizable": true,
|
|
404
|
+
"retryable": true,
|
|
405
|
+
"context": {{
|
|
406
|
+
"rules": ["Always add tests for new functionality"],
|
|
407
|
+
"skills": ["test_runner"],
|
|
408
|
+
"environment": {{
|
|
409
|
+
"required_tools": ["python", "pytest"],
|
|
410
|
+
"working_dir": "/repo/tests"
|
|
411
|
+
}},
|
|
412
|
+
"inherited_context": {{
|
|
413
|
+
"project_type": "flask_application",
|
|
414
|
+
"critical_files": ["test_auth.py"]
|
|
415
|
+
}}
|
|
416
|
+
}}
|
|
417
|
+
}}
|
|
418
|
+
]
|
|
419
|
+
}}
|
|
420
|
+
"""
|