devops-bot-sdk 1.6.24__tar.gz → 1.6.26__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/PKG-INFO +3 -1
  2. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/devops_bot_sdk.egg-info/PKG-INFO +3 -1
  3. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/devops_bot_sdk.egg-info/SOURCES.txt +7 -0
  4. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/devops_bot_sdk.egg-info/requires.txt +2 -0
  5. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/pyproject.toml +5 -0
  6. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/__init__.py +2 -2
  7. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/activity.py +47 -14
  8. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/cli.py +228 -1
  9. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/client.py +189 -118
  10. devops_bot_sdk-1.6.26/sdk/github_ingest.py +161 -0
  11. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/intake.py +182 -8
  12. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/models/responses.py +73 -0
  13. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/plan_run.py +106 -18
  14. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/run_auto.py +194 -15
  15. devops_bot_sdk-1.6.26/sdk/self_report.py +597 -0
  16. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/api.py +223 -66
  17. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/models.py +29 -0
  18. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/security.py +5 -9
  19. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/server.py +14 -74
  20. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/app.js +194 -1
  21. devops_bot_sdk-1.6.26/sdk/ui/static/report.html +97 -0
  22. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/styles.css +30 -0
  23. devops_bot_sdk-1.6.26/sdk/vps_health.py +111 -0
  24. devops_bot_sdk-1.6.26/tests/test_intake_plan_review.py +177 -0
  25. devops_bot_sdk-1.6.26/tests/test_plan_new_command.py +140 -0
  26. devops_bot_sdk-1.6.26/tests/test_plan_run_activity.py +210 -0
  27. devops_bot_sdk-1.6.26/tests/test_self_report.py +644 -0
  28. devops_bot_sdk-1.6.26/tests/test_task_file_format_doc.py +283 -0
  29. devops_bot_sdk-1.6.24/sdk/github_ingest.py +0 -570
  30. devops_bot_sdk-1.6.24/sdk/vps_health.py +0 -264
  31. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/README.md +0 -0
  32. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
  33. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
  34. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/devops_bot_sdk.egg-info/top_level.txt +0 -0
  35. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agentd.py +0 -0
  36. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/__init__.py +0 -0
  37. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/builder.py +0 -0
  38. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/chat.py +0 -0
  39. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/connectors.py +0 -0
  40. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/engines/__init__.py +0 -0
  41. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/engines/claude_code.py +0 -0
  42. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/engines/http.py +0 -0
  43. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/engines/mcp.py +0 -0
  44. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/engines/n8n.py +0 -0
  45. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/engines/shell.py +0 -0
  46. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/integrations.py +0 -0
  47. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/inventory.py +0 -0
  48. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/library/__init__.py +0 -0
  49. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/manifest.py +0 -0
  50. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/prompt_studio.py +0 -0
  51. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/prompt_template.py +0 -0
  52. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/prompt_vars.py +0 -0
  53. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/run_log.py +0 -0
  54. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/schedules.py +0 -0
  55. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/secrets.py +0 -0
  56. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/ticket_run.py +0 -0
  57. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/usage.py +0 -0
  58. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/agents/varstore.py +0 -0
  59. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/collectors/__init__.py +0 -0
  60. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/collectors/files.py +0 -0
  61. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/collectors/process.py +0 -0
  62. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/collectors/screenshot.py +0 -0
  63. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/config.py +0 -0
  64. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/crucial.py +0 -0
  65. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/departments.py +0 -0
  66. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/design_verify/__init__.py +0 -0
  67. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/design_verify/assets.py +0 -0
  68. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/design_verify/bootstrap.py +0 -0
  69. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/design_verify/browser.py +0 -0
  70. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/design_verify/compare.py +0 -0
  71. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/design_verify/loop.py +0 -0
  72. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/exceptions.py +0 -0
  73. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/formats.py +0 -0
  74. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/git_ops.py +0 -0
  75. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/graph_recon.py +0 -0
  76. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/graphify.py +0 -0
  77. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/hooks/__init__.py +0 -0
  78. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/hooks/crucial_guard.py +0 -0
  79. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ipc/__init__.py +0 -0
  80. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ipc/electron_bridge.py +0 -0
  81. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ipc/handlers.py +0 -0
  82. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/local_exec.py +0 -0
  83. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/models/__init__.py +0 -0
  84. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/models/envelope.py +0 -0
  85. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/models/requests.py +0 -0
  86. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/models/snapshots.py +0 -0
  87. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/phase_timer.py +0 -0
  88. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/platform_compat.py +0 -0
  89. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/py.typed +0 -0
  90. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/scheduler.py +0 -0
  91. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/sse.py +0 -0
  92. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/task_file.py +0 -0
  93. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/test.py +0 -0
  94. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/test_pipeline.py +0 -0
  95. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ticket_fields.py +0 -0
  96. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/__init__.py +0 -0
  97. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/dashboard.py +0 -0
  98. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/health.py +0 -0
  99. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/ip_allowlist.py +0 -0
  100. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/jobs.py +0 -0
  101. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/runner.py +0 -0
  102. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/service.py +0 -0
  103. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/session.py +0 -0
  104. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/setup_manager.py +0 -0
  105. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/agents.html +0 -0
  106. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/chat.html +0 -0
  107. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/custom-agents.html +0 -0
  108. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/default-agents.html +0 -0
  109. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/index.html +0 -0
  110. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/login.html +0 -0
  111. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/runs.html +0 -0
  112. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/schedules.html +0 -0
  113. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/setup.html +0 -0
  114. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/ui/static/tickets.html +0 -0
  115. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/sdk/updater.py +0 -0
  116. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/setup.cfg +0 -0
  117. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_agent_activity.py +0 -0
  118. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_agent_activity_tracking.py +0 -0
  119. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_agent_chat_features.py +0 -0
  120. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_agent_listing.py +0 -0
  121. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_agent_prompt_async.py +0 -0
  122. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_agent_prompt_models.py +0 -0
  123. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_agent_run_ticket.py +0 -0
  124. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_agent_schedules.py +0 -0
  125. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_agent_workspace_settings.py +0 -0
  126. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_agents_connectors_builder.py +0 -0
  127. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_allowed_tools_config.py +0 -0
  128. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_auto_agent_dispatch.py +0 -0
  129. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_client_jira_projects.py +0 -0
  130. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_config_token_diagnostics.py +0 -0
  131. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_configure_token_owner.py +0 -0
  132. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_console_encoding.py +0 -0
  133. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_departments.py +0 -0
  134. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_epic_decompose_run.py +0 -0
  135. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_epic_inherited_agent_id.py +0 -0
  136. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_epic_session_isolation.py +0 -0
  137. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_formats.py +0 -0
  138. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_git_action.py +0 -0
  139. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_github_ingest.py +0 -0
  140. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_graph_recon.py +0 -0
  141. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_graphify_build.py +0 -0
  142. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_graphify_hook_install.py +0 -0
  143. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_health.py +0 -0
  144. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_otp_login.py +0 -0
  145. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_phase_timer.py +0 -0
  146. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_recon_session_isolation.py +0 -0
  147. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_run_auto_agent_only.py +0 -0
  148. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_run_outputs.py +0 -0
  149. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_schedule_api.py +0 -0
  150. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_scheduler.py +0 -0
  151. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_service_token_warning.py +0 -0
  152. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_task_file_and_plan_run.py +0 -0
  153. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_ticket_fields.py +0 -0
  154. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_ticket_run_resolve_by_id.py +0 -0
  155. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_ticket_speed_fixes.py +0 -0
  156. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_update_timer.py +0 -0
  157. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_updater_extras.py +0 -0
  158. {devops_bot_sdk-1.6.24 → devops_bot_sdk-1.6.26}/tests/test_vps_health.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devops-bot-sdk
