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.
Files changed (328) hide show
  1. qoder_agent_sdk-1.0.0/.gitignore +58 -0
  2. qoder_agent_sdk-1.0.0/LICENSE +7 -0
  3. qoder_agent_sdk-1.0.0/PKG-INFO +355 -0
  4. qoder_agent_sdk-1.0.0/README.md +317 -0
  5. qoder_agent_sdk-1.0.0/pyproject.toml +111 -0
  6. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/__init__.py +954 -0
  7. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_bundled/.gitignore +3 -0
  8. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_cli_version.py +3 -0
  9. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_errors.py +117 -0
  10. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/__init__.py +1 -0
  11. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/auth_helpers.py +39 -0
  12. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/client.py +162 -0
  13. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/cloud_agent.py +1406 -0
  14. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/mcp_handler.py +145 -0
  15. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/mcp_serialize.py +58 -0
  16. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/message_parser.py +312 -0
  17. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/query.py +1619 -0
  18. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/sdk_mcp_transport.py +63 -0
  19. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/session_mutations.py +666 -0
  20. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/sessions.py +1076 -0
  21. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/transport/__init__.py +68 -0
  22. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_internal/transport/subprocess_cli.py +992 -0
  23. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/_version.py +3 -0
  24. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/auth.py +146 -0
  25. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/client.py +818 -0
  26. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/py.typed +0 -0
  27. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/query.py +138 -0
  28. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/settings.py +57 -0
  29. qoder_agent_sdk-1.0.0/src/qoder_agent_sdk/types.py +2490 -0
  30. qoder_agent_sdk-1.0.0/tests/__init__.py +1 -0
  31. qoder_agent_sdk-1.0.0/tests/_shared/__init__.py +1 -0
  32. qoder_agent_sdk-1.0.0/tests/_shared/dotenv.py +34 -0
  33. qoder_agent_sdk-1.0.0/tests/_shared/e2e.py +287 -0
  34. qoder_agent_sdk-1.0.0/tests/_shared/e2e_env.py +86 -0
  35. qoder_agent_sdk-1.0.0/tests/_shared/fake_qodercli.py +275 -0
  36. qoder_agent_sdk-1.0.0/tests/agents/__init__.py +0 -0
  37. qoder_agent_sdk-1.0.0/tests/agents/conftest.py +32 -0
  38. qoder_agent_sdk-1.0.0/tests/agents/test_agent_description.py +267 -0
  39. qoder_agent_sdk-1.0.0/tests/agents/test_agent_disallowed_tools.py +307 -0
  40. qoder_agent_sdk-1.0.0/tests/agents/test_agent_effort.py +390 -0
  41. qoder_agent_sdk-1.0.0/tests/agents/test_agent_initial_prompt.py +263 -0
  42. qoder_agent_sdk-1.0.0/tests/agents/test_agent_max_turns.py +242 -0
  43. qoder_agent_sdk-1.0.0/tests/agents/test_agent_mcp_servers.py +275 -0
  44. qoder_agent_sdk-1.0.0/tests/agents/test_agent_model.py +661 -0
  45. qoder_agent_sdk-1.0.0/tests/agents/test_agent_permission_mode.py +316 -0
  46. qoder_agent_sdk-1.0.0/tests/agents/test_agent_prompt.py +251 -0
  47. qoder_agent_sdk-1.0.0/tests/agents/test_agent_skills.py +276 -0
  48. qoder_agent_sdk-1.0.0/tests/agents/test_agent_tools.py +319 -0
  49. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_disallowed_tools_empty.py +201 -0
  50. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_effort_max.py +235 -0
  51. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_empty_agents.py +189 -0
  52. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_initial_prompt_empty.py +206 -0
  53. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_many_agents.py +220 -0
  54. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_max_turns_zero.py +231 -0
  55. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_multi_agent_task_isolation.py +226 -0
  56. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_permission_mode_default.py +235 -0
  57. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_tools_empty.py +235 -0
  58. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_tools_non_existent.py +191 -0
  59. qoder_agent_sdk-1.0.0/tests/agents/test_boundary_unregistered_session_agent.py +191 -0
  60. qoder_agent_sdk-1.0.0/tests/agents/test_register_custom_subagent.py +238 -0
  61. qoder_agent_sdk-1.0.0/tests/agents/test_session_agent.py +192 -0
  62. qoder_agent_sdk-1.0.0/tests/agents/test_session_agent_from_sdk_agents.py +218 -0
  63. qoder_agent_sdk-1.0.0/tests/agents/test_subagent_isolated_context.py +242 -0
  64. qoder_agent_sdk-1.0.0/tests/agents/test_subagent_tool_call_agent_selection.py +255 -0
  65. qoder_agent_sdk-1.0.0/tests/agents/test_subagent_tool_call_prompt.py +247 -0
  66. qoder_agent_sdk-1.0.0/tests/agents/test_subagent_tool_call_timeout.py +229 -0
  67. qoder_agent_sdk-1.0.0/tests/agents/test_supported_agents_list.py +218 -0
  68. qoder_agent_sdk-1.0.0/tests/auth/contract/test_subprocess_auth.py +387 -0
  69. qoder_agent_sdk-1.0.0/tests/auth/e2e/test_access_token_auth.py +169 -0
  70. qoder_agent_sdk-1.0.0/tests/auth/e2e/test_job_token_auth.py +180 -0
  71. qoder_agent_sdk-1.0.0/tests/auth/e2e/test_qodercli_auth.py +70 -0
  72. qoder_agent_sdk-1.0.0/tests/auth/unit/test_auth.py +320 -0
  73. qoder_agent_sdk-1.0.0/tests/auth/unit/test_dotenv.py +52 -0
  74. qoder_agent_sdk-1.0.0/tests/cloud_agent/__init__.py +1 -0
  75. qoder_agent_sdk-1.0.0/tests/cloud_agent/functional/__init__.py +1 -0
  76. qoder_agent_sdk-1.0.0/tests/cloud_agent/functional/_helpers.py +96 -0
  77. qoder_agent_sdk-1.0.0/tests/cloud_agent/functional/test_client_multi_turn_session.py +107 -0
  78. qoder_agent_sdk-1.0.0/tests/cloud_agent/functional/test_create_agent_session_stream.py +86 -0
  79. qoder_agent_sdk-1.0.0/tests/cloud_agent/functional/test_multi_turn_session.py +112 -0
  80. qoder_agent_sdk-1.0.0/tests/cloud_agent/test_cloud_agent_query.py +777 -0
  81. qoder_agent_sdk-1.0.0/tests/conftest.py +4 -0
  82. qoder_agent_sdk-1.0.0/tests/hooks/__init__.py +0 -0
  83. qoder_agent_sdk-1.0.0/tests/hooks/conftest.py +20 -0
  84. qoder_agent_sdk-1.0.0/tests/hooks/functional/__init__.py +0 -0
  85. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_compact.py +220 -0
  86. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_config_change.py +235 -0
  87. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_cwd_changed.py +168 -0
  88. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_decision_merge.py +211 -0
  89. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_elicitation.py +26 -0
  90. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_elicitation_result.py +26 -0
  91. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_file_changed.py +207 -0
  92. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_hooks_e2e.py +961 -0
  93. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_instructions_loaded.py +194 -0
  94. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_notification.py +134 -0
  95. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_permission_denied.py +139 -0
  96. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_permission_request.py +195 -0
  97. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_post_tool_use.py +344 -0
  98. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_post_tool_use_failure.py +143 -0
  99. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_pre_tool_use.py +553 -0
  100. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_session_end.py +165 -0
  101. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_session_start.py +203 -0
  102. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_setup.py +27 -0
  103. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_stop.py +171 -0
  104. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_stop_failure.py +143 -0
  105. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_subagent.py +255 -0
  106. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_task_completed.py +167 -0
  107. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_task_created.py +155 -0
  108. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_teammate_idle.py +23 -0
  109. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_user_prompt_submit.py +195 -0
  110. qoder_agent_sdk-1.0.0/tests/hooks/functional/test_worktree.py +37 -0
  111. qoder_agent_sdk-1.0.0/tests/permissions/__init__.py +1 -0
  112. qoder_agent_sdk-1.0.0/tests/permissions/_e2e.py +18 -0
  113. qoder_agent_sdk-1.0.0/tests/permissions/test_can_use_tool.py +270 -0
  114. qoder_agent_sdk-1.0.0/tests/permissions/test_client_and_streaming.py +49 -0
  115. qoder_agent_sdk-1.0.0/tests/permissions/test_external_prompt_tool.py +251 -0
  116. qoder_agent_sdk-1.0.0/tests/permissions/test_options_and_modes.py +181 -0
  117. qoder_agent_sdk-1.0.0/tests/permissions/test_permission_modes.py +131 -0
  118. qoder_agent_sdk-1.0.0/tests/permissions/test_permission_request_hook_allow_skips_can_use_tool.py +102 -0
  119. qoder_agent_sdk-1.0.0/tests/permissions/test_permission_request_hook_deny_fires_denied.py +110 -0
  120. qoder_agent_sdk-1.0.0/tests/permissions/test_permission_updates.py +445 -0
  121. qoder_agent_sdk-1.0.0/tests/permissions/test_settings_and_mcp_policy.py +455 -0
  122. qoder_agent_sdk-1.0.0/tests/permissions/test_streaming_async_iterable_can_use_tool.py +94 -0
  123. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/__init__.py +0 -0
  124. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/conftest.py +38 -0
  125. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_bogus_plugin_dir.py +59 -0
  126. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_broken_plugin_content.py +81 -0
  127. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_local_plugin_init.py +87 -0
  128. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_multiple_plugin_dirs.py +84 -0
  129. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_plugin_contributes_resources.py +112 -0
  130. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_reload_plugins_commands.py +122 -0
  131. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_reload_plugins_error_count.py +89 -0
  132. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/test_reload_plugins_response_shape.py +48 -0
  133. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/unit/__init__.py +0 -0
  134. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/unit/test_plugin_dir_argv.py +68 -0
  135. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/unit/test_reload_plugins_control_request.py +112 -0
  136. qoder_agent_sdk-1.0.0/tests/plugins_loading_control/unit/test_settings_passthrough.py +97 -0
  137. qoder_agent_sdk-1.0.0/tests/query_io/test_at_file_reference.py +89 -0
  138. qoder_agent_sdk-1.0.0/tests/query_io/test_client_multi_turn_io.py +47 -0
  139. qoder_agent_sdk-1.0.0/tests/query_io/test_compact_context.py +109 -0
  140. qoder_agent_sdk-1.0.0/tests/query_io/test_multimodal_content_blocks.py +63 -0
  141. qoder_agent_sdk-1.0.0/tests/query_io/test_partial_stream_events.py +42 -0
  142. qoder_agent_sdk-1.0.0/tests/query_io/test_query_stream_turns_io.py +81 -0
  143. qoder_agent_sdk-1.0.0/tests/query_io/test_server_output_style_info.py +30 -0
  144. qoder_agent_sdk-1.0.0/tests/query_io/test_stream_user_message_io.py +91 -0
  145. qoder_agent_sdk-1.0.0/tests/query_io/test_string_prompt_io.py +94 -0
  146. qoder_agent_sdk-1.0.0/tests/query_io/test_system_prompt.py +163 -0
  147. qoder_agent_sdk-1.0.0/tests/query_mcp/__init__.py +0 -0
  148. qoder_agent_sdk-1.0.0/tests/query_mcp/conftest.py +79 -0
  149. qoder_agent_sdk-1.0.0/tests/query_mcp/fixtures/__init__.py +0 -0
  150. qoder_agent_sdk-1.0.0/tests/query_mcp/fixtures/elicit_mcp_server.py +152 -0
  151. qoder_agent_sdk-1.0.0/tests/query_mcp/fixtures/fake_oauth_mcp_server.py +399 -0
  152. qoder_agent_sdk-1.0.0/tests/query_mcp/fixtures/minimal_mcp_server.py +95 -0
  153. qoder_agent_sdk-1.0.0/tests/query_mcp/fixtures/sse_mcp_server.py +198 -0
  154. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/__init__.py +0 -0
  155. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_allowed_mcp_server_names_exempts_sdk.py +63 -0
  156. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_allowed_mcp_server_names_filters_stdio.py +69 -0
  157. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_control_request_timeout_does_not_poison_runner.py +103 -0
  158. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_elicitation_hook_probe.py +192 -0
  159. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_elicitation_result_hook_probe.py +157 -0
  160. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_elicitation_url_mode_unsupported.py +144 -0
  161. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_http_server_public_deepwiki.py +59 -0
  162. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_http_sse_bogus_url_not_crashing.py +74 -0
  163. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_mcp_server_status_metadata_fields.py +103 -0
  164. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_mcp_server_status_point_in_time_snapshot.py +71 -0
  165. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_mcp_status_empty_when_no_servers.py +41 -0
  166. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_mixed_inprocess_and_stdio_servers.py +82 -0
  167. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_mixed_three_way_transports.py +127 -0
  168. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_authenticate_custom_redirect_uri.py +80 -0
  169. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_authenticate_returns_url_with_dcr.py +82 -0
  170. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_authenticate_silent_refresh.py +110 -0
  171. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_clear_auth_resets_to_needs_auth.py +87 -0
  172. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_inject_token_connects.py +92 -0
  173. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_needs_auth_status.py +67 -0
  174. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_submit_callback_completes_flow.py +110 -0
  175. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_oauth_token_persists_across_sessions.py +139 -0
  176. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_permission_prompt_tool_probe.py +160 -0
  177. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_annotations_not_echoed_in_status.py +100 -0
  178. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_close_tears_down_transport.py +71 -0
  179. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_multi_turn_reuse.py +108 -0
  180. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_multiple_servers_isolated.py +71 -0
  181. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_server_connected_status.py +77 -0
  182. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sdk_mcp_tool_description_passthrough.py +67 -0
  183. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_server_name_special_chars_prefix.py +58 -0
  184. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_sse_server_headers_and_connection.py +130 -0
  185. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_stdio_grandchild_reclaim_on_close.py +114 -0
  186. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_stdio_server_lifecycle.py +135 -0
  187. qoder_agent_sdk-1.0.0/tests/query_mcp/functional/test_strict_mcp_config_blocks_external_config.py +90 -0
  188. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/__init__.py +0 -0
  189. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_cli_args_allowed_mcp_server_names.py +35 -0
  190. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_cli_args_mcp_config.py +102 -0
  191. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_cli_args_permission_prompt_tool.py +28 -0
  192. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_cli_args_strict_mcp_config.py +26 -0
  193. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_create_sdk_mcp_server.py +78 -0
  194. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_handler_accepts_extra_helper.py +64 -0
  195. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_inbound_elicitation_callback.py +217 -0
  196. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_inbound_elicitation_default_cancel.py +73 -0
  197. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_inbound_get_model_policy.py +138 -0
  198. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_mcp_authenticate_response_variants.py +136 -0
  199. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_mcp_server_status_request.py +113 -0
  200. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_mcp_server_status_timeout.py +131 -0
  201. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_mcp_toggle_and_reconnect_requests.py +87 -0
  202. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_sdk_mcp_handler_extra_signal.py +190 -0
  203. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_sdk_mcp_handler_non_content_normalization.py +84 -0
  204. qoder_agent_sdk-1.0.0/tests/query_mcp/unit/test_sdk_server_split_from_process_servers.py +92 -0
  205. qoder_agent_sdk-1.0.0/tests/query_model_policy/__init__.py +0 -0
  206. qoder_agent_sdk-1.0.0/tests/query_model_policy/functional/__init__.py +0 -0
  207. qoder_agent_sdk-1.0.0/tests/query_model_policy/functional/conftest.py +25 -0
  208. qoder_agent_sdk-1.0.0/tests/query_model_policy/functional/test_model_policy_e2e.py +704 -0
  209. qoder_agent_sdk-1.0.0/tests/query_model_policy/functional/test_model_selection_e2e_logging.py +340 -0
  210. qoder_agent_sdk-1.0.0/tests/query_model_policy/functional/test_model_selection_logging.py +610 -0
  211. qoder_agent_sdk-1.0.0/tests/query_model_policy/unit/__init__.py +0 -0
  212. qoder_agent_sdk-1.0.0/tests/query_model_policy/unit/test_list_byok_providers.py +193 -0
  213. qoder_agent_sdk-1.0.0/tests/query_model_policy/unit/test_pull_suppresses_model_flag.py +1072 -0
  214. qoder_agent_sdk-1.0.0/tests/rewind_api/__init__.py +1 -0
  215. qoder_agent_sdk-1.0.0/tests/rewind_api/conftest.py +168 -0
  216. qoder_agent_sdk-1.0.0/tests/rewind_api/test_capture_checkpoint_uuid_from_stream.py +40 -0
  217. qoder_agent_sdk-1.0.0/tests/rewind_api/test_enable_file_checkpointing.py +41 -0
  218. qoder_agent_sdk-1.0.0/tests/rewind_api/test_mid_stream_rewind.py +51 -0
  219. qoder_agent_sdk-1.0.0/tests/rewind_api/test_multiple_checkpoints_rewind.py +53 -0
  220. qoder_agent_sdk-1.0.0/tests/rewind_api/test_replay_user_messages_checkpoint_uuid.py +43 -0
  221. qoder_agent_sdk-1.0.0/tests/rewind_api/test_resume_session_rewind.py +56 -0
  222. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_bash_changes_not_tracked.py +62 -0
  223. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_cross_session_rejected.py +55 -0
  224. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_directory_ops_not_undone.py +47 -0
  225. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_dry_run_with_checkpoint.py +41 -0
  226. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_files_success.py +41 -0
  227. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_local_files_only.py +64 -0
  228. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_malformed_message_id.py +37 -0
  229. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_preserves_conversation.py +56 -0
  230. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_stats.py +51 -0
  231. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_unknown_message.py +40 -0
  232. qoder_agent_sdk-1.0.0/tests/rewind_api/test_rewind_without_checkpointing.py +40 -0
  233. qoder_agent_sdk-1.0.0/tests/session_control/test_continue_latest_session.py +132 -0
  234. qoder_agent_sdk-1.0.0/tests/session_control/test_fork_session.py +160 -0
  235. qoder_agent_sdk-1.0.0/tests/session_control/test_new_client_session.py +53 -0
  236. qoder_agent_sdk-1.0.0/tests/session_control/test_new_query_session.py +53 -0
  237. qoder_agent_sdk-1.0.0/tests/session_control/test_new_session_with_session_id.py +149 -0
  238. qoder_agent_sdk-1.0.0/tests/session_control/test_resume_session.py +143 -0
  239. qoder_agent_sdk-1.0.0/tests/skills_loading_control/__init__.py +0 -0
  240. qoder_agent_sdk-1.0.0/tests/skills_loading_control/conftest.py +41 -0
  241. qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_agent_preloaded_skills.py +61 -0
  242. qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_builtin_skills_visibility.py +93 -0
  243. qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_default_skills_policy.py +50 -0
  244. qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_enable_all_skills.py +40 -0
  245. qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_enable_named_skills.py +35 -0
  246. qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_plugin_skill_in_init.py +87 -0
  247. qoder_agent_sdk-1.0.0/tests/skills_loading_control/test_settings_skill_overrides.py +114 -0
  248. qoder_agent_sdk-1.0.0/tests/skills_loading_control/unit/__init__.py +0 -0
  249. qoder_agent_sdk-1.0.0/tests/skills_loading_control/unit/test_skills_argv.py +114 -0
  250. qoder_agent_sdk-1.0.0/tests/test_build_wheel.py +86 -0
  251. qoder_agent_sdk-1.0.0/tests/test_client.py +322 -0
  252. qoder_agent_sdk-1.0.0/tests/test_control_request_timeout.py +230 -0
  253. qoder_agent_sdk-1.0.0/tests/test_download_cli.py +132 -0
  254. qoder_agent_sdk-1.0.0/tests/test_errors.py +52 -0
  255. qoder_agent_sdk-1.0.0/tests/test_integration.py +308 -0
  256. qoder_agent_sdk-1.0.0/tests/test_mcp_dynamic.py +279 -0
  257. qoder_agent_sdk-1.0.0/tests/test_mcp_large_output.py +335 -0
  258. qoder_agent_sdk-1.0.0/tests/test_mcp_oauth.py +434 -0
  259. qoder_agent_sdk-1.0.0/tests/test_message_parser.py +927 -0
  260. qoder_agent_sdk-1.0.0/tests/test_permission_alignment.py +734 -0
  261. qoder_agent_sdk-1.0.0/tests/test_query.py +943 -0
  262. qoder_agent_sdk-1.0.0/tests/test_rate_limit_event_repro.py +108 -0
  263. qoder_agent_sdk-1.0.0/tests/test_sdk_mcp_integration.py +1093 -0
  264. qoder_agent_sdk-1.0.0/tests/test_sdk_mcp_routing.py +348 -0
  265. qoder_agent_sdk-1.0.0/tests/test_session_mutations.py +794 -0
  266. qoder_agent_sdk-1.0.0/tests/test_sessions.py +1556 -0
  267. qoder_agent_sdk-1.0.0/tests/test_streaming_client.py +1316 -0
  268. qoder_agent_sdk-1.0.0/tests/test_subprocess_buffering.py +385 -0
  269. qoder_agent_sdk-1.0.0/tests/test_tool_callbacks.py +1070 -0
  270. qoder_agent_sdk-1.0.0/tests/test_transport.py +1784 -0
  271. qoder_agent_sdk-1.0.0/tests/test_types.py +597 -0
  272. qoder_agent_sdk-1.0.0/tests/tools/__init__.py +0 -0
  273. qoder_agent_sdk-1.0.0/tests/tools/conftest.py +71 -0
  274. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_allowedTools_disallowedTools_conflict_priority.py +45 -0
  275. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_canUseTool_throws_error.py +53 -0
  276. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_concurrent_multiple_tool_uses.py +60 -0
  277. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_createSdkMcpServer_many_tools.py +45 -0
  278. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_handler_long_running_vs_controlRequestTimeoutMs.py +46 -0
  279. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_handler_returns_large_content.py +41 -0
  280. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_handler_returns_malformed_result.py +39 -0
  281. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_handler_returns_undefined.py +39 -0
  282. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_model_calls_unknown_tool_functional.py +39 -0
  283. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_tool_input_deeply_nested_schema.py +78 -0
  284. qoder_agent_sdk-1.0.0/tests/tools/test_boundary_tool_input_many_fields.py +67 -0
  285. qoder_agent_sdk-1.0.0/tests/tools/test_createSdkMcpServer_empty_tools.py +67 -0
  286. qoder_agent_sdk-1.0.0/tests/tools/test_createSdkMcpServer_mcpServers_option.py +40 -0
  287. qoder_agent_sdk-1.0.0/tests/tools/test_createSdkMcpServer_multiple_tools.py +51 -0
  288. qoder_agent_sdk-1.0.0/tests/tools/test_createSdkMcpServer_name_routes_tool.py +69 -0
  289. qoder_agent_sdk-1.0.0/tests/tools/test_createSdkMcpServer_version.py +38 -0
  290. qoder_agent_sdk-1.0.0/tests/tools/test_error_handler_isError_true.py +66 -0
  291. qoder_agent_sdk-1.0.0/tests/tools/test_error_handler_isError_with_structured_data.py +56 -0
  292. qoder_agent_sdk-1.0.0/tests/tools/test_error_handler_throws_async_rejection.py +51 -0
  293. qoder_agent_sdk-1.0.0/tests/tools/test_error_handler_throws_non_Error.py +46 -0
  294. qoder_agent_sdk-1.0.0/tests/tools/test_error_handler_throws_sync_Error.py +47 -0
  295. qoder_agent_sdk-1.0.0/tests/tools/test_error_isError_allows_agent_retry.py +65 -0
  296. qoder_agent_sdk-1.0.0/tests/tools/test_permission_allowedTools_permits_mcp_tool.py +44 -0
  297. qoder_agent_sdk-1.0.0/tests/tools/test_permission_allowedTools_server_pattern.py +46 -0
  298. qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_allow_passthrough.py +69 -0
  299. qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_conditional_on_input.py +95 -0
  300. qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_deny.py +73 -0
  301. qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_deny_with_interrupt.py +72 -0
  302. qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_receives_mcp_toolName_format.py +56 -0
  303. qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_updatedInput.py +79 -0
  304. qoder_agent_sdk-1.0.0/tests/tools/test_permission_canUseTool_updatedPermissions.py +73 -0
  305. qoder_agent_sdk-1.0.0/tests/tools/test_permission_disallowedTools_blocks_tool.py +48 -0
  306. qoder_agent_sdk-1.0.0/tests/tools/test_permission_mode_bypassPermissions_with_mcp_tool.py +44 -0
  307. qoder_agent_sdk-1.0.0/tests/tools/test_permission_postToolUse_hook_additionalContext.py +57 -0
  308. qoder_agent_sdk-1.0.0/tests/tools/test_permission_preToolUse_hook_updatedInput.py +66 -0
  309. qoder_agent_sdk-1.0.0/tests/tools/test_return_empty_content_array.py +49 -0
  310. qoder_agent_sdk-1.0.0/tests/tools/test_return_image_content.py +45 -0
  311. qoder_agent_sdk-1.0.0/tests/tools/test_return_multiple_content_blocks.py +62 -0
  312. qoder_agent_sdk-1.0.0/tests/tools/test_return_text_content.py +81 -0
  313. qoder_agent_sdk-1.0.0/tests/tools/test_tool_destructiveHint.py +50 -0
  314. qoder_agent_sdk-1.0.0/tests/tools/test_tool_handler_receives_args_and_returns_content.py +94 -0
  315. qoder_agent_sdk-1.0.0/tests/tools/test_tool_input_schema_describe.py +54 -0
  316. qoder_agent_sdk-1.0.0/tests/tools/test_tool_input_schema_nested.py +113 -0
  317. qoder_agent_sdk-1.0.0/tests/tools/test_tool_input_schema_zod_shape.py +49 -0
  318. qoder_agent_sdk-1.0.0/tests/tools/test_tool_name_and_description.py +44 -0
  319. qoder_agent_sdk-1.0.0/tests/tools/test_tool_openWorldHint.py +49 -0
  320. qoder_agent_sdk-1.0.0/tests/tools/test_tool_readOnlyHint.py +48 -0
  321. qoder_agent_sdk-1.0.0/tests/tools/test_unit_createSdkMcpServer.py +102 -0
  322. qoder_agent_sdk-1.0.0/tests/tools/test_unit_createSdkMcpServer_duplicate_tool_name.py +20 -0
  323. qoder_agent_sdk-1.0.0/tests/tools/test_unit_createSdkMcpServer_empty_server_name.py +17 -0
  324. qoder_agent_sdk-1.0.0/tests/tools/test_unit_createSdkMcpServer_empty_tool_description.py +16 -0
  325. qoder_agent_sdk-1.0.0/tests/tools/test_unit_createSdkMcpServer_empty_tool_name.py +27 -0
  326. qoder_agent_sdk-1.0.0/tests/tools/test_unit_mcp_handler.py +224 -0
  327. qoder_agent_sdk-1.0.0/tests/tools/test_unit_sdk_mcp_transport.py +80 -0
  328. 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,7 @@
1
+ Copyright (c) 2026 Qoder
2
+
3
+ Use of this software is governed by the Qoder Product Service Terms:
4
+
5
+ https://qoder.com/product-service
6
+
7
+ By installing or using this package, you agree to those terms.
@@ -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.