praisonAI 2.3.76__tar.gz → 2.3.77__tar.gz
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.
- {praisonai-2.3.76 → praisonai-2.3.77}/PKG-INFO +1 -1
- {praisonai-2.3.76 → praisonai-2.3.77}/PraisonAI.egg-info/PKG-INFO +1 -1
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/at_mentions.py +69 -14
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/eval.py +55 -17
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/fast_context.py +13 -5
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/guardrail.py +7 -1
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/main.py +27 -27
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/deploy.py +1 -1
- praisonai-2.3.77/praisonai/version.py +1 -0
- praisonai-2.3.76/praisonai/version.py +0 -1
- {praisonai-2.3.76 → praisonai-2.3.77}/PraisonAI.egg-info/SOURCES.txt +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/PraisonAI.egg-info/dependency_links.txt +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/PraisonAI.egg-info/entry_points.txt +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/PraisonAI.egg-info/requires.txt +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/PraisonAI.egg-info/top_level.txt +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/README.md +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/__main__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/agent_scheduler.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/agents_generator.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/api/call.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/auto.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/chainlit_ui.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/agent_scheduler.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/auto_memory.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/autonomy_mode.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/base.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/compare.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/cost_tracker.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/external_agents.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/flow_display.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/git_integration.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/handoff.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/image.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/interactive_tui.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/knowledge.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/mcp.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/message_queue.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/metrics.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/n8n.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/profiling.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/repo_map.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/router.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/sandbox_executor.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/session.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/skills.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/slash_commands.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/telemetry.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/todo.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/tools.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/features/workflow.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/cli/schedule_cli.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/agent_tools.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/diff/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/diff/diff_strategy.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/tools/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/tools/apply_diff.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/tools/execute_command.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/tools/list_files.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/tools/read_file.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/tools/search_replace.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/tools/write_file.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/utils/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/utils/file_utils.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/utils/ignore_utils.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/code/utils/text_utils.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/inbuilt_tools/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/inbuilt_tools/autogen_tools.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/inc/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/inc/config.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/inc/models.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/integrations/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/integrations/base.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/integrations/claude_code.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/integrations/codex_cli.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/integrations/cursor_cli.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/integrations/gemini_cli.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/profiler.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/scheduler/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/scheduler/agent_scheduler.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/scheduler/base.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/scheduler/daemon_manager.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/scheduler/state_manager.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/scheduler/yaml_loader.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/scheduler.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/setup/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/setup/build.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/setup/post_install.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/setup/setup_conda_env.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/setup.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/test.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/train.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/train_vision.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/agents.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/callbacks.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/chat.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/code.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/colab.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/colab_chainlit.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/components/aicoder.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/context.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/database_config.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/db.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/realtime.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/realtimeclient/__init__.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/realtimeclient/tools.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/ui/sql_alchemy.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/praisonai/upload_vision.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/pyproject.toml +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/setup.cfg +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/tests/test.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/tests/test_agents_playbook.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/tests/test_approval_system.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/tests/test_basic.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/tests/test_cli_features.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/tests/test_custom_tools_fix.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/tests/test_double_api_fix.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/tests/test_n8n_integration.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/tests/test_phase2_refactor.py +0 -0
- {praisonai-2.3.76 → praisonai-2.3.77}/tests/test_runner.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PraisonAI
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.77
|
|
4
4
|
Summary: PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration.
|
|
5
5
|
Author: Mervin Praison
|
|
6
6
|
License: MIT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PraisonAI
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.77
|
|
4
4
|
Summary: PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration.
|
|
5
5
|
Author: Mervin Praison
|
|
6
6
|
License: MIT
|
|
@@ -105,6 +105,7 @@ class FileSearchService:
|
|
|
105
105
|
- Fuzzy match file paths
|
|
106
106
|
- Cache results with TTL
|
|
107
107
|
- Respect .gitignore (basic)
|
|
108
|
+
- Support absolute paths (@/Users/...) and home paths (@~/...)
|
|
108
109
|
"""
|
|
109
110
|
|
|
110
111
|
def __init__(
|
|
@@ -125,9 +126,10 @@ class FileSearchService:
|
|
|
125
126
|
# Cache: query -> (results, timestamp)
|
|
126
127
|
self._cache: Dict[str, Tuple[List[FileSuggestion], float]] = {}
|
|
127
128
|
|
|
128
|
-
# File list cache
|
|
129
|
+
# File list cache per directory
|
|
129
130
|
self._file_list: Optional[List[str]] = None
|
|
130
131
|
self._file_list_time: float = 0
|
|
132
|
+
self._file_list_dir: Optional[str] = None
|
|
131
133
|
|
|
132
134
|
def _should_ignore(self, name: str) -> bool:
|
|
133
135
|
"""Check if file/dir should be ignored."""
|
|
@@ -136,20 +138,23 @@ class FileSearchService:
|
|
|
136
138
|
return True
|
|
137
139
|
return False
|
|
138
140
|
|
|
139
|
-
def _get_file_list(self) -> List[str]:
|
|
141
|
+
def _get_file_list(self, search_dir: str = None) -> List[str]:
|
|
140
142
|
"""Get list of all files (cached)."""
|
|
141
143
|
now = time.time()
|
|
144
|
+
target_dir = search_dir or self._root
|
|
142
145
|
|
|
143
|
-
# Return cached if fresh
|
|
144
|
-
if self._file_list is not None and
|
|
146
|
+
# Return cached if fresh and same directory
|
|
147
|
+
if (self._file_list is not None and
|
|
148
|
+
self._file_list_dir == target_dir and
|
|
149
|
+
(now - self._file_list_time) < self._cache_ttl):
|
|
145
150
|
return self._file_list
|
|
146
151
|
|
|
147
152
|
files = []
|
|
148
153
|
|
|
149
154
|
try:
|
|
150
|
-
for root, dirs, filenames in os.walk(
|
|
155
|
+
for root, dirs, filenames in os.walk(target_dir):
|
|
151
156
|
# Calculate depth
|
|
152
|
-
rel_root = os.path.relpath(root,
|
|
157
|
+
rel_root = os.path.relpath(root, target_dir)
|
|
153
158
|
depth = 0 if rel_root == '.' else rel_root.count(os.sep) + 1
|
|
154
159
|
|
|
155
160
|
if depth > self._max_depth:
|
|
@@ -161,19 +166,20 @@ class FileSearchService:
|
|
|
161
166
|
|
|
162
167
|
# Add directories
|
|
163
168
|
for d in dirs:
|
|
164
|
-
rel_path = os.path.relpath(os.path.join(root, d),
|
|
169
|
+
rel_path = os.path.relpath(os.path.join(root, d), target_dir)
|
|
165
170
|
files.append(rel_path + os.sep)
|
|
166
171
|
|
|
167
172
|
# Add files
|
|
168
173
|
for f in filenames:
|
|
169
174
|
if not self._should_ignore(f):
|
|
170
|
-
rel_path = os.path.relpath(os.path.join(root, f),
|
|
175
|
+
rel_path = os.path.relpath(os.path.join(root, f), target_dir)
|
|
171
176
|
files.append(rel_path)
|
|
172
177
|
except OSError:
|
|
173
178
|
pass
|
|
174
179
|
|
|
175
180
|
self._file_list = files
|
|
176
181
|
self._file_list_time = now
|
|
182
|
+
self._file_list_dir = target_dir
|
|
177
183
|
return files
|
|
178
184
|
|
|
179
185
|
def _fuzzy_match(self, text: str, query: str) -> int:
|
|
@@ -221,6 +227,11 @@ class FileSearchService:
|
|
|
221
227
|
"""
|
|
222
228
|
Search for files matching query.
|
|
223
229
|
|
|
230
|
+
Supports:
|
|
231
|
+
- Relative paths: @file.txt, @src/main.py
|
|
232
|
+
- Home paths: @~/Documents, @~/.config
|
|
233
|
+
- Absolute paths: @/Users/name/file.txt, @/etc/hosts
|
|
234
|
+
|
|
224
235
|
Args:
|
|
225
236
|
query: Search query (fuzzy matched)
|
|
226
237
|
max_results: Maximum results to return
|
|
@@ -228,8 +239,51 @@ class FileSearchService:
|
|
|
228
239
|
Returns:
|
|
229
240
|
List of FileSuggestion sorted by score
|
|
230
241
|
"""
|
|
242
|
+
# Determine search directory based on query
|
|
243
|
+
search_dir = self._root
|
|
244
|
+
search_query = query
|
|
245
|
+
prefix = ""
|
|
246
|
+
|
|
247
|
+
# Handle home directory paths (@~/)
|
|
248
|
+
if query.startswith('~'):
|
|
249
|
+
expanded = os.path.expanduser(query)
|
|
250
|
+
# Find the directory part and filename part
|
|
251
|
+
if os.path.isdir(expanded):
|
|
252
|
+
search_dir = expanded
|
|
253
|
+
search_query = ""
|
|
254
|
+
prefix = query.rstrip('/') + '/'
|
|
255
|
+
else:
|
|
256
|
+
parent = os.path.dirname(expanded)
|
|
257
|
+
if os.path.isdir(parent):
|
|
258
|
+
search_dir = parent
|
|
259
|
+
search_query = os.path.basename(expanded)
|
|
260
|
+
prefix = os.path.dirname(query).rstrip('/') + '/'
|
|
261
|
+
else:
|
|
262
|
+
# Just expand ~ and search from home
|
|
263
|
+
search_dir = os.path.expanduser('~')
|
|
264
|
+
search_query = query[2:] if query.startswith('~/') else query[1:]
|
|
265
|
+
prefix = "~/"
|
|
266
|
+
|
|
267
|
+
# Handle absolute paths (@/Users/..., @/etc/...)
|
|
268
|
+
elif query.startswith('/'):
|
|
269
|
+
if os.path.isdir(query):
|
|
270
|
+
search_dir = query
|
|
271
|
+
search_query = ""
|
|
272
|
+
prefix = query.rstrip('/') + '/'
|
|
273
|
+
else:
|
|
274
|
+
parent = os.path.dirname(query)
|
|
275
|
+
if os.path.isdir(parent):
|
|
276
|
+
search_dir = parent
|
|
277
|
+
search_query = os.path.basename(query)
|
|
278
|
+
prefix = parent.rstrip('/') + '/'
|
|
279
|
+
else:
|
|
280
|
+
# Search from root with the query
|
|
281
|
+
search_dir = '/'
|
|
282
|
+
search_query = query[1:]
|
|
283
|
+
prefix = "/"
|
|
284
|
+
|
|
231
285
|
# Check cache
|
|
232
|
-
cache_key = f"{
|
|
286
|
+
cache_key = f"{search_dir}:{search_query}:{max_results}"
|
|
233
287
|
now = time.time()
|
|
234
288
|
|
|
235
289
|
if cache_key in self._cache:
|
|
@@ -237,25 +291,26 @@ class FileSearchService:
|
|
|
237
291
|
if (now - cached_time) < self._cache_ttl:
|
|
238
292
|
return results
|
|
239
293
|
|
|
240
|
-
# Get all files
|
|
241
|
-
all_files = self._get_file_list()
|
|
294
|
+
# Get all files from the appropriate directory
|
|
295
|
+
all_files = self._get_file_list(search_dir)
|
|
242
296
|
|
|
243
297
|
# Score and filter
|
|
244
298
|
scored: List[Tuple[int, str]] = []
|
|
245
299
|
for path in all_files:
|
|
246
|
-
score = self._fuzzy_match(path,
|
|
300
|
+
score = self._fuzzy_match(path, search_query)
|
|
247
301
|
if score > 0:
|
|
248
302
|
scored.append((score, path))
|
|
249
303
|
|
|
250
304
|
# Sort by score descending
|
|
251
305
|
scored.sort(key=lambda x: (-x[0], x[1]))
|
|
252
306
|
|
|
253
|
-
# Build results
|
|
307
|
+
# Build results with proper prefix
|
|
254
308
|
results = []
|
|
255
309
|
for score, path in scored[:max_results]:
|
|
256
310
|
file_type = "directory" if path.endswith(os.sep) else "file"
|
|
311
|
+
display_path = prefix + path if prefix else path
|
|
257
312
|
results.append(FileSuggestion(
|
|
258
|
-
path=
|
|
313
|
+
path=display_path,
|
|
259
314
|
file_type=file_type,
|
|
260
315
|
score=score
|
|
261
316
|
))
|
|
@@ -26,42 +26,68 @@ class EvalHandler:
|
|
|
26
26
|
|
|
27
27
|
def run_accuracy(
|
|
28
28
|
self,
|
|
29
|
-
agent_file: str,
|
|
30
|
-
input_text: str,
|
|
31
|
-
expected_output: str,
|
|
29
|
+
agent_file: Optional[str] = None,
|
|
30
|
+
input_text: str = "",
|
|
31
|
+
expected_output: str = "",
|
|
32
32
|
iterations: int = 1,
|
|
33
33
|
model: Optional[str] = None,
|
|
34
|
-
output_file: Optional[str] = None
|
|
34
|
+
output_file: Optional[str] = None,
|
|
35
|
+
prompt: Optional[str] = None,
|
|
36
|
+
llm: Optional[str] = None
|
|
35
37
|
) -> Dict[str, Any]:
|
|
36
38
|
"""
|
|
37
39
|
Run accuracy evaluation on an agent.
|
|
38
40
|
|
|
39
41
|
Args:
|
|
40
|
-
agent_file: Path to agents.yaml file
|
|
42
|
+
agent_file: Path to agents.yaml file (optional if prompt is provided)
|
|
41
43
|
input_text: Input to provide to the agent
|
|
42
44
|
expected_output: Expected output to compare against
|
|
43
45
|
iterations: Number of evaluation iterations
|
|
44
46
|
model: LLM model for judging
|
|
45
47
|
output_file: Path to save results
|
|
48
|
+
prompt: Direct prompt (alternative to agent_file)
|
|
49
|
+
llm: LLM model for the agent (when using prompt)
|
|
46
50
|
|
|
47
51
|
Returns:
|
|
48
52
|
Evaluation result dictionary
|
|
49
53
|
"""
|
|
50
54
|
try:
|
|
51
55
|
from praisonaiagents.eval import AccuracyEvaluator
|
|
52
|
-
from
|
|
56
|
+
from praisonaiagents import Agent
|
|
53
57
|
except ImportError as e:
|
|
54
58
|
logger.error(f"Failed to import evaluation modules: {e}")
|
|
55
59
|
return {"error": str(e)}
|
|
56
60
|
|
|
57
61
|
try:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
# Create agent either from file or from prompt
|
|
63
|
+
if prompt:
|
|
64
|
+
# Direct prompt mode - create agent on the fly
|
|
65
|
+
agent = Agent(
|
|
66
|
+
name="EvalAgent",
|
|
67
|
+
role="Assistant",
|
|
68
|
+
goal="Complete the given task",
|
|
69
|
+
backstory="You are a helpful assistant.",
|
|
70
|
+
llm=llm or model or "gpt-4o-mini",
|
|
71
|
+
verbose=False
|
|
72
|
+
)
|
|
73
|
+
# Use prompt as input if input_text not provided
|
|
74
|
+
if not input_text:
|
|
75
|
+
input_text = prompt
|
|
76
|
+
elif agent_file:
|
|
77
|
+
# Load from agents.yaml
|
|
78
|
+
try:
|
|
79
|
+
from praisonai.agents_generator import AgentsGenerator
|
|
80
|
+
generator = AgentsGenerator(agent_file)
|
|
81
|
+
agents = generator.generate_agents()
|
|
82
|
+
|
|
83
|
+
if not agents:
|
|
84
|
+
return {"error": "No agents found in configuration"}
|
|
85
|
+
|
|
86
|
+
agent = agents[0] if isinstance(agents, list) else agents
|
|
87
|
+
except Exception as e:
|
|
88
|
+
return {"error": f"Failed to load agents from {agent_file}: {e}"}
|
|
89
|
+
else:
|
|
90
|
+
return {"error": "Either --agent or --prompt must be provided"}
|
|
65
91
|
|
|
66
92
|
evaluator = AccuracyEvaluator(
|
|
67
93
|
agent=agent,
|
|
@@ -331,8 +357,16 @@ def handle_eval_command(args) -> None:
|
|
|
331
357
|
handler = EvalHandler(verbose=getattr(args, 'verbose', False))
|
|
332
358
|
|
|
333
359
|
eval_type = getattr(args, 'eval_type', 'accuracy')
|
|
334
|
-
agent_file = getattr(args, 'agent',
|
|
360
|
+
agent_file = getattr(args, 'agent', None)
|
|
335
361
|
output_file = getattr(args, 'output', None)
|
|
362
|
+
prompt = getattr(args, 'prompt', None)
|
|
363
|
+
llm = getattr(args, 'llm', None)
|
|
364
|
+
|
|
365
|
+
# If no agent file and no prompt, check if agents.yaml exists
|
|
366
|
+
if not agent_file and not prompt:
|
|
367
|
+
import os
|
|
368
|
+
if os.path.exists('agents.yaml'):
|
|
369
|
+
agent_file = 'agents.yaml'
|
|
336
370
|
|
|
337
371
|
if eval_type == 'accuracy':
|
|
338
372
|
result = handler.run_accuracy(
|
|
@@ -341,7 +375,9 @@ def handle_eval_command(args) -> None:
|
|
|
341
375
|
expected_output=getattr(args, 'expected', ''),
|
|
342
376
|
iterations=getattr(args, 'iterations', 1),
|
|
343
377
|
model=getattr(args, 'model', None),
|
|
344
|
-
output_file=output_file
|
|
378
|
+
output_file=output_file,
|
|
379
|
+
prompt=prompt,
|
|
380
|
+
llm=llm
|
|
345
381
|
)
|
|
346
382
|
elif eval_type == 'performance':
|
|
347
383
|
result = handler.run_performance(
|
|
@@ -410,8 +446,10 @@ def add_eval_parser(subparsers) -> None:
|
|
|
410
446
|
'accuracy',
|
|
411
447
|
help='Run accuracy evaluation'
|
|
412
448
|
)
|
|
413
|
-
accuracy_parser.add_argument('--agent', '-a',
|
|
414
|
-
accuracy_parser.add_argument('--
|
|
449
|
+
accuracy_parser.add_argument('--agent', '-a', help='Agent config file (optional if --prompt used)')
|
|
450
|
+
accuracy_parser.add_argument('--prompt', '-p', help='Direct prompt (alternative to --agent)')
|
|
451
|
+
accuracy_parser.add_argument('--llm', help='LLM model for agent (when using --prompt)')
|
|
452
|
+
accuracy_parser.add_argument('--input', '-i', help='Input text (defaults to --prompt if not provided)')
|
|
415
453
|
accuracy_parser.add_argument('--expected', '-e', required=True, help='Expected output')
|
|
416
454
|
accuracy_parser.add_argument('--iterations', '-n', type=int, default=1, help='Number of iterations')
|
|
417
455
|
accuracy_parser.add_argument('--model', '-m', help='Judge model')
|
|
@@ -69,6 +69,9 @@ class FastContextHandler(FlagHandler):
|
|
|
69
69
|
query: Search query
|
|
70
70
|
path: Path to search
|
|
71
71
|
**kwargs: Additional search options
|
|
72
|
+
- use_llm: Use LLM for intelligent search (slower, default: False)
|
|
73
|
+
- max_turns: Max search turns for LLM mode
|
|
74
|
+
- model: LLM model for intelligent search
|
|
72
75
|
|
|
73
76
|
Returns:
|
|
74
77
|
List of matching results
|
|
@@ -86,15 +89,20 @@ class FastContextHandler(FlagHandler):
|
|
|
86
89
|
try:
|
|
87
90
|
from praisonaiagents import FastContext
|
|
88
91
|
|
|
92
|
+
# Use fast non-LLM search by default for better performance
|
|
93
|
+
use_llm = kwargs.get('use_llm', False)
|
|
94
|
+
|
|
89
95
|
fc = FastContext(
|
|
90
|
-
|
|
96
|
+
workspace_path=path,
|
|
91
97
|
model=kwargs.get('model', 'gpt-4o-mini'),
|
|
92
|
-
max_turns=kwargs.get('max_turns',
|
|
93
|
-
|
|
94
|
-
timeout=kwargs.get('timeout',
|
|
98
|
+
max_turns=kwargs.get('max_turns', 2), # Reduced from 4 for speed
|
|
99
|
+
max_parallel=kwargs.get('parallelism', 8),
|
|
100
|
+
timeout=kwargs.get('timeout', 15.0), # Reduced timeout
|
|
101
|
+
verbose=self.verbose
|
|
95
102
|
)
|
|
96
103
|
|
|
97
|
-
|
|
104
|
+
# Use non-LLM search by default (much faster)
|
|
105
|
+
result = fc.search(query, use_llm=use_llm)
|
|
98
106
|
|
|
99
107
|
# Convert to list of dicts
|
|
100
108
|
matches = []
|
|
@@ -75,7 +75,7 @@ class GuardrailHandler(FlagHandler):
|
|
|
75
75
|
|
|
76
76
|
Args:
|
|
77
77
|
description: Natural language description of validation criteria
|
|
78
|
-
llm: Optional LLM instance for validation
|
|
78
|
+
llm: Optional LLM instance for validation (defaults to gpt-4o-mini)
|
|
79
79
|
|
|
80
80
|
Returns:
|
|
81
81
|
LLMGuardrail instance or None if unavailable
|
|
@@ -87,6 +87,12 @@ class GuardrailHandler(FlagHandler):
|
|
|
87
87
|
)
|
|
88
88
|
return None
|
|
89
89
|
|
|
90
|
+
# Provide default LLM if none specified
|
|
91
|
+
if llm is None:
|
|
92
|
+
import os
|
|
93
|
+
# Try to get from environment or use default
|
|
94
|
+
llm = os.environ.get('OPENAI_MODEL_NAME', 'gpt-4o-mini')
|
|
95
|
+
|
|
90
96
|
return LLMGuardrail(description=description, llm=llm)
|
|
91
97
|
|
|
92
98
|
def validate_output(self, output: str, description: str, llm: Any = None) -> Tuple[bool, str]:
|
|
@@ -4741,16 +4741,14 @@ Provide a concise summary (max 200 words):"""
|
|
|
4741
4741
|
|
|
4742
4742
|
def _process_interactive_prompt_async(self, prompt, tools_list, console, session_state=None):
|
|
4743
4743
|
"""
|
|
4744
|
-
Process a prompt asynchronously with
|
|
4744
|
+
Process a prompt asynchronously with non-blocking status display.
|
|
4745
4745
|
|
|
4746
|
-
Shows
|
|
4746
|
+
Shows status updates without blocking user input.
|
|
4747
4747
|
Allows user to queue more messages while processing.
|
|
4748
4748
|
"""
|
|
4749
4749
|
import threading
|
|
4750
4750
|
import time
|
|
4751
|
-
|
|
4752
|
-
from rich.panel import Panel
|
|
4753
|
-
from rich.text import Text
|
|
4751
|
+
import sys
|
|
4754
4752
|
from praisonai.cli.features.message_queue import ProcessingState
|
|
4755
4753
|
|
|
4756
4754
|
state_manager = session_state['state_manager']
|
|
@@ -4762,8 +4760,11 @@ Provide a concise summary (max 200 words):"""
|
|
|
4762
4760
|
live_status.clear()
|
|
4763
4761
|
live_status.update_status("Thinking...")
|
|
4764
4762
|
|
|
4763
|
+
# Print initial status (non-blocking - user can still type)
|
|
4764
|
+
console.print(f"[dim cyan]⏳ {live_status.current_status}[/dim cyan]")
|
|
4765
|
+
|
|
4765
4766
|
# Result container for thread communication
|
|
4766
|
-
result_container = {'response': None, 'error': None, 'done': False}
|
|
4767
|
+
result_container = {'response': None, 'error': None, 'done': False, 'last_status': ''}
|
|
4767
4768
|
|
|
4768
4769
|
def process_in_background():
|
|
4769
4770
|
"""Run agent processing in background thread."""
|
|
@@ -4809,37 +4810,36 @@ Provide a concise summary (max 200 words):"""
|
|
|
4809
4810
|
bg_thread = threading.Thread(target=process_in_background, daemon=True)
|
|
4810
4811
|
bg_thread.start()
|
|
4811
4812
|
|
|
4812
|
-
#
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4813
|
+
# Wait for completion with periodic status updates (non-blocking style)
|
|
4814
|
+
start_time = time.time()
|
|
4815
|
+
last_status_update = ""
|
|
4816
|
+
while not result_container['done']:
|
|
4817
|
+
time.sleep(0.2)
|
|
4818
|
+
current_status = live_status.current_status
|
|
4819
|
+
# Only print status if it changed
|
|
4820
|
+
if current_status != last_status_update:
|
|
4821
|
+
# Use carriage return to update in place
|
|
4822
|
+
elapsed = time.time() - start_time
|
|
4823
|
+
queue_count = message_queue.count
|
|
4824
|
+
queue_info = f" | 📋 Queued: {queue_count}" if queue_count > 0 else ""
|
|
4825
|
+
sys.stdout.write(f"\r[dim cyan]⏳ {current_status} ({elapsed:.1f}s){queue_info}[/dim cyan]")
|
|
4826
|
+
sys.stdout.flush()
|
|
4827
|
+
last_status_update = current_status
|
|
4828
|
+
|
|
4829
|
+
# Clear the status line
|
|
4830
|
+
sys.stdout.write("\r" + " " * 80 + "\r")
|
|
4831
|
+
sys.stdout.flush()
|
|
4830
4832
|
|
|
4831
4833
|
# Wait for thread to finish
|
|
4832
4834
|
bg_thread.join(timeout=1.0)
|
|
4833
4835
|
|
|
4834
4836
|
# Handle result
|
|
4835
4837
|
if result_container['error']:
|
|
4836
|
-
console.print(f"
|
|
4838
|
+
console.print(f"[red]Error: {result_container['error']}[/red]")
|
|
4837
4839
|
elif result_container['response']:
|
|
4838
4840
|
# Print response with streaming effect
|
|
4839
|
-
console.print()
|
|
4840
4841
|
response_str = result_container['response']
|
|
4841
4842
|
words = response_str.split()
|
|
4842
|
-
import sys
|
|
4843
4843
|
for i, word in enumerate(words):
|
|
4844
4844
|
console.print(word + " ", end="")
|
|
4845
4845
|
sys.stdout.flush()
|
|
@@ -57,7 +57,7 @@ class CloudDeployer:
|
|
|
57
57
|
file.write("FROM python:3.11-slim\n")
|
|
58
58
|
file.write("WORKDIR /app\n")
|
|
59
59
|
file.write("COPY . .\n")
|
|
60
|
-
file.write("RUN pip install flask praisonai==2.3.
|
|
60
|
+
file.write("RUN pip install flask praisonai==2.3.77 gunicorn markdown\n")
|
|
61
61
|
file.write("EXPOSE 8080\n")
|
|
62
62
|
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
|
63
63
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.3.77"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.3.76"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|