3
- Version: 1.6.24
3
+ Version: 1.6.26
4
4
  Summary: DevOps Bot Desktop SDK — thin client for the AgentOS Electron desktop app
5
5
  Author: noumanaziz2128
6
6
  License-Expression: LicenseRef-Proprietary
@@ -21,11 +21,13 @@ Provides-Extra: ui
21
21
  Requires-Dist: fastapi>=0.110; extra == "ui"
22
22
  Requires-Dist: uvicorn>=0.29; extra == "ui"
23
23
  Requires-Dist: psutil>=5.9; extra == "ui"
24
+ Requires-Dist: python-multipart>=0.0.9; extra == "ui"
24
25
  Provides-Extra: all
25
26
  Requires-Dist: Pillow>=10.0; extra == "all"
26
27
  Requires-Dist: psutil>=5.9; extra == "all"
27
28
  Requires-Dist: fastapi>=0.110; extra == "all"
28
29
  Requires-Dist: uvicorn>=0.29; extra == "all"
30
+ Requires-Dist: python-multipart>=0.0.9; extra == "all"
29
31
 
30
32
  # DevOpsBot SDK
31
33
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devops-bot-sdk
3
- Version: 1.6.24
3
+ Version: 1.6.26
4
4
  Summary: DevOps Bot Desktop SDK — thin client for the AgentOS Electron desktop app
