acra-cli 0.1.1__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.
Files changed (169) hide show
  1. acra/__init__.py +7 -0
  2. acra/__main__.py +4 -0
  3. acra/agents/__init__.py +0 -0
  4. acra/agents/__pycache__/__init__.cpython-312.pyc +0 -0
  5. acra/agents/__pycache__/llm.cpython-312.pyc +0 -0
  6. acra/agents/__pycache__/llm_utils.cpython-312.pyc +0 -0
  7. acra/agents/coder/__init__.py +0 -0
  8. acra/agents/coder/__pycache__/__init__.cpython-312.pyc +0 -0
  9. acra/agents/coder/__pycache__/coder_agent.cpython-312.pyc +0 -0
  10. acra/agents/coder/__pycache__/coder_chain.cpython-312.pyc +0 -0
  11. acra/agents/coder/coder_agent.py +235 -0
  12. acra/agents/coder/coder_chain.py +204 -0
  13. acra/agents/critic/__init__.py +0 -0
  14. acra/agents/critic/__pycache__/__init__.cpython-312.pyc +0 -0
  15. acra/agents/critic/__pycache__/critic_agent.cpython-312.pyc +0 -0
  16. acra/agents/critic/__pycache__/critic_chain.cpython-312.pyc +0 -0
  17. acra/agents/critic/critic_agent.py +199 -0
  18. acra/agents/critic/critic_chain.py +268 -0
  19. acra/agents/executor/__init__.py +0 -0
  20. acra/agents/executor/__pycache__/__init__.cpython-312.pyc +0 -0
  21. acra/agents/executor/__pycache__/docker_runner.cpython-312.pyc +0 -0
  22. acra/agents/executor/__pycache__/executor_agent.cpython-312.pyc +0 -0
  23. acra/agents/executor/__pycache__/sandbox_runner.cpython-312.pyc +0 -0
  24. acra/agents/executor/docker_runner.py +114 -0
  25. acra/agents/executor/executor_agent.py +142 -0
  26. acra/agents/executor/sandbox_runner.py +144 -0
  27. acra/agents/human/__init__.py +0 -0
  28. acra/agents/human/__pycache__/__init__.cpython-312.pyc +0 -0
  29. acra/agents/human/__pycache__/human_node.cpython-312.pyc +0 -0
  30. acra/agents/human/human_node.py +37 -0
  31. acra/agents/llm.py +263 -0
  32. acra/agents/llm_utils.py +161 -0
  33. acra/agents/memory/__init__.py +0 -0
  34. acra/agents/memory/__pycache__/__init__.cpython-312.pyc +0 -0
  35. acra/agents/memory/__pycache__/memory_agent.cpython-312.pyc +0 -0
  36. acra/agents/memory/__pycache__/memory_manager.cpython-312.pyc +0 -0
  37. acra/agents/memory/__pycache__/retrieval.cpython-312.pyc +0 -0
  38. acra/agents/memory/memory_agent.py +239 -0
  39. acra/agents/memory/memory_manager.py +273 -0
  40. acra/agents/memory/retrieval.py +355 -0
  41. acra/agents/planner/__init__.py +0 -0
  42. acra/agents/planner/__pycache__/__init__.cpython-312.pyc +0 -0
  43. acra/agents/planner/__pycache__/planner_agent.cpython-312.pyc +0 -0
  44. acra/agents/planner/__pycache__/planner_chain.cpython-312.pyc +0 -0
  45. acra/agents/planner/planner_agent.py +97 -0
  46. acra/agents/planner/planner_chain.py +160 -0
  47. acra/agents/researcher/__init__.py +1 -0
  48. acra/agents/researcher/__pycache__/__init__.cpython-312.pyc +0 -0
  49. acra/agents/researcher/__pycache__/researcher_agent.cpython-312.pyc +0 -0
  50. acra/agents/researcher/__pycache__/researcher_chain.cpython-312.pyc +0 -0
  51. acra/agents/researcher/researcher_agent.py +231 -0
  52. acra/agents/researcher/researcher_chain.py +193 -0
  53. acra/brain/__init__.py +6 -0
  54. acra/brain/model_registry.py +19 -0
  55. acra/brain/provider_manager.py +21 -0
  56. acra/cli.py +52 -0
  57. acra/commands/__init__.py +29 -0
  58. acra/commands/ask.py +49 -0
  59. acra/commands/brain.py +58 -0
  60. acra/commands/config.py +25 -0
  61. acra/commands/context.py +30 -0
  62. acra/commands/graph.py +18 -0
  63. acra/commands/keys.py +40 -0
  64. acra/commands/logs.py +13 -0
  65. acra/commands/memory.py +27 -0
  66. acra/commands/plugin.py +18 -0
  67. acra/commands/research.py +65 -0
  68. acra/commands/serve.py +13 -0
  69. acra/commands/session.py +20 -0
  70. acra/commands/utils.py +12 -0
  71. acra/config/__init__.py +36 -0
  72. acra/config/__pycache__/__init__.cpython-312.pyc +0 -0
  73. acra/config/__pycache__/defaults.cpython-312.pyc +0 -0
  74. acra/config/__pycache__/profile_manager.cpython-312.pyc +0 -0
  75. acra/config/defaults.py +88 -0
  76. acra/config/profile_manager.py +87 -0
  77. acra/execution/__init__.py +1 -0
  78. acra/execution/logs/__init__.py +1 -0
  79. acra/execution/logs/error_logs/__init__.py +1 -0
  80. acra/execution/logs/execution_logs/__init__.py +1 -0
  81. acra/execution/sandbox/__init__.py +1 -0
  82. acra/execution/sandbox/docker_executor.py +209 -0
  83. acra/execution/sandbox/isolated_runner.py +148 -0
  84. acra/execution/sandbox/sandbox_manager.py +178 -0
  85. acra/graph/__init__.py +0 -0
  86. acra/graph/checkpoint.py +85 -0
  87. acra/graph/conditional_edges.py +103 -0
  88. acra/graph/edges.py +85 -0
  89. acra/graph/graph_visualizer.py +175 -0
  90. acra/graph/nodes.py +68 -0
  91. acra/graph/router.py +69 -0
  92. acra/graph/state.py +93 -0
  93. acra/graph/workflow.py +117 -0
  94. acra/memory/__init__.py +1 -0
  95. acra/memory/checkpoints/__init__.py +1 -0
  96. acra/memory/checkpoints/data/__init__.py +1 -0
  97. acra/memory/checkpoints/postgres_checkpoint.py +247 -0
  98. acra/memory/checkpoints/sqlite_checkpoint.py +309 -0
  99. acra/memory/chroma_db/__init__.py +1 -0
  100. acra/memory/conversation_memory/__init__.py +1 -0
  101. acra/memory/conversation_memory/long_term.py +229 -0
  102. acra/memory/conversation_memory/short_term.py +158 -0
  103. acra/memory/storage/__init__.py +1 -0
  104. acra/memory/vector_store/__init__.py +0 -0
  105. acra/memory/vector_store/chroma_store.py +260 -0
  106. acra/memory/vector_store/embeddings.py +43 -0
  107. acra/observability/__init__.py +1 -0
  108. acra/observability/langsmith_tracing.py +91 -0
  109. acra/observability/metrics.py +189 -0
  110. acra/observability/monitoring.py +162 -0
  111. acra/observability/token_tracking.py +131 -0
  112. acra/prompts/__init__.py +1 -0
  113. acra/schemas/__init__.py +0 -0
  114. acra/schemas/__pycache__/__init__.cpython-312.pyc +0 -0
  115. acra/schemas/__pycache__/coder_schema.cpython-312.pyc +0 -0
  116. acra/schemas/__pycache__/critic_schema.cpython-312.pyc +0 -0
  117. acra/schemas/__pycache__/execution_schema.cpython-312.pyc +0 -0
  118. acra/schemas/__pycache__/planner_schema.cpython-312.pyc +0 -0
  119. acra/schemas/__pycache__/researcher_schema.cpython-312.pyc +0 -0
  120. acra/schemas/__pycache__/shared_schema.cpython-312.pyc +0 -0
  121. acra/schemas/coder_schema.py +257 -0
  122. acra/schemas/critic_schema.py +177 -0
  123. acra/schemas/execution_schema.py +74 -0
  124. acra/schemas/planner_schema.py +129 -0
  125. acra/schemas/researcher_schema.py +220 -0
  126. acra/schemas/shared_schema.py +329 -0
  127. acra/tools/__init__.py +1 -0
  128. acra/tools/code_tools/__init__.py +1 -0
  129. acra/tools/code_tools/file_reader.py +156 -0
  130. acra/tools/code_tools/file_writer.py +108 -0
  131. acra/tools/code_tools/python_repl.py +72 -0
  132. acra/tools/code_tools/terminal_runner.py +98 -0
  133. acra/tools/github_tools/__init__.py +1 -0
  134. acra/tools/github_tools/commit_generator.py +91 -0
  135. acra/tools/github_tools/github_search.py +113 -0
  136. acra/tools/github_tools/repo_analyzer.py +138 -0
  137. acra/tools/integration_test_helper.py +370 -0
  138. acra/tools/validation_tools/__init__.py +1 -0
  139. acra/tools/validation_tools/dependency_checker.py +101 -0
  140. acra/tools/validation_tools/environment_config_validator.py +353 -0
  141. acra/tools/validation_tools/http_validator.py +336 -0
  142. acra/tools/validation_tools/response_validator.py +407 -0
  143. acra/tools/validation_tools/security_checker.py +93 -0
  144. acra/tools/validation_tools/syntax_checker.py +75 -0
  145. acra/tools/validation_tools/web_framework_validator.py +382 -0
  146. acra/tools/web_tools/__init__.py +1 -0
  147. acra/tools/web_tools/arxiv_search.py +110 -0
  148. acra/tools/web_tools/serpapi_search.py +106 -0
  149. acra/tools/web_tools/tavily_search.py +96 -0
  150. acra/ui/__init__.py +8 -0
  151. acra/ui/__pycache__/__init__.cpython-312.pyc +0 -0
  152. acra/ui/__pycache__/banner.cpython-312.pyc +0 -0
  153. acra/ui/__pycache__/components.cpython-312.pyc +0 -0
  154. acra/ui/__pycache__/shell.cpython-312.pyc +0 -0
  155. acra/ui/__pycache__/theme.cpython-312.pyc +0 -0
  156. acra/ui/banner.py +40 -0
  157. acra/ui/components.py +32 -0
  158. acra/ui/shell.py +91 -0
  159. acra/ui/theme.py +28 -0
  160. acra/utils/__init__.py +21 -0
  161. acra/utils/context_manager.py +20 -0
  162. acra/utils/keyring_manager.py +83 -0
  163. acra/utils/output_formatter.py +18 -0
  164. acra/utils/session_manager.py +59 -0
  165. acra_cli-0.1.1.dist-info/METADATA +616 -0
  166. acra_cli-0.1.1.dist-info/RECORD +169 -0
  167. acra_cli-0.1.1.dist-info/WHEEL +5 -0
  168. acra_cli-0.1.1.dist-info/licenses/LICENSE +661 -0
  169. acra_cli-0.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,37 @@
