PraisonAI 3.0.0__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 (393) hide show
  1. praisonai/__init__.py +54 -0
  2. praisonai/__main__.py +15 -0
  3. praisonai/acp/__init__.py +54 -0
  4. praisonai/acp/config.py +159 -0
  5. praisonai/acp/server.py +587 -0
  6. praisonai/acp/session.py +219 -0
  7. praisonai/adapters/__init__.py +50 -0
  8. praisonai/adapters/readers.py +395 -0
  9. praisonai/adapters/rerankers.py +315 -0
  10. praisonai/adapters/retrievers.py +394 -0
  11. praisonai/adapters/vector_stores.py +409 -0
  12. praisonai/agent_scheduler.py +337 -0
  13. praisonai/agents_generator.py +903 -0
  14. praisonai/api/call.py +292 -0
  15. praisonai/auto.py +1197 -0
  16. praisonai/capabilities/__init__.py +275 -0
  17. praisonai/capabilities/a2a.py +140 -0
  18. praisonai/capabilities/assistants.py +283 -0
  19. praisonai/capabilities/audio.py +320 -0
  20. praisonai/capabilities/batches.py +469 -0
  21. praisonai/capabilities/completions.py +336 -0
  22. praisonai/capabilities/container_files.py +155 -0
  23. praisonai/capabilities/containers.py +93 -0
  24. praisonai/capabilities/embeddings.py +158 -0
  25. praisonai/capabilities/files.py +467 -0
  26. praisonai/capabilities/fine_tuning.py +293 -0
  27. praisonai/capabilities/guardrails.py +182 -0
  28. praisonai/capabilities/images.py +330 -0
  29. praisonai/capabilities/mcp.py +190 -0
  30. praisonai/capabilities/messages.py +270 -0
  31. praisonai/capabilities/moderations.py +154 -0
  32. praisonai/capabilities/ocr.py +217 -0
  33. praisonai/capabilities/passthrough.py +204 -0
  34. praisonai/capabilities/rag.py +207 -0
  35. praisonai/capabilities/realtime.py +160 -0
  36. praisonai/capabilities/rerank.py +165 -0
  37. praisonai/capabilities/responses.py +266 -0
  38. praisonai/capabilities/search.py +109 -0
  39. praisonai/capabilities/skills.py +133 -0
  40. praisonai/capabilities/vector_store_files.py +334 -0
  41. praisonai/capabilities/vector_stores.py +304 -0
  42. praisonai/capabilities/videos.py +141 -0
  43. praisonai/chainlit_ui.py +304 -0
  44. praisonai/chat/__init__.py +106 -0
  45. praisonai/chat/app.py +125 -0
  46. praisonai/cli/__init__.py +26 -0
  47. praisonai/cli/app.py +213 -0
  48. praisonai/cli/commands/__init__.py +75 -0
  49. praisonai/cli/commands/acp.py +70 -0
  50. praisonai/cli/commands/completion.py +333 -0
  51. praisonai/cli/commands/config.py +166 -0
  52. praisonai/cli/commands/debug.py +142 -0
  53. praisonai/cli/commands/diag.py +55 -0
  54. praisonai/cli/commands/doctor.py +166 -0
  55. praisonai/cli/commands/environment.py +179 -0
  56. praisonai/cli/commands/lsp.py +112 -0
  57. praisonai/cli/commands/mcp.py +210 -0
  58. praisonai/cli/commands/profile.py +457 -0
  59. praisonai/cli/commands/run.py +228 -0
  60. praisonai/cli/commands/schedule.py +150 -0
  61. praisonai/cli/commands/serve.py +97 -0
  62. praisonai/cli/commands/session.py +212 -0
  63. praisonai/cli/commands/traces.py +145 -0
  64. praisonai/cli/commands/version.py +101 -0
  65. praisonai/cli/configuration/__init__.py +18 -0
  66. praisonai/cli/configuration/loader.py +353 -0
  67. praisonai/cli/configuration/paths.py +114 -0
  68. praisonai/cli/configuration/schema.py +164 -0
  69. praisonai/cli/features/__init__.py +268 -0
  70. praisonai/cli/features/acp.py +236 -0
  71. praisonai/cli/features/action_orchestrator.py +546 -0
  72. praisonai/cli/features/agent_scheduler.py +773 -0
  73. praisonai/cli/features/agent_tools.py +474 -0
  74. praisonai/cli/features/agents.py +375 -0
  75. praisonai/cli/features/at_mentions.py +471 -0
  76. praisonai/cli/features/auto_memory.py +182 -0
  77. praisonai/cli/features/autonomy_mode.py +490 -0
  78. praisonai/cli/features/background.py +356 -0
  79. praisonai/cli/features/base.py +168 -0
  80. praisonai/cli/features/capabilities.py +1326 -0
  81. praisonai/cli/features/checkpoints.py +338 -0
  82. praisonai/cli/features/code_intelligence.py +652 -0
  83. praisonai/cli/features/compaction.py +294 -0
  84. praisonai/cli/features/compare.py +534 -0
  85. praisonai/cli/features/cost_tracker.py +514 -0
  86. praisonai/cli/features/debug.py +810 -0
  87. praisonai/cli/features/deploy.py +517 -0
  88. praisonai/cli/features/diag.py +289 -0
  89. praisonai/cli/features/doctor/__init__.py +63 -0
  90. praisonai/cli/features/doctor/checks/__init__.py +24 -0
  91. praisonai/cli/features/doctor/checks/acp_checks.py +240 -0
  92. praisonai/cli/features/doctor/checks/config_checks.py +366 -0
  93. praisonai/cli/features/doctor/checks/db_checks.py +366 -0
  94. praisonai/cli/features/doctor/checks/env_checks.py +543 -0
  95. praisonai/cli/features/doctor/checks/lsp_checks.py +199 -0
  96. praisonai/cli/features/doctor/checks/mcp_checks.py +349 -0
  97. praisonai/cli/features/doctor/checks/memory_checks.py +268 -0
  98. praisonai/cli/features/doctor/checks/network_checks.py +251 -0
  99. praisonai/cli/features/doctor/checks/obs_checks.py +328 -0
  100. praisonai/cli/features/doctor/checks/performance_checks.py +235 -0
  101. praisonai/cli/features/doctor/checks/permissions_checks.py +259 -0
  102. praisonai/cli/features/doctor/checks/selftest_checks.py +322 -0
  103. praisonai/cli/features/doctor/checks/serve_checks.py +426 -0
  104. praisonai/cli/features/doctor/checks/skills_checks.py +231 -0
  105. praisonai/cli/features/doctor/checks/tools_checks.py +371 -0
  106. praisonai/cli/features/doctor/engine.py +266 -0
  107. praisonai/cli/features/doctor/formatters.py +310 -0
  108. praisonai/cli/features/doctor/handler.py +397 -0
  109. praisonai/cli/features/doctor/models.py +264 -0
  110. praisonai/cli/features/doctor/registry.py +239 -0
  111. praisonai/cli/features/endpoints.py +1019 -0
  112. praisonai/cli/features/eval.py +560 -0
  113. praisonai/cli/features/external_agents.py +231 -0
  114. praisonai/cli/features/fast_context.py +410 -0
  115. praisonai/cli/features/flow_display.py +566 -0
  116. praisonai/cli/features/git_integration.py +651 -0
  117. praisonai/cli/features/guardrail.py +171 -0
  118. praisonai/cli/features/handoff.py +185 -0
  119. praisonai/cli/features/hooks.py +583 -0
  120. praisonai/cli/features/image.py +384 -0
  121. praisonai/cli/features/interactive_runtime.py +585 -0
  122. praisonai/cli/features/interactive_tools.py +380 -0
  123. praisonai/cli/features/interactive_tui.py +603 -0
  124. praisonai/cli/features/jobs.py +632 -0
  125. praisonai/cli/features/knowledge.py +531 -0
  126. praisonai/cli/features/lite.py +244 -0
  127. praisonai/cli/features/lsp_cli.py +225 -0
  128. praisonai/cli/features/mcp.py +169 -0
  129. praisonai/cli/features/message_queue.py +587 -0
  130. praisonai/cli/features/metrics.py +211 -0
  131. praisonai/cli/features/n8n.py +673 -0
  132. praisonai/cli/features/observability.py +293 -0
  133. praisonai/cli/features/ollama.py +361 -0
  134. praisonai/cli/features/output_style.py +273 -0
  135. praisonai/cli/features/package.py +631 -0
  136. praisonai/cli/features/performance.py +308 -0
  137. praisonai/cli/features/persistence.py +636 -0
  138. praisonai/cli/features/profile.py +226 -0
  139. praisonai/cli/features/profiler/__init__.py +81 -0
  140. praisonai/cli/features/profiler/core.py +558 -0
  141. praisonai/cli/features/profiler/optimizations.py +652 -0
  142. praisonai/cli/features/profiler/suite.py +386 -0
  143. praisonai/cli/features/profiling.py +350 -0
  144. praisonai/cli/features/queue/__init__.py +73 -0
  145. praisonai/cli/features/queue/manager.py +395 -0
  146. praisonai/cli/features/queue/models.py +286 -0
  147. praisonai/cli/features/queue/persistence.py +564 -0
  148. praisonai/cli/features/queue/scheduler.py +484 -0
  149. praisonai/cli/features/queue/worker.py +372 -0
  150. praisonai/cli/features/recipe.py +1723 -0
  151. praisonai/cli/features/recipes.py +449 -0
  152. praisonai/cli/features/registry.py +229 -0
  153. praisonai/cli/features/repo_map.py +860 -0
  154. praisonai/cli/features/router.py +466 -0
  155. praisonai/cli/features/sandbox_executor.py +515 -0
  156. praisonai/cli/features/serve.py +829 -0
  157. praisonai/cli/features/session.py +222 -0
  158. praisonai/cli/features/skills.py +856 -0
  159. praisonai/cli/features/slash_commands.py +650 -0
  160. praisonai/cli/features/telemetry.py +179 -0
  161. praisonai/cli/features/templates.py +1384 -0
  162. praisonai/cli/features/thinking.py +305 -0
  163. praisonai/cli/features/todo.py +334 -0
  164. praisonai/cli/features/tools.py +680 -0
  165. praisonai/cli/features/tui/__init__.py +83 -0
  166. praisonai/cli/features/tui/app.py +580 -0
  167. praisonai/cli/features/tui/cli.py +566 -0
  168. praisonai/cli/features/tui/debug.py +511 -0
  169. praisonai/cli/features/tui/events.py +99 -0
  170. praisonai/cli/features/tui/mock_provider.py +328 -0
  171. praisonai/cli/features/tui/orchestrator.py +652 -0
  172. praisonai/cli/features/tui/screens/__init__.py +50 -0
  173. praisonai/cli/features/tui/screens/main.py +245 -0
  174. praisonai/cli/features/tui/screens/queue.py +174 -0
  175. praisonai/cli/features/tui/screens/session.py +124 -0
  176. praisonai/cli/features/tui/screens/settings.py +148 -0
  177. praisonai/cli/features/tui/widgets/__init__.py +56 -0
  178. praisonai/cli/features/tui/widgets/chat.py +261 -0
  179. praisonai/cli/features/tui/widgets/composer.py +224 -0
  180. praisonai/cli/features/tui/widgets/queue_panel.py +200 -0
  181. praisonai/cli/features/tui/widgets/status.py +167 -0
  182. praisonai/cli/features/tui/widgets/tool_panel.py +248 -0
  183. praisonai/cli/features/workflow.py +720 -0
  184. praisonai/cli/legacy.py +236 -0
  185. praisonai/cli/main.py +5559 -0
  186. praisonai/cli/schedule_cli.py +54 -0
  187. praisonai/cli/state/__init__.py +31 -0
  188. praisonai/cli/state/identifiers.py +161 -0
  189. praisonai/cli/state/sessions.py +313 -0
  190. praisonai/code/__init__.py +93 -0
  191. praisonai/code/agent_tools.py +344 -0
  192. praisonai/code/diff/__init__.py +21 -0
  193. praisonai/code/diff/diff_strategy.py +432 -0
  194. praisonai/code/tools/__init__.py +27 -0
  195. praisonai/code/tools/apply_diff.py +221 -0
  196. praisonai/code/tools/execute_command.py +275 -0
  197. praisonai/code/tools/list_files.py +274 -0
  198. praisonai/code/tools/read_file.py +206 -0
  199. praisonai/code/tools/search_replace.py +248 -0
  200. praisonai/code/tools/write_file.py +217 -0
  201. praisonai/code/utils/__init__.py +46 -0
  202. praisonai/code/utils/file_utils.py +307 -0
  203. praisonai/code/utils/ignore_utils.py +308 -0
  204. praisonai/code/utils/text_utils.py +276 -0
  205. praisonai/db/__init__.py +64 -0
  206. praisonai/db/adapter.py +531 -0
  207. praisonai/deploy/__init__.py +62 -0
  208. praisonai/deploy/api.py +231 -0
  209. praisonai/deploy/docker.py +454 -0
  210. praisonai/deploy/doctor.py +367 -0
  211. praisonai/deploy/main.py +327 -0
  212. praisonai/deploy/models.py +179 -0
  213. praisonai/deploy/providers/__init__.py +33 -0
  214. praisonai/deploy/providers/aws.py +331 -0
  215. praisonai/deploy/providers/azure.py +358 -0
  216. praisonai/deploy/providers/base.py +101 -0
  217. praisonai/deploy/providers/gcp.py +314 -0
  218. praisonai/deploy/schema.py +208 -0
  219. praisonai/deploy.py +185 -0
  220. praisonai/endpoints/__init__.py +53 -0
  221. praisonai/endpoints/a2u_server.py +410 -0
  222. praisonai/endpoints/discovery.py +165 -0
  223. praisonai/endpoints/providers/__init__.py +28 -0
  224. praisonai/endpoints/providers/a2a.py +253 -0
  225. praisonai/endpoints/providers/a2u.py +208 -0
  226. praisonai/endpoints/providers/agents_api.py +171 -0
  227. praisonai/endpoints/providers/base.py +231 -0
  228. praisonai/endpoints/providers/mcp.py +263 -0
  229. praisonai/endpoints/providers/recipe.py +206 -0
  230. praisonai/endpoints/providers/tools_mcp.py +150 -0
  231. praisonai/endpoints/registry.py +131 -0
  232. praisonai/endpoints/server.py +161 -0
  233. praisonai/inbuilt_tools/__init__.py +24 -0
  234. praisonai/inbuilt_tools/autogen_tools.py +117 -0
  235. praisonai/inc/__init__.py +2 -0
  236. praisonai/inc/config.py +96 -0
  237. praisonai/inc/models.py +155 -0
  238. praisonai/integrations/__init__.py +56 -0
  239. praisonai/integrations/base.py +303 -0
  240. praisonai/integrations/claude_code.py +270 -0
  241. praisonai/integrations/codex_cli.py +255 -0
  242. praisonai/integrations/cursor_cli.py +195 -0
  243. praisonai/integrations/gemini_cli.py +222 -0
  244. praisonai/jobs/__init__.py +67 -0
  245. praisonai/jobs/executor.py +425 -0
  246. praisonai/jobs/models.py +230 -0
  247. praisonai/jobs/router.py +314 -0
  248. praisonai/jobs/server.py +186 -0
  249. praisonai/jobs/store.py +203 -0
  250. praisonai/llm/__init__.py +66 -0
  251. praisonai/llm/registry.py +382 -0
  252. praisonai/mcp_server/__init__.py +152 -0
  253. praisonai/mcp_server/adapters/__init__.py +74 -0
  254. praisonai/mcp_server/adapters/agents.py +128 -0
  255. praisonai/mcp_server/adapters/capabilities.py +168 -0
  256. praisonai/mcp_server/adapters/cli_tools.py +568 -0
  257. praisonai/mcp_server/adapters/extended_capabilities.py +462 -0
  258. praisonai/mcp_server/adapters/knowledge.py +93 -0
  259. praisonai/mcp_server/adapters/memory.py +104 -0
  260. praisonai/mcp_server/adapters/prompts.py +306 -0
  261. praisonai/mcp_server/adapters/resources.py +124 -0
  262. praisonai/mcp_server/adapters/tools_bridge.py +280 -0
  263. praisonai/mcp_server/auth/__init__.py +48 -0
  264. praisonai/mcp_server/auth/api_key.py +291 -0
  265. praisonai/mcp_server/auth/oauth.py +460 -0
  266. praisonai/mcp_server/auth/oidc.py +289 -0
  267. praisonai/mcp_server/auth/scopes.py +260 -0
  268. praisonai/mcp_server/cli.py +852 -0
  269. praisonai/mcp_server/elicitation.py +445 -0
  270. praisonai/mcp_server/icons.py +302 -0
  271. praisonai/mcp_server/recipe_adapter.py +573 -0
  272. praisonai/mcp_server/recipe_cli.py +824 -0
  273. praisonai/mcp_server/registry.py +703 -0
  274. praisonai/mcp_server/sampling.py +422 -0
  275. praisonai/mcp_server/server.py +490 -0
  276. praisonai/mcp_server/tasks.py +443 -0
  277. praisonai/mcp_server/transports/__init__.py +18 -0
  278. praisonai/mcp_server/transports/http_stream.py +376 -0
  279. praisonai/mcp_server/transports/stdio.py +132 -0
  280. praisonai/persistence/__init__.py +84 -0
  281. praisonai/persistence/config.py +238 -0
  282. praisonai/persistence/conversation/__init__.py +25 -0
  283. praisonai/persistence/conversation/async_mysql.py +427 -0
  284. praisonai/persistence/conversation/async_postgres.py +410 -0
  285. praisonai/persistence/conversation/async_sqlite.py +371 -0
  286. praisonai/persistence/conversation/base.py +151 -0
  287. praisonai/persistence/conversation/json_store.py +250 -0
  288. praisonai/persistence/conversation/mysql.py +387 -0
  289. praisonai/persistence/conversation/postgres.py +401 -0
  290. praisonai/persistence/conversation/singlestore.py +240 -0
  291. praisonai/persistence/conversation/sqlite.py +341 -0
  292. praisonai/persistence/conversation/supabase.py +203 -0
  293. praisonai/persistence/conversation/surrealdb.py +287 -0
  294. praisonai/persistence/factory.py +301 -0
  295. praisonai/persistence/hooks/__init__.py +18 -0
  296. praisonai/persistence/hooks/agent_hooks.py +297 -0
  297. praisonai/persistence/knowledge/__init__.py +26 -0
  298. praisonai/persistence/knowledge/base.py +144 -0
  299. praisonai/persistence/knowledge/cassandra.py +232 -0
  300. praisonai/persistence/knowledge/chroma.py +295 -0
  301. praisonai/persistence/knowledge/clickhouse.py +242 -0
  302. praisonai/persistence/knowledge/cosmosdb_vector.py +438 -0
  303. praisonai/persistence/knowledge/couchbase.py +286 -0
  304. praisonai/persistence/knowledge/lancedb.py +216 -0
  305. praisonai/persistence/knowledge/langchain_adapter.py +291 -0
  306. praisonai/persistence/knowledge/lightrag_adapter.py +212 -0
  307. praisonai/persistence/knowledge/llamaindex_adapter.py +256 -0
  308. praisonai/persistence/knowledge/milvus.py +277 -0
  309. praisonai/persistence/knowledge/mongodb_vector.py +306 -0
  310. praisonai/persistence/knowledge/pgvector.py +335 -0
  311. praisonai/persistence/knowledge/pinecone.py +253 -0
  312. praisonai/persistence/knowledge/qdrant.py +301 -0
  313. praisonai/persistence/knowledge/redis_vector.py +291 -0
  314. praisonai/persistence/knowledge/singlestore_vector.py +299 -0
  315. praisonai/persistence/knowledge/surrealdb_vector.py +309 -0
  316. praisonai/persistence/knowledge/upstash_vector.py +266 -0
  317. praisonai/persistence/knowledge/weaviate.py +223 -0
  318. praisonai/persistence/migrations/__init__.py +10 -0
  319. praisonai/persistence/migrations/manager.py +251 -0
  320. praisonai/persistence/orchestrator.py +406 -0
  321. praisonai/persistence/state/__init__.py +21 -0
  322. praisonai/persistence/state/async_mongodb.py +200 -0
  323. praisonai/persistence/state/base.py +107 -0
  324. praisonai/persistence/state/dynamodb.py +226 -0
  325. praisonai/persistence/state/firestore.py +175 -0
  326. praisonai/persistence/state/gcs.py +155 -0
  327. praisonai/persistence/state/memory.py +245 -0
  328. praisonai/persistence/state/mongodb.py +158 -0
  329. praisonai/persistence/state/redis.py +190 -0
  330. praisonai/persistence/state/upstash.py +144 -0
  331. praisonai/persistence/tests/__init__.py +3 -0
  332. praisonai/persistence/tests/test_all_backends.py +633 -0
  333. praisonai/profiler.py +1214 -0
  334. praisonai/recipe/__init__.py +134 -0
  335. praisonai/recipe/bridge.py +278 -0
  336. praisonai/recipe/core.py +893 -0
  337. praisonai/recipe/exceptions.py +54 -0
  338. praisonai/recipe/history.py +402 -0
  339. praisonai/recipe/models.py +266 -0
  340. praisonai/recipe/operations.py +440 -0
  341. praisonai/recipe/policy.py +422 -0
  342. praisonai/recipe/registry.py +849 -0
  343. praisonai/recipe/runtime.py +214 -0
  344. praisonai/recipe/security.py +711 -0
  345. praisonai/recipe/serve.py +859 -0
  346. praisonai/recipe/server.py +613 -0
  347. praisonai/scheduler/__init__.py +45 -0
  348. praisonai/scheduler/agent_scheduler.py +552 -0
  349. praisonai/scheduler/base.py +124 -0
  350. praisonai/scheduler/daemon_manager.py +225 -0
  351. praisonai/scheduler/state_manager.py +155 -0
  352. praisonai/scheduler/yaml_loader.py +193 -0
  353. praisonai/scheduler.py +194 -0
  354. praisonai/setup/__init__.py +1 -0
  355. praisonai/setup/build.py +21 -0
  356. praisonai/setup/post_install.py +23 -0
  357. praisonai/setup/setup_conda_env.py +25 -0
  358. praisonai/setup.py +16 -0
  359. praisonai/templates/__init__.py +116 -0
  360. praisonai/templates/cache.py +364 -0
  361. praisonai/templates/dependency_checker.py +358 -0
  362. praisonai/templates/discovery.py +391 -0
  363. praisonai/templates/loader.py +564 -0
  364. praisonai/templates/registry.py +511 -0
  365. praisonai/templates/resolver.py +206 -0
  366. praisonai/templates/security.py +327 -0
  367. praisonai/templates/tool_override.py +498 -0
  368. praisonai/templates/tools_doctor.py +256 -0
  369. praisonai/test.py +105 -0
  370. praisonai/train.py +562 -0
  371. praisonai/train_vision.py +306 -0
  372. praisonai/ui/agents.py +824 -0
  373. praisonai/ui/callbacks.py +57 -0
  374. praisonai/ui/chainlit_compat.py +246 -0
  375. praisonai/ui/chat.py +532 -0
  376. praisonai/ui/code.py +717 -0
  377. praisonai/ui/colab.py +474 -0
  378. praisonai/ui/colab_chainlit.py +81 -0
  379. praisonai/ui/components/aicoder.py +284 -0
  380. praisonai/ui/context.py +283 -0
  381. praisonai/ui/database_config.py +56 -0
  382. praisonai/ui/db.py +294 -0
  383. praisonai/ui/realtime.py +488 -0
  384. praisonai/ui/realtimeclient/__init__.py +756 -0
  385. praisonai/ui/realtimeclient/tools.py +242 -0
  386. praisonai/ui/sql_alchemy.py +710 -0
  387. praisonai/upload_vision.py +140 -0
  388. praisonai/version.py +1 -0
  389. praisonai-3.0.0.dist-info/METADATA +3493 -0
  390. praisonai-3.0.0.dist-info/RECORD +393 -0
  391. praisonai-3.0.0.dist-info/WHEEL +5 -0
  392. praisonai-3.0.0.dist-info/entry_points.txt +4 -0
  393. praisonai-3.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,474 @@
