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,309 @@
1
+ """
2
+ SurrealDB Vector implementation of KnowledgeStore.
3
+
4
+ Requires: surrealdb
5
+ Install: pip install surrealdb
6
+ """
7
+
8
+ import logging
9
+ from typing import Any, Dict, List, Optional
10
+
11
+ from .base import KnowledgeStore, KnowledgeDocument
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class SurrealDBVectorKnowledgeStore(KnowledgeStore):
17
+ """
18
+ SurrealDB vector store for knowledge/RAG.
19
+
20
+ Uses SurrealDB's vector capabilities.
21
+
22
+ Example:
23
+ store = SurrealDBVectorKnowledgeStore(
24
+ url="ws://localhost:8000/rpc",
25
+ namespace="praisonai",
26
+ database="vectors"
27
+ )
28
+ """
29
+
30
+ def __init__(
31
+ self,
32
+ url: str = "ws://localhost:8000/rpc",
33
+ namespace: str = "praisonai",
34
+ database: str = "vectors",
35
+ username: str = "root",
36
+ password: str = "root",
37
+ embedding_dim: int = 1536,
38
+ ):
39
+ """
40
+ Initialize SurrealDB Vector store.
41
+
42
+ Args:
43
+ url: SurrealDB WebSocket URL
44
+ namespace: SurrealDB namespace
45
+ database: SurrealDB database
46
+ username: Authentication username
47
+ password: Authentication password
48
+ embedding_dim: Embedding dimension
49
+ """
50
+ self.url = url
51
+ self.namespace = namespace
52
+ self.database = database
53
+ self.username = username
54
+ self.password = password
55
+ self.embedding_dim = embedding_dim
56
+
57
+ self._client = None
58
+ self._initialized = False
59
+
60
+ def _init_client(self):
61
+ """Initialize SurrealDB client lazily."""
62
+ if self._initialized:
63
+ return
64
+
65
+ try:
66
+ from surrealdb import Surreal
67
+ except ImportError:
68
+ raise ImportError(
69
+ "surrealdb is required for SurrealDB Vector support. "
70
+ "Install with: pip install surrealdb"
71
+ )
72
+
73
+ import asyncio
74
+
75
+ async def connect():
76
+ client = Surreal(self.url)
77
+ await client.connect()
78
+ await client.signin({"user": self.username, "pass": self.password})
79
+ await client.use(self.namespace, self.database)
80
+ return client
81
+
82
+ loop = asyncio.get_event_loop()
83
+ self._client = loop.run_until_complete(connect())
84
+ self._initialized = True
85
+
86
+ def _run_async(self, coro):
87
+ """Run async coroutine synchronously."""
88
+ import asyncio
89
+ return asyncio.get_event_loop().run_until_complete(coro)
90
+
91
+ def create_collection(
92
+ self,
93
+ name: str,
94
+ dimension: int = 1536,
95
+ distance: str = "cosine",
96
+ metadata: Optional[Dict[str, Any]] = None
97
+ ) -> None:
98
+ """Create a collection (SurrealDB creates tables on insert)."""
99
+ self._init_client()
100
+ # SurrealDB creates tables automatically
101
+ logger.info(f"Collection '{name}' will be created on first insert")
102
+
103
+ def delete_collection(self, name: str) -> bool:
104
+ """Delete a collection."""
105
+ self._init_client()
106
+ try:
107
+ self._run_async(self._client.query(f"REMOVE TABLE {name}"))
108
+ return True
109
+ except Exception as e:
110
+ logger.error(f"Failed to delete collection {name}: {e}")
111
+ return False
112
+
113
+ def collection_exists(self, name: str) -> bool:
114
+ """Check if collection exists."""
115
+ self._init_client()
116
+ try:
117
+ result = self._run_async(self._client.query(f"INFO FOR TABLE {name}"))
118
+ return bool(result)
119
+ except Exception:
120
+ return False
121
+
122
+ def list_collections(self) -> List[str]:
123
+ """List all collections."""
124
+ self._init_client()
125
+ try:
126
+ result = self._run_async(self._client.query("INFO FOR DB"))
127
+ if result and len(result) > 0:
128
+ tables = result[0].get("result", {}).get("tables", {})
129
+ return list(tables.keys())
130
+ return []
131
+ except Exception as e:
132
+ logger.error(f"Failed to list collections: {e}")
133
+ return []
134
+
135
+ def insert(
136
+ self,
137
+ collection: str,
138
+ documents: List[KnowledgeDocument]
139
+ ) -> List[str]:
140
+ """Insert documents."""
141
+ self._init_client()
142
+
143
+ ids = []
144
+ for doc in documents:
145
+ record = {
146
+ "content": doc.content,
147
+ "embedding": doc.embedding,
148
+ "metadata": doc.metadata or {},
149
+ "content_hash": doc.content_hash,
150
+ "created_at": doc.created_at,
151
+ }
152
+
153
+ try:
154
+ result = self._run_async(
155
+ self._client.create(f"{collection}:{doc.id}", record)
156
+ )
157
+ ids.append(doc.id)
158
+ except Exception as e:
159
+ logger.warning(f"Failed to insert document {doc.id}: {e}")
160
+
161
+ return ids
162
+
163
+ def upsert(
164
+ self,
165
+ collection: str,
166
+ documents: List[KnowledgeDocument]
167
+ ) -> List[str]:
168
+ """Upsert documents."""
169
+ self._init_client()
170
+
171
+ ids = []
172
+ for doc in documents:
173
+ record = {
174
+ "content": doc.content,
175
+ "embedding": doc.embedding,
176
+ "metadata": doc.metadata or {},
177
+ "content_hash": doc.content_hash,
178
+ "created_at": doc.created_at,
179
+ }
180
+
181
+ try:
182
+ self._run_async(
183
+ self._client.update(f"{collection}:{doc.id}", record)
184
+ )
185
+ ids.append(doc.id)
186
+ except Exception as e:
187
+ logger.warning(f"Failed to upsert document {doc.id}: {e}")
188
+
189
+ return ids
190
+
191
+ def search(
192
+ self,
193
+ collection: str,
194
+ query_embedding: List[float],
195
+ limit: int = 5,
196
+ filters: Optional[Dict[str, Any]] = None,
197
+ score_threshold: Optional[float] = None
198
+ ) -> List[KnowledgeDocument]:
199
+ """Search for similar documents using vector search."""
200
+ self._init_client()
201
+
202
+ # SurrealDB vector search query
203
+ embedding_str = str(query_embedding)
204
+ query = f"""
205
+ SELECT *, vector::similarity::cosine(embedding, {embedding_str}) AS score
206
+ FROM {collection}
207
+ ORDER BY score DESC
208
+ LIMIT {limit}
209
+ """
210
+
211
+ try:
212
+ result = self._run_async(self._client.query(query))
213
+
214
+ documents = []
215
+ if result and len(result) > 0:
216
+ for row in result[0].get("result", []):
217
+ score = row.get("score", 0)
218
+ if score_threshold and score < score_threshold:
219
+ continue
220
+
221
+ doc_id = str(row.get("id", "")).split(":")[-1]
222
+ documents.append(KnowledgeDocument(
223
+ id=doc_id,
224
+ content=row.get("content", ""),
225
+ embedding=row.get("embedding"),
226
+ metadata={**(row.get("metadata") or {}), "score": score},
227
+ content_hash=row.get("content_hash"),
228
+ created_at=row.get("created_at", 0)
229
+ ))
230
+
231
+ return documents
232
+ except Exception as e:
233
+ logger.error(f"Vector search failed: {e}")
234
+ return []
235
+
236
+ def get(
237
+ self,
238
+ collection: str,
239
+ ids: List[str]
240
+ ) -> List[KnowledgeDocument]:
241
+ """Get documents by IDs."""
242
+ self._init_client()
243
+
244
+ documents = []
245
+ for doc_id in ids:
246
+ try:
247
+ result = self._run_async(self._client.select(f"{collection}:{doc_id}"))
248
+ if result:
249
+ row = result if isinstance(result, dict) else result[0]
250
+ documents.append(KnowledgeDocument(
251
+ id=doc_id,
252
+ content=row.get("content", ""),
253
+ embedding=row.get("embedding"),
254
+ metadata=row.get("metadata"),
255
+ content_hash=row.get("content_hash"),
256
+ created_at=row.get("created_at", 0)
257
+ ))
258
+ except Exception as e:
259
+ logger.warning(f"Failed to get document {doc_id}: {e}")
260
+
261
+ return documents
262
+
263
+ def delete(
264
+ self,
265
+ collection: str,
266
+ ids: Optional[List[str]] = None,
267
+ filters: Optional[Dict[str, Any]] = None
268
+ ) -> int:
269
+ """Delete documents."""
270
+ self._init_client()
271
+
272
+ count = 0
273
+ if ids:
274
+ for doc_id in ids:
275
+ try:
276
+ self._run_async(self._client.delete(f"{collection}:{doc_id}"))
277
+ count += 1
278
+ except Exception as e:
279
+ logger.warning(f"Failed to delete {doc_id}: {e}")
280
+ else:
281
+ try:
282
+ self._run_async(self._client.query(f"DELETE FROM {collection}"))
283
+ count = -1 # Unknown count
284
+ except Exception as e:
285
+ logger.error(f"Failed to delete all: {e}")
286
+
287
+ return count
288
+
289
+ def count(self, collection: str) -> int:
290
+ """Count documents."""
291
+ self._init_client()
292
+
293
+ try:
294
+ result = self._run_async(
295
+ self._client.query(f"SELECT count() FROM {collection} GROUP ALL")
296
+ )
297
+ if result and len(result) > 0:
298
+ return result[0].get("result", [{}])[0].get("count", 0)
299
+ return 0
300
+ except Exception as e:
301
+ logger.error(f"Count failed: {e}")
302
+ return 0
303
+
304
+ def close(self) -> None:
305
+ """Close the connection."""
306
+ if self._client:
307
+ self._run_async(self._client.close())
308
+ self._client = None
309
+ self._initialized = False
@@ -0,0 +1,266 @@
1
+ """
2
+ Upstash Vector implementation of KnowledgeStore.
3
+
4
+ Requires: upstash-vector
5
+ Install: pip install upstash-vector
6
+ """
7
+
8
+ import logging
9
+ import os
10
+ from typing import Any, Dict, List, Optional
11
+
12
+ from .base import KnowledgeStore, KnowledgeDocument
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class UpstashVectorKnowledgeStore(KnowledgeStore):
18
+ """
19
+ Upstash Vector store for knowledge/RAG.
20
+
21
+ Uses Upstash's serverless vector database.
22
+
23
+ Example:
24
+ store = UpstashVectorKnowledgeStore(
25
+ url="https://xxx.upstash.io",
26
+ token="your-token"
27
+ )
28
+ """
29
+
30
+ def __init__(
31
+ self,
32
+ url: Optional[str] = None,
33
+ token: Optional[str] = None,
34
+ embedding_dim: int = 1536,
35
+ ):
36
+ """
37
+ Initialize Upstash Vector store.
38
+
39
+ Args:
40
+ url: Upstash Vector REST URL (or UPSTASH_VECTOR_REST_URL env)
41
+ token: Upstash Vector REST token (or UPSTASH_VECTOR_REST_TOKEN env)
42
+ embedding_dim: Embedding dimension
43
+ """
44
+ self.url = url or os.getenv("UPSTASH_VECTOR_REST_URL")
45
+ self.token = token or os.getenv("UPSTASH_VECTOR_REST_TOKEN")
46
+ self.embedding_dim = embedding_dim
47
+
48
+ self._index = None
49
+ self._initialized = False
50
+
51
+ def _init_client(self):
52
+ """Initialize Upstash client lazily."""
53
+ if self._initialized:
54
+ return
55
+
56
+ if not self.url or not self.token:
57
+ raise ValueError(
58
+ "Upstash Vector requires url and token. "
59
+ "Set UPSTASH_VECTOR_REST_URL and UPSTASH_VECTOR_REST_TOKEN env vars."
60
+ )
61
+
62
+ try:
63
+ from upstash_vector import Index
64
+ except ImportError:
65
+ raise ImportError(
66
+ "upstash-vector is required for Upstash Vector support. "
67
+ "Install with: pip install upstash-vector"
68
+ )
69
+
70
+ self._index = Index(url=self.url, token=self.token)
71
+ self._initialized = True
72
+
73
+ def create_collection(
74
+ self,
75
+ name: str,
76
+ dimension: int = 1536,
77
+ distance: str = "cosine",
78
+ metadata: Optional[Dict[str, Any]] = None
79
+ ) -> None:
80
+ """Create collection (Upstash uses namespaces)."""
81
+ self._init_client()
82
+ # Upstash Vector uses a single index with namespaces
83
+ logger.info(f"Using namespace '{name}' in Upstash Vector index")
84
+
85
+ def delete_collection(self, name: str) -> bool:
86
+ """Delete all vectors in namespace."""
87
+ self._init_client()
88
+ try:
89
+ self._index.delete_namespace(name)
90
+ return True
91
+ except Exception as e:
92
+ logger.error(f"Failed to delete namespace {name}: {e}")
93
+ return False
94
+
95
+ def collection_exists(self, name: str) -> bool:
96
+ """Check if namespace has vectors."""
97
+ self._init_client()
98
+ try:
99
+ info = self._index.info()
100
+ namespaces = info.namespaces if hasattr(info, 'namespaces') else {}
101
+ return name in namespaces
102
+ except Exception:
103
+ return False
104
+
105
+ def list_collections(self) -> List[str]:
106
+ """List all namespaces."""
107
+ self._init_client()
108
+ try:
109
+ info = self._index.info()
110
+ namespaces = info.namespaces if hasattr(info, 'namespaces') else {}
111
+ return list(namespaces.keys())
112
+ except Exception as e:
113
+ logger.error(f"Failed to list namespaces: {e}")
114
+ return []
115
+
116
+ def insert(
117
+ self,
118
+ collection: str,
119
+ documents: List[KnowledgeDocument]
120
+ ) -> List[str]:
121
+ """Insert documents."""
122
+ self._init_client()
123
+
124
+ vectors = []
125
+ for doc in documents:
126
+ if not doc.embedding:
127
+ logger.warning(f"Document {doc.id} has no embedding, skipping")
128
+ continue
129
+
130
+ vectors.append({
131
+ "id": doc.id,
132
+ "vector": doc.embedding,
133
+ "metadata": {
134
+ "content": doc.content,
135
+ **(doc.metadata or {}),
136
+ "content_hash": doc.content_hash,
137
+ "created_at": doc.created_at,
138
+ }
139
+ })
140
+
141
+ if vectors:
142
+ self._index.upsert(vectors, namespace=collection)
143
+
144
+ return [v["id"] for v in vectors]
145
+
146
+ def upsert(
147
+ self,
148
+ collection: str,
149
+ documents: List[KnowledgeDocument]
150
+ ) -> List[str]:
151
+ """Upsert documents (same as insert for Upstash)."""
152
+ return self.insert(collection, documents)
153
+
154
+ def search(
155
+ self,
156
+ collection: str,
157
+ query_embedding: List[float],
158
+ limit: int = 5,
159
+ filters: Optional[Dict[str, Any]] = None,
160
+ score_threshold: Optional[float] = None
161
+ ) -> List[KnowledgeDocument]:
162
+ """Search for similar documents."""
163
+ self._init_client()
164
+
165
+ try:
166
+ results = self._index.query(
167
+ vector=query_embedding,
168
+ top_k=limit,
169
+ include_metadata=True,
170
+ namespace=collection,
171
+ filter=filters
172
+ )
173
+
174
+ documents = []
175
+ for result in results:
176
+ score = result.score if hasattr(result, 'score') else 0
177
+ if score_threshold and score < score_threshold:
178
+ continue
179
+
180
+ metadata = result.metadata if hasattr(result, 'metadata') else {}
181
+ content = metadata.pop("content", "") if metadata else ""
182
+
183
+ documents.append(KnowledgeDocument(
184
+ id=result.id,
185
+ content=content,
186
+ metadata={**metadata, "score": score},
187
+ content_hash=metadata.get("content_hash") if metadata else None,
188
+ created_at=metadata.get("created_at", 0) if metadata else 0
189
+ ))
190
+
191
+ return documents
192
+ except Exception as e:
193
+ logger.error(f"Search failed: {e}")
194
+ return []
195
+
196
+ def get(
197
+ self,
198
+ collection: str,
199
+ ids: List[str]
200
+ ) -> List[KnowledgeDocument]:
201
+ """Get documents by IDs."""
202
+ self._init_client()
203
+
204
+ documents = []
205
+ try:
206
+ results = self._index.fetch(ids, include_metadata=True, namespace=collection)
207
+
208
+ for result in results:
209
+ if result:
210
+ metadata = result.metadata if hasattr(result, 'metadata') else {}
211
+ content = metadata.pop("content", "") if metadata else ""
212
+
213
+ documents.append(KnowledgeDocument(
214
+ id=result.id,
215
+ content=content,
216
+ embedding=result.vector if hasattr(result, 'vector') else None,
217
+ metadata=metadata,
218
+ content_hash=metadata.get("content_hash") if metadata else None,
219
+ created_at=metadata.get("created_at", 0) if metadata else 0
220
+ ))
221
+ except Exception as e:
222
+ logger.error(f"Fetch failed: {e}")
223
+
224
+ return documents
225
+
226
+ def delete(
227
+ self,
228
+ collection: str,
229
+ ids: Optional[List[str]] = None,
230
+ filters: Optional[Dict[str, Any]] = None
231
+ ) -> int:
232
+ """Delete documents."""
233
+ self._init_client()
234
+
235
+ try:
236
+ if ids:
237
+ self._index.delete(ids, namespace=collection)
238
+ return len(ids)
239
+ elif filters:
240
+ # Upstash doesn't support filter-based delete directly
241
+ logger.warning("Filter-based delete not supported, use IDs")
242
+ return 0
243
+ else:
244
+ self._index.delete_namespace(collection)
245
+ return -1 # Unknown count
246
+ except Exception as e:
247
+ logger.error(f"Delete failed: {e}")
248
+ return 0
249
+
250
+ def count(self, collection: str) -> int:
251
+ """Count documents in namespace."""
252
+ self._init_client()
253
+
254
+ try:
255
+ info = self._index.info()
256
+ namespaces = info.namespaces if hasattr(info, 'namespaces') else {}
257
+ ns_info = namespaces.get(collection, {})
258
+ return ns_info.get("vector_count", 0) if isinstance(ns_info, dict) else 0
259
+ except Exception as e:
260
+ logger.error(f"Count failed: {e}")
261
+ return 0
262
+
263
+ def close(self) -> None:
264
+ """Close the client."""
265
+ self._index = None
266
+ self._initialized = False