agentnode-sdk 0.18.0__tar.gz → 0.19.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.18.0 → agentnode_sdk-0.19.0}/CHANGELOG.md +35 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/PKG-INFO +1 -1
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/__init__.py +1 -1
- agentnode_sdk-0.19.0/agentnode_sdk/cli/setup_wizard.py +522 -0
- agentnode_sdk-0.19.0/dist-0.19.0/.gitignore +1 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/pyproject.toml +1 -1
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_setup_wizard.py +487 -397
- agentnode_sdk-0.18.0/agentnode_sdk/cli/setup_wizard.py +0 -370
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/.env.example +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/.gitignore +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/README.md +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/REGISTRY_SIGNING_ACTIVATION.md +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/REGISTRY_SIGNING_SPEC.md +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/THREAT_MODEL.md +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/TRUST_STACK.md +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode.lock +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/_fileutil.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/async_client.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/capability_graph.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/capability_taxonomy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/__init__.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/__main__.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/audit.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/auth.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/cassette_audit.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/commands.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/complements.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/init.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/main.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/mcp_commands.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/mcp_status.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/mcp_submit.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/mcp_verify.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/output.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/publish.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/record_cases.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/sandbox_commands.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/serve.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/smart_run.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/templates.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/validate.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/cli/verify_local.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/client.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/compatibility.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/config.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/credential_handle.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/credential_resolver.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/credential_store.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/detect.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/exceptions.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/guard.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/input_guard.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/installer.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/key_status.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/llm_providers.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/lock_integrity.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/mcp_server.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/models.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/planner.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/policy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/references.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/registry_trust.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/resolve.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/resource_provider.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/risk_profile.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/run_log.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runner.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtime.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtimes/__init__.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtimes/agent_llm_broker.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtimes/agent_llm_policy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtimes/agent_runner.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtimes/agent_sandbox.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtimes/mcp_consent.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtimes/mcp_consent_store.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtimes/mcp_runner.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtimes/python_runner.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/runtimes/remote_runner.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/__init__.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/agent_container_wrapper.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/agent_rpc.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/agent_session.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/backend.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/container_backend.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/domain_policy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/egress.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/egress_proxy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/mcp_preinstall.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/policy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/sandbox/types.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/signature.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/signing_key.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/agentnode_sdk/skill.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/data/compatibility/current.json +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/dist-0.18.0/.gitignore +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/sandbox-image/Dockerfile +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/sandbox-image/README.md +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/scripts/analyze_scores.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/scripts/batch_verify.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/scripts/ci_smoke_test.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/scripts/generate_compatibility_artifacts.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/scripts/merge_batches.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/scripts/verify_toolcalls.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/scripts/weekly_retest.sh +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/spikes/agent_sandbox_routing/README.md +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/spikes/agent_sandbox_routing/__init__.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/spikes/agent_sandbox_routing/container_agent_wrapper.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/spikes/agent_sandbox_routing/fake_llm.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/spikes/agent_sandbox_routing/host_driver.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/spikes/agent_sandbox_routing/trivial_agent.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/__init__.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/conftest.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/data/allowed_domains_vectors.json +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_agent_llm_broker.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_agent_llm_policy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_agent_rpc.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_agent_runner.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_agent_sandbox_e2e.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_agent_sandbox_routing.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_agent_sandbox_spike.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_agent_session_container.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_async_client.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_audit_ux.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_auth_cli_vault.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_auto_upgrade_policy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_cli.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_cli_lock.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_cli_run_resolution.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_client.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_client_json_guard.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_client_sprint_b.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_config.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_consent_prompt.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_credential_handle.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_credential_integration.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_credential_resolver.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_credential_store.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_credential_vault.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_detect.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_detect_and_install.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_domain_policy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_e2e_runtime.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_edge_cases.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_egress_domain_validation.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_egress_e2e.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_egress_lifecycle.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_egress_proxy_unit.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_egress_wrap.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_env_passthrough_wrap.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_check.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_config_cache.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_policy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_preview.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_schema.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_set.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_status.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_tool_override.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_tool_override_audit.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_tool_override_cli.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_guard_ux.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_host_trust_policy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_host_trust_policy_routing.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_input_guard.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_input_guard_escalation.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_install_hardening.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_installer_sprint_b.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_intelligence.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_key_status.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_llm_binding.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_llm_call_runlog.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_llm_providers.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_llm_vault_binding.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_lock_integrity.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_lock_runtime.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_allowed_domains_seal.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_audit.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_consent.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_consent_resolver.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_consent_store.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_credentialed_launch.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_doctor.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_preinstall.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_preinstall_run.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_sandbox.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_mcp_server.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_observability.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_planner.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_policy.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_policy_integration.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_prompt_specs.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_provider_matrix.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_publish.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_references.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_registry_trust.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_remote_hardening.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_remote_runner.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_resource_provider.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_resource_specs.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_risk_profile.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_run_log.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_runner.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_runtime.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_runtime_audit.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_sandbox_backend.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_sandbox_doctor.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_sandbox_e2e.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_sandbox_gate.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_security_hardening.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_signature.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_signing_key.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_skill.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_smart.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_stability.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_toolpack_sandbox.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_v02.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_validate.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/test_validate_skill.py +0 -0
- {agentnode_sdk-0.18.0 → agentnode_sdk-0.19.0}/tests/validation_lockfile.json +0 -0
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.0 — Full setup wizard coverage
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Expanded `agentnode setup` to cover the full first-class configuration surface
|
|
8
|
+
with multiple-choice prompts and clearly marked recommended defaults.
|
|
9
|
+
- Added a Guard posture step with Balanced, Strict, Permissive and Customize-each
|
|
10
|
+
options.
|
|
11
|
+
- Added setup support for `sandbox.host_trust_policy`.
|
|
12
|
+
- Added an optional Advanced gate for niche first-class settings.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Promoted minimum trust level to a direct setup screen.
|
|
17
|
+
- Added consistent `(recommended)` labels across setup choices.
|
|
18
|
+
- A stored LLM key provider can now be offered as the default LLM provider,
|
|
19
|
+
matching the existing Ollama behavior.
|
|
20
|
+
|
|
21
|
+
### Hardened
|
|
22
|
+
|
|
23
|
+
- Invalid interactive menu input now re-prompts instead of silently falling back
|
|
24
|
+
to the recommended option — a typo can no longer set a security choice unnoticed.
|
|
25
|
+
- Non-interactive (non-TTY) setup continues to take the recommended defaults and
|
|
26
|
+
never hangs.
|
|
27
|
+
- Accepting all recommended choices reproduces the current default configuration,
|
|
28
|
+
so upgrading changes nothing until you opt in.
|
|
29
|
+
|
|
30
|
+
### Notes
|
|
31
|
+
|
|
32
|
+
- Deeply nested configuration (`llm.providers`, the `agent_sandbox.llm` ceiling,
|
|
33
|
+
and `guard` overrides / rate limits) remains CLI/manual-only by design and is
|
|
34
|
+
surfaced as follow-up commands rather than turned into a wizard editor.
|
|
35
|
+
- This release changes only the setup wizard; runtime behavior and the default
|
|
36
|
+
configuration are unchanged.
|
|
37
|
+
|
|
3
38
|
## 0.18.0 — User-controlled host-trust policy
|
|
4
39
|
|
|
5
40
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentnode-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.19.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
|
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
"""AgentNode setup wizard — interactive configuration.
|
|
2
|
+
|
|
3
|
+
Covers the full first-class config surface with multiple-choice prompts; the
|
|
4
|
+
recommended option is marked "(recommended)" and is the default (Enter / non-TTY).
|
|
5
|
+
Accepting every recommendation reproduces ``default_config()`` exactly, so the
|
|
6
|
+
wizard is non-breaking by construction.
|
|
7
|
+
|
|
8
|
+
Deeply nested config (``llm.providers``, the ``agent_sandbox.llm`` ceiling, and
|
|
9
|
+
``guard.tool_overrides`` / ``agent_overrides`` / ``rate_limits``) stays CLI/manual
|
|
10
|
+
only BY DESIGN and is surfaced only as follow-up hints — the wizard is a
|
|
11
|
+
first-class-settings tool, not a nested YAML editor.
|
|
12
|
+
|
|
13
|
+
UX invariants preserved:
|
|
14
|
+
- Config is built by mutating ``default_config()`` + one ``save_config(cfg)`` — not
|
|
15
|
+
per-key config setters (booleans persist as real bools).
|
|
16
|
+
- No docker calls here; the only sandbox action is the reused ``cmd_sandbox_pull``.
|
|
17
|
+
- Credentials via getpass/env-import only, masked output, honest storage labels.
|
|
18
|
+
- Non-TTY never hangs: every prompt falls back to its recommended/default. An
|
|
19
|
+
invalid *interactive* choice re-prompts — a typo must not set a security choice.
|
|
20
|
+
"""
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
from agentnode_sdk.config import (
|
|
26
|
+
default_config,
|
|
27
|
+
installation_behavior_label,
|
|
28
|
+
save_config,
|
|
29
|
+
)
|
|
30
|
+
from agentnode_sdk.cli.output import bold, dim, kv, section
|
|
31
|
+
|
|
32
|
+
# Key-provider menu (grouped for readability); choice 8 = ollama (keyless,
|
|
33
|
+
# handled separately — never a key prompt), choice 9 = skip (the default).
|
|
34
|
+
_LLM_CHOICES = {
|
|
35
|
+
"1": "openai", "2": "anthropic", "3": "openrouter",
|
|
36
|
+
"4": "deepseek", "5": "mistral", "6": "qwen", "7": "gemini",
|
|
37
|
+
}
|
|
38
|
+
_OLLAMA_CHOICE = "8"
|
|
39
|
+
_SKIP_CHOICE = "9"
|
|
40
|
+
|
|
41
|
+
# Guard action types in a risk-ordered display order + friendly labels.
|
|
42
|
+
_GUARD_ORDER = [
|
|
43
|
+
"delete", "write_external", "execute", "credential_use",
|
|
44
|
+
"network_egress", "write_local", "read", "compute", "unknown",
|
|
45
|
+
]
|
|
46
|
+
_GUARD_LABELS = {
|
|
47
|
+
"delete": "Delete resources",
|
|
48
|
+
"write_external": "Write / send externally",
|
|
49
|
+
"execute": "Execute code",
|
|
50
|
+
"credential_use": "Use credentials",
|
|
51
|
+
"network_egress": "Network egress",
|
|
52
|
+
"write_local": "Write locally",
|
|
53
|
+
"read": "Read data",
|
|
54
|
+
"compute": "Compute",
|
|
55
|
+
"unknown": "Unknown action type",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def run_wizard() -> int:
|
|
60
|
+
"""Run the setup wizard. Returns exit code."""
|
|
61
|
+
try:
|
|
62
|
+
cfg = _wizard_flow()
|
|
63
|
+
return 0 if cfg is not None else 1
|
|
64
|
+
except (KeyboardInterrupt, EOFError):
|
|
65
|
+
print("\n\nSetup cancelled.")
|
|
66
|
+
return 130
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _prompt(text: str, default: str = "") -> str:
|
|
70
|
+
result = input(text).strip()
|
|
71
|
+
return result if result else default
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _pick(title: str, options: list[tuple[str, object]], recommended: int,
|
|
75
|
+
notes: list[str] | None = None) -> object:
|
|
76
|
+
"""Multiple-choice menu. ``options`` = ``[(label, value), ...]`` (1-indexed);
|
|
77
|
+
``recommended`` is the 1-based index of the recommended option (also the
|
|
78
|
+
Enter/non-TTY default). ``notes`` (optional, same length) renders each option
|
|
79
|
+
on its own line with a dim hint.
|
|
80
|
+
|
|
81
|
+
Empty input → recommended. Non-TTY → recommended (never hangs). An INVALID
|
|
82
|
+
interactive choice re-prompts (``Please choose 1–N.``) — it never silently
|
|
83
|
+
falls back to the recommended value, so a typo cannot set a security choice.
|
|
84
|
+
"""
|
|
85
|
+
n = len(options)
|
|
86
|
+
print(f" {title}")
|
|
87
|
+
if notes:
|
|
88
|
+
width = max(len(label) for label, _ in options) + 18
|
|
89
|
+
for i, (label, _v) in enumerate(options, 1):
|
|
90
|
+
tag = " (recommended)" if i == recommended else ""
|
|
91
|
+
left = f" [{i}] {label}{tag}"
|
|
92
|
+
print(f"{left:<{width}}{dim(notes[i - 1])}")
|
|
93
|
+
else:
|
|
94
|
+
cells = []
|
|
95
|
+
for i, (label, _v) in enumerate(options, 1):
|
|
96
|
+
tag = " (recommended)" if i == recommended else ""
|
|
97
|
+
cells.append(f"[{i}] {label}{tag}")
|
|
98
|
+
print(" " + " ".join(cells))
|
|
99
|
+
|
|
100
|
+
if not sys.stdin.isatty():
|
|
101
|
+
return options[recommended - 1][1]
|
|
102
|
+
while True:
|
|
103
|
+
raw = _prompt(f" Choice [{recommended}]: ")
|
|
104
|
+
if not raw:
|
|
105
|
+
return options[recommended - 1][1]
|
|
106
|
+
if raw.isdigit() and 1 <= int(raw) <= n:
|
|
107
|
+
return options[int(raw) - 1][1]
|
|
108
|
+
print(f" Please choose 1–{n}.")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _store_llm_key(provider: str) -> str | None:
|
|
112
|
+
"""Store one provider key via the vault. Returns the short storage label
|
|
113
|
+
("OS keychain"/"plaintext file") on success, None when skipped.
|
|
114
|
+
|
|
115
|
+
Key entry is getpass-only (hidden, never argv); if the provider's env var
|
|
116
|
+
is already set (incl. ~/.agentnode/.env), offers to import it instead.
|
|
117
|
+
Output shows only the masked tail and the honest storage label."""
|
|
118
|
+
import getpass
|
|
119
|
+
import os
|
|
120
|
+
|
|
121
|
+
from agentnode_sdk.cli.auth import _masked, _storage_short, cmd_auth_test
|
|
122
|
+
from agentnode_sdk.credential_store import set_credential
|
|
123
|
+
|
|
124
|
+
from agentnode_sdk.llm_providers import resolve_provider_spec
|
|
125
|
+
env_var = (resolve_provider_spec(provider) or {}).get("api_key_env") or ""
|
|
126
|
+
try:
|
|
127
|
+
from agentnode_sdk.runtimes.agent_runner import _load_agentnode_env
|
|
128
|
+
_load_agentnode_env()
|
|
129
|
+
except Exception:
|
|
130
|
+
pass
|
|
131
|
+
env_val = (os.environ.get(env_var) or "").strip() if env_var else ""
|
|
132
|
+
|
|
133
|
+
token = ""
|
|
134
|
+
if env_val:
|
|
135
|
+
print(f" Found {env_var} in your environment (env always overrides stored keys).")
|
|
136
|
+
imp = _prompt(f" Store this key from {env_var}? [Y/n]: ", "y")
|
|
137
|
+
if imp.lower() != "n":
|
|
138
|
+
token = env_val
|
|
139
|
+
if not token:
|
|
140
|
+
token = getpass.getpass(f" Enter API key for {provider} (input hidden): ").strip()
|
|
141
|
+
if not token:
|
|
142
|
+
print(" No key entered — skipped.")
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
storage = set_credential(provider, token, auth_type="api_key")
|
|
146
|
+
if storage == "keyring":
|
|
147
|
+
where = "OS keychain"
|
|
148
|
+
else:
|
|
149
|
+
where = "plaintext file (0600) — OS keychain unavailable on this system"
|
|
150
|
+
print(f" Credential stored for {provider} ({_masked(token)}) — storage: {where}.")
|
|
151
|
+
|
|
152
|
+
t = _prompt(" Test the key now? (free endpoint, no completion call) [Y/n]: ", "y")
|
|
153
|
+
if t.lower() != "n":
|
|
154
|
+
try:
|
|
155
|
+
rc = cmd_auth_test(provider)
|
|
156
|
+
except Exception:
|
|
157
|
+
rc = 3
|
|
158
|
+
if rc not in (0, 1):
|
|
159
|
+
# indeterminate/network — never block the wizard on it
|
|
160
|
+
print(dim(f" Could not verify right now — test later with "
|
|
161
|
+
f"`agentnode auth test {provider}`."))
|
|
162
|
+
return _storage_short(storage)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _credentials_screen(cfg: dict) -> list[tuple[str, str]]:
|
|
166
|
+
"""Screen: LLM credentials (optional, default = skip). Key providers come
|
|
167
|
+
from the registry-backed menu; ollama is a keyless CONFIG selection. After a
|
|
168
|
+
key provider is stored, offers to make it the default provider (mirrors the
|
|
169
|
+
ollama path). Returns the (provider, storage label) pairs selected."""
|
|
170
|
+
print()
|
|
171
|
+
print(bold(" LLM credentials (optional)"))
|
|
172
|
+
print()
|
|
173
|
+
print(" Agents and the sandboxed-agent LLM broker need a provider API key.")
|
|
174
|
+
print(" Keys are stored in your OS keychain when available; otherwise in a")
|
|
175
|
+
print(" plaintext file (0600) — AgentNode will tell you which.")
|
|
176
|
+
print()
|
|
177
|
+
|
|
178
|
+
if not sys.stdin.isatty():
|
|
179
|
+
print(dim(" Non-interactive session — skipping. Add keys later with"))
|
|
180
|
+
print(dim(" `agentnode auth set <provider>`."))
|
|
181
|
+
return []
|
|
182
|
+
|
|
183
|
+
stored: list[tuple[str, str]] = []
|
|
184
|
+
all_options = list(_LLM_CHOICES) + [_OLLAMA_CHOICE, _SKIP_CHOICE]
|
|
185
|
+
while True:
|
|
186
|
+
print(" Recommended: [1] OpenAI [2] Anthropic [3] OpenRouter")
|
|
187
|
+
print(" More: [4] DeepSeek [5] Mistral [6] Qwen [7] Gemini")
|
|
188
|
+
print(" Local: [8] Ollama — keyless, requires a running Ollama")
|
|
189
|
+
print(" [9] Skip for now (recommended)")
|
|
190
|
+
c = _prompt(" Choice [9]: ", _SKIP_CHOICE)
|
|
191
|
+
if c not in all_options:
|
|
192
|
+
print(" Please choose 1–9.")
|
|
193
|
+
continue
|
|
194
|
+
if c == _SKIP_CHOICE:
|
|
195
|
+
break
|
|
196
|
+
if c == _OLLAMA_CHOICE:
|
|
197
|
+
# keyless local provider: a config selection, NOT a credential.
|
|
198
|
+
if any(p == "ollama" for p, _ in stored):
|
|
199
|
+
print(" ollama already selected in this run.")
|
|
200
|
+
else:
|
|
201
|
+
print(" Ollama runs models locally — no API key, no per-token cost.")
|
|
202
|
+
print(dim(" Requires a running Ollama (https://ollama.com); the wizard"))
|
|
203
|
+
print(dim(" does not start or probe it."))
|
|
204
|
+
use = _prompt(" Use Ollama as your default LLM provider? [Y/n]: ", "y")
|
|
205
|
+
if use.lower() != "n":
|
|
206
|
+
cfg["llm"]["default_provider"] = "ollama"
|
|
207
|
+
stored.append(("ollama", "local, keyless"))
|
|
208
|
+
print(dim(" Selected. Test later with `agentnode auth test ollama`."))
|
|
209
|
+
else:
|
|
210
|
+
provider = _LLM_CHOICES[c]
|
|
211
|
+
if any(p == provider for p, _ in stored):
|
|
212
|
+
print(f" {provider} already added in this run.")
|
|
213
|
+
else:
|
|
214
|
+
label = _store_llm_key(provider)
|
|
215
|
+
if label is not None:
|
|
216
|
+
stored.append((provider, label))
|
|
217
|
+
if len(stored) >= len(_LLM_CHOICES) + 1:
|
|
218
|
+
break
|
|
219
|
+
more = _prompt(" Add another provider? [y/N]: ", "n")
|
|
220
|
+
if more.lower() != "y":
|
|
221
|
+
break
|
|
222
|
+
|
|
223
|
+
# Offer to make a stored KEY provider the default (ollama already sets it above).
|
|
224
|
+
key_providers = [p for p, _ in stored if p != "ollama"]
|
|
225
|
+
if key_providers and cfg["llm"]["default_provider"] not in key_providers:
|
|
226
|
+
first = key_providers[0]
|
|
227
|
+
ans = _prompt(f" Use {first} as your default LLM provider? [Y/n]: ", "y")
|
|
228
|
+
if ans.lower() != "n":
|
|
229
|
+
cfg["llm"]["default_provider"] = first
|
|
230
|
+
return stored
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _guard_screen(cfg: dict) -> str:
|
|
234
|
+
"""Screen: Guard posture. Sets the 9 ``guard.<action>`` keys from a preset
|
|
235
|
+
bundle, or drills into all 9 individually on "Customize each". Reuses
|
|
236
|
+
guard.py's shipped Balanced (== defaults) and Strict bundles. Returns the
|
|
237
|
+
chosen posture label for the Summary."""
|
|
238
|
+
from agentnode_sdk.guard import _DEFAULT_GUARD_POLICY, _STRICT_GUARD_POLICY
|
|
239
|
+
|
|
240
|
+
print()
|
|
241
|
+
print(bold(" Guard posture"))
|
|
242
|
+
print()
|
|
243
|
+
print(" How tools are gated at run time (the pre-execution policy).")
|
|
244
|
+
posture = _pick("Choose a posture", [
|
|
245
|
+
("Balanced", "balanced"),
|
|
246
|
+
("Strict", "strict"),
|
|
247
|
+
("Permissive", "permissive"),
|
|
248
|
+
("Customize each", "custom"),
|
|
249
|
+
], recommended=1, notes=[
|
|
250
|
+
"risky actions ask, safe ones allow",
|
|
251
|
+
"destructive actions denied, more prompts",
|
|
252
|
+
"allow everything, ask only on unknown",
|
|
253
|
+
"set all 9 action types yourself",
|
|
254
|
+
])
|
|
255
|
+
|
|
256
|
+
if posture == "balanced":
|
|
257
|
+
pass # cfg["guard"] is already the shipped default == Balanced
|
|
258
|
+
elif posture == "strict":
|
|
259
|
+
cfg["guard"].update(_STRICT_GUARD_POLICY)
|
|
260
|
+
elif posture == "permissive":
|
|
261
|
+
cfg["guard"].update({a: "allow" for a in _GUARD_ORDER})
|
|
262
|
+
cfg["guard"]["unknown"] = "prompt"
|
|
263
|
+
else: # custom — recommended per action = the Balanced value
|
|
264
|
+
print()
|
|
265
|
+
print(dim(" Set each action type (allow / prompt / deny):"))
|
|
266
|
+
pol = ("allow", "allow"), ("prompt", "prompt"), ("deny", "deny")
|
|
267
|
+
idx = {"allow": 1, "prompt": 2, "deny": 3}
|
|
268
|
+
for action in _GUARD_ORDER:
|
|
269
|
+
rec = idx[_DEFAULT_GUARD_POLICY[action]]
|
|
270
|
+
cfg["guard"][action] = _pick(_GUARD_LABELS[action], list(pol), recommended=rec)
|
|
271
|
+
return posture
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def _sandbox_screen(cfg: dict) -> tuple[str, bool]:
|
|
275
|
+
"""Screen: host-trust policy + local sandbox.
|
|
276
|
+
|
|
277
|
+
Sets ``sandbox.host_trust_policy`` (which trust tiers may run on the host),
|
|
278
|
+
then diagnoses the container runtime via the doctor's read-only
|
|
279
|
+
``_build_env_checks``. The ONLY action is an optional, TTY-confirmed image
|
|
280
|
+
pull via the existing ``cmd_sandbox_pull`` — the wizard never talks to docker.
|
|
281
|
+
The agent-sandbox enable prompt (default No) is offered only when the sandbox
|
|
282
|
+
is fully ready. Returns (status line for Summary/Success, image_still_missing).
|
|
283
|
+
"""
|
|
284
|
+
from agentnode_sdk.cli.sandbox_commands import _build_env_checks, cmd_sandbox_pull
|
|
285
|
+
|
|
286
|
+
print()
|
|
287
|
+
print(bold(" Sandbox & host-trust policy"))
|
|
288
|
+
print()
|
|
289
|
+
print(" Community packages always run in an isolated container sandbox.")
|
|
290
|
+
print(" Trusted/curated packages run on the host under the default policy —")
|
|
291
|
+
print(" the host-trust policy can sandbox them too.")
|
|
292
|
+
print()
|
|
293
|
+
|
|
294
|
+
htp = _pick("Which trust tiers may run directly on your host?", [
|
|
295
|
+
("Default", "default"),
|
|
296
|
+
("Curated only", "curated_only"),
|
|
297
|
+
("None", "none"),
|
|
298
|
+
], recommended=1, notes=[
|
|
299
|
+
"curated + trusted on host (today's behavior)",
|
|
300
|
+
"trusted is sandboxed; only curated on host",
|
|
301
|
+
"everything sandboxed; nothing on the host",
|
|
302
|
+
])
|
|
303
|
+
cfg["sandbox"]["host_trust_policy"] = htp
|
|
304
|
+
if htp != "default":
|
|
305
|
+
print(dim(" Note: stronger isolation can break trusted/curated packages that"))
|
|
306
|
+
print(dim(" expect host FS, broad tools, LLM keys or network — a reinstall may"))
|
|
307
|
+
print(dim(" be needed. Check with `agentnode sandbox doctor <slug>`."))
|
|
308
|
+
print()
|
|
309
|
+
|
|
310
|
+
checks, ready, image_missing = _build_env_checks()
|
|
311
|
+
|
|
312
|
+
def _render(check_list):
|
|
313
|
+
for c in check_list:
|
|
314
|
+
mark = "[OK]" if c["ok"] else ("[--]" if c["ok"] is None else "[!!]")
|
|
315
|
+
print(f" {mark} {c['check']}: {c['detail']}")
|
|
316
|
+
if c["ok"] is False and c.get("fix"):
|
|
317
|
+
print(dim(f" -> {c['fix']}"))
|
|
318
|
+
|
|
319
|
+
_render(checks)
|
|
320
|
+
print()
|
|
321
|
+
|
|
322
|
+
if image_missing and not ready:
|
|
323
|
+
if sys.stdin.isatty():
|
|
324
|
+
print(" Pull the pinned AgentNode sandbox image now? [y/N]")
|
|
325
|
+
print(dim(" This downloads the digest-pinned sandbox image."))
|
|
326
|
+
print(dim(" It does not install Docker/Podman."))
|
|
327
|
+
print(dim(" It does not enable auto-pull."))
|
|
328
|
+
answer = _prompt(" > ", "n")
|
|
329
|
+
if answer.lower() == "y":
|
|
330
|
+
rc = cmd_sandbox_pull()
|
|
331
|
+
if rc == 0:
|
|
332
|
+
checks, ready, image_missing = _build_env_checks()
|
|
333
|
+
else:
|
|
334
|
+
print(dim(" Pull failed or was skipped — the wizard continues."))
|
|
335
|
+
print(dim(" Run `agentnode sandbox pull` later."))
|
|
336
|
+
else:
|
|
337
|
+
print(dim(" Skipped. Run `agentnode sandbox pull` when ready."))
|
|
338
|
+
else:
|
|
339
|
+
print(dim(" Non-interactive session — run `agentnode sandbox doctor` later."))
|
|
340
|
+
|
|
341
|
+
if ready:
|
|
342
|
+
print()
|
|
343
|
+
print(" Sandbox ready — community packages run isolated.")
|
|
344
|
+
print()
|
|
345
|
+
print(" Sandboxed community agents are currently disabled (default).")
|
|
346
|
+
print(" Enabling lets verified/unverified community agents run isolated;")
|
|
347
|
+
print(" without it they are refused.")
|
|
348
|
+
if sys.stdin.isatty():
|
|
349
|
+
en = _prompt(" Enable sandboxed community agents now? [y/N]: ", "n")
|
|
350
|
+
if en.lower() == "y":
|
|
351
|
+
cfg["agent_sandbox"]["enabled"] = True
|
|
352
|
+
else:
|
|
353
|
+
print(dim(" You can enable it later with "
|
|
354
|
+
"`agentnode config set agent_sandbox.enabled true`."))
|
|
355
|
+
else:
|
|
356
|
+
print(dim(" Enable later with "
|
|
357
|
+
"`agentnode config set agent_sandbox.enabled true`."))
|
|
358
|
+
return "ready", False
|
|
359
|
+
|
|
360
|
+
from agentnode_sdk.cli.sandbox_commands import _first_failure
|
|
361
|
+
fail = _first_failure(checks)
|
|
362
|
+
detail = (fail or {}).get("detail", "not ready")
|
|
363
|
+
print(dim(" Not ready — details and guidance: agentnode sandbox doctor"))
|
|
364
|
+
return f"not ready — {detail}", image_missing
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def _advanced_screen(cfg: dict) -> None:
|
|
368
|
+
"""Screen: advanced settings (opt-in gate, default No, non-TTY skip). Covers
|
|
369
|
+
the two niche first-class keys; deeper nested config stays CLI-only."""
|
|
370
|
+
print()
|
|
371
|
+
print(bold(" Advanced settings (optional)"))
|
|
372
|
+
print()
|
|
373
|
+
if not sys.stdin.isatty():
|
|
374
|
+
return
|
|
375
|
+
if _prompt(" Configure advanced settings? [y/N]: ", "n").lower() != "y":
|
|
376
|
+
return
|
|
377
|
+
|
|
378
|
+
cfg["credentials"]["require_before_auto_install"] = _pick(
|
|
379
|
+
"During auto-install, skip packages needing credentials you don't have?",
|
|
380
|
+
[("Yes", True), ("No", False)], recommended=1,
|
|
381
|
+
notes=["skip them (recommended)", "try anyway"])
|
|
382
|
+
cfg["risk_policies"]["external_write_capable"] = _pick(
|
|
383
|
+
"Packages that can write or send data externally",
|
|
384
|
+
[("log", "log"), ("allow", "allow"), ("prompt", "prompt"), ("deny", "deny")],
|
|
385
|
+
recommended=1)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def _wizard_flow() -> dict | None:
|
|
389
|
+
cfg = default_config()
|
|
390
|
+
|
|
391
|
+
# Screen 1: Intro
|
|
392
|
+
print()
|
|
393
|
+
print(section("AgentNode Setup"))
|
|
394
|
+
print(" Configure how AgentNode manages capabilities for your agents.")
|
|
395
|
+
print(" Each choice marks our (recommended) default — press Enter to accept it.")
|
|
396
|
+
print(" You can change everything later with `agentnode setup` or `config set`.")
|
|
397
|
+
print()
|
|
398
|
+
print(dim(" Press Enter to continue..."))
|
|
399
|
+
_prompt("")
|
|
400
|
+
|
|
401
|
+
# Screen 2: Installation behavior (one choice -> two keys)
|
|
402
|
+
print()
|
|
403
|
+
print(bold(" Installation behavior"))
|
|
404
|
+
print()
|
|
405
|
+
behavior = _pick("How should capabilities be installed?", [
|
|
406
|
+
("Automatic", "auto"),
|
|
407
|
+
("Review before install", "review"),
|
|
408
|
+
("Manual only", "manual"),
|
|
409
|
+
], recommended=1, notes=[
|
|
410
|
+
"install verified capabilities without asking",
|
|
411
|
+
"ask before each installation",
|
|
412
|
+
"never install automatically",
|
|
413
|
+
])
|
|
414
|
+
if behavior == "auto":
|
|
415
|
+
cfg["auto_upgrade_policy"] = "safe"
|
|
416
|
+
cfg["install_confirmation"] = "auto"
|
|
417
|
+
elif behavior == "review":
|
|
418
|
+
cfg["auto_upgrade_policy"] = "safe"
|
|
419
|
+
cfg["install_confirmation"] = "prompt"
|
|
420
|
+
else:
|
|
421
|
+
cfg["auto_upgrade_policy"] = "off"
|
|
422
|
+
cfg["install_confirmation"] = "auto"
|
|
423
|
+
|
|
424
|
+
# Screen 3: Trust level (now a direct screen)
|
|
425
|
+
print()
|
|
426
|
+
print(bold(" Minimum trust level"))
|
|
427
|
+
print()
|
|
428
|
+
cfg["trust"]["minimum_trust_level"] = _pick("Minimum trust tier to install/run", [
|
|
429
|
+
("verified", "verified"),
|
|
430
|
+
("trusted", "trusted"),
|
|
431
|
+
("curated", "curated"),
|
|
432
|
+
], recommended=1, notes=[
|
|
433
|
+
"community-reviewed packages",
|
|
434
|
+
"manually approved by the AgentNode team",
|
|
435
|
+
"official AgentNode packages only",
|
|
436
|
+
])
|
|
437
|
+
|
|
438
|
+
# Screen 4: Permission defaults
|
|
439
|
+
print()
|
|
440
|
+
print(bold(" Permission defaults"))
|
|
441
|
+
print()
|
|
442
|
+
cfg["permissions"]["network"] = _pick(
|
|
443
|
+
"Network access", [("allow", "allow"), ("prompt", "prompt"), ("deny", "deny")],
|
|
444
|
+
recommended=2)
|
|
445
|
+
cfg["permissions"]["filesystem"] = _pick(
|
|
446
|
+
"Filesystem access", [("allow", "allow"), ("prompt", "prompt"), ("deny", "deny")],
|
|
447
|
+
recommended=2)
|
|
448
|
+
cfg["permissions"]["code_execution"] = _pick(
|
|
449
|
+
"Code execution",
|
|
450
|
+
[("sandboxed", "sandboxed"), ("prompt", "prompt"), ("deny", "deny")],
|
|
451
|
+
recommended=1)
|
|
452
|
+
|
|
453
|
+
# Screen 5: Guard posture (sets the 9 guard.* keys)
|
|
454
|
+
guard_posture = _guard_screen(cfg)
|
|
455
|
+
|
|
456
|
+
# Screen 6: LLM credentials (optional)
|
|
457
|
+
stored_providers = _credentials_screen(cfg)
|
|
458
|
+
|
|
459
|
+
# Screen 7: Sandbox + host-trust policy
|
|
460
|
+
sandbox_status, image_missing = _sandbox_screen(cfg)
|
|
461
|
+
|
|
462
|
+
# Screen 8: Advanced (opt-in)
|
|
463
|
+
_advanced_screen(cfg)
|
|
464
|
+
|
|
465
|
+
# Screen 9: Summary
|
|
466
|
+
print()
|
|
467
|
+
print(section("Summary"))
|
|
468
|
+
print(kv("Installation behavior", installation_behavior_label(cfg)))
|
|
469
|
+
print(kv("Trust level", cfg["trust"]["minimum_trust_level"]))
|
|
470
|
+
print(kv("Guard posture", guard_posture))
|
|
471
|
+
if stored_providers:
|
|
472
|
+
creds_line = ", ".join(f"{p} ({label})" for p, label in stored_providers)
|
|
473
|
+
else:
|
|
474
|
+
creds_line = "none — add later with `agentnode auth set <provider>`"
|
|
475
|
+
print(kv("LLM credentials", creds_line))
|
|
476
|
+
print(kv("LLM default provider", cfg["llm"]["default_provider"]))
|
|
477
|
+
print(kv("Host-trust policy", cfg["sandbox"]["host_trust_policy"]))
|
|
478
|
+
print(kv("Sandbox", sandbox_status))
|
|
479
|
+
print(kv("Agent sandbox",
|
|
480
|
+
"enabled" if cfg["agent_sandbox"]["enabled"] else "disabled"))
|
|
481
|
+
print()
|
|
482
|
+
print(" Permissions")
|
|
483
|
+
print(" " + "-" * 11)
|
|
484
|
+
print(kv("Network", cfg["permissions"]["network"]))
|
|
485
|
+
print(kv("Filesystem", cfg["permissions"]["filesystem"]))
|
|
486
|
+
print(kv("Code execution", cfg["permissions"]["code_execution"]))
|
|
487
|
+
print()
|
|
488
|
+
confirm = _prompt(" Save? [Y/n]: ", "y")
|
|
489
|
+
if confirm.lower() == "n":
|
|
490
|
+
print("\n Setup cancelled. No changes saved.")
|
|
491
|
+
return None
|
|
492
|
+
|
|
493
|
+
save_config(cfg)
|
|
494
|
+
|
|
495
|
+
# Screen 10: Success
|
|
496
|
+
print()
|
|
497
|
+
print(bold(" Configuration saved."))
|
|
498
|
+
print()
|
|
499
|
+
print(kv("Sandbox", sandbox_status))
|
|
500
|
+
print(kv("Host-trust policy", cfg["sandbox"]["host_trust_policy"]))
|
|
501
|
+
print(dim(" Community packages need a local sandbox. Trusted/curated packages"))
|
|
502
|
+
print(dim(" run on the host unless the host-trust policy sandboxes them."))
|
|
503
|
+
print()
|
|
504
|
+
print(dim(" Next steps:"))
|
|
505
|
+
print(dim(" agentnode auth status check your credentials"))
|
|
506
|
+
print(dim(" agentnode sandbox doctor check the sandbox runtime"))
|
|
507
|
+
if image_missing:
|
|
508
|
+
print(dim(" agentnode sandbox pull fetch the sandbox image"))
|
|
509
|
+
if not cfg["agent_sandbox"]["enabled"]:
|
|
510
|
+
print(dim(" agentnode config set agent_sandbox.enabled true"))
|
|
511
|
+
print(dim(" enable sandboxed community agents"))
|
|
512
|
+
print(dim(" agentnode install word-counter-pack install a first capability"))
|
|
513
|
+
print(dim(" agentnode run word-counter-pack --input '{\"text\":\"hello\"}'"))
|
|
514
|
+
print(dim(" agentnode doctor check your whole setup"))
|
|
515
|
+
print()
|
|
516
|
+
print(dim(" Fine-tuning beyond these settings (CLI):"))
|
|
517
|
+
print(dim(" agentnode guard set <action> <policy> per-action guard overrides"))
|
|
518
|
+
print(dim(" agentnode config set sandbox.host_trust_policy <default|curated_only|none>"))
|
|
519
|
+
print(dim(" agentnode config set llm.default_provider <provider> (custom endpoints via config)"))
|
|
520
|
+
print()
|
|
521
|
+
|
|
522
|
+
return cfg
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agentnode-sdk"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.19.0"
|
|
8
8
|
description = "Python SDK for AgentNode — the open upgrade and discovery infrastructure for AI agents."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|