5
5
  Author: noumanaziz2128
6
6
  License-Expression: LicenseRef-Proprietary
@@ -21,11 +21,13 @@ Provides-Extra: ui
21
21
  Requires-Dist: fastapi>=0.110; extra == "ui"
22
22
  Requires-Dist: uvicorn>=0.29; extra == "ui"
23
23
  Requires-Dist: psutil>=5.9; extra == "ui"
24
+ Requires-Dist: python-multipart>=0.0.9; extra == "ui"
24
25
  Provides-Extra: all
25
26
  Requires-Dist: Pillow>=10.0; extra == "all"
26
27
  Requires-Dist: psutil>=5.9; extra == "all"
27
28
  Requires-Dist: fastapi>=0.110; extra == "all"
28
29
  Requires-Dist: uvicorn>=0.29; extra == "all"
30
+ Requires-Dist: python-multipart>=0.0.9; extra == "all"
29
31
 
30
32
  # DevOpsBot SDK
31
33
 
@@ -27,6 +27,7 @@ sdk/platform_compat.py
27
27
  sdk/py.typed
28
28
  sdk/run_auto.py
29
29
  sdk/scheduler.py
30
+ sdk/self_report.py
30
31
  sdk/sse.py
31
32
  sdk/task_file.py
32
33
  sdk/test.py
@@ -98,6 +99,7 @@ sdk/ui/static/custom-agents.html
98
99
  sdk/ui/static/default-agents.html
99
100
  sdk/ui/static/index.html
100
101
  sdk/ui/static/login.html
102
+ sdk/ui/static/report.html
101
103
  sdk/ui/static/runs.html
102
104
  sdk/ui/static/schedules.html
103
105
  sdk/ui/static/setup.html
@@ -130,15 +132,20 @@ tests/test_graph_recon.py
130
132
  tests/test_graphify_build.py
131
133
  tests/test_graphify_hook_install.py
132
134
  tests/test_health.py
135
+ tests/test_intake_plan_review.py
133
136
  tests/test_otp_login.py
134
137
  tests/test_phase_timer.py
138
+ tests/test_plan_new_command.py
139
+ tests/test_plan_run_activity.py
135
140
  tests/test_recon_session_isolation.py
136
141
  tests/test_run_auto_agent_only.py
137
142
  tests/test_run_outputs.py
138
143
  tests/test_schedule_api.py
139
144
  tests/test_scheduler.py
