agentnode-sdk 0.15.0__tar.gz → 0.17.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 (215) hide show
  1. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/CHANGELOG.md +69 -0
  2. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/PKG-INFO +1 -1
  3. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/__init__.py +1 -1
  4. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/auth.py +105 -36
  5. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/commands.py +11 -2
  6. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/main.py +425 -412
  7. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/mcp_commands.py +280 -170
  8. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/setup_wizard.py +49 -19
  9. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/client.py +10 -0
  10. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/credential_store.py +12 -5
  11. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/installer.py +224 -1
  12. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/lock_integrity.py +245 -230
  13. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runner.py +6 -1
  14. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/agent_runner.py +16 -7
  15. agentnode_sdk-0.17.0/agentnode_sdk/runtimes/mcp_consent.py +207 -0
  16. agentnode_sdk-0.17.0/agentnode_sdk/runtimes/mcp_consent_store.py +264 -0
  17. agentnode_sdk-0.17.0/agentnode_sdk/runtimes/mcp_runner.py +768 -0
  18. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/container_backend.py +350 -266
  19. agentnode_sdk-0.17.0/agentnode_sdk/sandbox/domain_policy.py +83 -0
  20. agentnode_sdk-0.17.0/agentnode_sdk/sandbox/egress.py +178 -0
  21. agentnode_sdk-0.17.0/agentnode_sdk/sandbox/egress_proxy.py +223 -0
  22. agentnode_sdk-0.17.0/agentnode_sdk/sandbox/mcp_preinstall.py +182 -0
  23. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/types.py +78 -52
  24. agentnode_sdk-0.17.0/data/compatibility/current.json +5061 -0
  25. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/pyproject.toml +4 -1
  26. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/generate_compatibility_artifacts.py +95 -31
  27. agentnode_sdk-0.17.0/scripts/merge_batches.py +196 -0
  28. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/conftest.py +20 -0
  29. agentnode_sdk-0.17.0/tests/data/allowed_domains_vectors.json +41 -0
  30. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_auth_cli_vault.py +129 -1
  31. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_cli_run_resolution.py +36 -36
  32. agentnode_sdk-0.17.0/tests/test_consent_prompt.py +84 -0
  33. agentnode_sdk-0.17.0/tests/test_domain_policy.py +50 -0
  34. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_e2e_runtime.py +8 -0
  35. agentnode_sdk-0.17.0/tests/test_egress_domain_validation.py +52 -0
  36. agentnode_sdk-0.17.0/tests/test_egress_e2e.py +94 -0
  37. agentnode_sdk-0.17.0/tests/test_egress_lifecycle.py +123 -0
  38. agentnode_sdk-0.17.0/tests/test_egress_proxy_unit.py +152 -0
  39. agentnode_sdk-0.17.0/tests/test_egress_wrap.py +112 -0
  40. agentnode_sdk-0.17.0/tests/test_env_passthrough_wrap.py +106 -0
  41. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_llm_vault_binding.py +4 -1
  42. agentnode_sdk-0.17.0/tests/test_mcp_allowed_domains_seal.py +122 -0
  43. agentnode_sdk-0.17.0/tests/test_mcp_consent.py +125 -0
  44. agentnode_sdk-0.17.0/tests/test_mcp_consent_resolver.py +186 -0
  45. agentnode_sdk-0.17.0/tests/test_mcp_consent_store.py +187 -0
  46. agentnode_sdk-0.17.0/tests/test_mcp_credentialed_launch.py +626 -0
  47. agentnode_sdk-0.17.0/tests/test_mcp_preinstall.py +308 -0
  48. agentnode_sdk-0.17.0/tests/test_mcp_preinstall_run.py +417 -0
  49. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_mcp_sandbox.py +170 -175
  50. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_setup_wizard.py +56 -1
  51. agentnode_sdk-0.15.0/agentnode_sdk/runtimes/mcp_runner.py +0 -429
  52. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/.env.example +0 -0
  53. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/.gitignore +0 -0
  54. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/README.md +0 -0
  55. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/REGISTRY_SIGNING_ACTIVATION.md +0 -0
  56. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/REGISTRY_SIGNING_SPEC.md +0 -0
  57. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/THREAT_MODEL.md +0 -0
  58. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/TRUST_STACK.md +0 -0
  59. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode.lock +0 -0
  60. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/_fileutil.py +0 -0
  61. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/async_client.py +0 -0
  62. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/capability_graph.py +0 -0
  63. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/capability_taxonomy.py +0 -0
  64. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/__init__.py +0 -0
  65. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/__main__.py +0 -0
  66. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/audit.py +0 -0
  67. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/cassette_audit.py +0 -0
  68. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/complements.py +0 -0
  69. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/init.py +0 -0
  70. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/mcp_status.py +0 -0
  71. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/mcp_submit.py +0 -0
  72. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/mcp_verify.py +0 -0
  73. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/output.py +0 -0
  74. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/publish.py +0 -0
  75. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/record_cases.py +0 -0
  76. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/sandbox_commands.py +0 -0
  77. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/serve.py +0 -0
  78. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/smart_run.py +0 -0
  79. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/templates.py +0 -0
  80. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/validate.py +0 -0
  81. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/verify_local.py +0 -0
  82. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/compatibility.py +0 -0
  83. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/config.py +0 -0
  84. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/credential_handle.py +0 -0
  85. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/credential_resolver.py +0 -0
  86. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/detect.py +0 -0
  87. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/exceptions.py +0 -0
  88. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/guard.py +0 -0
  89. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/input_guard.py +0 -0
  90. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/key_status.py +0 -0
  91. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/llm_providers.py +0 -0
  92. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/mcp_server.py +0 -0
  93. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/models.py +0 -0
  94. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/planner.py +0 -0
  95. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/policy.py +0 -0
  96. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/references.py +0 -0
  97. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/registry_trust.py +0 -0
  98. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/resolve.py +0 -0
  99. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/resource_provider.py +0 -0
  100. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/risk_profile.py +0 -0
  101. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/run_log.py +0 -0
  102. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtime.py +0 -0
  103. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/__init__.py +0 -0
  104. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/agent_llm_broker.py +0 -0
  105. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/agent_llm_policy.py +0 -0
  106. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/agent_sandbox.py +0 -0
  107. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/python_runner.py +0 -0
  108. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/remote_runner.py +0 -0
  109. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/__init__.py +0 -0
  110. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/agent_container_wrapper.py +0 -0
  111. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/agent_rpc.py +0 -0
  112. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/agent_session.py +0 -0
  113. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/backend.py +0 -0
  114. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/policy.py +0 -0
  115. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/signature.py +0 -0
  116. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/signing_key.py +0 -0
  117. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/skill.py +0 -0
  118. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/sandbox-image/Dockerfile +0 -0
  119. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/sandbox-image/README.md +0 -0
  120. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/analyze_scores.py +0 -0
  121. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/batch_verify.py +0 -0
  122. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/ci_smoke_test.py +0 -0
  123. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/verify_toolcalls.py +0 -0
  124. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/weekly_retest.sh +0 -0
  125. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/README.md +0 -0
  126. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/__init__.py +0 -0
  127. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/container_agent_wrapper.py +0 -0
  128. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/fake_llm.py +0 -0
  129. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/host_driver.py +0 -0
  130. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/trivial_agent.py +0 -0
  131. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/__init__.py +0 -0
  132. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_llm_broker.py +0 -0
  133. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_llm_policy.py +0 -0
  134. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_rpc.py +0 -0
  135. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_runner.py +0 -0
  136. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_sandbox_e2e.py +0 -0
  137. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_sandbox_routing.py +0 -0
  138. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_sandbox_spike.py +0 -0
  139. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_session_container.py +0 -0
  140. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_async_client.py +0 -0
  141. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_audit_ux.py +0 -0
  142. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_auto_upgrade_policy.py +0 -0
  143. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_cli.py +0 -0
  144. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_cli_lock.py +0 -0
  145. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_client.py +0 -0
  146. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_client_json_guard.py +0 -0
  147. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_client_sprint_b.py +0 -0
  148. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_config.py +0 -0
  149. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_credential_handle.py +0 -0
  150. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_credential_integration.py +0 -0
  151. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_credential_resolver.py +0 -0
  152. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_credential_store.py +0 -0
  153. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_credential_vault.py +0 -0
  154. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_detect.py +0 -0
  155. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_detect_and_install.py +0 -0
  156. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_edge_cases.py +0 -0
  157. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard.py +0 -0
  158. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_check.py +0 -0
  159. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_config_cache.py +0 -0
  160. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_policy.py +0 -0
  161. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_preview.py +0 -0
  162. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_schema.py +0 -0
  163. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_set.py +0 -0
  164. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_status.py +0 -0
  165. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_tool_override.py +0 -0
  166. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_tool_override_audit.py +0 -0
  167. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_tool_override_cli.py +0 -0
  168. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_ux.py +0 -0
  169. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_input_guard.py +0 -0
  170. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_input_guard_escalation.py +0 -0
  171. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_install_hardening.py +0 -0
  172. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_installer_sprint_b.py +0 -0
  173. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_intelligence.py +0 -0
  174. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_key_status.py +0 -0
  175. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_llm_binding.py +0 -0
  176. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_llm_call_runlog.py +0 -0
  177. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_llm_providers.py +0 -0
  178. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_lock_integrity.py +0 -0
  179. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_lock_runtime.py +0 -0
  180. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_mcp_audit.py +0 -0
  181. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_mcp_doctor.py +0 -0
  182. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_mcp_server.py +0 -0
  183. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_observability.py +0 -0
  184. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_planner.py +0 -0
  185. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_policy.py +0 -0
  186. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_policy_integration.py +0 -0
  187. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_prompt_specs.py +0 -0
  188. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_provider_matrix.py +0 -0
  189. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_publish.py +0 -0
  190. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_references.py +0 -0
  191. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_registry_trust.py +0 -0
  192. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_remote_hardening.py +0 -0
  193. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_remote_runner.py +0 -0
  194. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_resource_provider.py +0 -0
  195. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_resource_specs.py +0 -0
  196. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_risk_profile.py +0 -0
  197. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_run_log.py +0 -0
  198. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_runner.py +0 -0
  199. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_runtime.py +0 -0
  200. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_runtime_audit.py +0 -0
  201. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_sandbox_backend.py +0 -0
  202. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_sandbox_doctor.py +0 -0
  203. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_sandbox_e2e.py +0 -0
  204. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_sandbox_gate.py +0 -0
  205. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_security_hardening.py +0 -0
  206. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_signature.py +0 -0
  207. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_signing_key.py +0 -0
  208. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_skill.py +0 -0
  209. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_smart.py +0 -0
  210. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_stability.py +0 -0
  211. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_toolpack_sandbox.py +0 -0
  212. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_v02.py +0 -0
  213. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_validate.py +0 -0
  214. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_validate_skill.py +0 -0
  215. {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/validation_lockfile.json +0 -0
@@ -1,5 +1,74 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.17.0 — MCP network isolation
4
+
5
+ ### Changed
6
+
7
+ - Community MCP servers now run only when pinned and preinstalled into a sealed
8
+ volume. Preinstalled community MCPs run with no network by default, or behind a
9
+ sealed egress allowlist when `mcp_allowed_domains` are declared.
10
+
11
+ ### Hardened
12
+
13
+ - Removed the open-network runtime-fetch path for community MCPs. Non-preinstalled
14
+ or floating community MCPs — including `npx`, `uvx`, `latest`, git, or URL-based
15
+ runtime fetches — are now refused fail-closed. The old `network_level`
16
+ open-network grant path is no longer honored for community MCP runtime execution.
17
+
18
+ ### BREAKING / Upgrade Notes
19
+
20
+ - Community MCPs that ship only an `mcp_command` are now refused instead of running
21
+ with an open network. To migrate, declare an exact pinned `mcp_install` so the MCP
22
+ is preinstalled into a sealed volume. If runtime network access is required,
23
+ declare `mcp_allowed_domains`; without declared allowed domains, the MCP runs with
24
+ no network.
25
+ - The credentialed MCP secret flow is unchanged. Curated/trusted MCP behavior is
26
+ unchanged.
27
+
28
+ ## 0.16.0 — Registry providers in auth CLI and setup wizard
29
+
30
+ ### Added
31
+
32
+ - **`agentnode auth status` now surfaces all registry providers** — OpenAI,
33
+ Anthropic, OpenRouter, DeepSeek, Mistral, Qwen, Gemini — with their storage
34
+ backend and effective source, plus **Ollama as a local keyless provider**
35
+ (shown as selected/configured/not selected instead of "missing"). Custom
36
+ providers configured under `llm.providers.<name>` appear automatically.
37
+ - **`agentnode auth test` supports the registry providers.** Compatible
38
+ providers are validated with a free, no-completion `GET {base_url}/models`
39
+ probe; `agentnode auth test ollama` is a keyless reachability check
40
+ (exit 0 reachable, exit 3 unreachable — never "rejected", and it never
41
+ starts Ollama). Custom configured endpoints can be tested the same way.
42
+ - **The setup wizard lists all registry providers**, grouped for readability
43
+ (Recommended / More / Local), with Skip remaining the default. Selecting
44
+ Ollama never asks for an API key — it sets `llm.default_provider` through
45
+ the wizard's normal save step.
46
+ - Additive `vendor` field in host-side LLM bindings: logs and tooling can now
47
+ show the real provider name; the protocol discriminator used by the broker
48
+ is unchanged.
49
+
50
+ ### Changed
51
+
52
+ - The auth CLI and the setup wizard now use the provider registry as their
53
+ single source of truth — no hardcoded provider lists or environment
54
+ variable names remain in those surfaces.
55
+ - OpenRouter keeps its dedicated `/auth/key` validation path (its `/models`
56
+ endpoint is unauthenticated and validates nothing).
57
+
58
+ ### Hardened
59
+
60
+ - Provider response bodies are never printed (they can echo key fragments);
61
+ keys are never printed, logged, or exposed in exceptions.
62
+ - Ollama is never started or probed automatically — only an explicit
63
+ `agentnode auth test ollama` performs a localhost reachability check.
64
+ - The `vendor` field stays host-side and does not change the broker/sandbox
65
+ wire shape.
66
+
67
+ ### BREAKING / Upgrade Notes
68
+
69
+ - None. All changes are additive; existing `auth` and `setup` flows behave
70
+ identically for the previously supported providers.
71
+
3
72
  ## 0.15.0 — Generic OpenAI-compatible LLM providers
4
73
 
5
74
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentnode-sdk
3
- Version: 0.15.0
3
+ Version: 0.17.0
4
4
  Summary: Python SDK for AgentNode — the open upgrade and discovery infrastructure for AI agents.
5
5
  Project-URL: Homepage, https://agentnode.net
6
6
  Project-URL: Repository, https://github.com/agentnode-ai/agentnode
@@ -38,7 +38,7 @@ from agentnode_sdk.runtime import AgentNodeRuntime
38
38
  Client = AgentNodeClient
39
39
  ToolError = AgentNodeToolError
40
40
 
41
- __version__ = "0.15.0"
41
+ __version__ = "0.17.0"
42
42
  __all__ = [
43
43
  "AgentNode",
44
44
  "AsyncAgentNode",
@@ -10,7 +10,6 @@ import os
10
10
  import sys
11
11
 
12
12
  from agentnode_sdk.credential_store import (
13
- LLM_PROVIDER_ENV,
14
13
  has_credential,
15
14
  list_credentials,
16
15
  load_credentials,
@@ -30,17 +29,28 @@ def _storage_short(storage: str) -> str:
30
29
  return "OS keychain" if storage == "keyring" else "plaintext file"
31
30
 
32
31
 
33
- def _llm_effective_source(provider: str) -> tuple[str | None, str]:
32
+ def _host_config() -> dict:
33
+ try:
34
+ from agentnode_sdk.config import load_config
35
+ return load_config() or {}
36
+ except Exception:
37
+ return {}
38
+
39
+
40
+ def _llm_effective_source(provider: str, host_config: dict | None = None) -> tuple[str | None, str]:
34
41
  """(effective key or None, human-readable source) for an LLM provider.
35
42
 
36
43
  Mirrors the runtime's resolution: env (incl. ~/.agentnode/.env) overrides
37
- the stored credential. Uses metadata only for the stored check here —
44
+ the stored credential. Env var names come from the provider REGISTRY
45
+ (single source of truth). Uses metadata only for the stored check here —
38
46
  the real keychain read happens in ``auth test``."""
47
+ from agentnode_sdk.llm_providers import resolve_provider_spec
39
48
  from agentnode_sdk.runtimes.agent_runner import _load_agentnode_env
40
49
  _load_agentnode_env()
41
50
 
42
- env_var = LLM_PROVIDER_ENV[provider]
43
- env_key = os.environ.get(env_var) or None
51
+ spec = resolve_provider_spec(provider, host_config) or {}
52
+ env_var = spec.get("api_key_env") or ""
53
+ env_key = (os.environ.get(env_var) or None) if env_var else None
44
54
  meta = load_credentials().get("providers", {}).get(provider)
45
55
  stored = isinstance(meta, dict)
46
56
  storage = (meta or {}).get("storage", "file")
@@ -54,6 +64,19 @@ def _llm_effective_source(provider: str) -> tuple[str | None, str]:
54
64
  return None, "not configured"
55
65
 
56
66
 
67
+ def _registry_key_providers(host_config: dict | None) -> list[str]:
68
+ """Key-requiring providers from the registry (presets + custom config
69
+ entries), in stable registry order."""
70
+ from agentnode_sdk.llm_providers import known_provider_names, resolve_provider_spec
71
+
72
+ names: list[str] = []
73
+ for name in known_provider_names(host_config):
74
+ spec = resolve_provider_spec(name, host_config)
75
+ if spec and spec.get("requires_key", True):
76
+ names.append(name)
77
+ return names
78
+
79
+
57
80
  def _resolve_auth_type(provider: str) -> str:
58
81
  """Read auth_type from lockfile connector entry. Falls back to 'api_key'.
59
82
 
@@ -132,15 +155,25 @@ def cmd_auth_remove(provider: str) -> int:
132
155
 
133
156
  def cmd_auth_status() -> int:
134
157
  # --- LLM providers (host runtime / sandbox broker) -----------------------
158
+ host_cfg = _host_config()
135
159
  print()
136
160
  print(section("LLM Providers"))
137
161
  print(f" {'Provider':<14}{'Status':<16}{'Effective source'}")
138
162
  print(f" {'--------':<14}{'------':<16}{'----------------'}")
139
- for provider in sorted(LLM_PROVIDER_ENV):
140
- key, source = _llm_effective_source(provider)
163
+ for provider in _registry_key_providers(host_cfg):
164
+ key, source = _llm_effective_source(provider, host_cfg)
141
165
  configured = key is not None or source not in ("not configured",)
142
166
  status = "configured" if configured else "missing"
143
167
  print(f" {provider:<14}{status:<16}{source}")
168
+ # ollama: keyless local provider — selection is config, not a credential
169
+ llm_cfg = host_cfg.get("llm") or {}
170
+ if llm_cfg.get("default_provider") == "ollama":
171
+ ollama_source = "selected via llm.default_provider"
172
+ elif "ollama" in (llm_cfg.get("providers") or {}):
173
+ ollama_source = "configured via llm.providers"
174
+ else:
175
+ ollama_source = "not selected — agentnode config set llm.default_provider ollama"
176
+ print(f" {'ollama':<14}{'local (keyless)':<16}{ollama_source}")
144
177
  print(dim(" Env vars always override stored credentials. "
145
178
  "Test a key: agentnode auth test <provider>"))
146
179
 
@@ -183,61 +216,97 @@ def cmd_auth_status() -> int:
183
216
 
184
217
 
185
218
  # Free, cost-less validation endpoints (no completion call, no charge).
186
- # anthropic REQUIRES the anthropic-version header (a 400 without it would be
187
- # misread as a bad key); openrouter's /models is UNAUTHENTICATED (validates
188
- # nothing) /auth/key is the correct probe.
189
- _TEST_REQUESTS = {
190
- "openai": lambda key: (
219
+ # GENERIC rule for OpenAI-compatible providers: GET {base_url}/models with a
220
+ # Bearer token (authenticated on deepseek/mistral/qwen/gemini and most custom
221
+ # endpoints). EXCEPTIONS: openai (official URL), anthropic (REQUIRES the
222
+ # anthropic-version header — a 400 without it would be misread as a bad key),
223
+ # openrouter (its /models is UNAUTHENTICATED, validates nothing — /auth/key is
224
+ # the correct probe).
225
+ _TEST_EXCEPTIONS = {
226
+ "openai": lambda key, spec: (
191
227
  "https://api.openai.com/v1/models",
192
228
  {"Authorization": f"Bearer {key}"},
193
229
  ),
194
- "anthropic": lambda key: (
230
+ "anthropic": lambda key, spec: (
195
231
  "https://api.anthropic.com/v1/models",
196
232
  {"x-api-key": key, "anthropic-version": "2023-06-01"},
197
233
  ),
198
- "openrouter": lambda key: (
234
+ "openrouter": lambda key, spec: (
199
235
  "https://openrouter.ai/api/v1/auth/key",
200
236
  {"Authorization": f"Bearer {key}"},
201
237
  ),
202
238
  }
203
239
 
204
240
 
241
+ def _test_request(provider: str, key: str | None, spec: dict) -> tuple[str, dict] | None:
242
+ if provider in _TEST_EXCEPTIONS:
243
+ return _TEST_EXCEPTIONS[provider](key, spec)
244
+ base = (spec.get("base_url") or "").rstrip("/")
245
+ if not base:
246
+ return None # no compat endpoint to probe
247
+ headers = {"Authorization": f"Bearer {key}"} if key else {}
248
+ return (base + "/models", headers)
249
+
250
+
205
251
  def cmd_auth_test(provider: str) -> int:
206
252
  """Validate the EFFECTIVE key for an LLM provider (env beats vault) via a
207
- free endpoint. Exit codes: 0 valid / 1 rejected (401/403) / 2 not
208
- configured or unsupported / 3 indeterminate (network/5xx never reported
209
- as invalid). Never prints the key (masked last-4 only) and never echoes
210
- the provider's response body (it can contain key fragments)."""
253
+ free endpoint registry-driven, so custom ``llm.providers`` entries work
254
+ too. Exit codes: 0 valid (key providers) / reachable (keyless) · 1
255
+ rejected (401/403, key providers only) · 2 not configured or unsupported ·
256
+ 3 indeterminate (network/5xx never reported as invalid; for keyless
257
+ providers this means unreachable). Never prints the key (masked last-4
258
+ only), never echoes provider response bodies (they can contain key
259
+ fragments), never starts anything."""
211
260
  provider = provider.lower().strip()
212
- if provider not in _TEST_REQUESTS:
213
- supported = ", ".join(sorted(_TEST_REQUESTS))
214
- print(f" auth test supports: {supported}", file=sys.stderr)
261
+ host_cfg = _host_config()
262
+ from agentnode_sdk.llm_providers import resolve_provider_spec
263
+ spec = resolve_provider_spec(provider, host_cfg)
264
+ if spec is None:
265
+ print(f" Unknown provider '{provider}'. Known: see `agentnode auth status`; "
266
+ "custom endpoints go under llm.providers.<name>.", file=sys.stderr)
215
267
  return 2
216
268
 
217
- key, source = _llm_effective_source(provider)
218
- if key is None:
219
- # No env override — resolve the stored credential (real keychain read).
220
- from agentnode_sdk.credential_store import get_llm_api_key
221
- key = get_llm_api_key(provider)
222
- if not key:
223
- print(f"\n {provider}: not configured. Run `agentnode auth set {provider}`.\n")
269
+ requires_key = spec.get("requires_key", True)
270
+ if requires_key:
271
+ key, source = _llm_effective_source(provider, host_cfg)
272
+ if key is None:
273
+ # No env override — resolve the stored credential (real keychain read).
274
+ from agentnode_sdk.credential_store import get_llm_api_key
275
+ key = get_llm_api_key(provider)
276
+ if not key:
277
+ print(f"\n {provider}: not configured. Run `agentnode auth set {provider}`.\n")
278
+ return 2
279
+ shown = f"{_masked(key)}, {source}"
280
+ else:
281
+ key, shown = None, "local (keyless)"
282
+
283
+ req = _test_request(provider, key, spec)
284
+ if req is None:
285
+ print(f"\n {provider}: no endpoint to probe (no base_url configured).\n")
224
286
  return 2
287
+ url, headers = req
225
288
 
226
- url, headers = _TEST_REQUESTS[provider](key)
227
289
  import httpx
228
290
  try:
229
291
  resp = httpx.get(url, headers=headers, timeout=10.0)
230
292
  except Exception:
231
- print(f"\n {provider} ({_masked(key)}, {source}): could not reach the "
232
- "provider key validity unknown.\n")
293
+ if not requires_key:
294
+ print(f"\n {provider} ({shown}): could not reach {url} — "
295
+ "is the local server (e.g. Ollama) running?\n")
296
+ else:
297
+ print(f"\n {provider} ({shown}): could not reach the "
298
+ "provider — key validity unknown.\n")
233
299
  return 3
234
300
  if resp.status_code == 200:
235
- print(f"\n {provider} ({_masked(key)}, {source}): key is valid.\n")
301
+ if requires_key:
302
+ print(f"\n {provider} ({shown}): key is valid.\n")
303
+ else:
304
+ print(f"\n {provider} ({shown}): endpoint is reachable.\n")
236
305
  return 0
237
- if resp.status_code in (401, 403):
238
- print(f"\n {provider} ({_masked(key)}, {source}): key was rejected by "
306
+ if requires_key and resp.status_code in (401, 403):
307
+ print(f"\n {provider} ({shown}): key was rejected by "
239
308
  f"the provider (HTTP {resp.status_code}).\n")
240
309
  return 1
241
- print(f"\n {provider} ({_masked(key)}, {source}): unexpected provider "
242
- f"response (HTTP {resp.status_code}) — key validity unknown.\n")
310
+ print(f"\n {provider} ({shown}): unexpected response "
311
+ f"(HTTP {resp.status_code}) — status unknown.\n")
243
312
  return 3
@@ -878,11 +878,16 @@ def cmd_run(
878
878
  try:
879
879
  from agentnode_sdk.runner import run_tool
880
880
  from agentnode_sdk.guard import cli_confirmation_callback
881
+ from agentnode_sdk.cli.mcp_commands import cli_consent_callback
881
882
 
882
883
  is_interactive = os.environ.get("AGENTNODE_NON_INTERACTIVE", "").lower() not in ("true", "1")
883
884
  callback = cli_confirmation_callback if is_interactive else None
885
+ # Stage 3B-2b: dedicated consent callback for credentialed MCPs (separate from the guard
886
+ # bool callback). None when non-TTY ⇒ resolver requires a valid stored grant (fail-closed).
887
+ consent_cb = cli_consent_callback if is_interactive else None
884
888
 
885
- result = run_tool(slug, tool_name=tool_name, confirmation_callback=callback, **data)
889
+ result = run_tool(slug, tool_name=tool_name, confirmation_callback=callback,
890
+ mcp_consent_callback=consent_cb, **data)
886
891
 
887
892
  if result.mode_used == "policy_denied" and result.policy:
888
893
  _print_guard_block(slug, tool_name, result)
@@ -1148,11 +1153,15 @@ def _cmd_run_smart(
1148
1153
  try:
1149
1154
  from agentnode_sdk.runner import run_tool
1150
1155
  from agentnode_sdk.guard import cli_confirmation_callback
1156
+ from agentnode_sdk.cli.mcp_commands import cli_consent_callback
1151
1157
 
1152
1158
  is_interactive_run = os.environ.get("AGENTNODE_NON_INTERACTIVE", "").lower() not in ("true", "1")
1153
1159
  callback = cli_confirmation_callback if is_interactive_run else None
1160
+ # Stage 3B-2b: dedicated consent callback for credentialed MCPs (separate from guard bool).
1161
+ consent_cb = cli_consent_callback if is_interactive_run else None
1154
1162
 
1155
- result = run_tool(target_slug, confirmation_callback=callback, **parsed.input_args)
1163
+ result = run_tool(target_slug, confirmation_callback=callback,
1164
+ mcp_consent_callback=consent_cb, **parsed.input_args)
1156
1165
 
1157
1166
  if result.mode_used == "policy_denied" and result.policy:
1158
1167
  _print_guard_block(target_slug, None, result)