devops-bot-sdk 1.6.93__tar.gz → 1.7.5__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 (272) hide show
  1. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/PKG-INFO +1 -1
  2. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
  3. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/devops_bot_sdk.egg-info/SOURCES.txt +14 -0
  4. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/__init__.py +2 -2
  5. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/collectors/windows_eventlog.py +36 -3
  6. devops_bot_sdk-1.7.5/sdk/agent_sharing.py +138 -0
  7. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/chat.py +16 -5
  8. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/cli.py +320 -13
  9. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/client.py +90 -0
  10. devops_bot_sdk-1.7.5/sdk/deferred_tickets.py +113 -0
  11. devops_bot_sdk-1.7.5/sdk/help_actions.py +265 -0
  12. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/helpdesk.py +108 -21
  13. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/helpdesk_kb.md +79 -2
  14. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ipc/handlers.py +816 -604
  15. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/local_exec.py +12 -2
  16. devops_bot_sdk-1.7.5/sdk/log_colors.py +92 -0
  17. devops_bot_sdk-1.7.5/sdk/model_policy.py +172 -0
  18. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/run_auto.py +120 -19
  19. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/schedule_tickets.py +2 -0
  20. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/scheduler.py +3 -0
  21. devops_bot_sdk-1.7.5/sdk/ticket_board.py +104 -0
  22. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/tickets.py +81 -4
  23. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/api.py +110 -1
  24. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/dashboard.py +15 -2
  25. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/models.py +13 -0
  26. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/runner.py +1 -0
  27. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/app.js +513 -85
  28. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/custom-agents.html +41 -0
  29. devops_bot_sdk-1.7.5/sdk/ui/static/index.html +70 -0
  30. devops_bot_sdk-1.7.5/sdk/ui/static/schedules.html +163 -0
  31. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/styles.css +334 -45
  32. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/tickets.html +1 -0
  33. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_activity_collectors.py +27 -0
  34. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agent_crud_cli.py +31 -0
  35. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agent_listing.py +1 -1
  36. devops_bot_sdk-1.7.5/tests/test_agent_sharing.py +199 -0
  37. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_crash_recovery.py +1 -1
  38. devops_bot_sdk-1.7.5/tests/test_deferred_tickets.py +157 -0
  39. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_done_transition.py +71 -0
  40. devops_bot_sdk-1.7.5/tests/test_help_actions.py +113 -0
  41. devops_bot_sdk-1.7.5/tests/test_help_questions.py +71 -0
  42. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_helpdesk.py +8 -9
  43. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_local_exec_provider.py +34 -0
  44. devops_bot_sdk-1.7.5/tests/test_log_colors_backlog.py +91 -0
  45. devops_bot_sdk-1.7.5/tests/test_model_policy.py +100 -0
  46. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_panel_help.py +1 -1
  47. devops_bot_sdk-1.7.5/tests/test_parallel_tickets.py +259 -0
  48. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_plan_new_command.py +7 -3
  49. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_task_file_format_doc.py +13 -8
  50. devops_bot_sdk-1.7.5/tests/test_ticket_board.py +80 -0
  51. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_ticket_cli.py +94 -4
  52. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_ticket_schedule_and_agent.py +1 -1
  53. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_ticket_speed_fixes.py +3 -2
  54. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_tier_flag_parity.py +2 -2
  55. devops_bot_sdk-1.6.93/sdk/ui/static/index.html +0 -68
  56. devops_bot_sdk-1.6.93/sdk/ui/static/schedules.html +0 -160
  57. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/README.md +0 -0
  58. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
  59. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
  60. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/devops_bot_sdk.egg-info/requires.txt +0 -0
  61. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/devops_bot_sdk.egg-info/top_level.txt +0 -0
  62. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/pyproject.toml +0 -0
  63. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/__init__.py +0 -0
  64. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/classifier.py +0 -0
  65. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/collectors/__init__.py +0 -0
  66. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/collectors/common.py +0 -0
  67. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/collectors/linux_auditd.py +0 -0
  68. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/collectors/macos_eslogger.py +0 -0
  69. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/models.py +0 -0
  70. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/os_setup.py +0 -0
  71. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/recorder.py +0 -0
  72. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/redact.py +0 -0
  73. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/settings.py +0 -0
  74. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/shipper.py +0 -0
  75. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/activity/spool.py +0 -0
  76. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agentd.py +0 -0
  77. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/__init__.py +0 -0
  78. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/activity.py +0 -0
  79. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/builder.py +0 -0
  80. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/connectors.py +0 -0
  81. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/engines/__init__.py +0 -0
  82. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/engines/claude_code.py +0 -0
  83. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/engines/http.py +0 -0
  84. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/engines/mcp.py +0 -0
  85. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/engines/n8n.py +0 -0
  86. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/engines/shell.py +0 -0
  87. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/integrations.py +0 -0
  88. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/inventory.py +0 -0
  89. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/library/__init__.py +0 -0
  90. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/manifest.py +0 -0
  91. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/prompt_studio.py +0 -0
  92. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/prompt_template.py +0 -0
  93. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/prompt_vars.py +0 -0
  94. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/run_log.py +0 -0
  95. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/schedules.py +0 -0
  96. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/secrets.py +0 -0
  97. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/ticket_run.py +0 -0
  98. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/usage.py +0 -0
  99. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/agents/varstore.py +0 -0
  100. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/browser_profile.py +0 -0
  101. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/claude_usage.py +0 -0
  102. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/collectors/__init__.py +0 -0
  103. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/collectors/files.py +0 -0
  104. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/collectors/process.py +0 -0
  105. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/collectors/screenshot.py +0 -0
  106. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/config.py +0 -0
  107. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/crucial.py +0 -0
  108. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/custom_agents.py +0 -0
  109. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/departments.py +0 -0
  110. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/design_verify/__init__.py +0 -0
  111. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/design_verify/assets.py +0 -0
  112. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/design_verify/bootstrap.py +0 -0
  113. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/design_verify/browser.py +0 -0
  114. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/design_verify/compare.py +0 -0
  115. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/design_verify/loop.py +0 -0
  116. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/estimator.py +0 -0
  117. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/exceptions.py +0 -0
  118. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/fallback_handoff.py +0 -0
  119. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/firewall.py +0 -0
  120. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/formats.py +0 -0
  121. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/git_ops.py +0 -0
  122. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/github_fetch.py +0 -0
  123. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/github_ingest.py +0 -0
  124. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/graph_recon.py +0 -0
  125. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/graphify.py +0 -0
  126. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/hooks/__init__.py +0 -0
  127. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/hooks/crucial_guard.py +0 -0
  128. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/intake.py +0 -0
  129. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ipc/__init__.py +0 -0
  130. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ipc/electron_bridge.py +0 -0
  131. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/journal.py +0 -0
  132. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/memory_guard.py +0 -0
  133. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/models/__init__.py +0 -0
  134. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/models/envelope.py +0 -0
  135. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/models/requests.py +0 -0
  136. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/models/responses.py +0 -0
  137. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/models/snapshots.py +0 -0
  138. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/phase_timer.py +0 -0
  139. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/plan_run.py +0 -0
  140. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/platform_compat.py +0 -0
  141. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/prd_progress.py +0 -0
  142. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/proof_readers.py +0 -0
  143. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/providers.py +0 -0
  144. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/py.typed +0 -0
  145. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/resume.py +0 -0
  146. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/router.py +0 -0
  147. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/self_report.py +0 -0
  148. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/self_report_local.py +0 -0
  149. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/sse.py +0 -0
  150. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/swagger.py +0 -0
  151. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/task_file.py +0 -0
  152. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/task_types.py +0 -0
  153. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/test.py +0 -0
  154. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/test_pipeline.py +0 -0
  155. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ticket_fields.py +0 -0
  156. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/tiers/__init__.py +0 -0
  157. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/tiers/mini_agent.py +0 -0
  158. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/__init__.py +0 -0
  159. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/health.py +0 -0
  160. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/ip_allowlist.py +0 -0
  161. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/jobs.py +0 -0
  162. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/security.py +0 -0
  163. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/server.py +0 -0
  164. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/service.py +0 -0
  165. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/session.py +0 -0
  166. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/setup_manager.py +0 -0
  167. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/agents.html +0 -0
  168. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/chat.html +0 -0
  169. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/default-agents.html +0 -0
  170. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/help.html +0 -0
  171. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/report.html +0 -0
  172. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/runs.html +0 -0
  173. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/static/setup.html +0 -0
  174. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/ui/swagger.py +0 -0
  175. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/updater.py +0 -0
  176. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/url_access.py +0 -0
  177. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/vps_health.py +0 -0
  178. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/vps_identity.py +0 -0
  179. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/sdk/write_hook.py +0 -0
  180. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/setup.cfg +0 -0
  181. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_activity_claude_runs.py +0 -0
  182. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_activity_core.py +0 -0
  183. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_activity_live_tracking.py +0 -0
  184. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_activity_macos.py +0 -0
  185. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_activity_os_setup.py +0 -0
  186. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_activity_pipeline.py +0 -0
  187. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agent_activity.py +0 -0
  188. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agent_activity_tracking.py +0 -0
  189. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agent_chat_features.py +0 -0
  190. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agent_prompt_async.py +0 -0
  191. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agent_prompt_models.py +0 -0
  192. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agent_run_ticket.py +0 -0
  193. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agent_schedules.py +0 -0
  194. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agent_workspace_settings.py +0 -0
  195. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_agents_connectors_builder.py +0 -0
  196. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_allowed_tools_config.py +0 -0
  197. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_approval_park.py +0 -0
  198. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_auto_agent_dispatch.py +0 -0
  199. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_auto_ticket_queue.py +0 -0
  200. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_browser_profile.py +0 -0
  201. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_cheap_tier.py +0 -0
  202. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_claude_usage_gate.py +0 -0
  203. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_client_jira_projects.py +0 -0
  204. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_config_token_diagnostics.py +0 -0
  205. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_configure_token_owner.py +0 -0
  206. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_console_encoding.py +0 -0
  207. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_create_safe_retry.py +0 -0
  208. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_departments.py +0 -0
  209. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_epic_decompose_run.py +0 -0
  210. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_epic_inherited_agent_id.py +0 -0
  211. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_epic_session_isolation.py +0 -0
  212. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_estimator.py +0 -0
  213. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_fallback_cli.py +0 -0
  214. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_fallback_cli_upgrade.py +0 -0
  215. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_firewall_open_on_update.py +0 -0
  216. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_formats.py +0 -0
  217. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_git_action.py +0 -0
  218. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_github_fetch.py +0 -0
  219. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_github_ingest.py +0 -0
  220. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_graph_recon.py +0 -0
  221. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_graphify_build.py +0 -0
  222. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_graphify_hook_install.py +0 -0
  223. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_health.py +0 -0
  224. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_help_attachments.py +0 -0
  225. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_infographic_data.py +0 -0
  226. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_intake_job_outcome.py +0 -0
  227. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_intake_plan_review.py +0 -0
  228. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_journal.py +0 -0
  229. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_limit_fallback_handoff.py +0 -0
  230. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_mcp_route_contract.py +0 -0
  231. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_memory_guard.py +0 -0
  232. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_panel_ticket_schedules.py +0 -0
  233. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_phase_timer.py +0 -0
  234. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_plan_run_activity.py +0 -0
  235. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_pr_identity.py +0 -0
  236. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_prd_artifact.py +0 -0
  237. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_project_path_resolution.py +0 -0
  238. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_proof_readers.py +0 -0
  239. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_providers.py +0 -0
  240. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_recon_session_isolation.py +0 -0
  241. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_resume.py +0 -0
  242. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_router.py +0 -0
  243. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_run_auto_agent_only.py +0 -0
  244. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_run_outputs.py +0 -0
  245. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_run_verdict_is_honest.py +0 -0
  246. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_schedule_api.py +0 -0
  247. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_schedule_outputs_and_plans.py +0 -0
  248. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_schedule_tickets.py +0 -0
  249. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_scheduler.py +0 -0
  250. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_scheduler_transient_retry.py +0 -0
  251. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_self_report.py +0 -0
  252. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_service_token_warning.py +0 -0
  253. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_stale_panel_restart.py +0 -0
  254. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_swagger_command.py +0 -0
  255. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_task_file_and_plan_run.py +0 -0
  256. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_ticket_fields.py +0 -0
  257. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_ticket_run_resolve_by_id.py +0 -0
  258. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_ui_gate.py +0 -0
  259. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_ui_lifespan.py +0 -0
  260. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_update_timer.py +0 -0
  261. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_updater_extras.py +0 -0
  262. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_updater_ignores_cwd.py +0 -0
  263. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_updater_pep668.py +0 -0
  264. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_updater_reports_the_truth.py +0 -0
  265. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_url_access.py +0 -0
  266. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_vps_health.py +0 -0
  267. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_vps_only_reporting.py +0 -0
  268. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_windows_loop_identity.py +0 -0
  269. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_windows_panel_task.py +0 -0
  270. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_windows_stop_and_pidfile.py +0 -0
  271. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/tests/test_windows_task_paths.py +0 -0
  272. {devops_bot_sdk-1.6.93 → devops_bot_sdk-1.7.5}/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.93
