praisonAI 2.3.83__tar.gz → 2.3.85__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.
Files changed (125) hide show
  1. {praisonai-2.3.83 → praisonai-2.3.85}/PKG-INFO +2 -2
  2. {praisonai-2.3.83 → praisonai-2.3.85}/PraisonAI.egg-info/PKG-INFO +2 -2
  3. {praisonai-2.3.83 → praisonai-2.3.85}/PraisonAI.egg-info/requires.txt +1 -1
  4. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/skills.py +204 -14
  5. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/deploy.py +1 -1
  6. praisonai-2.3.85/praisonai/version.py +1 -0
  7. {praisonai-2.3.83 → praisonai-2.3.85}/pyproject.toml +1 -1
  8. praisonai-2.3.83/praisonai/version.py +0 -1
  9. {praisonai-2.3.83 → praisonai-2.3.85}/PraisonAI.egg-info/SOURCES.txt +0 -0
  10. {praisonai-2.3.83 → praisonai-2.3.85}/PraisonAI.egg-info/dependency_links.txt +0 -0
  11. {praisonai-2.3.83 → praisonai-2.3.85}/PraisonAI.egg-info/entry_points.txt +0 -0
  12. {praisonai-2.3.83 → praisonai-2.3.85}/PraisonAI.egg-info/top_level.txt +0 -0
  13. {praisonai-2.3.83 → praisonai-2.3.85}/README.md +0 -0
  14. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/__init__.py +0 -0
  15. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/__main__.py +0 -0
  16. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/agent_scheduler.py +0 -0
  17. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/agents_generator.py +0 -0
  18. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/api/call.py +0 -0
  19. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/auto.py +0 -0
  20. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/chainlit_ui.py +0 -0
  21. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/__init__.py +0 -0
  22. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/__init__.py +0 -0
  23. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/agent_scheduler.py +0 -0
  24. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/agents.py +0 -0
  25. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/at_mentions.py +0 -0
  26. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/auto_memory.py +0 -0
  27. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/autonomy_mode.py +0 -0
  28. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/base.py +0 -0
  29. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/compare.py +0 -0
  30. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/cost_tracker.py +0 -0
  31. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/eval.py +0 -0
  32. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/external_agents.py +0 -0
  33. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/fast_context.py +0 -0
  34. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/flow_display.py +0 -0
  35. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/git_integration.py +0 -0
  36. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/guardrail.py +0 -0
  37. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/handoff.py +0 -0
  38. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/image.py +0 -0
  39. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/interactive_tui.py +0 -0
  40. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/knowledge.py +0 -0
  41. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/mcp.py +0 -0
  42. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/message_queue.py +0 -0
  43. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/metrics.py +0 -0
  44. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/n8n.py +0 -0
  45. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/profile.py +0 -0
  46. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/profiling.py +0 -0
  47. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/repo_map.py +0 -0
  48. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/router.py +0 -0
  49. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/sandbox_executor.py +0 -0
  50. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/session.py +0 -0
  51. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/slash_commands.py +0 -0
  52. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/telemetry.py +0 -0
  53. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/todo.py +0 -0
  54. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/tools.py +0 -0
  55. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/features/workflow.py +0 -0
  56. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/main.py +0 -0
  57. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/cli/schedule_cli.py +0 -0
  58. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/__init__.py +0 -0
  59. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/agent_tools.py +0 -0
  60. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/diff/__init__.py +0 -0
  61. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/diff/diff_strategy.py +0 -0
  62. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/tools/__init__.py +0 -0
  63. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/tools/apply_diff.py +0 -0
  64. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/tools/execute_command.py +0 -0
  65. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/tools/list_files.py +0 -0
  66. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/tools/read_file.py +0 -0
  67. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/tools/search_replace.py +0 -0
  68. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/tools/write_file.py +0 -0
  69. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/utils/__init__.py +0 -0
  70. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/utils/file_utils.py +0 -0
  71. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/utils/ignore_utils.py +0 -0
  72. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/code/utils/text_utils.py +0 -0
  73. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/inbuilt_tools/__init__.py +0 -0
  74. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/inbuilt_tools/autogen_tools.py +0 -0
  75. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/inc/__init__.py +0 -0
  76. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/inc/config.py +0 -0
  77. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/inc/models.py +0 -0
  78. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/integrations/__init__.py +0 -0
  79. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/integrations/base.py +0 -0
  80. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/integrations/claude_code.py +0 -0
  81. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/integrations/codex_cli.py +0 -0
  82. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/integrations/cursor_cli.py +0 -0
  83. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/integrations/gemini_cli.py +0 -0
  84. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/profiler.py +0 -0
  85. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/scheduler/__init__.py +0 -0
  86. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/scheduler/agent_scheduler.py +0 -0
  87. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/scheduler/base.py +0 -0
  88. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/scheduler/daemon_manager.py +0 -0
  89. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/scheduler/state_manager.py +0 -0
  90. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/scheduler/yaml_loader.py +0 -0
  91. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/scheduler.py +0 -0
  92. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/setup/__init__.py +0 -0
  93. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/setup/build.py +0 -0
  94. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/setup/post_install.py +0 -0
  95. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/setup/setup_conda_env.py +0 -0
  96. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/setup.py +0 -0
  97. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/test.py +0 -0
  98. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/train.py +0 -0
  99. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/train_vision.py +0 -0
  100. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/agents.py +0 -0
  101. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/callbacks.py +0 -0
  102. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/chat.py +0 -0
  103. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/code.py +0 -0
  104. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/colab.py +0 -0
  105. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/colab_chainlit.py +0 -0
  106. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/components/aicoder.py +0 -0
  107. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/context.py +0 -0
  108. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/database_config.py +0 -0
  109. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/db.py +0 -0
  110. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/realtime.py +0 -0
  111. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/realtimeclient/__init__.py +0 -0
  112. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/realtimeclient/tools.py +0 -0
  113. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/ui/sql_alchemy.py +0 -0
  114. {praisonai-2.3.83 → praisonai-2.3.85}/praisonai/upload_vision.py +0 -0
  115. {praisonai-2.3.83 → praisonai-2.3.85}/setup.cfg +0 -0
  116. {praisonai-2.3.83 → praisonai-2.3.85}/tests/test.py +0 -0
  117. {praisonai-2.3.83 → praisonai-2.3.85}/tests/test_agents_playbook.py +0 -0
  118. {praisonai-2.3.83 → praisonai-2.3.85}/tests/test_approval_system.py +0 -0
  119. {praisonai-2.3.83 → praisonai-2.3.85}/tests/test_basic.py +0 -0
  120. {praisonai-2.3.83 → praisonai-2.3.85}/tests/test_cli_features.py +0 -0
  121. {praisonai-2.3.83 → praisonai-2.3.85}/tests/test_custom_tools_fix.py +0 -0
  122. {praisonai-2.3.83 → praisonai-2.3.85}/tests/test_double_api_fix.py +0 -0
  123. {praisonai-2.3.83 → praisonai-2.3.85}/tests/test_n8n_integration.py +0 -0
  124. {praisonai-2.3.83 → praisonai-2.3.85}/tests/test_phase2_refactor.py +0 -0
  125. {praisonai-2.3.83 → praisonai-2.3.85}/tests/test_runner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PraisonAI
