openhands-sdk 1.53.0__tar.gz → 1.55.0__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 (329) hide show
  1. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/PKG-INFO +1 -1
  2. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/__init__.py +13 -1
  3. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/acp_agent.py +91 -84
  4. openhands_sdk-1.55.0/openhands/sdk/agent/acp_contracts.py +424 -0
  5. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/acp_file_credentials.py +5 -2
  6. openhands_sdk-1.55.0/openhands/sdk/agent/acp_model_discovery.py +100 -0
  7. openhands_sdk-1.55.0/openhands/sdk/agent/acp_models.py +170 -0
  8. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/acp_tracing.py +4 -2
  9. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/agent.py +58 -27
  10. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/response_dispatch.py +13 -2
  11. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/base.py +4 -1
  12. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/impl/local_conversation.py +25 -9
  13. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/impl/remote_conversation.py +0 -2
  14. openhands_sdk-1.55.0/openhands/sdk/conversation/message_request.py +19 -0
  15. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/request.py +57 -39
  16. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/__init__.py +2 -0
  17. openhands_sdk-1.55.0/openhands/sdk/event/security.py +48 -0
  18. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/extensions/fetch.py +32 -10
  19. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/extensions/installation/manager.py +57 -4
  20. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/git/cached_repo.py +20 -5
  21. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/git/git_diff.py +8 -2
  22. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/git/utils.py +17 -3
  23. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/hooks/config.py +23 -9
  24. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/launch/finalize.py +25 -2
  25. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/launch/preview.py +11 -3
  26. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/launch/resolve.py +47 -9
  27. openhands_sdk-1.55.0/openhands/sdk/llm/_message_normalization.py +91 -0
  28. openhands_sdk-1.55.0/openhands/sdk/llm/_response_stream.py +99 -0
  29. openhands_sdk-1.55.0/openhands/sdk/llm/_tokenizer.py +102 -0
  30. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/auth/openai.py +14 -13
  31. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/llm.py +49 -99
  32. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/message.py +51 -78
  33. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/mixins/non_native_fc.py +6 -5
  34. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/model_features.py +7 -1
  35. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/openhands_provider.py +17 -6
  36. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/telemetry.py +32 -6
  37. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/unverified_models.py +8 -5
  38. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/verified_models.py +33 -9
  39. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/mcp/client.py +4 -0
  40. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/format/agent_plugins.py +14 -5
  41. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/profiles/agent_profile.py +25 -4
  42. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/profiles/resolver.py +88 -47
  43. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/profiles/seed.py +1 -5
  44. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/__init__.py +2 -1
  45. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/_shell_ast.py +61 -0
  46. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/analyzer.py +68 -16
  47. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/defense_in_depth/pattern.py +18 -9
  48. openhands_sdk-1.55.0/openhands/sdk/security/defense_in_depth/policy_rails.py +928 -0
  49. openhands_sdk-1.55.0/openhands/sdk/security/defense_in_depth/shell_semantics.py +1506 -0
  50. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/settings/__init__.py +5 -1
  51. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/settings/acp_providers.py +58 -12
  52. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/settings/model.py +32 -19
  53. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/skills/skill.py +27 -10
  54. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/skills/utils.py +14 -6
  55. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/subagent/registry.py +29 -19
  56. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/subagent/schema.py +4 -1
  57. openhands_sdk-1.55.0/openhands/sdk/subagent/scope.py +129 -0
  58. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/builtins/invoke_skill.py +1 -1
  59. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/registry.py +5 -2
  60. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/schema.py +6 -8
  61. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/tool.py +3 -0
  62. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/files.py +18 -1
  63. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/redact.py +13 -29
  64. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands_sdk.egg-info/PKG-INFO +1 -1
  65. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands_sdk.egg-info/SOURCES.txt +14 -0
  66. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/pyproject.toml +1 -1
  67. openhands_sdk-1.53.0/openhands/sdk/agent/acp_models.py +0 -71
  68. openhands_sdk-1.53.0/openhands/sdk/security/defense_in_depth/policy_rails.py +0 -185
  69. openhands_sdk-1.53.0/openhands/sdk/security/defense_in_depth/shell_semantics.py +0 -515
  70. openhands_sdk-1.53.0/openhands/sdk/subagent/scope.py +0 -81
  71. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/__init__.py +0 -0
  72. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/base.py +0 -0
  73. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/critic_mixin.py +0 -0
  74. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/parallel_executor.py +0 -0
  75. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/stream_context.py +0 -0
  76. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/agent/utils.py +0 -0
  77. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/automation/__init__.py +0 -0
  78. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/banner.py +0 -0
  79. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/__init__.py +0 -0
  80. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/agent_context.py +0 -0
  81. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/condenser/__init__.py +0 -0
  82. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/condenser/base.py +0 -0
  83. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/condenser/llm_summarizing_condenser.py +0 -0
  84. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/condenser/no_op_condenser.py +0 -0
  85. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/condenser/pipeline_condenser.py +0 -0
  86. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/condenser/prompts/summarizing_events.j2 +0 -0
  87. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/condenser/prompts/summarizing_system.j2 +0 -0
  88. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/condenser/utils.py +0 -0
  89. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/memory.py +0 -0
  90. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/__init__.py +0 -0
  91. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/presets.py +0 -0
  92. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/prompt.py +0 -0
  93. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/registry.py +0 -0
  94. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/section.py +0 -0
  95. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/sections/__init__.py +0 -0
  96. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/sections/dynamic.py +0 -0
  97. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/sections/planning.py +0 -0
  98. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/sections/static.py +0 -0
  99. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/templates/ask_agent_template.j2 +0 -0
  100. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/prompts/templates/skill_knowledge_info.j2 +0 -0
  101. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/view/__init__.py +0 -0
  102. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/view/manipulation_indices.py +0 -0
  103. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/view/properties/__init__.py +0 -0
  104. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/view/properties/base.py +0 -0
  105. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/view/properties/batch_atomicity.py +0 -0
  106. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/view/properties/observation_uniqueness.py +0 -0
  107. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/view/properties/tool_call_matching.py +0 -0
  108. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/view/properties/tool_loop_atomicity.py +0 -0
  109. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/context/view/view.py +0 -0
  110. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/__init__.py +0 -0
  111. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/cancellation.py +0 -0
  112. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/conversation.py +0 -0
  113. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/conversation_stats.py +0 -0
  114. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/event_store.py +0 -0
  115. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/events_list_base.py +0 -0
  116. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/exceptions.py +0 -0
  117. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/fifo_lock.py +0 -0
  118. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/goal/__init__.py +0 -0
  119. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/goal/controller.py +0 -0
  120. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/goal/judge.py +0 -0
  121. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/goal/prompts.py +0 -0
  122. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/goal/runner.py +0 -0
  123. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/impl/__init__.py +0 -0
  124. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/persistence_const.py +0 -0
  125. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/resource_lock_manager.py +0 -0
  126. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/response_utils.py +0 -0
  127. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/secret_registry.py +0 -0
  128. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/state.py +0 -0
  129. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/stuck_detector.py +0 -0
  130. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/title_utils.py +0 -0
  131. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/types.py +0 -0
  132. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/visualizer/__init__.py +0 -0
  133. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/visualizer/base.py +0 -0
  134. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/conversation/visualizer/default.py +0 -0
  135. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/credential.py +0 -0
  136. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/__init__.py +0 -0
  137. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/base.py +0 -0
  138. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/impl/__init__.py +0 -0
  139. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/impl/agent_finished.py +0 -0
  140. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/impl/api/__init__.py +0 -0
  141. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/impl/api/chat_template.py +0 -0
  142. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/impl/api/client.py +0 -0
  143. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/impl/api/critic.py +0 -0
  144. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/impl/api/taxonomy.py +0 -0
  145. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/impl/empty_patch.py +0 -0
  146. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/impl/pass_critic.py +0 -0
  147. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/critic/result.py +0 -0
  148. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/acp_tool_call.py +0 -0
  149. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/base.py +0 -0
  150. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/condenser.py +0 -0
  151. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/conversation_error.py +0 -0
  152. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/conversation_state.py +0 -0
  153. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/error_classification.py +0 -0
  154. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/hook_execution.py +0 -0
  155. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/llm_completion_log.py +0 -0
  156. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/llm_convertible/__init__.py +0 -0
  157. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/llm_convertible/action.py +0 -0
  158. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/llm_convertible/message.py +0 -0
  159. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/llm_convertible/observation.py +0 -0
  160. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/llm_convertible/reasoning_utils.py +0 -0
  161. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/llm_convertible/system.py +0 -0
  162. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/resume_transcript.py +0 -0
  163. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/streaming_delta.py +0 -0
  164. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/token.py +0 -0
  165. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/types.py +0 -0
  166. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/event/user_action.py +0 -0
  167. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/extensions/__init__.py +0 -0
  168. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/extensions/installation/__init__.py +0 -0
  169. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/extensions/installation/info.py +0 -0
  170. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/extensions/installation/interface.py +0 -0
  171. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/extensions/installation/metadata.py +0 -0
  172. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/extensions/installation/utils.py +0 -0
  173. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/git/exceptions.py +0 -0
  174. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/git/git_changes.py +0 -0
  175. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/git/git_commits.py +0 -0
  176. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/git/models.py +0 -0
  177. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/hooks/__init__.py +0 -0
  178. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/hooks/conversation_hooks.py +0 -0
  179. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/hooks/executor.py +0 -0
  180. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/hooks/manager.py +0 -0
  181. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/hooks/types.py +0 -0
  182. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/io/__init__.py +0 -0
  183. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/io/base.py +0 -0
  184. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/io/cache.py +0 -0
  185. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/io/local.py +0 -0
  186. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/io/memory.py +0 -0
  187. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/launch/__init__.py +0 -0
  188. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/launch/errors.py +0 -0
  189. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/__init__.py +0 -0
  190. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/auth/__init__.py +0 -0
  191. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/auth/credentials.py +0 -0
  192. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/call_context.py +0 -0
  193. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/cleanup_profile.py +0 -0
  194. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/exceptions/__init__.py +0 -0
  195. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/exceptions/classifier.py +0 -0
  196. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/exceptions/mapping.py +0 -0
  197. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/exceptions/types.py +0 -0
  198. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/fallback_strategy.py +0 -0
  199. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/llm_profile_store.py +0 -0
  200. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/llm_registry.py +0 -0
  201. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/llm_response.py +0 -0
  202. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/meta_profile_store.py +0 -0
  203. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/mixins/fn_call_converter.py +0 -0
  204. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/mixins/fn_call_examples.py +0 -0
  205. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/options/__init__.py +0 -0
  206. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/options/chat_options.py +0 -0
  207. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/options/common.py +0 -0
  208. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/options/responses_options.py +0 -0
  209. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/provider_connection_store.py +0 -0
  210. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/router/__init__.py +0 -0
  211. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/router/base.py +0 -0
  212. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/router/impl/multimodal.py +0 -0
  213. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/router/impl/random.py +0 -0
  214. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/streaming.py +0 -0
  215. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/image_inline.py +0 -0
  216. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/image_resize.py +0 -0
  217. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/litellm_provider.py +0 -0
  218. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/metrics.py +0 -0
  219. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/model_info.py +0 -0
  220. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/model_prompt_spec.py +0 -0
  221. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/providers/__init__.py +0 -0
  222. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/providers/openrouter.py +0 -0
  223. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/responses_serialization.py +0 -0
  224. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/retry_mixin.py +0 -0
  225. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/runtime_metadata.py +0 -0
  226. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/llm/utils/vertex_preflight.py +0 -0
  227. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/logger/__init__.py +0 -0
  228. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/logger/logger.py +0 -0
  229. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/logger/rolling.py +0 -0
  230. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/marketplace/__init__.py +0 -0
  231. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/marketplace/registration.py +0 -0
  232. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/marketplace/registry.py +0 -0
  233. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/marketplace/types.py +0 -0
  234. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/mcp/__init__.py +0 -0
  235. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/mcp/config.py +0 -0
  236. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/mcp/definition.py +0 -0
  237. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/mcp/exceptions.py +0 -0
  238. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/mcp/oauth.py +0 -0
  239. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/mcp/tool.py +0 -0
  240. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/mcp/utils.py +0 -0
  241. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/observability/__init__.py +0 -0
  242. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/observability/laminar.py +0 -0
  243. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/observability/utils.py +0 -0
  244. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/__init__.py +0 -0
  245. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/discovery.py +0 -0
  246. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/fetch.py +0 -0
  247. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/format/__init__.py +0 -0
  248. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/format/agent_plugins_mcp.py +0 -0
  249. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/format/base.py +0 -0
  250. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/format/claude_code.py +0 -0
  251. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/format/schemas/mcp-1.0.0.schema.json +0 -0
  252. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/format/schemas/plugin-1.0.0.schema.json +0 -0
  253. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/installed.py +0 -0
  254. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/loader.py +0 -0
  255. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/plugin.py +0 -0
  256. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/source.py +0 -0
  257. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/plugin/types.py +0 -0
  258. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/profiles/__init__.py +0 -0
  259. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/profiles/agent_profile_store.py +0 -0
  260. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/profiles/profile_refs.py +0 -0
  261. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/py.typed +0 -0
  262. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/secret/__init__.py +0 -0
  263. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/secret/secrets.py +0 -0
  264. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/confirmation_policy.py +0 -0
  265. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/defense_in_depth/__init__.py +0 -0
  266. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/defense_in_depth/utils.py +0 -0
  267. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/ensemble.py +0 -0
  268. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/grayswan/__init__.py +0 -0
  269. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/grayswan/analyzer.py +0 -0
  270. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/grayswan/utils.py +0 -0
  271. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/llm_analyzer.py +0 -0
  272. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/risk.py +0 -0
  273. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/shell_parser.py +0 -0
  274. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/toolshield_helpers.py +0 -0
  275. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/security/toolshield_llm_analyzer.py +0 -0
  276. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/settings/acp_install_catalog.py +0 -0
  277. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/settings/api_models.py +0 -0
  278. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/settings/metadata.py +0 -0
  279. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/skills/__init__.py +0 -0
  280. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/skills/exceptions.py +0 -0
  281. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/skills/execute.py +0 -0
  282. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/skills/fetch.py +0 -0
  283. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/skills/installed.py +0 -0
  284. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/skills/trigger.py +0 -0
  285. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/skills/types.py +0 -0
  286. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/subagent/__init__.py +0 -0
  287. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/subagent/load.py +0 -0
  288. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/testing/__init__.py +0 -0
  289. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/testing/test_llm.py +0 -0
  290. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/__init__.py +0 -0
  291. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/builtins/__init__.py +0 -0
  292. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/builtins/classify_and_switch_llm.py +0 -0
  293. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/builtins/finish.py +0 -0
  294. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/builtins/switch_llm.py +0 -0
  295. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/builtins/think.py +0 -0
  296. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/builtins/vision_inspect.py +0 -0
  297. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/client_tool.py +0 -0
  298. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/defaults.py +0 -0
  299. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/tool/spec.py +0 -0
  300. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/__init__.py +0 -0
  301. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/async_executor.py +0 -0
  302. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/async_utils.py +0 -0
  303. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/cipher.py +0 -0
  304. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/command.py +0 -0
  305. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/datetime.py +0 -0
  306. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/deprecation.py +0 -0
  307. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/github.py +0 -0
  308. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/json.py +0 -0
  309. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/masking.py +0 -0
  310. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/models.py +0 -0
  311. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/paging.py +0 -0
  312. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/path.py +0 -0
  313. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/pydantic_secrets.py +0 -0
  314. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/truncate.py +0 -0
  315. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/utils/visualize.py +0 -0
  316. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/workspace/__init__.py +0 -0
  317. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/workspace/base.py +0 -0
  318. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/workspace/local.py +0 -0
  319. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/workspace/models.py +0 -0
  320. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/workspace/remote/__init__.py +0 -0
  321. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/workspace/remote/async_remote_workspace.py +0 -0
  322. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/workspace/remote/base.py +0 -0
  323. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/workspace/remote/remote_workspace_mixin.py +0 -0
  324. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/workspace/repo.py +0 -0
  325. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands/sdk/workspace/workspace.py +0 -0
  326. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands_sdk.egg-info/dependency_links.txt +0 -0
  327. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands_sdk.egg-info/requires.txt +0 -0
  328. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/openhands_sdk.egg-info/top_level.txt +0 -0
  329. {openhands_sdk-1.53.0 → openhands_sdk-1.55.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openhands-sdk
3
- Version: 1.53.0
3
+ Version: 1.55.0
4
4
  Summary: OpenHands SDK - Core functionality for building AI agents
5
5
  Project-URL: Source, https://github.com/OpenHands/software-agent-sdk
6
6
  Project-URL: Homepage, https://github.com/OpenHands/software-agent-sdk
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from importlib.metadata import PackageNotFoundError, version
4
+ from typing import TYPE_CHECKING, Any
4
5
 
5
6
  from openhands.sdk.agent import (
6
7
  Agent,
@@ -51,7 +52,6 @@ from openhands.sdk.settings import (
51
52
  ACP_PROVIDERS,
52
53
  ACPAgentSettings,
53
54
  ACPFileSecretSpec,
54
- ACPModelOption,
55
55
  ACPProviderInfo,
56
56
  AgentSettingsBase,
57
57
  AgentSettingsConfig,
@@ -109,6 +109,10 @@ from openhands.sdk.workspace import (
109
109
  )
110
110
 
111
111
 
112
+ if TYPE_CHECKING:
113
+ from openhands.sdk.settings.acp_providers import ACPModelOption
114
+
115
+
112
116
  try:
113
117
  __version__ = version("openhands-sdk")
114
118
  except PackageNotFoundError:
@@ -207,3 +211,11 @@ __all__ = [
207
211
  "page_iterator",
208
212
  "__version__",
209
213
  ]
214
+
215
+
216
+ def __getattr__(name: str) -> Any:
217
+ if name == "ACPModelOption":
218
+ from openhands.sdk.settings.acp_providers import _deprecated_model_option
219
+
220
+ return _deprecated_model_option()
221
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
@@ -32,7 +32,6 @@ from collections.abc import (
32
32
  Callable,
33
33
  Collection,
34
34
  Generator,
35
- Iterable,
36
35
  Sequence,
37
36
  )
38
37
  from concurrent.futures import Future
@@ -42,6 +41,7 @@ from typing import TYPE_CHECKING, Any, Final, Literal, NamedTuple
42
41
  from acp.client.connection import ClientSideConnection
43
42
  from acp.exceptions import RequestError as ACPRequestError
44
43
  from acp.helpers import image_block, text_block
44
+ from acp.meta import AGENT_METHODS
45
45
  from acp.schema import (
46
46
  AcpMcpServer,
47
47
  AgentMessageChunk,
@@ -57,6 +57,8 @@ from acp.schema import (
57
57
  ImageContentBlock,
58
58
  KillTerminalResponse,
59
59
  McpServerStdio,
60
+ NewSessionRequest,
61
+ NewSessionResponse,
60
62
  PermissionOption,
61
63
  PromptResponse,
62
64
  ReadTextFileResponse,
@@ -73,15 +75,26 @@ from acp.schema import (
73
75
  WriteTextFileResponse,
74
76
  )
75
77
  from acp.transports import default_environment
78
+ from acp.utils import request_model
76
79
  from pydantic import (
77
80
  Field,
78
81
  PrivateAttr,
79
82
  SecretStr,
83
+ ValidationError,
80
84
  ValidationInfo,
81
85
  field_serializer,
82
86
  field_validator,
83
87
  )
84
88
 
89
+ from openhands.sdk.agent.acp_contracts import (
90
+ ACPLegacySessionModels,
91
+ extract_session_models,
92
+ is_model_dumpable,
93
+ normalize_acp_error,
94
+ normalize_auth_method,
95
+ normalize_mcp_capabilities,
96
+ supports_legacy_model_switch,
97
+ )
85
98
  from openhands.sdk.agent.acp_file_credentials import (
86
99
  ACPFileCredentialLifecycle,
87
100
  ACPFileCredentialNeedsReauthError,
@@ -409,7 +422,9 @@ def _auth_selection_failure_reason(
409
422
  # which the runtime does not have. Named so the log says why the method was
410
423
  # never a candidate rather than implying a missing credential.
411
424
  terminal_ids = sorted(
412
- m.id for m in auth_methods if getattr(m, "type", None) == "terminal"
425
+ m.id
426
+ for m in (normalize_auth_method(raw) for raw in auth_methods)
427
+ if m.type == "terminal"
413
428
  )
414
429
  if terminal_ids:
415
430
  reasons.append(
@@ -589,31 +604,6 @@ def _model_config_options(
589
604
  return ((_MODEL_CONFIG_OPTION_ID, model),)
590
605
 
591
606
 
592
- def _model_config_option(response: Any) -> Any | None:
593
- """Return the ``model`` ``configOptions`` select off a session response.
594
-
595
- Newer ACP CLIs dropped the UNSTABLE ``models`` capability and expose model
596
- selection as a ``configOptions`` entry with ``id == "model"`` (``type ==
597
- "select"``), switched via ``session/set_config_option`` instead of
598
- ``session/set_model``. Returns that option (carrying ``options`` and
599
- ``current_value``) or ``None`` when the server uses neither / the old
600
- mechanism. ``getattr`` keeps it tolerant of partial structures.
601
-
602
- The ``agent-client-protocol`` Python lib wraps each entry in a
603
- ``SessionConfigOption`` ``RootModel`` on 0.8.x (access via ``.root``) but
604
- lists the union members directly on 0.10.x; unwrap ``.root`` so detection
605
- works on either.
606
- """
607
- for raw in getattr(response, "config_options", None) or []:
608
- opt = getattr(raw, "root", raw)
609
- if (
610
- getattr(opt, "type", None) == "select"
611
- and getattr(opt, "id", None) == _MODEL_CONFIG_OPTION_ID
612
- ):
613
- return opt
614
- return None
615
-
616
-
617
607
  async def _apply_acp_model(
618
608
  conn: ClientSideConnection,
619
609
  session_id: str,
@@ -631,28 +621,17 @@ async def _apply_acp_model(
631
621
  codex-acp exposes reasoning effort as a separate config option, so split it
632
622
  only on the config-options mechanism.
633
623
 
634
- agent-client-protocol 0.12.1 dropped the UNSTABLE ``models`` extension from
635
- the ACP schema and removed ``ClientSideConnection.set_session_model``. A live
636
- 0.12 connection therefore has no legacy RPC to call, so the ``else`` branch
637
- only invokes it when the connection actually exposes the method (test
638
- doubles do; real 0.12 connections do not) and otherwise no-ops rather than
639
- raising ``AttributeError``.
624
+ agent-client-protocol 0.12.1 removed ``ClientSideConnection.set_session_model``;
625
+ :class:`_ACPClientConnection` restores it, and a connection without it
626
+ no-ops rather than raising ``AttributeError``.
640
627
  """
641
628
  if via_config_option:
642
629
  for config_id, value in _model_config_options(agent_name, model):
643
630
  await conn.set_config_option(
644
631
  config_id=config_id, value=value, session_id=session_id
645
632
  )
646
- elif hasattr(conn, "set_session_model"):
647
- await conn.set_session_model( # type: ignore[attr-defined]
648
- model_id=model, session_id=session_id
649
- )
650
-
651
-
652
- def _usable_models(infos: Iterable[ACPModelInfo]) -> list[ACPModelInfo]:
653
- """Drop entries without a usable ``model_id`` — an empty/missing id is an
654
- invalid picker option and an unusable model-switch target."""
655
- return [info for info in infos if info.model_id]
633
+ elif supports_legacy_model_switch(conn):
634
+ await conn.set_session_model(model_id=model, session_id=session_id) # type: ignore[attr-defined]
656
635
 
657
636
 
658
637
  def _extract_session_models(
@@ -682,32 +661,11 @@ def _extract_session_models(
682
661
  configOptions select, ``False`` for the ``models`` capability, and
683
662
  ``default_via_config_option`` when the response carries neither (the
684
663
  resume-path default for a ``load_session`` that omits the model block).
685
-
686
- ``getattr`` keeps the helper tolerant of agents that emit a partial
687
- structure.
688
664
  """
689
- if response is None:
690
- return None, None, default_via_config_option
691
- # Prefer configOptions when an adapter advertises both it and the legacy
692
- # ``models`` extension. The ``model`` select carries the same state, with
693
- # each option's ``value`` as the model id (== the ``set_config_option`` target).
694
- opt = _model_config_option(response)
695
- if opt is not None:
696
- current = getattr(opt, "current_value", None)
697
- current = current if isinstance(current, str) and current else None
698
- options = getattr(opt, "options", None) or []
699
- usable = _usable_models(
700
- ACPModelInfo.from_protocol(o, id_attr="value") for o in options
701
- )
702
- return current, usable, True
703
- models = getattr(response, "models", None)
704
- if models is not None:
705
- current = getattr(models, "current_model_id", None)
706
- current = current if isinstance(current, str) and current else None
707
- raw = getattr(models, "available_models", None) or []
708
- usable = _usable_models(ACPModelInfo.from_protocol(m) for m in raw)
709
- return current, usable, False
710
- return None, None, default_via_config_option
665
+ state = extract_session_models(
666
+ response, default_via_config_option=default_via_config_option
667
+ )
668
+ return state.current_model_id, state.available_models, state.via_config_option
711
669
 
712
670
 
713
671
  # The ACP MCP server union accepted by new_session() / load_session().
@@ -768,8 +726,9 @@ def _mcp_config_to_acp_servers(
768
726
  to the protocol's ``[{name, value}]`` list form; header-compatible auth
769
727
  credentials are also converted to headers.
770
728
  """
771
- http_ok = bool(getattr(mcp_capabilities, "http", False))
772
- sse_ok = bool(getattr(mcp_capabilities, "sse", False))
729
+ caps = normalize_mcp_capabilities(mcp_capabilities)
730
+ http_ok = caps.http
731
+ sse_ok = caps.sse
773
732
  result: list[_ACPMcpServer] = []
774
733
  for name, server in mcp_config.items():
775
734
  if not server.enabled:
@@ -1026,7 +985,7 @@ def _serialize_tool_content(content: list[Any] | None) -> list[dict[str, Any]] |
1026
985
  for content_block in content:
1027
986
  block_dict = (
1028
987
  content_block.model_dump(mode="json")
1029
- if hasattr(content_block, "model_dump")
988
+ if is_model_dumpable(content_block)
1030
989
  else content_block
1031
990
  )
1032
991
  if (
@@ -1044,6 +1003,47 @@ def _serialize_tool_content(content: list[Any] | None) -> list[dict[str, Any]] |
1044
1003
  return result
1045
1004
 
1046
1005
 
1006
+ class _NewSessionResponse(NewSessionResponse):
1007
+ models: ACPLegacySessionModels | None = None
1008
+
1009
+ @field_validator("models", mode="before")
1010
+ @classmethod
1011
+ def _drop_malformed_models(cls, value: Any) -> Any:
1012
+ try:
1013
+ return ACPLegacySessionModels.model_validate(value)
1014
+ except ValidationError:
1015
+ return None
1016
+
1017
+
1018
+ # ``@final`` is typing-only; nothing but these two calls is overridden.
1019
+ class _ACPClientConnection(ClientSideConnection): # pyright: ignore[reportGeneralTypeIssues]
1020
+ """Restore the UNSTABLE model calls ACP 0.12 dropped; gemini-cli needs them."""
1021
+
1022
+ async def new_session( # type: ignore[override]
1023
+ self,
1024
+ cwd: str,
1025
+ additional_directories: list[str] | None = None,
1026
+ mcp_servers: list[Any] | None = None,
1027
+ **kwargs: Any,
1028
+ ) -> NewSessionResponse:
1029
+ return await request_model(
1030
+ self._conn,
1031
+ AGENT_METHODS["session_new"],
1032
+ NewSessionRequest(
1033
+ cwd=cwd,
1034
+ additional_directories=additional_directories,
1035
+ mcp_servers=mcp_servers or [],
1036
+ field_meta=kwargs or None,
1037
+ ),
1038
+ _NewSessionResponse,
1039
+ )
1040
+
1041
+ async def set_session_model(self, *, model_id: str, session_id: str) -> None:
1042
+ await self._conn.send_request(
1043
+ "session/set_model", {"sessionId": session_id, "modelId": model_id}
1044
+ )
1045
+
1046
+
1047
1047
  async def _filter_jsonrpc_lines(source: Any, dest: Any) -> None:
1048
1048
  """Read lines from *source* and forward only JSON-RPC lines to *dest*.
1049
1049
 
@@ -1136,10 +1136,11 @@ def _stringify_acp_error_data(data: Any) -> str:
1136
1136
 
1137
1137
  def _acp_error_text(exc: BaseException) -> str:
1138
1138
  """Lowercased message + data text used for substring classification."""
1139
+ info = normalize_acp_error(exc)
1139
1140
  if isinstance(exc, ACPRequestError):
1140
- data_str = _stringify_acp_error_data(getattr(exc, "data", None))
1141
- return f"{exc} {data_str}".lower()
1142
- return str(exc).lower()
1141
+ data_str = _stringify_acp_error_data(info.data)
1142
+ return f"{info.message} {data_str}".lower()
1143
+ return info.message.lower()
1143
1144
 
1144
1145
 
1145
1146
  def _acp_error_indicates_auth(exc: BaseException) -> bool:
@@ -1149,8 +1150,10 @@ def _acp_error_indicates_auth(exc: BaseException) -> bool:
1149
1150
  auth marker is an upstream 401/403 the server collapsed into a generic internal
1150
1151
  error. Either way the client should offer re-authentication.
1151
1152
  """
1152
- if isinstance(exc, ACPRequestError) and getattr(exc, "code", None) == -32000:
1153
- return True
1153
+ if isinstance(exc, ACPRequestError):
1154
+ info = normalize_acp_error(exc)
1155
+ if info.code == -32000:
1156
+ return True
1154
1157
  text = _acp_error_text(exc)
1155
1158
  return any(marker in text for marker in _ACP_AUTH_ERROR_MARKERS) or bool(
1156
1159
  _ACP_AUTH_HTTP_CODES_RE.search(text)
@@ -1171,9 +1174,10 @@ def _acp_error_detail(
1171
1174
  secret values) before it leaves, and capped to the 500-char event limit.
1172
1175
  """
1173
1176
  if isinstance(exc, ACPRequestError):
1174
- code = getattr(exc, "code", None)
1175
- message = str(exc)
1176
- data_str = _stringify_acp_error_data(getattr(exc, "data", None))
1177
+ info = normalize_acp_error(exc)
1178
+ code = info.code
1179
+ message = info.message
1180
+ data_str = _stringify_acp_error_data(info.data)
1177
1181
  detail = f"[{code}] {message}" if code is not None else message
1178
1182
  if data_str and data_str != message:
1179
1183
  detail = f"{detail}: {data_str}"
@@ -3067,7 +3071,7 @@ class ACPAgent(AgentBase):
3067
3071
  _log_acp_subprocess_stderr(process.stderr)
3068
3072
  )
3069
3073
 
3070
- conn = ClientSideConnection(
3074
+ conn = _ACPClientConnection(
3071
3075
  client,
3072
3076
  process.stdin, # write to subprocess
3073
3077
  filtered_reader, # read filtered output
@@ -4597,8 +4601,10 @@ class ACPAgent(AgentBase):
4597
4601
  logger.debug("Error killing ACP process: %s", kill_error)
4598
4602
  self._process = None
4599
4603
 
4600
- for task_attr in ("_stdout_filter_task", "_stderr_log_task"):
4601
- task = getattr(self, task_attr)
4604
+ for task_name, task in (
4605
+ ("stdout filter task", self._stdout_filter_task),
4606
+ ("stderr log task", self._stderr_log_task),
4607
+ ):
4602
4608
  if task is not None:
4603
4609
  task.cancel()
4604
4610
  if self._executor is not None:
@@ -4607,8 +4613,9 @@ class ACPAgent(AgentBase):
4607
4613
  self._await_cancelled_task, task, timeout=5.0
4608
4614
  )
4609
4615
  except Exception as e:
4610
- logger.debug("Error stopping %s: %s", task_attr, e)
4611
- setattr(self, task_attr, None)
4616
+ logger.debug("Error stopping %s: %s", task_name, e)
4617
+ self._stdout_filter_task = None
4618
+ self._stderr_log_task = None
4612
4619
 
4613
4620
  credential_failures = self._release_file_credentials_collect()
4614
4621
  failures.update(credential_failures)