3
+ Version: 1.7.5
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.93
3
+ Version: 1.7.5
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
@@ -7,6 +7,7 @@ devops_bot_sdk.egg-info/entry_points.txt
7
7
  devops_bot_sdk.egg-info/requires.txt
8
8
  devops_bot_sdk.egg-info/top_level.txt
9
9
  sdk/__init__.py
10
+ sdk/agent_sharing.py
10
11
  sdk/agentd.py
11
12
  sdk/browser_profile.py
12
13
  sdk/claude_usage.py
@@ -15,6 +16,7 @@ sdk/client.py
15
16
  sdk/config.py
16
17
  sdk/crucial.py
17
18
  sdk/custom_agents.py
19
+ sdk/deferred_tickets.py
18
20
  sdk/departments.py
19
21
  sdk/estimator.py
20
22
  sdk/exceptions.py
@@ -26,12 +28,15 @@ sdk/github_fetch.py
26
28
  sdk/github_ingest.py
27
29
  sdk/graph_recon.py
28
30
  sdk/graphify.py
31
+ sdk/help_actions.py
29
32
  sdk/helpdesk.py
30
33
  sdk/helpdesk_kb.md
31
34
  sdk/intake.py
32
35
  sdk/journal.py
33
36
  sdk/local_exec.py