1
+ """
2
+ Agent-Centric Tools for PraisonAI Interactive Mode.
3
+
4
+ These tools route file operations and code intelligence through LSP/ACP,
5
+ making the Agent the central orchestrator for all actions.
6
+ """
7
+
8
+ import asyncio
9
+ import json
10
+ import logging
11
+ from typing import Callable, Dict, List, TYPE_CHECKING
12
+
13
+ if TYPE_CHECKING:
14
+ from .interactive_runtime import InteractiveRuntime
15
+ from .code_intelligence import CodeIntelligenceRouter
16
+ from .action_orchestrator import ActionOrchestrator
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ def create_agent_centric_tools(
22
+ runtime: "InteractiveRuntime",
23
+ router: "CodeIntelligenceRouter" = None,
24
+ orchestrator: "ActionOrchestrator" = None
25
+ ) -> List[Callable]:
26
+ """
27
+ Create tools that route through LSP/ACP for agent-centric architecture.
28
+
29
+ Args:
30
+ runtime: The InteractiveRuntime instance
31
+ router: Optional CodeIntelligenceRouter (created if not provided)
32
+ orchestrator: Optional ActionOrchestrator (created if not provided)
33
+
34
+ Returns:
35
+ List of tool functions for the Agent
36
+ """
37
+ from .code_intelligence import CodeIntelligenceRouter
38
+ from .action_orchestrator import ActionOrchestrator
39
+
40
+ if router is None:
41
+ router = CodeIntelligenceRouter(runtime)
42
+ if orchestrator is None:
43
+ orchestrator = ActionOrchestrator(runtime)
44
+
45
+ # Helper to run async functions synchronously
46
+ def run_async(coro):
47
+ """Run async coroutine synchronously."""
48
+ try:
49
+ loop = asyncio.get_event_loop()
50
+ if loop.is_running():
51
+ # Create a new loop in a thread
52
+ import concurrent.futures
53
+ with concurrent.futures.ThreadPoolExecutor() as executor:
54
+ future = executor.submit(asyncio.run, coro)
55
+ return future.result(timeout=60)
56
+ else:
57
+ return loop.run_until_complete(coro)
58
+ except RuntimeError:
59
+ return asyncio.run(coro)
60
+
61
+ # =========================================================================
62
+ # ACP-Powered File Tools
63
+ # =========================================================================
64
+
65
+ def acp_create_file(filepath: str, content: str) -> str:
66
+ """
67
+ Create a file through ACP with plan/approve/apply/verify flow.
68
+
69
+ This tool routes file creation through the ActionOrchestrator,
70
+ ensuring proper tracking, approval, and verification.
71
+
72
+ Args:
73
+ filepath: Path to the file to create (relative to workspace)
74
+ content: Content to write to the file
75
+
76
+ Returns:
77
+ JSON string with result including plan status and verification
78
+ """
79
+ async def _create():
80
+ # Build a detailed prompt for the orchestrator
81
+ prompt = f"create file {filepath}"
82
+
83
+ # Create plan
84
+ result = await orchestrator.create_plan(prompt)
85
+ if not result.success:
86
+ return json.dumps({
87
+ "success": False,
88
+ "error": result.error,
89
+ "read_only": result.read_only_blocked
90
+ })
91
+
92
+ plan = result.plan
93
+
94
+ # Update the plan step with actual content
95
+ if plan.steps:
96
+ plan.steps[0].params["content"] = content
97
+
98
+ # Approve based on runtime config
99
+ auto_approve = runtime.config.approval_mode == "auto"
100
+ approved = await orchestrator.approve_plan(plan, auto=auto_approve)
101
+
102
+ if not approved and runtime.config.approval_mode == "manual":
103
+ return json.dumps({
104
+ "success": False,
105
+ "error": "Manual approval required",
106
+ "plan": plan.to_dict(),
107
+ "requires_approval": True
108
+ })
109
+
110
+ # Apply the plan
111
+ result = await orchestrator.apply_plan(plan, force=auto_approve)
112
+ if not result.success:
113
+ return json.dumps({
114
+ "success": False,
115
+ "error": result.error,
116
+ "plan": plan.to_dict()
117
+ })
118
+
119
+ # Verify
120
+ result = await orchestrator.verify_plan(plan)
121
+
122
+ return json.dumps({
123
+ "success": result.success,
124
+ "file_created": filepath,
125
+ "plan_id": plan.id,
126
+ "status": plan.status.value,
127
+ "verified": result.success
128
+ })
129
+
130
+ return run_async(_create())
131
+
132
+ def acp_edit_file(filepath: str, new_content: str) -> str:
133
+ """
134
+ Edit a file through ACP with plan/approve/apply/verify flow.
135
+
136
+ Args:
137
+ filepath: Path to the file to edit (relative to workspace)
138
+ new_content: New content for the file
139
+
140
+ Returns:
141
+ JSON string with result including plan status
142
+ """
143
+ async def _edit():
144
+ prompt = f"edit file {filepath}"
145
+
146
+ result = await orchestrator.create_plan(prompt)
147
+ if not result.success:
148
+ return json.dumps({
149
+ "success": False,
150
+ "error": result.error,
151
+ "read_only": result.read_only_blocked
152
+ })
153
+
154
+ plan = result.plan
155
+
156
+ # Update step with new content
157
+ if plan.steps:
158
+ plan.steps[0].params["new_content"] = new_content
159
+
160
+ auto_approve = runtime.config.approval_mode == "auto"
161
+ approved = await orchestrator.approve_plan(plan, auto=auto_approve)
162
+
163
+ if not approved and runtime.config.approval_mode == "manual":
164
+ return json.dumps({
165
+ "success": False,
166
+ "error": "Manual approval required",
167
+ "requires_approval": True
168
+ })
169
+
170
+ result = await orchestrator.apply_plan(plan, force=auto_approve)
171
+
172
+ return json.dumps({
173
+ "success": result.success,
174
+ "file_edited": filepath,
175
+ "plan_id": plan.id,
176
+ "error": result.error
177
+ })
178
+
179
+ return run_async(_edit())
180
+
181
+ def acp_delete_file(filepath: str) -> str:
182
+ """
183
+ Delete a file through ACP with plan/approve/apply/verify flow.
184
+
185
+ Args:
186
+ filepath: Path to the file to delete
187
+
188
+ Returns:
189
+ JSON string with result
190
+ """
191
+ async def _delete():
192
+ prompt = f"delete file {filepath}"
193
+
194
+ result = await orchestrator.create_plan(prompt)
195
+ if not result.success:
196
+ return json.dumps({
197
+ "success": False,
198
+ "error": result.error
199
+ })
200
+
201
+ plan = result.plan
202
+
203
+ # Delete requires explicit approval even in auto mode
204
+ auto_approve = runtime.config.approval_mode == "auto"
205
+ approved = await orchestrator.approve_plan(plan, auto=auto_approve)
206
+
207
+ if not approved:
208
+ return json.dumps({
209
+ "success": False,
210
+ "error": "Delete requires approval",
211
+ "requires_approval": True
212
+ })
213
+
214
+ result = await orchestrator.apply_plan(plan)
215
+ result = await orchestrator.verify_plan(plan)
216
+
217
+ return json.dumps({
218
+ "success": result.success,
219
+ "file_deleted": filepath,
220
+ "verified": result.success
221
+ })
222
+
223
+ return run_async(_delete())
224
+
225
+ def acp_execute_command(command: str, cwd: str = None) -> str:
226
+ """
227
+ Execute a shell command through ACP with tracking.
228
+
229
+ Args:
230
+ command: The command to execute
231
+ cwd: Working directory (optional)
232
+
233
+ Returns:
234
+ JSON string with command output
235
+ """
236
+ async def _execute():
237
+ prompt = f"run command: {command}"
238
+
239
+ result = await orchestrator.create_plan(prompt)
240
+ if not result.success:
241
+ return json.dumps({
242
+ "success": False,
243
+ "error": result.error
244
+ })
245
+
246
+ plan = result.plan
247
+
248
+ # Commands require approval
249
+ auto_approve = runtime.config.approval_mode == "auto"
250
+ approved = await orchestrator.approve_plan(plan, auto=auto_approve)
251
+
252
+ if not approved:
253
+ return json.dumps({
254
+ "success": False,
255
+ "error": "Command requires approval",
256
+ "requires_approval": True
257
+ })
258
+
259
+ result = await orchestrator.apply_plan(plan)
260
+
261
+ # Extract command result
262
+ if plan.steps and plan.steps[0].result:
263
+ cmd_result = plan.steps[0].result
264
+ return json.dumps({
265
+ "success": result.success,
266
+ "command": command,
267
+ "stdout": cmd_result.get("stdout", ""),
268
+ "stderr": cmd_result.get("stderr", ""),
269
+ "returncode": cmd_result.get("returncode", -1)
270
+ })
271
+
272
+ return json.dumps({
273
+ "success": result.success,
274
+ "error": result.error
275
+ })
276
+
277
+ return run_async(_execute())
278
+
279
+ # =========================================================================
280
+ # LSP-Powered Code Intelligence Tools
281
+ # =========================================================================
282
+
283
+ def lsp_list_symbols(file_path: str) -> str:
284
+ """
285
+ List all symbols (functions, classes, methods) in a file using LSP.
286
+
287
+ Falls back to regex-based extraction if LSP is unavailable.
288
+
289
+ Args:
290
+ file_path: Path to the file to analyze
291
+
292
+ Returns:
293
+ JSON string with list of symbols and their locations
294
+ """
295
+ async def _list():
296
+ result = await router.handle_query(
297
+ f"list all functions and classes in {file_path}",
298
+ file_path=file_path
299
+ )
300
+ return json.dumps(result.to_dict())
301
+
302
+ return run_async(_list())
303
+
304
+ def lsp_find_definition(symbol: str, file_path: str = None) -> str:
305
+ """
306
+ Find where a symbol is defined using LSP.
307
+
308
+ Args:
309
+ symbol: The symbol name to find
310
+ file_path: Optional file path for context
311
+
312
+ Returns:
313
+ JSON string with definition location(s)
314
+ """
315
+ async def _find():
316
+ query = f"where is {symbol} defined"
317
+ if file_path:
318
+ query += f" in {file_path}"
319
+
320
+ result = await router.handle_query(query, file_path=file_path)
321
+ return json.dumps(result.to_dict())
322
+
323
+ return run_async(_find())
324
+
325
+ def lsp_find_references(symbol: str, file_path: str = None) -> str:
326
+ """
327
+ Find all references to a symbol using LSP.
328
+
329
+ Args:
330
+ symbol: The symbol name to find references for
331
+ file_path: Optional file path for context
332
+
333
+ Returns:
334
+ JSON string with reference locations
335
+ """
336
+ async def _find():
337
+ query = f"find all references to {symbol}"
338
+ if file_path:
339
+ query += f" in {file_path}"
340
+
341
+ result = await router.handle_query(query, file_path=file_path)
342
+ return json.dumps(result.to_dict())
343
+
344
+ return run_async(_find())
345
+
346
+ def lsp_get_diagnostics(file_path: str = None) -> str:
347
+ """
348
+ Get diagnostics (errors, warnings) for a file using LSP.
349
+
350
+ Args:
351
+ file_path: Path to the file (optional, gets all if not specified)
352
+
353
+ Returns:
354
+ JSON string with diagnostic information
355
+ """
356
+ async def _get():
357
+ query = "show all errors and warnings"
358
+ if file_path:
359
+ query += f" in {file_path}"
360
+
361
+ result = await router.handle_query(query, file_path=file_path)
362
+ return json.dumps(result.to_dict())
363
+
364
+ return run_async(_get())
365
+
366
+ # =========================================================================
367
+ # Basic File Tools (for read-only operations)
368
+ # =========================================================================
369
+
370
+ def read_file(filepath: str) -> str:
371
+ """
372
+ Read content from a file.
373
+
374
+ This is a read-only operation that doesn't require ACP.
375
+
376
+ Args:
377
+ filepath: Path to the file to read
378
+
379
+ Returns:
380
+ File content or error message
381
+ """
382
+ from pathlib import Path
383
+
384
+ try:
385
+ path = Path(filepath)
386
+ if not path.is_absolute():
387
+ path = Path(runtime.config.workspace) / filepath
388
+
389
+ if not path.exists():
390
+ return json.dumps({"error": f"File not found: {filepath}"})
391
+
392
+ content = path.read_text()
393
+
394
+ # Track in trace if enabled
395
+ if runtime._trace:
396
+ runtime._trace.add_entry(
397
+ category="file",
398
+ action="read",
399
+ params={"file": str(path)},
400
+ result={"size": len(content)}
401
+ )
402
+
403
+ return content
404
+
405
+ except Exception as e:
406
+ return json.dumps({"error": str(e)})
407
+
408
+ def list_files(directory: str = ".", pattern: str = "*") -> str:
409
+ """
410
+ List files in a directory.
411
+
412
+ Args:
413
+ directory: Directory to list (relative to workspace)
414
+ pattern: Glob pattern to filter files
415
+
416
+ Returns:
417
+ JSON string with list of files
418
+ """
419
+ from pathlib import Path
420
+
421
+ try:
422
+ path = Path(directory)
423
+ if not path.is_absolute():
424
+ path = Path(runtime.config.workspace) / directory
425
+
426
+ if not path.exists():
427
+ return json.dumps({"error": f"Directory not found: {directory}"})
428
+
429
+ files = []
430
+ for f in path.glob(pattern):
431
+ files.append({
432
+ "name": f.name,
433
+ "path": str(f.relative_to(runtime.config.workspace)),
434
+ "is_dir": f.is_dir(),
435
+ "size": f.stat().st_size if f.is_file() else None
436
+ })
437
+
438
+ return json.dumps({"files": files, "count": len(files)})
439
+
440
+ except Exception as e:
441
+ return json.dumps({"error": str(e)})
442
+
443
+ # Return all tools
444
+ return [
445
+ # ACP-powered file tools
446
+ acp_create_file,
447
+ acp_edit_file,
448
+ acp_delete_file,
449
+ acp_execute_command,
450
+ # LSP-powered code intelligence
451
+ lsp_list_symbols,
452
+ lsp_find_definition,
453
+ lsp_find_references,
454
+ lsp_get_diagnostics,
455
+ # Basic read-only tools
456
+ read_file,
457
+ list_files,
458
+ ]
459
+
460
+
461
+ def get_tool_descriptions() -> Dict[str, str]:
462
+ """Get descriptions of all agent-centric tools."""
463
+ return {
464
+ "acp_create_file": "Create a file through ACP with plan/approve/apply/verify",
465
+ "acp_edit_file": "Edit a file through ACP with tracking",
466
+ "acp_delete_file": "Delete a file through ACP (requires approval)",
467
+ "acp_execute_command": "Execute a shell command through ACP",
468
+ "lsp_list_symbols": "List symbols in a file using LSP",
469
+ "lsp_find_definition": "Find where a symbol is defined",
470
+ "lsp_find_references": "Find all references to a symbol",
471
+ "lsp_get_diagnostics": "Get errors and warnings for a file",
472
+ "read_file": "Read content from a file (read-only)",
473
+ "list_files": "List files in a directory",
474
+ }