agentnode-sdk 0.21.0__tar.gz → 0.22.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.21.0 → agentnode_sdk-0.22.0}/CHANGELOG.md +20 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/PKG-INFO +1 -1
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/__init__.py +1 -1
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/commands.py +8 -3
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/main.py +1 -1
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/publish.py +14 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/templates.py +86 -0
- agentnode_sdk-0.22.0/agentnode_sdk/compatibility.py +144 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/data/compatibility/current.json +3303 -999
- agentnode_sdk-0.22.0/data/compatibility/removed_2026-07-09.txt +40 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/pyproject.toml +1 -1
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/scripts/check_model_drift.py +6 -4
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/scripts/ci_smoke_test.py +9 -1
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/scripts/generate_compatibility_artifacts.py +8 -1
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/scripts/merge_batches.py +259 -196
- agentnode_sdk-0.22.0/tests/test_mcp_cli_scaffold.py +91 -0
- agentnode_sdk-0.21.0/agentnode_sdk/compatibility.py +0 -139
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/.env.example +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/.gitignore +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/README.md +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/REGISTRY_SIGNING_ACTIVATION.md +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/REGISTRY_SIGNING_SPEC.md +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/THREAT_MODEL.md +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/TRUST_STACK.md +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode.lock +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/_fileutil.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/async_client.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/capability_graph.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/capability_taxonomy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/__init__.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/__main__.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/audit.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/auth.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/cassette_audit.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/complements.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/init.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/mcp_commands.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/mcp_status.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/mcp_submit.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/mcp_verify.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/output.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/record_cases.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/sandbox_commands.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/serve.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/setup_wizard.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/smart_run.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/validate.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/cli/verify_local.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/client.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/config.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/credential_handle.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/credential_resolver.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/credential_store.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/detect.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/exceptions.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/guard.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/input_guard.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/installer.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/key_status.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/llm_providers.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/lock_integrity.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/mcp_server.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/models.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/planner.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/policy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/references.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/registry_trust.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/resolve.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/resource_provider.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/risk_profile.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/run_log.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runner.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtime.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/__init__.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/agent_llm_broker.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/agent_llm_policy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/agent_runner.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/agent_sandbox.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/mcp_consent.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/mcp_consent_store.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/mcp_runner.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/python_runner.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/remote_runner.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/runtimes/toolpack_credentials.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/__init__.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/agent_container_wrapper.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/agent_rpc.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/agent_session.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/backend.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/container_backend.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/domain_policy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/egress.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/egress_proxy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/mcp_preinstall.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/policy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/sandbox/types.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/signature.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/signing_key.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/agentnode_sdk/skill.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/dist-0.18.0/.gitignore +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/dist-0.19.0/.gitignore +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/sandbox-image/Dockerfile +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/sandbox-image/README.md +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/scripts/analyze_scores.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/scripts/batch_verify.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/scripts/verify_toolcalls.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/scripts/weekly_retest.sh +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/spikes/agent_sandbox_routing/README.md +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/spikes/agent_sandbox_routing/__init__.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/spikes/agent_sandbox_routing/container_agent_wrapper.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/spikes/agent_sandbox_routing/fake_llm.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/spikes/agent_sandbox_routing/host_driver.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/spikes/agent_sandbox_routing/trivial_agent.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/__init__.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/conftest.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/data/allowed_domains_vectors.json +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_agent_llm_broker.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_agent_llm_policy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_agent_rpc.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_agent_runner.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_agent_sandbox_e2e.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_agent_sandbox_hardening.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_agent_sandbox_routing.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_agent_sandbox_spike.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_agent_session_container.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_async_client.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_audit_ux.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_auth_cli_vault.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_auto_upgrade_policy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_cli.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_cli_lock.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_cli_run_resolution.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_client.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_client_json_guard.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_client_sprint_b.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_config.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_consent_prompt.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_credential_handle.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_credential_integration.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_credential_resolver.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_credential_store.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_credential_vault.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_detect.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_detect_and_install.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_domain_policy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_e2e_runtime.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_edge_cases.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_egress_domain_validation.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_egress_e2e.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_egress_lifecycle.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_egress_proxy_unit.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_egress_wrap.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_env_passthrough_wrap.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_check.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_config_cache.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_policy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_preview.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_schema.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_set.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_status.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_tool_override.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_tool_override_audit.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_tool_override_cli.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_guard_ux.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_host_trust_policy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_host_trust_policy_routing.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_input_guard.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_input_guard_escalation.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_install_hardening.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_installer_sprint_b.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_intelligence.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_key_status.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_llm_binding.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_llm_call_runlog.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_llm_providers.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_llm_vault_binding.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_lock_integrity.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_lock_runtime.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_allowed_domains_seal.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_audit.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_consent.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_consent_resolver.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_consent_store.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_credentialed_launch.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_doctor.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_preinstall.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_preinstall_run.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_sandbox.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_server.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_mcp_submit.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_observability.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_planner.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_policy.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_policy_integration.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_prompt_specs.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_provider_matrix.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_publish.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_references.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_registry_trust.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_remote_hardening.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_remote_runner.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_resource_provider.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_resource_specs.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_risk_profile.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_run_log.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_runner.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_runtime.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_runtime_audit.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_sandbox_backend.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_sandbox_doctor.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_sandbox_e2e.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_sandbox_gate.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_security_hardening.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_setup_wizard.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_signature.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_signing_key.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_skill.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_smart.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_stability.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_toolpack_credentials.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_toolpack_credentials_b.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_toolpack_sandbox.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_v02.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_validate.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/test_validate_skill.py +0 -0
- {agentnode_sdk-0.21.0 → agentnode_sdk-0.22.0}/tests/validation_lockfile.json +0 -0
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.22.0 — MCP from the terminal + refreshed compatibility
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `agentnode init --type mcp` scaffolds an MCP server listing: a schema-valid
|
|
8
|
+
manifest (runtime `mcp`, a pinned `mcp_server` command with an npm/PyPI
|
|
9
|
+
package and `source_repo`, honest permissions) plus a README that walks
|
|
10
|
+
`agentnode mcp verify` → `agentnode mcp submit`. MCP now has the same
|
|
11
|
+
terminal starting point as toolpacks, skills, and agents.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- `agentnode publish` detects an MCP manifest (runtime `mcp` or an `mcp_server`
|
|
16
|
+
block) and routes you to `agentnode mcp verify` / `agentnode mcp submit`
|
|
17
|
+
instead of failing deep in toolpack validation. Non-MCP manifests are
|
|
18
|
+
unaffected.
|
|
19
|
+
- Refreshed model compatibility data: 246 scored models (222 S-tier), current
|
|
20
|
+
flagships added, models untestable in the latest batch kept with their prior
|
|
21
|
+
result marked legacy, and only hard-evidence removals delisted.
|
|
22
|
+
|
|
3
23
|
## 0.21.0 — Community agents run sandboxed by default
|
|
4
24
|
|
|
5
25
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentnode-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.22.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
|
|
@@ -2338,9 +2338,14 @@ def cmd_init(name: str | None = None, template_type: str | None = None) -> int:
|
|
|
2338
2338
|
print()
|
|
2339
2339
|
print(dim(" Next steps:"))
|
|
2340
2340
|
print(dim(f" cd {pkg_id}"))
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2341
|
+
if chosen == "mcp":
|
|
2342
|
+
print(dim(" # Fill in npm_package/pypi_package, pin the version, set source_repo"))
|
|
2343
|
+
print(dim(" agentnode mcp verify . --test # check ownership, package, pinning"))
|
|
2344
|
+
print(dim(" agentnode mcp submit . # submit for the catalog"))
|
|
2345
|
+
else:
|
|
2346
|
+
print(dim(" # Edit the tool code and manifest"))
|
|
2347
|
+
print(dim(" agentnode validate ."))
|
|
2348
|
+
print(dim(" agentnode publish . # or publish via agentnode.net/publish"))
|
|
2344
2349
|
print()
|
|
2345
2350
|
return 0
|
|
2346
2351
|
|
|
@@ -149,7 +149,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
149
149
|
# init
|
|
150
150
|
init_parser = sub.add_parser("init", help="Create a new package from template")
|
|
151
151
|
init_parser.add_argument("name", nargs="?", default=None, help="Package ID (optional, prompted if omitted)")
|
|
152
|
-
init_parser.add_argument("--type", dest="template_type", choices=["local", "api", "file", "agent", "skill"], default=None)
|
|
152
|
+
init_parser.add_argument("--type", dest="template_type", choices=["local", "api", "file", "agent", "skill", "mcp"], default=None)
|
|
153
153
|
|
|
154
154
|
# validate
|
|
155
155
|
validate_parser = sub.add_parser("validate", help="Validate package before publishing")
|
|
@@ -389,6 +389,20 @@ def cmd_publish(
|
|
|
389
389
|
print(" Error: package_id and version are required in agentnode.yaml.", file=sys.stderr)
|
|
390
390
|
return 1
|
|
391
391
|
|
|
392
|
+
# MCP listings go through the dedicated submit flow (registry re-verification
|
|
393
|
+
# + ownership), not the toolpack/skill/agent publish path. Route the user
|
|
394
|
+
# cleanly instead of failing deep in validation.
|
|
395
|
+
if manifest.get("runtime") == "mcp" or manifest.get("mcp_server"):
|
|
396
|
+
print()
|
|
397
|
+
print(section(" This is an MCP server listing"))
|
|
398
|
+
print(" MCP servers are listed with a dedicated command, not `publish`:")
|
|
399
|
+
print()
|
|
400
|
+
print(" agentnode mcp verify . # check ownership, package, pinning")
|
|
401
|
+
print(" agentnode mcp submit . # submit for the catalog")
|
|
402
|
+
print()
|
|
403
|
+
print(" (`publish` is for toolpacks, skills, and agents.)")
|
|
404
|
+
return 1
|
|
405
|
+
|
|
392
406
|
print()
|
|
393
407
|
print(section(" AgentNode Publish"))
|
|
394
408
|
print(kv("Package", f"{pkg_id}@{version}"))
|
|
@@ -598,6 +598,92 @@ This is an example of the expected output quality and format.
|
|
|
598
598
|
## Summary
|
|
599
599
|
|
|
600
600
|
A concise summary of the analysis.
|
|
601
|
+
""",
|
|
602
|
+
},
|
|
603
|
+
},
|
|
604
|
+
"mcp": {
|
|
605
|
+
"label": "MCP server (list an existing npm/PyPI MCP server)",
|
|
606
|
+
"description": "A listing for an MCP server already published to npm or PyPI. No code is uploaded — you point AgentNode at the package. Submit with `agentnode mcp submit` after `agentnode mcp verify`.",
|
|
607
|
+
"files": {
|
|
608
|
+
"agentnode.yaml": """\
|
|
609
|
+
manifest_version: "0.3"
|
|
610
|
+
package_id: "{package_id}"
|
|
611
|
+
package_type: "toolpack"
|
|
612
|
+
name: "{name}"
|
|
613
|
+
publisher: "{publisher}"
|
|
614
|
+
version: "1.0.0"
|
|
615
|
+
summary: "{summary}"
|
|
616
|
+
description: |
|
|
617
|
+
{description}
|
|
618
|
+
|
|
619
|
+
runtime: "mcp"
|
|
620
|
+
install_mode: "package"
|
|
621
|
+
hosting_type: "agentnode_hosted"
|
|
622
|
+
|
|
623
|
+
# The MCP server to run. Fill in ONE of npm_package / pypi_package and pin the
|
|
624
|
+
# EXACT version in the command (e.g. @0.1.0 for npm, ==0.1.0 for PyPI) — an
|
|
625
|
+
# unpinned command is not reproducible and is flagged on submit.
|
|
626
|
+
mcp_server:
|
|
627
|
+
# npm example (delete the pypi_package line):
|
|
628
|
+
command: ["npx", "-y", "REPLACE_ME_PACKAGE@REPLACE_VERSION"]
|
|
629
|
+
npm_package: "REPLACE_ME_PACKAGE"
|
|
630
|
+
# pypi example (swap the command + use pypi_package instead of npm_package):
|
|
631
|
+
# command: ["uvx", "REPLACE_ME_PACKAGE==REPLACE_VERSION"]
|
|
632
|
+
# pypi_package: "REPLACE_ME_PACKAGE"
|
|
633
|
+
# Ownership is checked against this repo — it must match the package's
|
|
634
|
+
# registry metadata (npm/PyPI "repository" / homepage).
|
|
635
|
+
source_repo: "https://github.com/REPLACE_ME_OWNER/REPLACE_ME_REPO"
|
|
636
|
+
|
|
637
|
+
tags: []
|
|
638
|
+
categories: []
|
|
639
|
+
|
|
640
|
+
compatibility:
|
|
641
|
+
frameworks: ["generic"]
|
|
642
|
+
|
|
643
|
+
# Declare honestly what the MCP server needs. Verification compares these
|
|
644
|
+
# against what the server actually requests.
|
|
645
|
+
permissions:
|
|
646
|
+
network:
|
|
647
|
+
level: "restricted"
|
|
648
|
+
allowed_domains: []
|
|
649
|
+
filesystem:
|
|
650
|
+
level: "none"
|
|
651
|
+
code_execution:
|
|
652
|
+
level: "none"
|
|
653
|
+
data_access:
|
|
654
|
+
level: "input_only"
|
|
655
|
+
user_approval:
|
|
656
|
+
required: "high_risk_only"
|
|
657
|
+
external_integrations: []
|
|
658
|
+
""",
|
|
659
|
+
"README.md": """\
|
|
660
|
+
# {name} (MCP server listing)
|
|
661
|
+
|
|
662
|
+
This package LISTS an existing MCP server (published on npm or PyPI) in the
|
|
663
|
+
AgentNode catalog. No code is uploaded — AgentNode points at the upstream
|
|
664
|
+
package.
|
|
665
|
+
|
|
666
|
+
## Before you submit
|
|
667
|
+
|
|
668
|
+
1. Edit `agentnode.yaml`:
|
|
669
|
+
- Set `mcp_server.npm_package` OR `mcp_server.pypi_package` (not both).
|
|
670
|
+
- Pin the EXACT version in `mcp_server.command` (npm `@x.y.z`, PyPI `==x.y.z`).
|
|
671
|
+
- Set `mcp_server.source_repo` to the repo that owns the package.
|
|
672
|
+
- Declare `permissions` honestly.
|
|
673
|
+
2. Verify locally:
|
|
674
|
+
|
|
675
|
+
```
|
|
676
|
+
agentnode mcp verify . --test
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
3. Submit for the catalog (server re-verifies authoritatively):
|
|
680
|
+
|
|
681
|
+
```
|
|
682
|
+
agentnode mcp submit . --token $AGENTNODE_API_KEY
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
`agentnode publish` is for toolpacks / skills / agents; MCP listings go
|
|
686
|
+
through `agentnode mcp submit`.
|
|
601
687
|
""",
|
|
602
688
|
},
|
|
603
689
|
},
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""AgentNode compatibility data and model recommendations.
|
|
2
|
+
|
|
3
|
+
Auto-generated by sdk/scripts/generate_compatibility_artifacts.py
|
|
4
|
+
Manual edits to _RECOMMENDED are preserved across regeneration.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
_TIER_ORDER = {"S": 0, "A": 1, "B": 2, "C": 3, "F": 4}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _tier_passes(tier: str, minimum: str) -> bool:
|
|
13
|
+
"""Check if a tier meets the minimum requirement."""
|
|
14
|
+
return _TIER_ORDER.get(tier, 99) <= _TIER_ORDER.get(minimum, 0)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Generated from current.json — provider -> [(model, tier), ...]
|
|
18
|
+
_TIER_DATA: dict[str, list[tuple[str, str]]] = {
|
|
19
|
+
"ai21": [("jamba-large-1.7", "C")],
|
|
20
|
+
"aion-labs": [("aion-2.0", "S"), ("aion-3.0", "S"), ("aion-3.0-mini", "S")],
|
|
21
|
+
"amazon": [("nova-2-lite-v1", "S"), ("nova-lite-v1", "S"), ("nova-micro-v1", "S"), ("nova-premier-v1", "S"), ("nova-pro-v1", "S")],
|
|
22
|
+
"anthropic": [("claude-3-haiku", "S"), ("claude-fable-5", "S"), ("claude-haiku-4.5", "S"), ("claude-opus-4", "S"), ("claude-opus-4.1", "S"), ("claude-opus-4.5", "S"), ("claude-opus-4.6", "S"), ("claude-opus-4.7", "S"), ("claude-opus-4.8", "S"), ("claude-opus-4.8-fast", "S"), ("claude-sonnet-4", "S"), ("claude-sonnet-4.5", "S"), ("claude-sonnet-4.6", "S"), ("claude-sonnet-5", "A")],
|
|
23
|
+
"arcee-ai": [("trinity-large-thinking", "A"), ("trinity-mini", "C")],
|
|
24
|
+
"bytedance-seed": [("seed-1.6", "S"), ("seed-1.6-flash", "S"), ("seed-2.0-lite", "S"), ("seed-2.0-mini", "S")],
|
|
25
|
+
"cohere": [("command-r-08-2024", "S"), ("command-r-plus-08-2024", "S"), ("north-mini-code:free", "S")],
|
|
26
|
+
"deepseek": [("deepseek-chat", "S"), ("deepseek-chat-v3-0324", "S"), ("deepseek-chat-v3.1", "S"), ("deepseek-r1", "S"), ("deepseek-r1-0528", "A"), ("deepseek-v3.1-terminus", "S"), ("deepseek-v3.2", "S"), ("deepseek-v3.2-exp", "S"), ("deepseek-v4-flash", "S"), ("deepseek-v4-pro", "A")],
|
|
27
|
+
"google": [("gemini-2.5-flash", "S"), ("gemini-2.5-flash-lite", "S"), ("gemini-2.5-flash-lite-preview-09-2025", "S"), ("gemini-2.5-pro", "S"), ("gemini-2.5-pro-preview", "S"), ("gemini-2.5-pro-preview-05-06", "S"), ("gemini-3-flash-preview", "A"), ("gemini-3-pro-image", "S"), ("gemini-3.1-flash-lite", "S"), ("gemini-3.1-flash-lite-preview", "S"), ("gemini-3.1-pro-preview", "A"), ("gemini-3.1-pro-preview-customtools", "S"), ("gemini-3.5-flash", "S"), ("gemma-3-12b-it", "F"), ("gemma-3-27b-it", "C"), ("gemma-4-26b-a4b-it", "S"), ("gemma-4-26b-a4b-it:free", "F"), ("gemma-4-31b-it", "S")],
|
|
28
|
+
"ibm-granite": [("granite-4.1-8b", "S")],
|
|
29
|
+
"inception": [("mercury-2", "S")],
|
|
30
|
+
"inclusionai": [("ling-2.6-1t", "S"), ("ling-2.6-flash", "A"), ("ring-2.6-1t", "S")],
|
|
31
|
+
"kwaipilot": [("kat-coder-pro-v2", "S")],
|
|
32
|
+
"meta-llama": [("llama-3-8b-instruct", "S"), ("llama-3.1-70b-instruct", "S"), ("llama-3.1-8b-instruct", "S"), ("llama-3.3-70b-instruct", "S"), ("llama-4-maverick", "S"), ("llama-4-scout", "S")],
|
|
33
|
+
"minimax": [("minimax-m1", "S"), ("minimax-m2", "S"), ("minimax-m2.1", "S"), ("minimax-m2.5", "S"), ("minimax-m2.7", "S"), ("minimax-m3", "S")],
|
|
34
|
+
"mistralai": [("codestral-2508", "S"), ("devstral-2512", "S"), ("ministral-14b-2512", "S"), ("ministral-3b-2512", "S"), ("ministral-8b-2512", "S"), ("mistral-large", "S"), ("mistral-large-2407", "S"), ("mistral-large-2512", "S"), ("mistral-medium-3", "S"), ("mistral-medium-3-5", "S"), ("mistral-medium-3.1", "S"), ("mistral-nemo", "S"), ("mistral-saba", "S"), ("mistral-small-2603", "S"), ("mistral-small-3.2-24b-instruct", "S"), ("mixtral-8x22b-instruct", "S"), ("voxtral-small-24b-2507", "S")],
|
|
35
|
+
"moonshotai": [("kimi-k2", "S"), ("kimi-k2-0905", "S"), ("kimi-k2-thinking", "S"), ("kimi-k2.5", "S"), ("kimi-k2.6", "S"), ("kimi-k2.7-code", "S")],
|
|
36
|
+
"nex-agi": [("nex-n2-mini", "S"), ("nex-n2-pro", "S")],
|
|
37
|
+
"nvidia": [("llama-3.3-nemotron-super-49b-v1.5", "S"), ("nemotron-3-nano-30b-a3b", "S"), ("nemotron-3-nano-30b-a3b:free", "A"), ("nemotron-3-nano-omni-30b-a3b-reasoning:free", "S"), ("nemotron-3-super-120b-a12b", "S"), ("nemotron-3-super-120b-a12b:free", "A"), ("nemotron-3-ultra-550b-a55b", "S"), ("nemotron-3-ultra-550b-a55b:free", "S"), ("nemotron-nano-12b-v2-vl:free", "C"), ("nemotron-nano-9b-v2:free", "A")],
|
|
38
|
+
"openai": [("gpt-3.5-turbo", "S"), ("gpt-3.5-turbo-0613", "S"), ("gpt-3.5-turbo-16k", "S"), ("gpt-4", "S"), ("gpt-4-turbo", "S"), ("gpt-4.1", "S"), ("gpt-4.1-mini", "S"), ("gpt-4.1-nano", "S"), ("gpt-4o", "S"), ("gpt-4o-2024-05-13", "S"), ("gpt-4o-2024-08-06", "S"), ("gpt-4o-2024-11-20", "S"), ("gpt-4o-mini", "S"), ("gpt-4o-mini-2024-07-18", "S"), ("gpt-5", "S"), ("gpt-5-codex", "S"), ("gpt-5-mini", "S"), ("gpt-5-nano", "S"), ("gpt-5-pro", "S"), ("gpt-5.1", "S"), ("gpt-5.1-chat", "S"), ("gpt-5.1-codex", "S"), ("gpt-5.1-codex-max", "S"), ("gpt-5.1-codex-mini", "S"), ("gpt-5.2", "S"), ("gpt-5.2-chat", "S"), ("gpt-5.2-codex", "S"), ("gpt-5.3-chat", "S"), ("gpt-5.3-codex", "S"), ("gpt-5.4", "S"), ("gpt-5.4-mini", "S"), ("gpt-5.4-nano", "S"), ("gpt-5.5", "S"), ("gpt-audio", "F"), ("gpt-chat-latest", "S"), ("gpt-oss-120b", "S"), ("gpt-oss-120b:free", "C"), ("gpt-oss-20b", "S"), ("gpt-oss-20b:free", "S"), ("gpt-oss-safeguard-20b", "B"), ("o1", "S"), ("o3", "S"), ("o3-mini", "S"), ("o3-mini-high", "S"), ("o3-pro", "S"), ("o4-mini", "S"), ("o4-mini-high", "S")],
|
|
39
|
+
"openrouter": [("auto", "S"), ("free", "S")],
|
|
40
|
+
"poolside": [("laguna-m.1", "S"), ("laguna-m.1:free", "A"), ("laguna-xs-2.1", "S"), ("laguna-xs-2.1:free", "S"), ("laguna-xs.2", "S"), ("laguna-xs.2:free", "S")],
|
|
41
|
+
"qwen": [("qwen-2.5-72b-instruct", "S"), ("qwen-2.5-7b-instruct", "S"), ("qwen-plus", "S"), ("qwen-plus-2025-07-28", "S"), ("qwen-plus-2025-07-28:thinking", "S"), ("qwen3-14b", "S"), ("qwen3-235b-a22b", "S"), ("qwen3-235b-a22b-2507", "S"), ("qwen3-235b-a22b-thinking-2507", "C"), ("qwen3-30b-a3b", "S"), ("qwen3-30b-a3b-instruct-2507", "S"), ("qwen3-30b-a3b-thinking-2507", "S"), ("qwen3-32b", "S"), ("qwen3-8b", "S"), ("qwen3-coder", "S"), ("qwen3-coder-30b-a3b-instruct", "S"), ("qwen3-coder-flash", "S"), ("qwen3-coder-next", "S"), ("qwen3-coder-plus", "S"), ("qwen3-max", "S"), ("qwen3-max-thinking", "S"), ("qwen3-next-80b-a3b-instruct", "S"), ("qwen3-next-80b-a3b-thinking", "S"), ("qwen3-vl-235b-a22b-instruct", "S"), ("qwen3-vl-235b-a22b-thinking", "S"), ("qwen3-vl-30b-a3b-instruct", "S"), ("qwen3-vl-30b-a3b-thinking", "S"), ("qwen3-vl-32b-instruct", "S"), ("qwen3-vl-8b-instruct", "S"), ("qwen3-vl-8b-thinking", "S"), ("qwen3.5-122b-a10b", "S"), ("qwen3.5-27b", "S"), ("qwen3.5-35b-a3b", "S"), ("qwen3.5-397b-a17b", "S"), ("qwen3.5-9b", "S"), ("qwen3.5-flash-02-23", "S"), ("qwen3.5-plus-02-15", "S"), ("qwen3.5-plus-20260420", "S"), ("qwen3.6-27b", "S"), ("qwen3.6-35b-a3b", "S"), ("qwen3.6-flash", "S"), ("qwen3.6-max-preview", "S"), ("qwen3.6-plus", "S"), ("qwen3.7-max", "S"), ("qwen3.7-plus", "S")],
|
|
42
|
+
"rekaai": [("reka-edge", "A")],
|
|
43
|
+
"relace": [("relace-search", "S")],
|
|
44
|
+
"stepfun": [("step-3.5-flash", "S"), ("step-3.7-flash", "S")],
|
|
45
|
+
"tencent": [("hy3", "S"), ("hy3-preview", "S"), ("hy3:free", "S")],
|
|
46
|
+
"thedrummer": [("unslopnemo-12b", "F")],
|
|
47
|
+
"upstage": [("solar-pro-3", "S")],
|
|
48
|
+
"x-ai": [("grok-4.20", "S"), ("grok-build-0.1", "S")],
|
|
49
|
+
"xiaomi": [("mimo-v2.5", "S"), ("mimo-v2.5-pro", "S")],
|
|
50
|
+
"z-ai": [("glm-4.5", "S"), ("glm-4.5-air", "S"), ("glm-4.5v", "S"), ("glm-4.6", "S"), ("glm-4.6v", "S"), ("glm-4.7", "S"), ("glm-4.7-flash", "S"), ("glm-5", "S"), ("glm-5-turbo", "S"), ("glm-5.1", "S"), ("glm-5.2", "S"), ("glm-5v-turbo", "S")],
|
|
51
|
+
"~anthropic": [("claude-haiku-latest", "S"), ("claude-opus-latest", "S"), ("claude-sonnet-latest", "S")],
|
|
52
|
+
"~google": [("gemini-flash-latest", "S")],
|
|
53
|
+
"~moonshotai": [("kimi-latest", "S")],
|
|
54
|
+
"~openai": [("gpt-latest", "S"), ("gpt-mini-latest", "A")],
|
|
55
|
+
"~x-ai": [("grok-latest", "S")],
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# Curated recommendations — override layer
|
|
59
|
+
_RECOMMENDED: dict[str | None, dict[str, str]] = {
|
|
60
|
+
None: {"best": "gpt-4o", "cheapest": "gpt-4o-mini"},
|
|
61
|
+
"openai": {"best": "gpt-4o", "cheapest": "gpt-4o-mini"},
|
|
62
|
+
"anthropic": {"best": "claude-sonnet-4.6", "cheapest": "claude-haiku-4.5"},
|
|
63
|
+
"google": {"best": "gemini-2.5-flash", "cheapest": "gemini-2.0-flash-001"},
|
|
64
|
+
"mistralai": {"best": "mistral-large", "cheapest": "mistral-nemo"},
|
|
65
|
+
"meta-llama": {"best": "llama-4-maverick", "cheapest": "llama-3.1-8b-instruct"},
|
|
66
|
+
"deepseek": {"best": "deepseek-chat", "cheapest": "deepseek-chat"},
|
|
67
|
+
"qwen": {"best": "qwen3-235b-a22b", "cheapest": "qwen3-30b-a3b"},
|
|
68
|
+
"x-ai": {"best": "grok-4", "cheapest": "grok-3-mini"},
|
|
69
|
+
"cohere": {"best": "command-r-plus-08-2024", "cheapest": "command-r-08-2024"},
|
|
70
|
+
"nvidia": {"best": "llama-3.3-nemotron-super-49b-v1.5", "cheapest": "nemotron-nano-9b-v2"},
|
|
71
|
+
"amazon": {"best": "nova-pro-v1", "cheapest": "nova-micro-v1"},
|
|
72
|
+
"minimax": {"best": "minimax-m2.7", "cheapest": "minimax-m1"},
|
|
73
|
+
"z-ai": {"best": "glm-5", "cheapest": "glm-4.7-flash"},
|
|
74
|
+
"inception": {"best": "mercury-2", "cheapest": "mercury"},
|
|
75
|
+
"moonshotai": {"best": "kimi-k2.5", "cheapest": "kimi-k2"},
|
|
76
|
+
"xiaomi": {"best": "mimo-v2-pro", "cheapest": "mimo-v2-flash"},
|
|
77
|
+
"bytedance-seed": {"best": "seed-1.6", "cheapest": "seed-2.0-mini"},
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def recommend_model(
|
|
82
|
+
provider: str | None = None,
|
|
83
|
+
*,
|
|
84
|
+
prefer: str = "best",
|
|
85
|
+
minimum_tier: str = "S",
|
|
86
|
+
) -> str | None:
|
|
87
|
+
"""Recommend a model for a given provider.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
provider: Provider name (e.g. "openai", "anthropic"). None for overall best.
|
|
91
|
+
prefer: "best" or "cheapest".
|
|
92
|
+
minimum_tier: Minimum acceptable tier ("S", "A", "B", "C", "F").
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Model name string, or None if no model meets the criteria.
|
|
96
|
+
|
|
97
|
+
Raises:
|
|
98
|
+
ValueError: If prefer or minimum_tier is invalid.
|
|
99
|
+
"""
|
|
100
|
+
if prefer not in ("best", "cheapest"):
|
|
101
|
+
raise ValueError(f"Unknown prefer value: {prefer!r}. Use 'best' or 'cheapest'.")
|
|
102
|
+
if minimum_tier not in _TIER_ORDER:
|
|
103
|
+
raise ValueError(
|
|
104
|
+
f"Unknown minimum_tier: {minimum_tier!r}. Use one of: {', '.join(_TIER_ORDER)}."
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if provider is not None:
|
|
108
|
+
provider = provider.lower()
|
|
109
|
+
|
|
110
|
+
# Try curated recommendation first
|
|
111
|
+
recs = _RECOMMENDED.get(provider)
|
|
112
|
+
if recs:
|
|
113
|
+
candidate = recs.get(prefer)
|
|
114
|
+
if candidate:
|
|
115
|
+
# Verify the candidate meets the minimum tier
|
|
116
|
+
tier_list = _TIER_DATA.get(provider, [])
|
|
117
|
+
for model_name, tier in tier_list:
|
|
118
|
+
if model_name == candidate and _tier_passes(tier, minimum_tier):
|
|
119
|
+
return candidate
|
|
120
|
+
|
|
121
|
+
# Fallback: find best model from tier data that meets minimum
|
|
122
|
+
if provider is None:
|
|
123
|
+
# Overall: check all providers
|
|
124
|
+
for prov, models in _TIER_DATA.items():
|
|
125
|
+
for model_name, tier in models:
|
|
126
|
+
if _tier_passes(tier, minimum_tier):
|
|
127
|
+
# Return overall curated default if available
|
|
128
|
+
overall = _RECOMMENDED.get(None, {})
|
|
129
|
+
fallback = overall.get(prefer)
|
|
130
|
+
if fallback:
|
|
131
|
+
return fallback
|
|
132
|
+
return model_name
|
|
133
|
+
return None
|
|
134
|
+
|
|
135
|
+
tier_list = _TIER_DATA.get(provider, [])
|
|
136
|
+
if not tier_list:
|
|
137
|
+
return None
|
|
138
|
+
|
|
139
|
+
# Find any model meeting the minimum tier
|
|
140
|
+
for model_name, tier in tier_list:
|
|
141
|
+
if _tier_passes(tier, minimum_tier):
|
|
142
|
+
return model_name
|
|
143
|
+
|
|
144
|
+
return None
|