37
+ sdk/log_colors.py
34
38
  sdk/memory_guard.py
39
+ sdk/model_policy.py
35
40
  sdk/phase_timer.py
36
41
  sdk/plan_run.py
37
42
  sdk/platform_compat.py
@@ -52,6 +57,7 @@ sdk/task_file.py
52
57
  sdk/task_types.py
53
58
  sdk/test.py
54
59
  sdk/test_pipeline.py
60
+ sdk/ticket_board.py
55
61
  sdk/ticket_fields.py
56
62
  sdk/tickets.py
57
63
  sdk/updater.py
@@ -162,6 +168,7 @@ tests/test_agent_prompt_async.py
162
168
  tests/test_agent_prompt_models.py
163
169
  tests/test_agent_run_ticket.py
164
170
  tests/test_agent_schedules.py
171
+ tests/test_agent_sharing.py
165
172
  tests/test_agent_workspace_settings.py
166
173
  tests/test_agents_connectors_builder.py
167
174
  tests/test_allowed_tools_config.py
@@ -177,6 +184,7 @@ tests/test_configure_token_owner.py
177
184
  tests/test_console_encoding.py
178
185
  tests/test_crash_recovery.py
179
186
  tests/test_create_safe_retry.py
187
+ tests/test_deferred_tickets.py
180
188
  tests/test_departments.py
