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.
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/CHANGELOG.md +69 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/PKG-INFO +1 -1
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/__init__.py +1 -1
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/auth.py +105 -36
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/commands.py +11 -2
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/main.py +425 -412
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/mcp_commands.py +280 -170
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/setup_wizard.py +49 -19
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/client.py +10 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/credential_store.py +12 -5
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/installer.py +224 -1
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/lock_integrity.py +245 -230
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runner.py +6 -1
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/agent_runner.py +16 -7
- agentnode_sdk-0.17.0/agentnode_sdk/runtimes/mcp_consent.py +207 -0
- agentnode_sdk-0.17.0/agentnode_sdk/runtimes/mcp_consent_store.py +264 -0
- agentnode_sdk-0.17.0/agentnode_sdk/runtimes/mcp_runner.py +768 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/container_backend.py +350 -266
- agentnode_sdk-0.17.0/agentnode_sdk/sandbox/domain_policy.py +83 -0
- agentnode_sdk-0.17.0/agentnode_sdk/sandbox/egress.py +178 -0
- agentnode_sdk-0.17.0/agentnode_sdk/sandbox/egress_proxy.py +223 -0
- agentnode_sdk-0.17.0/agentnode_sdk/sandbox/mcp_preinstall.py +182 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/types.py +78 -52
- agentnode_sdk-0.17.0/data/compatibility/current.json +5061 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/pyproject.toml +4 -1
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/generate_compatibility_artifacts.py +95 -31
- agentnode_sdk-0.17.0/scripts/merge_batches.py +196 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/conftest.py +20 -0
- agentnode_sdk-0.17.0/tests/data/allowed_domains_vectors.json +41 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_auth_cli_vault.py +129 -1
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_cli_run_resolution.py +36 -36
- agentnode_sdk-0.17.0/tests/test_consent_prompt.py +84 -0
- agentnode_sdk-0.17.0/tests/test_domain_policy.py +50 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_e2e_runtime.py +8 -0
- agentnode_sdk-0.17.0/tests/test_egress_domain_validation.py +52 -0
- agentnode_sdk-0.17.0/tests/test_egress_e2e.py +94 -0
- agentnode_sdk-0.17.0/tests/test_egress_lifecycle.py +123 -0
- agentnode_sdk-0.17.0/tests/test_egress_proxy_unit.py +152 -0
- agentnode_sdk-0.17.0/tests/test_egress_wrap.py +112 -0
- agentnode_sdk-0.17.0/tests/test_env_passthrough_wrap.py +106 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_llm_vault_binding.py +4 -1
- agentnode_sdk-0.17.0/tests/test_mcp_allowed_domains_seal.py +122 -0
- agentnode_sdk-0.17.0/tests/test_mcp_consent.py +125 -0
- agentnode_sdk-0.17.0/tests/test_mcp_consent_resolver.py +186 -0
- agentnode_sdk-0.17.0/tests/test_mcp_consent_store.py +187 -0
- agentnode_sdk-0.17.0/tests/test_mcp_credentialed_launch.py +626 -0
- agentnode_sdk-0.17.0/tests/test_mcp_preinstall.py +308 -0
- agentnode_sdk-0.17.0/tests/test_mcp_preinstall_run.py +417 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_mcp_sandbox.py +170 -175
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_setup_wizard.py +56 -1
- agentnode_sdk-0.15.0/agentnode_sdk/runtimes/mcp_runner.py +0 -429
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/.env.example +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/.gitignore +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/README.md +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/REGISTRY_SIGNING_ACTIVATION.md +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/REGISTRY_SIGNING_SPEC.md +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/THREAT_MODEL.md +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/TRUST_STACK.md +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode.lock +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/_fileutil.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/async_client.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/capability_graph.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/capability_taxonomy.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/__init__.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/__main__.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/audit.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/cassette_audit.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/complements.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/init.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/mcp_status.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/mcp_submit.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/mcp_verify.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/output.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/publish.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/record_cases.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/sandbox_commands.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/serve.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/smart_run.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/templates.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/validate.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/cli/verify_local.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/compatibility.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/config.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/credential_handle.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/credential_resolver.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/detect.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/exceptions.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/guard.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/input_guard.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/key_status.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/llm_providers.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/mcp_server.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/models.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/planner.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/policy.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/references.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/registry_trust.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/resolve.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/resource_provider.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/risk_profile.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/run_log.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtime.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/__init__.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/agent_llm_broker.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/agent_llm_policy.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/agent_sandbox.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/python_runner.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/runtimes/remote_runner.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/__init__.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/agent_container_wrapper.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/agent_rpc.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/agent_session.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/backend.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/sandbox/policy.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/signature.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/signing_key.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/agentnode_sdk/skill.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/sandbox-image/Dockerfile +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/sandbox-image/README.md +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/analyze_scores.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/batch_verify.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/ci_smoke_test.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/verify_toolcalls.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/scripts/weekly_retest.sh +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/README.md +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/__init__.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/container_agent_wrapper.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/fake_llm.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/host_driver.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/spikes/agent_sandbox_routing/trivial_agent.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/__init__.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_llm_broker.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_llm_policy.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_rpc.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_runner.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_sandbox_e2e.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_sandbox_routing.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_sandbox_spike.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_agent_session_container.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_async_client.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_audit_ux.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_auto_upgrade_policy.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_cli.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_cli_lock.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_client.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_client_json_guard.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_client_sprint_b.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_config.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_credential_handle.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_credential_integration.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_credential_resolver.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_credential_store.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_credential_vault.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_detect.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_detect_and_install.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_edge_cases.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_check.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_config_cache.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_policy.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_preview.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_schema.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_set.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_status.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_tool_override.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_tool_override_audit.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_tool_override_cli.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_guard_ux.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_input_guard.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_input_guard_escalation.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_install_hardening.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_installer_sprint_b.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_intelligence.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_key_status.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_llm_binding.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_llm_call_runlog.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_llm_providers.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_lock_integrity.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_lock_runtime.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_mcp_audit.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_mcp_doctor.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_mcp_server.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_observability.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_planner.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_policy.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_policy_integration.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_prompt_specs.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_provider_matrix.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_publish.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_references.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_registry_trust.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_remote_hardening.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_remote_runner.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_resource_provider.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_resource_specs.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_risk_profile.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_run_log.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_runner.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_runtime.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_runtime_audit.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_sandbox_backend.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_sandbox_doctor.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_sandbox_e2e.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_sandbox_gate.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_security_hardening.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_signature.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_signing_key.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_skill.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_smart.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_stability.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_toolpack_sandbox.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_v02.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_validate.py +0 -0
- {agentnode_sdk-0.15.0 → agentnode_sdk-0.17.0}/tests/test_validate_skill.py +0 -0
- {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.
|
|
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
|
|
@@ -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
|
|
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.
|
|
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
|
-
|
|
43
|
-
|
|
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
|
|
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
|
-
#
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
|
|
190
|
-
|
|
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
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
218
|
-
if
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
-
|
|
232
|
-
|
|
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
|
-
|
|
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} ({
|
|
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} ({
|
|
242
|
-
f"
|
|
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,
|
|
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,
|
|
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)
|