agentkit-sdk-python 0.7.0__tar.gz → 0.7.2__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.
- {agentkit_sdk_python-0.7.0/agentkit_sdk_python.egg-info → agentkit_sdk_python-0.7.2}/PKG-INFO +6 -1
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/README.md +5 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/simple_app/simple_app.py +4 -3
- agentkit_sdk_python-0.7.2/agentkit/auth/_redact.py +25 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/errors.py +3 -1
- agentkit_sdk_python-0.7.2/agentkit/auth/model_login.py +360 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/session.py +4 -2
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/client/base_agentkit_client.py +6 -1
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/client/base_service_client.py +89 -10
- agentkit_sdk_python-0.7.2/agentkit/errors.py +32 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/platform/configuration.py +2 -2
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/account/client.py +0 -2
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/identity/auth.py +3 -2
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/cli.py +7 -1
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/cli_create.py +269 -46
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/cli_exec.py +145 -27
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/cli_file.py +8 -2
- agentkit_sdk_python-0.7.2/agentkit/toolkit/cli/sandbox/cli_model_login.py +238 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/cli_mount.py +2 -1
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/cli_run.py +24 -10
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/cli_shell.py +3 -5
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/model_config.py +184 -39
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/session_create.py +64 -29
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/tool_resolve.py +129 -6
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/tos_config.py +2 -1
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/errors.py +16 -1
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/runners/ve_agentkit.py +5 -2
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/cr.py +3 -3
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/iam.py +1 -1
- agentkit_sdk_python-0.7.2/agentkit/utils/http_defaults.py +54 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/utils/logging_config.py +22 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/utils/request.py +4 -4
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/utils/ve_sign.py +99 -10
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/version.py +1 -1
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2/agentkit_sdk_python.egg-info}/PKG-INFO +6 -1
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit_sdk_python.egg-info/SOURCES.txt +7 -1
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/pyproject.toml +1 -1
- agentkit_sdk_python-0.7.2/tests/test_error_hierarchy.py +86 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/LICENSE +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/MANIFEST.in +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/a2a_app/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/a2a_app/a2a_app.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/a2a_app/telemetry.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/agent_server_app/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/agent_server_app/agent_server_app.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/agent_server_app/middleware.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/agent_server_app/origin.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/agent_server_app/telemetry.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/base_app.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/mcp_app/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/mcp_app/mcp_app.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/mcp_app/telemetry.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/simple_app/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/simple_app/simple_app_handlers.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/simple_app/telemetry.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/utils.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/_openapi.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/_sigv4.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/admin.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/credential_hosting.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/oauth.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/profile.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/providers.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/resolve.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/ssl_trust.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/sso.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/store.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/auth/sts.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/client/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/client/base_iam_client.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/platform/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/platform/console_urls.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/platform/constants.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/platform/context.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/platform/provider.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/account/types.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/identity/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/identity/client.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/identity/types.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/knowledge/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/knowledge/client.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/knowledge/types.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/mcp/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/mcp/client.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/mcp/types.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/memory/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/memory/client.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/memory/types.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/runtime/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/runtime/client.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/runtime/types.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/skills/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/skills/client.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/skills/types.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/tools/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/tools/client.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/sdk/tools/types.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/builders/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/builders/base.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/builders/local_docker.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/builders/ve_pipeline.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/__main__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_add.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_auth.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_build.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_config.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_delete.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_deploy.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_destroy.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_init.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_invoke.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_knowledge.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_launch.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_list.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_logs.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_memory.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_runtime.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_skill.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_skills.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_skills_workflow.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_status.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_tools.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/cli_version.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/console_reporter.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/interactive_config.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/cli_get.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/cli_web.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/git_config.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/sandbox_client.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/sandbox/session_sync.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/cli/utils.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/choice_resolvers.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/cloud_provider.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/config.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/config_handler.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/config_validator.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/constants.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/dataclass_utils.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/docker_build_config.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/global_config.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/region_defaults.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/region_resolver.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/strategy_configs.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/config/utils.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/context.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/docker/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/docker/base_images.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/docker/container.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/docker/dockerfile/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/docker/dockerfile/manager.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/docker/dockerfile/metadata.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/docker/utils.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/executors/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/executors/base_executor.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/executors/build_executor.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/executors/deploy_executor.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/executors/init_executor.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/executors/invoke_executor.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/executors/lifecycle_executor.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/executors/status_executor.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/harness/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/harness/config_builder.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/harness/deploy.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/harness/env_mapping.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/models.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/reporter.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/__pycache__/customer_support_assistant.cpython-312.pyc +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/__pycache__/financial_analyst.cpython-312.pyc +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/__pycache__/simple_app_veadk.cpython-312.pyc +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/__pycache__/simple_mcp_veadk.cpython-312.pyc +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/a2a.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/agent_server.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/basic.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/basic_stream.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/customer_support_assistant.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/eino_a2a/agent.go +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/eino_a2a/build.sh +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/eino_a2a/go.mod +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/eino_a2a/go.sum +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/eino_a2a/main.go +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/financial_analyst.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/langchain_basic_stream.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/simple_app_veadk.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/simple_mcp_veadk.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/veadk_go_a2a/agent.go +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/veadk_go_a2a/build.sh +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/veadk_go_a2a/go.mod +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/veadk_go_a2a/go.sum +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/veadk_go_a2a/main.go +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/veadk_go_basic/agent.go +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/veadk_go_basic/build.sh +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/veadk_go_basic/go.mod +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/veadk_go_basic/go.sum +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/samples/veadk_go_basic/main.go +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/templates/code-pipeline-tos-cr-step.j2 +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/templates/golang/Dockerfile.j2 +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/templates/python/Dockerfile.j2 +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/wrappers/wrapper_basic.py.jinja2 +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/resources/wrappers/wrapper_stream.py.jinja2 +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/runners/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/runners/base.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/runners/local_docker.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/bindings/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/bindings/memory.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/builder.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/client.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/config.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/deployer.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/initializer.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/invoker.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/lifecycle.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/sdk/status.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/strategies/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/strategies/base_strategy.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/strategies/cloud_strategy.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/strategies/hybrid_strategy.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/strategies/local_strategy.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/utils/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/utils/agent_parser.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/apmplus_logs.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/code_pipeline.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/services/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/services/cr_service.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/services/tos_service.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/sts.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/utils/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/toolkit/volcengine/utils/project_archiver.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/utils/__init__.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/utils/global_config_io.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/utils/misc.py +0 -0
- /agentkit_sdk_python-0.7.0/agentkit/auth/_redact.py → /agentkit_sdk_python-0.7.2/agentkit/utils/redact.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/utils/template_utils.py +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit_sdk_python.egg-info/dependency_links.txt +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit_sdk_python.egg-info/entry_points.txt +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit_sdk_python.egg-info/requires.txt +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit_sdk_python.egg-info/top_level.txt +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/setup.cfg +0 -0
- {agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/tests/test_client_uses_platform_context.py +0 -0
{agentkit_sdk_python-0.7.0/agentkit_sdk_python.egg-info → agentkit_sdk_python-0.7.2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentkit-sdk-python
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Python SDK for transforming any AI agent into a production-ready application. Framework-agnostic primitives for runtime, memory, authentication, and tools with volcengine-managed infrastructure.
|
|
5
5
|
Author-email: Xiangrui Cheng <innsdcc@gmail.com>, Yumeng Bao <baoyumeng.123@gmail.com>, Yaozheng Fang <fangyozheng@gmail.com>, Guodong Li <cu.eric.lee@gmail.com>
|
|
6
6
|
License: Apache License
|
|
@@ -333,6 +333,11 @@ pip install agentkit-sdk-python==1.0.0.dev1
|
|
|
333
333
|
|
|
334
334
|
**Note**: Development versions may contain bugs and are not recommended for production use.
|
|
335
335
|
|
|
336
|
+
## Security and privacy
|
|
337
|
+
|
|
338
|
+
This project takes security seriously.
|
|
339
|
+
For vulnerability reporting and supported versions, see [SECURITY.md](SECURITY.md).
|
|
340
|
+
|
|
336
341
|
## License
|
|
337
342
|
|
|
338
343
|
This project is licensed under the [Apache 2.0 License](./LICENSE).
|
|
@@ -85,6 +85,11 @@ pip install agentkit-sdk-python==1.0.0.dev1
|
|
|
85
85
|
|
|
86
86
|
**Note**: Development versions may contain bugs and are not recommended for production use.
|
|
87
87
|
|
|
88
|
+
## Security and privacy
|
|
89
|
+
|
|
90
|
+
This project takes security seriously.
|
|
91
|
+
For vulnerability reporting and supported versions, see [SECURITY.md](SECURITY.md).
|
|
92
|
+
|
|
88
93
|
## License
|
|
89
94
|
|
|
90
95
|
This project is licensed under the [Apache 2.0 License](./LICENSE).
|
{agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/apps/simple_app/simple_app.py
RENAMED
|
@@ -52,9 +52,10 @@ class AgentkitSimpleApp(BaseAgentkitApp, Starlette):
|
|
|
52
52
|
return func
|
|
53
53
|
|
|
54
54
|
def ping(self, func: Callable) -> Callable:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
if len(inspect.signature(func).parameters) != 0:
|
|
56
|
+
raise TypeError(
|
|
57
|
+
f"Health check function `{func.__name__}` should not receive any arguments."
|
|
58
|
+
)
|
|
58
59
|
|
|
59
60
|
self.ping_handler.func = func
|
|
60
61
|
return func
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Backward-compatible shim.
|
|
16
|
+
|
|
17
|
+
The redaction helpers now live in :mod:`agentkit.utils.redact`; this module
|
|
18
|
+
re-exports them so existing importers keep working.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from agentkit.utils.redact import mask, redact
|
|
24
|
+
|
|
25
|
+
__all__ = ["redact", "mask"]
|
|
@@ -16,8 +16,10 @@
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
+
from agentkit.errors import AgentKitError
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
|
|
22
|
+
class AuthError(AgentKitError):
|
|
21
23
|
"""Base class for all authentication failures.
|
|
22
24
|
|
|
23
25
|
Carries an optional ``hint`` with an actionable next step that CLIs can
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Bring a user's *own* third-party model subscription into the sandbox.
|
|
16
|
+
|
|
17
|
+
Many foreign models (ChatGPT/Codex, Claude Code) are used via a JWT obtained by an
|
|
18
|
+
interactive SSO login, not a static API key. A user who subscribed to one of those
|
|
19
|
+
plans wants the **sandbox's** codex to run on *their* subscription.
|
|
20
|
+
|
|
21
|
+
The agentkit UserPool does not (and need not) federate with OpenAI/Anthropic. Codex
|
|
22
|
+
already supports SSO **locally**; in the sandbox it is "remote", so the agreed design
|
|
23
|
+
is dead simple and is what this module implements:
|
|
24
|
+
|
|
25
|
+
1. The user runs the provider's native SSO **on their PC** (``codex login`` for
|
|
26
|
+
Codex/ChatGPT, ``claude`` for Claude Code). That writes the provider's native
|
|
27
|
+
credential file:
|
|
28
|
+
Codex -> $CODEX_HOME/auth.json (default ~/.codex/auth.json)
|
|
29
|
+
Claude -> ~/.claude/.credentials.json (or the macOS Keychain)
|
|
30
|
+
2. We read that file verbatim and inject it into the **same native path inside
|
|
31
|
+
the user's private sandbox** — so the sandbox's codex finds its token exactly
|
|
32
|
+
where it natively looks. No proxy, no federation: the sandbox refreshes the
|
|
33
|
+
token itself against the provider, just like a local install would.
|
|
34
|
+
|
|
35
|
+
This module is pure (stdlib only) and side-effect-light so it is unit-testable; the
|
|
36
|
+
network/forwarding lives in the CLI layer (``cli_accesscontrol.py``).
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
from __future__ import annotations
|
|
40
|
+
|
|
41
|
+
import base64
|
|
42
|
+
import datetime
|
|
43
|
+
import json
|
|
44
|
+
import os
|
|
45
|
+
import re
|
|
46
|
+
import sys
|
|
47
|
+
from pathlib import Path
|
|
48
|
+
from typing import Callable, Optional
|
|
49
|
+
|
|
50
|
+
# ── Codex / ChatGPT facts ────────────────────────────────────────────────────
|
|
51
|
+
CODEX_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann" # codex CLI's public OAuth client (the id_token aud)
|
|
52
|
+
CODEX_OAUTH_NAMESPACE = "https://api.openai.com/auth" # claim namespace holding the ChatGPT plan
|
|
53
|
+
DEFAULT_SANDBOX_CODEX_HOME = "/home/gem/.codex" # informational; the shell resolves ${CODEX_HOME:-$HOME/.codex}
|
|
54
|
+
CODEX_INJECT_MARKER = "AGENTKIT_CODEX_INJECTED"
|
|
55
|
+
CLAUDE_INJECT_MARKER = "AGENTKIT_CLAUDE_INJECTED"
|
|
56
|
+
CLAUDE_KEYCHAIN_SERVICE = "Claude Code-credentials"
|
|
57
|
+
|
|
58
|
+
PROVIDERS = ("codex", "claude")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ModelLoginError(RuntimeError):
|
|
62
|
+
"""A user-facing failure resolving or injecting a model subscription token."""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ── small helpers ────────────────────────────────────────────────────────────
|
|
66
|
+
def b64(data: str | bytes) -> str:
|
|
67
|
+
"""Standard base64 (single line, no newlines) — safe to embed in a shell ``printf``."""
|
|
68
|
+
if isinstance(data, str):
|
|
69
|
+
data = data.encode("utf-8")
|
|
70
|
+
return base64.b64encode(data).decode("ascii")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _iso(epoch_seconds: int) -> str:
|
|
74
|
+
return datetime.datetime.fromtimestamp(epoch_seconds, tz=datetime.timezone.utc).isoformat()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def decode_jwt_claims(jwt: str) -> dict:
|
|
78
|
+
"""Decode (NOT verify) a JWT's payload claims. We only read non-secret metadata."""
|
|
79
|
+
parts = (jwt or "").split(".")
|
|
80
|
+
if len(parts) < 2:
|
|
81
|
+
raise ModelLoginError("malformed JWT")
|
|
82
|
+
seg = parts[1]
|
|
83
|
+
try:
|
|
84
|
+
return json.loads(base64.urlsafe_b64decode(seg + "=" * (-len(seg) % 4)))
|
|
85
|
+
except Exception as exc: # noqa: BLE001
|
|
86
|
+
raise ModelLoginError(f"cannot decode JWT claims: {exc}") from exc
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# ── Codex (ChatGPT) ──────────────────────────────────────────────────────────
|
|
90
|
+
def codex_home_path(explicit: Optional[str] = None) -> Path:
|
|
91
|
+
"""Resolve the LOCAL codex home: --codex-home > $CODEX_HOME > ~/.codex."""
|
|
92
|
+
if explicit:
|
|
93
|
+
return Path(explicit).expanduser()
|
|
94
|
+
env = os.environ.get("CODEX_HOME")
|
|
95
|
+
if env:
|
|
96
|
+
return Path(env).expanduser()
|
|
97
|
+
return Path.home() / ".codex"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def read_codex_auth(path: str | Path) -> dict:
|
|
101
|
+
p = Path(path)
|
|
102
|
+
try:
|
|
103
|
+
data = json.loads(p.read_text(encoding="utf-8"))
|
|
104
|
+
except FileNotFoundError as exc:
|
|
105
|
+
raise ModelLoginError(f"codex auth file not found: {p}") from exc
|
|
106
|
+
except (json.JSONDecodeError, OSError) as exc:
|
|
107
|
+
raise ModelLoginError(f"cannot read codex auth file {p}: {exc}") from exc
|
|
108
|
+
if not isinstance(data, dict):
|
|
109
|
+
raise ModelLoginError(f"codex auth file {p} is not a JSON object")
|
|
110
|
+
return data
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def validate_codex_auth(data: dict) -> None:
|
|
114
|
+
"""A usable codex auth has ChatGPT tokens (SSO) or an API key."""
|
|
115
|
+
tokens = data.get("tokens")
|
|
116
|
+
has_tokens = isinstance(tokens, dict) and bool(tokens.get("id_token") or tokens.get("access_token"))
|
|
117
|
+
has_key = bool(data.get("OPENAI_API_KEY"))
|
|
118
|
+
if not (has_tokens or has_key):
|
|
119
|
+
raise ModelLoginError(
|
|
120
|
+
"codex auth.json has neither ChatGPT tokens nor an API key — run `codex login` first"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def codex_auth_summary(data: dict) -> dict:
|
|
125
|
+
"""A redacted, secret-free summary (provider, plan, account, expiry) for display."""
|
|
126
|
+
tokens = data.get("tokens") or {}
|
|
127
|
+
summary: dict = {
|
|
128
|
+
"provider": "codex (ChatGPT)",
|
|
129
|
+
"auth_mode": data.get("auth_mode") or ("chatgpt" if tokens else "apikey"),
|
|
130
|
+
"has_refresh_token": bool(tokens.get("refresh_token")),
|
|
131
|
+
"account_id": tokens.get("account_id"),
|
|
132
|
+
}
|
|
133
|
+
idt = tokens.get("id_token")
|
|
134
|
+
if idt:
|
|
135
|
+
try:
|
|
136
|
+
claims = decode_jwt_claims(idt)
|
|
137
|
+
except ModelLoginError:
|
|
138
|
+
claims = {}
|
|
139
|
+
ns = claims.get(CODEX_OAUTH_NAMESPACE) or {}
|
|
140
|
+
summary["email"] = claims.get("email")
|
|
141
|
+
summary["plan"] = ns.get("chatgpt_plan_type")
|
|
142
|
+
summary["chatgpt_account_id"] = ns.get("chatgpt_account_id") or summary.get("account_id")
|
|
143
|
+
exp = claims.get("exp")
|
|
144
|
+
if isinstance(exp, int):
|
|
145
|
+
summary["id_token_expires"] = _iso(exp)
|
|
146
|
+
summary["id_token_expired"] = exp < int(datetime.datetime.now(datetime.timezone.utc).timestamp())
|
|
147
|
+
return {k: v for k, v in summary.items() if v is not None}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def run_codex_login(
|
|
151
|
+
*, codex_home: Optional[Path] = None, codex_bin: str = "codex", timeout: int = 300
|
|
152
|
+
) -> None:
|
|
153
|
+
"""Trigger codex's native local SSO (opens a browser) so it writes a fresh auth.json."""
|
|
154
|
+
import subprocess
|
|
155
|
+
|
|
156
|
+
env = dict(os.environ)
|
|
157
|
+
if codex_home:
|
|
158
|
+
env["CODEX_HOME"] = str(codex_home)
|
|
159
|
+
try:
|
|
160
|
+
subprocess.run([codex_bin, "login"], env=env, timeout=timeout, check=True) # noqa: S603
|
|
161
|
+
except FileNotFoundError as exc:
|
|
162
|
+
raise ModelLoginError(
|
|
163
|
+
f"`{codex_bin}` not found on PATH — install the Codex CLI and run `codex login`, "
|
|
164
|
+
f"or pass --auth-file <path-to-your-auth.json>"
|
|
165
|
+
) from exc
|
|
166
|
+
except subprocess.CalledProcessError as exc:
|
|
167
|
+
raise ModelLoginError(f"`codex login` failed (exit {exc.returncode})") from exc
|
|
168
|
+
except subprocess.TimeoutExpired as exc:
|
|
169
|
+
raise ModelLoginError("`codex login` timed out") from exc
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def resolve_local_codex_auth(
|
|
173
|
+
*,
|
|
174
|
+
codex_home: Optional[str] = None,
|
|
175
|
+
auth_file: Optional[str] = None,
|
|
176
|
+
allow_login: bool = True,
|
|
177
|
+
login_timeout: int = 300,
|
|
178
|
+
login_runner: Optional[Callable[..., None]] = None,
|
|
179
|
+
) -> tuple[Path, dict]:
|
|
180
|
+
"""Return ``(path, data)`` of a usable LOCAL codex auth, running `codex login` if needed."""
|
|
181
|
+
if auth_file:
|
|
182
|
+
path = Path(auth_file).expanduser()
|
|
183
|
+
if not path.exists():
|
|
184
|
+
raise ModelLoginError(f"--auth-file not found: {path}")
|
|
185
|
+
data = read_codex_auth(path)
|
|
186
|
+
validate_codex_auth(data)
|
|
187
|
+
return path, data
|
|
188
|
+
|
|
189
|
+
home = codex_home_path(codex_home)
|
|
190
|
+
path = home / "auth.json"
|
|
191
|
+
if not path.exists():
|
|
192
|
+
if not allow_login:
|
|
193
|
+
raise ModelLoginError(
|
|
194
|
+
f"no codex auth at {path} — run `codex login` (or pass --auth-file / --no-login off)"
|
|
195
|
+
)
|
|
196
|
+
(login_runner or run_codex_login)(codex_home=home, timeout=login_timeout)
|
|
197
|
+
if not path.exists():
|
|
198
|
+
raise ModelLoginError(f"`codex login` finished but {path} is still missing")
|
|
199
|
+
data = read_codex_auth(path)
|
|
200
|
+
validate_codex_auth(data)
|
|
201
|
+
return path, data
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# ── Codex config.toml: switch the sandbox codex to the ChatGPT subscription ──
|
|
205
|
+
_TOP_MODEL_PIN = re.compile(r"^\s*(model|model_provider|review_model)\s*=")
|
|
206
|
+
_AUTH_METHOD = re.compile(r"^\s*preferred_auth_method\s*=")
|
|
207
|
+
_TABLE_HEADER = re.compile(r"^\s*\[")
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def rewrite_codex_config_for_chatgpt(toml_text: str) -> str:
|
|
211
|
+
"""Switch an existing codex config.toml to ChatGPT-subscription auth, preserving everything else.
|
|
212
|
+
|
|
213
|
+
The sandbox's default config pins a custom ``model_provider``/``model`` to a Volcengine Ark
|
|
214
|
+
endpoint that authenticates with an API key (``env_key``); in that mode codex never looks at the
|
|
215
|
+
injected ChatGPT token. To use the subscription we:
|
|
216
|
+
* drop the top-level ``model`` / ``model_provider`` / ``review_model`` pins, so codex falls back
|
|
217
|
+
to its built-in ``openai`` provider and the subscription's default model, and
|
|
218
|
+
* force ``preferred_auth_method = "chatgpt"`` so the OAuth token wins over any stray API key.
|
|
219
|
+
Tables (``[tui]``, ``[projects.*]``, ``[mcp_servers.*]``, ``[model_providers.*]``) and other
|
|
220
|
+
top-level keys (approval_policy, sandbox_mode, model_reasoning_effort, …) are kept verbatim.
|
|
221
|
+
"""
|
|
222
|
+
out: list[str] = []
|
|
223
|
+
seen_table = False
|
|
224
|
+
for line in toml_text.splitlines():
|
|
225
|
+
if _TABLE_HEADER.match(line):
|
|
226
|
+
seen_table = True
|
|
227
|
+
if _AUTH_METHOD.match(line):
|
|
228
|
+
continue # re-added at the top
|
|
229
|
+
if not seen_table and _TOP_MODEL_PIN.match(line):
|
|
230
|
+
continue
|
|
231
|
+
out.append(line)
|
|
232
|
+
body = "\n".join(out).strip("\n")
|
|
233
|
+
return 'preferred_auth_method = "chatgpt"\n' + (body + "\n" if body else "")
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def minimal_chatgpt_codex_config() -> str:
|
|
237
|
+
"""A config.toml for a sandbox that has no codex config yet — ChatGPT auth, headless-friendly."""
|
|
238
|
+
return "\n".join(
|
|
239
|
+
[
|
|
240
|
+
'preferred_auth_method = "chatgpt"',
|
|
241
|
+
'approval_policy = "never"',
|
|
242
|
+
'sandbox_mode = "danger-full-access"',
|
|
243
|
+
"",
|
|
244
|
+
'[projects."/home/gem"]',
|
|
245
|
+
'trust_level = "trusted"',
|
|
246
|
+
"",
|
|
247
|
+
]
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def read_codex_config_command() -> str:
|
|
252
|
+
"""Shell command that prints the sandbox's current codex config.toml (empty if none)."""
|
|
253
|
+
return 'cat "${CODEX_HOME:-$HOME/.codex}/config.toml" 2>/dev/null || true'
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def build_codex_injection_command(*, auth_json: str, config_toml: Optional[str] = None) -> str:
|
|
257
|
+
"""A single POSIX-sh command that writes auth.json (and optionally config.toml) into the
|
|
258
|
+
sandbox's native codex home (``${CODEX_HOME:-$HOME/.codex}``), 0600, and prints a marker."""
|
|
259
|
+
lines = [
|
|
260
|
+
"set -e",
|
|
261
|
+
'CH="${CODEX_HOME:-$HOME/.codex}"',
|
|
262
|
+
'mkdir -p "$CH"',
|
|
263
|
+
"umask 077",
|
|
264
|
+
f"printf %s '{b64(auth_json)}' | base64 -d > \"$CH/auth.json\"",
|
|
265
|
+
'chmod 600 "$CH/auth.json"',
|
|
266
|
+
]
|
|
267
|
+
if config_toml is not None:
|
|
268
|
+
lines.append(f"printf %s '{b64(config_toml)}' | base64 -d > \"$CH/config.toml\"")
|
|
269
|
+
lines.append(f'echo "{CODEX_INJECT_MARKER} $CH"')
|
|
270
|
+
return "\n".join(lines)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
# ── Claude Code ──────────────────────────────────────────────────────────────
|
|
274
|
+
def claude_creds_path(explicit: Optional[str] = None) -> Path:
|
|
275
|
+
if explicit:
|
|
276
|
+
return Path(explicit).expanduser()
|
|
277
|
+
return Path.home() / ".claude" / ".credentials.json"
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _read_macos_keychain(service: str) -> Optional[str]:
|
|
281
|
+
import subprocess
|
|
282
|
+
|
|
283
|
+
try:
|
|
284
|
+
out = subprocess.run( # noqa: S603
|
|
285
|
+
["security", "find-generic-password", "-s", service, "-w"], # noqa: S607
|
|
286
|
+
capture_output=True,
|
|
287
|
+
text=True,
|
|
288
|
+
timeout=10,
|
|
289
|
+
)
|
|
290
|
+
except (FileNotFoundError, OSError, subprocess.TimeoutExpired):
|
|
291
|
+
return None
|
|
292
|
+
if out.returncode != 0:
|
|
293
|
+
return None
|
|
294
|
+
return (out.stdout or "").strip() or None
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def read_claude_creds(*, creds_file: Optional[str] = None, allow_keychain: bool = True) -> dict:
|
|
298
|
+
"""Read Claude Code subscription creds from the file, or the macOS Keychain as a fallback."""
|
|
299
|
+
path = claude_creds_path(creds_file)
|
|
300
|
+
if path.exists():
|
|
301
|
+
try:
|
|
302
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
303
|
+
except (json.JSONDecodeError, OSError) as exc:
|
|
304
|
+
raise ModelLoginError(f"cannot read {path}: {exc}") from exc
|
|
305
|
+
elif creds_file:
|
|
306
|
+
raise ModelLoginError(f"--auth-file not found: {path}")
|
|
307
|
+
elif allow_keychain and sys.platform == "darwin":
|
|
308
|
+
raw = _read_macos_keychain(CLAUDE_KEYCHAIN_SERVICE)
|
|
309
|
+
if not raw:
|
|
310
|
+
raise ModelLoginError(
|
|
311
|
+
"no Claude Code credentials in ~/.claude/.credentials.json or the macOS Keychain — "
|
|
312
|
+
"run `claude` and log in with your subscription first"
|
|
313
|
+
)
|
|
314
|
+
try:
|
|
315
|
+
data = json.loads(raw)
|
|
316
|
+
except json.JSONDecodeError as exc:
|
|
317
|
+
raise ModelLoginError("Claude Keychain entry is not valid JSON") from exc
|
|
318
|
+
else:
|
|
319
|
+
raise ModelLoginError(
|
|
320
|
+
"no Claude Code credentials at ~/.claude/.credentials.json — "
|
|
321
|
+
"run `claude` and log in with your subscription first"
|
|
322
|
+
)
|
|
323
|
+
if not isinstance(data, dict):
|
|
324
|
+
raise ModelLoginError("Claude credentials file is not a JSON object")
|
|
325
|
+
return data
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def validate_claude_creds(data: dict) -> None:
|
|
329
|
+
oauth = data.get("claudeAiOauth")
|
|
330
|
+
if not (isinstance(oauth, dict) and oauth.get("accessToken")):
|
|
331
|
+
raise ModelLoginError("Claude credentials missing claudeAiOauth.accessToken")
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def claude_creds_summary(data: dict) -> dict:
|
|
335
|
+
oauth = data.get("claudeAiOauth") or {}
|
|
336
|
+
summary: dict = {
|
|
337
|
+
"provider": "claude (Claude Code)",
|
|
338
|
+
"subscription": oauth.get("subscriptionType"),
|
|
339
|
+
"scopes": oauth.get("scopes"),
|
|
340
|
+
"has_refresh_token": bool(oauth.get("refreshToken")),
|
|
341
|
+
}
|
|
342
|
+
exp = oauth.get("expiresAt")
|
|
343
|
+
if isinstance(exp, (int, float)):
|
|
344
|
+
summary["access_token_expires"] = _iso(int(exp / 1000)) # Claude stores epoch milliseconds
|
|
345
|
+
return {k: v for k, v in summary.items() if v is not None}
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def build_claude_injection_command(*, creds_json: str) -> str:
|
|
349
|
+
"""A single POSIX-sh command that writes Claude Code creds into ``$HOME/.claude``, 0600."""
|
|
350
|
+
return "\n".join(
|
|
351
|
+
[
|
|
352
|
+
"set -e",
|
|
353
|
+
'CD="$HOME/.claude"',
|
|
354
|
+
'mkdir -p "$CD"',
|
|
355
|
+
"umask 077",
|
|
356
|
+
f"printf %s '{b64(creds_json)}' | base64 -d > \"$CD/.credentials.json\"",
|
|
357
|
+
'chmod 600 "$CD/.credentials.json"',
|
|
358
|
+
f'echo "{CLAUDE_INJECT_MARKER} $CD"',
|
|
359
|
+
]
|
|
360
|
+
)
|
|
@@ -207,7 +207,8 @@ class AuthSession:
|
|
|
207
207
|
self._refresh_token = sibling._refresh_token or self._refresh_token
|
|
208
208
|
return self._sts
|
|
209
209
|
self._renew_locked()
|
|
210
|
-
|
|
210
|
+
if self._sts is None:
|
|
211
|
+
raise AuthError("internal: STS credentials not populated after renew")
|
|
211
212
|
return self._sts
|
|
212
213
|
|
|
213
214
|
# -- data-plane JWT (id_token) --------------------------------------------
|
|
@@ -238,7 +239,8 @@ class AuthSession:
|
|
|
238
239
|
self._access_token = sibling._access_token or self._access_token
|
|
239
240
|
return self._id_token
|
|
240
241
|
self._refresh_id_token_locked()
|
|
241
|
-
|
|
242
|
+
if self._id_token is None:
|
|
243
|
+
raise AuthError("internal: id_token not populated after renew")
|
|
242
244
|
return self._id_token
|
|
243
245
|
|
|
244
246
|
def _refresh_id_token_locked(self) -> None:
|
{agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/client/base_agentkit_client.py
RENAMED
|
@@ -70,8 +70,13 @@ class BaseAgentkitClient(BaseServiceClient):
|
|
|
70
70
|
|
|
71
71
|
def _get(self, api_action: str, params: Dict[str, Any] = None) -> str:
|
|
72
72
|
"""Legacy method for GET requests."""
|
|
73
|
+
# Imported lazily: ``agentkit.toolkit`` pulls in ``sdk`` which imports
|
|
74
|
+
# back into ``agentkit.client``, so a module-level import would cycle
|
|
75
|
+
# (mirrors ``BaseServiceClient._invoke_api``).
|
|
76
|
+
from agentkit.toolkit.errors import ApiError
|
|
77
|
+
|
|
73
78
|
try:
|
|
74
79
|
resp = self.get(api_action, params)
|
|
75
80
|
return resp
|
|
76
81
|
except Exception as e:
|
|
77
|
-
raise
|
|
82
|
+
raise ApiError(f"Failed to {api_action}: {e}") from e
|
{agentkit_sdk_python-0.7.0 → agentkit_sdk_python-0.7.2}/agentkit/client/base_service_client.py
RENAMED
|
@@ -21,11 +21,15 @@ import json
|
|
|
21
21
|
from typing import Any, Dict, Type, TypeVar, Union, Optional
|
|
22
22
|
from dataclasses import dataclass
|
|
23
23
|
|
|
24
|
+
import requests
|
|
25
|
+
from requests.adapters import HTTPAdapter
|
|
26
|
+
from urllib3.util.retry import Retry
|
|
24
27
|
from volcengine.ApiInfo import ApiInfo
|
|
25
28
|
from volcengine.base.Service import Service
|
|
26
29
|
from volcengine.Credentials import Credentials as VolcCredentials
|
|
27
30
|
from volcengine.ServiceInfo import ServiceInfo
|
|
28
31
|
|
|
32
|
+
from agentkit.auth.errors import NetworkError
|
|
29
33
|
from agentkit.platform import (
|
|
30
34
|
VolcConfiguration,
|
|
31
35
|
resolve_credentials,
|
|
@@ -33,8 +37,12 @@ from agentkit.platform import (
|
|
|
33
37
|
)
|
|
34
38
|
from agentkit.platform.configuration import Credentials as PlatformCredentials
|
|
35
39
|
from agentkit.platform.provider import CloudProvider
|
|
40
|
+
from agentkit.utils.http_defaults import http_retries, http_timeout
|
|
41
|
+
from agentkit.utils.logging_config import get_logger
|
|
36
42
|
from agentkit.utils.ve_sign import ensure_x_custom_source_header
|
|
37
43
|
|
|
44
|
+
logger = get_logger(__name__)
|
|
45
|
+
|
|
38
46
|
T = TypeVar("T")
|
|
39
47
|
_CREDENTIAL_ERROR_TOKENS = frozenset(
|
|
40
48
|
{
|
|
@@ -158,8 +166,8 @@ class BaseServiceClient(Service):
|
|
|
158
166
|
region=self.region,
|
|
159
167
|
session_token=self.session_token or "",
|
|
160
168
|
),
|
|
161
|
-
connection_timeout=
|
|
162
|
-
socket_timeout=
|
|
169
|
+
connection_timeout=int(http_timeout()),
|
|
170
|
+
socket_timeout=int(http_timeout()),
|
|
163
171
|
scheme=self.scheme,
|
|
164
172
|
)
|
|
165
173
|
|
|
@@ -174,6 +182,38 @@ class BaseServiceClient(Service):
|
|
|
174
182
|
if self.session_token:
|
|
175
183
|
self.set_session_token(self.session_token)
|
|
176
184
|
|
|
185
|
+
self._install_retry_adapter()
|
|
186
|
+
|
|
187
|
+
def _install_retry_adapter(self) -> None:
|
|
188
|
+
"""Retry transient overload responses (429/503) and connection failures
|
|
189
|
+
with exponential backoff on the shared ``Service`` session.
|
|
190
|
+
|
|
191
|
+
Scoped to cases that mean the request was not processed, so
|
|
192
|
+
non-idempotent ``Create*`` actions are never double-executed: read
|
|
193
|
+
timeouts are not retried (``read=0``) and only 429/503 are status-
|
|
194
|
+
retried. Honors ``Retry-After``. Disabled with AGENTKIT_HTTP_RETRIES=0.
|
|
195
|
+
"""
|
|
196
|
+
retries = http_retries()
|
|
197
|
+
if retries <= 0:
|
|
198
|
+
return
|
|
199
|
+
session = getattr(self, "session", None)
|
|
200
|
+
if session is None:
|
|
201
|
+
return
|
|
202
|
+
retry = Retry(
|
|
203
|
+
total=retries,
|
|
204
|
+
connect=retries,
|
|
205
|
+
read=0,
|
|
206
|
+
status=retries,
|
|
207
|
+
status_forcelist=(429, 503),
|
|
208
|
+
allowed_methods=None, # OpenAPI calls are POST; gate by status only
|
|
209
|
+
backoff_factor=0.5,
|
|
210
|
+
respect_retry_after_header=True,
|
|
211
|
+
raise_on_status=False,
|
|
212
|
+
)
|
|
213
|
+
adapter = HTTPAdapter(max_retries=retry)
|
|
214
|
+
session.mount("https://", adapter)
|
|
215
|
+
session.mount("http://", adapter)
|
|
216
|
+
|
|
177
217
|
def _should_auto_refresh_vefaas_credentials(self) -> bool:
|
|
178
218
|
if self._explicit_credentials:
|
|
179
219
|
return False
|
|
@@ -213,7 +253,14 @@ class BaseServiceClient(Service):
|
|
|
213
253
|
creds = self._platform_config.get_vefaas_iam_credentials(force=force)
|
|
214
254
|
if not creds:
|
|
215
255
|
return False
|
|
216
|
-
|
|
256
|
+
applied = self._apply_credentials(creds)
|
|
257
|
+
if applied:
|
|
258
|
+
logger.info(
|
|
259
|
+
"Refreshed vefaas credentials (force=%s) for service %s",
|
|
260
|
+
force,
|
|
261
|
+
self.service,
|
|
262
|
+
)
|
|
263
|
+
return applied
|
|
217
264
|
|
|
218
265
|
def _is_probable_credential_error_code(self, code: str) -> bool:
|
|
219
266
|
c = (code or "").lower()
|
|
@@ -281,12 +328,18 @@ class BaseServiceClient(Service):
|
|
|
281
328
|
Typed response object
|
|
282
329
|
|
|
283
330
|
Raises:
|
|
284
|
-
|
|
331
|
+
ApiError: If the API call fails or returns an error response.
|
|
332
|
+
NetworkError: If a transport-level failure occurs.
|
|
285
333
|
"""
|
|
334
|
+
# Imported lazily: ``agentkit.toolkit`` pulls in ``sdk`` which imports
|
|
335
|
+
# back into ``agentkit.client``, so a module-level import would cycle.
|
|
336
|
+
from agentkit.toolkit.errors import ApiError
|
|
337
|
+
|
|
286
338
|
self._refresh_credentials_if_needed()
|
|
287
339
|
last_error: Optional[BaseException] = None
|
|
288
340
|
|
|
289
341
|
for attempt in (0, 1):
|
|
342
|
+
logger.debug("Invoking API %s (attempt %d)", api_action, attempt)
|
|
290
343
|
if attempt == 1:
|
|
291
344
|
self._refresh_credentials_if_needed(force=True)
|
|
292
345
|
|
|
@@ -298,16 +351,34 @@ class BaseServiceClient(Service):
|
|
|
298
351
|
request.model_dump(by_alias=True, exclude_none=True)
|
|
299
352
|
),
|
|
300
353
|
)
|
|
354
|
+
except (
|
|
355
|
+
requests.exceptions.ConnectionError,
|
|
356
|
+
requests.exceptions.Timeout,
|
|
357
|
+
requests.exceptions.HTTPError,
|
|
358
|
+
requests.exceptions.RequestException,
|
|
359
|
+
) as e:
|
|
360
|
+
# Transport-level failure: not a credential issue, surface as
|
|
361
|
+
# a typed network error so callers can distinguish it.
|
|
362
|
+
raise NetworkError(f"Failed to {api_action}: network error") from e
|
|
301
363
|
except Exception as e:
|
|
302
364
|
last_error = e
|
|
303
365
|
if attempt == 0 and self._is_probable_credential_error_text(str(e)):
|
|
366
|
+
logger.debug(
|
|
367
|
+
"Retrying %s after probable credential error", api_action
|
|
368
|
+
)
|
|
304
369
|
continue
|
|
305
|
-
raise
|
|
370
|
+
raise ApiError(f"Failed to {api_action}: {str(e)}") from e
|
|
306
371
|
|
|
307
372
|
if not res:
|
|
308
|
-
raise
|
|
373
|
+
raise ApiError(f"Empty response from {api_action} request.")
|
|
374
|
+
|
|
375
|
+
try:
|
|
376
|
+
response_data = json.loads(res)
|
|
377
|
+
except (ValueError, TypeError) as e:
|
|
378
|
+
raise ApiError(
|
|
379
|
+
f"Failed to {api_action}: malformed response body"
|
|
380
|
+
) from e
|
|
309
381
|
|
|
310
|
-
response_data = json.loads(res)
|
|
311
382
|
metadata = response_data.get("ResponseMetadata", {})
|
|
312
383
|
if metadata.get("Error"):
|
|
313
384
|
err = metadata.get("Error", {}) or {}
|
|
@@ -317,13 +388,21 @@ class BaseServiceClient(Service):
|
|
|
317
388
|
self._is_probable_credential_error_code(error_code)
|
|
318
389
|
or self._is_probable_credential_error_text(error_msg)
|
|
319
390
|
):
|
|
391
|
+
logger.debug(
|
|
392
|
+
"Retrying %s after credential error code %s",
|
|
393
|
+
api_action,
|
|
394
|
+
error_code or "<none>",
|
|
395
|
+
)
|
|
320
396
|
continue
|
|
321
|
-
raise
|
|
397
|
+
raise ApiError(
|
|
398
|
+
f"Failed to {api_action}: {error_msg}",
|
|
399
|
+
error_code=error_code or None,
|
|
400
|
+
)
|
|
322
401
|
|
|
323
402
|
return response_type(**response_data.get("Result", {}))
|
|
324
403
|
|
|
325
404
|
if last_error is not None:
|
|
326
|
-
raise
|
|
405
|
+
raise ApiError(
|
|
327
406
|
f"Failed to {api_action}: {str(last_error)}"
|
|
328
407
|
) from last_error
|
|
329
|
-
raise
|
|
408
|
+
raise ApiError(f"Failed to {api_action}: Unknown error")
|