1
+ """
2
+ Human approval node.
3
+ Pauses the workflow and waits for human input via stdin (CLI) or sets
4
+ approved=False automatically in non-interactive environments.
5
+ """
6
+ import sys
7
+ from typing import Dict
8
+ from langchain_core.messages import AIMessage
9
+ from acra.graph.state import AgentState
10
+
11
+
12
+ def human_node(state: AgentState) -> Dict:
13
+ """
14
+ Human-in-the-loop approval node.
15
+ In a TTY environment, prompts the user. Otherwise auto-denies.
16
+ """
17
+ reason = state.get("critic_feedback", "Agent requested human review.")
18
+ print(f"\n[HUMAN APPROVAL REQUIRED]\n{reason}\n")
19
+
20
+ approved = False
21
+ feedback = ""
22
+
23
+ if sys.stdin.isatty():
24
+ answer = input("Approve? (y/n): ").strip().lower()
25
+ approved = answer == "y"
26
+ if not approved:
27
+ feedback = input("Feedback (optional): ").strip()
28
+ else:
29
+ print("Non-interactive environment — auto-denying.")
30
+
31
+ return {
32
+ "messages": [AIMessage(content=f"Human node: {'Approved' if approved else 'Denied'}.")],
33
+ "approved": approved,
34
+ "human_feedback": feedback,
35
+ "next_agent": "coder" if approved else "end",
36
+ "current_agent": "human",
37
+ }
acra/agents/llm.py ADDED
@@ -0,0 +1,263 @@
1
+ """
2
+ LLM initialisation for OmniAgent.
3
+ Supports multiple LLM providers: Google Gemini, OpenAI, Groq, Ollama, HuggingFace.
4
+ Cached as a singleton — calling llm() multiple times returns the same instance.
5
+ """
6
+ import functools
7
+ import os
8
+ from pathlib import Path
9
+ from typing import TYPE_CHECKING, Union
10
+
11
+ from dotenv import load_dotenv
12
+
13
+ load_dotenv()
14
+
15
+ # Import provider-specific modules
16
+ from langchain_google_genai import ChatGoogleGenerativeAI
17
+
18
+ try:
19
+ from langchain_openai import ChatOpenAI
20
+ OPENAI_AVAILABLE = True
21
+ except ImportError:
22
+ ChatOpenAI = None
23
+ OPENAI_AVAILABLE = False
24
+
25
+ try:
26
+ from langchain_groq import ChatGroq
27
+ GROQ_AVAILABLE = True
28
+ except ImportError:
29
+ ChatGroq = None
30
+ GROQ_AVAILABLE = False
31
+
32
+ # HuggingFace imports (handled gracefully if not installed)
33
+ try:
34
+ from langchain_huggingface import HuggingFaceEndpoint, ChatHuggingFace
35
+ from langchain_huggingface.llms import HuggingFacePipeline
36
+ HF_AVAILABLE = True
37
+ except ImportError:
38
+ HuggingFaceEndpoint = None
39
+ ChatHuggingFace = None
40
+ HuggingFacePipeline = None
41
+ HF_AVAILABLE = False
42
+
43
+ # Ollama imports (handled gracefully if not installed)
44
+ try:
45
+ from langchain_ollama import OllamaLLM
46
+ OLLAMA_AVAILABLE = True
47
+ except ImportError:
48
+ OllamaLLM = None
49
+ OLLAMA_AVAILABLE = False
50
+
51
+ if TYPE_CHECKING:
52
+ from langchain_google_genai import ChatGoogleGenerativeAI
53
+ from langchain_openai import ChatOpenAI
54
+ from langchain_groq import ChatGroq
55
+ from langchain_ollama import OllamaLLM
56
+ from langchain_huggingface import ChatHuggingFace
57
+ from langchain_huggingface.llms import HuggingFacePipeline
58
+
59
+ from acra.config import (
60
+ LLM_PROVIDER, LLM_TEMPERATURE,
61
+ GEMINI_MODEL,
62
+ OPENAI_MODEL,
63
+ GROQ_MODEL,
64
+ OLLAMA_MODEL, OLLAMA_BASE_URL,
65
+ HF_MODEL, HF_DEVICE, HF_LOCAL_REPO,
66
+ )
67
+
68
+
69
+ class LLMInitializationError(Exception):
70
+ """Raised when LLM initialization fails."""
71
+ pass
72
+
73
+
74
+ def _init_gemini():
75
+ """Initialize Google Gemini LLM."""
76
+ gemini_api_key = os.getenv("GOOGLE_GEMINI_API_KEY") or os.getenv("GEMINI_API_KEY")
77
+ if not gemini_api_key or gemini_api_key.startswith("your_"):
78
+ raise EnvironmentError(
79
+ "GEMINI_API_KEY is not set. Add GOOGLE_GEMINI_API_KEY to your .env file."
80
+ )
81
+ os.environ["GOOGLE_API_KEY"] = gemini_api_key
82
+ return ChatGoogleGenerativeAI(
83
+ model=GEMINI_MODEL,
84
+ temperature=LLM_TEMPERATURE
85
+ )
86
+
87
+
88
+ def _init_openai():
89
+ """Initialize OpenAI LLM."""
90
+ if not OPENAI_AVAILABLE:
91
+ raise LLMInitializationError(
92
+ "OpenAI support is not installed. Install with: pip install langchain-openai"
93
+ )
94
+ openai_api_key = os.getenv("OPENAI_API_KEY")
95
+ if not openai_api_key or openai_api_key.startswith("your_"):
96
+ raise LLMInitializationError(
97
+ "OPENAI_API_KEY is not set. Add OPENAI_API_KEY to your .env file."
98
+ )
99
+ return ChatOpenAI(
100
+ model=OPENAI_MODEL,
101
+ api_key=openai_api_key,
102
+ temperature=LLM_TEMPERATURE
103
+ )
104
+
105
+
106
+ def _init_groq():
107
+ """Initialize Groq LLM."""
108
+ if not GROQ_AVAILABLE:
109
+ raise LLMInitializationError(
110
+ "Groq support is not installed. Install with: pip install langchain-groq"
111
+ )
112
+ groq_api_key = os.getenv("GROQ_API_KEY")
113
+ if not groq_api_key or groq_api_key.startswith("your_"):
114
+ raise LLMInitializationError(
115
+ "GROQ_API_KEY is not set. Add GROQ_API_KEY to your .env file."
116
+ )
117
+ return ChatGroq(
118
+ model=GROQ_MODEL,
119
+ api_key=groq_api_key,
120
+ temperature=LLM_TEMPERATURE
121
+ )
122
+
123
+
124
+ def _init_ollama():
125
+ """Initialize Ollama LLM (local inference)."""
126
+ if not OLLAMA_AVAILABLE:
127
+ raise LLMInitializationError(
128
+ "Ollama not installed. Install with: pip install langchain-ollama"
129
+ )
130
+
131
+ try:
132
+ # Test connection
133
+ llm = OllamaLLM(
134
+ model=OLLAMA_MODEL,
135
+ base_url=OLLAMA_BASE_URL,
136
+ temperature=LLM_TEMPERATURE
137
+ )
138
+ return llm
139
+ except Exception as e:
140
+ raise LLMInitializationError(
141
+ f"Failed to connect to Ollama at {OLLAMA_BASE_URL}. "
142
+ f"Ensure Ollama is running with: ollama serve\nError: {e}"
143
+ )
144
+
145
+
146
+ def _init_huggingface_cloud():
147
+ """Initialize HuggingFace cloud-based LLM (via API)."""
148
+ if not HF_AVAILABLE:
149
+ raise LLMInitializationError(
150
+ "HuggingFace not installed. Install with: pip install langchain-huggingface"
151
+ )
152
+
153
+ huggingface_api_key = os.getenv("HF_API_KEY")
154
+ if not huggingface_api_key or huggingface_api_key.startswith("your_"):
155
+ raise LLMInitializationError(
156
+ "HF_API_KEY is not set. Add HF_API_KEY to your .env file. "
157
+ "Get a token at: https://huggingface.co/settings/tokens"
158
+ )
159
+
160
+ endpoint = HuggingFaceEndpoint(
161
+ repo_id=HF_MODEL,
162
+ huggingfacehub_api_token=huggingface_api_key,
163
+ temperature=LLM_TEMPERATURE
164
+ )
165
+
166
+ return ChatHuggingFace(llm=endpoint)
167
+
168
+
169
+ def _init_huggingface_local():
170
+ """Initialize HuggingFace local model (requires transformers & torch)."""
171
+ if not HF_AVAILABLE:
172
+ raise LLMInitializationError(
173
+ "HuggingFace not installed. Install with: pip install langchain-huggingface"
174
+ )
175
+
176
+ try:
177
+ from transformers import pipeline
178
+
179
+ # Create local repo directory
180
+ repo_path = Path(HF_LOCAL_REPO)
181
+ repo_path.mkdir(parents=True, exist_ok=True)
182
+
183
+ # Initialize pipeline
184
+ pipe = pipeline(
185
+ "text-generation",
186
+ model=HF_MODEL,
187
+ device=0 if HF_DEVICE == "cuda" else -1, # 0 for GPU, -1 for CPU
188
+ model_kwargs={"cache_dir": str(repo_path)}
189
+ )
190
+
191
+ llm = HuggingFacePipeline(
192
+ model_id=HF_MODEL,
193
+ task="text-generation",
194
+ pipeline=pipe
195
+ )
196
+ return llm
197
+ except ImportError as e:
198
+ raise LLMInitializationError(
199
+ f"HuggingFace local model requires transformers and torch. "
200
+ f"Install with: pip install transformers torch\nError: {e}"
201
+ )
202
+ except Exception as e:
203
+ raise LLMInitializationError(
204
+ f"Failed to initialize HuggingFace local model {HF_MODEL}. "
205
+ f"Error: {e}"
206
+ )
207
+
208
+
209
+ @functools.lru_cache(maxsize=32)
210
+ def _get_cached_llm(
211
+ provider: str,
212
+ gemini_api_key: str,
213
+ openai_api_key: str,
214
+ groq_api_key: str,
215
+ hf_api_key: str,
216
+ ollama_model: str,
217
+ ollama_base_url: str,
218
+ hf_model: str,
219
+ hf_device: str,
220
+ hf_local_repo: str,
221
+ temperature: str,
222
+ ):
223
+ if provider == "gemini":
224
+ return _init_gemini()
225
+ if provider == "openai":
226
+ return _init_openai()
227
+ if provider == "groq":
228
+ return _init_groq()
229
+ if provider == "ollama":
230
+ return _init_ollama()
231
+ if provider == "huggingface_local":
232
+ return _init_huggingface_local()
233
+ if provider == "huggingface_cloud":
234
+ return _init_huggingface_cloud()
235
+ raise LLMInitializationError(
236
+ f"Unknown LLM_PROVIDER: {provider}. "
237
+ f"Supported providers: gemini, openai, groq, ollama, huggingface_local, huggingface_cloud"
238
+ )
239
+
240
+
241
+ def llm() -> Union[
242
+ "ChatGoogleGenerativeAI",
243
+ "ChatOpenAI",
244
+ "ChatGroq",
245
+ "OllamaLLM",
246
+ "ChatHuggingFace",
247
+ "HuggingFacePipeline",
248
+ ]:
249
+ """Return a cached LLM instance based on the current provider configuration."""
250
+ provider = os.getenv("LLM_PROVIDER", LLM_PROVIDER).lower().strip()
251
+ return _get_cached_llm(
252
+ provider,
253
+ os.getenv("GOOGLE_GEMINI_API_KEY") or os.getenv("GEMINI_API_KEY"),
254
+ os.getenv("OPENAI_API_KEY"),
255
+ os.getenv("GROQ_API_KEY"),
256
+ os.getenv("HF_API_KEY"),
257
+ os.getenv("OLLAMA_MODEL", OLLAMA_MODEL),
258
+ os.getenv("OLLAMA_BASE_URL", OLLAMA_BASE_URL),
259
+ os.getenv("HF_MODEL", HF_MODEL),
260
+ os.getenv("HF_DEVICE", HF_DEVICE),
261
+ os.getenv("HF_LOCAL_REPO", HF_LOCAL_REPO),
262
+ str(LLM_TEMPERATURE),
263
+ )
@@ -0,0 +1,161 @@
1
+ """
2
+ LLM provider utilities for testing and debugging.
3
+ Run with: python -m agents.llm_utils
4
+ """
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ # Add project root to path
9
+ sys.path.insert(0, str(Path(__file__).parent.parent))
10
+
11
+ from acra.agents.llm import llm, LLMInitializationError
12
+ from acra.config import (
13
+ LLM_PROVIDER, LLM_TEMPERATURE,
14
+ GEMINI_API_KEY, OPENAI_API_KEY, GROQ_API_KEY,
15
+ HF_API_KEY, OLLAMA_BASE_URL, HF_MODEL, OLLAMA_MODEL
16
+ )
17
+
18
+
19
+ def print_config():
20
+ """Print current LLM configuration."""
21
+ print("\n" + "="*60)
22
+ print("OmniAgent LLM Configuration")
23
+ print("="*60)
24
+ print(f"\nProvider: {LLM_PROVIDER}")
25
+ print(f"Temperature: {LLM_TEMPERATURE}")
26
+
27
+ print("\n" + "-"*60)
28
+ print("Credentials Status:")
29
+ print("-"*60)
30
+ print(f"Gemini API Key: {'✓ Set' if GEMINI_API_KEY else '✗ Not set'}")
31
+ print(f"OpenAI API Key: {'✓ Set' if OPENAI_API_KEY else '✗ Not set'}")
32
+ print(f"Groq API Key: {'✓ Set' if GROQ_API_KEY else '✗ Not set'}")
33
+ print(f"HuggingFace Token: {'✓ Set' if HF_API_KEY else '✗ Not set'}")
34
+
35
+ print("\n" + "-"*60)
36
+ print("Provider-Specific Config:")
37
+ print("-"*60)
38
+ print(f"Ollama Base URL: {OLLAMA_BASE_URL}")
39
+ print(f"Ollama Model: {OLLAMA_MODEL}")
40
+ print(f"HuggingFace Model: {HF_MODEL}")
41
+
42
+
43
+ def test_provider():
44
+ """Test if the current LLM provider works."""
45
+ print("\n" + "="*60)
46
+ print(f"Testing LLM Provider: {LLM_PROVIDER}")
47
+ print("="*60 + "\n")
48
+
49
+ try:
50
+ print(f"Initializing {LLM_PROVIDER} provider...", end=" ")
51
+ llm_instance = llm()
52
+ print("✓ Success!\n")
53
+
54
+ print(f"Provider type: {type(llm_instance).__name__}")
55
+ print(f"Model: {getattr(llm_instance, 'model_name', getattr(llm_instance, 'model', 'Unknown'))}")
56
+
57
+ # Test a simple prompt
58
+ print("\nTesting with simple prompt: 'Say hello'")
59
+ print("-"*60)
60
+ response = llm_instance.invoke("Say hello in one sentence.")
61
+ print(response.content if hasattr(response, 'content') else str(response))
62
+ print("-"*60)
63
+ print("\n✓ Provider test successful!")
64
+ return True
65
+
66
+ except LLMInitializationError as e:
67
+ print(f"\n✗ Initialization Error:\n{e}")
68
+ return False
69
+ except Exception as e:
70
+ print(f"\n✗ Error: {e}")
71
+ print("\nTroubleshooting tips:")
72
+ if "connection" in str(e).lower():
73
+ print("- Check your internet connection")
74
+ print("- Verify the API endpoint is accessible")
75
+ if "key" in str(e).lower() or "auth" in str(e).lower():
76
+ print("- Verify your API credentials in .env file")
77
+ print("\nFor more help, see docs/LLM_PROVIDER_GUIDE.md")
78
+ return False
79
+
80
+
81
+ def list_providers():
82
+ """List all available providers and their status."""
83
+ print("\n" + "="*60)
84
+ print("Available LLM Providers")
85
+ print("="*60 + "\n")
86
+
87
+ providers = {
88
+ "gemini": {
89
+ "description": "Google Gemini API",
90
+ "credential_env": "GOOGLE_GEMINI_API_KEY",
91
+ "setup": "https://aistudio.google.com/app/apikeys"
92
+ },
93
+ "openai": {
94
+ "description": "OpenAI GPT models",
95
+ "credential_env": "OPENAI_API_KEY",
96
+ "setup": "https://platform.openai.com/api-keys"
97
+ },
98
+ "groq": {
99
+ "description": "Groq API (fastest inference)",
100
+ "credential_env": "GROQ_API_KEY",
101
+ "setup": "https://console.groq.com/keys"
102
+ },
103
+ "ollama": {
104
+ "description": "Local Ollama inference",
105
+ "credential_env": "None (local)",
106
+ "setup": "https://ollama.ai"
107
+ },
108
+ "huggingface_local": {
109
+ "description": "Local HuggingFace models",
110
+ "credential_env": "None (local)",
111
+ "setup": "pip install transformers torch"
112
+ },
113
+ "huggingface_cloud": {
114
+ "description": "HuggingFace Inference API",
115
+ "credential_env": "HF_API_KEY",
116
+ "setup": "https://huggingface.co/settings/tokens"
117
+ }
118
+ }
119
+
120
+ for name, info in providers.items():
121
+ is_current = "← CURRENT" if name == LLM_PROVIDER.lower() else ""
122
+ print(f"{name.upper()} {is_current}")
123
+ print(f" Description: {info['description']}")
124
+ print(f" Credential: {info['credential_env']}")
125
+ print(f" Setup: {info['setup']}")
126
+ print()
127
+
128
+
129
+ def main():
130
+ """Run diagnostic utilities."""
131
+ import argparse
132
+
133
+ parser = argparse.ArgumentParser(
134
+ description="OmniAgent LLM Provider Utilities"
135
+ )
136
+ parser.add_argument(
137
+ "command",
138
+ choices=["config", "test", "list"],
139
+ help="Command to run"
140
+ )
141
+
142
+ args = parser.parse_args()
143
+
144
+ if args.command == "config":
145
+ print_config()
146
+ elif args.command == "test":
147
+ success = test_provider()
148
+ sys.exit(0 if success else 1)
149
+ elif args.command == "list":
150
+ list_providers()
151
+
152
+
153
+ if __name__ == "__main__":
154
+ if len(sys.argv) < 2:
155
+ print(__doc__)
156
+ print("\nUsage:")
157
+ print(" python -m agents.llm_utils config # Show current configuration")
158
+ print(" python -m agents.llm_utils test # Test the current provider")
159
+ print(" python -m agents.llm_utils list # List all available providers")
160
+ else:
161
+ main()
File without changes
@@ -0,0 +1,239 @@
1
+ from typing import Dict
2
+
3
+ from langchain_core.messages import AIMessage
4
+
5
+ from acra.graph.state import AgentState
6
+
7
+ from acra.agents.memory.memory_manager import (
8
+ get_memory_manager
9
+ )
10
+
11
+ from acra.agents.memory.retrieval import (
12
+ get_memory_retrieval
13
+ )
14
+
15
+
16
+ def memory_agent(state: AgentState) -> Dict:
17
+ """
18
+ Memory Agent
19
+
20
+ Responsibilities:
21
+ - Persist workflow memories
22
+ - Store successful execution patterns
23
+ - Store runtime failures
24
+ - Build historical context
25
+ - Retrieve relevant memories
26
+ - Support long-term autonomous reasoning
27
+ """
28
+
29
+ # extract state
30
+
31
+ session_id = state.get(
32
+ "session_id",
33
+ "default_session"
34
+ )
35
+
36
+ user_request = state.get(
37
+ "user_request",
38
+ ""
39
+ )
40
+
41
+ current_step = state.get(
42
+ "current_step",
43
+ ""
44
+ )
45
+
46
+ workflow_status = state.get(
47
+ "workflow_status",
48
+ ""
49
+ )
50
+
51
+ execution_success = state.get(
52
+ "execution_success",
53
+ False
54
+ )
55
+
56
+ execution_logs = state.get(
57
+ "execution_logs",
58
+ ""
59
+ )
60
+
61
+ error_message = state.get(
62
+ "error_message",
63
+ ""
64
+ )
65
+
66
+ generated_files = state.get(
67
+ "generated_files",
68
+ {}
69
+ )
70
+
71
+ critic_feedback = state.get(
72
+ "critic_feedback",
73
+ ""
74
+ )
75
+
76
+ quality_score = state.get(
77
+ "quality_score",
78
+ 0
79
+ )
80
+
81
+ retry_count = state.get(
82
+ "retry_count",
83
+ 0
84
+ )
85
+
86
+ next_agent = state.get(
87
+ "next_agent",
88
+ "end"
89
+ )
90
+
91
+
92
+ # initialize memory manager and retrieval system
93
+
94
+ memory_manager = get_memory_manager(
95
+ session_id=session_id
96
+ )
97
+
98
+ retrieval_system = get_memory_retrieval(
99
+ session_id=session_id
100
+ )
101
+
102
+
103
+ # determine memory type
104
+
105
+ if execution_success and quality_score >= 8:
106
+
107
+ memory_type = "successful_execution"
108
+
109
+ elif error_message:
110
+
111
+ memory_type = "execution_failure"
112
+
113
+ elif critic_feedback:
114
+
115
+ memory_type = "critic_feedback"
116
+
117
+ else:
118
+
119
+ memory_type = "workflow_context"
120
+
121
+
122
+ # build memory content
123
+
124
+ memory_content = {
125
+
126
+ "user_request": user_request,
127
+
128
+ "current_step": current_step,
129
+
130
+ "workflow_status": workflow_status,
131
+
132
+ "execution_success": execution_success,
133
+
134
+ "quality_score": quality_score,
135
+
136
+ "retry_count": retry_count,
137
+
138
+ "error_message": error_message,
139
+
140
+ "critic_feedback": critic_feedback,
141
+
142
+ "generated_files": list(
143
+ generated_files.keys()
144
+ ),
145
+
146
+ "execution_logs": (
147
+ execution_logs[:2000]
148
+ if execution_logs
149
+ else ""
150
+ )
151
+ }
152
+
153
+
154
+ # store memory
155
+
156
+ memory_manager.add_memory(
157
+ memory_type=memory_type,
158
+ content=memory_content
159
+ )
160
+
161
+
162
+ # retrieve relevant memories for context building
163
+
164
+ relevant_memories = (
165
+ retrieval_system.get_relevant_memories(
166
+ query=user_request,
167
+ limit=3
168
+ )
169
+ )
170
+
171
+
172
+ # retrieve similar past failures if current execution failed
173
+
174
+ similar_failures = []
175
+
176
+ if error_message:
177
+
178
+ similar_failures = (
179
+ retrieval_system.get_error_solutions(
180
+ error_message=error_message,
181
+ limit=3
182
+ )
183
+ )
184
+
185
+
186
+ # memory statistics
187
+
188
+ memory_stats = (
189
+ retrieval_system.get_memory_insights()
190
+ )
191
+
192
+
193
+ # build memory message
194
+
195
+ if execution_success:
196
+
197
+ memory_message = (
198
+ "🧠 Memory Agent: "
199
+ "Stored successful execution pattern "
200
+ "for future optimization."
201
+ )
202
+
203
+ elif error_message:
204
+
205
+ memory_message = (
206
+ "🛠️ Memory Agent: "
207
+ "Stored runtime failure and "
208
+ "retrieved similar debugging history."
209
+ )
210
+
211
+ else:
212
+
213
+ memory_message = (
214
+ "📚 Memory Agent: "
215
+ "Workflow context stored successfully."
216
+ )
217
+
218
+
219
+ # return updated state
220
+
221
+ return {
222
+
223
+ "messages": [
224
+ AIMessage(content=memory_message)
225
+ ],
226
+
227
+ # Memory Storage
228
+ "memory_type": memory_type,
229
+
230
+ "memory_stats": memory_stats,
231
+
232
+ # Retrieved Context
233
+ "memory_context": relevant_memories,
234
+
235
+ "similar_failures": similar_failures,
236
+
237
+ # Workflow
238
+ "next_agent": next_agent,
239
+ }