181
189
  tests/test_done_transition.py
182
190
  tests/test_epic_decompose_run.py
@@ -194,7 +202,9 @@ tests/test_graph_recon.py
194
202
  tests/test_graphify_build.py
195
203
  tests/test_graphify_hook_install.py
196
204
  tests/test_health.py
205
+ tests/test_help_actions.py
197
206
  tests/test_help_attachments.py
207
+ tests/test_help_questions.py
198
208
  tests/test_helpdesk.py
199
209
  tests/test_infographic_data.py
200
210
  tests/test_intake_job_outcome.py
@@ -202,10 +212,13 @@ tests/test_intake_plan_review.py
202
212
  tests/test_journal.py
203
213
  tests/test_limit_fallback_handoff.py
204
214
  tests/test_local_exec_provider.py
215
+ tests/test_log_colors_backlog.py
205
216
  tests/test_mcp_route_contract.py
206
217
  tests/test_memory_guard.py
218
+ tests/test_model_policy.py
207
219
  tests/test_panel_help.py
208
220
  tests/test_panel_ticket_schedules.py
221
+ tests/test_parallel_tickets.py
209
222
  tests/test_phase_timer.py
210
223
  tests/test_plan_new_command.py
211
224
  tests/test_plan_run_activity.py
@@ -231,6 +244,7 @@ tests/test_stale_panel_restart.py
231
244
  tests/test_swagger_command.py
