devops-bot-sdk 1.6.40__tar.gz → 1.6.41__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 (201) hide show
  1. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/PKG-INFO +1 -1
  2. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
  3. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/devops_bot_sdk.egg-info/SOURCES.txt +1 -0
  4. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/__init__.py +2 -2
  5. devops_bot_sdk-1.6.41/tests/test_mcp_route_contract.py +209 -0
  6. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/README.md +0 -0
  7. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
  8. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
  9. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/devops_bot_sdk.egg-info/requires.txt +0 -0
  10. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/devops_bot_sdk.egg-info/top_level.txt +0 -0
  11. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/pyproject.toml +0 -0
  12. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agentd.py +0 -0
  13. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/__init__.py +0 -0
  14. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/activity.py +0 -0
  15. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/builder.py +0 -0
  16. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/chat.py +0 -0
  17. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/connectors.py +0 -0
  18. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/engines/__init__.py +0 -0
  19. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/engines/claude_code.py +0 -0
  20. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/engines/http.py +0 -0
  21. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/engines/mcp.py +0 -0
  22. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/engines/n8n.py +0 -0
  23. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/engines/shell.py +0 -0
  24. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/integrations.py +0 -0
  25. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/inventory.py +0 -0
  26. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/library/__init__.py +0 -0
  27. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/manifest.py +0 -0
  28. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/prompt_studio.py +0 -0
  29. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/prompt_template.py +0 -0
  30. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/prompt_vars.py +0 -0
  31. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/run_log.py +0 -0
  32. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/schedules.py +0 -0
  33. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/secrets.py +0 -0
  34. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/ticket_run.py +0 -0
  35. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/usage.py +0 -0
  36. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/agents/varstore.py +0 -0
  37. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/browser_profile.py +0 -0
  38. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/cli.py +0 -0
  39. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/client.py +0 -0
  40. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/collectors/__init__.py +0 -0
  41. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/collectors/files.py +0 -0
  42. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/collectors/process.py +0 -0
  43. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/collectors/screenshot.py +0 -0
  44. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/config.py +0 -0
  45. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/crucial.py +0 -0
  46. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/departments.py +0 -0
  47. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/design_verify/__init__.py +0 -0
  48. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/design_verify/assets.py +0 -0
  49. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/design_verify/bootstrap.py +0 -0
  50. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/design_verify/browser.py +0 -0
  51. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/design_verify/compare.py +0 -0
  52. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/design_verify/loop.py +0 -0
  53. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/estimator.py +0 -0
  54. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/exceptions.py +0 -0
  55. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/firewall.py +0 -0
  56. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/formats.py +0 -0
  57. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/git_ops.py +0 -0
  58. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/github_fetch.py +0 -0
  59. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/github_ingest.py +0 -0
  60. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/graph_recon.py +0 -0
  61. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/graphify.py +0 -0
  62. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/hooks/__init__.py +0 -0
  63. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/hooks/crucial_guard.py +0 -0
  64. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/intake.py +0 -0
  65. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ipc/__init__.py +0 -0
  66. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ipc/electron_bridge.py +0 -0
  67. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ipc/handlers.py +0 -0
  68. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/journal.py +0 -0
  69. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/local_exec.py +0 -0
  70. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/memory_guard.py +0 -0
  71. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/models/__init__.py +0 -0
  72. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/models/envelope.py +0 -0
  73. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/models/requests.py +0 -0
  74. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/models/responses.py +0 -0
  75. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/models/snapshots.py +0 -0
  76. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/phase_timer.py +0 -0
  77. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/plan_run.py +0 -0
  78. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/platform_compat.py +0 -0
  79. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/prd_progress.py +0 -0
  80. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/proof_readers.py +0 -0
  81. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/providers.py +0 -0
  82. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/py.typed +0 -0
  83. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/resume.py +0 -0
  84. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/router.py +0 -0
  85. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/run_auto.py +0 -0
  86. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/scheduler.py +0 -0
  87. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/self_report.py +0 -0
  88. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/self_report_local.py +0 -0
  89. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/sse.py +0 -0
  90. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/swagger.py +0 -0
  91. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/task_file.py +0 -0
  92. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/task_types.py +0 -0
  93. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/test.py +0 -0
  94. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/test_pipeline.py +0 -0
  95. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ticket_fields.py +0 -0
  96. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/tiers/__init__.py +0 -0
  97. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/tiers/mini_agent.py +0 -0
  98. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/__init__.py +0 -0
  99. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/api.py +0 -0
  100. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/dashboard.py +0 -0
  101. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/health.py +0 -0
  102. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/ip_allowlist.py +0 -0
  103. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/jobs.py +0 -0
  104. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/models.py +0 -0
  105. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/runner.py +0 -0
  106. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/security.py +0 -0
  107. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/server.py +0 -0
  108. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/service.py +0 -0
  109. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/session.py +0 -0
  110. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/setup_manager.py +0 -0
  111. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/agents.html +0 -0
  112. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/app.js +0 -0
  113. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/chat.html +0 -0
  114. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/custom-agents.html +0 -0
  115. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/default-agents.html +0 -0
  116. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/index.html +0 -0
  117. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/report.html +0 -0
  118. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/runs.html +0 -0
  119. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/schedules.html +0 -0
  120. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/setup.html +0 -0
  121. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/styles.css +0 -0
  122. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/static/tickets.html +0 -0
  123. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/ui/swagger.py +0 -0
  124. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/updater.py +0 -0
  125. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/url_access.py +0 -0
  126. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/vps_health.py +0 -0
  127. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/sdk/write_hook.py +0 -0
  128. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/setup.cfg +0 -0
  129. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_agent_activity.py +0 -0
  130. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_agent_activity_tracking.py +0 -0
  131. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_agent_chat_features.py +0 -0
  132. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_agent_listing.py +0 -0
  133. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_agent_prompt_async.py +0 -0
  134. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_agent_prompt_models.py +0 -0
  135. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_agent_run_ticket.py +0 -0
  136. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_agent_schedules.py +0 -0
  137. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_agent_workspace_settings.py +0 -0
  138. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_agents_connectors_builder.py +0 -0
  139. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_allowed_tools_config.py +0 -0
  140. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_auto_agent_dispatch.py +0 -0
  141. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_browser_profile.py +0 -0
  142. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_cheap_tier.py +0 -0
  143. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_client_jira_projects.py +0 -0
  144. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_config_token_diagnostics.py +0 -0
  145. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_configure_token_owner.py +0 -0
  146. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_console_encoding.py +0 -0
  147. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_crash_recovery.py +0 -0
  148. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_departments.py +0 -0
  149. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_done_transition.py +0 -0
  150. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_epic_decompose_run.py +0 -0
  151. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_epic_inherited_agent_id.py +0 -0
  152. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_epic_session_isolation.py +0 -0
  153. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_estimator.py +0 -0
  154. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_firewall_open_on_update.py +0 -0
  155. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_formats.py +0 -0
  156. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_git_action.py +0 -0
  157. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_github_fetch.py +0 -0
  158. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_github_ingest.py +0 -0
  159. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_graph_recon.py +0 -0
  160. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_graphify_build.py +0 -0
  161. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_graphify_hook_install.py +0 -0
  162. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_health.py +0 -0
  163. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_intake_job_outcome.py +0 -0
  164. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_intake_plan_review.py +0 -0
  165. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_journal.py +0 -0
  166. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_local_exec_provider.py +0 -0
  167. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_memory_guard.py +0 -0
  168. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_phase_timer.py +0 -0
  169. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_plan_new_command.py +0 -0
  170. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_plan_run_activity.py +0 -0
  171. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_pr_identity.py +0 -0
  172. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_prd_artifact.py +0 -0
  173. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_project_path_resolution.py +0 -0
  174. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_proof_readers.py +0 -0
  175. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_providers.py +0 -0
  176. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_recon_session_isolation.py +0 -0
  177. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_resume.py +0 -0
  178. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_router.py +0 -0
  179. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_run_auto_agent_only.py +0 -0
  180. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_run_outputs.py +0 -0
  181. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_run_verdict_is_honest.py +0 -0
  182. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_schedule_api.py +0 -0
  183. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_scheduler.py +0 -0
  184. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_self_report.py +0 -0
  185. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_service_token_warning.py +0 -0
  186. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_swagger_command.py +0 -0
  187. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_task_file_and_plan_run.py +0 -0
  188. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_task_file_format_doc.py +0 -0
  189. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_ticket_fields.py +0 -0
  190. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_ticket_run_resolve_by_id.py +0 -0
  191. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_ticket_speed_fixes.py +0 -0
  192. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_tier_flag_parity.py +0 -0
  193. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_ui_gate.py +0 -0
  194. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_ui_lifespan.py +0 -0
  195. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_update_timer.py +0 -0
  196. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_updater_extras.py +0 -0
  197. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_updater_reports_the_truth.py +0 -0
  198. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_url_access.py +0 -0
  199. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_vps_health.py +0 -0
  200. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_windows_loop_identity.py +0 -0
  201. {devops_bot_sdk-1.6.40 → devops_bot_sdk-1.6.41}/tests/test_write_hook.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devops-bot-sdk
