praisonai-code 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. praisonai_code/__init__.py +17 -0
  2. praisonai_code/cli/__init__.py +12 -0
  3. praisonai_code/cli/_forward_shim.py +10 -0
  4. praisonai_code/cli/_paths.py +88 -0
  5. praisonai_code/cli/_warnings.py +58 -0
  6. praisonai_code/cli/app.py +757 -0
  7. praisonai_code/cli/approval_backend.py +272 -0
  8. praisonai_code/cli/branding.py +94 -0
  9. praisonai_code/cli/commands/__init__.py +114 -0
  10. praisonai_code/cli/commands/acp.py +80 -0
  11. praisonai_code/cli/commands/agent.py +116 -0
  12. praisonai_code/cli/commands/agents.py +80 -0
  13. praisonai_code/cli/commands/app.py +139 -0
  14. praisonai_code/cli/commands/attach.py +95 -0
  15. praisonai_code/cli/commands/audit.py +102 -0
  16. praisonai_code/cli/commands/auth.py +508 -0
  17. praisonai_code/cli/commands/batch.py +848 -0
  18. praisonai_code/cli/commands/benchmark.py +286 -0
  19. praisonai_code/cli/commands/browser.py +299 -0
  20. praisonai_code/cli/commands/call.py +45 -0
  21. praisonai_code/cli/commands/chat.py +332 -0
  22. praisonai_code/cli/commands/checkpoint.py +170 -0
  23. praisonai_code/cli/commands/code.py +276 -0
  24. praisonai_code/cli/commands/command.py +114 -0
  25. praisonai_code/cli/commands/commit.py +47 -0
  26. praisonai_code/cli/commands/completion.py +333 -0
  27. praisonai_code/cli/commands/config.py +681 -0
  28. praisonai_code/cli/commands/context.py +414 -0
  29. praisonai_code/cli/commands/daemon.py +203 -0
  30. praisonai_code/cli/commands/debug.py +142 -0
  31. praisonai_code/cli/commands/deploy.py +71 -0
  32. praisonai_code/cli/commands/diag.py +55 -0
  33. praisonai_code/cli/commands/docs.py +1575 -0
  34. praisonai_code/cli/commands/doctor.py +332 -0
  35. praisonai_code/cli/commands/endpoints.py +51 -0
  36. praisonai_code/cli/commands/environment.py +179 -0
  37. praisonai_code/cli/commands/eval.py +131 -0
  38. praisonai_code/cli/commands/examples.py +953 -0
  39. praisonai_code/cli/commands/flow.py +436 -0
  40. praisonai_code/cli/commands/github.py +752 -0
  41. praisonai_code/cli/commands/hooks.py +74 -0
  42. praisonai_code/cli/commands/init.py +174 -0
  43. praisonai_code/cli/commands/knowledge.py +440 -0
  44. praisonai_code/cli/commands/langextract.py +120 -0
  45. praisonai_code/cli/commands/langfuse.py +984 -0
  46. praisonai_code/cli/commands/loop.py +211 -0
  47. praisonai_code/cli/commands/lsp.py +112 -0
  48. praisonai_code/cli/commands/managed.py +659 -0
  49. praisonai_code/cli/commands/mcp.py +763 -0
  50. praisonai_code/cli/commands/memory.py +298 -0
  51. praisonai_code/cli/commands/models.py +264 -0
  52. praisonai_code/cli/commands/n8n.py +326 -0
  53. praisonai_code/cli/commands/obs.py +19 -0
  54. praisonai_code/cli/commands/package.py +76 -0
  55. praisonai_code/cli/commands/paths.py +106 -0
  56. praisonai_code/cli/commands/permissions.py +272 -0
  57. praisonai_code/cli/commands/plugins.py +609 -0
  58. praisonai_code/cli/commands/port.py +530 -0
  59. praisonai_code/cli/commands/profile.py +466 -0
  60. praisonai_code/cli/commands/publish.py +193 -0
  61. praisonai_code/cli/commands/rag.py +913 -0
  62. praisonai_code/cli/commands/realtime.py +52 -0
  63. praisonai_code/cli/commands/recipe.py +684 -0
  64. praisonai_code/cli/commands/registry.py +59 -0
  65. praisonai_code/cli/commands/replay.py +830 -0
  66. praisonai_code/cli/commands/research.py +49 -0
  67. praisonai_code/cli/commands/retrieval.py +377 -0
  68. praisonai_code/cli/commands/rules.py +71 -0
  69. praisonai_code/cli/commands/run.py +1573 -0
  70. praisonai_code/cli/commands/sandbox.py +371 -0
  71. praisonai_code/cli/commands/schedule.py +529 -0
  72. praisonai_code/cli/commands/serve.py +690 -0
  73. praisonai_code/cli/commands/session.py +450 -0
  74. praisonai_code/cli/commands/setup.py +174 -0
  75. praisonai_code/cli/commands/skills.py +545 -0
  76. praisonai_code/cli/commands/standardise.py +711 -0
  77. praisonai_code/cli/commands/templates.py +54 -0
  78. praisonai_code/cli/commands/test.py +558 -0
  79. praisonai_code/cli/commands/todo.py +74 -0
  80. praisonai_code/cli/commands/tools.py +205 -0
  81. praisonai_code/cli/commands/traces.py +145 -0
  82. praisonai_code/cli/commands/tracker.py +852 -0
  83. praisonai_code/cli/commands/train.py +613 -0
  84. praisonai_code/cli/commands/ui.py +172 -0
  85. praisonai_code/cli/commands/up.py +354 -0
  86. praisonai_code/cli/commands/validate.py +291 -0
  87. praisonai_code/cli/commands/version.py +101 -0
  88. praisonai_code/cli/commands/workflow.py +97 -0
  89. praisonai_code/cli/config_loader.py +437 -0
  90. praisonai_code/cli/configuration/__init__.py +27 -0
  91. praisonai_code/cli/configuration/config.schema.json +57 -0
  92. praisonai_code/cli/configuration/credentials.py +446 -0
  93. praisonai_code/cli/configuration/loader.py +364 -0
  94. praisonai_code/cli/configuration/model_resolver.py +161 -0
  95. praisonai_code/cli/configuration/oauth.py +389 -0
  96. praisonai_code/cli/configuration/paths.py +224 -0
  97. praisonai_code/cli/configuration/resolver.py +687 -0
  98. praisonai_code/cli/configuration/schema.py +317 -0
  99. praisonai_code/cli/execution/__init__.py +99 -0
  100. praisonai_code/cli/execution/core.py +208 -0
  101. praisonai_code/cli/execution/profiler.py +898 -0
  102. praisonai_code/cli/execution/request.py +85 -0
  103. praisonai_code/cli/execution/result.py +74 -0
  104. praisonai_code/cli/fallback_schema.py +416 -0
  105. praisonai_code/cli/features/__init__.py +278 -0
  106. praisonai_code/cli/features/_endpoint_registry.py +64 -0
  107. praisonai_code/cli/features/_search_registry.py +43 -0
  108. praisonai_code/cli/features/acp.py +236 -0
  109. praisonai_code/cli/features/action_orchestrator.py +576 -0
  110. praisonai_code/cli/features/agent_scheduler.py +773 -0
  111. praisonai_code/cli/features/agent_tools.py +603 -0
  112. praisonai_code/cli/features/agents.py +397 -0
  113. praisonai_code/cli/features/at_mentions.py +471 -0
  114. praisonai_code/cli/features/audit_cli.py +270 -0
  115. praisonai_code/cli/features/auto_memory.py +182 -0
  116. praisonai_code/cli/features/auto_mode.py +552 -0
  117. praisonai_code/cli/features/autonomy_mode.py +546 -0
  118. praisonai_code/cli/features/background.py +356 -0
  119. praisonai_code/cli/features/base.py +168 -0
  120. praisonai_code/cli/features/benchmark.py +1462 -0
  121. praisonai_code/cli/features/capabilities.py +1326 -0
  122. praisonai_code/cli/features/checkpoints.py +345 -0
  123. praisonai_code/cli/features/cli_profiler.py +335 -0
  124. praisonai_code/cli/features/code_intelligence.py +666 -0
  125. praisonai_code/cli/features/compaction.py +294 -0
  126. praisonai_code/cli/features/compare.py +534 -0
  127. praisonai_code/cli/features/config_hierarchy.py +366 -0
  128. praisonai_code/cli/features/context_manager.py +597 -0
  129. praisonai_code/cli/features/cost_tracker.py +514 -0
  130. praisonai_code/cli/features/csv_test_runner.py +736 -0
  131. praisonai_code/cli/features/custom_definitions.py +790 -0
  132. praisonai_code/cli/features/debug.py +810 -0
  133. praisonai_code/cli/features/deploy.py +605 -0
  134. praisonai_code/cli/features/diag.py +289 -0
  135. praisonai_code/cli/features/display_jsonl.py +173 -0
  136. praisonai_code/cli/features/doctor/__init__.py +63 -0
  137. praisonai_code/cli/features/doctor/checks/__init__.py +29 -0
  138. praisonai_code/cli/features/doctor/checks/acp_checks.py +220 -0
  139. praisonai_code/cli/features/doctor/checks/bot_checks.py +340 -0
  140. praisonai_code/cli/features/doctor/checks/config_checks.py +373 -0
  141. praisonai_code/cli/features/doctor/checks/db_checks.py +366 -0
  142. praisonai_code/cli/features/doctor/checks/env_checks.py +637 -0
  143. praisonai_code/cli/features/doctor/checks/gateway_checks.py +387 -0
  144. praisonai_code/cli/features/doctor/checks/lsp_checks.py +231 -0
  145. praisonai_code/cli/features/doctor/checks/mcp_checks.py +367 -0
  146. praisonai_code/cli/features/doctor/checks/memory_checks.py +268 -0
  147. praisonai_code/cli/features/doctor/checks/network_checks.py +251 -0
  148. praisonai_code/cli/features/doctor/checks/obs_checks.py +328 -0
  149. praisonai_code/cli/features/doctor/checks/packaging_checks.py +422 -0
  150. praisonai_code/cli/features/doctor/checks/performance_checks.py +235 -0
  151. praisonai_code/cli/features/doctor/checks/permissions_checks.py +259 -0
  152. praisonai_code/cli/features/doctor/checks/runtime_checks.py +650 -0
  153. praisonai_code/cli/features/doctor/checks/runtime_migration_checks.py +220 -0
  154. praisonai_code/cli/features/doctor/checks/selftest_checks.py +322 -0
  155. praisonai_code/cli/features/doctor/checks/serve_checks.py +426 -0
  156. praisonai_code/cli/features/doctor/checks/skills_checks.py +327 -0
  157. praisonai_code/cli/features/doctor/checks/tools_checks.py +371 -0
  158. praisonai_code/cli/features/doctor/engine.py +266 -0
  159. praisonai_code/cli/features/doctor/formatters.py +377 -0
  160. praisonai_code/cli/features/doctor/handler.py +564 -0
  161. praisonai_code/cli/features/doctor/models.py +276 -0
  162. praisonai_code/cli/features/doctor/registry.py +239 -0
  163. praisonai_code/cli/features/endpoints.py +1016 -0
  164. praisonai_code/cli/features/eval.py +559 -0
  165. praisonai_code/cli/features/examples.py +707 -0
  166. praisonai_code/cli/features/external_agents.py +231 -0
  167. praisonai_code/cli/features/fast_context.py +410 -0
  168. praisonai_code/cli/features/file_history.py +320 -0
  169. praisonai_code/cli/features/flow_display.py +566 -0
  170. praisonai_code/cli/features/git_attribution.py +159 -0
  171. praisonai_code/cli/features/git_integration.py +651 -0
  172. praisonai_code/cli/features/guardrail.py +171 -0
  173. praisonai_code/cli/features/handoff.py +252 -0
  174. praisonai_code/cli/features/hooks.py +583 -0
  175. praisonai_code/cli/features/hybrid_workflow.py +391 -0
  176. praisonai_code/cli/features/image.py +384 -0
  177. praisonai_code/cli/features/interactive_core_headless.py +450 -0
  178. praisonai_code/cli/features/interactive_runtime.py +600 -0
  179. praisonai_code/cli/features/interactive_test_harness.py +537 -0
  180. praisonai_code/cli/features/interactive_tools.py +428 -0
  181. praisonai_code/cli/features/interactive_tui.py +603 -0
  182. praisonai_code/cli/features/job_workflow.py +906 -0
  183. praisonai_code/cli/features/jobs.py +632 -0
  184. praisonai_code/cli/features/knowledge.py +531 -0
  185. praisonai_code/cli/features/knowledge_cli.py +438 -0
  186. praisonai_code/cli/features/lite.py +244 -0
  187. praisonai_code/cli/features/logs.py +200 -0
  188. praisonai_code/cli/features/lsp_cli.py +225 -0
  189. praisonai_code/cli/features/lsp_diagnostics.py +185 -0
  190. praisonai_code/cli/features/mcp.py +344 -0
  191. praisonai_code/cli/features/message_queue.py +587 -0
  192. praisonai_code/cli/features/metrics.py +210 -0
  193. praisonai_code/cli/features/migrate.py +1329 -0
  194. praisonai_code/cli/features/migration_flow.py +463 -0
  195. praisonai_code/cli/features/migration_spec.py +276 -0
  196. praisonai_code/cli/features/n8n.py +703 -0
  197. praisonai_code/cli/features/observability.py +293 -0
  198. praisonai_code/cli/features/ollama.py +361 -0
  199. praisonai_code/cli/features/output_modes.py +155 -0
  200. praisonai_code/cli/features/output_style.py +273 -0
  201. praisonai_code/cli/features/package.py +631 -0
  202. praisonai_code/cli/features/performance.py +308 -0
  203. praisonai_code/cli/features/persistence.py +636 -0
  204. praisonai_code/cli/features/profiler/__init__.py +81 -0
  205. praisonai_code/cli/features/profiler/core.py +558 -0
  206. praisonai_code/cli/features/profiler/optimizations.py +652 -0
  207. praisonai_code/cli/features/profiler/suite.py +386 -0
  208. praisonai_code/cli/features/queue/__init__.py +73 -0
  209. praisonai_code/cli/features/queue/manager.py +435 -0
  210. praisonai_code/cli/features/queue/models.py +289 -0
  211. praisonai_code/cli/features/queue/persistence.py +564 -0
  212. praisonai_code/cli/features/queue/scheduler.py +529 -0
  213. praisonai_code/cli/features/queue/worker.py +400 -0
  214. praisonai_code/cli/features/recipe.py +2187 -0
  215. praisonai_code/cli/features/recipe_creator.py +996 -0
  216. praisonai_code/cli/features/recipe_optimizer.py +1364 -0
  217. praisonai_code/cli/features/recipe_prompts.py +226 -0
  218. praisonai_code/cli/features/registry.py +229 -0
  219. praisonai_code/cli/features/repo_map.py +860 -0
  220. praisonai_code/cli/features/router.py +466 -0
  221. praisonai_code/cli/features/safe_shell.py +427 -0
  222. praisonai_code/cli/features/sandbox_cli.py +283 -0
  223. praisonai_code/cli/features/sandbox_executor.py +536 -0
  224. praisonai_code/cli/features/sdk_knowledge.py +500 -0
  225. praisonai_code/cli/features/session.py +222 -0
  226. praisonai_code/cli/features/session_checkpoints.py +208 -0
  227. praisonai_code/cli/features/setup/__init__.py +9 -0
  228. praisonai_code/cli/features/setup/handler.py +355 -0
  229. praisonai_code/cli/features/setup/templates.py +62 -0
  230. praisonai_code/cli/features/skills.py +940 -0
  231. praisonai_code/cli/features/slash_commands.py +692 -0
  232. praisonai_code/cli/features/telemetry.py +179 -0
  233. praisonai_code/cli/features/templates.py +1390 -0
  234. praisonai_code/cli/features/thinking.py +343 -0
  235. praisonai_code/cli/features/todo.py +334 -0
  236. praisonai_code/cli/features/tools.py +680 -0
  237. praisonai_code/cli/features/tui/__init__.py +83 -0
  238. praisonai_code/cli/features/tui/app.py +871 -0
  239. praisonai_code/cli/features/tui/cli.py +580 -0
  240. praisonai_code/cli/features/tui/config.py +150 -0
  241. praisonai_code/cli/features/tui/debug.py +526 -0
  242. praisonai_code/cli/features/tui/events.py +99 -0
  243. praisonai_code/cli/features/tui/mock_provider.py +328 -0
  244. praisonai_code/cli/features/tui/orchestrator.py +652 -0
  245. praisonai_code/cli/features/tui/screens/__init__.py +50 -0
  246. praisonai_code/cli/features/tui/screens/help.py +157 -0
  247. praisonai_code/cli/features/tui/screens/main.py +568 -0
  248. praisonai_code/cli/features/tui/screens/queue.py +174 -0
  249. praisonai_code/cli/features/tui/screens/session.py +124 -0
  250. praisonai_code/cli/features/tui/screens/settings.py +148 -0
  251. praisonai_code/cli/features/tui/session_store.py +198 -0
  252. praisonai_code/cli/features/tui/widgets/__init__.py +56 -0
  253. praisonai_code/cli/features/tui/widgets/chat.py +263 -0
  254. praisonai_code/cli/features/tui/widgets/command_popup.py +258 -0
  255. praisonai_code/cli/features/tui/widgets/composer.py +292 -0
  256. praisonai_code/cli/features/tui/widgets/file_popup.py +207 -0
  257. praisonai_code/cli/features/tui/widgets/queue_panel.py +223 -0
  258. praisonai_code/cli/features/tui/widgets/status.py +181 -0
  259. praisonai_code/cli/features/tui/widgets/tool_panel.py +307 -0
  260. praisonai_code/cli/features/wizard.py +289 -0
  261. praisonai_code/cli/features/workflow.py +802 -0
  262. praisonai_code/cli/features/yaml_utils.py +321 -0
  263. praisonai_code/cli/interactive/__init__.py +48 -0
  264. praisonai_code/cli/interactive/async_tui.py +1218 -0
  265. praisonai_code/cli/interactive/config.py +139 -0
  266. praisonai_code/cli/interactive/core.py +618 -0
  267. praisonai_code/cli/interactive/events.py +131 -0
  268. praisonai_code/cli/interactive/frontends/__init__.py +31 -0
  269. praisonai_code/cli/interactive/frontends/rich_frontend.py +462 -0
  270. praisonai_code/cli/interactive/frontends/textual_frontend.py +157 -0
  271. praisonai_code/cli/interactive/praison_io.py +502 -0
  272. praisonai_code/cli/interactive/repl.py +297 -0
  273. praisonai_code/cli/interactive/split_tui.py +456 -0
  274. praisonai_code/cli/interactive/tui_app.py +457 -0
  275. praisonai_code/cli/langfuse_client.py +360 -0
  276. praisonai_code/cli/main.py +7421 -0
  277. praisonai_code/cli/output/__init__.py +25 -0
  278. praisonai_code/cli/output/console.py +456 -0
  279. praisonai_code/cli/output/event_bridge.py +191 -0
  280. praisonai_code/cli/schedule_cli.py +54 -0
  281. praisonai_code/cli/schema_provider.py +23 -0
  282. praisonai_code/cli/session/__init__.py +16 -0
  283. praisonai_code/cli/session/resume.py +148 -0
  284. praisonai_code/cli/session/unified.py +548 -0
  285. praisonai_code/cli/state/__init__.py +31 -0
  286. praisonai_code/cli/state/identifiers.py +161 -0
  287. praisonai_code/cli/state/project_sessions.py +383 -0
  288. praisonai_code/cli/state/sessions.py +390 -0
  289. praisonai_code/cli/ui/__init__.py +160 -0
  290. praisonai_code/cli/ui/config.py +46 -0
  291. praisonai_code/cli/ui/events.py +61 -0
  292. praisonai_code/cli/ui/mg_backend.py +342 -0
  293. praisonai_code/cli/ui/plain.py +133 -0
  294. praisonai_code/cli/ui/rich_backend.py +162 -0
  295. praisonai_code/cli/unified_schema.py +655 -0
  296. praisonai_code/cli/utils/env_utils.py +126 -0
  297. praisonai_code/cli/utils/project.py +131 -0
  298. praisonai_code/cli_backends/__init__.py +73 -0
  299. praisonai_code/cli_backends/claude.py +373 -0
  300. praisonai_code/cli_backends/registry.py +113 -0
  301. praisonai_code/runtime/__init__.py +36 -0
  302. praisonai_code/runtime/__main__.py +81 -0
  303. praisonai_code/runtime/client.py +131 -0
  304. praisonai_code/runtime/descriptor.py +209 -0
  305. praisonai_code/runtime/server.py +356 -0
  306. praisonai_code-0.0.1.dist-info/METADATA +80 -0
  307. praisonai_code-0.0.1.dist-info/RECORD +309 -0
  308. praisonai_code-0.0.1.dist-info/WHEEL +5 -0
  309. praisonai_code-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,289 @@