232
245
  tests/test_task_file_and_plan_run.py
233
246
  tests/test_task_file_format_doc.py
247
+ tests/test_ticket_board.py
234
248
  tests/test_ticket_cli.py
235
249
  tests/test_ticket_fields.py
236
250
  tests/test_ticket_run_resolve_by_id.py
@@ -1,6 +1,6 @@
1
1
  """AgentOS Desktop SDK — thin HTTPS/SSE client for the Electron app.
2
2
 
3
- Version: 1.6.93
3
+ Version: 1.7.5
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.93" # SINGLE SOURCE OF TRUTH — bump on every change; pyproject,
37
+ __version__ = "1.7.5" # 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
@@ -80,12 +80,45 @@ class WinEvent:
80
80
  data: dict[str, str]
81
81
 
82
82
 
83
+ #: Characters XML 1.0 forbids. ``wevtutil`` writes them unescaped — most often an ESC
84
+ #: from coloured terminal output in a 4688 command line — and expat rejects the whole
85
+ #: document with "not well-formed (invalid token)".
86
+ _XML_INVALID = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f￾￿]")
87
+ #: Start of each top-level record; the ``[\s>]`` keeps ``<EventID>`` / ``<EventData>`` out.
88
+ _EVENT_START = re.compile(r"(?=<Event[\s>])")
89
+
90
+
83
91
  def parse_events(xml_text: str | None) -> list[WinEvent]:
84
- """Parse ``wevtutil qe ... /f:xml`` output (a bare run of ``<Event>`` elements)."""
85
- xml_text = (xml_text or "").strip()
92
+ """Parse ``wevtutil qe ... /f:xml`` output (a bare run of ``<Event>`` elements).
93
+
94
+ Never lets one bad record poison the batch. The poll loop only advances its
95
+ bookmark past records that parsed, so a batch that failed as a whole was re-read
96
+ and re-failed every poll forever — the machine silently stopped reporting.
97
+ Characters XML forbids are replaced first; if the batch still does not parse,
98
+ each record is parsed on its own and the unparseable ones are skipped.
99
+ """
100
+ xml_text = _XML_INVALID.sub("�", (xml_text or "").strip())
86
101
  if not xml_text:
87
102
  return []
88
- root = ET.fromstring(f"<Events>{xml_text}</Events>")
103
+ try:
104
+ return _parse_root(ET.fromstring(f"<Events>{xml_text}</Events>"))
105
+ except ET.ParseError as exc:
106
+ logger.warning("eventlog: batch did not parse (%s); parsing records one by one", exc)
107
+ out: list[WinEvent] = []
108
+ skipped = 0
109
+ for chunk in _EVENT_START.split(xml_text):
110
+ if not chunk.strip():
111
+ continue
112
+ try:
113
+ out.extend(_parse_root(ET.fromstring(f"<Events>{chunk}</Events>")))
114
+ except ET.ParseError:
115
+ skipped += 1
116
+ if skipped:
117
+ logger.warning("eventlog: skipped %d unparseable record(s)", skipped)
118
+ return out
119
+
120
+
121
+ def _parse_root(root: ET.Element) -> list[WinEvent]:
89
122
  out: list[WinEvent] = []
90
123
  for ev in root.iter(f"{_NS}Event"):
91
124
  sysnode = ev.find(f"{_NS}System")
@@ -0,0 +1,138 @@
1
+ """Share your custom agents with a person or a team — they accept before it appears.
2
+
3
+ The one implementation behind ``agentos agent share|shares|accept|decline|unshare``
4
+ and the Custom Agents page. State lives on the AI backend (devops-bot-ai, Mongo
5
+ ``agent_shares``); the SDK never stores a share.
6
+
7
+ Lifecycle: the OWNER shares an agent ``--to`` people (email or name) and/or a team
8
+ by name ("AI Team" → one invite per member). Each recipient gets a ``pending``
9
+ invite and ACCEPTS or DECLINES it; only accepted shares show up in their "Shared
10
+ with me" list and become runnable (``sdk.agents.chat.resolve_agent`` reads them).
11
+ It is a live reference, not a copy: the owner's later edits reach recipients, and
12
+ the owner can revoke at any time. Secret NAMES travel with the agent; values never
13
+ do — a recipient stores their own keys (``agentos agent set-key``).
14
+
15
+ Every function returns a dict with ``ok`` and, on failure, ``error``; none raise.
16
+ """
17
+ from __future__ import annotations
18
+
19
+ from typing import Any
20
+
21
+ _NOT_DEPLOYED = ("agent sharing isn't available on the AI backend yet — it ships with "
22
+ "the devops-bot-ai update; ask your admin to deploy it")
23
+
24
+
25
+ def _fail(client, fallback: str) -> dict:
26
+ err = getattr(client, "last_share_error", None) or {}
27
+ status = err.get("statusCode") if isinstance(err, dict) else None
28
+ detail = err.get("detail") if isinstance(err, dict) else None
29
+ if isinstance(detail, dict):
30
+ detail = detail.get("message") or detail.get("detail") or str(detail)
31
+ if detail is None and isinstance(err, dict):
32
+ detail = err.get("error")
33
+ text = str(detail or "").strip()
34
+ # A backend without sharing answers 404, or 405 where an older `/agents/{name}`
35
+ # route swallows the path — FastAPI's own bodies, not a real share error.
36
+ if status in (404, 405) and (not text or text.lower() in ("not found", "method not allowed")):
37
+ return {"ok": False, "error": _NOT_DEPLOYED, "status": status}
38
+ return {"ok": False, "error": text or fallback, "status": status}
39
+
40
+
41
+ async def targets(client, q: str = "", kind: str = "all") -> dict:
42
+ """People, teams and departments (names, emails, member counts) for the picker."""
43
+ res = await client.share_targets(q, kind)
44
+ if res is None:
45
+ return _fail(client, "could not search people, teams and departments")
46
+ return {"ok": True, "people": res.get("people") or [], "teams": res.get("teams") or [],
47
+ "departments": res.get("departments") or []}
48
+
49
+
50
+ async def share(client, agent: str, to: list[str], message: str = "") -> dict:
51
+ to = [t.strip() for t in to if t and t.strip()]
52
+ if not to:
53
+ return {"ok": False, "error": "say who to share with: --to \"Name\" or --to \"Team name\""}
54
+ res = await client.share_agent(agent, to, message)
55
+ if res is None:
56
+ return _fail(client, "share failed")
57
+ return {"ok": True, "shared": res.get("shared") or [], "skipped": res.get("skipped") or [],
58
+ "unresolved": res.get("unresolved") or []}
59
+
60
+
61
+ async def shares(client, direction: str = "incoming", status: str = "all") -> dict:
62
+ res = await client.list_shares(direction, status)
63
+ if res is None:
64
+ return _fail(client, "could not list shares")
65
+ return {"ok": True, "shares": res.get("shares") or []}
66
+
67
+
68
+ async def _resolve_id(client, ref: str, direction: str) -> tuple[str | None, str]:
69
+ """A share id, or a unique prefix of one (the CLI shows 8 characters)."""
70
+ ref = (ref or "").strip()
71
+ listed = await shares(client, direction, "all")
72
+ if not listed["ok"]:
73
+ return None, listed["error"]
74
+ hits = [s for s in listed["shares"] if str(s.get("id", "")).startswith(ref)]
75
+ if len(hits) == 1:
76
+ return str(hits[0]["id"]), ""
77
+ if not hits:
78
+ return None, f"no share {ref!r} — see `agentos agent shares`"
79
+ return None, f"{ref!r} matches {len(hits)} shares — give more of the id"
80
+
81
+
82
+ async def respond(client, ref: str, accept: bool) -> dict:
83
+ """Accept or decline one incoming invite (``ref`` = id or unique prefix)."""
84
+ share_id, err = await _resolve_id(client, ref, "incoming")
85
+ if not share_id:
86
+ return {"ok": False, "error": err}
87
+ res = await client.respond_share(share_id, "accept" if accept else "decline")
88
+ if res is None:
89
+ return _fail(client, "could not " + ("accept" if accept else "decline"))
90
+ return {"ok": True, "share": res}
91
+
92
+
93
+ async def accept_all(client) -> dict:
94
+ pending = await shares(client, "incoming", "pending")
95
+ if not pending["ok"]:
96
+ return pending
97
+ done, failed = [], []
98
+ for s in pending["shares"]:
99
+ res = await client.respond_share(str(s["id"]), "accept")
100
+ (done if res is not None else failed).append(s)
101
+ return {"ok": not failed, "accepted": done, "failed": failed,
102
+ **({"error": f"{len(failed)} could not be accepted"} if failed else {})}
103
+
104
+
105
+ async def revoke(client, ref: str) -> dict:
106
+ """Owner revokes a share they made, or a recipient removes one they hold."""
107
+ share_id, err = await _resolve_id(client, ref, "outgoing")
108
+ if not share_id:
109
+ share_id, err = await _resolve_id(client, ref, "incoming")
110
+ if not share_id:
111
+ return {"ok": False, "error": err}
112
+ res = await client.revoke_share(share_id)
113
+ if res is None:
114
+ return _fail(client, "could not remove the share")
115
+ return {"ok": True, "share": res}
116
+
117
+
118
+ def who(share: dict[str, Any], direction: str) -> str:
119
+ """The other party of a share, for display."""
120
+ if direction == "incoming":
121
+ name, email = share.get("owner_name"), share.get("owner_email")
122
+ else:
123
+ name, email = share.get("recipient_name"), share.get("recipient_email")
124
+ via = share.get("via_team") or {}
125
+ label = name or email or "?"
126
+ if email and name:
127
+ label = f"{name} <{email}>"
128
+ if not via.get("name"):
129
+ return label
130
+ return label + f" (via {'department' if via.get('kind') == 'department' else 'team'} {via['name']})"
131
+
132
+
133
+ def recipient_label(item: dict[str, Any]) -> str:
134
+ """A skipped/unresolved row's person by NAME — never the raw record or id."""
135
+ r = item.get("recipient") or {}
136
+ if isinstance(r, dict) and (r.get("name") or r.get("email")):
137
+ return r.get("name") or r.get("email")
138
+ return str(item.get("to") or "?")
@@ -25,6 +25,7 @@ from sdk.agents.prompt_vars import substitute_variables
25
25
  from sdk.agents import secrets as agent_secrets