3
- Version: 2.3.83
3
+ Version: 2.3.85
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
@@ -11,7 +11,7 @@ Description-Content-Type: text/markdown
11
11
  Requires-Dist: rich>=13.7
12
12
  Requires-Dist: markdown>=3.5
13
13
  Requires-Dist: pyparsing>=3.0.0
14
- Requires-Dist: praisonaiagents>=0.1.24
14
+ Requires-Dist: praisonaiagents>=0.1.25
15
15
  Requires-Dist: python-dotenv>=0.19.0
16
16
  Requires-Dist: instructor>=1.3.3
17
17
  Requires-Dist: PyYAML>=6.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PraisonAI
3
- Version: 2.3.83
3
+ Version: 2.3.85
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
@@ -11,7 +11,7 @@ Description-Content-Type: text/markdown
11
11
  Requires-Dist: rich>=13.7
12
12
  Requires-Dist: markdown>=3.5
13
13
  Requires-Dist: pyparsing>=3.0.0
14
- Requires-Dist: praisonaiagents>=0.1.24
14
+ Requires-Dist: praisonaiagents>=0.1.25
15
15
  Requires-Dist: python-dotenv>=0.19.0
16
16
  Requires-Dist: instructor>=1.3.3
17
17
  Requires-Dist: PyYAML>=6.0
