monoco-toolkit 0.3.10__py3-none-any.whl → 0.3.11__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.
- monoco/__main__.py +8 -0
- monoco/core/artifacts/__init__.py +16 -0
- monoco/core/artifacts/manager.py +575 -0
- monoco/core/artifacts/models.py +161 -0
- monoco/core/config.py +31 -4
- monoco/core/git.py +23 -0
- monoco/core/ingestion/__init__.py +20 -0
- monoco/core/ingestion/discovery.py +248 -0
- monoco/core/ingestion/watcher.py +343 -0
- monoco/core/ingestion/worker.py +436 -0
- monoco/core/loader.py +633 -0
- monoco/core/registry.py +34 -25
- monoco/core/skills.py +119 -80
- monoco/daemon/app.py +77 -1
- monoco/daemon/commands.py +10 -0
- monoco/daemon/mailroom_service.py +196 -0
- monoco/daemon/models.py +1 -0
- monoco/daemon/scheduler.py +236 -0
- monoco/daemon/services.py +185 -0
- monoco/daemon/triggers.py +55 -0
- monoco/features/agent/adapter.py +17 -7
- monoco/features/agent/apoptosis.py +4 -4
- monoco/features/agent/manager.py +41 -5
- monoco/{core/resources/en/skills/monoco_core → features/agent/resources/en/skills/monoco_atom_core}/SKILL.md +2 -2
- monoco/features/agent/resources/en/skills/{flow_engineer → monoco_workflow_agent_engineer}/SKILL.md +2 -2
- monoco/features/agent/resources/en/skills/{flow_manager → monoco_workflow_agent_manager}/SKILL.md +2 -2
- monoco/features/agent/resources/en/skills/{flow_planner → monoco_workflow_agent_planner}/SKILL.md +2 -2
- monoco/features/agent/resources/en/skills/{flow_reviewer → monoco_workflow_agent_reviewer}/SKILL.md +2 -2
- monoco/features/agent/resources/{roles/role-engineer.yaml → zh/roles/monoco_role_engineer.yaml} +3 -3
- monoco/features/agent/resources/{roles/role-manager.yaml → zh/roles/monoco_role_manager.yaml} +8 -8
- monoco/features/agent/resources/{roles/role-planner.yaml → zh/roles/monoco_role_planner.yaml} +8 -8
- monoco/features/agent/resources/{roles/role-reviewer.yaml → zh/roles/monoco_role_reviewer.yaml} +8 -8
- monoco/{core/resources/zh/skills/monoco_core → features/agent/resources/zh/skills/monoco_atom_core}/SKILL.md +2 -2
- monoco/features/agent/resources/zh/skills/{flow_engineer → monoco_workflow_agent_engineer}/SKILL.md +2 -2
- monoco/features/agent/resources/zh/skills/{flow_manager → monoco_workflow_agent_manager}/SKILL.md +2 -2
- monoco/features/agent/resources/zh/skills/{flow_planner → monoco_workflow_agent_planner}/SKILL.md +2 -2
- monoco/features/agent/resources/zh/skills/{flow_reviewer → monoco_workflow_agent_reviewer}/SKILL.md +2 -2
- monoco/features/agent/session.py +59 -11
- monoco/features/artifact/__init__.py +0 -0
- monoco/features/artifact/adapter.py +33 -0
- monoco/features/artifact/resources/zh/AGENTS.md +14 -0
- monoco/features/artifact/resources/zh/skills/monoco_atom_artifact/SKILL.md +278 -0
- monoco/features/glossary/adapter.py +18 -7
- monoco/features/glossary/resources/en/skills/{monoco_glossary → monoco_atom_glossary}/SKILL.md +2 -2
- monoco/features/glossary/resources/zh/skills/{monoco_glossary → monoco_atom_glossary}/SKILL.md +2 -2
- monoco/features/hooks/__init__.py +11 -0
- monoco/features/hooks/adapter.py +67 -0
- monoco/features/hooks/commands.py +309 -0
- monoco/features/hooks/core.py +441 -0
- monoco/features/hooks/resources/ADDING_HOOKS.md +234 -0
- monoco/features/i18n/adapter.py +18 -5
- monoco/features/i18n/core.py +482 -17
- monoco/features/i18n/resources/en/skills/{monoco_i18n → monoco_atom_i18n}/SKILL.md +2 -2
- monoco/features/i18n/resources/en/skills/{i18n_scan_workflow → monoco_workflow_i18n_scan}/SKILL.md +2 -2
- monoco/features/i18n/resources/zh/skills/{monoco_i18n → monoco_atom_i18n}/SKILL.md +2 -2
- monoco/features/i18n/resources/zh/skills/{i18n_scan_workflow → monoco_workflow_i18n_scan}/SKILL.md +2 -2
- monoco/features/issue/adapter.py +19 -6
- monoco/features/issue/commands.py +281 -7
- monoco/features/issue/core.py +227 -13
- monoco/features/issue/engine/machine.py +114 -4
- monoco/features/issue/linter.py +60 -5
- monoco/features/issue/models.py +2 -2
- monoco/features/issue/resources/en/AGENTS.md +109 -0
- monoco/features/issue/resources/en/skills/{monoco_issue → monoco_atom_issue}/SKILL.md +2 -2
- monoco/features/issue/resources/en/skills/{issue_create_workflow → monoco_workflow_issue_creation}/SKILL.md +2 -2
- monoco/features/issue/resources/en/skills/{issue_develop_workflow → monoco_workflow_issue_development}/SKILL.md +2 -2
- monoco/features/issue/resources/en/skills/{issue_lifecycle_workflow → monoco_workflow_issue_management}/SKILL.md +2 -2
- monoco/features/issue/resources/en/skills/{issue_refine_workflow → monoco_workflow_issue_refinement}/SKILL.md +2 -2
- monoco/features/issue/resources/hooks/post-checkout.sh +39 -0
- monoco/features/issue/resources/hooks/pre-commit.sh +41 -0
- monoco/features/issue/resources/hooks/pre-push.sh +35 -0
- monoco/features/issue/resources/zh/AGENTS.md +109 -0
- monoco/features/issue/resources/zh/skills/{monoco_issue → monoco_atom_issue_lifecycle}/SKILL.md +2 -2
- monoco/features/issue/resources/zh/skills/{issue_create_workflow → monoco_workflow_issue_creation}/SKILL.md +2 -2
- monoco/features/issue/resources/zh/skills/{issue_develop_workflow → monoco_workflow_issue_development}/SKILL.md +2 -2
- monoco/features/issue/resources/zh/skills/{issue_lifecycle_workflow → monoco_workflow_issue_management}/SKILL.md +2 -2
- monoco/features/issue/resources/zh/skills/{issue_refine_workflow → monoco_workflow_issue_refinement}/SKILL.md +2 -2
- monoco/features/issue/validator.py +101 -1
- monoco/features/memo/adapter.py +21 -8
- monoco/features/memo/cli.py +103 -10
- monoco/features/memo/core.py +178 -92
- monoco/features/memo/models.py +53 -0
- monoco/features/memo/resources/en/skills/{monoco_memo → monoco_atom_memo}/SKILL.md +2 -2
- monoco/features/memo/resources/en/skills/{note_processing_workflow → monoco_workflow_note_processing}/SKILL.md +2 -2
- monoco/features/memo/resources/zh/skills/{monoco_memo → monoco_atom_memo}/SKILL.md +2 -2
- monoco/features/memo/resources/zh/skills/{note_processing_workflow → monoco_workflow_note_processing}/SKILL.md +2 -2
- monoco/features/spike/adapter.py +18 -5
- monoco/features/spike/resources/en/skills/{monoco_spike → monoco_atom_spike}/SKILL.md +2 -2
- monoco/features/spike/resources/en/skills/{research_workflow → monoco_workflow_research}/SKILL.md +2 -2
- monoco/features/spike/resources/zh/skills/{monoco_spike → monoco_atom_spike}/SKILL.md +2 -2
- monoco/features/spike/resources/zh/skills/{research_workflow → monoco_workflow_research}/SKILL.md +2 -2
- monoco/main.py +38 -1
- {monoco_toolkit-0.3.10.dist-info → monoco_toolkit-0.3.11.dist-info}/METADATA +7 -1
- monoco_toolkit-0.3.11.dist-info/RECORD +181 -0
- monoco_toolkit-0.3.10.dist-info/RECORD +0 -156
- /monoco/{core → features/agent}/resources/en/AGENTS.md +0 -0
- /monoco/{core → features/agent}/resources/zh/AGENTS.md +0 -0
- {monoco_toolkit-0.3.10.dist-info → monoco_toolkit-0.3.11.dist-info}/WHEEL +0 -0
- {monoco_toolkit-0.3.10.dist-info → monoco_toolkit-0.3.11.dist-info}/entry_points.txt +0 -0
- {monoco_toolkit-0.3.10.dist-info → monoco_toolkit-0.3.11.dist-info}/licenses/LICENSE +0 -0
monoco/features/agent/adapter.py
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from typing import Dict
|
|
3
|
-
from monoco.core.
|
|
3
|
+
from monoco.core.loader import FeatureModule, FeatureMetadata
|
|
4
|
+
from monoco.core.feature import IntegrationData
|
|
4
5
|
|
|
5
6
|
|
|
6
|
-
class AgentFeature(
|
|
7
|
-
|
|
8
|
-
def name(self) -> str:
|
|
9
|
-
return "agent"
|
|
7
|
+
class AgentFeature(FeatureModule):
|
|
8
|
+
"""Agent management feature module with unified lifecycle support."""
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
@property
|
|
11
|
+
def metadata(self) -> FeatureMetadata:
|
|
12
|
+
return FeatureMetadata(
|
|
13
|
+
name="agent",
|
|
14
|
+
version="1.0.0",
|
|
15
|
+
description="Agent session and role management",
|
|
16
|
+
dependencies=["core"],
|
|
17
|
+
priority=20,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def _on_mount(self, context: "FeatureContext") -> None: # type: ignore
|
|
21
|
+
"""Agent feature doesn't require special initialization."""
|
|
13
22
|
pass
|
|
14
23
|
|
|
15
24
|
def integrate(self, root: Path, config: Dict) -> IntegrationData:
|
|
25
|
+
"""Provide integration data for agent environment."""
|
|
16
26
|
# Determine language from config, default to 'en'
|
|
17
27
|
lang = config.get("i18n", {}).get("source_lang", "en")
|
|
18
28
|
|
|
@@ -10,7 +10,7 @@ class ApoptosisManager:
|
|
|
10
10
|
def __init__(self, session_manager: SessionManager):
|
|
11
11
|
self.session_manager = session_manager
|
|
12
12
|
|
|
13
|
-
def trigger_apoptosis(self, session_id: str) -> None:
|
|
13
|
+
def trigger_apoptosis(self, session_id: str, failure_reason: str = "Unknown") -> None:
|
|
14
14
|
"""
|
|
15
15
|
Trigger the apoptosis process for a given session.
|
|
16
16
|
1. Mark session as crashed.
|
|
@@ -24,14 +24,14 @@ class ApoptosisManager:
|
|
|
24
24
|
session.model.status = "crashed"
|
|
25
25
|
|
|
26
26
|
# 2. Start Coroner
|
|
27
|
-
self._perform_autopsy(session)
|
|
27
|
+
self._perform_autopsy(session, failure_reason)
|
|
28
28
|
|
|
29
|
-
def _perform_autopsy(self, victim_session):
|
|
29
|
+
def _perform_autopsy(self, victim_session, failure_reason: str):
|
|
30
30
|
coroner_role = RoleTemplate(
|
|
31
31
|
name="Coroner",
|
|
32
32
|
description="Investigates cause of death for failed agents.",
|
|
33
33
|
trigger="system.crash",
|
|
34
|
-
goal="Determine why the previous agent failed.",
|
|
34
|
+
goal=f"Determine why the previous agent failed. Reason: {failure_reason}",
|
|
35
35
|
system_prompt="You are the Coroner. Analyze the logs.",
|
|
36
36
|
engine="gemini"
|
|
37
37
|
)
|
monoco/features/agent/manager.py
CHANGED
|
@@ -25,22 +25,56 @@ class SessionManager:
|
|
|
25
25
|
self._sessions: Dict[str, RuntimeSession] = {}
|
|
26
26
|
self.project_root = project_root or find_monoco_root()
|
|
27
27
|
self.config = config
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
self.sessions_dir = self.project_root / ".monoco" / "sessions"
|
|
30
|
+
self.sessions_dir.mkdir(parents=True, exist_ok=True)
|
|
31
|
+
|
|
29
32
|
# Initialize hook registry
|
|
30
33
|
self.hook_registry = hook_registry or get_registry()
|
|
31
|
-
|
|
34
|
+
|
|
32
35
|
# Load hooks from config if available
|
|
33
36
|
self._load_hooks_from_config()
|
|
34
37
|
|
|
38
|
+
# Load persisted sessions
|
|
39
|
+
self._load_sessions()
|
|
40
|
+
|
|
41
|
+
def _load_sessions(self):
|
|
42
|
+
"""Load sessions from disk."""
|
|
43
|
+
import json
|
|
44
|
+
|
|
45
|
+
for session_file in self.sessions_dir.glob("*.json"):
|
|
46
|
+
try:
|
|
47
|
+
data = json.loads(session_file.read_text())
|
|
48
|
+
session_model = Session(**data)
|
|
49
|
+
# Rehydrate as Observer
|
|
50
|
+
runtime = RuntimeSession(
|
|
51
|
+
session_model,
|
|
52
|
+
worker=None, # No worker for loaded sessions initially (Observer mode)
|
|
53
|
+
hook_registry=self.hook_registry,
|
|
54
|
+
project_root=self.project_root,
|
|
55
|
+
save_callback=self._save_session,
|
|
56
|
+
)
|
|
57
|
+
self._sessions[session_model.id] = runtime
|
|
58
|
+
# Check status immediately to see if it's still running
|
|
59
|
+
runtime.refresh_status()
|
|
60
|
+
except Exception as e:
|
|
61
|
+
print(f"Failed to load session {session_file}: {e}")
|
|
62
|
+
|
|
63
|
+
def _save_session(self, session: Session):
|
|
64
|
+
"""Save session to disk."""
|
|
65
|
+
file_path = self.sessions_dir / f"{session.id}.json"
|
|
66
|
+
file_path.write_text(session.model_dump_json(indent=2))
|
|
67
|
+
|
|
35
68
|
def _load_hooks_from_config(self) -> None:
|
|
36
69
|
"""Load and register hooks from configuration."""
|
|
37
70
|
if self.config is None:
|
|
38
71
|
try:
|
|
39
72
|
from monoco.core.config import get_config
|
|
73
|
+
|
|
40
74
|
self.config = get_config(str(self.project_root))
|
|
41
75
|
except Exception:
|
|
42
76
|
return
|
|
43
|
-
|
|
77
|
+
|
|
44
78
|
# Load hooks from config
|
|
45
79
|
if self.config and hasattr(self.config, "session_hooks"):
|
|
46
80
|
hooks_config = self.config.session_hooks
|
|
@@ -67,12 +101,14 @@ class SessionManager:
|
|
|
67
101
|
|
|
68
102
|
worker = Worker(role, issue_id, timeout=timeout)
|
|
69
103
|
runtime = RuntimeSession(
|
|
70
|
-
session_model,
|
|
104
|
+
session_model,
|
|
71
105
|
worker,
|
|
72
106
|
hook_registry=self.hook_registry,
|
|
73
107
|
project_root=self.project_root,
|
|
108
|
+
save_callback=self._save_session,
|
|
74
109
|
)
|
|
75
110
|
self._sessions[session_id] = runtime
|
|
111
|
+
self._save_session(session_model)
|
|
76
112
|
return runtime
|
|
77
113
|
|
|
78
114
|
def get_session(self, session_id: str) -> Optional[RuntimeSession]:
|
|
@@ -87,5 +123,5 @@ class SessionManager:
|
|
|
87
123
|
session = self.get_session(session_id)
|
|
88
124
|
if session:
|
|
89
125
|
session.terminate()
|
|
90
|
-
# We
|
|
126
|
+
# We keep the record for history
|
|
91
127
|
# del self._sessions[session_id]
|
monoco/features/agent/resources/en/skills/{flow_engineer → monoco_workflow_agent_engineer}/SKILL.md
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: monoco_workflow_agent_engineer
|
|
3
3
|
description: Standardized workflow for the Engineer role (Flow Skill). Defines the standard operating procedure from requirement investigation to code submission, ensuring test coverage and code quality.
|
|
4
|
-
type:
|
|
4
|
+
type: workflow
|
|
5
5
|
role: engineer
|
|
6
6
|
version: 1.0.0
|
|
7
7
|
---
|
monoco/features/agent/resources/en/skills/{flow_manager → monoco_workflow_agent_manager}/SKILL.md
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: monoco_workflow_agent_manager
|
|
3
3
|
description: Standardized workflow for the Manager role (Flow Skill). Defines the standard operating procedure from inbox organization to task assignment, ensuring clear requirements and reasonable task breakdown.
|
|
4
|
-
type:
|
|
4
|
+
type: workflow
|
|
5
5
|
role: manager
|
|
6
6
|
version: 1.0.0
|
|
7
7
|
---
|
monoco/features/agent/resources/en/skills/{flow_reviewer → monoco_workflow_agent_reviewer}/SKILL.md
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: monoco_workflow_agent_reviewer
|
|
3
3
|
description: Standardized workflow for the Reviewer role (Flow Skill). Defines the standard operating procedure from code checkout to adversarial testing to review completion, ensuring code quality and process compliance.
|
|
4
|
-
type:
|
|
4
|
+
type: workflow
|
|
5
5
|
role: reviewer
|
|
6
6
|
version: 1.0.0
|
|
7
7
|
---
|
monoco/features/agent/resources/{roles/role-engineer.yaml → zh/roles/monoco_role_engineer.yaml}
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: monoco_role_engineer
|
|
3
3
|
type: role
|
|
4
|
-
description: Engineer 角色 -
|
|
4
|
+
description: Engineer 角色 - 负责代码生成、测试和维护
|
|
5
5
|
version: 1.0.0
|
|
6
6
|
author: Monoco Toolkit
|
|
7
7
|
|
|
8
8
|
# 默认工作流
|
|
9
|
-
workflow:
|
|
9
|
+
workflow: monoco_workflow_agent_engineer
|
|
10
10
|
|
|
11
11
|
# 默认执行模式
|
|
12
12
|
default_mode: autopilot
|
monoco/features/agent/resources/{roles/role-manager.yaml → zh/roles/monoco_role_manager.yaml}
RENAMED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: monoco_role_manager
|
|
3
3
|
type: role
|
|
4
|
-
description: Manager 角色 -
|
|
4
|
+
description: Manager 角色 - 负责 Issue 管理、进度跟踪和决策
|
|
5
5
|
version: 1.0.0
|
|
6
6
|
author: Monoco Toolkit
|
|
7
7
|
|
|
8
8
|
# 默认工作流
|
|
9
|
-
workflow:
|
|
9
|
+
workflow: monoco_workflow_issue_creation
|
|
10
10
|
|
|
11
11
|
# 默认执行模式
|
|
12
12
|
default_mode: copilot
|
|
13
13
|
|
|
14
14
|
# 触发条件
|
|
15
|
-
trigger:
|
|
15
|
+
trigger: 'incoming.requirement'
|
|
16
16
|
goal: 将模糊需求转化为清晰、可执行的任务
|
|
17
17
|
|
|
18
18
|
# 角色偏好 / Mindset
|
|
19
19
|
preferences:
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
20
|
+
- '5W2H: 使用 5W2H 分析法澄清需求'
|
|
21
|
+
- 'Vertical Slicing: 垂直切片分解任务'
|
|
22
|
+
- 'Clear Acceptance Criteria: 每个任务必须有清晰的验收标准'
|
|
23
|
+
- 'No Unclear Assignment: 禁止指派没有澄清的需求给 Engineer'
|
|
24
24
|
|
|
25
25
|
# 系统提示
|
|
26
26
|
system_prompt: |
|
monoco/features/agent/resources/{roles/role-planner.yaml → zh/roles/monoco_role_planner.yaml}
RENAMED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: monoco_role_planner
|
|
3
3
|
type: role
|
|
4
4
|
description: Planner 角色 - 负责架构设计、技术规划和交接
|
|
5
5
|
version: 1.0.0
|
|
6
6
|
author: Monoco Toolkit
|
|
7
7
|
|
|
8
8
|
# 默认工作流
|
|
9
|
-
workflow:
|
|
9
|
+
workflow: monoco_workflow_agent_planner
|
|
10
10
|
|
|
11
11
|
# 默认执行模式
|
|
12
12
|
default_mode: copilot
|
|
13
13
|
|
|
14
14
|
# 触发条件
|
|
15
|
-
trigger:
|
|
15
|
+
trigger: 'issue.needs_refine'
|
|
16
16
|
goal: 产出清晰的架构设计和可执行的计划
|
|
17
17
|
|
|
18
18
|
# 角色偏好 / Mindset
|
|
19
19
|
preferences:
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
20
|
+
- 'Evidence Based: 所有架构决策必须有代码或文档证据支持'
|
|
21
|
+
- 'Incremental Design: 优先采用增量式设计,避免过度设计'
|
|
22
|
+
- 'Clear Boundaries: 明确模块边界和接口契约'
|
|
23
|
+
- 'Document First: 先写设计文档,再创建实现任务'
|
|
24
|
+
- 'Review Loop: 复杂设计应经过 Review 后再交接'
|
|
25
25
|
|
|
26
26
|
# 系统提示
|
|
27
27
|
system_prompt: |
|
monoco/features/agent/resources/{roles/role-reviewer.yaml → zh/roles/monoco_role_reviewer.yaml}
RENAMED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: monoco_role_reviewer
|
|
3
3
|
type: role
|
|
4
|
-
description: Reviewer 角色 -
|
|
4
|
+
description: Reviewer 角色 - 负责代码审计、架构合规检查和反馈
|
|
5
5
|
version: 1.0.0
|
|
6
6
|
author: Monoco Toolkit
|
|
7
7
|
|
|
8
8
|
# 默认工作流
|
|
9
|
-
workflow:
|
|
9
|
+
workflow: monoco_workflow_agent_reviewer
|
|
10
10
|
|
|
11
11
|
# 默认执行模式
|
|
12
12
|
default_mode: autopilot
|
|
13
13
|
|
|
14
14
|
# 触发条件
|
|
15
|
-
trigger:
|
|
15
|
+
trigger: 'issue.submitted'
|
|
16
16
|
goal: 确保代码质量和流程合规
|
|
17
17
|
|
|
18
18
|
# 角色偏好 / Mindset
|
|
19
19
|
preferences:
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
20
|
+
- 'Double Defense: 双层防御体系 - Engineer 自证 (Verify) + Reviewer 对抗 (Challenge)'
|
|
21
|
+
- 'Try to Break It: 尝试破坏代码,寻找边界情况'
|
|
22
|
+
- 'No Approve Without Test: 禁止未经测试直接 Approve'
|
|
23
|
+
- 'Challenge Tests: 保留有价值的 Challenge Tests 并提交到代码库'
|
|
24
24
|
|
|
25
25
|
# 系统提示
|
|
26
26
|
system_prompt: |
|
monoco/features/agent/session.py
CHANGED
|
@@ -25,6 +25,7 @@ class Session(BaseModel):
|
|
|
25
25
|
branch_name: str = Field(
|
|
26
26
|
..., description="Git branch name associated with this session"
|
|
27
27
|
)
|
|
28
|
+
pid: Optional[int] = Field(default=None, description="Process ID of the worker")
|
|
28
29
|
created_at: datetime = Field(default_factory=datetime.now)
|
|
29
30
|
updated_at: datetime = Field(default_factory=datetime.now)
|
|
30
31
|
# History could be a list of logs or pointers to git commits
|
|
@@ -37,22 +38,33 @@ class RuntimeSession:
|
|
|
37
38
|
"""
|
|
38
39
|
|
|
39
40
|
def __init__(
|
|
40
|
-
self,
|
|
41
|
-
session_model: Session,
|
|
42
|
-
worker: Worker,
|
|
41
|
+
self,
|
|
42
|
+
session_model: Session,
|
|
43
|
+
worker: Optional[Worker],
|
|
43
44
|
hook_registry: Optional[HookRegistry] = None,
|
|
44
45
|
project_root: Optional[Path] = None,
|
|
46
|
+
save_callback: Optional[callable] = None,
|
|
45
47
|
):
|
|
46
48
|
self.model = session_model
|
|
47
49
|
self.worker = worker
|
|
48
50
|
self.hook_registry = hook_registry or get_registry()
|
|
49
51
|
self.project_root = project_root or find_monoco_root()
|
|
52
|
+
self.save_callback = save_callback
|
|
53
|
+
|
|
54
|
+
def _save(self):
|
|
55
|
+
if self.save_callback:
|
|
56
|
+
self.save_callback(self.model)
|
|
50
57
|
|
|
51
58
|
def _create_hook_context(self) -> HookContext:
|
|
52
59
|
"""Create a HookContext from the current session state."""
|
|
53
60
|
return HookContext.from_runtime_session(self, self.project_root)
|
|
54
61
|
|
|
55
62
|
def start(self, context: Optional[dict] = None):
|
|
63
|
+
if not self.worker:
|
|
64
|
+
raise RuntimeError(
|
|
65
|
+
"Cannot start session in observer mode (no worker attached)"
|
|
66
|
+
)
|
|
67
|
+
|
|
56
68
|
print(
|
|
57
69
|
f"Session {self.model.id}: Starting worker on branch {self.model.branch_name}"
|
|
58
70
|
)
|
|
@@ -64,50 +76,83 @@ class RuntimeSession:
|
|
|
64
76
|
# Execute on_session_start hooks
|
|
65
77
|
hook_context = self._create_hook_context()
|
|
66
78
|
self.hook_registry.execute_on_session_start(hook_context)
|
|
67
|
-
|
|
79
|
+
|
|
68
80
|
self.worker.start(context)
|
|
69
81
|
# Async mode: we assume it started running.
|
|
70
82
|
# Use poll or refresh_status to check later.
|
|
71
83
|
self.model.status = "running"
|
|
84
|
+
self.model.pid = self.worker.process_id
|
|
72
85
|
except Exception:
|
|
73
86
|
self.model.status = "failed"
|
|
74
87
|
raise
|
|
75
88
|
finally:
|
|
76
89
|
self.model.updated_at = datetime.now()
|
|
90
|
+
self._save()
|
|
77
91
|
|
|
78
92
|
def refresh_status(self) -> str:
|
|
79
93
|
"""
|
|
80
94
|
Polls the worker and updates the session model status.
|
|
81
95
|
"""
|
|
82
|
-
|
|
83
|
-
|
|
96
|
+
if self.worker:
|
|
97
|
+
worker_status = self.worker.poll()
|
|
98
|
+
self.model.status = worker_status
|
|
99
|
+
else:
|
|
100
|
+
# Observer mode
|
|
101
|
+
if self.model.pid:
|
|
102
|
+
try:
|
|
103
|
+
import os
|
|
104
|
+
|
|
105
|
+
# Check if process exists.
|
|
106
|
+
# kill(pid, 0) does not send a signal but raises OSError if pid missing
|
|
107
|
+
os.kill(self.model.pid, 0)
|
|
108
|
+
# If we are here, process exists. We assume running if it was running.
|
|
109
|
+
# We can't detect "suspended" easily without psutil.
|
|
110
|
+
if self.model.status == "terminated":
|
|
111
|
+
# If we thought it was terminated but it's alive, maybe update?
|
|
112
|
+
# Or keep as terminated? Let's assume running if found.
|
|
113
|
+
pass
|
|
114
|
+
except OSError:
|
|
115
|
+
self.model.status = "terminated"
|
|
116
|
+
else:
|
|
117
|
+
self.model.status = "terminated"
|
|
118
|
+
|
|
84
119
|
self.model.updated_at = datetime.now()
|
|
85
|
-
|
|
120
|
+
self._save()
|
|
121
|
+
return self.model.status
|
|
86
122
|
|
|
87
123
|
def suspend(self):
|
|
124
|
+
if not self.worker:
|
|
125
|
+
raise RuntimeError("Cannot suspend session in observer mode")
|
|
126
|
+
|
|
88
127
|
print(f"Session {self.model.id}: Suspending worker")
|
|
89
128
|
self.worker.stop()
|
|
90
129
|
self.model.status = "suspended"
|
|
91
130
|
self.model.updated_at = datetime.now()
|
|
131
|
+
self._save()
|
|
92
132
|
# In real impl, ensure git commit of current state?
|
|
93
133
|
|
|
94
134
|
def resume(self):
|
|
135
|
+
if not self.worker:
|
|
136
|
+
raise RuntimeError("Cannot resume session in observer mode")
|
|
137
|
+
|
|
95
138
|
print(f"Session {self.model.id}: Resuming worker")
|
|
96
139
|
self.worker.start() # In real impl, might need to re-init process
|
|
97
140
|
|
|
98
141
|
# Async mode: assume running
|
|
99
142
|
self.model.status = "running"
|
|
143
|
+
self.model.pid = self.worker.process_id
|
|
100
144
|
self.model.updated_at = datetime.now()
|
|
145
|
+
self._save()
|
|
101
146
|
|
|
102
147
|
def terminate(self):
|
|
103
148
|
print(f"Session {self.model.id}: Terminating")
|
|
104
|
-
|
|
149
|
+
|
|
105
150
|
# Execute on_session_end hooks before stopping worker
|
|
106
151
|
# This allows hooks to perform cleanup while session context is still valid
|
|
107
152
|
try:
|
|
108
153
|
hook_context = self._create_hook_context()
|
|
109
154
|
results = self.hook_registry.execute_on_session_end(hook_context)
|
|
110
|
-
|
|
155
|
+
|
|
111
156
|
# Log hook results
|
|
112
157
|
for result in results:
|
|
113
158
|
if result.status == "failure":
|
|
@@ -115,7 +160,10 @@ class RuntimeSession:
|
|
|
115
160
|
except Exception as e:
|
|
116
161
|
# Don't let hook errors prevent session termination
|
|
117
162
|
print(f" Hook execution error: {e}")
|
|
118
|
-
|
|
119
|
-
self.worker
|
|
163
|
+
|
|
164
|
+
if self.worker:
|
|
165
|
+
self.worker.stop()
|
|
166
|
+
|
|
120
167
|
self.model.status = "terminated"
|
|
121
168
|
self.model.updated_at = datetime.now()
|
|
169
|
+
self._save()
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Dict
|
|
3
|
+
from monoco.core.loader import FeatureModule, FeatureMetadata
|
|
4
|
+
from monoco.core.feature import IntegrationData
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ArtifactFeature(FeatureModule):
|
|
8
|
+
"""Artifact management feature module."""
|
|
9
|
+
|
|
10
|
+
@property
|
|
11
|
+
def metadata(self) -> FeatureMetadata:
|
|
12
|
+
return FeatureMetadata(
|
|
13
|
+
name="artifact",
|
|
14
|
+
version="1.0.0",
|
|
15
|
+
description="Artifact management system for Monoco",
|
|
16
|
+
dependencies=["core"],
|
|
17
|
+
priority=20,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def integrate(self, root: Path, config: Dict) -> IntegrationData:
|
|
21
|
+
"""Provide integration data for agent environment."""
|
|
22
|
+
lang = config.get("i18n", {}).get("source_lang", "zh")
|
|
23
|
+
base_dir = Path(__file__).parent / "resources"
|
|
24
|
+
prompt_file = base_dir / lang / "AGENTS.md"
|
|
25
|
+
|
|
26
|
+
if not prompt_file.exists():
|
|
27
|
+
prompt_file = base_dir / "en" / "AGENTS.md"
|
|
28
|
+
|
|
29
|
+
content = ""
|
|
30
|
+
if prompt_file.exists():
|
|
31
|
+
content = prompt_file.read_text(encoding="utf-8").strip()
|
|
32
|
+
|
|
33
|
+
return IntegrationData(system_prompts={"Artifacts & Mailroom": content})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Artifacts & Mailroom
|
|
2
|
+
|
|
3
|
+
Monoco Artifacts 系统提供了多模态产物的生命周期管理能力,包括:
|
|
4
|
+
|
|
5
|
+
1. **内容寻址存储 (CAS)**: 所有产物存储在全局池 `~/.monoco/artifacts` 中,基于内容的 SHA256 哈希值进行寻址和去重。
|
|
6
|
+
2. **自动化摄取 (Mailroom)**: 通过监听 `.monoco/dropzone/` 目录,自动触发文档(Office, PDF 等)到 WebP 的转换流程。
|
|
7
|
+
3. **环境追踪**: 自动探测系统中的 `LibreOffice`, `PyMuPDF` 等工具链。
|
|
8
|
+
4. **元数据管理**: 项目本地维护 `manifest.jsonl`,记录所有产物的类型、哈希及创建时间。
|
|
9
|
+
|
|
10
|
+
### 常用操作建议
|
|
11
|
+
|
|
12
|
+
- **上传文档**: 建议将原始文档放入 `.monoco/dropzone/`,等待 Mailroom 自动完成转换并注册为 Artifact。
|
|
13
|
+
- **查看产物**: 检查 `.monoco/artifacts/manifest.jsonl` 获取当前可用的产物列表。
|
|
14
|
+
- **引用产物**: 在多模态分析时,可以使用产物的 ID 或本地软链接路径。
|