145
+ tests/test_self_report.py
140
146
  tests/test_service_token_warning.py
141
147
  tests/test_task_file_and_plan_run.py
148
+ tests/test_task_file_format_doc.py
142
149
  tests/test_ticket_fields.py
143
150
  tests/test_ticket_run_resolve_by_id.py
144
151
  tests/test_ticket_speed_fixes.py
@@ -9,6 +9,7 @@ Pillow>=10.0
9
9
  psutil>=5.9
10
10
  fastapi>=0.110
11
11
  uvicorn>=0.29
12
+ python-multipart>=0.0.9
12
13
 
13
14
  [process]
14
15
  psutil>=5.9
@@ -20,3 +21,4 @@ Pillow>=10.0
20
21
  fastapi>=0.110
21
22
  uvicorn>=0.29
22
23
  psutil>=5.9
24
+ python-multipart>=0.0.9
@@ -36,12 +36,17 @@ ui = [
36
36
  # bootstrap installs `[ui]` only, so without it here every
37
37
  # VPS reports "resources.available: False" and the health
38
38
  # cron can only send status + IP.
39
+ "python-multipart>=0.0.9", # POST /api/ui/reports/self — the ONE multipart route in
40
+ # the panel (self-report proofs are file uploads). Starlette
41
+ # raises at request time without it, so it belongs in [ui]
42
+ # alongside fastapi rather than in an optional extra.
39
43
  ]
40
44
  all = [
41
45
  "Pillow>=10.0",
42
46
  "psutil>=5.9",
43
47
  "fastapi>=0.110",
44
48
  "uvicorn>=0.29",
49
+ "python-multipart>=0.0.9",
45
50
  ]
46
51
 
47
52
  [project.scripts]
@@ -1,6 +1,6 @@
1
1
  """AgentOS Desktop SDK — thin HTTPS/SSE client for the Electron app.
2
2
 
3
- Version: 1.6.24
3
+ Version: 1.6.26
4
4
 
5
5
  Public surface:
6
6
  BackendClient.from_config() — create client from ~/.agentos/config.toml
@@ -34,7 +34,7 @@ Rules:
34
34
  - All data egress through submit_webhook only
35
35
  """
36
36
 
37
- __version__ = "1.6.24" # SINGLE SOURCE OF TRUTH — bump on every change; pyproject,
37
+ __version__ = "1.6.26" # SINGLE SOURCE OF TRUTH — bump on every change; pyproject,
38
38
  __author__ = "AgentOS" # sdk.client.SDK_VERSION and the UI server version all read this.
39
39
 
40
40
  from sdk.client import BackendClient
@@ -124,6 +124,46 @@ def _lines_block(lines: list[str]) -> str:
124
124
  return "\n".join(reversed(out))
125
125
 
126
126
 
127
+ def mirror_to_auto_log_line(text: str, *, pointer: str = "") -> bool:
128
+ """Append ONE already-composed summary line to ``~/.agentos/auto.log``.
129
+
130
+ The append-with-opt-out core of :func:`mirror_to_auto_log`, split out so a
131
+ caller that is not an agent run can use it. `agentos-auto logs [-f]` tails
132
+ that file and nothing else, so anything a person should be able to watch
133
+ live has to land here — including a self-report submission, which has no
134
+ agent, no `agent_dir()` and no `describe()` verb to render.
135
+
136
+ `text` is written verbatim under the shared ` • [<stamp>] ` prefix so every
137
+ line in the file reads the same way. `pointer` adds the indented `↳` line
138
+ the agent path uses for a transcript path; pass an empty string for none.
139
+
140
+ Honours ``AGENTOS_NO_AGENT_LOG_MIRROR=1`` and never raises: a log line must
141
+ never break the work that produced it. Returns True when a line was written.
142
+ """
143
+ line = str(text or "").strip()
144
+ if not line:
145
+ return False
146
+ if os.getenv("AGENTOS_NO_AGENT_LOG_MIRROR"):
147
+ return False
148
+ try:
149
+ from sdk.run_auto import _LOG_FILE
150
+ except Exception: # noqa: BLE001 — never break a caller over a log line
151
+ return False
152
+
153
+ stamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%SZ")
154
+ out = f" • [{stamp}] {line}"
155
+ if pointer:
156
+ out += f"\n ↳ {pointer}"
157
+ try:
158
+ _LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
159
+ with _LOG_FILE.open("a", encoding="utf-8") as fh:
160
+ fh.write(out + "\n")
161
+ return True
162
+ except Exception as exc: # noqa: BLE001
163
+ logger.debug("auto.log mirror failed err=%s", exc)
164
+ return False
165
+
166
+
127
167
  def mirror_to_auto_log(name: str, kind: str, result: dict | None,
128
168
  duration_s: float = 0.0, *, detail: str = "",
129
169
  task_id: str = "") -> bool:
@@ -141,18 +181,20 @@ def mirror_to_auto_log(name: str, kind: str, result: dict | None,
141
181
  the pointer below is how you get from one to the other. Best-effort and
142
182
  silent on failure: a log line must never break a run. Set
143
183
  ``AGENTOS_NO_AGENT_LOG_MIRROR=1`` to turn it off.
184
+
185
+ The append itself lives in :func:`mirror_to_auto_log_line`; what stays here
186
+ is the AGENT-shaped part — the `describe()` verb, the ticket suffix and the
187
+ `agent_dir()` transcript pointer — none of which a non-agent caller wants.
144
188
  """
145
189
  if os.getenv("AGENTOS_NO_AGENT_LOG_MIRROR"):
146
190
  return False
147
191
  try:
148
192
  from sdk.agents.run_log import agent_dir
149
- from sdk.run_auto import _LOG_FILE
150
193
  except Exception: # noqa: BLE001 — never break a run over a log line
151
194
  return False
152
195
 
153
196
  res = result or {}
154
- stamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%SZ")
155
- line = f" • [{stamp}] {describe(name, kind, res, duration_s, detail)}"
197
+ line = describe(name, kind, res, duration_s, detail)
156
198
  # agentd passes the ticket BOTH as `detail` ("task T1") and as `task_id`, so an
157
199
  # unconditional suffix renders "… — task T1 · task T1".
158
200
  if task_id and f"task {task_id}" not in line:
@@ -161,17 +203,8 @@ def mirror_to_auto_log(name: str, kind: str, result: dict | None,
161
203
  where = agent_dir(name)
162
204
  except Exception: # noqa: BLE001
163
205
  where = None
164
- if where:
165
- line += f"\n ↳ transcript: {where}"
166
-
167
- try:
168
- _LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
169
- with _LOG_FILE.open("a", encoding="utf-8") as fh:
170
- fh.write(line + "\n")
171
- return True
172
- except Exception as exc: # noqa: BLE001
173
- logger.debug("auto.log mirror failed agent=%s err=%s", name, exc)
174
- return False
206
+ return mirror_to_auto_log_line(
207
+ line, pointer=f"transcript: {where}" if where else "")
175
208
 
176
209
 
177
210
  async def emit(name: str, kind: str, result: dict | None, duration_s: float = 0.0,
@@ -58,6 +58,19 @@ Command surface:
58
58
  agentos integration rm <name>
59
59
  Remove a registered integration.
60
60
 
61
+ agentos report submit [--date YYYY-MM-DD] (--text "…" | --file PATH)
62
+ [--project NAME] [--proof PATH|URL]… [--no-wait]
63
+ Report work that never reached Jira or GitHub, attach proofs (local
64
+ files and/or http(s) URLs), and have the submission SCORED against
65
+ them. Prints the submission id, the score and the verdict. The same
66
+ mechanism the control panel's Report work page uses — see
67
+ sdk/self_report.py.
68
+ agentos report list [--limit N]
69
+ Recent submissions, newest first: date, score, verdict, id.
70
+ agentos report show <ID>
71
+ One submission in full — its text, its proofs and the evaluator's
72
+ per-criterion reasoning.
73
+
61
74
  agentos agentd start [--foreground]
62
75
  Start the local agent daemon (background by default).
63
76
  agentos agentd status
@@ -123,12 +136,16 @@ def main() -> None:
123
136
  _github_command(rest)
124
137
  return
125
138
 
139
+ if noun == "report":
140
+ _report_command(rest)
141
+ return
142
+
126
143
  _print_usage()
127
144
  sys.exit(1)
128
145
 
129
146
 
130
147
  def _print_usage() -> None:
131
- print("usage: agentos <configure|chat|agent|integration|default-agents|agentd|github> ...")
148
+ print("usage: agentos <configure|chat|agent|integration|default-agents|agentd|github|report> ...")
132
149
  print()
133
150
  print(" agentos configure [--rotate]")
134
151
  print(" agentos chat [--product-id ID] [--pv-id ID] [--no-autorun] # requirements → ticket")
@@ -138,6 +155,7 @@ def _print_usage() -> None:
138
155
  print(" agentos default-agents list [--department-id UUID] # read-only; agents are created in the web app")
139
156
  print(" agentos agentd <start [--foreground]|status>")
140
157
  print(" agentos github <ingest [--days N]|status> # PR ingestion; --days N backfills N days")
158
+ print(" agentos report <submit|list|show ID> # report work Jira/GitHub never saw")
141
159
 
142
160
 
143
161
  # ── agent ────────────────────────────────────────────────────────────────
@@ -703,5 +721,214 @@ def _github_command(args: list[str]) -> None:
703
721
  sys.exit(1)
704
722
 
705
723
 
724
+ # ── report ───────────────────────────────────────────────────────────────
725
+
726
+ def _report_usage() -> None:
727
+ print("usage: agentos report submit [--date YYYY-MM-DD] (--text \"…\" | --file PATH)")
728
+ print(" [--project NAME] [--proof PATH|URL]… [--no-wait]")
729
+ print(" agentos report list [--limit N]")
730
+ print(" agentos report show <ID>")
731
+ print()
732
+ print(" Report work that never reached Jira or GitHub, attach proofs, and have the")
733
+ print(" submission scored against them. It then appears in your daily and overall")
734
+ print(" reports and in the reporting chat.")
735
+ print()
736
+ print(" --date the day the work happened (default: today; never the future)")
737
+ print(" --text the report body; --file reads it from a file instead")
738
+ print(" --proof repeatable — a local file path OR an http(s) URL")
739
+ print(" --no-wait submit and exit without waiting for the verdict")
740
+
741
+
742
+ def _report_flag(args: list[str], name: str) -> list[str]:
743
+ """Every ``--name VALUE`` in args, in order. Repeatable flags collect.
744
+
745
+ Same hand-rolled shape as `run_auto._flag_values` — this CLI has no
746
+ argparse subparsers by design (see the module docstring).
747
+ """
748
+ out: list[str] = []
749
+ for i, a in enumerate(args):
750
+ if a == name and i + 1 < len(args):
751
+ out.append(args[i + 1])
752
+ elif a.startswith(name + "="):
753
+ out.append(a.split("=", 1)[1])
754
+ return out
755
+
756
+
757
+ def _report_command(args: list[str]) -> None:
758
+ """``agentos report submit|list|show`` — the CLI half of self-reporting.
759
+
760
+ Every verb resolves the backend client the same way and fails the same way
761
+ when the box has no ``co_`` token: the shared "not configured" message
762
+ ``agentos configure`` prints, and exit 1 — never a traceback.
763
+ """
764
+ from sdk.exceptions import TokenNotConfigured
765
+ from sdk.self_report import SelfReportError
766
+
767
+ verb = args[0] if args else None
768
+ rest = args[1:]
769
+
770
+ try:
771
+ if verb == "submit":
772
+ _report_submit(rest)
773
+ return
774
+ if verb == "list":
775
+ limits = _report_flag(rest, "--limit")
776
+ _report_list(int(limits[0]) if limits and limits[0].isdigit() else 25)
777
+ return
778
+ if verb == "show" and rest and not rest[0].startswith("-"):
779
+ _report_show(rest[0])
780
+ return
781
+ except TokenNotConfigured as exc:
782
+ # The same failure every other verb gives on an unconfigured machine —
783
+ # `sdk.config` composes a cause-specific message; we only add the prefix.
784
+ print(f"error: {exc}")
785
+ sys.exit(1)
786
+ except SelfReportError as exc:
787
+ print(f"error: {exc}")
788
+ sys.exit(1)
789
+
790
+ _report_usage()
791
+ sys.exit(1)
792
+
793
+
794
+ def _report_submit(args: list[str]) -> None:
795
+ """Submit one report, then print the id, the score and the verdict."""
796
+ from sdk import self_report
797
+
798
+ texts = _report_flag(args, "--text")
799
+ files = _report_flag(args, "--file")
800
+ if not texts and not files:
801
+ # A usage line and a non-zero exit — not an empty submission.
802
+ print("error: say what you did — pass --text \"…\" or --file report.md")
803
+ _report_usage()
804
+ sys.exit(1)
805
+
806
+ body = texts[0] if texts else ""
807
+ if files:
808
+ src = Path(files[0]).expanduser()
809
+ if not src.is_file():
810
+ print(f"error: no such file: {src}")
811
+ sys.exit(1)
812
+ try:
813
+ # --file supplies the body; a --text alongside it is a header line.
814
+ file_body = src.read_text(encoding="utf-8", errors="replace").strip()
815
+ except OSError as exc:
816
+ print(f"error: cannot read {src}: {exc}")
817
+ sys.exit(1)
818
+ body = f"{body}\n\n{file_body}".strip() if body else file_body
819
+
820
+ dates = _report_flag(args, "--date")
821
+ projects = _report_flag(args, "--project")
822
+ proofs, rejected = self_report.collect_proofs(_report_flag(args, "--proof"))
823
+ for r in rejected:
824
+ print(f"⚠ proof skipped — {r.get('name', '')}: {r.get('reason', '')}")
825
+
826
+ result = asyncio.run(self_report.submit_and_evaluate(
827
+ date=dates[0] if dates else "",
828
+ text=body,
829
+ project=projects[0] if projects else "",
830
+ proofs=proofs,
831
+ rejected=rejected,
832
+ wait="--no-wait" not in args,
833
+ ))
834
+
835
+ status = str(result.get("status") or "")
836
+ if status == "failed":
837
+ print(f"error: {result.get('error') or 'the submission was not stored.'}")
838
+ sys.exit(1)
839
+
840
+ print(f"submission : {result.get('id') or '(no id returned)'}")
841
+ print(f"date : {result.get('date', '')}"
842
+ + (f" project: {result['project']}" if result.get("project") else ""))
843
+ print(f"proofs : {len(result.get('proofs') or [])} accepted"
844
+ + (f", {len(result.get('rejected') or [])} skipped" if result.get("rejected") else ""))
845
+ if status == "evaluated":
846
+ print(f"score : {result.get('score', 0)}/100")
847
+ print(f"verdict : {result.get('verdict') or 'unknown'}")
848
+ elif status == "evaluation_failed":
849
+ print("score : —")
850
+ print("verdict : evaluation failed — the submission is stored and can be "
851
+ "re-evaluated")
852
+ else:
853
+ print(f"status : {status or 'accepted'} — not evaluated yet; "
854
+ f"`agentos report show {result.get('id', '')}` for the verdict")
855
+ # Exit 0 whenever the submission was STORED. A failed evaluation is a
856
+ # backend-side outcome the person cannot act on, and it is recorded, not lost.
857
+
858
+
859
+ def _report_list(limit: int) -> None:
860
+ """Recent submissions, newest first — date, score, verdict, id."""
861
+ from sdk import self_report
862
+
863
+ rows = asyncio.run(self_report.list_reports(limit))
864
+ if not rows:
865
+ print("no submissions yet — `agentos report submit --text \"…\"` records one.")
866
+ return
867
+ print(f"{'DATE':<12}{'SCORE':<8}{'VERDICT':<26}{'ID':<26}WHAT")
868
+ for r in rows:
869
+ ev = r.get("evaluation") or {}
870
+ score = f"{ev.get('score')}/100" if r.get("status") == "evaluated" else "—"
871
+ verdict = (ev.get("verdict") or r.get("status") or "")[:25]
872
+ what = " ".join(str(r.get("text") or "").split())[:46]
873
+ print(f"{str(r.get('date', '')):<12}{score:<8}{verdict:<26}"
874
+ f"{str(r.get('id', '')):<26}{what}")
875
+
876
+
877
+ def _report_show(report_id: str) -> None:
878
+ """One submission in full — its text, its proofs, and the per-criterion reasoning."""
879
+ from sdk import self_report
880
+
881
+ sub = asyncio.run(self_report.show_report(report_id))
882
+ if not sub:
883
+ print(f"error: no submission {report_id} (or it is not yours).")
884
+ sys.exit(1)
885
+
886
+ ev = sub.get("evaluation") or {}
887
+ print(f"submission : {sub.get('id', report_id)}")
888
+ print(f"date : {sub.get('date', '')}")
889
+ if sub.get("project"):
890
+ print(f"project : {sub['project']}")
891
+ print(f"status : {sub.get('status', '')}")
892
+ if sub.get("status") == "evaluated":
893
+ print(f"score : {ev.get('score', 0)}/100")
894
+ print(f"verdict : {ev.get('verdict', '')}")
895
+ print()
896
+ print("what I did")
897
+ for line in str(sub.get("text") or "").splitlines() or [""]:
898
+ print(f" {line}")
899
+
900
+ proofs = sub.get("proofs") or []
901
+ print()
902
+ print(f"proofs ({len(proofs)})")
903
+ if not proofs:
904
+ print(" (none — an unproven report is recorded, never silently dropped)")
905
+ for p in proofs:
906
+ head = f" · {p.get('name') or p.get('url') or 'proof'}"
907
+ judged = p.get("judgement") or "not judged"
908
+ print(f"{head} [{judged}]")
909
+ if p.get("url"):
910
+ print(f" url : {p['url']}")
911
+ if p.get("size_bytes"):
912
+ print(f" size : {p['size_bytes']} bytes {p.get('content_type', '')}")
913
+ if p.get("reason"):
914
+ print(f" why : {p['reason']}")
915
+
916
+ findings = ev.get("findings") or []
917
+ print()
918
+ print(f"evaluator findings ({len(findings)})")
919
+ if ev.get("summary"):
920
+ print(f" {ev['summary']}")
921
+ for f in findings:
922
+ print(f" · [{f.get('verdict', '')}] {f.get('criterion', '')}")
923
+ if f.get("detail"):
924
+ print(f" {f['detail']}")
925
+ if not findings and sub.get("status") == "evaluation_failed":
926
+ print(" the evaluator returned unparseable output — the raw response is retained "
927
+ "server-side for diagnosis, and the submission can be re-evaluated.")
928
+
929
+ for r in (sub.get("rejected") or []):
930
+ print(f"⚠ proof not accepted — {r.get('name', '')}: {r.get('reason', '')}")
931
+
932
+
706
933
  if __name__ == "__main__":
707
934
  main()