@@ -1,7 +1,7 @@
1
1
  rich>=13.7
2
2
  markdown>=3.5
3
3
  pyparsing>=3.0.0
4
- praisonaiagents>=0.1.24
4
+ praisonaiagents>=0.1.25
5
5
  python-dotenv>=0.19.0
6
6
  instructor>=1.3.3
7
7
  PyYAML>=6.0
@@ -157,19 +157,22 @@ class SkillsHandler:
157
157
  else:
158
158
  # Use template
159
159
  skill_md_content = self._generate_template_content(
160
- name, description, author, license, compatibility
160
+ name, description, author, license, compatibility,
161
+ include_script=generate_script
161
162
  )
162
163
  if self.verbose and use_ai and not template:
163
164
  print("⚠ No API key found, using template")
164
165
 
165
166
  (skill_dir / "SKILL.md").write_text(skill_md_content)
166
167
 
167
- # Generate scripts/skill.py if requested or AI provided it
168
+ # Generate scripts/script.py if requested or AI provided it
168
169
  if generate_script or (ai_content and ai_content.get("skill_py")):
169
170
  script_content = (ai_content or {}).get("skill_py") or self._generate_template_script(name, description)
170
- (skill_dir / "scripts" / "skill.py").write_text(script_content)
171
+ # Strip any remaining code blocks from script content
172
+ script_content = self._strip_code_blocks(script_content)
173
+ (skill_dir / "scripts" / "script.py").write_text(script_content)
171
174
  if self.verbose:
172
- print(" - scripts/skill.py")
175
+ print(" - scripts/script.py")
173
176
  else:
174
177
  (skill_dir / "scripts" / ".gitkeep").write_text("")
175
178
 
@@ -192,10 +195,36 @@ class SkillsHandler:
192
195
  description: str,
193
196
  author: str,
194
197
  license: str,
195
- compatibility: str
198
+ compatibility: str,
199
+ include_script: bool = False
196
200
  ) -> str:
197
201
  """Generate template SKILL.md content."""
198
202
  title = name.replace('-', ' ').title()
203
+ func_name = name.replace('-', '_')
204
+
205
+ script_section = ""
206
+ if include_script:
207
+ script_section = f"""
208
+ ## Script Usage
209
+
210
+ This skill includes a Python script at `scripts/script.py` that provides the core functionality.
211
+
212
+ ### Running the Script
213
+
214
+ ```bash
215
+ python scripts/script.py <input>
216
+ ```
217
+
218
+ ### Using as a Module
219
+
220
+ ```python
221
+ from scripts.script import {func_name}
222
+
223
+ result = {func_name}(input_data)
224
+ print(result)
225
+ ```
226
+ """
227
+
199
228
  return f"""---
200
229
  name: {name}
201
230
  description: {description}
@@ -211,7 +240,7 @@ metadata:
211
240
  ## Overview
212
241
 
213
242
  {description}
214
-
243
+ {script_section}
215
244
  ## Usage
216
245
 
217
246
  Describe how to use this skill.
@@ -224,8 +253,128 @@ Describe how to use this skill.
224
253
  """
225
254
 
226
255
  def _generate_template_script(self, name: str, description: str) -> str:
227
- """Generate template scripts/skill.py content."""
256
+ """Generate description-relevant scripts/script.py content."""
228
257
  func_name = name.replace('-', '_')