26
26
  from sdk.agents import varstore as agent_varstore
27
27
  from sdk.agents import run_log
28
+ from sdk.exceptions import BackendFeatureMissing
28
29
 
29
30
  logger = logging.getLogger("sdk.agents.chat")
30
31
 
@@ -58,6 +59,8 @@ async def _fetch_rows(fetch) -> list[dict]:
58
59
  await asyncio.sleep(delay)
59
60
  try:
60
61
  return await fetch() or []
62
+ except BackendFeatureMissing:
63
+ raise # the endpoint is absent: retrying cannot change that
61
64
  except Exception as exc: # noqa: BLE001 — classified by the caller
62
65
  last = exc
63
66
  assert last is not None
@@ -129,13 +132,17 @@ async def resolve_agent(name: str, client=None) -> AgentManifest:
129
132
  reasons: list[str] = []
130
133
  unreadable = False
131
134
  for label, attr in (("your agents", "list_custom_agents"),
132
- ("department defaults", "list_department_agents")):
135
+ ("department defaults", "list_department_agents"),
136
+ # Accepted shares (sdk/agent_sharing.py): runnable like your own.
137
+ ("agents shared with you", "list_shared_agents")):
133
138
  fetch = getattr(client, attr, None)
134
139
  if fetch is None:
135
140
  continue
136
141
  try:
137
142
  rows = await _fetch_rows(fetch)
138
143
  except Exception as exc: # noqa: BLE001 — a fetch failure is not "not found"
144
+ if attr == "list_shared_agents" and isinstance(exc, BackendFeatureMissing):
145
+ continue # a backend without sharing has none to offer — not "unreadable"
139
146
  unreadable = True
140
147
  reasons.append(f"{label} could not be fetched ({str(exc) or type(exc).__name__})")
141
148
  continue
@@ -150,7 +157,8 @@ async def resolve_agent(name: str, client=None) -> AgentManifest:
150
157
  )
151
158
 
152
159
  detail = "; ".join(reasons) if reasons else (
153
- "not in ~/.agentos/agents/, your backend agents, or your department defaults"
160
+ "not in ~/.agentos/agents/, your backend agents, your department defaults, "
161
+ "or agents shared with you"
154
162
  )
155
163
  if unreadable:
156
164
  manifest = await _gateway_manifest(client, name)
@@ -267,6 +275,7 @@ async def run_agent(
267
275
  trigger: str = "",
268
276
  kind: str = "run",
269
277
  client=None,
278
+ extra_env: dict[str, str] | None = None,
270
279
  ) -> dict:
271
280
  """Run an agent once against its own standing prompt — NOT a chat turn.
272
281
 
@@ -285,7 +294,8 @@ async def run_agent(
285
294
  ``trigger`` / ``kind`` are recorded in the run's output file so a reader can
286
295
  tell a cron firing from someone pressing Run. ``client`` lets a caller that
287
296
  already has a :class:`BackendClient` reuse it instead of having one built per
288
- run (see :func:`resolve_agent`).
297
+ run (see :func:`resolve_agent`). ``extra_env`` is added to the agent process's
298
+ environment on top of its stored keys (the scheduler marks its runs this way).
289
299
 
290
300
  Returns the engine's normalized result dict. Raises ``ValueError`` if any
291
301
  ``{{variable}}`` is left unfilled — the UI gates the Run button on this, and
@@ -324,14 +334,15 @@ async def run_agent(
324
334
  variables=variables, trigger=trigger,
325
335
  )
326
336
  teed = _tee_events(log_path, on_event)
337
+ run_env = {**(stored_secrets or {}), **(extra_env or {})} or None
327
338
 
328
339
  if manifest.engine in ("claude_code", "model"):
329
340
  result = await claude_code_engine.run(
330
341
  turn, skill_text, mcp_config, project_path=project_path,
331
- on_event=teed, extra_env=stored_secrets or None,
342
+ on_event=teed, extra_env=run_env,
332
343
  )
333
344
  elif manifest.engine == "shell":
334
- result = await shell_engine.run(turn, extra_env=stored_secrets or None)
345
+ result = await shell_engine.run(turn, extra_env=run_env)
335
346
  else:
336
347
  result = {
337
348
  "ok": False,