3
- Version: 1.6.40
3
+ Version: 1.6.41
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devops-bot-sdk
3
- Version: 1.6.40
3
+ Version: 1.6.41
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
@@ -161,6 +161,7 @@ tests/test_intake_job_outcome.py
161
161
  tests/test_intake_plan_review.py
162
162
  tests/test_journal.py
163
163
  tests/test_local_exec_provider.py
164
+ tests/test_mcp_route_contract.py
164
165
  tests/test_memory_guard.py
165
166
  tests/test_phase_timer.py
166
167
  tests/test_plan_new_command.py
@@ -1,6 +1,6 @@
1
1
  """AgentOS Desktop SDK — thin HTTPS/SSE client for the Electron app.
2
2
 
3
- Version: 1.6.38
3
+ Version: 1.6.41
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.40" # SINGLE SOURCE OF TRUTH — bump on every change; pyproject,
37
+ __version__ = "1.6.41" # 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
@@ -0,0 +1,209 @@
1
+ """The `/api/ui/*` routes an external MCP client drives, frozen as a contract.
2
+
3
+ ``devops-bot-ai`` exposes 17 of this panel's routes as Model Context Protocol
4
+ tools (`modules/mcp/catalog.py`, design in that repo's
5
+ `docs/PRD_MCP_VPS_TOOLS.md`). Its catalogue hard-codes the bare path suffix, the
6
+ HTTP verb and the query-parameter NAMES of each one, because ``_call_sdk`` builds
7
+ ``f"{sdk_url}/api/ui/{path}"`` and forwards ``params`` verbatim.
8
+
9
+ That makes an ordinary, reasonable-looking rename here — ``loop-status`` to
10
+ ``loop_status``, ``lines`` to ``limit``, ``GET /tasks`` to ``GET /task-files`` —
11
+ a production break in a DIFFERENT repository, per user, with no failing test on
12
+ either side. The panel's own UI would be updated in the same commit and look
13
+ fine; the first symptom would be an AI agent telling someone their VPS cannot be
14
+ reached.
15
+
16
+ So this file is a tripwire, not a behaviour test. It asserts only what the remote
17
+ catalogue actually depends on. Changing one of these is allowed — it is a
18
+ coordinated change with `modules/mcp/catalog.py`, and this test failing by name
19
+ is how you find that out before shipping.
20
+ """
21
+ from __future__ import annotations
22
+
23
+ import pytest
24
+
25
+ fastapi = pytest.importorskip("fastapi")
26
+
27
+ from sdk import config # noqa: E402
28
+ from sdk.ui import security # noqa: E402
29
+ from sdk.ui.api import require_token, router # noqa: E402
30
+
31
+ #: (method, path) exactly as `modules/mcp/catalog.py` spells it, `/api/ui/`
32
+ #: prefix stripped. 10 reads then 7 writes, matching the catalogue's own order.
33
+ MCP_CONSUMED_ROUTES: tuple[tuple[str, str], ...] = (
34
+ ("GET", "/health"),
35
+ ("GET", "/status"),
36
+ ("GET", "/loop-status"),
37
+ ("GET", "/logs"),
38
+ ("GET", "/system/inventory"),
39
+ ("GET", "/dashboard"),
40
+ ("GET", "/jobs/{job_id}"),
41
+ ("GET", "/agents/all"),
42
+ ("GET", "/tasks"),
43
+ ("GET", "/agents/schedules"),
44
+ ("POST", "/agents/run"),
45
+ ("POST", "/agents/chat"),
46
+ ("POST", "/run"),
47
+ ("POST", "/resume"),
48
+ ("POST", "/stop"),
49
+ ("POST", "/git"), # both open_vps_pull_request and push_vps_branch
50
+ ("POST", "/git"),
51
+ )
52
+
53
+ #: Query parameters the remote catalogue sends BY NAME. A rename here is
54
+ #: silently dropped by FastAPI (the default is used instead), so the tool keeps
55
+ #: "working" while ignoring everything the model asked for — the worst failure
56
+ #: shape available, because nothing errors.
57
+ MCP_QUERY_PARAMS: tuple[tuple[str, str, object], ...] = (
58
+ ("/logs", "lines", 200),
59
+ ("/dashboard", "period", "7d"),
60
+ ("/agents/all", "department_id", ""),
61
+ )
62
+
63
+
64
+ #: The router carries its own `/api/ui` prefix, so `route.path` is the full
65
+ #: path. The table above holds the bare suffix the remote catalogue stores.
66
+ _PREFIX = router.prefix
67
+
68
+
69
+ def _routes() -> dict[tuple[str, str], object]:
70
+ """(method, bare suffix) -> route, with the `/api/ui` prefix stripped."""
71
+ out = {}
72
+ for route in router.routes:
73
+ path = getattr(route, "path", "")
74
+ suffix = path[len(_PREFIX):] if path.startswith(_PREFIX) else path
75
+ for method in getattr(route, "methods", set()) or set():
76
+ out[(method, suffix)] = route
77
+ return out
78
+
79
+
80
+ def _client():
81
+ app = fastapi.FastAPI()
82
+ app.include_router(router)
83
+ app.dependency_overrides[require_token] = lambda: None
84
+ from fastapi.testclient import TestClient
85
+
86
+ return TestClient(app)
87
+
88
+
89
+ class TestRoutesExist:
90
+ @pytest.mark.parametrize("method,path", sorted(set(MCP_CONSUMED_ROUTES)))
91
+ def test_the_route_is_still_served_at_this_exact_spelling(self, method, path):
92
+ assert (method, path) in _routes(), (
93
+ f"{method} /api/ui{path} is consumed as an MCP tool by devops-bot-ai "
94
+ f"(modules/mcp/catalog.py). Renaming or removing it breaks that tool "
95
+ f"in production with no error on either side — update the catalogue "
96
+ f"in the same change."
97
+ )
98
+
99
+ def test_the_count_has_not_silently_changed(self):
100
+ """17 tools, 16 distinct routes — the two git tools share POST /git."""
101
+ assert len(MCP_CONSUMED_ROUTES) == 17
102
+ assert len(set(MCP_CONSUMED_ROUTES)) == 16
103
+
104
+
105
+ class TestQueryParameterNames:
106
+ @pytest.mark.parametrize("path,name,default", MCP_QUERY_PARAMS)
107
+ def test_the_parameter_name_and_default_are_unchanged(self, path, name, default):
108
+ route = _routes()[("GET", path)]
109
+ params = {
110
+ p.name: p for p in route.dependant.query_params # type: ignore[attr-defined]
111
+ }
112
+ assert name in params, (
113
+ f"GET /api/ui{path} no longer accepts '{name}'. The MCP catalogue "
114
+ f"sends it by name; FastAPI drops an unknown query param silently, "
115
+ f"so the tool would keep answering while ignoring its arguments."
116
+ )
117
+ assert params[name].default == default
118
+
119
+ def test_the_logs_bound_the_catalogue_publishes_is_the_one_enforced(self):
120
+ """The remote JSON Schema advertises 1..5000 to the model. If the route
121
+ narrows that, a model asking for a legal value gets a 422 it cannot
122
+ interpret."""
123
+ client = _client()
124
+ assert client.get("/api/ui/logs?lines=5000").status_code != 422
125
+ assert client.get("/api/ui/logs?lines=5001").status_code == 422
126
+ assert client.get("/api/ui/logs?lines=0").status_code == 422
127
+
128
+
129
+ class TestJobPolling:
130
+ def test_the_job_id_is_a_path_parameter_named_job_id(self):
131
+ """`get_vps_job` interpolates the id into the path, and validates it
132
+ against `^[0-9a-f]{32}$` precisely because it lands there."""
133
+ route = _routes()[("GET", "/jobs/{job_id}")]
134
+ names = {p.name for p in route.dependant.path_params} # type: ignore[attr-defined]
135
+ assert names == {"job_id"}
136
+
137
+ def test_job_ids_are_still_32_char_lowercase_hex(self):
138
+ """The remote side validates the shape before interpolating it. A change
139
+ to uuid4() *with* dashes, or to an incrementing integer, would make every
140
+ legitimate poll fail argument validation before it ever left that repo."""
141
+ from sdk.ui import jobs
142
+
143
+ async def _noop():
144
+ return {"ok": True}
145
+
146
+ import asyncio
147
+
148
+ async def _run():
149
+ job_id = jobs.start(_noop())
150
+ await asyncio.sleep(0)
151
+ return job_id
152
+
153
+ job_id = asyncio.run(_run())
154
+ assert len(job_id) == 32
155
+ assert job_id == job_id.lower()
156
+ assert all(c in "0123456789abcdef" for c in job_id)
157
+
158
+
159
+ class TestBodylessStop:
160
+ def test_stop_accepts_a_request_with_no_body_at_all(self):
161
+ """`action_router._build_empty` returns None and the proxy sends
162
+ `json=None`. A required request model here would 422 every stop."""
163
+ route = _routes()[("POST", "/stop")]
164
+ assert route.dependant.body_params == [] # type: ignore[attr-defined]
165
+ assert _client().post("/api/ui/stop").status_code != 422
166
+
167
+
168
+ class TestEveryConsumedRouteIsStillTokenGated:
169
+ @pytest.mark.parametrize("method,path", sorted(set(MCP_CONSUMED_ROUTES)))
170
+ def test_the_route_still_requires_the_api_token(self, method, path):
171
+ """These are now reachable by an external product, not just the panel's
172
+ own page. A route that loses `_auth` becomes readable by anything that
173
+ can reach port 8765 from an allowlisted address."""
174
+ route = _routes()[(method, path)]
175
+ names = {
176
+ getattr(d.call, "__name__", "") for d in route.dependant.dependencies # type: ignore[attr-defined]
177
+ }
178
+ assert "require_token" in names, f"{method} /api/ui{path} is no longer token-gated"
179
+
180
+
181
+ class TestTokenTransport:
182
+ def test_a_bearer_prefixed_token_is_accepted(self):
183
+ """The MCP consumer (`ai-draftsman-ml-b2b`) sends `Authorization: Bearer
184
+ co_…` by default — it does not know about this panel's bare-token
185
+ convention, and the backend forwards the header as it received it."""
186
+ assert security.extract_token({"authorization": "Bearer co_abc_123"}, {}) == "co_abc_123"
187
+
188
+ def test_a_bare_token_is_still_accepted(self):
189
+ """The backend's own proxies forward the caller's token verbatim, with
190
+ no prefix. Both forms must keep working — this is the one place they
191
+ meet."""
192
+ assert security.extract_token({"authorization": "co_abc_123"}, {}) == "co_abc_123"
193
+
194
+ def test_the_prefix_match_is_case_insensitive(self):
195
+ assert security.extract_token({"authorization": "bearer co_abc_123"}, {}) == "co_abc_123"
196
+
197
+
198
+ class TestBackendReachability:
199
+ def test_the_backend_egress_ips_stay_permanently_allowlisted(self):
200
+ """Every MCP tool call arrives FROM the backend, so these addresses are
201
+ the whole path. They are permanent (not removable through the API) on
202
+ purpose: a user disabling one through the panel would cut off a product
203
+ integration they never configured from here and cannot see."""
204
+ permanent = config.permanent_allowed_ips()
205
+ for ip in config._DEFAULT_ALLOWED_IPS:
206
+ assert ip in permanent, (
207
+ f"{ip} is a devops-bot-ai egress address; dropping it stops every "
208
+ f"backend-driven call, including all MCP tools."
209
+ )