258
+
259
+ # Analyze description to generate relevant code
260
+ desc_lower = description.lower()
261
+
262
+ # CSV/Data analysis patterns
263
+ if any(kw in desc_lower for kw in ['csv', 'spreadsheet', 'data analysis', 'analyze data', 'tabular']):
264
+ return self._generate_csv_script(name, description, func_name)
265
+
266
+ # PDF patterns
267
+ if any(kw in desc_lower for kw in ['pdf', 'document', 'extract text']):
268
+ return self._generate_pdf_script(name, description, func_name)
269
+
270
+ # Web/API patterns
271
+ if any(kw in desc_lower for kw in ['api', 'http', 'request', 'web', 'fetch', 'url']):
272
+ return self._generate_api_script(name, description, func_name)
273
+
274
+ # File processing patterns
275
+ if any(kw in desc_lower for kw in ['file', 'read', 'write', 'process', 'parse']):
276
+ return self._generate_file_script(name, description, func_name)
277
+
278
+ # Image patterns
279
+ if any(kw in desc_lower for kw in ['image', 'photo', 'picture', 'resize', 'convert']):
280
+ return self._generate_image_script(name, description, func_name)
281
+
282
+ # JSON/YAML patterns
283
+ if any(kw in desc_lower for kw in ['json', 'yaml', 'config', 'configuration']):
284
+ return self._generate_json_script(name, description, func_name)
285
+
286
+ # Text processing patterns
287
+ if any(kw in desc_lower for kw in ['text', 'string', 'regex', 'search', 'replace', 'format']):
288
+ return self._generate_text_script(name, description, func_name)
289
+
290
+ # Default generic script
291
+ return self._generate_generic_script(name, description, func_name)
292
+
293
+ def _generate_csv_script(self, name: str, description: str, func_name: str) -> str:
294
+ """Generate CSV analysis script."""
295
+ return f'''"""
296
+ {name} - {description}
297
+
298
+ This script provides functionality for the {name} skill.
299
+ """
300
+
301
+ def {func_name}(file_path: str) -> dict:
302
+ """
303
+ Analyze CSV file and return statistics.
304
+
305
+ Args:
306
+ file_path: Path to the CSV file to analyze
307
+
308
+ Returns:
309
+ Dictionary with analysis results
310
+ """
311
+ import pandas as pd
312
+
313
+ df = pd.read_csv(file_path)
314
+
315
+ result = {{
316
+ "rows": len(df),
317
+ "columns": len(df.columns),
318
+ "column_names": list(df.columns),
319
+ "dtypes": {{col: str(dtype) for col, dtype in df.dtypes.items()}},
320
+ "missing_values": df.isnull().sum().to_dict(),
321
+ "numeric_summary": {{}}
322
+ }}
323
+
324
+ numeric_cols = df.select_dtypes(include=['number']).columns
325
+ for col in numeric_cols:
326
+ result["numeric_summary"][col] = {{
327
+ "mean": float(df[col].mean()),
328
+ "std": float(df[col].std()),
329
+ "min": float(df[col].min()),
330
+ "max": float(df[col].max())
331
+ }}
332
+
333
+ return result
334
+
335
+
336
+ def main():
337
+ """Main entry point for the skill."""
338
+ import sys
339
+ import json
340
+
341
+ if len(sys.argv) > 1:
342
+ result = {func_name}(sys.argv[1])
343
+ print(json.dumps(result, indent=2))
344
+ else:
345
+ print("Usage: python script.py <csv_file>")
346
+
347
+
348
+ if __name__ == "__main__":
349
+ main()
350
+ '''
351
+
352
+ def _generate_pdf_script(self, name: str, description: str, func_name: str) -> str:
353
+ """Generate PDF processing script."""
354
+ return f'''"""\n{name} - {description}\n\nThis script provides PDF processing functionality.\n"""\n\ndef {func_name}(file_path: str) -> dict:\n """\n Process PDF file and extract content.\n \n Args:\n file_path: Path to the PDF file\n \n Returns:\n Dictionary with extracted content\n """\n from pypdf import PdfReader\n \n reader = PdfReader(file_path)\n \n result = {{\n "pages": len(reader.pages),\n "metadata": {{\n "title": reader.metadata.title if reader.metadata else None,\n "author": reader.metadata.author if reader.metadata else None\n }},\n "text": []\n }}\n \n for i, page in enumerate(reader.pages):\n result["text"].append({{\n "page": i + 1,\n "content": page.extract_text()\n }})\n \n return result\n\n\ndef main():\n """Main entry point for the skill."""\n import sys\n import json\n \n if len(sys.argv) > 1:\n result = {func_name}(sys.argv[1])\n print(json.dumps(result, indent=2))\n else:\n print("Usage: python script.py <pdf_file>")\n\n\nif __name__ == "__main__":\n main()\n'''
355
+
356
+ def _generate_api_script(self, name: str, description: str, func_name: str) -> str:
357
+ """Generate API/HTTP request script."""
358
+ return f'''"""\n{name} - {description}\n\nThis script provides API request functionality.\n"""\nimport requests\n\ndef {func_name}(url: str, method: str = "GET", data: dict = None) -> dict:\n """\n Make HTTP request to API endpoint.\n \n Args:\n url: API endpoint URL\n method: HTTP method (GET, POST, PUT, DELETE)\n data: Optional request body data\n \n Returns:\n Dictionary with response data\n """\n headers = {{"Content-Type": "application/json"}}\n \n if method.upper() == "GET":\n response = requests.get(url, headers=headers)\n elif method.upper() == "POST":\n response = requests.post(url, json=data, headers=headers)\n elif method.upper() == "PUT":\n response = requests.put(url, json=data, headers=headers)\n elif method.upper() == "DELETE":\n response = requests.delete(url, headers=headers)\n else:\n raise ValueError(f"Unsupported method: {{method}}")\n \n return {{\n "status_code": response.status_code,\n "headers": dict(response.headers),\n "data": response.json() if response.headers.get("content-type", "").startswith("application/json") else response.text\n }}\n\n\ndef main():\n """Main entry point for the skill."""\n import sys\n import json\n \n if len(sys.argv) > 1:\n result = {func_name}(sys.argv[1])\n print(json.dumps(result, indent=2))\n else:\n print("Usage: python script.py <url>")\n\n\nif __name__ == "__main__":\n main()\n'''
359
+
360
+ def _generate_file_script(self, name: str, description: str, func_name: str) -> str:
361
+ """Generate file processing script."""
362
+ return f'''"""\n{name} - {description}\n\nThis script provides file processing functionality.\n"""\nfrom pathlib import Path\n\ndef {func_name}(file_path: str) -> dict:\n """\n Process file and return information.\n \n Args:\n file_path: Path to the file to process\n \n Returns:\n Dictionary with file information and content\n """\n path = Path(file_path)\n \n if not path.exists():\n raise FileNotFoundError(f"File not found: {{file_path}}")\n \n stat = path.stat()\n \n result = {{\n "name": path.name,\n "extension": path.suffix,\n "size_bytes": stat.st_size,\n "is_file": path.is_file(),\n "is_dir": path.is_dir()\n }}\n \n if path.is_file() and stat.st_size < 1024 * 1024:\n try:\n result["content"] = path.read_text()\n result["lines"] = len(result["content"].splitlines())\n except UnicodeDecodeError:\n result["content"] = "<binary file>"\n \n return result\n\n\ndef main():\n """Main entry point for the skill."""\n import sys\n import json\n \n if len(sys.argv) > 1:\n result = {func_name}(sys.argv[1])\n print(json.dumps(result, indent=2))\n else:\n print("Usage: python script.py <file_path>")\n\n\nif __name__ == "__main__":\n main()\n'''
363
+
364
+ def _generate_image_script(self, name: str, description: str, func_name: str) -> str:
365
+ """Generate image processing script."""
366
+ return f'''"""\n{name} - {description}\n\nThis script provides image processing functionality.\n"""\nfrom PIL import Image\n\ndef {func_name}(file_path: str, output_path: str = None, resize: tuple = None) -> dict:\n """\n Process image file.\n \n Args:\n file_path: Path to the image file\n output_path: Optional output path for processed image\n resize: Optional tuple (width, height) to resize\n \n Returns:\n Dictionary with image information\n """\n img = Image.open(file_path)\n \n result = {{\n "format": img.format,\n "mode": img.mode,\n "size": img.size,\n "width": img.width,\n "height": img.height\n }}\n \n if resize:\n img = img.resize(resize)\n result["resized_to"] = resize\n \n if output_path:\n img.save(output_path)\n result["saved_to"] = output_path\n \n return result\n\n\ndef main():\n """Main entry point for the skill."""\n import sys\n import json\n \n if len(sys.argv) > 1:\n result = {func_name}(sys.argv[1])\n print(json.dumps(result, indent=2))\n else:\n print("Usage: python script.py <image_file>")\n\n\nif __name__ == "__main__":\n main()\n'''
367
+
368
+ def _generate_json_script(self, name: str, description: str, func_name: str) -> str:
369
+ """Generate JSON/YAML processing script."""
370
+ return f'''"""\n{name} - {description}\n\nThis script provides JSON/YAML processing functionality.\n"""\nimport json\nfrom pathlib import Path\n\ndef {func_name}(file_path: str) -> dict:\n """\n Process JSON or YAML file.\n \n Args:\n file_path: Path to the JSON/YAML file\n \n Returns:\n Dictionary with parsed content and metadata\n """\n path = Path(file_path)\n content = path.read_text()\n \n if path.suffix in [".yaml", ".yml"]:\n import yaml\n data = yaml.safe_load(content)\n else:\n data = json.loads(content)\n \n result = {{\n "file": file_path,\n "format": "yaml" if path.suffix in [".yaml", ".yml"] else "json",\n "keys": list(data.keys()) if isinstance(data, dict) else None,\n "length": len(data) if isinstance(data, (list, dict)) else None,\n "data": data\n }}\n \n return result\n\n\ndef main():\n """Main entry point for the skill."""\n import sys\n \n if len(sys.argv) > 1:\n result = {func_name}(sys.argv[1])\n print(json.dumps(result, indent=2))\n else:\n print("Usage: python script.py <json_or_yaml_file>")\n\n\nif __name__ == "__main__":\n main()\n'''
371
+
372
+ def _generate_text_script(self, name: str, description: str, func_name: str) -> str:
373
+ """Generate text processing script."""
374
+ return f'''"""\n{name} - {description}\n\nThis script provides text processing functionality.\n"""\nimport re\n\ndef {func_name}(text: str, pattern: str = None, replacement: str = None) -> dict:\n """\n Process text with optional regex operations.\n \n Args:\n text: Input text to process\n pattern: Optional regex pattern to search\n replacement: Optional replacement string\n \n Returns:\n Dictionary with processing results\n """\n result = {{\n "original_length": len(text),\n "lines": len(text.splitlines()),\n "words": len(text.split()),\n "characters": len(text.replace(" ", ""))\n }}\n \n if pattern:\n matches = re.findall(pattern, text)\n result["matches"] = matches\n result["match_count"] = len(matches)\n \n if replacement is not None:\n result["replaced_text"] = re.sub(pattern, replacement, text)\n \n return result\n\n\ndef main():\n """Main entry point for the skill."""\n import sys\n import json\n \n if len(sys.argv) > 1:\n with open(sys.argv[1]) as f:\n text = f.read()\n result = {func_name}(text)\n print(json.dumps(result, indent=2))\n else:\n print("Usage: python script.py <text_file>")\n\n\nif __name__ == "__main__":\n main()\n'''
375
+
376
+ def _generate_generic_script(self, name: str, description: str, func_name: str) -> str:
377
+ """Generate generic script template."""
229
378
  return f'''"""
230
379
  {name} - {description}
231
380
 
@@ -242,7 +391,6 @@ def {func_name}(input_data: str) -> str:
242
391
  Returns:
243
392
  Processed result
244
393
  """
245
- # TODO: Implement your skill logic here
246
394
  result = f"Processed: {{input_data}}"
247
395
  return result
248
396
 
@@ -254,7 +402,7 @@ def main():
254
402
  result = {func_name}(sys.argv[1])
255
403
  print(result)
256
404
  else:
257
- print("Usage: python skill.py <input>")
405
+ print("Usage: python script.py <input>")
258
406
 
259
407
 
260
408
  if __name__ == "__main__":
@@ -329,7 +477,32 @@ metadata:
329
477
  Generate detailed, practical content based on the description. Make it comprehensive but concise.
330
478
  The skill should be immediately useful for an AI agent.
331
479
 
332
- Also, if this skill requires any Python code to function, provide a skill.py script that implements the core functionality.
480
+ Also, if this skill requires any Python code to function, provide a script.py that implements the core functionality.
481
+ The script MUST follow this pattern:
482
+ 1. Have a main function that accepts file path as command line argument (sys.argv[1])
483
+ 2. Print JSON output using json.dumps()
484
+ 3. Include usage message if no arguments provided
485
+
486
+ Example script pattern:
487
+ ```python
488
+ import sys
489
+ import json
490
+
491
+ def process_file(file_path: str) -> dict:
492
+ # Core logic here
493
+ return {{"result": "data"}}
494
+
495
+ def main():
496
+ if len(sys.argv) > 1:
497
+ result = process_file(sys.argv[1])
498
+ print(json.dumps(result, indent=2))
499
+ else:
500
+ print("Usage: python script.py <file_path>")
501
+
502
+ if __name__ == "__main__":
503
+ main()
504
+ ```
505
+
333
506
  Format your response as:
334
507
  ---SKILL.MD---
335
508
  [content]
@@ -357,12 +530,12 @@ Format your response as:
357
530
 
358
531
  if "---SKILL.PY---" in skill_md_part:
359
532
  md_parts = skill_md_part.split("---SKILL.PY---")
360
- skill_md = md_parts[0].strip()
533
+ skill_md = self._strip_code_blocks(md_parts[0].strip())
361
534
  skill_py_content = md_parts[1].strip() if len(md_parts) > 1 else None
362
535
  if skill_py_content and skill_py_content.upper() != "NONE":
363
- skill_py = skill_py_content
536
+ skill_py = self._strip_code_blocks(skill_py_content)
364
537
  else:
365
- skill_md = skill_md_part.strip()
538
+ skill_md = self._strip_code_blocks(skill_md_part.strip())
366
539
 
367
540
  return {"skill_md": skill_md, "skill_py": skill_py}
368
541
 
@@ -373,6 +546,23 @@ Format your response as:
373
546
  print(f"⚠ AI generation failed: {e}")
374
547
  return None
375
548
 
549
+ def _strip_code_blocks(self, content: str) -> str:
550
+ """Strip markdown code block wrappers from content.
551
+
552
+ Args:
553
+ content: Content that may be wrapped in ```markdown or ```python blocks
554
+
555
+ Returns:
556
+ Content with code block wrappers removed
557
+ """
558
+ import re
559
+ # Match ```language at start and ``` at end
560
+ pattern = r'^```(?:markdown|python|json|yaml|md)?\s*\n?(.*?)\n?```\s*$'
561
+ match = re.match(pattern, content, re.DOTALL)
562
+ if match:
563
+ return match.group(1).strip()
564
+ return content
565
+
376
566
  def upload_skill(
377
567
  self,
378
568
  skill_path: str,
@@ -432,7 +622,7 @@ Format your response as:
432
622
  )
433
623
 
434
624
  if self.verbose:
435
- print(f"✓ Skill uploaded successfully!")
625
+ print("✓ Skill uploaded successfully!")
436
626
  print(f" ID: {response.id}")
437
627
  print(f" Title: {response.display_title}")
438
628
 
@@ -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.83 gunicorn markdown\n")
60
+ file.write("RUN pip install flask praisonai==2.3.85 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.85"
@@ -12,7 +12,7 @@ dependencies = [
12
12
  "rich>=13.7",
13
13
  "markdown>=3.5",
14
14
  "pyparsing>=3.0.0",
15
- "praisonaiagents>=0.1.24",
15
+ "praisonaiagents>=0.1.25",
16
16
  "python-dotenv>=0.19.0",
17
17
  "instructor>=1.3.3",
18
18
  "PyYAML>=6.0",
@@ -1 +0,0 @@
1
- __version__ = "2.3.83"
File without changes
File without changes
File without changes
File without changes
File without changes