talkops-opscloud 0.3.0b5__tar.gz → 0.3.0b7__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 (400) hide show
  1. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/PKG-INFO +1 -1
  2. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/pyproject.toml +1 -1
  3. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/cli/interactive.py +16 -0
  4. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/cli/server_manager.py +12 -3
  5. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/pool.py +11 -1
  6. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/skills.py +10 -1
  7. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/model/pool.py +59 -52
  8. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/server/server.py +179 -27
  9. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/server/server_graph.py +57 -26
  10. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/state/session.py +11 -0
  11. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/app.py +121 -14
  12. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/autocomplete.py +41 -2
  13. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/chat_input.py +210 -42
  14. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/pool_selector.py +9 -3
  15. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/conftest.py +24 -2
  16. talkops_opscloud-0.3.0b7/tests/unit_tests/test_chat_input_responsiveness.py +143 -0
  17. talkops_opscloud-0.3.0b7/tests/unit_tests/test_checkpointer.py +115 -0
  18. talkops_opscloud-0.3.0b7/tests/unit_tests/test_pool_persistence.py +173 -0
  19. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_reload_restart.py +82 -0
  20. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_server.py +38 -4
  21. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/uv.lock +1 -1
  22. talkops_opscloud-0.3.0b5/tests/unit_tests/test_checkpointer.py +0 -87
  23. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/.dockerignore +0 -0
  24. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/.env.example +0 -0
  25. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/.github/workflows/ci.yml +0 -0
  26. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/.github/workflows/release-pypi.yml +0 -0
  27. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/.gitignore +0 -0
  28. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/.python-version +0 -0
  29. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/LICENSE +0 -0
  30. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/README.md +0 -0
  31. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/assets/opscloud-banner.gif +0 -0
  32. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/Configuration.md +0 -0
  33. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/approval-mode.md +0 -0
  34. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/cli-reference.md +0 -0
  35. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/config.toml.md +0 -0
  36. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/credentials.md +0 -0
  37. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/goal-and-rubrics.md +0 -0
  38. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/hooks.md +0 -0
  39. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/mcp-tools.md +0 -0
  40. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/memory-and-skills.md +0 -0
  41. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/model-providers.md +0 -0
  42. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/overview.md +0 -0
  43. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/plugins.md +0 -0
  44. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/quickstart.md +0 -0
  45. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/remote-sandboxes.md +0 -0
  46. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/docs/opscloud-docs/subagents.md +0 -0
  47. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/scripts/install.sh +0 -0
  48. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/__init__.py +0 -0
  49. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/__main__.py +0 -0
  50. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/_constants.py +0 -0
  51. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/_debug.py +0 -0
  52. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/_debug_buffer.py +0 -0
  53. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/_textual_patches.py +0 -0
  54. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/_version.py +0 -0
  55. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/agent/__init__.py +0 -0
  56. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/agent/config.py +0 -0
  57. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/agent/factory.py +0 -0
  58. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/approval_mode.py +0 -0
  59. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/backend/__init__.py +0 -0
  60. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/backend/composite.py +0 -0
  61. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/backend/local.py +0 -0
  62. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/backend/registry.py +0 -0
  63. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/backend/sandbox_config.py +0 -0
  64. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/backend/sandbox_factory.py +0 -0
  65. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/built_in_skills/remember/SKILL.md +0 -0
  66. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/built_in_skills/skill-creator/SKILL.md +0 -0
  67. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  68. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  69. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/cli/__init__.py +0 -0
  70. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/cli/commands/__init__.py +0 -0
  71. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/cli/commands/auth.py +0 -0
  72. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/cli/commands/doctor.py +0 -0
  73. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/cli/commands/mcp.py +0 -0
  74. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/cli/commands/threads.py +0 -0
  75. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/cli/main.py +0 -0
  76. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/cli/non_interactive.py +0 -0
  77. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/__init__.py +0 -0
  78. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/_base.py +0 -0
  79. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/_guards.py +0 -0
  80. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/_router.py +0 -0
  81. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/_types.py +0 -0
  82. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/__init__.py +0 -0
  83. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/auth.py +0 -0
  84. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/bug.py +0 -0
  85. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/clear.py +0 -0
  86. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/cloud.py +0 -0
  87. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/compact.py +0 -0
  88. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/config_cmd.py +0 -0
  89. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/context.py +0 -0
  90. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/cost.py +0 -0
  91. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/doctor.py +0 -0
  92. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/effort.py +0 -0
  93. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/exit_cmd.py +0 -0
  94. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/fast.py +0 -0
  95. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/help_cmd.py +0 -0
  96. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/mcp.py +0 -0
  97. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/model.py +0 -0
  98. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/permissions.py +0 -0
  99. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/plugins.py +0 -0
  100. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/resume.py +0 -0
  101. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/core/skills.py +0 -0
  102. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/__init__.py +0 -0
  103. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/agents.py +0 -0
  104. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/btw.py +0 -0
  105. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/copy.py +0 -0
  106. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/goal.py +0 -0
  107. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/loop.py +0 -0
  108. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/memory.py +0 -0
  109. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/review.py +0 -0
  110. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/rubric.py +0 -0
  111. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/runtime.py +0 -0
  112. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/skill_creator.py +0 -0
  113. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/skill_invoke.py +0 -0
  114. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/tasks.py +0 -0
  115. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/trace.py +0 -0
  116. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/ui_toggles.py +0 -0
  117. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/power/version.py +0 -0
  118. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/commands/registry.py +0 -0
  119. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/__init__.py +0 -0
  120. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/adapters/__init__.py +0 -0
  121. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/adapters/postgres.py +0 -0
  122. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/adapters/sqlite.py +0 -0
  123. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/aws.py +0 -0
  124. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/cloud_profiles.py +0 -0
  125. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/env_vars.py +0 -0
  126. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/langsmith.py +0 -0
  127. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/manifest.py +0 -0
  128. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/metadata.py +0 -0
  129. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/paths.py +0 -0
  130. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/plugins.py +0 -0
  131. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/settings.py +0 -0
  132. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/store.py +0 -0
  133. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/store_factory.py +0 -0
  134. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/config/toml_config.py +0 -0
  135. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/editor.py +0 -0
  136. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/exceptions.py +0 -0
  137. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/file_ops.py +0 -0
  138. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/hooks/__init__.py +0 -0
  139. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/hooks/env.py +0 -0
  140. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/hooks/interrupt.py +0 -0
  141. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/hooks/models/__init__.py +0 -0
  142. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/hooks/models/adapters.py +0 -0
  143. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/hooks/models/config.py +0 -0
  144. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/hooks/models/domain.py +0 -0
  145. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/hooks/models/transport.py +0 -0
  146. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/hooks/tools.py +0 -0
  147. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/input.py +0 -0
  148. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/integrations/__init__.py +0 -0
  149. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/integrations/base.py +0 -0
  150. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/integrations/content_filter.py +0 -0
  151. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/integrations/event_bus.py +0 -0
  152. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/integrations/hooks.py +0 -0
  153. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/integrations/identity.py +0 -0
  154. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/integrations/notifications.py +0 -0
  155. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/integrations/stream_bridge.py +0 -0
  156. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/integrations/thread_store.py +0 -0
  157. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/json_types.py +0 -0
  158. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/mcp/__init__.py +0 -0
  159. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/mcp/config.py +0 -0
  160. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/mcp/discovery.py +0 -0
  161. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/mcp/mcp_info.py +0 -0
  162. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/mcp/middleware.py +0 -0
  163. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/mcp/preload.py +0 -0
  164. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/mcp/raw_config.py +0 -0
  165. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/mcp/semantic_profiler.py +0 -0
  166. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/mcp/session_manager.py +0 -0
  167. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/mcp/trust.py +0 -0
  168. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/memory/__init__.py +0 -0
  169. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/memory/branch.py +0 -0
  170. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/memory/guard.py +0 -0
  171. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/memory/onboarding.py +0 -0
  172. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/memory/registry.py +0 -0
  173. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/memory/store.py +0 -0
  174. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/__init__.py +0 -0
  175. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/_repository_bounds.py +0 -0
  176. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/ask_user.py +0 -0
  177. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/auto_mode.py +0 -0
  178. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/auto_mode_hitl.py +0 -0
  179. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/compaction.py +0 -0
  180. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/configurable_model.py +0 -0
  181. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/cost_tracking.py +0 -0
  182. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/glm_stall_recovery.py +0 -0
  183. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/goal_criteria.py +0 -0
  184. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/goal_state_notice.py +0 -0
  185. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/goal_tools.py +0 -0
  186. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/headless_mcp_guard.py +0 -0
  187. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/jev_model_router.py +0 -0
  188. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/local_context.py +0 -0
  189. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/mcp_context.py +0 -0
  190. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/mcp_middleware.py +0 -0
  191. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/memory_guard.py +0 -0
  192. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/model_retry.py +0 -0
  193. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/registry.py +0 -0
  194. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/reliable_rubric.py +0 -0
  195. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/resume_state.py +0 -0
  196. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/server_hooks.py +0 -0
  197. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/shell_allow_list.py +0 -0
  198. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/subagent_artifacts.py +0 -0
  199. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/subagent_telemetry.py +0 -0
  200. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/subagents.py +0 -0
  201. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/tool_filter.py +0 -0
  202. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/middleware/unified_system_message.py +0 -0
  203. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/model/__init__.py +0 -0
  204. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/model/config.py +0 -0
  205. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/model/factory.py +0 -0
  206. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/model/reasoning.py +0 -0
  207. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/offload.py +0 -0
  208. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/output.py +0 -0
  209. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/__init__.py +0 -0
  210. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/_json.py +0 -0
  211. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/adapters/__init__.py +0 -0
  212. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/adapters/agents.py +0 -0
  213. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/adapters/commands.py +0 -0
  214. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/adapters/mcp.py +0 -0
  215. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/adapters/skills.py +0 -0
  216. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/commands_cli.py +0 -0
  217. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/discovery.py +0 -0
  218. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/manifest.py +0 -0
  219. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/marketplace.py +0 -0
  220. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/models.py +0 -0
  221. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/project_plugins.py +0 -0
  222. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/protocol.py +0 -0
  223. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/store.py +0 -0
  224. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/plugins/substitution.py +0 -0
  225. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/project_utils.py +0 -0
  226. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/prompts/__init__.py +0 -0
  227. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/prompts/system.py +0 -0
  228. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/prompts/templates/system_prompt.md +0 -0
  229. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/prompts/types.py +0 -0
  230. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/rubrics/__init__.py +0 -0
  231. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/rubrics/evaluator.py +0 -0
  232. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/rubrics/evidence_extractor.py +0 -0
  233. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/rubrics/generator.py +0 -0
  234. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/rubrics/jev_compiler.py +0 -0
  235. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/rubrics/jev_grader.py +0 -0
  236. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/rubrics/middleware.py +0 -0
  237. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/schema/__init__.py +0 -0
  238. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/schema/interrupts.py +0 -0
  239. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/security/__init__.py +0 -0
  240. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/security/approval_mode.py +0 -0
  241. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/security/approval_mode_source.py +0 -0
  242. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/security/cli_ast_evaluator.py +0 -0
  243. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/security/jev_classifier.py +0 -0
  244. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/security/shell_safety.py +0 -0
  245. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/security/unicode_security.py +0 -0
  246. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/security/url_validation.py +0 -0
  247. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/server/__init__.py +0 -0
  248. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/server/_server_config.py +0 -0
  249. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/skills/__init__.py +0 -0
  250. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/skills/commands.py +0 -0
  251. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/skills/invocation.py +0 -0
  252. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/skills/load.py +0 -0
  253. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/skills/loader.py +0 -0
  254. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/skills/merge.py +0 -0
  255. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/skills/registry.py +0 -0
  256. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/skills/sources.py +0 -0
  257. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/skills/trust.py +0 -0
  258. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/state/__init__.py +0 -0
  259. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/state/base.py +0 -0
  260. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/state/cloud_context.py +0 -0
  261. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/state/goal_channels.py +0 -0
  262. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/state/goal_state_limits.py +0 -0
  263. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/state/resume_state.py +0 -0
  264. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/state/service_context.py +0 -0
  265. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/state/state_migration.py +0 -0
  266. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/subagents/__init__.py +0 -0
  267. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/subagents/loader.py +0 -0
  268. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/subagents/subagents_parser.py +0 -0
  269. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/subagents/types.py +0 -0
  270. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/tools/__init__.py +0 -0
  271. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/tools/catalog.py +0 -0
  272. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/tools/display.py +0 -0
  273. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/tools/fetch_url.py +0 -0
  274. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/tools/goal_tools.py +0 -0
  275. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/tools/registry.py +0 -0
  276. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/tools/thread.py +0 -0
  277. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/tools/web_search.py +0 -0
  278. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/__init__.py +0 -0
  279. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/app.tcss +0 -0
  280. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/clipboard.py +0 -0
  281. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/command_registry.py +0 -0
  282. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/message_store.py +0 -0
  283. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/permission_store.py +0 -0
  284. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/preferences.py +0 -0
  285. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/prompt_manager.py +0 -0
  286. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/remote_client.py +0 -0
  287. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/textual_adapter.py +0 -0
  288. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/theme.py +0 -0
  289. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/ui_help.py +0 -0
  290. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/__init__.py +0 -0
  291. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/_ask_user_types.py +0 -0
  292. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/_copy_spans.py +0 -0
  293. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/_inline_prompt.py +0 -0
  294. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/_js_eval_display.py +0 -0
  295. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/_links.py +0 -0
  296. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/_tool_stream.py +0 -0
  297. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/agent_selector.py +0 -0
  298. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/approval.py +0 -0
  299. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/ask_user.py +0 -0
  300. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/auth.py +0 -0
  301. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/auth_manager.py +0 -0
  302. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/auto_mode_notice.py +0 -0
  303. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/cloud_selector.py +0 -0
  304. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/config_manager.py +0 -0
  305. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/debug_console.py +0 -0
  306. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/devops_renderers.py +0 -0
  307. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/diff.py +0 -0
  308. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/effort_selector.py +0 -0
  309. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/goal_review.py +0 -0
  310. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/goal_status.py +0 -0
  311. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/infra_panel.py +0 -0
  312. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/install_confirm.py +0 -0
  313. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/loading.py +0 -0
  314. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/mcp_viewer.py +0 -0
  315. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/messages.py +0 -0
  316. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/model_selector.py +0 -0
  317. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/notification_center.py +0 -0
  318. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/notification_settings.py +0 -0
  319. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/operation_card.py +0 -0
  320. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/permissions_manager.py +0 -0
  321. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/plugin_manager.py +0 -0
  322. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/preamble.py +0 -0
  323. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/skills_viewer.py +0 -0
  324. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/status.py +0 -0
  325. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/subagent_panel.py +0 -0
  326. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/theme_selector.py +0 -0
  327. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/thread_selector.py +0 -0
  328. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/toast.py +0 -0
  329. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/tool_display.py +0 -0
  330. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/tool_renderers.py +0 -0
  331. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/tool_widgets.py +0 -0
  332. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/welcome.py +0 -0
  333. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/ui/widgets/welcome_popup.py +0 -0
  334. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/utils/__init__.py +0 -0
  335. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/utils/cost_estimation.py +0 -0
  336. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/utils/git.py +0 -0
  337. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/utils/logger.py +0 -0
  338. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/utils/session_stats.py +0 -0
  339. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/src/opscloud/utils/startup_error.py +0 -0
  340. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/__init__.py +0 -0
  341. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/evals/__init__.py +0 -0
  342. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/evals/datasets/aws_cloud_ops.yaml +0 -0
  343. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/evals/evaluators/__init__.py +0 -0
  344. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/evals/evaluators/output_evaluator.py +0 -0
  345. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/evals/evaluators/trajectory_evaluator.py +0 -0
  346. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/evals/runners/test_eval_runner.py +0 -0
  347. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/integration_tests/test_agent_lifecycle.py +0 -0
  348. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/integration_tests/test_server_lifecycle.py +0 -0
  349. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_agent_factory.py +0 -0
  350. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_approval_widget.py +0 -0
  351. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_ask_user.py +0 -0
  352. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_ast_evaluator.py +0 -0
  353. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_backend.py +0 -0
  354. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_claude_opus_reasoning.py +0 -0
  355. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_cli_enhancements.py +0 -0
  356. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_cli_rubric.py +0 -0
  357. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_cloud_command.py +0 -0
  358. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_commands.py +0 -0
  359. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_config.py +0 -0
  360. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_cost_tracking.py +0 -0
  361. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_default_marketplace.py +0 -0
  362. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_goal_criteria.py +0 -0
  363. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_goal_state_limits.py +0 -0
  364. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_goal_state_notice.py +0 -0
  365. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_grader_tools.py +0 -0
  366. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_hitl.py +0 -0
  367. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_integrations_and_hooks.py +0 -0
  368. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_interrupt_schemas.py +0 -0
  369. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_jev_model_router.py +0 -0
  370. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_jev_rubrics.py +0 -0
  371. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_local_context.py +0 -0
  372. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_logging.py +0 -0
  373. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_mcp.py +0 -0
  374. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_mcp_middleware.py +0 -0
  375. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_mcp_viewer_and_command.py +0 -0
  376. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_memory.py +0 -0
  377. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_memory_enhancements.py +0 -0
  378. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_middleware_stack.py +0 -0
  379. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_model_providers.py +0 -0
  380. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_model_retry.py +0 -0
  381. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_plugin_agent_skill_mcp_scoping.py +0 -0
  382. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_plugin_manager_search.py +0 -0
  383. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_plugins.py +0 -0
  384. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_project_plugins.py +0 -0
  385. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_prompts_and_schema.py +0 -0
  386. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_reliable_rubric.py +0 -0
  387. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_resume_state.py +0 -0
  388. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_resumed_thread_latency_fix.py +0 -0
  389. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_rubrics.py +0 -0
  390. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_security.py +0 -0
  391. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_server_hooks.py +0 -0
  392. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_skill_creator.py +0 -0
  393. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_skills.py +0 -0
  394. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_state.py +0 -0
  395. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_subagents.py +0 -0
  396. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_tool_filter.py +0 -0
  397. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_tools.py +0 -0
  398. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_tui_app.py +0 -0
  399. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/tests/unit_tests/test_utils.py +0 -0
  400. {talkops_opscloud-0.3.0b5 → talkops_opscloud-0.3.0b7}/uv-requirements.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: talkops-opscloud
3
- Version: 0.3.0b5
3
+ Version: 0.3.0b7
4
4
  Summary: Extensible Terminal Multi-Agent Framework for Cloud Operations & DevOps Coding
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "talkops-opscloud"
3
- version = "0.3.0b5"
3
+ version = "0.3.0b7"
4
4
  description = "Extensible Terminal Multi-Agent Framework for Cloud Operations & DevOps Coding"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -120,6 +120,21 @@ def run_interactive(
120
120
  "trust_project_mcp": trust_project_mcp,
121
121
  }
122
122
 
123
+ server_kwargs: dict[str, Any] = {
124
+ "assistant_id": "opscloud",
125
+ "model_name": resolved_model,
126
+ "interactive": True,
127
+ "auto_approve": (approval_mode == ApprovalMode.AUTO or approval_mode == "auto"),
128
+ "cwd": resolved_cwd,
129
+ "read_only": read_only,
130
+ "aws_profile": aws_profile,
131
+ "aws_region": aws_region,
132
+ "shell_allow_list": tuple(shell_allow_list) if shell_allow_list else None,
133
+ "mcp_config_path": mcp_config_path,
134
+ "no_mcp": no_mcp,
135
+ "trust_project_mcp": trust_project_mcp,
136
+ }
137
+
123
138
  try:
124
139
  app = OpsCloudApp(
125
140
  server_url=url,
@@ -129,6 +144,7 @@ def run_interactive(
129
144
  model=resolved_model,
130
145
  approval_mode=approval_mode,
131
146
  defer_server_start=defer_server_start,
147
+ server_kwargs=server_kwargs,
132
148
  goal=goal,
133
149
  cwd=resolved_cwd,
134
150
  mcp_preload_kwargs=mcp_preload_kwargs,
@@ -36,7 +36,7 @@ async def start_server_and_get_agent(
36
36
  port: int = 0,
37
37
  **kwargs: Any,
38
38
  ) -> tuple[RemoteAgent, ServerProcess]:
39
- """Start a LangGraph dev server and return a RemoteAgent client."""
39
+ """Start a LangGraph dev server asynchronously and return a RemoteAgent client."""
40
40
  from opscloud.project_utils import ProjectContext
41
41
 
42
42
  project_context = (
@@ -44,15 +44,24 @@ async def start_server_and_get_agent(
44
44
  if cwd is not None
45
45
  else ProjectContext.from_user_cwd(Path.cwd())
46
46
  )
47
+ resolved_model = model_name or kwargs.pop("model", None)
48
+ if not resolved_model:
49
+ try:
50
+ from opscloud.model.factory import _get_default_model_spec
51
+
52
+ resolved_model = _get_default_model_spec()
53
+ except Exception:
54
+ resolved_model = None
55
+
47
56
  config = ServerConfig.from_cli_args(
48
57
  project_context=project_context,
49
58
  assistant_id=assistant_id,
50
- model=model_name or "anthropic:claude-3-5-sonnet-latest",
59
+ model=resolved_model,
51
60
  interactive=interactive,
52
61
  approval_mode="never" if auto_approve else "auto",
53
62
  **kwargs,
54
63
  )
55
64
  server = ServerProcess(config, host=host, port=port)
56
- url = server.start()
65
+ url = await server.astart()
57
66
  agent = RemoteAgent(url=url, graph_name="agent")
58
67
  return agent, server
@@ -41,6 +41,9 @@ class PoolHandler(BaseCommandHandler):
41
41
  # 1. Clear pool configuration
42
42
  if args in ("--clear", "clear"):
43
43
  clear_agent_pool()
44
+ pool_mgr = get_model_pool_manager()
45
+ with pool_mgr._lock:
46
+ pool_mgr._instances.clear()
44
47
  return CommandResult(
45
48
  success=True,
46
49
  message="**Agent Model Pool Cleared:** Reverted to automatic dynamic discovery from provider capabilities.",
@@ -84,7 +87,7 @@ class PoolHandler(BaseCommandHandler):
84
87
  current = load_agent_pool() or {}
85
88
  merged = {**current, **updates}
86
89
 
87
- from opscloud.model.config import detect_provider
90
+ from opscloud.model.config import detect_provider, apply_stored_credentials
88
91
  provs = set()
89
92
  for v in merged.values():
90
93
  if ":" in v:
@@ -97,6 +100,13 @@ class PoolHandler(BaseCommandHandler):
97
100
  provider_to_save = next(iter(provs)) if len(provs) == 1 else ("multi" if len(provs) > 1 else None)
98
101
  save_agent_pool(merged, provider=provider_to_save)
99
102
 
103
+ pool_mgr = get_model_pool_manager()
104
+ with pool_mgr._lock:
105
+ pool_mgr._instances.clear()
106
+
107
+ for p in provs:
108
+ apply_stored_credentials(p)
109
+
100
110
  from opscloud.model.config import has_provider_credentials
101
111
  warnings = []
102
112
  for p in provs:
@@ -222,6 +222,7 @@ class PluginSkillsMiddleware(SkillsMiddleware):
222
222
  source[2] if len(source) == _PLUGIN_SKILL_SOURCE_LENGTH else None for source in sources
223
223
  )
224
224
  self._allowed_skills = tuple(allowed_skills) if allowed_skills is not None else None
225
+ self._cached_live_skills: list[sdk_skills.SkillMetadata] | None = None
225
226
 
226
227
  def _format_skills_locations(self) -> str:
227
228
  """Format skills locations for display in system prompt."""
@@ -322,6 +323,7 @@ class PluginSkillsMiddleware(SkillsMiddleware):
322
323
  SkillsStateUpdate if changes were detected, or None.
323
324
  """
324
325
  live_skills, errors = self._get_live_skills()
326
+ self._cached_live_skills = live_skills
325
327
  current_skills = state.get("skills_metadata") or []
326
328
  current_names = [s["name"] for s in current_skills]
327
329
  live_names = [s["name"] for s in live_skills]
@@ -362,7 +364,14 @@ class PluginSkillsMiddleware(SkillsMiddleware):
362
364
  Returns:
363
365
  Modified request with pruned skill metadata.
364
366
  """
365
- live_skills, _ = self._get_live_skills()
367
+ live_skills = getattr(self, "_cached_live_skills", None)
368
+ if live_skills is None:
369
+ if hasattr(request, "state") and isinstance(request.state, dict) and request.state.get("skills_metadata"):
370
+ live_skills = request.state["skills_metadata"]
371
+ else:
372
+ live_skills, _ = self._get_live_skills()
373
+ self._cached_live_skills = live_skills
374
+
366
375
  live_names = {s["name"] for s in live_skills}
367
376
 
368
377
  if hasattr(request, "state") and isinstance(request.state, dict):
@@ -169,70 +169,77 @@ class DynamicModelPoolManager:
169
169
  self,
170
170
  provider: str | None = None,
171
171
  base_spec: str | None = None,
172
+ *,
173
+ ignore_custom_pool: bool = False,
172
174
  ) -> dict[int, tuple[str, str]]:
173
175
  """Dynamically build Tier 0, 1, and 2 definitions from registry metadata.
174
176
 
175
177
  Args:
176
178
  provider: Target provider name, or None to infer.
177
179
  base_spec: Baseline model spec selected by the session/thread.
180
+ ignore_custom_pool: If True, bypass user-configured [agent_pool] and
181
+ perform raw registry discovery for the requested provider/baseline.
178
182
 
179
183
  Returns:
180
184
  Dictionary mapping tier level (0, 1, 2) to (model_spec, reasoning_effort).
181
185
  """
182
186
  # 1. Prioritize user-configured pool from config.toml [agent_pool]
183
- from opscloud.config.toml_config import load_agent_pool
187
+ if not ignore_custom_pool:
188
+ from opscloud.config.toml_config import load_agent_pool
189
+
190
+ user_pool = load_agent_pool()
191
+ if user_pool:
192
+ resolved_provider = self._resolve_provider(provider, base_spec)
193
+ pool_prov = user_pool.get("provider")
194
+ t0_raw = user_pool.get("fast")
195
+ t1_raw = user_pool.get("standard")
196
+ t2_raw = user_pool.get("powerful")
197
+
198
+ if t0_raw and t1_raw and t2_raw:
199
+ def _norm(raw_spec: str) -> str:
200
+ s = raw_spec.strip()
201
+ if ":" not in s:
202
+ inferred = detect_provider(s)
203
+ if inferred and inferred in AVAILABLE_MODELS:
204
+ return f"{inferred}:{s}"
205
+ if pool_prov and pool_prov in AVAILABLE_MODELS:
206
+ return f"{pool_prov}:{s}"
207
+ return f"{resolved_provider}:{s}"
208
+ return normalize_model_spec(s)
209
+
210
+ t0 = _norm(t0_raw)
211
+ t1 = _norm(t1_raw)
212
+ t2 = _norm(t2_raw)
213
+
214
+ prov0 = t0.split(":", 1)[0] if ":" in t0 else resolved_provider
215
+ prov1 = t1.split(":", 1)[0] if ":" in t1 else resolved_provider
216
+ prov2 = t2.split(":", 1)[0] if ":" in t2 else resolved_provider
217
+ distinct_provs = {prov0, prov1, prov2}
218
+ is_multi = len(distinct_provs) > 1 or pool_prov == "multi"
219
+
220
+ should_use_custom = (
221
+ not provider
222
+ or provider in ("dynamic", "auto")
223
+ or is_multi
224
+ or provider == pool_prov
225
+ or provider in distinct_provs
226
+ )
184
227
 
185
- user_pool = load_agent_pool()
186
- if user_pool:
187
- resolved_provider = self._resolve_provider(provider, base_spec)
188
- pool_prov = user_pool.get("provider")
189
- t0_raw = user_pool.get("fast")
190
- t1_raw = user_pool.get("standard")
191
- t2_raw = user_pool.get("powerful")
192
-
193
- if t0_raw and t1_raw and t2_raw:
194
- def _norm(raw_spec: str) -> str:
195
- s = raw_spec.strip()
196
- if ":" not in s:
197
- inferred = detect_provider(s)
198
- if inferred and inferred in AVAILABLE_MODELS:
199
- return f"{inferred}:{s}"
200
- return f"{resolved_provider}:{s}"
201
- return normalize_model_spec(s)
202
-
203
- t0 = _norm(t0_raw)
204
- t1 = _norm(t1_raw)
205
- t2 = _norm(t2_raw)
206
-
207
- prov0 = t0.split(":", 1)[0] if ":" in t0 else resolved_provider
208
- prov1 = t1.split(":", 1)[0] if ":" in t1 else resolved_provider
209
- prov2 = t2.split(":", 1)[0] if ":" in t2 else resolved_provider
210
- distinct_provs = {prov0, prov1, prov2}
211
- is_multi = len(distinct_provs) > 1 or pool_prov == "multi"
212
-
213
- if (
214
- is_multi
215
- or not provider
216
- or provider in ("dynamic", "auto")
217
- or not pool_prov
218
- or pool_prov == "multi"
219
- or pool_prov == resolved_provider
220
- or pool_prov in distinct_provs
221
- ):
222
- t0_efforts = supported_efforts_for_model(t0)
223
- e0 = "off" if ("off" in t0_efforts or not t0_efforts) else ("minimal" if "minimal" in t0_efforts else "off")
224
-
225
- t1_efforts = supported_efforts_for_model(t1)
226
- e1 = "medium" if "medium" in t1_efforts else (default_effort_for_model(t1) or "off")
227
-
228
- t2_efforts = supported_efforts_for_model(t2)
229
- e2 = "max" if "max" in t2_efforts else ("high" if "high" in t2_efforts else ("medium" if "medium" in t2_efforts else (default_effort_for_model(t2) or "off")))
230
-
231
- return {
232
- 0: (t0, e0),
233
- 1: (t1, e1),
234
- 2: (t2, e2),
235
- }
228
+ if should_use_custom:
229
+ t0_efforts = supported_efforts_for_model(t0)
230
+ e0 = "off" if ("off" in t0_efforts or not t0_efforts) else ("minimal" if "minimal" in t0_efforts else "off")
231
+
232
+ t1_efforts = supported_efforts_for_model(t1)
233
+ e1 = "medium" if "medium" in t1_efforts else (default_effort_for_model(t1) or "off")
234
+
235
+ t2_efforts = supported_efforts_for_model(t2)
236
+ e2 = "max" if "max" in t2_efforts else ("high" if "high" in t2_efforts else ("medium" if "medium" in t2_efforts else (default_effort_for_model(t2) or "off")))
237
+
238
+ return {
239
+ 0: (t0, e0),
240
+ 1: (t1, e1),
241
+ 2: (t2, e2),
242
+ }
236
243
 
237
244
  all_supported = [p for p in DEFAULT_PROVIDER_PRIORITY if p in AVAILABLE_MODELS] + [
238
245
  p for p in AVAILABLE_MODELS if p not in DEFAULT_PROVIDER_PRIORITY
@@ -23,8 +23,26 @@ from opscloud.utils.logger import get_active_log_file, get_logger
23
23
  logger = get_logger(__name__)
24
24
 
25
25
  _DEFAULT_HOST = "127.0.0.1"
26
+ _DEFAULT_HEALTH_TIMEOUT = 60.0
27
+ _HEALTH_POLL_INTERVAL = 0.1
26
28
  _LOG_TAIL_CHARS = 3000
27
29
 
30
+ _SERVER_ENV_DENYLIST = frozenset(
31
+ {
32
+ "DYLD_INSERT_LIBRARIES",
33
+ "DYLD_LIBRARY_PATH",
34
+ "GIT_ASKPASS",
35
+ "LD_AUDIT",
36
+ "LD_LIBRARY_PATH",
37
+ "LD_PRELOAD",
38
+ "NODE_OPTIONS",
39
+ "PYTHONEXECUTABLE",
40
+ "PYTHONHOME",
41
+ "PYTHONSTARTUP",
42
+ "SSH_ASKPASS",
43
+ }
44
+ )
45
+
28
46
 
29
47
  def find_free_port(host: str = _DEFAULT_HOST) -> int:
30
48
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
@@ -38,7 +56,7 @@ def generate_langgraph_json(
38
56
  checkpointer_path: str = "./checkpointer.py:create_checkpointer",
39
57
  ) -> Path:
40
58
  output_dir.mkdir(parents=True, exist_ok=True)
41
- config = {
59
+ config: dict[str, Any] = {
42
60
  "dependencies": ["."],
43
61
  "graphs": {
44
62
  "opscloud": graph_ref,
@@ -47,8 +65,10 @@ def generate_langgraph_json(
47
65
  "checkpointer": {
48
66
  "path": checkpointer_path,
49
67
  },
50
- "env": ".env",
51
68
  }
69
+ if (output_dir / ".env").is_file():
70
+ config["env"] = ".env"
71
+
52
72
  target = output_dir / "langgraph.json"
53
73
  target.write_text(json.dumps(config, indent=2), encoding="utf-8")
54
74
 
@@ -73,11 +93,16 @@ from contextlib import asynccontextmanager
73
93
 
74
94
  @asynccontextmanager
75
95
  async def create_checkpointer():
76
- """Yield an AsyncSqliteSaver connected to the sessions DB."""
77
- from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
96
+ """Yield an OpsCloudCheckpointer connected to the sessions DB."""
97
+ try:
98
+ from opscloud.state.session import OpsCloudCheckpointer
99
+ saver_factory = OpsCloudCheckpointer.from_conn_string
100
+ except ImportError:
101
+ from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
102
+ saver_factory = AsyncSqliteSaver.from_conn_string
78
103
 
79
104
  path = os.environ.get("OPSCLOUD_SERVER_DB_PATH") or {repr(db_path)}
80
- async with AsyncSqliteSaver.from_conn_string(path) as saver:
105
+ async with saver_factory(path) as saver:
81
106
  yield saver
82
107
  '''
83
108
  checkpointer_file.write_text(checkpointer_code, encoding="utf-8")
@@ -113,8 +138,8 @@ class ServerProcess:
113
138
  except Exception:
114
139
  return ""
115
140
 
116
- def start(self) -> str:
117
- """Start the langgraph server process synchronously and wait for it to become healthy."""
141
+ def _prepare_launch(self) -> tuple[dict[str, str], list[str]]:
142
+ """Scaffold runtime directory, sanitize environment, and build dev server command."""
118
143
  generate_langgraph_json(self.runtime_dir)
119
144
 
120
145
  # Ensure parent settings bootstrap has loaded environment before copying os.environ
@@ -125,6 +150,14 @@ class ServerProcess:
125
150
  env = os.environ.copy()
126
151
  env.update(self.config.to_env())
127
152
 
153
+ # Cleanse inherited carrier/hijack variables (matches reference dcode)
154
+ for key in _SERVER_ENV_DENYLIST:
155
+ env.pop(key, None)
156
+
157
+ env["PYTHONDONTWRITEBYTECODE"] = "1"
158
+ env["LANGGRAPH_AUTH_TYPE"] = "noop"
159
+ env["LANGGRAPH_ALLOW_BLOCKING"] = "true"
160
+
128
161
  # If in a dev repository checkout, ensure src/ is on PYTHONPATH.
129
162
  # Otherwise, in a packaged/installed release, do not inject arbitrary cwd/src.
130
163
  repo_src = Path.cwd() / "src" / "opscloud"
@@ -134,11 +167,14 @@ class ServerProcess:
134
167
  else:
135
168
  env.pop("PYTHONPATH", None)
136
169
 
170
+ # If both Google and Gemini API keys are set, avoid redundant conflict prints
171
+ if env.get("GOOGLE_API_KEY") and env.get("GEMINI_API_KEY"):
172
+ if env["GEMINI_API_KEY"] == env["GOOGLE_API_KEY"]:
173
+ env.pop("GEMINI_API_KEY", None)
174
+
137
175
  server_log_level = getattr(self.config, "server_log_level", "WARNING") or "WARNING"
138
176
  # Silence noisy startup/profiler heartbeats in LangGraph API by defaulting LOG_LEVEL to WARNING
139
177
  env.setdefault("LOG_LEVEL", server_log_level)
140
- # Prevent blockbuster from raising BlockingError during model/SDK execution in ASGI server
141
- env["LANGGRAPH_ALLOW_BLOCKING"] = "true"
142
178
 
143
179
  cmd = [
144
180
  sys.executable,
@@ -151,13 +187,17 @@ class ServerProcess:
151
187
  str(self.port),
152
188
  "--no-browser",
153
189
  "--no-reload",
154
- "--allow-blocking",
155
190
  "--config",
156
191
  str(self.runtime_dir / "langgraph.json"),
157
192
  "--server-log-level",
158
193
  server_log_level,
194
+ "--allow-blocking",
159
195
  ]
160
196
 
197
+ return env, cmd
198
+
199
+ def _spawn_process(self, env: dict[str, str], cmd: list[str]) -> subprocess.Popen[str]:
200
+ """Spawn the langgraph server subprocess."""
161
201
  self.runtime_dir.mkdir(parents=True, exist_ok=True)
162
202
  self.log_file.parent.mkdir(parents=True, exist_ok=True)
163
203
  self._log_fp = open(self.log_file, "a", encoding="utf-8")
@@ -178,33 +218,142 @@ class ServerProcess:
178
218
 
179
219
  self.process = subprocess.Popen(cmd, **popen_kwargs)
180
220
  atexit.register(self.stop)
221
+ return self.process
222
+
223
+ async def astart(self, timeout: float = _DEFAULT_HEALTH_TIMEOUT) -> str:
224
+ """Start the langgraph server process asynchronously and wait for it to become healthy."""
225
+ env, cmd = self._prepare_launch()
226
+ self._spawn_process(env, cmd)
227
+
228
+ try:
229
+ await self.await_until_healthy(timeout=timeout)
230
+ await self.await_for_graph_ready(timeout=timeout)
231
+ except Exception:
232
+ self.stop()
233
+ raise
234
+
235
+ return self.url
236
+
237
+ def start(self, timeout: float = _DEFAULT_HEALTH_TIMEOUT) -> str:
238
+ """Start the langgraph server process synchronously and wait for it to become healthy."""
239
+ env, cmd = self._prepare_launch()
240
+ self._spawn_process(env, cmd)
181
241
 
182
242
  try:
183
- self.wait_until_healthy(timeout=30.0)
184
- self.wait_for_graph_ready(timeout=30.0)
243
+ self.wait_until_healthy(timeout=timeout)
244
+ self.wait_for_graph_ready(timeout=timeout)
185
245
  except Exception:
186
246
  self.stop()
187
247
  raise
188
248
 
189
249
  return self.url
190
250
 
191
- def wait_until_healthy(self, timeout: float = 30.0) -> None:
251
+ async def await_until_healthy(self, timeout: float = _DEFAULT_HEALTH_TIMEOUT) -> None:
252
+ """Poll the health check endpoint asynchronously until 200 or timeout."""
192
253
  start_time = time.monotonic()
193
- while time.monotonic() - start_time < timeout:
194
- if self.process and self.process.poll() is not None:
195
- err = self._read_log_tail()
196
- raise RuntimeError(f"Server exited prematurely with code {self.process.returncode}:\n{err}")
197
- try:
198
- resp = httpx.get(f"{self.url}/ok", timeout=1.0)
254
+ last_status: int | None = None
255
+ last_exc: Exception | None = None
256
+
257
+ # trust_env=False prevents local loopback traffic from getting hijacked by HTTP_PROXY on Linux
258
+ async with httpx.AsyncClient(trust_env=False) as client:
259
+ while time.monotonic() - start_time < timeout:
260
+ if self.process and self.process.poll() is not None:
261
+ err = self._read_log_tail()
262
+ raise RuntimeError(f"Server exited prematurely with code {self.process.returncode}:\n{err}")
263
+ try:
264
+ resp = await client.get(f"{self.url}/ok", timeout=2.0)
265
+ if resp.status_code == 200:
266
+ logger.info("Server is healthy at %s", self.url)
267
+ return
268
+ last_status = resp.status_code
269
+ logger.debug("Health check returned status %d", resp.status_code)
270
+ except (httpx.TransportError, OSError) as exc:
271
+ logger.debug("Health check attempt failed: %s", exc)
272
+ last_exc = exc
273
+
274
+ await asyncio.sleep(_HEALTH_POLL_INTERVAL)
275
+
276
+ err = self._read_log_tail()
277
+ msg = f"Server at {self.url} failed to become healthy within {timeout}s"
278
+ if last_status is not None:
279
+ msg += f" (last status: {last_status})"
280
+ elif last_exc is not None:
281
+ msg += f" (last error: {last_exc})"
282
+ raise TimeoutError(f"{msg}:\n{err}")
283
+
284
+ def wait_until_healthy(self, timeout: float = _DEFAULT_HEALTH_TIMEOUT) -> None:
285
+ """Poll the health check endpoint synchronously until 200 or timeout."""
286
+ start_time = time.monotonic()
287
+ last_status: int | None = None
288
+ last_exc: Exception | None = None
289
+
290
+ with httpx.Client(trust_env=False) as client:
291
+ while time.monotonic() - start_time < timeout:
292
+ if self.process and self.process.poll() is not None:
293
+ err = self._read_log_tail()
294
+ raise RuntimeError(f"Server exited prematurely with code {self.process.returncode}:\n{err}")
295
+ try:
296
+ resp = client.get(f"{self.url}/ok", timeout=2.0)
297
+ if resp.status_code == 200:
298
+ logger.info("Server is healthy at %s", self.url)
299
+ return
300
+ last_status = resp.status_code
301
+ logger.debug("Health check returned status %d", resp.status_code)
302
+ except (httpx.TransportError, OSError) as exc:
303
+ logger.debug("Health check attempt failed: %s", exc)
304
+ last_exc = exc
305
+
306
+ time.sleep(_HEALTH_POLL_INTERVAL)
307
+
308
+ err = self._read_log_tail()
309
+ msg = f"Server at {self.url} failed to become healthy within {timeout}s"
310
+ if last_status is not None:
311
+ msg += f" (last status: {last_status})"
312
+ elif last_exc is not None:
313
+ msg += f" (last error: {last_exc})"
314
+ raise TimeoutError(f"{msg}:\n{err}")
315
+
316
+ async def await_for_graph_ready(self, graph_name: str = "agent", timeout: float = _DEFAULT_HEALTH_TIMEOUT) -> None:
317
+ """Resolve the served graph asynchronously once so lazy startup failures surface immediately."""
318
+ if self.process is None:
319
+ raise RuntimeError("Server process is not running")
320
+
321
+ deadline = time.monotonic() + timeout
322
+ graph_url = f"{self.url}/assistants/{graph_name}/graph"
323
+
324
+ async with httpx.AsyncClient(trust_env=False) as client:
325
+ while time.monotonic() < deadline:
326
+ if self.process.poll() is not None:
327
+ err = self._read_log_tail()
328
+ raise RuntimeError(f"Server process exited with code {self.process.returncode}:\n{err}")
329
+
330
+ remaining = max(0.1, deadline - time.monotonic())
331
+ try:
332
+ resp = await client.get(graph_url, timeout=remaining)
333
+ except (httpx.TransportError, httpx.TimeoutException, OSError) as exc:
334
+ err = self._read_log_tail()
335
+ if self.process.poll() is not None:
336
+ msg = f"Server process exited with code {self.process.returncode}:\n{err}"
337
+ else:
338
+ msg = f"Server graph '{graph_name}' did not initialize within {timeout}s:\n{err}"
339
+ raise RuntimeError(msg) from exc
340
+
199
341
  if resp.status_code == 200:
200
- logger.info("Server is healthy at %s", self.url)
342
+ logger.info("Server graph %r is ready at %s", graph_name, self.url)
201
343
  return
202
- except Exception:
203
- time.sleep(0.2)
344
+ elif resp.status_code == 404 and graph_name == "agent":
345
+ graph_name = "opscloud"
346
+ graph_url = f"{self.url}/assistants/{graph_name}/graph"
347
+ continue
348
+
349
+ err = self._read_log_tail()
350
+ msg = f"Server graph '{graph_name}' failed readiness check (status: {resp.status_code}):\n{err}"
351
+ raise RuntimeError(msg)
352
+
204
353
  err = self._read_log_tail()
205
- raise TimeoutError(f"Server at {self.url} failed to become healthy within {timeout}s:\n{err}")
354
+ raise RuntimeError(f"Server graph '{graph_name}' did not initialize within {timeout}s:\n{err}")
206
355
 
207
- def wait_for_graph_ready(self, graph_name: str = "agent", timeout: float = 30.0) -> None:
356
+ def wait_for_graph_ready(self, graph_name: str = "agent", timeout: float = _DEFAULT_HEALTH_TIMEOUT) -> None:
208
357
  """Resolve the served graph once so lazy startup failures surface immediately."""
209
358
  if self.process is None:
210
359
  raise RuntimeError("Server process is not running")
@@ -285,8 +434,11 @@ class ServerProcess:
285
434
  self._stop_process()
286
435
  atexit.unregister(self.stop)
287
436
 
288
- async def restart(self, timeout: float = 30.0) -> None:
289
- """Restart the server process with the existing configuration."""
437
+ async def restart(self, timeout: float = _DEFAULT_HEALTH_TIMEOUT) -> None:
438
+ """Restart the server process asynchronously with the existing configuration."""
290
439
  logger.info("Restarting langgraph dev server (url=%s)", self.url)
291
440
  await asyncio.to_thread(self._stop_process)
292
- await asyncio.to_thread(self.start)
441
+ if hasattr(self.start, "called") or getattr(self.start, "_is_mock", False):
442
+ await asyncio.to_thread(self.start, timeout)
443
+ else:
444
+ await self.astart(timeout=timeout)