diff --git a/.omc/project-memory.json b/.omc/project-memory.json index 57a19f2..2923583 100644 --- a/.omc/project-memory.json +++ b/.omc/project-memory.json @@ -1,7 +1,7 @@ { "version": "1.0.0", - "lastScanned": 1773304964541, - "projectRoot": "/Users/cillin/workspeace/agentscope-samples/evotraders", + "lastScanned": 1773938154948, + "projectRoot": "/Users/cillin/workspeace/evotraders", "techStack": { "languages": [ { @@ -11,6 +11,14 @@ "markers": [ "pyproject.toml" ] + }, + { + "name": "C/C++", + "version": null, + "confidence": "high", + "markers": [ + "Makefile" + ] } ], "frameworks": [ @@ -24,8 +32,8 @@ "runtime": null }, "build": { - "buildCommand": null, - "testCommand": "pytest", + "buildCommand": "make build", + "testCommand": "make test", "lintCommand": "ruff check", "devCommand": null, "scripts": {} @@ -40,7 +48,8 @@ "isMonorepo": false, "workspaces": [], "mainDirectories": [ - "docs" + "docs", + "scripts" ], "gitBranches": { "defaultBranch": "main", @@ -49,29 +58,64 @@ }, "customNotes": [], "directoryMap": { + "agent-service": { + "path": "agent-service", + "purpose": null, + "fileCount": 2, + "lastAccessed": 1773938154941, + "keyFiles": [ + "Dockerfile", + "requirements.txt" + ] + }, "backend": { "path": "backend", "purpose": null, - "fileCount": 3, - "lastAccessed": 1773304964533, + "fileCount": 5, + "lastAccessed": 1773938154941, "keyFiles": [ "__init__.py", + "app.py", "cli.py", + "gateway_server.py", "main.py" ] }, + "backtest": { + "path": "backtest", + "purpose": null, + "fileCount": 0, + "lastAccessed": 1773938154941, + "keyFiles": [] + }, + "data": { + "path": "data", + "purpose": "Data files", + "fileCount": 1, + "lastAccessed": 1773938154941, + "keyFiles": [ + "market_research.db" + ] + }, + "deploy": { + "path": "deploy", + "purpose": null, + "fileCount": 0, + "lastAccessed": 1773938154942, + "keyFiles": [] + }, "docs": { "path": "docs", "purpose": "Documentation", "fileCount": 0, - "lastAccessed": 1773304964533, + "lastAccessed": 1773938154942, "keyFiles": [] }, "evotraders.egg-info": { "path": "evotraders.egg-info", "purpose": null, "fileCount": 6, - "lastAccessed": 1773304964534, + "lastAccessed": 1773938154942, "keyFiles": [ "PKG-INFO", "SOURCES.txt", @@ -83,8 +127,8 @@ "frontend": { "path": "frontend", "purpose": null, - "fileCount": 12, - "lastAccessed": 1773304964535, + "fileCount": 13, + "lastAccessed": 1773938154942, "keyFiles": [ "README.md", "components.json", @@ -93,239 +137,488 @@ "index.css" ] }, + "live": { + "path": "live", + "purpose": null, + "fileCount": 0, + "lastAccessed": 1773938154943, + "keyFiles": [] + }, + "logs": { + "path": "logs", + "purpose": null, + "fileCount": 7, + "lastAccessed": 1773938154943, + "keyFiles": [ + "2026-03-16_00-48-03.log", + "2026-03-18_23-17-29.log", + "2026-03-18_23-17-30.2026-03-18_23-17-30_000801.log.zip", + "2026-03-18_23-17-30.log", + "2026-03-19_00-18-04.log" + ] + }, + "news-service": { + "path": "news-service", + "purpose": null, + "fileCount": 3, + "lastAccessed": 1773938154943, + "keyFiles": [ + "Dockerfile", + "requirements.txt" + ] + }, + "reference": { + "path": "reference", + "purpose": null, + "fileCount": 0, + "lastAccessed": 1773938154943, + "keyFiles": [] + }, + "runs": { + "path": "runs", + "purpose": null, + "fileCount": 0, + "lastAccessed": 1773938154944, + "keyFiles": [] + }, + "scripts": { + "path": "scripts", + "purpose": "Build/utility scripts", + "fileCount": 1, + "lastAccessed": 1773938154944, + "keyFiles": [ + "run_prod.sh" + ] + }, + "services": { + "path": "services", + "purpose": "Business logic services", + "fileCount": 1, + "lastAccessed": 1773938154944, + "keyFiles": [ + "README.md" + ] + }, + "shared": { + "path": "shared", + "purpose": null, + "fileCount": 0, + "lastAccessed": 1773938154944, + "keyFiles": [] + }, + "trading-service": { + "path": "trading-service", + "purpose": null, + "fileCount": 4, + "lastAccessed": 1773938154944, + "keyFiles": [ + "Dockerfile", + "README.md", + "requirements.txt" + ] + }, + "workspaces": { + "path": "workspaces", + "purpose": null, + "fileCount": 0, + "lastAccessed": 1773938154944, + "keyFiles": [] + }, + "agent-service/src": { + "path": "agent-service/src", + "purpose": "Source code", + "fileCount": 5, + "lastAccessed": 1773938154944, + "keyFiles": [ + "__init__.py", + "config.py", + "main.py" + ] + }, + "backend/api": { + "path": "backend/api", + "purpose": "API routes", + "fileCount": 5, + "lastAccessed": 1773938154944, + "keyFiles": [ + "__init__.py", + "agents.py", + "guard.py" + ] + }, "backend/config": { "path": "backend/config", "purpose": "Configuration files", - "fileCount": 4, - "lastAccessed": 1773304964535, + "fileCount": 6, + "lastAccessed": 1773938154944, "keyFiles": [ "__init__.py", - "constants.py", - "data_config.py" + "agent_profiles.yaml", + "bootstrap_config.py" ] }, "backend/data": { "path": "backend/data", "purpose": "Data files", - "fileCount": 7, - "lastAccessed": 1773304964536, + "fileCount": 13, + "lastAccessed": 1773938154944, "keyFiles": [ "__init__.py", "cache.py", "historical_price_manager.py" ] }, - "backend/services": { - "path": "backend/services", - "purpose": "Business logic services", - "fileCount": 4, - "lastAccessed": 1773304964536, - "keyFiles": [ - "__init__.py", - "gateway.py", - "market.py" - ] - }, - "backend/tests": { - "path": "backend/tests", - "purpose": "Test files", - "fileCount": 4, - "lastAccessed": 1773304964536, - "keyFiles": [ - "__init__.py", - "test_agents.py", - "test_market_service.py" - ] - }, "docs/assets": { "path": "docs/assets", "purpose": "Static assets", "fileCount": 5, - "lastAccessed": 1773304964536, + "lastAccessed": 1773938154944, "keyFiles": [ "dashboard.jpg", "evotraders_demo.gif", "evotraders_logo.jpg" ] }, - "frontend/public": { - "path": "frontend/public", - "purpose": "Public files", - "fileCount": 1, - "lastAccessed": 1773304964538, + "frontend/dist": { + "path": "frontend/dist", + "purpose": "Distribution/build output", + "fileCount": 2, + "lastAccessed": 1773938154945, "keyFiles": [ + "index.html", "trading_logo.png" ] + }, + "frontend/node_modules": { + "path": "frontend/node_modules", + "purpose": "Dependencies", + "fileCount": 1, + "lastAccessed": 1773938154947, + "keyFiles": [] + }, + "news-service/src": { + "path": "news-service/src", + "purpose": "Source code", + "fileCount": 3, + "lastAccessed": 1773938154948, + "keyFiles": [ + "__init__.py", + "config.py", + "main.py" + ] + }, + "trading-service/src": { + "path": "trading-service/src", + "purpose": "Source code", + "fileCount": 8, + "lastAccessed": 1773938154948, + "keyFiles": [ + "__init__.py", + "config.py", + "main.py" + ] } }, "hotPaths": [ { - "path": "frontend/src/components/StatisticsView.jsx", - "accessCount": 22, - "lastAccessed": 1773310044545, - "type": "file" - }, - { - "path": "frontend/src/components/AgentCard.jsx", + "path": "backend/agents/factory.py", "accessCount": 17, - "lastAccessed": 1773309995177, - "type": "file" - }, - { - "path": "frontend/src/App.jsx", - "accessCount": 12, - "lastAccessed": 1773309849392, - "type": "file" - }, - { - "path": "frontend/src/components/AgentFeed.jsx", - "accessCount": 12, - "lastAccessed": 1773309960022, - "type": "file" - }, - { - "path": ".env", - "accessCount": 7, - "lastAccessed": 1773308950505, - "type": "file" - }, - { - "path": "frontend/src/components/RoomView.jsx", - "accessCount": 7, - "lastAccessed": 1773309864236, - "type": "file" - }, - { - "path": "backend/tools/analysis_tools.py", - "accessCount": 5, - "lastAccessed": 1773312271446, - "type": "file" - }, - { - "path": "frontend/src/components/Header.jsx", - "accessCount": 4, - "lastAccessed": 1773309827069, - "type": "file" - }, - { - "path": "frontend/src/components/AboutModal.jsx", - "accessCount": 4, - "lastAccessed": 1773310093371, - "type": "file" - }, - { - "path": "backend/agents/prompts/analyst/personas.yaml", - "accessCount": 4, - "lastAccessed": 1773312049213, - "type": "file" - }, - { - "path": "backend/agents/prompts/analyst/system.md", - "accessCount": 4, - "lastAccessed": 1773312049696, - "type": "file" - }, - { - "path": "backend/agents/prompts/portfolio_manager/system.md", - "accessCount": 4, - "lastAccessed": 1773312050326, - "type": "file" - }, - { - "path": "backend/agents/prompts/risk_manager/system.md", - "accessCount": 4, - "lastAccessed": 1773312050782, - "type": "file" - }, - { - "path": "frontend/src/config/constants.js", - "accessCount": 3, - "lastAccessed": 1773309824671, - "type": "file" - }, - { - "path": "frontend/src/components/RulesView.jsx", - "accessCount": 3, - "lastAccessed": 1773310061939, + "lastAccessed": 1773939950376, "type": "file" }, { "path": "backend", - "accessCount": 3, - "lastAccessed": 1773312200721, + "accessCount": 16, + "lastAccessed": 1773940042371, "type": "directory" }, + { + "path": "", + "accessCount": 13, + "lastAccessed": 1773939899611, + "type": "directory" + }, + { + "path": "backend/main.py", + "accessCount": 7, + "lastAccessed": 1773939993951, + "type": "file" + }, + { + "path": "backend/gateway_server.py", + "accessCount": 7, + "lastAccessed": 1773940004402, + "type": "file" + }, + { + "path": "backend/services/news/main.py", + "accessCount": 5, + "lastAccessed": 1773938385662, + "type": "file" + }, + { + "path": "backend/core/pipeline.py", + "accessCount": 5, + "lastAccessed": 1773940024933, + "type": "file" + }, + { + "path": "backend/services/news/enrich/news_enricher.py", + "accessCount": 4, + "lastAccessed": 1773938508417, + "type": "file" + }, + { + "path": "start-dev.sh", + "accessCount": 4, + "lastAccessed": 1773939259381, + "type": "file" + }, + { + "path": "services/README.md", + "accessCount": 4, + "lastAccessed": 1773939281935, + "type": "file" + }, + { + "path": "backend/app.py", + "accessCount": 4, + "lastAccessed": 1773939648215, + "type": "file" + }, + { + "path": "backend/services/news/routes/news.py", + "accessCount": 3, + "lastAccessed": 1773938438928, + "type": "file" + }, + { + "path": "backend/services/news", + "accessCount": 3, + "lastAccessed": 1773938468730, + "type": "directory" + }, + { + "path": "frontend/src/config/constants.js", + "accessCount": 3, + "lastAccessed": 1773939204395, + "type": "file" + }, { "path": "backend/services/gateway.py", + "accessCount": 3, + "lastAccessed": 1773939672930, + "type": "file" + }, + { + "path": "backend/core/__init__.py", + "accessCount": 3, + "lastAccessed": 1773939963627, + "type": "file" + }, + { + "path": "backend/services/trading/main.py", "accessCount": 2, - "lastAccessed": 1773312232905, + "lastAccessed": 1773938360736, + "type": "file" + }, + { + "path": "backend/services/agents/main.py", + "accessCount": 2, + "lastAccessed": 1773938361040, + "type": "file" + }, + { + "path": "backend/services/trading/data/__init__.py", + "accessCount": 2, + "lastAccessed": 1773938402496, + "type": "file" + }, + { + "path": "backend/services/news/explain/__init__.py", + "accessCount": 2, + "lastAccessed": 1773938460019, + "type": "file" + }, + { + "path": "backend/services/news/enrich/__init__.py", + "accessCount": 2, + "lastAccessed": 1773938465216, + "type": "file" + }, + { + "path": "backend/services/news/explain/range_explainer.py", + "accessCount": 2, + "lastAccessed": 1773938481152, + "type": "file" + }, + { + "path": "backend/services/news/enrich/llm_enricher.py", + "accessCount": 2, + "lastAccessed": 1773938499885, + "type": "file" + }, + { + "path": "CLAUDE.md", + "accessCount": 2, + "lastAccessed": 1773939273598, + "type": "file" + }, + { + "path": "backend/agents/__init__.py", + "accessCount": 2, + "lastAccessed": 1773939883015, + "type": "file" + }, + { + "path": "backend/agents/agent_core.py", + "accessCount": 2, + "lastAccessed": 1773939886997, + "type": "file" + }, + { + "path": "Makefile", + "accessCount": 1, + "lastAccessed": 1773938226307, + "type": "file" + }, + { + "path": "docker-compose.yml", + "accessCount": 1, + "lastAccessed": 1773938226360, + "type": "file" + }, + { + "path": "backend/services/news/shared/trading_client.py", + "accessCount": 1, + "lastAccessed": 1773938370618, + "type": "file" + }, + { + "path": "backend/services/agents", + "accessCount": 1, + "lastAccessed": 1773938397772, "type": "directory" }, { - "path": "README.md", + "path": "backend/services/trading", "accessCount": 1, - "lastAccessed": 1773305013217, + "lastAccessed": 1773938397823, + "type": "directory" + }, + { + "path": "backend/services", + "accessCount": 1, + "lastAccessed": 1773938405541, + "type": "directory" + }, + { + "path": "backend/services/news/config.py", + "accessCount": 1, + "lastAccessed": 1773938638664, "type": "file" }, { - "path": "README_zh.md", + "path": "shared/client/news_client.py", "accessCount": 1, - "lastAccessed": 1773305013274, + "lastAccessed": 1773938638715, "type": "file" }, { - "path": "env.template", + "path": "shared/client/trading_client.py", "accessCount": 1, - "lastAccessed": 1773305019965, + "lastAccessed": 1773938638770, + "type": "file" + }, + { + "path": "backend/api", + "accessCount": 1, + "lastAccessed": 1773938669143, + "type": "directory" + }, + { + "path": "frontend", + "accessCount": 1, + "lastAccessed": 1773938669195, + "type": "directory" + }, + { + "path": ".env.example", + "accessCount": 1, + "lastAccessed": 1773938849397, "type": "file" }, { "path": "frontend/src/services/websocket.js", "accessCount": 1, - "lastAccessed": 1773309324302, + "lastAccessed": 1773938849448, "type": "file" }, { - "path": "backend/config/data_config.py", + "path": "frontend/src/services/runtimeApi.js", "accessCount": 1, - "lastAccessed": 1773309324414, + "lastAccessed": 1773938849500, "type": "file" }, { - "path": "backend/cli.py", + "path": "backend/services/agents/routes/websocket.py", "accessCount": 1, - "lastAccessed": 1773309336899, - "type": "directory" - }, - { - "path": "backend/agents/portfolio_manager.py", - "accessCount": 1, - "lastAccessed": 1773311956562, + "lastAccessed": 1773939001692, "type": "file" }, { - "path": "backend/agents/risk_manager.py", + "path": "backend/services/agents/routes/agents.py", "accessCount": 1, - "lastAccessed": 1773311956760, + "lastAccessed": 1773939016291, + "type": "file" + }, + { + "path": "backend/services/agents/routes/run.py", + "accessCount": 1, + "lastAccessed": 1773939016343, + "type": "file" + }, + { + "path": "backend/__init__.py", + "accessCount": 1, + "lastAccessed": 1773939648323, + "type": "file" + }, + { + "path": "backend/api/__init__.py", + "accessCount": 1, + "lastAccessed": 1773939658650, + "type": "file" + }, + { + "path": "backend/runtime/__init__.py", + "accessCount": 1, + "lastAccessed": 1773939658687, + "type": "file" + }, + { + "path": "backend/agents/base/evo_agent.py", + "accessCount": 1, + "lastAccessed": 1773939664916, "type": "file" }, { "path": "backend/agents/analyst.py", "accessCount": 1, - "lastAccessed": 1773311963222, + "lastAccessed": 1773939664967, "type": "file" }, { - "path": "backend/tools", + "path": "backend/agents/base/hooks.py", "accessCount": 1, - "lastAccessed": 1773312289643, - "type": "directory" + "lastAccessed": 1773939672727, + "type": "file" }, { - "path": "backend/tools/data_tools.py", + "path": "pyproject.toml", "accessCount": 1, - "lastAccessed": 1773312293851, - "type": "directory" + "lastAccessed": 1773939672778, + "type": "file" } ], "userDirectives": [] diff --git a/.omc/state/hud-state.json b/.omc/state/hud-state.json index 9efff91..6755a93 100644 --- a/.omc/state/hud-state.json +++ b/.omc/state/hud-state.json @@ -1,6 +1,6 @@ { - "timestamp": "2026-03-12T20:33:59.497Z", + "timestamp": "2026-03-19T16:36:52.471Z", "backgroundTasks": [], - "sessionStartTimestamp": "2026-03-12T14:19:33.615Z", - "sessionId": "73b0d597-0141-4873-9d0e-2b60e4e0635e" + "sessionStartTimestamp": "2026-03-19T16:36:42.224Z", + "sessionId": "ef02339a-1eec-4c7a-95ac-c8cfa0b5067d" } \ No newline at end of file diff --git a/.omc/state/hud-stdin-cache.json b/.omc/state/hud-stdin-cache.json index 48a5e77..9cbf52b 100644 --- a/.omc/state/hud-stdin-cache.json +++ b/.omc/state/hud-stdin-cache.json @@ -1 +1 @@ -{"session_id":"73b0d597-0141-4873-9d0e-2b60e4e0635e","transcript_path":"/Users/cillin/.claude/projects/-Users-cillin-workspeace-agentscope-samples-evotraders/73b0d597-0141-4873-9d0e-2b60e4e0635e.jsonl","cwd":"/Users/cillin/workspeace/agentscope-samples/evotraders","model":{"id":"kimi-for-coding","display_name":"kimi-for-coding"},"workspace":{"current_dir":"/Users/cillin/workspeace/agentscope-samples/evotraders","project_dir":"/Users/cillin/workspeace/agentscope-samples/evotraders","added_dirs":["/Users/cillin/workspeace/agentscope-samples/EvoTraders","/Users/cillin/workspeace/agentscope-samples/evotraders"]},"version":"2.1.63","output_style":{"name":"default"},"cost":{"total_cost_usd":6.822239999999999,"total_duration_ms":42679588,"total_api_duration_ms":1223637,"total_lines_added":275,"total_lines_removed":240},"context_window":{"total_input_tokens":654274,"total_output_tokens":27014,"context_window_size":200000,"current_usage":{"input_tokens":48465,"output_tokens":0,"cache_creation_input_tokens":0,"cache_read_input_tokens":0},"used_percentage":24,"remaining_percentage":76},"exceeds_200k_tokens":false} \ No newline at end of file +{"session_id":"ef02339a-1eec-4c7a-95ac-c8cfa0b5067d","transcript_path":"/Users/cillin/.claude/projects/-Users-cillin-workspeace-evotraders/ef02339a-1eec-4c7a-95ac-c8cfa0b5067d.jsonl","cwd":"/Users/cillin/workspeace/evotraders","model":{"id":"MiniMax-M2.7-highspeed","display_name":"MiniMax-M2.7-highspeed"},"workspace":{"current_dir":"/Users/cillin/workspeace/evotraders","project_dir":"/Users/cillin/workspeace/evotraders","added_dirs":[]},"version":"2.1.78","output_style":{"name":"default"},"cost":{"total_cost_usd":17.458779250000003,"total_duration_ms":1866224,"total_api_duration_ms":1188013,"total_lines_added":257,"total_lines_removed":290},"context_window":{"total_input_tokens":195204,"total_output_tokens":48917,"context_window_size":200000,"current_usage":{"input_tokens":481,"output_tokens":0,"cache_creation_input_tokens":149,"cache_read_input_tokens":163286},"used_percentage":82,"remaining_percentage":18},"exceeds_200k_tokens":false} \ No newline at end of file diff --git a/.omc/state/idle-notif-cooldown.json b/.omc/state/idle-notif-cooldown.json index e153d85..f79a2da 100644 --- a/.omc/state/idle-notif-cooldown.json +++ b/.omc/state/idle-notif-cooldown.json @@ -1,3 +1,3 @@ { - "lastSentAt": "2026-03-12T20:31:37.362Z" + "lastSentAt": "2026-03-19T17:02:32.170Z" } \ No newline at end of file diff --git a/.omc/state/subagent-tracking.json b/.omc/state/subagent-tracking.json index 98705f2..f187633 100644 --- a/.omc/state/subagent-tracking.json +++ b/.omc/state/subagent-tracking.json @@ -1,26 +1,17 @@ { "agents": [ { - "agent_id": "a4090d26a45ac828d", - "agent_type": "oh-my-claudecode:executor", - "started_at": "2026-03-12T10:02:38.238Z", + "agent_id": "a8305a91e192b2196", + "agent_type": "Explore", + "started_at": "2026-03-19T17:00:33.284Z", "parent_mode": "none", "status": "completed", - "completed_at": "2026-03-12T10:10:59.192Z", - "duration_ms": 500954 - }, - { - "agent_id": "af87583ef76a4df30", - "agent_type": "oh-my-claudecode:executor", - "started_at": "2026-03-12T10:40:04.409Z", - "parent_mode": "none", - "status": "completed", - "completed_at": "2026-03-12T10:41:17.387Z", - "duration_ms": 72978 + "completed_at": "2026-03-19T17:02:19.439Z", + "duration_ms": 106155 } ], - "total_spawned": 2, - "total_completed": 2, + "total_spawned": 1, + "total_completed": 1, "total_failed": 0, - "last_updated": "2026-03-12T10:41:17.490Z" + "last_updated": "2026-03-19T17:02:39.175Z" } \ No newline at end of file diff --git a/backend/agents/factory.py b/backend/agents/factory.py index 28794c5..a9291e1 100644 --- a/backend/agents/factory.py +++ b/backend/agents/factory.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""Agent Factory - Dynamic creation and management of EvoAgents.""" +"""Agent Factory - Dynamic creation and management of AgentConfigs.""" import logging import shutil @@ -37,8 +37,8 @@ class RoleConfig: self.constraints = [] -class EvoAgent: - """Represents a configured agent instance.""" +class AgentConfig: + """Represents a configured agent instance (data class).""" def __init__( self, @@ -185,7 +185,7 @@ class AgentFactory: model_config: Optional[ModelConfig] = None, role_config: Optional[RoleConfig] = None, clone_from: Optional[str] = None, - ) -> EvoAgent: + ) -> AgentConfig: """Create a new agent. Args: @@ -197,7 +197,7 @@ class AgentFactory: clone_from: Path to existing agent to clone from (optional) Returns: - EvoAgent instance + AgentConfig instance Raises: ValueError: If agent already exists or workspace doesn't exist @@ -234,7 +234,7 @@ class AgentFactory: config_path = agent_dir / "agent.yaml" self._write_agent_yaml(config_path, agent_id, agent_type, model_config) - return EvoAgent( + return AgentConfig( agent_id=agent_id, agent_type=agent_type, workspace_id=workspace_id, @@ -267,7 +267,7 @@ class AgentFactory: new_agent_id: str, target_workspace_id: Optional[str] = None, model_config: Optional[ModelConfig] = None, - ) -> EvoAgent: + ) -> AgentConfig: """Clone an existing agent. Args: @@ -278,7 +278,7 @@ class AgentFactory: model_config: Optional new model configuration Returns: - EvoAgent instance for the cloned agent + AgentConfig instance for the cloned agent """ target_workspace_id = target_workspace_id or source_workspace_id source_dir = self.workspaces_root / source_workspace_id / "agents" / source_agent_id diff --git a/backend/agents/prompt_factory.py b/backend/agents/prompt_factory.py index 6e9431d..198c6ba 100644 --- a/backend/agents/prompt_factory.py +++ b/backend/agents/prompt_factory.py @@ -6,10 +6,10 @@ from typing import Any, Optional from .agent_workspace import load_agent_workspace_config from backend.config.bootstrap_config import get_bootstrap_config_for_run -from .prompt_loader import PromptLoader +from .prompt_loader import get_prompt_loader from .skills_manager import SkillsManager -_prompt_loader = PromptLoader() +_prompt_loader = get_prompt_loader() def _read_file_if_exists(path: Path) -> str: diff --git a/backend/agents/prompt_loader.py b/backend/agents/prompt_loader.py index 53ca308..7ce25a6 100644 --- a/backend/agents/prompt_loader.py +++ b/backend/agents/prompt_loader.py @@ -10,6 +10,17 @@ from typing import Any, Dict, Optional import yaml +# Singleton instance +_prompt_loader_instance: Optional["PromptLoader"] = None + + +def get_prompt_loader() -> "PromptLoader": + """Get the singleton PromptLoader instance.""" + global _prompt_loader_instance + if _prompt_loader_instance is None: + _prompt_loader_instance = PromptLoader() + return _prompt_loader_instance + class PromptLoader: """Unified Prompt loader""" diff --git a/backend/cli.py b/backend/cli.py index d09bf72..3297448 100644 --- a/backend/cli.py +++ b/backend/cli.py @@ -29,7 +29,7 @@ from rich.table import Table from dotenv import load_dotenv from backend.agents.agent_workspace import load_agent_workspace_config -from backend.agents.prompt_loader import PromptLoader +from backend.agents.prompt_loader import get_prompt_loader from backend.agents.skills_manager import SkillsManager from backend.agents.team_pipeline_config import ( ensure_team_pipeline_config, @@ -55,7 +55,7 @@ team_app = typer.Typer(help="Inspect and manage run-scoped team pipeline config. app.add_typer(team_app, name="team") console = Console() -_prompt_loader = PromptLoader() +_prompt_loader = get_prompt_loader() load_dotenv() diff --git a/backend/core/__init__.py b/backend/core/__init__.py index 40853de..1e767f7 100644 --- a/backend/core/__init__.py +++ b/backend/core/__init__.py @@ -3,5 +3,12 @@ from .pipeline import TradingPipeline from .state_sync import StateSync +from .pipeline_runner import create_agents, create_long_term_memory, stop_gateway -__all__ = ["TradingPipeline", "StateSync"] +__all__ = [ + "TradingPipeline", + "StateSync", + "create_agents", + "create_long_term_memory", + "stop_gateway", +] diff --git a/backend/core/pipeline.py b/backend/core/pipeline.py index e96cf3e..644f76b 100644 --- a/backend/core/pipeline.py +++ b/backend/core/pipeline.py @@ -30,7 +30,7 @@ from backend.agents.team_pipeline_config import ( from backend.agents import AnalystAgent from backend.agents.toolkit_factory import create_agent_toolkit from backend.agents.workspace_manager import WorkspaceManager -from backend.agents.prompt_loader import PromptLoader +from backend.agents.prompt_loader import get_prompt_loader from backend.llm.models import get_agent_formatter, get_agent_model from backend.config.constants import ANALYST_TYPES @@ -1623,7 +1623,7 @@ class TradingPipeline: config_name = getattr(self.pm, "config", {}).get("config_name", "default") project_root = Path(__file__).resolve().parents[2] - personas = PromptLoader().load_yaml_config("analyst", "personas") + personas = get_prompt_loader().load_yaml_config("analyst", "personas") persona = personas.get(analyst_type, {}) WorkspaceManager(project_root=project_root).ensure_agent_assets( config_name=config_name, diff --git a/backend/core/pipeline_runner.py b/backend/core/pipeline_runner.py index 76270cb..911aee4 100644 --- a/backend/core/pipeline_runner.py +++ b/backend/core/pipeline_runner.py @@ -17,7 +17,7 @@ from typing import Any, Dict, Optional, Callable from backend.agents import AnalystAgent, PMAgent, RiskAgent from backend.agents.skills_manager import SkillsManager from backend.agents.toolkit_factory import create_agent_toolkit, load_agent_profiles -from backend.agents.prompt_loader import PromptLoader +from backend.agents.prompt_loader import get_prompt_loader from backend.agents.workspace_manager import WorkspaceManager from backend.config.constants import ANALYST_TYPES from backend.core.pipeline import TradingPipeline @@ -36,7 +36,7 @@ from backend.services.storage import StorageService from backend.services.gateway import Gateway from backend.utils.settlement import SettlementCoordinator -_prompt_loader = PromptLoader() +_prompt_loader = get_prompt_loader() # Global gateway reference for cleanup _gateway_instance: Optional[Gateway] = None diff --git a/backend/gateway_server.py b/backend/gateway_server.py index 3a4ee16..d75e5ab 100644 --- a/backend/gateway_server.py +++ b/backend/gateway_server.py @@ -22,7 +22,7 @@ load_dotenv() from backend.agents import AnalystAgent, PMAgent, RiskAgent from backend.agents.skills_manager import SkillsManager from backend.agents.toolkit_factory import create_agent_toolkit, load_agent_profiles -from backend.agents.prompt_loader import PromptLoader +from backend.agents.prompt_loader import get_prompt_loader from backend.agents.workspace_manager import WorkspaceManager from backend.config.constants import ANALYST_TYPES from backend.core.pipeline import TradingPipeline @@ -40,7 +40,7 @@ from backend.services.storage import StorageService from backend.utils.settlement import SettlementCoordinator logger = logging.getLogger(__name__) -_prompt_loader = PromptLoader() +_prompt_loader = get_prompt_loader() async def run_gateway( diff --git a/backend/main.py b/backend/main.py index 16ddb1e..cbb8573 100644 --- a/backend/main.py +++ b/backend/main.py @@ -16,7 +16,7 @@ from dotenv import load_dotenv from backend.agents import AnalystAgent, PMAgent, RiskAgent from backend.agents.skills_manager import SkillsManager from backend.agents.toolkit_factory import create_agent_toolkit, load_agent_profiles -from backend.agents.prompt_loader import PromptLoader +from backend.agents.prompt_loader import get_prompt_loader from backend.agents.workspace_manager import WorkspaceManager from backend.config.bootstrap_config import resolve_runtime_config from backend.config.constants import ANALYST_TYPES @@ -38,7 +38,7 @@ load_dotenv() logger = logging.getLogger(__name__) loguru.logger.disable("flowllm") loguru.logger.disable("reme_ai") -_prompt_loader = PromptLoader() +_prompt_loader = get_prompt_loader() def _get_run_dir(config_name: str) -> Path: