qoder-agent-sdk 1.0.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.
- qoder_agent_sdk-1.0.0/.gitignore +58 -0
- qoder_agent_sdk-1.0.0/LICENSE +7 -0
- qoder_agent_sdk-1.0.0/PKG-INFO +355 -0
- qoder_agent_sdk-1.0.0/README.md +317 -0
- qoder_agent_sdk-1.0.0/pyproject.toml +111 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/__init__.py +954 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_bundled/.gitignore +3 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_cli_version.py +3 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_errors.py +117 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/__init__.py +1 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/auth_helpers.py +39 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/client.py +162 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/cloud_agent.py +1406 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/mcp_handler.py +145 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/mcp_serialize.py +58 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/message_parser.py +312 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/query.py +1619 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/sdk_mcp_transport.py +63 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/session_mutations.py +666 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/sessions.py +1076 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/transport/__init__.py +68 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/transport/subprocess_cli.py +992 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_version.py +3 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/auth.py +146 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/client.py +818 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/py.typed +0 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/query.py +138 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/settings.py +57 -0
- qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/types.py +2490 -0
- qoder_agent_sdk-1.0.0/tests/__init__.py +1 -0
- qoder_agent_sdk-1.0.0/tests/_shared/__init__.py +1 -0
- qoder_agent_sdk-1.0.0/tests/_shared/dotenv.py +34 -0
- qoder_agent_sdk-1.0.0/tests/_shared/e2e.py +287 -0
- qoder_agent_sdk-1.0.0/tests/_shared/e2e_env.py +86 -0
- qoder_agent_sdk-1.0.0/tests/_shared/fake_qodercli.py +275 -0
- qoder_agent_sdk-1.0.0/tests/agents/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/agents/conftest.py +32 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_description.py +267 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_disallowed_tools.py +307 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_effort.py +390 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_initial_prompt.py +263 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_max_turns.py +242 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_mcp_servers.py +275 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_model.py +661 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_permission_mode.py +316 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_prompt.py +251 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_skills.py +276 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_agent_tools.py +319 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_disallowed_tools_empty.py +201 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_effort_max.py +235 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_empty_agents.py +189 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_initial_prompt_empty.py +206 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_many_agents.py +220 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_max_turns_zero.py +231 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_multi_agent_task_isolation.py +226 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_permission_mode_default.py +235 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_tools_empty.py +235 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_tools_non_existent.py +191 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_boundary_unregistered_session_agent.py +191 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_register_custom_subagent.py +238 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_session_agent.py +192 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_session_agent_from_sdk_agents.py +218 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_subagent_isolated_context.py +242 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_subagent_tool_call_agent_selection.py +255 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_subagent_tool_call_prompt.py +247 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_subagent_tool_call_timeout.py +229 -0
- qoder_agent_sdk-1.0.0/tests/agents/test_supported_agents_list.py +218 -0
- qoder_agent_sdk-1.0.0/tests/auth/contract/test_subprocess_auth.py +387 -0
- qoder_agent_sdk-1.0.0/tests/auth/e2e/test_access_token_auth.py +169 -0
- qoder_agent_sdk-1.0.0/tests/auth/e2e/test_job_token_auth.py +180 -0
- qoder_agent_sdk-1.0.0/tests/auth/e2e/test_qodercli_auth.py +70 -0
- qoder_agent_sdk-1.0.0/tests/auth/unit/test_auth.py +320 -0
- qoder_agent_sdk-1.0.0/tests/auth/unit/test_dotenv.py +52 -0
- qoder_agent_sdk-1.0.0/tests/cloud_agent/__init__.py +1 -0
- qoder_agent_sdk-1.0.0/tests/cloud_agent/functional/__init__.py +1 -0
- qoder_agent_sdk-1.0.0/tests/cloud_agent/functional/_helpers.py +96 -0
- qoder_agent_sdk-1.0.0/tests/cloud_agent/functional/test_client_multi_turn_session.py +107 -0
- qoder_agent_sdk-1.0.0/tests/cloud_agent/functional/test_create_agent_session_stream.py +86 -0
- qoder_agent_sdk-1.0.0/tests/cloud_agent/functional/test_multi_turn_session.py +112 -0
- qoder_agent_sdk-1.0.0/tests/cloud_agent/test_cloud_agent_query.py +777 -0
- qoder_agent_sdk-1.0.0/tests/conftest.py +4 -0
- qoder_agent_sdk-1.0.0/tests/hooks/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/hooks/conftest.py +20 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_compact.py +220 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_config_change.py +235 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_cwd_changed.py +168 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_decision_merge.py +211 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_elicitation.py +26 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_elicitation_result.py +26 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_file_changed.py +207 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_hooks_e2e.py +961 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_instructions_loaded.py +194 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_notification.py +134 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_permission_denied.py +139 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_permission_request.py +195 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_post_tool_use.py +344 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_post_tool_use_failure.py +143 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_pre_tool_use.py +553 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_session_end.py +165 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_session_start.py +203 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_setup.py +27 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_stop.py +171 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_stop_failure.py +143 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_subagent.py +255 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_task_completed.py +167 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_task_created.py +155 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_teammate_idle.py +23 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_user_prompt_submit.py +195 -0
- qoder_agent_sdk-1.0.0/tests/hooks/functional/test_worktree.py +37 -0
- qoder_agent_sdk-1.0.0/tests/permissions/__init__.py +1 -0
- qoder_agent_sdk-1.0.0/tests/permissions/_e2e.py +18 -0
- qoder_agent_sdk-1.0.0/tests/permissions/test_can_use_tool.py +270 -0
- qoder_agent_sdk-1.0.0/tests/permissions/test_client_and_streaming.py +49 -0
- qoder_agent_sdk-1.0.0/tests/permissions/test_external_prompt_tool.py +251 -0
- qoder_agent_sdk-1.0.0/tests/permissions/test_options_and_modes.py +181 -0
- qoder_agent_sdk-1.0.0/tests/permissions/test_permission_modes.py +131 -0
- qoder_agent_sdk-1.0.0/tests/permissions/test_permission_request_hook_allow_skips_can_use_tool.py +102 -0
- qoder_agent_sdk-1.0.0/tests/permissions/test_permission_request_hook_deny_fires_denied.py +110 -0
- qoder_agent_sdk-1.0.0/tests/permissions/test_permission_updates.py +445 -0
- qoder_agent_sdk-1.0.0/tests/permissions/test_settings_and_mcp_policy.py +455 -0
- qoder_agent_sdk-1.0.0/tests/permissions/test_streaming_async_iterable_can_use_tool.py +94 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/conftest.py +38 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_bogus_plugin_dir.py +59 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_broken_plugin_content.py +81 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_local_plugin_init.py +87 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_multiple_plugin_dirs.py +84 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_plugin_contributes_resources.py +112 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_reload_plugins_commands.py +122 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_reload_plugins_error_count.py +89 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_reload_plugins_response_shape.py +48 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/unit/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/unit/test_plugin_dir_argv.py +68 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/unit/test_reload_plugins_control_request.py +112 -0
- qoder_agent_sdk-1.0.0/tests/plugins_loading_control/unit/test_settings_passthrough.py +97 -0
- qoder_agent_sdk-1.0.0/tests/query_io/test_at_file_reference.py +89 -0
- qoder_agent_sdk-1.0.0/tests/query_io/test_client_multi_turn_io.py +47 -0
- qoder_agent_sdk-1.0.0/tests/query_io/test_compact_context.py +109 -0
- qoder_agent_sdk-1.0.0/tests/query_io/test_multimodal_content_blocks.py +63 -0
- qoder_agent_sdk-1.0.0/tests/query_io/test_partial_stream_events.py +42 -0
- qoder_agent_sdk-1.0.0/tests/query_io/test_query_stream_turns_io.py +81 -0
- qoder_agent_sdk-1.0.0/tests/query_io/test_server_output_style_info.py +30 -0
- qoder_agent_sdk-1.0.0/tests/query_io/test_stream_user_message_io.py +91 -0
- qoder_agent_sdk-1.0.0/tests/query_io/test_string_prompt_io.py +94 -0
- qoder_agent_sdk-1.0.0/tests/query_io/test_system_prompt.py +163 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/conftest.py +79 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/fixtures/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/fixtures/elicit_mcp_server.py +152 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/fixtures/fake_oauth_mcp_server.py +399 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/fixtures/minimal_mcp_server.py +95 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/fixtures/sse_mcp_server.py +198 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_allowed_mcp_server_names_exempts_sdk.py +63 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_allowed_mcp_server_names_filters_stdio.py +69 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_control_request_timeout_does_not_poison_runner.py +103 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_elicitation_hook_probe.py +192 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_elicitation_result_hook_probe.py +157 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_elicitation_url_mode_unsupported.py +144 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_http_server_public_deepwiki.py +59 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_http_sse_bogus_url_not_crashing.py +74 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_mcp_server_status_metadata_fields.py +103 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_mcp_server_status_point_in_time_snapshot.py +71 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_mcp_status_empty_when_no_servers.py +41 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_mixed_inprocess_and_stdio_servers.py +82 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_mixed_three_way_transports.py +127 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_authenticate_custom_redirect_uri.py +80 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_authenticate_returns_url_with_dcr.py +82 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_authenticate_silent_refresh.py +110 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_clear_auth_resets_to_needs_auth.py +87 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_inject_token_connects.py +92 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_needs_auth_status.py +67 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_submit_callback_completes_flow.py +110 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_token_persists_across_sessions.py +139 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_permission_prompt_tool_probe.py +160 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_annotations_not_echoed_in_status.py +100 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_close_tears_down_transport.py +71 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_multi_turn_reuse.py +108 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_multiple_servers_isolated.py +71 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_server_connected_status.py +77 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_tool_description_passthrough.py +67 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_server_name_special_chars_prefix.py +58 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sse_server_headers_and_connection.py +130 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_stdio_grandchild_reclaim_on_close.py +114 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_stdio_server_lifecycle.py +135 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_strict_mcp_config_blocks_external_config.py +90 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_cli_args_allowed_mcp_server_names.py +35 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_cli_args_mcp_config.py +102 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_cli_args_permission_prompt_tool.py +28 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_cli_args_strict_mcp_config.py +26 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_create_sdk_mcp_server.py +78 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_handler_accepts_extra_helper.py +64 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_inbound_elicitation_callback.py +217 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_inbound_elicitation_default_cancel.py +73 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_inbound_get_model_policy.py +138 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_mcp_authenticate_response_variants.py +136 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_mcp_server_status_request.py +113 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_mcp_server_status_timeout.py +131 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_mcp_toggle_and_reconnect_requests.py +87 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_sdk_mcp_handler_extra_signal.py +190 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_sdk_mcp_handler_non_content_normalization.py +84 -0
- qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_sdk_server_split_from_process_servers.py +92 -0
- qoder_agent_sdk-1.0.0/tests/query_model_policy/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/query_model_policy/functional/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/query_model_policy/functional/conftest.py +25 -0
- qoder_agent_sdk-1.0.0/tests/query_model_policy/functional/test_model_policy_e2e.py +704 -0
- qoder_agent_sdk-1.0.0/tests/query_model_policy/functional/test_model_selection_e2e_logging.py +340 -0
- qoder_agent_sdk-1.0.0/tests/query_model_policy/functional/test_model_selection_logging.py +610 -0
- qoder_agent_sdk-1.0.0/tests/query_model_policy/unit/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/query_model_policy/unit/test_list_byok_providers.py +193 -0
- qoder_agent_sdk-1.0.0/tests/query_model_policy/unit/test_pull_suppresses_model_flag.py +1072 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/__init__.py +1 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/conftest.py +168 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_capture_checkpoint_uuid_from_stream.py +40 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_enable_file_checkpointing.py +41 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_mid_stream_rewind.py +51 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_multiple_checkpoints_rewind.py +53 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_replay_user_messages_checkpoint_uuid.py +43 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_resume_session_rewind.py +56 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_bash_changes_not_tracked.py +62 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_cross_session_rejected.py +55 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_directory_ops_not_undone.py +47 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_dry_run_with_checkpoint.py +41 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_files_success.py +41 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_local_files_only.py +64 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_malformed_message_id.py +37 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_preserves_conversation.py +56 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_stats.py +51 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_unknown_message.py +40 -0
- qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_without_checkpointing.py +40 -0
- qoder_agent_sdk-1.0.0/tests/session_control/test_continue_latest_session.py +132 -0
- qoder_agent_sdk-1.0.0/tests/session_control/test_fork_session.py +160 -0
- qoder_agent_sdk-1.0.0/tests/session_control/test_new_client_session.py +53 -0
- qoder_agent_sdk-1.0.0/tests/session_control/test_new_query_session.py +53 -0
- qoder_agent_sdk-1.0.0/tests/session_control/test_new_session_with_session_id.py +149 -0
- qoder_agent_sdk-1.0.0/tests/session_control/test_resume_session.py +143 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/conftest.py +41 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_agent_preloaded_skills.py +61 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_builtin_skills_visibility.py +93 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_default_skills_policy.py +50 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_enable_all_skills.py +40 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_enable_named_skills.py +35 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_plugin_skill_in_init.py +87 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_settings_skill_overrides.py +114 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/unit/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/skills_loading_control/unit/test_skills_argv.py +114 -0
- qoder_agent_sdk-1.0.0/tests/test_build_wheel.py +86 -0
- qoder_agent_sdk-1.0.0/tests/test_client.py +322 -0
- qoder_agent_sdk-1.0.0/tests/test_control_request_timeout.py +230 -0
- qoder_agent_sdk-1.0.0/tests/test_download_cli.py +132 -0
- qoder_agent_sdk-1.0.0/tests/test_errors.py +52 -0
- qoder_agent_sdk-1.0.0/tests/test_integration.py +308 -0
- qoder_agent_sdk-1.0.0/tests/test_mcp_dynamic.py +279 -0
- qoder_agent_sdk-1.0.0/tests/test_mcp_large_output.py +335 -0
- qoder_agent_sdk-1.0.0/tests/test_mcp_oauth.py +434 -0
- qoder_agent_sdk-1.0.0/tests/test_message_parser.py +927 -0
- qoder_agent_sdk-1.0.0/tests/test_permission_alignment.py +734 -0
- qoder_agent_sdk-1.0.0/tests/test_query.py +943 -0
- qoder_agent_sdk-1.0.0/tests/test_rate_limit_event_repro.py +108 -0
- qoder_agent_sdk-1.0.0/tests/test_sdk_mcp_integration.py +1093 -0
- qoder_agent_sdk-1.0.0/tests/test_sdk_mcp_routing.py +348 -0
- qoder_agent_sdk-1.0.0/tests/test_session_mutations.py +794 -0
- qoder_agent_sdk-1.0.0/tests/test_sessions.py +1556 -0
- qoder_agent_sdk-1.0.0/tests/test_streaming_client.py +1316 -0
- qoder_agent_sdk-1.0.0/tests/test_subprocess_buffering.py +385 -0
- qoder_agent_sdk-1.0.0/tests/test_tool_callbacks.py +1070 -0
- qoder_agent_sdk-1.0.0/tests/test_transport.py +1784 -0
- qoder_agent_sdk-1.0.0/tests/test_types.py +597 -0
- qoder_agent_sdk-1.0.0/tests/tools/__init__.py +0 -0
- qoder_agent_sdk-1.0.0/tests/tools/conftest.py +71 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_allowedTools_disallowedTools_conflict_priority.py +45 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_canUseTool_throws_error.py +53 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_concurrent_multiple_tool_uses.py +60 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_createSdkMcpServer_many_tools.py +45 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_handler_long_running_vs_controlRequestTimeoutMs.py +46 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_handler_returns_large_content.py +41 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_handler_returns_malformed_result.py +39 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_handler_returns_undefined.py +39 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_model_calls_unknown_tool_functional.py +39 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_tool_input_deeply_nested_schema.py +78 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_boundary_tool_input_many_fields.py +67 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_createSdkMcpServer_empty_tools.py +67 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_createSdkMcpServer_mcpServers_option.py +40 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_createSdkMcpServer_multiple_tools.py +51 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_createSdkMcpServer_name_routes_tool.py +69 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_createSdkMcpServer_version.py +38 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_error_handler_isError_true.py +66 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_error_handler_isError_with_structured_data.py +56 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_error_handler_throws_async_rejection.py +51 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_error_handler_throws_non_Error.py +46 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_error_handler_throws_sync_Error.py +47 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_error_isError_allows_agent_retry.py +65 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_allowedTools_permits_mcp_tool.py +44 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_allowedTools_server_pattern.py +46 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_allow_passthrough.py +69 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_conditional_on_input.py +95 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_deny.py +73 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_deny_with_interrupt.py +72 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_receives_mcp_toolName_format.py +56 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_updatedInput.py +79 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_updatedPermissions.py +73 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_disallowedTools_blocks_tool.py +48 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_mode_bypassPermissions_with_mcp_tool.py +44 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_postToolUse_hook_additionalContext.py +57 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_permission_preToolUse_hook_updatedInput.py +66 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_return_empty_content_array.py +49 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_return_image_content.py +45 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_return_multiple_content_blocks.py +62 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_return_text_content.py +81 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_tool_destructiveHint.py +50 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_tool_handler_receives_args_and_returns_content.py +94 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_tool_input_schema_describe.py +54 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_tool_input_schema_nested.py +113 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_tool_input_schema_zod_shape.py +49 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_tool_name_and_description.py +44 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_tool_openWorldHint.py +49 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_tool_readOnlyHint.py +48 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_unit_createSdkMcpServer.py +102 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_unit_createSdkMcpServer_duplicate_tool_name.py +20 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_unit_createSdkMcpServer_empty_server_name.py +17 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_unit_createSdkMcpServer_empty_tool_description.py +16 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_unit_createSdkMcpServer_empty_tool_name.py +27 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_unit_mcp_handler.py +224 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_unit_sdk_mcp_transport.py +80 -0
- qoder_agent_sdk-1.0.0/tests/tools/test_unit_tool_helper.py +79 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
MANIFEST
|
|
23
|
+
|
|
24
|
+
# Virtual environments
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
env/
|
|
28
|
+
.venv
|
|
29
|
+
.venv-release/
|
|
30
|
+
uv.lock
|
|
31
|
+
|
|
32
|
+
# IDEs
|
|
33
|
+
.vscode/
|
|
34
|
+
.idea/
|
|
35
|
+
*.swp
|
|
36
|
+
*.swo
|
|
37
|
+
*~
|
|
38
|
+
**/.DS_Store
|
|
39
|
+
|
|
40
|
+
# Local test credentials
|
|
41
|
+
.env
|
|
42
|
+
.env.local
|
|
43
|
+
|
|
44
|
+
# Testing
|
|
45
|
+
.tox/
|
|
46
|
+
.coverage
|
|
47
|
+
.coverage.*
|
|
48
|
+
.cache
|
|
49
|
+
.pytest_cache/
|
|
50
|
+
htmlcov/
|
|
51
|
+
|
|
52
|
+
# Type checking
|
|
53
|
+
.mypy_cache/
|
|
54
|
+
.dmypy.json
|
|
55
|
+
dmypy.json
|
|
56
|
+
.pyre/
|
|
57
|
+
.qoder/worktrees/
|
|
58
|
+
test-reports/
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qoder-agent-sdk
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python SDK for Qoder Agent
|
|
5
|
+
Author: Qoder
|
|
6
|
+
License: Copyright (c) 2026 Qoder
|
|
7
|
+
|
|
8
|
+
Use of this software is governed by the Qoder Product Service Terms:
|
|
9
|
+
|
|
10
|
+
https://qoder.com/product-service
|
|
11
|
+
|
|
12
|
+
By installing or using this package, you agree to those terms.
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Keywords: agent,ai,qoder,sdk
|
|
15
|
+
Classifier: Development Status :: 3 - Alpha
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: Other/Proprietary License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: anyio>=4.0.0
|
|
26
|
+
Requires-Dist: mcp>=0.1.0
|
|
27
|
+
Requires-Dist: typing-extensions>=4.0.0; python_version < '3.11'
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: anyio[trio]>=4.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.20.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-timeout>=2.0.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: python-dotenv>=1.0.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# Qoder Agent SDK for Python
|
|
40
|
+
|
|
41
|
+
Python SDK for building applications on top of Qoder Agent.
|
|
42
|
+
|
|
43
|
+
The SDK starts `qodercli` for you, streams agent messages back to Python, and
|
|
44
|
+
lets your application configure tools, permissions, working directories, MCP
|
|
45
|
+
servers, hooks, and interactive sessions.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install qoder-agent-sdk
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Prerequisites:
|
|
54
|
+
|
|
55
|
+
- Python 3.10+
|
|
56
|
+
- A Qoder account or another authentication method supported by your host
|
|
57
|
+
application
|
|
58
|
+
|
|
59
|
+
## CLI Behavior
|
|
60
|
+
|
|
61
|
+
Published platform wheels include a bundled `qodercli`, so a separate CLI
|
|
62
|
+
installation is not required for normal SDK use. If you prefer to use a
|
|
63
|
+
system-wide CLI or a pinned local build, pass `QoderAgentOptions(cli_path=...)`.
|
|
64
|
+
|
|
65
|
+
## Authentication
|
|
66
|
+
|
|
67
|
+
Every SDK query needs an explicit authentication option.
|
|
68
|
+
|
|
69
|
+
To reuse the local `qodercli` login state:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from qoder_agent_sdk import QoderAgentOptions, qodercli_auth
|
|
73
|
+
|
|
74
|
+
options = QoderAgentOptions(auth=qodercli_auth())
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
To authenticate with a personal access token:
|
|
78
|
+
|
|
79
|
+
Generate a Personal Access Token at
|
|
80
|
+
[qoder.com/account/integrations](https://qoder.com/account/integrations):
|
|
81
|
+
|
|
82
|
+
1. Sign in to your Qoder account.
|
|
83
|
+
2. Open the integrations page.
|
|
84
|
+
3. Create a new PAT, choosing the expiry and scopes you need.
|
|
85
|
+
4. Copy the token immediately. The value cannot be retrieved again after the
|
|
86
|
+
page is closed.
|
|
87
|
+
|
|
88
|
+
Use separate tokens for local scripts, CI, and production services when
|
|
89
|
+
possible, so each environment can be revoked independently. Do not hard-code
|
|
90
|
+
tokens in source code.
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from qoder_agent_sdk import QoderAgentOptions, access_token_from_env
|
|
94
|
+
|
|
95
|
+
options = QoderAgentOptions(auth=access_token_from_env())
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`access_token_from_env()` reads `QODER_PERSONAL_ACCESS_TOKEN` by default.
|
|
99
|
+
|
|
100
|
+
## Quick Start
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
import anyio
|
|
104
|
+
from qoder_agent_sdk import QoderAgentOptions, qodercli_auth, query
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
async def main() -> None:
|
|
108
|
+
options = QoderAgentOptions(auth=qodercli_auth())
|
|
109
|
+
|
|
110
|
+
async for message in query(
|
|
111
|
+
prompt="What is 2 + 2?",
|
|
112
|
+
options=options,
|
|
113
|
+
):
|
|
114
|
+
print(message)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
anyio.run(main)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Basic Usage
|
|
121
|
+
|
|
122
|
+
`query()` runs a single SDK query and returns an async iterator of response
|
|
123
|
+
messages.
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from qoder_agent_sdk import (
|
|
127
|
+
AssistantMessage,
|
|
128
|
+
QoderAgentOptions,
|
|
129
|
+
TextBlock,
|
|
130
|
+
qodercli_auth,
|
|
131
|
+
query,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
options = QoderAgentOptions(
|
|
135
|
+
auth=qodercli_auth(),
|
|
136
|
+
system_prompt="You are a helpful assistant.",
|
|
137
|
+
max_turns=1,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
async for message in query(prompt="Explain this repository", options=options):
|
|
141
|
+
if isinstance(message, AssistantMessage):
|
|
142
|
+
for block in message.content:
|
|
143
|
+
if isinstance(block, TextBlock):
|
|
144
|
+
print(block.text)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Tools and Permissions
|
|
148
|
+
|
|
149
|
+
Qoder Agent can use tools such as file reads, file edits, shell commands, and
|
|
150
|
+
MCP tools. `allowed_tools` is an approval allowlist: listed tools are
|
|
151
|
+
auto-approved, while unlisted tools continue through `permission_mode` and
|
|
152
|
+
`can_use_tool` for a decision. It does not remove tools from the agent's
|
|
153
|
+
available toolset. To block tools, use `disallowed_tools`.
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
from qoder_agent_sdk import QoderAgentOptions, qodercli_auth, query
|
|
157
|
+
|
|
158
|
+
options = QoderAgentOptions(
|
|
159
|
+
auth=qodercli_auth(),
|
|
160
|
+
allowed_tools=["Read", "Edit"],
|
|
161
|
+
disallowed_tools=["Bash"],
|
|
162
|
+
permission_mode="acceptEdits",
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
async for message in query(
|
|
166
|
+
prompt="Update the README introduction.",
|
|
167
|
+
options=options,
|
|
168
|
+
):
|
|
169
|
+
print(message)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
For application-specific approval flows, provide `can_use_tool`:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from qoder_agent_sdk import (
|
|
176
|
+
PermissionResultAllow,
|
|
177
|
+
PermissionResultDeny,
|
|
178
|
+
QoderAgentOptions,
|
|
179
|
+
ToolPermissionContext,
|
|
180
|
+
qodercli_auth,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
async def can_use_tool(
|
|
185
|
+
tool_name: str,
|
|
186
|
+
tool_input: dict,
|
|
187
|
+
context: ToolPermissionContext,
|
|
188
|
+
):
|
|
189
|
+
if tool_name == "Bash":
|
|
190
|
+
return PermissionResultDeny(message="Shell commands are disabled here.")
|
|
191
|
+
return PermissionResultAllow()
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
options = QoderAgentOptions(
|
|
195
|
+
auth=qodercli_auth(),
|
|
196
|
+
can_use_tool=can_use_tool,
|
|
197
|
+
)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Working Directory
|
|
201
|
+
|
|
202
|
+
Use `cwd` to run the agent in a specific project directory:
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
from pathlib import Path
|
|
206
|
+
|
|
207
|
+
from qoder_agent_sdk import QoderAgentOptions, qodercli_auth
|
|
208
|
+
|
|
209
|
+
options = QoderAgentOptions(
|
|
210
|
+
auth=qodercli_auth(),
|
|
211
|
+
cwd=Path("/path/to/project"),
|
|
212
|
+
)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Interactive Sessions
|
|
216
|
+
|
|
217
|
+
Use `QoderSDKClient` when you need a long-lived, bidirectional session instead
|
|
218
|
+
of a single `query()` call.
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
from qoder_agent_sdk import QoderAgentOptions, QoderSDKClient, qodercli_auth
|
|
222
|
+
|
|
223
|
+
options = QoderAgentOptions(auth=qodercli_auth())
|
|
224
|
+
|
|
225
|
+
async with QoderSDKClient(options=options) as client:
|
|
226
|
+
await client.query("Inspect this project and summarize the main modules.")
|
|
227
|
+
|
|
228
|
+
async for message in client.receive_response():
|
|
229
|
+
print(message)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`QoderSDKClient` is useful for chat interfaces, follow-up prompts, interrupts,
|
|
233
|
+
runtime permission changes, MCP server management, and other workflows that need
|
|
234
|
+
state across multiple turns.
|
|
235
|
+
|
|
236
|
+
## Custom Tools
|
|
237
|
+
|
|
238
|
+
You can expose Python functions to Qoder Agent as in-process SDK MCP servers.
|
|
239
|
+
This avoids managing a separate MCP subprocess for simple application-local
|
|
240
|
+
tools.
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
from qoder_agent_sdk import (
|
|
244
|
+
QoderAgentOptions,
|
|
245
|
+
QoderSDKClient,
|
|
246
|
+
create_sdk_mcp_server,
|
|
247
|
+
qodercli_auth,
|
|
248
|
+
tool,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@tool("greet", "Greet a user", {"name": str})
|
|
253
|
+
async def greet_user(args):
|
|
254
|
+
return {
|
|
255
|
+
"content": [
|
|
256
|
+
{"type": "text", "text": f"Hello, {args['name']}!"}
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
server = create_sdk_mcp_server(
|
|
262
|
+
name="my-tools",
|
|
263
|
+
version="1.0.0",
|
|
264
|
+
tools=[greet_user],
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
options = QoderAgentOptions(
|
|
268
|
+
auth=qodercli_auth(),
|
|
269
|
+
mcp_servers={"tools": server},
|
|
270
|
+
allowed_tools=["mcp__tools__greet"],
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
async with QoderSDKClient(options=options) as client:
|
|
274
|
+
await client.query("Greet Alice.")
|
|
275
|
+
async for message in client.receive_response():
|
|
276
|
+
print(message)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Hooks
|
|
280
|
+
|
|
281
|
+
Hooks are deterministic Python callbacks invoked at specific points in the
|
|
282
|
+
agent loop. They are useful for validation, policy checks, logging, and
|
|
283
|
+
application-specific feedback.
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from qoder_agent_sdk import HookMatcher, QoderAgentOptions, qodercli_auth
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
async def block_script(input_data, tool_use_id, context):
|
|
290
|
+
if input_data["tool_name"] != "Bash":
|
|
291
|
+
return {}
|
|
292
|
+
|
|
293
|
+
command = input_data["tool_input"].get("command", "")
|
|
294
|
+
if "./deploy.sh" in command:
|
|
295
|
+
return {
|
|
296
|
+
"hookSpecificOutput": {
|
|
297
|
+
"hookEventName": "PreToolUse",
|
|
298
|
+
"permissionDecision": "deny",
|
|
299
|
+
"permissionDecisionReason": "Deployment scripts require review.",
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return {}
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
options = QoderAgentOptions(
|
|
306
|
+
auth=qodercli_auth(),
|
|
307
|
+
hooks={
|
|
308
|
+
"PreToolUse": [
|
|
309
|
+
HookMatcher(matcher="Bash", hooks=[block_script]),
|
|
310
|
+
],
|
|
311
|
+
},
|
|
312
|
+
)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Error Handling
|
|
316
|
+
|
|
317
|
+
```python
|
|
318
|
+
from qoder_agent_sdk import (
|
|
319
|
+
CLIConnectionError,
|
|
320
|
+
CLIJSONDecodeError,
|
|
321
|
+
CLINotFoundError,
|
|
322
|
+
ProcessError,
|
|
323
|
+
QoderAgentOptions,
|
|
324
|
+
QoderSDKError,
|
|
325
|
+
qodercli_auth,
|
|
326
|
+
query,
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
try:
|
|
330
|
+
async for message in query(
|
|
331
|
+
prompt="Hello Qoder",
|
|
332
|
+
options=QoderAgentOptions(auth=qodercli_auth()),
|
|
333
|
+
):
|
|
334
|
+
print(message)
|
|
335
|
+
except CLINotFoundError:
|
|
336
|
+
print("qodercli was not found. Install a platform wheel or set cli_path.")
|
|
337
|
+
except CLIConnectionError as exc:
|
|
338
|
+
print(f"Connection failed: {exc}")
|
|
339
|
+
except ProcessError as exc:
|
|
340
|
+
print(f"qodercli exited with code {exc.exit_code}")
|
|
341
|
+
except CLIJSONDecodeError as exc:
|
|
342
|
+
print(f"Could not parse qodercli output: {exc}")
|
|
343
|
+
except QoderSDKError as exc:
|
|
344
|
+
print(f"SDK error: {exc}")
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## License and Terms
|
|
348
|
+
|
|
349
|
+
Copyright (c) 2026 Qoder
|
|
350
|
+
|
|
351
|
+
Use of this software is governed by the Qoder Product Service Terms:
|
|
352
|
+
|
|
353
|
+
https://qoder.com/product-service
|
|
354
|
+
|
|
355
|
+
By installing or using this package, you agree to those terms.
|