openhands-sdk 1.58.1__tar.gz → 1.59.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.
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/PKG-INFO +1 -1
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/__init__.py +0 -14
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/acp_agent.py +101 -7
- openhands_sdk-1.59.0/openhands/sdk/agent/acp_skills.py +67 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/agent.py +38 -2
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/conversation.py +5 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/event_store.py +131 -52
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/impl/local_conversation.py +32 -9
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/impl/remote_conversation.py +32 -9
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/request.py +17 -4
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/secret_registry.py +10 -10
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/state.py +36 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/__init__.py +2 -1
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/acp_tool_call.py +2 -2
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/base.py +3 -2
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/hook_execution.py +3 -3
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/llm_completion_log.py +2 -2
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/types.py +13 -3
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/extensions/fetch.py +18 -11
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/extensions/installation/manager.py +3 -3
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/launch/finalize.py +4 -2
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/launch/preview.py +1 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/launch/resolve.py +1 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/exceptions/classifier.py +31 -5
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/llm.py +9 -1
- openhands_sdk-1.59.0/openhands/sdk/llm/utils/retry_after.py +67 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/retry_mixin.py +23 -6
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/profiles/agent_profile.py +23 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/profiles/resolver.py +3 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/settings/__init__.py +0 -6
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/settings/acp_install_catalog.py +1 -1
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/settings/acp_providers.py +0 -209
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/skills/skill.py +4 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/skills/utils.py +11 -0
- openhands_sdk-1.59.0/openhands/sdk/utils/masking.py +70 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands_sdk.egg-info/PKG-INFO +1 -1
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands_sdk.egg-info/SOURCES.txt +4 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/pyproject.toml +1 -1
- openhands_sdk-1.58.1/openhands/sdk/utils/masking.py +0 -13
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/acp_contracts.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/acp_file_credentials.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/acp_model_discovery.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/acp_models.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/acp_tracing.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/critic_mixin.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/parallel_executor.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/response_dispatch.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/stream_context.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/agent/utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/automation/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/banner.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/agent_context.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/condenser/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/condenser/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/condenser/llm_summarizing_condenser.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/condenser/no_op_condenser.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/condenser/pipeline_condenser.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/condenser/prompts/summarizing_events.j2 +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/condenser/prompts/summarizing_system.j2 +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/condenser/utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/memory.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/presets.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/prompt.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/registry.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/section.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/sections/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/sections/dynamic.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/sections/planning.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/sections/static.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/templates/ask_agent_template.j2 +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/prompts/templates/skill_knowledge_info.j2 +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/view/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/view/manipulation_indices.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/view/properties/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/view/properties/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/view/properties/batch_atomicity.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/view/properties/observation_uniqueness.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/view/properties/tool_call_matching.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/view/properties/tool_loop_atomicity.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/context/view/view.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/cancellation.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/conversation_stats.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/events_list_base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/exceptions.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/fifo_lock.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/goal/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/goal/controller.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/goal/judge.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/goal/prompts.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/goal/runner.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/impl/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/message_request.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/persistence_const.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/resource_lock_manager.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/response_utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/stuck_detector.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/title_utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/types.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/visualizer/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/visualizer/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/conversation/visualizer/default.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/credential.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/impl/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/impl/agent_finished.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/impl/api/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/impl/api/chat_template.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/impl/api/client.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/impl/api/critic.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/impl/api/taxonomy.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/impl/empty_patch.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/impl/pass_critic.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/critic/result.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/condenser.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/conversation_error.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/conversation_state.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/error_classification.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/llm_convertible/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/llm_convertible/action.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/llm_convertible/message.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/llm_convertible/observation.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/llm_convertible/reasoning_utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/llm_convertible/system.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/resume_transcript.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/security.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/streaming_delta.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/token.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/event/user_action.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/extensions/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/extensions/installation/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/extensions/installation/info.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/extensions/installation/interface.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/extensions/installation/metadata.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/extensions/installation/utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/git/cached_repo.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/git/exceptions.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/git/git_changes.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/git/git_commits.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/git/git_diff.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/git/models.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/git/utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/hooks/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/hooks/config.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/hooks/conversation_hooks.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/hooks/executor.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/hooks/manager.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/hooks/types.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/io/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/io/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/io/cache.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/io/local.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/io/memory.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/launch/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/launch/errors.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/_message_normalization.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/_response_stream.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/_tokenizer.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/auth/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/auth/credentials.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/auth/openai.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/call_context.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/cleanup_profile.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/exceptions/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/exceptions/mapping.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/exceptions/types.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/fallback_strategy.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/llm_profile_store.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/llm_registry.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/llm_response.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/message.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/meta_profile_store.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/mixins/fn_call_converter.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/mixins/fn_call_examples.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/mixins/non_native_fc.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/options/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/options/chat_options.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/options/common.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/options/responses_options.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/provider_connection_store.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/router/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/router/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/router/impl/multimodal.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/router/impl/random.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/streaming.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/image_inline.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/image_resize.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/litellm_provider.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/metrics.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/model_features.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/model_info.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/model_prompt_spec.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/openhands_provider.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/providers/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/providers/openrouter.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/responses_serialization.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/runtime_metadata.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/telemetry.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/unverified_models.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/verified_models.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/llm/utils/vertex_preflight.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/logger/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/logger/_rich_handler.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/logger/logger.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/logger/rolling.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/marketplace/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/marketplace/registration.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/marketplace/registry.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/marketplace/types.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/mcp/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/mcp/client.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/mcp/config.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/mcp/definition.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/mcp/exceptions.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/mcp/oauth.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/mcp/tool.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/mcp/utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/observability/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/observability/laminar.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/observability/utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/discovery.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/fetch.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/format/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/format/agent_plugins.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/format/agent_plugins_mcp.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/format/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/format/claude_code.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/format/schemas/mcp-1.0.0.schema.json +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/format/schemas/plugin-1.0.0.schema.json +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/installed.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/loader.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/paths.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/plugin.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/source.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/strict_fetch.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/plugin/types.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/profiles/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/profiles/agent_profile_store.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/profiles/profile_refs.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/profiles/seed.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/py.typed +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/secret/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/secret/secrets.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/_shell_ast.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/analyzer.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/confirmation_policy.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/defense_in_depth/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/defense_in_depth/pattern.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/defense_in_depth/policy_rails.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/defense_in_depth/shell_semantics.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/defense_in_depth/utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/ensemble.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/grayswan/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/grayswan/analyzer.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/grayswan/utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/llm_analyzer.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/risk.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/shell_parser.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/toolshield_helpers.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/security/toolshield_llm_analyzer.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/settings/api_models.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/settings/metadata.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/settings/model.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/skills/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/skills/exceptions.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/skills/execute.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/skills/fetch.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/skills/installed.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/skills/trigger.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/skills/types.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/subagent/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/subagent/load.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/subagent/registry.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/subagent/schema.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/subagent/scope.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/testing/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/testing/test_llm.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/builtins/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/builtins/classify_and_switch_llm.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/builtins/finish.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/builtins/invoke_skill.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/builtins/switch_llm.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/builtins/think.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/builtins/vision_inspect.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/client_tool.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/defaults.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/registry.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/schema.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/spec.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/tool/tool.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/async_executor.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/async_utils.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/cipher.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/command.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/datetime.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/deprecation.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/files.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/github.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/json.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/models.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/paging.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/path.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/pydantic_secrets.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/redact.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/truncate.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/utils/visualize.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/workspace/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/workspace/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/workspace/local.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/workspace/models.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/workspace/remote/__init__.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/workspace/remote/async_remote_workspace.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/workspace/remote/base.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/workspace/remote/remote_workspace_mixin.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/workspace/repo.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands/sdk/workspace/workspace.py +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands_sdk.egg-info/dependency_links.txt +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands_sdk.egg-info/requires.txt +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/openhands_sdk.egg-info/top_level.txt +0 -0
- {openhands_sdk-1.58.1 → openhands_sdk-1.59.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openhands-sdk
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.59.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,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from importlib.metadata import PackageNotFoundError, version
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
4
|
|
|
6
5
|
from openhands.sdk.agent import (
|
|
7
6
|
Agent,
|
|
@@ -109,10 +108,6 @@ from openhands.sdk.workspace import (
|
|
|
109
108
|
)
|
|
110
109
|
|
|
111
110
|
|
|
112
|
-
if TYPE_CHECKING:
|
|
113
|
-
from openhands.sdk.settings.acp_providers import ACPModelOption
|
|
114
|
-
|
|
115
|
-
|
|
116
111
|
try:
|
|
117
112
|
__version__ = version("openhands-sdk")
|
|
118
113
|
except PackageNotFoundError:
|
|
@@ -167,7 +162,6 @@ __all__ = [
|
|
|
167
162
|
"ACP_PROVIDERS",
|
|
168
163
|
"ACPAgentSettings",
|
|
169
164
|
"ACPFileSecretSpec",
|
|
170
|
-
"ACPModelOption",
|
|
171
165
|
"ACPProviderInfo",
|
|
172
166
|
"AgentSettingsBase",
|
|
173
167
|
"AgentSettingsConfig",
|
|
@@ -211,11 +205,3 @@ __all__ = [
|
|
|
211
205
|
"page_iterator",
|
|
212
206
|
"__version__",
|
|
213
207
|
]
|
|
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}")
|
|
@@ -23,6 +23,7 @@ import inspect
|
|
|
23
23
|
import json
|
|
24
24
|
import os
|
|
25
25
|
import re
|
|
26
|
+
import shutil
|
|
26
27
|
import threading
|
|
27
28
|
import time
|
|
28
29
|
import uuid
|
|
@@ -106,6 +107,7 @@ from openhands.sdk.agent.acp_file_credentials import (
|
|
|
106
107
|
write_secret_file,
|
|
107
108
|
)
|
|
108
109
|
from openhands.sdk.agent.acp_models import ACPModelInfo
|
|
110
|
+
from openhands.sdk.agent.acp_skills import render_skill_catalog, write_skill_files
|
|
109
111
|
from openhands.sdk.agent.acp_tracing import ACPTurnTrace
|
|
110
112
|
from openhands.sdk.agent.base import AgentBase
|
|
111
113
|
from openhands.sdk.agent.stream_context import StreamContext
|
|
@@ -126,7 +128,7 @@ from openhands.sdk.event import (
|
|
|
126
128
|
from openhands.sdk.event.conversation_error import ConversationErrorEvent
|
|
127
129
|
from openhands.sdk.llm import LLM, ImageContent, Message, MessageToolCall, TextContent
|
|
128
130
|
from openhands.sdk.logger import get_logger
|
|
129
|
-
from openhands.sdk.mcp.config import MCPServer
|
|
131
|
+
from openhands.sdk.mcp.config import MCPOAuthAuthCredential, MCPServer
|
|
130
132
|
from openhands.sdk.observability.laminar import maybe_init_laminar, observe
|
|
131
133
|
from openhands.sdk.settings.acp_providers import (
|
|
132
134
|
ACP_PROVIDERS,
|
|
@@ -672,20 +674,65 @@ def _extract_session_models(
|
|
|
672
674
|
_ACPMcpServer = HttpMcpServer | SseMcpServer | McpServerStdio | AcpMcpServer
|
|
673
675
|
|
|
674
676
|
|
|
677
|
+
def _oauth_bearer_header(auth: MCPOAuthAuthCredential, name: str) -> dict[str, str]:
|
|
678
|
+
"""Forward a stored OAuth2 access token as an ``Authorization`` header.
|
|
679
|
+
|
|
680
|
+
The ACP subprocess owns its own MCP transport and has no access to the
|
|
681
|
+
FastMCP token store the native path uses, so the token persisted in the
|
|
682
|
+
connection's ``auth.state`` is the only credential available here. Without
|
|
683
|
+
this the server is forwarded as a bare URL and the ACP agent reports it is
|
|
684
|
+
not logged in (``codex mcp login ...``).
|
|
685
|
+
|
|
686
|
+
A missing or expired token still forwards what exists: a 401 from the
|
|
687
|
+
server is more actionable than an unauthenticated URL. Both cases are
|
|
688
|
+
logged so the drop is not silent.
|
|
689
|
+
"""
|
|
690
|
+
state = auth.state
|
|
691
|
+
token = state.tokens.access_token if state is not None and state.tokens else None
|
|
692
|
+
if token is None:
|
|
693
|
+
logger.warning(
|
|
694
|
+
"ACP MCP server %r has an OAuth2 connection with no stored access "
|
|
695
|
+
"token; forwarding it unauthenticated",
|
|
696
|
+
name,
|
|
697
|
+
)
|
|
698
|
+
return {}
|
|
699
|
+
if (
|
|
700
|
+
state is not None
|
|
701
|
+
and state.token_expires_at is not None
|
|
702
|
+
and state.token_expires_at <= time.time()
|
|
703
|
+
):
|
|
704
|
+
logger.warning(
|
|
705
|
+
"ACP MCP server %r has an expired OAuth2 access token; the ACP path "
|
|
706
|
+
"cannot refresh it, forwarding it as-is",
|
|
707
|
+
name,
|
|
708
|
+
)
|
|
709
|
+
return {"Authorization": f"Bearer {token.get_secret_value()}"}
|
|
710
|
+
|
|
711
|
+
|
|
675
712
|
def _remote_mcp_headers(server: MCPServer, name: str) -> list[HttpHeader]:
|
|
676
|
-
"""Convert remote MCP headers/auth into ACP's header-only representation.
|
|
713
|
+
"""Convert remote MCP headers/auth into ACP's header-only representation.
|
|
714
|
+
|
|
715
|
+
Header-compatible auth (api key / bearer / basic / explicit headers)
|
|
716
|
+
converts directly. OAuth2 does not -- ``to_http_headers()`` returns ``None``
|
|
717
|
+
because the native path materializes tokens through FastMCP's token store --
|
|
718
|
+
so its stored access token is forwarded explicitly instead.
|
|
719
|
+
"""
|
|
677
720
|
headers = [
|
|
678
721
|
HttpHeader(name=name, value=value.get_secret_value())
|
|
679
722
|
for name, value in (server.headers or {}).items()
|
|
680
723
|
]
|
|
681
724
|
|
|
682
|
-
|
|
725
|
+
auth = server.auth
|
|
726
|
+
if isinstance(auth, MCPOAuthAuthCredential):
|
|
727
|
+
auth_headers = _oauth_bearer_header(auth, name)
|
|
728
|
+
else:
|
|
729
|
+
auth_headers = auth.to_http_headers() if auth is not None else {}
|
|
683
730
|
if auth_headers is None:
|
|
684
731
|
logger.warning(
|
|
685
732
|
"ACP MCP server %r uses unsupported remote MCP auth type %r; "
|
|
686
733
|
"only header-compatible auth can be forwarded",
|
|
687
734
|
name,
|
|
688
|
-
type(
|
|
735
|
+
type(auth).__name__,
|
|
689
736
|
)
|
|
690
737
|
return headers
|
|
691
738
|
headers.extend(
|
|
@@ -724,7 +771,8 @@ def _mcp_config_to_acp_servers(
|
|
|
724
771
|
with a warning rather than failing init — one misconfigured server should
|
|
725
772
|
not sink the whole conversation. ``env`` / ``headers`` maps are converted
|
|
726
773
|
to the protocol's ``[{name, value}]`` list form; header-compatible auth
|
|
727
|
-
credentials
|
|
774
|
+
credentials, and the stored access token of an OAuth2 connection, are also
|
|
775
|
+
converted to headers.
|
|
728
776
|
"""
|
|
729
777
|
caps = normalize_mcp_capabilities(mcp_capabilities)
|
|
730
778
|
http_ok = caps.http
|
|
@@ -1974,6 +2022,10 @@ class ACPAgent(AgentBase):
|
|
|
1974
2022
|
# "installed" — already in subprocess history; skip further injection
|
|
1975
2023
|
_suffix_install_state: str = PrivateAttr(default="unused")
|
|
1976
2024
|
_installed_suffix: str | None = PrivateAttr(default=None)
|
|
2025
|
+
# Skills written to disk and listed by path in the prompt, not inlined.
|
|
2026
|
+
_skill_locations: dict[str, Path] = PrivateAttr(default_factory=dict)
|
|
2027
|
+
_skills_root: Path | None = PrivateAttr(default=None)
|
|
2028
|
+
_additional_directories_supported: bool = PrivateAttr(default=False)
|
|
1977
2029
|
_restart_session_on_next_turn: bool = PrivateAttr(default=False)
|
|
1978
2030
|
# Stream identity for the turn in flight; see stream_context.py. Held on
|
|
1979
2031
|
# the agent rather than threaded through the finalizers because the ACP
|
|
@@ -2285,6 +2337,7 @@ class ACPAgent(AgentBase):
|
|
|
2285
2337
|
|
|
2286
2338
|
# Render the suffix once, pulling secrets from the conversation's
|
|
2287
2339
|
# secret_registry to match the regular Agent's get_dynamic_context().
|
|
2340
|
+
self._materialize_skills(state)
|
|
2288
2341
|
self._installed_suffix = self._render_suffix(state)
|
|
2289
2342
|
# A prior session id means we may be resuming; used by ``truly_resumed``
|
|
2290
2343
|
# below to decide whether the model state reported for this launch
|
|
@@ -2447,6 +2500,25 @@ class ACPAgent(AgentBase):
|
|
|
2447
2500
|
)
|
|
2448
2501
|
)
|
|
2449
2502
|
|
|
2503
|
+
def _skill_directories(self) -> list[str] | None:
|
|
2504
|
+
if self._skills_root and self._additional_directories_supported:
|
|
2505
|
+
return [str(self._skills_root)]
|
|
2506
|
+
return None
|
|
2507
|
+
|
|
2508
|
+
def _materialize_skills(self, state: ConversationState) -> None:
|
|
2509
|
+
self._skill_locations = {}
|
|
2510
|
+
self._skills_root = None
|
|
2511
|
+
context = self.agent_context
|
|
2512
|
+
if context is None or not context.skills:
|
|
2513
|
+
return
|
|
2514
|
+
_, available = context._partition_skills()
|
|
2515
|
+
if not available:
|
|
2516
|
+
return
|
|
2517
|
+
root = self._acp_file_secret_dir(state, "skills")
|
|
2518
|
+
shutil.rmtree(root, ignore_errors=True)
|
|
2519
|
+
self._skill_locations = write_skill_files(root, available)
|
|
2520
|
+
self._skills_root = root
|
|
2521
|
+
|
|
2450
2522
|
def _render_suffix(self, state: ConversationState) -> str | None:
|
|
2451
2523
|
"""Render the system suffix once, including secrets from the registry.
|
|
2452
2524
|
|
|
@@ -2487,12 +2559,23 @@ class ACPAgent(AgentBase):
|
|
|
2487
2559
|
if not secret_infos:
|
|
2488
2560
|
return None
|
|
2489
2561
|
agent_context = AgentContext(current_datetime=None)
|
|
2490
|
-
|
|
2562
|
+
listed = [s for s in agent_context.skills if s.name in self._skill_locations]
|
|
2563
|
+
if listed:
|
|
2564
|
+
agent_context = agent_context.model_copy(
|
|
2565
|
+
update={"skills": [s for s in agent_context.skills if s not in listed]}
|
|
2566
|
+
)
|
|
2567
|
+
if agent_context.secrets:
|
|
2491
2568
|
# The registry already carries these (and their descriptions), so
|
|
2492
2569
|
# clear the agent_context copy to advertise from the registry alone
|
|
2493
2570
|
# rather than re-merging a redundant second source.
|
|
2494
2571
|
agent_context = agent_context.model_copy(update={"secrets": {}})
|
|
2495
|
-
|
|
2572
|
+
rendered = agent_context.to_acp_prompt_context(
|
|
2573
|
+
additional_secret_infos=secret_infos
|
|
2574
|
+
)
|
|
2575
|
+
if not listed:
|
|
2576
|
+
return rendered
|
|
2577
|
+
catalog = render_skill_catalog(listed, self._skill_locations)
|
|
2578
|
+
return f"{rendered}\n\n{catalog}" if rendered else catalog
|
|
2496
2579
|
|
|
2497
2580
|
def _present_file_secret_names(self, state: ConversationState) -> set[str]:
|
|
2498
2581
|
"""Reserved file-content secret names supplied for this conversation.
|
|
@@ -3115,6 +3198,15 @@ class ACPAgent(AgentBase):
|
|
|
3115
3198
|
if init_response.agent_capabilities is not None
|
|
3116
3199
|
else None
|
|
3117
3200
|
)
|
|
3201
|
+
session_caps = (
|
|
3202
|
+
init_response.agent_capabilities.session_capabilities
|
|
3203
|
+
if init_response.agent_capabilities is not None
|
|
3204
|
+
else None
|
|
3205
|
+
)
|
|
3206
|
+
self._additional_directories_supported = (
|
|
3207
|
+
session_caps is not None
|
|
3208
|
+
and session_caps.additional_directories is not None
|
|
3209
|
+
)
|
|
3118
3210
|
acp_mcp_servers = _mcp_config_to_acp_servers(self.mcp_config, mcp_caps)
|
|
3119
3211
|
if acp_mcp_servers:
|
|
3120
3212
|
logger.info(
|
|
@@ -3210,6 +3302,7 @@ class ACPAgent(AgentBase):
|
|
|
3210
3302
|
load_response = await conn.load_session(
|
|
3211
3303
|
cwd=working_dir,
|
|
3212
3304
|
session_id=prior_session_id,
|
|
3305
|
+
additional_directories=self._skill_directories(),
|
|
3213
3306
|
mcp_servers=acp_mcp_servers,
|
|
3214
3307
|
)
|
|
3215
3308
|
session_id = prior_session_id
|
|
@@ -3255,6 +3348,7 @@ class ACPAgent(AgentBase):
|
|
|
3255
3348
|
session_meta = build_session_model_meta(agent_name, self.acp_model)
|
|
3256
3349
|
response = await conn.new_session(
|
|
3257
3350
|
cwd=working_dir,
|
|
3351
|
+
additional_directories=self._skill_directories(),
|
|
3258
3352
|
mcp_servers=acp_mcp_servers,
|
|
3259
3353
|
**session_meta,
|
|
3260
3354
|
)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Expose skills to any ACP agent as files plus a catalog that points at them."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import re
|
|
7
|
+
from collections.abc import Sequence
|
|
8
|
+
from html import escape
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from openhands.sdk.skills import Skill
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _description(skill: Skill) -> str:
|
|
15
|
+
if skill.description:
|
|
16
|
+
return skill.description
|
|
17
|
+
return next(
|
|
18
|
+
(line.strip() for line in skill.content.splitlines() if line.strip()),
|
|
19
|
+
skill.name,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _directory_name(name: str, taken: set[str]) -> str:
|
|
24
|
+
base = re.sub(r"[^A-Za-z0-9._-]+", "-", name).strip(".-") or "skill"
|
|
25
|
+
candidate, suffix = base, 2
|
|
26
|
+
while candidate.lower() in taken:
|
|
27
|
+
candidate, suffix = f"{base}-{suffix}", suffix + 1
|
|
28
|
+
taken.add(candidate.lower())
|
|
29
|
+
return candidate
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def write_skill_files(root: Path, skills: Sequence[Skill]) -> dict[str, Path]:
|
|
33
|
+
"""Write each skill to ``root/<dir>/SKILL.md``; return its path by skill name."""
|
|
34
|
+
locations: dict[str, Path] = {}
|
|
35
|
+
taken: set[str] = set()
|
|
36
|
+
for skill in skills:
|
|
37
|
+
skill_dir = root / _directory_name(skill.name, taken)
|
|
38
|
+
skill_dir.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
path = skill_dir / "SKILL.md"
|
|
40
|
+
name = json.dumps(skill.name, ensure_ascii=False)
|
|
41
|
+
description = json.dumps(_description(skill)[:1000], ensure_ascii=False)
|
|
42
|
+
path.write_text(
|
|
43
|
+
f"---\nname: {name}\ndescription: {description}\n---\n\n{skill.content}\n",
|
|
44
|
+
encoding="utf-8",
|
|
45
|
+
)
|
|
46
|
+
locations[skill.name] = path
|
|
47
|
+
return locations
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def render_skill_catalog(skills: Sequence[Skill], locations: dict[str, Path]) -> str:
|
|
51
|
+
entries = [
|
|
52
|
+
" <skill>\n"
|
|
53
|
+
f" <name>{escape(skill.name)}</name>\n"
|
|
54
|
+
f" <description>{escape(_description(skill)[:1024])}</description>\n"
|
|
55
|
+
f" <location>{escape(str(locations[skill.name]))}</location>\n"
|
|
56
|
+
" </skill>"
|
|
57
|
+
for skill in skills
|
|
58
|
+
if skill.name in locations
|
|
59
|
+
]
|
|
60
|
+
return (
|
|
61
|
+
"<SKILLS>\n"
|
|
62
|
+
"The following skills are available. When one is relevant to the task, "
|
|
63
|
+
"read its SKILL.md at the given location with your file-reading tool "
|
|
64
|
+
"and follow its instructions.\n\n"
|
|
65
|
+
"<available_skills>\n" + "\n".join(entries) + "\n</available_skills>\n"
|
|
66
|
+
"</SKILLS>"
|
|
67
|
+
)
|
|
@@ -52,6 +52,7 @@ from openhands.sdk.event.condenser import (
|
|
|
52
52
|
)
|
|
53
53
|
from openhands.sdk.event.error_classification import AGENT_OUTCOME
|
|
54
54
|
from openhands.sdk.event.security import SecurityAnalysisEvent
|
|
55
|
+
from openhands.sdk.event.types import ROOT_PARENT_ID, EventID
|
|
55
56
|
from openhands.sdk.llm import (
|
|
56
57
|
LLM,
|
|
57
58
|
ImageContent,
|
|
@@ -561,12 +562,25 @@ class Agent(CriticMixin, ResponseDispatchMixin, AgentBase):
|
|
|
561
562
|
)
|
|
562
563
|
return
|
|
563
564
|
|
|
565
|
+
# A damaged event log can lose the SystemPromptEvent's file. The first
|
|
566
|
+
# surviving event still names it as its parent, or names the copy that an
|
|
567
|
+
# earlier resume re-created under the same id.
|
|
568
|
+
restored_prompt_id: EventID | None = None
|
|
569
|
+
if has_user_message:
|
|
570
|
+
parent_id = state.events[0].parent_id
|
|
571
|
+
if parent_id is not None and parent_id in state.events:
|
|
572
|
+
parent = state.events[state.events.get_index(parent_id)]
|
|
573
|
+
if isinstance(parent, SystemPromptEvent):
|
|
574
|
+
return
|
|
575
|
+
elif parent_id not in (None, ROOT_PARENT_ID):
|
|
576
|
+
restored_prompt_id = parent_id
|
|
577
|
+
|
|
564
578
|
# Assert: A user message should never appear before the system prompt.
|
|
565
579
|
#
|
|
566
580
|
# NOTE: This is a best-effort check based on the first few events only.
|
|
567
581
|
# Remote conversations can include a ConversationStateUpdateEvent near the
|
|
568
582
|
# start, so we scan a small prefix window.
|
|
569
|
-
if has_user_message:
|
|
583
|
+
if has_user_message and restored_prompt_id is None:
|
|
570
584
|
event_types = [type(e).__name__ for e in prefix_events]
|
|
571
585
|
logger.error(
|
|
572
586
|
f"init_state: User message found in prefix before SystemPromptEvent! "
|
|
@@ -598,7 +612,29 @@ class Agent(CriticMixin, ResponseDispatchMixin, AgentBase):
|
|
|
598
612
|
if dynamic_context
|
|
599
613
|
else None,
|
|
600
614
|
)
|
|
601
|
-
|
|
615
|
+
if restored_prompt_id is None:
|
|
616
|
+
on_event(event)
|
|
617
|
+
return
|
|
618
|
+
|
|
619
|
+
# Re-create it as an explicit root under its old id, so the surviving
|
|
620
|
+
# history hangs off it again; appending must not move HEAD onto it.
|
|
621
|
+
logger.warning(
|
|
622
|
+
"SystemPromptEvent '%s' is missing from the event log (its file was "
|
|
623
|
+
"lost); re-creating it as the root of the surviving history. "
|
|
624
|
+
"conversation_id=%s",
|
|
625
|
+
restored_prompt_id,
|
|
626
|
+
state.id,
|
|
627
|
+
)
|
|
628
|
+
head = state.active_branch(limit=1)
|
|
629
|
+
head_is_empty = state.head_is_empty
|
|
630
|
+
on_event(
|
|
631
|
+
event.model_copy(
|
|
632
|
+
update={"id": restored_prompt_id, "parent_id": ROOT_PARENT_ID}
|
|
633
|
+
)
|
|
634
|
+
)
|
|
635
|
+
state.leaf_event_id = head[-1].id if head else None
|
|
636
|
+
state.head_is_empty = head_is_empty
|
|
637
|
+
state.rebuild_view()
|
|
602
638
|
|
|
603
639
|
def get_dynamic_context(self, state: ConversationState) -> str | None:
|
|
604
640
|
"""Get dynamic context for the system prompt, including secrets from state.
|
|
@@ -73,6 +73,7 @@ class Conversation:
|
|
|
73
73
|
token_callbacks: list[ConversationTokenCallbackType] | None = None,
|
|
74
74
|
hook_config: HookConfig | None = None,
|
|
75
75
|
max_iteration_per_run: int = 500,
|
|
76
|
+
max_budget_per_run: float | None = None,
|
|
76
77
|
stuck_detection: bool = True,
|
|
77
78
|
stuck_detection_thresholds: (
|
|
78
79
|
StuckDetectionThresholds | Mapping[str, int] | None
|
|
@@ -103,6 +104,7 @@ class Conversation:
|
|
|
103
104
|
token_callbacks: list[ConversationTokenCallbackType] | None = None,
|
|
104
105
|
hook_config: HookConfig | None = None,
|
|
105
106
|
max_iteration_per_run: int = 500,
|
|
107
|
+
max_budget_per_run: float | None = None,
|
|
106
108
|
stuck_detection: bool = True,
|
|
107
109
|
stuck_detection_thresholds: (
|
|
108
110
|
StuckDetectionThresholds | Mapping[str, int] | None
|
|
@@ -133,6 +135,7 @@ class Conversation:
|
|
|
133
135
|
token_callbacks: list[ConversationTokenCallbackType] | None = None,
|
|
134
136
|
hook_config: HookConfig | None = None,
|
|
135
137
|
max_iteration_per_run: int = 500,
|
|
138
|
+
max_budget_per_run: float | None = None,
|
|
136
139
|
stuck_detection: bool = True,
|
|
137
140
|
stuck_detection_thresholds: (
|
|
138
141
|
StuckDetectionThresholds | Mapping[str, int] | None
|
|
@@ -200,6 +203,7 @@ class Conversation:
|
|
|
200
203
|
token_callbacks=token_callbacks,
|
|
201
204
|
hook_config=hook_config,
|
|
202
205
|
max_iteration_per_run=max_iteration_per_run,
|
|
206
|
+
max_budget_per_run=max_budget_per_run,
|
|
203
207
|
stuck_detection=stuck_detection,
|
|
204
208
|
stuck_detection_thresholds=stuck_detection_thresholds,
|
|
205
209
|
visualizer=visualizer,
|
|
@@ -223,6 +227,7 @@ class Conversation:
|
|
|
223
227
|
token_callbacks=token_callbacks,
|
|
224
228
|
hook_config=hook_config,
|
|
225
229
|
max_iteration_per_run=max_iteration_per_run,
|
|
230
|
+
max_budget_per_run=max_budget_per_run,
|
|
226
231
|
stuck_detection=stuck_detection,
|
|
227
232
|
stuck_detection_thresholds=stuck_detection_thresholds,
|
|
228
233
|
visualizer=visualizer,
|