1
+ """
2
+ Data models for the PraisonAI Queue System.
3
+
4
+ Defines QueuedRun, RunState, RunPriority, and QueueConfig.
5
+ """
6
+
7
+ from dataclasses import dataclass, field
8
+ from enum import Enum, IntEnum
9
+ from typing import Any, Dict, List, Optional
10
+ import time
11
+ import uuid
12
+
13
+
14
+ class RunState(str, Enum):
15
+ """State of a queued run."""
16
+ QUEUED = "queued"
17
+ RUNNING = "running"
18
+ PAUSED = "paused"
19
+ SUCCEEDED = "succeeded"
20
+ FAILED = "failed"
21
+ CANCELLED = "cancelled"
22
+
23
+ def is_terminal(self) -> bool:
24
+ """Check if this is a terminal state."""
25
+ return self in (RunState.SUCCEEDED, RunState.FAILED, RunState.CANCELLED)
26
+
27
+ def is_active(self) -> bool:
28
+ """Check if this is an active (non-terminal) state."""
29
+ return not self.is_terminal()
30
+
31
+
32
+ class RunPriority(IntEnum):
33
+ """Priority levels for queued runs. Higher value = higher priority."""
34
+ LOW = 0
35
+ NORMAL = 1
36
+ HIGH = 2
37
+ URGENT = 3
38
+
39
+ @classmethod
40
+ def from_string(cls, s: str) -> "RunPriority":
41
+ """Parse priority from string."""
42
+ mapping = {
43
+ "low": cls.LOW,
44
+ "normal": cls.NORMAL,
45
+ "high": cls.HIGH,
46
+ "urgent": cls.URGENT,
47
+ }
48
+ return mapping.get(s.lower(), cls.NORMAL)
49
+
50
+
51
+ @dataclass
52
+ class QueuedRun:
53
+ """A single queued agent run."""
54
+
55
+ # Identity
56
+ run_id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
57
+ agent_name: str = ""
58
+ input_content: str = ""
59
+
60
+ # State
61
+ state: RunState = RunState.QUEUED
62
+ priority: RunPriority = RunPriority.NORMAL
63
+
64
+ # Attribution / tracing
65
+ session_id: Optional[str] = None
66
+ trace_id: Optional[str] = None
67
+ workspace: Optional[str] = None
68
+ user_id: Optional[str] = None
69
+
70
+ # Timing
71
+ created_at: float = field(default_factory=time.time)
72
+ started_at: Optional[float] = None
73
+ ended_at: Optional[float] = None
74
+
75
+ # Results
76
+ output_content: Optional[str] = None
77
+ error: Optional[str] = None
78
+ metrics: Dict[str, Any] = field(default_factory=dict)
79
+
80
+ # Retry tracking
81
+ retry_count: int = 0
82
+ max_retries: int = 3
83
+ parent_run_id: Optional[str] = None # Link to original run if this is a retry
84
+
85
+ # Configuration
86
+ config: Dict[str, Any] = field(default_factory=dict)
87
+
88
+ # Chat history for session continuity
89
+ chat_history: List[Dict[str, str]] = field(default_factory=list)
90
+
91
+ # Streaming state
92
+ output_chunks: List[str] = field(default_factory=list)
93
+
94
+ def __post_init__(self):
95
+ """Ensure proper types after initialization."""
96
+ if isinstance(self.state, str):
97
+ self.state = RunState(self.state)
98
+ if isinstance(self.priority, int) and not isinstance(self.priority, RunPriority):
99
+ self.priority = RunPriority(self.priority)
100
+
101
+ @property
102
+ def duration_seconds(self) -> Optional[float]:
103
+ """Get run duration in seconds."""
104
+ if self.started_at is None:
105
+ return None
106
+ end = self.ended_at or time.time()
107
+ return end - self.started_at
108
+
109
+ @property
110
+ def wait_seconds(self) -> float:
111
+ """Get time spent waiting in queue."""
112
+ start = self.started_at or time.time()
113
+ return start - self.created_at
114
+
115
+ def can_retry(self) -> bool:
116
+ """Check if this run can be retried."""
117
+ return (
118
+ self.state == RunState.FAILED and
119
+ self.retry_count < self.max_retries
120
+ )
121
+
122
+ def to_dict(self) -> Dict[str, Any]:
123
+ """Convert to dictionary for persistence."""
124
+ return {
125
+ "run_id": self.run_id,
126
+ "agent_name": self.agent_name,
127
+ "input_content": self.input_content,
128
+ "state": self.state.value,
129
+ "priority": int(self.priority),
130
+ "session_id": self.session_id,
131
+ "trace_id": self.trace_id,
132
+ "workspace": self.workspace,
133
+ "user_id": self.user_id,
134
+ "created_at": self.created_at,
135
+ "started_at": self.started_at,
136
+ "ended_at": self.ended_at,
137
+ "output_content": self.output_content,
138
+ "error": self.error,
139
+ "metrics": self.metrics,
140
+ "retry_count": self.retry_count,
141
+ "max_retries": self.max_retries,
142
+ "parent_run_id": self.parent_run_id,
143
+ "config": self.config,
144
+ }
145
+
146
+ @classmethod
147
+ def from_dict(cls, data: Dict[str, Any]) -> "QueuedRun":
148
+ """Create from dictionary."""
149
+ # Handle state conversion
150
+ state = data.get("state", "queued")
151
+ if isinstance(state, str):
152
+ state = RunState(state)
153
+
154
+ # Handle priority conversion
155
+ priority = data.get("priority", 1)
156
+ if isinstance(priority, int):
157
+ priority = RunPriority(priority)
158
+
159
+ return cls(
160
+ run_id=data.get("run_id", str(uuid.uuid4())[:8]),
161
+ agent_name=data.get("agent_name", ""),
162
+ input_content=data.get("input_content", ""),
163
+ state=state,
164
+ priority=priority,
165
+ session_id=data.get("session_id"),
166
+ trace_id=data.get("trace_id"),
167
+ workspace=data.get("workspace"),
168
+ user_id=data.get("user_id"),
169
+ created_at=data.get("created_at", time.time()),
170
+ started_at=data.get("started_at"),
171
+ ended_at=data.get("ended_at"),
172
+ output_content=data.get("output_content"),
173
+ error=data.get("error"),
174
+ metrics=data.get("metrics", {}),
175
+ retry_count=data.get("retry_count", 0),
176
+ max_retries=data.get("max_retries", 3),
177
+ parent_run_id=data.get("parent_run_id"),
178
+ config=data.get("config", {}),
179
+ )
180
+
181
+
182
+ @dataclass
183
+ class QueueConfig:
184
+ """Configuration for the queue system."""
185
+
186
+ # Concurrency limits
187
+ max_concurrent_global: int = 4
188
+ max_concurrent_per_agent: int = 2
189
+ max_concurrent_per_workspace: int = 4
190
+
191
+ # Queue limits
192
+ max_queue_size: int = 100
193
+
194
+ # Defaults
195
+ default_priority: RunPriority = RunPriority.NORMAL
196
+ default_max_retries: int = 3
197
+
198
+ # Persistence
199
+ enable_persistence: bool = True
200
+ db_path: str = ".praison/queue.db"
201
+
202
+ # Autosave
203
+ autosave_interval_seconds: float = 30.0
204
+
205
+ # Backpressure
206
+ stream_buffer_size: int = 1000
207
+ drop_strategy: str = "oldest" # "oldest" or "newest"
208
+
209
+ # Timeouts
210
+ run_timeout_seconds: Optional[float] = None # None = no timeout
211
+ worker_poll_interval: float = 0.1
212
+
213
+ def to_dict(self) -> Dict[str, Any]:
214
+ """Convert to dictionary."""
215
+ return {
216
+ "max_concurrent_global": self.max_concurrent_global,
217
+ "max_concurrent_per_agent": self.max_concurrent_per_agent,
218
+ "max_concurrent_per_workspace": self.max_concurrent_per_workspace,
219
+ "max_queue_size": self.max_queue_size,
220
+ "default_priority": int(self.default_priority),
221
+ "default_max_retries": self.default_max_retries,
222
+ "enable_persistence": self.enable_persistence,
223
+ "db_path": self.db_path,
224
+ "autosave_interval_seconds": self.autosave_interval_seconds,
225
+ "stream_buffer_size": self.stream_buffer_size,
226
+ "drop_strategy": self.drop_strategy,
227
+ "run_timeout_seconds": self.run_timeout_seconds,
228
+ "worker_poll_interval": self.worker_poll_interval,
229
+ }
230
+
231
+ @classmethod
232
+ def from_dict(cls, data: Dict[str, Any]) -> "QueueConfig":
233
+ """Create from dictionary."""
234
+ priority = data.get("default_priority", 1)
235
+ if isinstance(priority, int):
236
+ priority = RunPriority(priority)
237
+
238
+ return cls(
239
+ max_concurrent_global=data.get("max_concurrent_global", 4),
240
+ max_concurrent_per_agent=data.get("max_concurrent_per_agent", 2),
241
+ max_concurrent_per_workspace=data.get("max_concurrent_per_workspace", 4),
242
+ max_queue_size=data.get("max_queue_size", 100),
243
+ default_priority=priority,
244
+ default_max_retries=data.get("default_max_retries", 3),
245
+ enable_persistence=data.get("enable_persistence", True),
246
+ db_path=data.get("db_path", ".praison/queue.db"),
247
+ autosave_interval_seconds=data.get("autosave_interval_seconds", 30.0),
248
+ stream_buffer_size=data.get("stream_buffer_size", 1000),
249
+ drop_strategy=data.get("drop_strategy", "oldest"),
250
+ run_timeout_seconds=data.get("run_timeout_seconds"),
251
+ worker_poll_interval=data.get("worker_poll_interval", 0.1),
252
+ )
253
+
254
+
255
+ @dataclass
256
+ class QueueStats:
257
+ """Statistics about the queue."""
258
+ queued_count: int = 0
259
+ running_count: int = 0
260
+ succeeded_count: int = 0
261
+ failed_count: int = 0
262
+ cancelled_count: int = 0
263
+ total_runs: int = 0
264
+ avg_wait_seconds: float = 0.0
265
+ avg_duration_seconds: float = 0.0
266
+
267
+ @property
268
+ def active_count(self) -> int:
269
+ """Count of active (non-terminal) runs."""
270
+ return self.queued_count + self.running_count
271
+
272
+
273
+ @dataclass
274
+ class StreamChunk:
275
+ """A chunk of streaming output."""
276
+ run_id: str
277
+ content: str
278
+ timestamp: float = field(default_factory=time.time)
279
+ chunk_index: int = 0
280
+ is_final: bool = False
281
+
282
+
283
+ @dataclass
284
+ class QueueEvent:
285
+ """An event from the queue system."""
286
+ event_type: str # "run_started", "run_completed", "run_failed", "output_chunk", "state_changed"
287
+ run_id: str
288
+ timestamp: float = field(default_factory=time.time)
289
+ data: Dict[str, Any] = field(default_factory=dict)