nucleus-mcp 1.0.7 → 1.2.0
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/package.json +2 -4
- package/.github/workflows/ci.yml +0 -72
- package/.smithery/shttp/module.js +0 -3
- package/.smithery/shttp/module.js.map +0 -7
- package/.smithery/stdio/index.cjs +0 -74
- package/.smithery/stdio/index.cjs.map +0 -7
- package/CHANGELOG.md +0 -65
- package/CODE_OF_CONDUCT.md +0 -34
- package/COMPARISON.md +0 -20
- package/CONTRIBUTING.md +0 -137
- package/DEVELOPMENT.md +0 -109
- package/LICENSE +0 -21
- package/README.md +0 -319
- package/ROADMAP.md +0 -24
- package/SECURITY.md +0 -88
- package/docs/COMMUNITY_FAQ.md +0 -48
- package/docs/COMPETITIVE_ANALYSIS.md +0 -90
- package/docs/DEMO_SCRIPT.md +0 -86
- package/docs/ENTERPRISE.md +0 -169
- package/docs/FAQ.md +0 -228
- package/docs/QUICK_START.md +0 -155
- package/docs/README.md +0 -67
- package/docs/RECURSIVE_SNAP_DEMO.gif +0 -0
- package/docs/social-preview-hq.png +0 -0
- package/docs/social-preview.png +0 -0
- package/examples/basic_usage.py +0 -84
- package/package.json.real +0 -24
- package/pyproject.toml +0 -50
- package/registry-server.json +0 -20
- package/scripts/demo_governance.py +0 -109
- package/scripts/sse_bridge.py +0 -87
- package/scripts/verify_windows_paths.py +0 -48
- package/server.json +0 -20
- package/src/mcp_server_nucleus/__init__.py +0 -8583
- package/src/mcp_server_nucleus/__main__.py +0 -9
- package/src/mcp_server_nucleus/cli.py +0 -1225
- package/src/mcp_server_nucleus/commitment_core.py +0 -146
- package/src/mcp_server_nucleus/commitment_ledger.py +0 -841
- package/src/mcp_server_nucleus/core/__init__.py +0 -6
- package/src/mcp_server_nucleus/core/orchestrator.py +0 -9
- package/src/mcp_server_nucleus/core/tool_registration_impl.py +0 -99
- package/src/mcp_server_nucleus/daemon/safety/lock.py +0 -121
- package/src/mcp_server_nucleus/deployment/render_integration.py +0 -4
- package/src/mcp_server_nucleus/hypervisor/__init__.py +0 -0
- package/src/mcp_server_nucleus/hypervisor/injector.py +0 -83
- package/src/mcp_server_nucleus/hypervisor/locker.py +0 -130
- package/src/mcp_server_nucleus/hypervisor/watchdog.py +0 -71
- package/src/mcp_server_nucleus/runtime/__init__.py +0 -58
- package/src/mcp_server_nucleus/runtime/agent.py +0 -517
- package/src/mcp_server_nucleus/runtime/agent_pool.py +0 -797
- package/src/mcp_server_nucleus/runtime/agents/base.py +0 -34
- package/src/mcp_server_nucleus/runtime/agents/oracle/manifest.json +0 -28
- package/src/mcp_server_nucleus/runtime/auth.py +0 -98
- package/src/mcp_server_nucleus/runtime/autopilot.py +0 -1057
- package/src/mcp_server_nucleus/runtime/broker.py +0 -126
- package/src/mcp_server_nucleus/runtime/budget.py +0 -153
- package/src/mcp_server_nucleus/runtime/capabilities/base.py +0 -20
- package/src/mcp_server_nucleus/runtime/capabilities/brain_ops.py +0 -253
- package/src/mcp_server_nucleus/runtime/capabilities/code_ops.py +0 -192
- package/src/mcp_server_nucleus/runtime/capabilities/depth_tracker.py +0 -81
- package/src/mcp_server_nucleus/runtime/capabilities/feature_map.py +0 -274
- package/src/mcp_server_nucleus/runtime/capabilities/marketing_engine.py +0 -205
- package/src/mcp_server_nucleus/runtime/capabilities/memory_ops.py +0 -79
- package/src/mcp_server_nucleus/runtime/capabilities/proof_system.py +0 -127
- package/src/mcp_server_nucleus/runtime/capabilities/render_ops.py +0 -80
- package/src/mcp_server_nucleus/runtime/capabilities/render_poller_cap.py +0 -266
- package/src/mcp_server_nucleus/runtime/capabilities/self_healing.py +0 -110
- package/src/mcp_server_nucleus/runtime/capabilities/strategy.py +0 -138
- package/src/mcp_server_nucleus/runtime/capabilities/synthesizer.py +0 -134
- package/src/mcp_server_nucleus/runtime/capabilities/web_ops.py +0 -94
- package/src/mcp_server_nucleus/runtime/common.py +0 -134
- package/src/mcp_server_nucleus/runtime/context_manager.py +0 -342
- package/src/mcp_server_nucleus/runtime/context_rules.json +0 -86
- package/src/mcp_server_nucleus/runtime/crdt_task_store.py +0 -349
- package/src/mcp_server_nucleus/runtime/critic.py +0 -150
- package/src/mcp_server_nucleus/runtime/daemon.py +0 -142
- package/src/mcp_server_nucleus/runtime/dashboard.py +0 -1087
- package/src/mcp_server_nucleus/runtime/depth_ops.py +0 -339
- package/src/mcp_server_nucleus/runtime/event_ops.py +0 -103
- package/src/mcp_server_nucleus/runtime/event_stream.py +0 -213
- package/src/mcp_server_nucleus/runtime/export.py +0 -64
- package/src/mcp_server_nucleus/runtime/factory.py +0 -594
- package/src/mcp_server_nucleus/runtime/federation.py +0 -1040
- package/src/mcp_server_nucleus/runtime/fetcher.py +0 -92
- package/src/mcp_server_nucleus/runtime/file_monitor.py +0 -208
- package/src/mcp_server_nucleus/runtime/firestore_bridge.py +0 -91
- package/src/mcp_server_nucleus/runtime/gcloud_ops.py +0 -186
- package/src/mcp_server_nucleus/runtime/hooks.py +0 -246
- package/src/mcp_server_nucleus/runtime/identity/gatekeeper.py +0 -106
- package/src/mcp_server_nucleus/runtime/identity/keygen.py +0 -147
- package/src/mcp_server_nucleus/runtime/identity/manifest.py +0 -62
- package/src/mcp_server_nucleus/runtime/identity/trust.py +0 -27
- package/src/mcp_server_nucleus/runtime/inspector.py +0 -74
- package/src/mcp_server_nucleus/runtime/installer.py +0 -81
- package/src/mcp_server_nucleus/runtime/ipc_auth.py +0 -377
- package/src/mcp_server_nucleus/runtime/lifecycle.py +0 -129
- package/src/mcp_server_nucleus/runtime/llm_client.py +0 -408
- package/src/mcp_server_nucleus/runtime/llm_tiers.json +0 -88
- package/src/mcp_server_nucleus/runtime/locking.py +0 -228
- package/src/mcp_server_nucleus/runtime/loops/fixer.py +0 -110
- package/src/mcp_server_nucleus/runtime/memory.py +0 -158
- package/src/mcp_server_nucleus/runtime/mounter.py +0 -210
- package/src/mcp_server_nucleus/runtime/mounter_ops.py +0 -250
- package/src/mcp_server_nucleus/runtime/nuke_protocol.py +0 -147
- package/src/mcp_server_nucleus/runtime/orchestrator.py +0 -370
- package/src/mcp_server_nucleus/runtime/orchestrator_unified.py +0 -263
- package/src/mcp_server_nucleus/runtime/orchestrator_v3.py +0 -617
- package/src/mcp_server_nucleus/runtime/plugin_loader.py +0 -84
- package/src/mcp_server_nucleus/runtime/policy.py +0 -117
- package/src/mcp_server_nucleus/runtime/profiling.py +0 -219
- package/src/mcp_server_nucleus/runtime/prometheus.py +0 -286
- package/src/mcp_server_nucleus/runtime/proposals.py +0 -101
- package/src/mcp_server_nucleus/runtime/publisher.py +0 -109
- package/src/mcp_server_nucleus/runtime/pulse.py +0 -516
- package/src/mcp_server_nucleus/runtime/registry.py +0 -82
- package/src/mcp_server_nucleus/runtime/render_ops.py +0 -83
- package/src/mcp_server_nucleus/runtime/schema_gen.py +0 -140
- package/src/mcp_server_nucleus/runtime/session_ops.py +0 -224
- package/src/mcp_server_nucleus/runtime/stdio_server.py +0 -633
- package/src/mcp_server_nucleus/runtime/storage.py +0 -83
- package/src/mcp_server_nucleus/runtime/strategy.py +0 -91
- package/src/mcp_server_nucleus/runtime/swarm.py +0 -170
- package/src/mcp_server_nucleus/runtime/sync_ops.py +0 -878
- package/src/mcp_server_nucleus/runtime/task_ingestion.py +0 -1020
- package/src/mcp_server_nucleus/runtime/task_ops.py +0 -449
- package/src/mcp_server_nucleus/runtime/task_scheduler.py +0 -488
- package/src/mcp_server_nucleus/runtime/team.py +0 -59
- package/src/mcp_server_nucleus/runtime/triggers.py +0 -237
- package/src/mcp_server_nucleus/runtime/vector_store.py +0 -125
- package/src/mcp_server_nucleus/runtime/watcher.py +0 -112
- package/src/mcp_server_nucleus/tool_tiers.py +0 -243
- package/tests/__init__.py +0 -1
- package/tests/conftest.py +0 -42
- package/tests/test_core.py +0 -235
- package/tests/test_search.py +0 -69
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import os
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Union
|
|
5
|
-
import logging
|
|
6
|
-
|
|
7
|
-
# Configuration
|
|
8
|
-
STORAGE_TYPE = os.environ.get("NUCLEUS_STORAGE_TYPE", "local") # local | firestore
|
|
9
|
-
FIRESTORE_COLLECTION = "nucleus_brain"
|
|
10
|
-
|
|
11
|
-
# Singleton Firestore Client
|
|
12
|
-
_firestore_client = None
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
try:
|
|
16
|
-
from google.cloud import firestore
|
|
17
|
-
except ImportError:
|
|
18
|
-
firestore = None
|
|
19
|
-
|
|
20
|
-
def get_firestore_client():
|
|
21
|
-
global _firestore_client
|
|
22
|
-
if _firestore_client is None:
|
|
23
|
-
if firestore is None:
|
|
24
|
-
logging.error("google-cloud-firestore not installed.")
|
|
25
|
-
raise ImportError("google-cloud-firestore module not found")
|
|
26
|
-
try:
|
|
27
|
-
_firestore_client = firestore.Client()
|
|
28
|
-
except Exception as e:
|
|
29
|
-
logging.error(f"Failed to initialize Firestore: {e}")
|
|
30
|
-
raise
|
|
31
|
-
return _firestore_client
|
|
32
|
-
|
|
33
|
-
def _path_to_id(path: Union[str, Path]) -> str:
|
|
34
|
-
"""Convert a file path to a Firestore Document ID."""
|
|
35
|
-
# We strip the brain root if possible to make IDs cleaner,
|
|
36
|
-
# but for now, just replacing slashes is enough uniqueness.
|
|
37
|
-
# e.g., "commitments/ledger.json" -> "commitments__ledger.json"
|
|
38
|
-
p = str(path)
|
|
39
|
-
# If path is absolute, try to make it relative to brain root?
|
|
40
|
-
# Actually, simplistic approach: replace / with __
|
|
41
|
-
return p.strip("/").replace("/", "__").replace(".", "_")
|
|
42
|
-
|
|
43
|
-
def read_brain_file(path: Union[str, Path]) -> str:
|
|
44
|
-
"""Read a file from Brain (Local or Firestore)."""
|
|
45
|
-
if STORAGE_TYPE == "firestore":
|
|
46
|
-
db = get_firestore_client()
|
|
47
|
-
doc_ref = db.collection(FIRESTORE_COLLECTION).document(_path_to_id(path))
|
|
48
|
-
doc = doc_ref.get()
|
|
49
|
-
if doc.exists:
|
|
50
|
-
return doc.to_dict().get("content", "")
|
|
51
|
-
else:
|
|
52
|
-
raise FileNotFoundError(f"Firestore document {doc_ref.id} not found")
|
|
53
|
-
else:
|
|
54
|
-
# Local Mode
|
|
55
|
-
p = Path(path)
|
|
56
|
-
return p.read_text()
|
|
57
|
-
|
|
58
|
-
def write_brain_file(path: Union[str, Path], content: str) -> None:
|
|
59
|
-
"""Write content to Brain (Local or Firestore)."""
|
|
60
|
-
if STORAGE_TYPE == "firestore":
|
|
61
|
-
db = get_firestore_client()
|
|
62
|
-
doc_id = _path_to_id(path)
|
|
63
|
-
doc_ref = db.collection(FIRESTORE_COLLECTION).document(doc_id)
|
|
64
|
-
|
|
65
|
-
doc_ref.set({
|
|
66
|
-
"content": content,
|
|
67
|
-
"path": str(path),
|
|
68
|
-
"updated_at": firestore.SERVER_TIMESTAMP
|
|
69
|
-
}, merge=True)
|
|
70
|
-
else:
|
|
71
|
-
# Local Mode
|
|
72
|
-
p = Path(path)
|
|
73
|
-
p.parent.mkdir(parents=True, exist_ok=True)
|
|
74
|
-
p.write_text(content)
|
|
75
|
-
|
|
76
|
-
def brain_file_exists(path: Union[str, Path]) -> bool:
|
|
77
|
-
"""Check if file exists in Brain."""
|
|
78
|
-
if STORAGE_TYPE == "firestore":
|
|
79
|
-
db = get_firestore_client()
|
|
80
|
-
doc_ref = db.collection(FIRESTORE_COLLECTION).document(_path_to_id(path))
|
|
81
|
-
return doc_ref.get().exists
|
|
82
|
-
else:
|
|
83
|
-
return Path(path).exists()
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import os
|
|
3
|
-
import logging
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Dict, Optional
|
|
6
|
-
|
|
7
|
-
# Configure logger
|
|
8
|
-
logger = logging.getLogger("nucleus.strategy")
|
|
9
|
-
|
|
10
|
-
def get_brain_path() -> Path:
|
|
11
|
-
"""Get the brain path from environment variable."""
|
|
12
|
-
brain_path = os.environ.get("NUCLEAR_BRAIN_PATH")
|
|
13
|
-
if not brain_path:
|
|
14
|
-
cwd = Path.cwd()
|
|
15
|
-
if (cwd / ".brain").exists():
|
|
16
|
-
return cwd / ".brain"
|
|
17
|
-
for parent in cwd.parents:
|
|
18
|
-
if (parent / ".brain").exists():
|
|
19
|
-
return parent / ".brain"
|
|
20
|
-
raise ValueError("NUCLEAR_BRAIN_PATH environment variable not set")
|
|
21
|
-
return Path(brain_path)
|
|
22
|
-
|
|
23
|
-
def _manage_strategy(action: str, content: Optional[str] = None) -> Dict:
|
|
24
|
-
"""
|
|
25
|
-
Manage the Strategy Document.
|
|
26
|
-
"""
|
|
27
|
-
try:
|
|
28
|
-
brain = get_brain_path()
|
|
29
|
-
strategy_file = brain / "strategy.md"
|
|
30
|
-
|
|
31
|
-
if action == "read":
|
|
32
|
-
if not strategy_file.exists():
|
|
33
|
-
return {"status": "empty", "content": ""}
|
|
34
|
-
return {"status": "success", "content": strategy_file.read_text()}
|
|
35
|
-
|
|
36
|
-
elif action == "update":
|
|
37
|
-
if not content:
|
|
38
|
-
return {"error": "Content required for update"}
|
|
39
|
-
strategy_file.write_text(content)
|
|
40
|
-
return {"status": "success", "message": "Strategy updated"}
|
|
41
|
-
|
|
42
|
-
elif action == "append":
|
|
43
|
-
if not content:
|
|
44
|
-
return {"error": "Content required for append"}
|
|
45
|
-
current = strategy_file.read_text() if strategy_file.exists() else ""
|
|
46
|
-
strategy_file.write_text(current + "\n\n" + content)
|
|
47
|
-
return {"status": "success", "message": "Strategy appended"}
|
|
48
|
-
|
|
49
|
-
else:
|
|
50
|
-
return {"error": f"Unknown action: {action}"}
|
|
51
|
-
|
|
52
|
-
except Exception as e:
|
|
53
|
-
logger.error(f"Strategy op failed: {e}")
|
|
54
|
-
return {"error": str(e)}
|
|
55
|
-
|
|
56
|
-
def _update_roadmap(action: str, item: str = None) -> Dict:
|
|
57
|
-
"""
|
|
58
|
-
Update the Roadmap.
|
|
59
|
-
"""
|
|
60
|
-
try:
|
|
61
|
-
brain = get_brain_path()
|
|
62
|
-
roadmap_file = brain / "roadmap.md"
|
|
63
|
-
|
|
64
|
-
if action == "read":
|
|
65
|
-
if not roadmap_file.exists():
|
|
66
|
-
return {"status": "empty", "content": ""}
|
|
67
|
-
return {"status": "success", "content": roadmap_file.read_text()}
|
|
68
|
-
|
|
69
|
-
elif action == "add":
|
|
70
|
-
current = roadmap_file.read_text() if roadmap_file.exists() else "# Roadmap\n"
|
|
71
|
-
new_content = current + f"\n- [ ] {item}"
|
|
72
|
-
roadmap_file.write_text(new_content)
|
|
73
|
-
return {"status": "success", "message": f"Added to roadmap: {item}"}
|
|
74
|
-
|
|
75
|
-
elif action == "complete":
|
|
76
|
-
if not roadmap_file.exists():
|
|
77
|
-
return {"error": "Roadmap not found"}
|
|
78
|
-
content = roadmap_file.read_text()
|
|
79
|
-
if item not in content:
|
|
80
|
-
return {"error": f"Item not found: {item}"}
|
|
81
|
-
# Simple string replacement for checkmark
|
|
82
|
-
new_content = content.replace(f"- [ ] {item}", f"- [x] {item}")
|
|
83
|
-
roadmap_file.write_text(new_content)
|
|
84
|
-
return {"status": "success", "message": f"Completed: {item}"}
|
|
85
|
-
|
|
86
|
-
else:
|
|
87
|
-
return {"error": f"Unknown action: {action}. Use 'read', 'add', or 'complete'."}
|
|
88
|
-
|
|
89
|
-
except Exception as e:
|
|
90
|
-
logger.error(f"Roadmap op failed: {e}")
|
|
91
|
-
return {"error": str(e)}
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Swarm Orchestration Entry Point.
|
|
3
|
-
Phase 60+ Enterprise Upgrade: Now uses SwarmsOrchestrator for real auto-execution.
|
|
4
|
-
|
|
5
|
-
This module is the bridge between the MCP tool (brain_orchestrate_swarm)
|
|
6
|
-
and the SwarmsOrchestrator class that handles actual agent spawning.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import os
|
|
10
|
-
import asyncio
|
|
11
|
-
import logging
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
from typing import Dict, List
|
|
14
|
-
|
|
15
|
-
# Configure logger
|
|
16
|
-
logger = logging.getLogger("nucleus.swarm")
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def get_brain_path() -> Path:
|
|
20
|
-
"""Get the brain path from environment variable."""
|
|
21
|
-
# Try NUCLEUS_BRAIN_PATH first (correct name), then NUCLEAR_BRAIN_PATH (legacy)
|
|
22
|
-
brain_path = os.environ.get("NUCLEUS_BRAIN_PATH") or os.environ.get("NUCLEAR_BRAIN_PATH")
|
|
23
|
-
if brain_path and Path(brain_path).exists():
|
|
24
|
-
return Path(brain_path)
|
|
25
|
-
|
|
26
|
-
# Fallback: search for .brain directory
|
|
27
|
-
cwd = Path.cwd()
|
|
28
|
-
if (cwd / ".brain").exists():
|
|
29
|
-
return cwd / ".brain"
|
|
30
|
-
for parent in cwd.parents:
|
|
31
|
-
if (parent / ".brain").exists():
|
|
32
|
-
return parent / ".brain"
|
|
33
|
-
|
|
34
|
-
# Ultimate fallback
|
|
35
|
-
return Path("/Users/lokeshgarg/ai-mvp-backend/.brain")
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def _orchestrate_swarm(mission: str, agents: List[str] = None) -> Dict:
|
|
39
|
-
"""
|
|
40
|
-
Orchestrate a swarm of agents to complete a complex mission.
|
|
41
|
-
|
|
42
|
-
Phase 60+ UPGRADE: Now uses SwarmsOrchestrator for REAL auto-execution.
|
|
43
|
-
Agents are spawned automatically in sequence - no manual intervention needed.
|
|
44
|
-
|
|
45
|
-
Args:
|
|
46
|
-
mission: High-level goal description
|
|
47
|
-
agents: List of agent personas to recruit (default: ["developer", "critic"])
|
|
48
|
-
|
|
49
|
-
Returns:
|
|
50
|
-
Dict with mission_id, status, and instructions for checking results
|
|
51
|
-
"""
|
|
52
|
-
try:
|
|
53
|
-
from .orchestrator import SwarmsOrchestrator
|
|
54
|
-
|
|
55
|
-
brain_path = get_brain_path()
|
|
56
|
-
logger.info(f"🐝 Initializing swarm for mission: {mission}")
|
|
57
|
-
|
|
58
|
-
# Create orchestrator
|
|
59
|
-
orchestrator = SwarmsOrchestrator(brain_path)
|
|
60
|
-
|
|
61
|
-
# Prepare agents list
|
|
62
|
-
agent_list = agents or ["developer", "critic"]
|
|
63
|
-
|
|
64
|
-
# Apply nest_asyncio for running async in sync context
|
|
65
|
-
try:
|
|
66
|
-
import nest_asyncio
|
|
67
|
-
nest_asyncio.apply()
|
|
68
|
-
except ImportError:
|
|
69
|
-
logger.warning("nest_asyncio not available, async may fail in some contexts")
|
|
70
|
-
|
|
71
|
-
# Run the async mission
|
|
72
|
-
try:
|
|
73
|
-
# Try to get existing loop
|
|
74
|
-
loop = asyncio.get_event_loop()
|
|
75
|
-
if loop.is_running():
|
|
76
|
-
# We're in an async context, use run_until_complete
|
|
77
|
-
result = loop.run_until_complete(orchestrator.start_mission(
|
|
78
|
-
mission_goal=mission,
|
|
79
|
-
swarm_type="execution",
|
|
80
|
-
agents=agent_list
|
|
81
|
-
))
|
|
82
|
-
else:
|
|
83
|
-
# No loop running, use asyncio.run
|
|
84
|
-
result = asyncio.run(orchestrator.start_mission(
|
|
85
|
-
mission_goal=mission,
|
|
86
|
-
swarm_type="execution",
|
|
87
|
-
agents=agent_list
|
|
88
|
-
))
|
|
89
|
-
except RuntimeError as async_error:
|
|
90
|
-
# Fallback: create new loop
|
|
91
|
-
logger.warning(f"Async issue: {async_error}, creating new event loop")
|
|
92
|
-
loop = asyncio.new_event_loop()
|
|
93
|
-
asyncio.set_event_loop(loop)
|
|
94
|
-
try:
|
|
95
|
-
result = loop.run_until_complete(orchestrator.start_mission(
|
|
96
|
-
mission_goal=mission,
|
|
97
|
-
swarm_type="execution",
|
|
98
|
-
agents=agent_list
|
|
99
|
-
))
|
|
100
|
-
finally:
|
|
101
|
-
loop.close()
|
|
102
|
-
|
|
103
|
-
mission_id = result.get("mission_id", "unknown")
|
|
104
|
-
status = result.get("status", "unknown")
|
|
105
|
-
|
|
106
|
-
logger.info(f"✅ Swarm {mission_id} initiated with agents: {agent_list}")
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
"success": True,
|
|
110
|
-
"mission_id": mission_id,
|
|
111
|
-
"status": status,
|
|
112
|
-
"agents": agent_list,
|
|
113
|
-
"message": f"Swarm {mission_id} started with agents {agent_list}. Agents are executing in background.",
|
|
114
|
-
"check_results": f".brain/swarms/{mission_id}/summary.md",
|
|
115
|
-
"check_state": ".brain/swarms/state.json"
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
except Exception as e:
|
|
119
|
-
logger.error(f"❌ Swarm orchestration failed: {e}")
|
|
120
|
-
import traceback
|
|
121
|
-
traceback.print_exc()
|
|
122
|
-
return {
|
|
123
|
-
"success": False,
|
|
124
|
-
"error": str(e),
|
|
125
|
-
"message": f"Swarm failed to start: {e}"
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def _get_swarm_status(mission_id: str) -> Dict:
|
|
130
|
-
"""
|
|
131
|
-
Check the status of a running swarm.
|
|
132
|
-
|
|
133
|
-
Args:
|
|
134
|
-
mission_id: The mission ID returned from _orchestrate_swarm
|
|
135
|
-
|
|
136
|
-
Returns:
|
|
137
|
-
Current mission state and any artifacts produced
|
|
138
|
-
"""
|
|
139
|
-
try:
|
|
140
|
-
from .orchestrator import SwarmsOrchestrator
|
|
141
|
-
|
|
142
|
-
brain_path = get_brain_path()
|
|
143
|
-
orchestrator = SwarmsOrchestrator(brain_path)
|
|
144
|
-
|
|
145
|
-
# Check state file
|
|
146
|
-
state = orchestrator._active_missions.get(mission_id)
|
|
147
|
-
if not state:
|
|
148
|
-
return {
|
|
149
|
-
"success": False,
|
|
150
|
-
"error": f"Mission {mission_id} not found"
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
# Check for artifacts
|
|
154
|
-
mission_dir = brain_path / "swarms" / mission_id
|
|
155
|
-
artifacts = []
|
|
156
|
-
if mission_dir.exists():
|
|
157
|
-
for f in mission_dir.iterdir():
|
|
158
|
-
artifacts.append(str(f.name))
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
"success": True,
|
|
162
|
-
"mission_id": mission_id,
|
|
163
|
-
"status": state.get("status", "unknown"),
|
|
164
|
-
"step_count": state.get("step_count", 0),
|
|
165
|
-
"cost_usd": state.get("cost_usd", 0),
|
|
166
|
-
"artifacts": artifacts
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
except Exception as e:
|
|
170
|
-
return {"success": False, "error": str(e)}
|