kyber-cli 4.0.0__tar.gz → 4.0.2__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.
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/PKG-INFO +1 -1
- kyber_cli-4.0.2/kyber/runtimes/__init__.py +22 -0
- kyber_cli-4.0.2/kyber/runtimes/base.py +113 -0
- kyber_cli-4.0.2/kyber/runtimes/go/__init__.py +4 -0
- kyber_cli-4.0.2/kyber/runtimes/go/adapter.py +34 -0
- kyber_cli-4.0.2/kyber/runtimes/node/__init__.py +4 -0
- kyber_cli-4.0.2/kyber/runtimes/node/adapter.py +34 -0
- kyber_cli-4.0.2/kyber/runtimes/python/__init__.py +4 -0
- kyber_cli-4.0.2/kyber/runtimes/python/adapter.py +150 -0
- kyber_cli-4.0.2/kyber/tests/test_distribution.py +27 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_tool_gateway_commands.py +1 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tool_gateway/dto.py +1 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber_cli.egg-info/PKG-INFO +1 -1
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber_cli.egg-info/SOURCES.txt +9 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/pyproject.toml +7 -2
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/README.md +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/__main__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/auth/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/auth/config.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/cli.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/circuit_runner.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/clear.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/defaults.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/deploy.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/deploy_progress.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/eject.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/explain.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/init.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/inspect.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/lifecycle.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/login.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/memory.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/profiles.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/run.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/run_artifacts.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/run_inputs.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/run_preflight.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/run_report.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/run_runtime.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/status.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/test.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/tools.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/validate.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/commands/versioning.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/agent_manifest.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/artifact_schema.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/capability_outputs.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/circuit_schema.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/compatibility.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/config.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/defaults.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/egress_validation.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/expanded_validation.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/interaction.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/manifest.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/merge.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/overrides.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/policy.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/policy_limits.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/runtime.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/schema_version.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/schemas/kyber.manifest.v1.schema.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/schemas/kyber.manifest.v2.schema.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/schemas.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/structure.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/test_environment.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/tier.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/core/ui.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/LITELLM-NOTICE.txt +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/application.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/audit.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/catalog.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/diff.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/models.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/policy.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profile_composition.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profile_files.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profiles/high-volume/profile.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profiles/high-volume/versions/1.0.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profiles/minimal/profile.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profiles/minimal/versions/1.0.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profiles/regulated/profile.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profiles/regulated/versions/1.0.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profiles/standard/profile.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profiles/standard/versions/1.0.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/profiles.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/registry.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/defaults/validation.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/compatibility.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/composition.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/config.json +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/dto/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/dto/common/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/dto/common/models.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/dto/request/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/dto/request/submission.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/dto/response/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/dto/response/authentication.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/dto/response/submission.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/errors.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/integrations/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/integrations/authentication.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/integrations/bundles.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/integrations/digests.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/integrations/http.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/integrations/python_runtime.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/ports.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/services/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/services/candidate.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/services/deployment.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/deployment/services/poller.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/local_memory_environment.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/local_tool_environment.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/go/templates/.kyber/runtime_wrapper.go.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/go/templates/go.mod.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/go/templates/kyber.circuit.json.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/go/templates/src/handler.go.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/go/templates/tests/fixtures/sample_event.json.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/go/templates/tests/handler_test.go.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/node/templates/.kyber/runtime_wrapper.js.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/node/templates/kyber.circuit.json.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/node/templates/package.json.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/node/templates/src/handler.js.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/node/templates/tests/circuit.test.js.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/node/templates/tests/fixtures/sample_event.json.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/runtimes/node/templates/tests/handler.test.js.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/direct_run_guard.py.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/kyber.agent.yaml.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/kyber.circuit.json.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/manifest.json.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/pytest.ini.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/requirements.txt.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/runtime_wrapper.py.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/src/handler.py.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/tests/README.md.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/tests/__init__.py.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/tests/conftest.py.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/tests/fixtures/sample_event.json.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/tests/test_circuit.py.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/tests/test_guardrails.py.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/templates/python_agent/tests/test_handler.py.j2 +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/conftest.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_agent_config_schema.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_artifact_schema.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_authentication.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_circuit_handoffs.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_clear_cache_command.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_defaults_registry.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_defaults_versioning.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_deploy_manifest.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_deploy_progress.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_deployment_workflow.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_egress_validation.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_expanded_config_tier_permissions.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_expanded_validation.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_interaction.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_memory_client.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_merge_strategy.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_policy.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_profiles_command.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_python_deployment_runtime.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_run_summary.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_sidecar_overrides.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_structure_validation.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_test_environment.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_tier_detection.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_tool_invocation_runtime.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tests/test_versioning_commands.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tool_gateway/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tool_gateway/cache.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tool_gateway/composition.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tool_gateway/errors.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tool_gateway/http.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tool_gateway/integrations/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tool_gateway/integrations/cicd.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/tool_gateway/service.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/ui/__init__.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber/ui/banner.py +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber_cli.egg-info/dependency_links.txt +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber_cli.egg-info/entry_points.txt +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber_cli.egg-info/requires.txt +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/kyber_cli.egg-info/top_level.txt +0 -0
- {kyber_cli-4.0.0 → kyber_cli-4.0.2}/setup.cfg +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from kyber.runtimes.go.adapter import GoRuntimeAdapter
|
|
2
|
+
from kyber.runtimes.node.adapter import NodeRuntimeAdapter
|
|
3
|
+
from kyber.runtimes.python.adapter import PythonRuntimeAdapter
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
_ADAPTERS = {
|
|
7
|
+
"python": PythonRuntimeAdapter(),
|
|
8
|
+
"node": NodeRuntimeAdapter(),
|
|
9
|
+
"go": GoRuntimeAdapter(),
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_runtime_adapter(runtime: str):
|
|
14
|
+
try:
|
|
15
|
+
return _ADAPTERS[runtime]
|
|
16
|
+
except KeyError as exc:
|
|
17
|
+
supported = ", ".join(sorted(_ADAPTERS))
|
|
18
|
+
raise ValueError(f"Unsupported runtime '{runtime}'. Supported runtimes: {supported}") from exc
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def supported_runtimes():
|
|
22
|
+
return tuple(_ADAPTERS)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import shutil
|
|
3
|
+
import subprocess
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any, Dict, Iterable, List
|
|
6
|
+
|
|
7
|
+
from jinja2 import Environment, FileSystemLoader
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RuntimeAdapter:
|
|
11
|
+
name: str
|
|
12
|
+
default_entrypoint: str
|
|
13
|
+
template_root: Path
|
|
14
|
+
managed_files: tuple[Path, ...] = ()
|
|
15
|
+
|
|
16
|
+
def scaffold(self, project_dir: Path, context: Dict[str, Any]) -> None:
|
|
17
|
+
project_dir.mkdir(parents=True)
|
|
18
|
+
for directory in self.required_directories():
|
|
19
|
+
(project_dir / directory).mkdir(parents=True, exist_ok=True)
|
|
20
|
+
self.render_templates(project_dir, context)
|
|
21
|
+
|
|
22
|
+
def required_directories(self) -> Iterable[Path]:
|
|
23
|
+
return (
|
|
24
|
+
Path("src"),
|
|
25
|
+
Path(".kyber"),
|
|
26
|
+
Path("tests"),
|
|
27
|
+
Path("tests") / "fixtures",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
def required_files(self) -> Iterable[Path]:
|
|
31
|
+
return ()
|
|
32
|
+
|
|
33
|
+
def local_test_command(self, project_root: Path, include_circuit_tests: bool = False) -> List[str]:
|
|
34
|
+
return []
|
|
35
|
+
|
|
36
|
+
def required_executables(self) -> tuple[str, ...]:
|
|
37
|
+
return ()
|
|
38
|
+
|
|
39
|
+
def missing_executables(self) -> List[str]:
|
|
40
|
+
return [
|
|
41
|
+
executable
|
|
42
|
+
for executable in self.required_executables()
|
|
43
|
+
if shutil.which(executable) is None
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
def dependency_errors(self) -> List[str]:
|
|
47
|
+
return [
|
|
48
|
+
f"runtime.{self.name}: Required executable not found on PATH: {executable}. "
|
|
49
|
+
f"Install {self.name} and reopen your terminal, or add {executable} to PATH."
|
|
50
|
+
for executable in self.missing_executables()
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
def validate_handler(self, handler_path: Path) -> tuple[bool, str]:
|
|
54
|
+
return True, ""
|
|
55
|
+
|
|
56
|
+
def validate_artifact_contract(
|
|
57
|
+
self,
|
|
58
|
+
handler_path: Path,
|
|
59
|
+
expected_agent_name: str = None,
|
|
60
|
+
expected_runtime: str = None,
|
|
61
|
+
) -> List[str]:
|
|
62
|
+
return []
|
|
63
|
+
|
|
64
|
+
def validate_source_contract(
|
|
65
|
+
self, project_root: Path, config: Dict[str, Any]
|
|
66
|
+
) -> List[str]:
|
|
67
|
+
return []
|
|
68
|
+
|
|
69
|
+
def discover_artifact_types(self, handler_path: Path) -> List[str]:
|
|
70
|
+
return []
|
|
71
|
+
|
|
72
|
+
def run_handler(self, wrapper_path: Path, handler_path: Path, event_payload: Any) -> Any:
|
|
73
|
+
raise NotImplementedError
|
|
74
|
+
|
|
75
|
+
def render_templates(self, project_dir: Path, context: Dict[str, Any]) -> None:
|
|
76
|
+
env = Environment(loader=FileSystemLoader(self.template_root))
|
|
77
|
+
for relative_template, relative_output in self.template_outputs():
|
|
78
|
+
output_path = project_dir / relative_output
|
|
79
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
80
|
+
rendered = env.get_template(relative_template.as_posix()).render(**context)
|
|
81
|
+
output_path.write_text(rendered, encoding="utf-8")
|
|
82
|
+
|
|
83
|
+
def template_outputs(self):
|
|
84
|
+
for template_path in self.template_root.rglob("*.j2"):
|
|
85
|
+
relative_template = template_path.relative_to(self.template_root)
|
|
86
|
+
yield relative_template, Path(str(relative_template)[:-3])
|
|
87
|
+
|
|
88
|
+
def run_json_subprocess(self, command: List[str], event_payload: Any, cwd: Path) -> Any:
|
|
89
|
+
missing = self.missing_executables()
|
|
90
|
+
if missing:
|
|
91
|
+
executable = missing[0]
|
|
92
|
+
raise RuntimeError(
|
|
93
|
+
f"Required executable not found on PATH: {executable}. "
|
|
94
|
+
f"Install {self.name} and reopen your terminal, or add {executable} to PATH."
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
result = subprocess.run(
|
|
98
|
+
command,
|
|
99
|
+
input=json.dumps(event_payload),
|
|
100
|
+
cwd=cwd,
|
|
101
|
+
capture_output=True,
|
|
102
|
+
text=True,
|
|
103
|
+
)
|
|
104
|
+
if result.returncode != 0:
|
|
105
|
+
message = result.stderr.strip() or result.stdout.strip()
|
|
106
|
+
raise RuntimeError(message or f"{self.name} handler exited with code {result.returncode}")
|
|
107
|
+
try:
|
|
108
|
+
return json.loads(result.stdout)
|
|
109
|
+
except json.JSONDecodeError as exc:
|
|
110
|
+
raise RuntimeError(f"{self.name} handler did not return valid JSON: {exc}") from exc
|
|
111
|
+
|
|
112
|
+
def executable(self, name: str) -> str:
|
|
113
|
+
return shutil.which(name) or name
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any, List
|
|
3
|
+
|
|
4
|
+
from kyber.runtimes.base import RuntimeAdapter
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class GoRuntimeAdapter(RuntimeAdapter):
|
|
8
|
+
name = "go"
|
|
9
|
+
default_entrypoint = "src/handler.go"
|
|
10
|
+
template_root = Path(__file__).resolve().parent / "templates"
|
|
11
|
+
managed_files = (Path(".kyber") / "runtime_wrapper.go",)
|
|
12
|
+
|
|
13
|
+
def required_files(self):
|
|
14
|
+
return (
|
|
15
|
+
Path("kyber.circuit.json"),
|
|
16
|
+
Path("go.mod"),
|
|
17
|
+
Path("src") / "handler.go",
|
|
18
|
+
Path("tests") / "handler_test.go",
|
|
19
|
+
Path("tests") / "fixtures" / "sample_event.json",
|
|
20
|
+
*self.managed_files,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def local_test_command(self, project_root: Path, include_circuit_tests: bool = False) -> List[str]:
|
|
24
|
+
return [self.executable("go"), "test", "./..."]
|
|
25
|
+
|
|
26
|
+
def required_executables(self):
|
|
27
|
+
return ("go",)
|
|
28
|
+
|
|
29
|
+
def run_handler(self, wrapper_path: Path, handler_path: Path, event_payload: Any) -> Any:
|
|
30
|
+
return self.run_json_subprocess(
|
|
31
|
+
[self.executable("go"), "run", str(wrapper_path), "--", str(handler_path)],
|
|
32
|
+
event_payload,
|
|
33
|
+
wrapper_path.parent.parent,
|
|
34
|
+
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any, List
|
|
3
|
+
|
|
4
|
+
from kyber.runtimes.base import RuntimeAdapter
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class NodeRuntimeAdapter(RuntimeAdapter):
|
|
8
|
+
name = "node"
|
|
9
|
+
default_entrypoint = "src/handler.js"
|
|
10
|
+
template_root = Path(__file__).resolve().parent / "templates"
|
|
11
|
+
managed_files = (Path(".kyber") / "runtime_wrapper.js",)
|
|
12
|
+
|
|
13
|
+
def required_files(self):
|
|
14
|
+
return (
|
|
15
|
+
Path("kyber.circuit.json"),
|
|
16
|
+
Path("package.json"),
|
|
17
|
+
Path("tests") / "handler.test.js",
|
|
18
|
+
Path("tests") / "circuit.test.js",
|
|
19
|
+
Path("tests") / "fixtures" / "sample_event.json",
|
|
20
|
+
*self.managed_files,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def local_test_command(self, project_root: Path, include_circuit_tests: bool = False) -> List[str]:
|
|
24
|
+
return [self.executable("npm"), "test"]
|
|
25
|
+
|
|
26
|
+
def required_executables(self):
|
|
27
|
+
return ("node", "npm")
|
|
28
|
+
|
|
29
|
+
def run_handler(self, wrapper_path: Path, handler_path: Path, event_payload: Any) -> Any:
|
|
30
|
+
return self.run_json_subprocess(
|
|
31
|
+
[self.executable("node"), str(wrapper_path), str(handler_path)],
|
|
32
|
+
event_payload,
|
|
33
|
+
wrapper_path.parent.parent,
|
|
34
|
+
)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, List
|
|
5
|
+
|
|
6
|
+
from kyber.core.artifact_schema import (
|
|
7
|
+
discover_python_handler_artifact_types,
|
|
8
|
+
validate_python_handler_artifact_contract,
|
|
9
|
+
)
|
|
10
|
+
from kyber.core.egress_validation import validate_python_egress
|
|
11
|
+
from kyber.llm import install_llm_instrumentation, invoke_instrumented
|
|
12
|
+
from kyber.runtimes.base import RuntimeAdapter
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PythonRuntimeAdapter(RuntimeAdapter):
|
|
16
|
+
name = "python"
|
|
17
|
+
default_entrypoint = "src/handler.py"
|
|
18
|
+
template_root = Path(__file__).resolve().parents[2] / "templates" / "python_agent"
|
|
19
|
+
managed_files = (
|
|
20
|
+
Path(".kyber") / "runtime_wrapper.py",
|
|
21
|
+
Path(".kyber") / "direct_run_guard.py",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def required_files(self):
|
|
25
|
+
return (
|
|
26
|
+
Path("kyber.circuit.json"),
|
|
27
|
+
Path("requirements.txt"),
|
|
28
|
+
Path("pytest.ini"),
|
|
29
|
+
Path("tests") / "conftest.py",
|
|
30
|
+
Path("tests") / "test_handler.py",
|
|
31
|
+
Path("tests") / "test_circuit.py",
|
|
32
|
+
Path("tests") / "test_guardrails.py",
|
|
33
|
+
Path("tests") / "fixtures" / "sample_event.json",
|
|
34
|
+
*self.managed_files,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def template_outputs(self):
|
|
38
|
+
return (
|
|
39
|
+
(Path("kyber.circuit.json.j2"), Path("kyber.circuit.json")),
|
|
40
|
+
(Path("src") / "handler.py.j2", Path("src") / "handler.py"),
|
|
41
|
+
(Path("runtime_wrapper.py.j2"), Path(".kyber") / "runtime_wrapper.py"),
|
|
42
|
+
(Path("direct_run_guard.py.j2"), Path(".kyber") / "direct_run_guard.py"),
|
|
43
|
+
(Path("requirements.txt.j2"), Path("requirements.txt")),
|
|
44
|
+
(Path("pytest.ini.j2"), Path("pytest.ini")),
|
|
45
|
+
(Path("tests") / "__init__.py.j2", Path("tests") / "__init__.py"),
|
|
46
|
+
(Path("tests") / "conftest.py.j2", Path("tests") / "conftest.py"),
|
|
47
|
+
(Path("tests") / "test_handler.py.j2", Path("tests") / "test_handler.py"),
|
|
48
|
+
(Path("tests") / "test_circuit.py.j2", Path("tests") / "test_circuit.py"),
|
|
49
|
+
(Path("tests") / "test_guardrails.py.j2", Path("tests") / "test_guardrails.py"),
|
|
50
|
+
(
|
|
51
|
+
Path("tests") / "fixtures" / "sample_event.json.j2",
|
|
52
|
+
Path("tests") / "fixtures" / "sample_event.json",
|
|
53
|
+
),
|
|
54
|
+
(Path("tests") / "README.md.j2", Path("tests") / "README.md"),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def local_test_command(self, project_root: Path, include_circuit_tests: bool = False) -> List[str]:
|
|
58
|
+
import sys
|
|
59
|
+
|
|
60
|
+
command = [sys.executable, "-m", "pytest", "-q", "tests"]
|
|
61
|
+
circuit_test = project_root / "tests" / "test_circuit.py"
|
|
62
|
+
if circuit_test.exists() and not include_circuit_tests:
|
|
63
|
+
command.extend(["--ignore", str(circuit_test.relative_to(project_root))])
|
|
64
|
+
return command
|
|
65
|
+
|
|
66
|
+
def validate_handler(self, handler_path: Path) -> tuple[bool, str]:
|
|
67
|
+
try:
|
|
68
|
+
tree = ast.parse(handler_path.read_text(encoding="utf-8"), filename=str(handler_path))
|
|
69
|
+
except SyntaxError as exc:
|
|
70
|
+
return False, f"Handler has invalid Python syntax: {exc}"
|
|
71
|
+
except Exception as exc:
|
|
72
|
+
return False, f"Unable to read handler: {exc}"
|
|
73
|
+
|
|
74
|
+
for node in ast.iter_child_nodes(tree):
|
|
75
|
+
if isinstance(node, ast.If) and _is_main_check(node.test):
|
|
76
|
+
if _delegates_to_direct_run_guard(node):
|
|
77
|
+
return True, ""
|
|
78
|
+
return False, "Direct handler execution must delegate to .kyber/direct_run_guard.py"
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
False,
|
|
82
|
+
"Handler must reject direct execution with an 'if __name__ == \"__main__\"' guard",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def validate_artifact_contract(
|
|
86
|
+
self,
|
|
87
|
+
handler_path: Path,
|
|
88
|
+
expected_agent_name: str = None,
|
|
89
|
+
expected_runtime: str = None,
|
|
90
|
+
):
|
|
91
|
+
_, errors = validate_python_handler_artifact_contract(
|
|
92
|
+
handler_path,
|
|
93
|
+
expected_agent_name=expected_agent_name,
|
|
94
|
+
expected_runtime=expected_runtime,
|
|
95
|
+
)
|
|
96
|
+
return errors
|
|
97
|
+
|
|
98
|
+
def discover_artifact_types(self, handler_path: Path) -> List[str]:
|
|
99
|
+
return discover_python_handler_artifact_types(handler_path)
|
|
100
|
+
|
|
101
|
+
def validate_source_contract(self, project_root: Path, config: dict) -> List[str]:
|
|
102
|
+
return validate_python_egress(project_root, config)
|
|
103
|
+
|
|
104
|
+
def run_handler(self, wrapper_path: Path, handler_path: Path, event_payload: Any) -> Any:
|
|
105
|
+
original_cwd = os.getcwd()
|
|
106
|
+
try:
|
|
107
|
+
os.chdir(wrapper_path.parent.parent)
|
|
108
|
+
namespace = {
|
|
109
|
+
"__file__": str(wrapper_path),
|
|
110
|
+
"__name__": "_kyber_runtime_wrapper",
|
|
111
|
+
}
|
|
112
|
+
exec(wrapper_path.read_text(encoding="utf-8"), namespace)
|
|
113
|
+
|
|
114
|
+
if "run_handler" not in namespace:
|
|
115
|
+
raise RuntimeError(f"Runtime wrapper is missing 'run_handler': {wrapper_path}")
|
|
116
|
+
|
|
117
|
+
# Keep instrumentation in the installed CLI so existing managed
|
|
118
|
+
# wrappers do not need to be rewritten or re-hashed.
|
|
119
|
+
install_llm_instrumentation()
|
|
120
|
+
return invoke_instrumented(
|
|
121
|
+
lambda payload: namespace["run_handler"](handler_path, payload),
|
|
122
|
+
event_payload,
|
|
123
|
+
)
|
|
124
|
+
finally:
|
|
125
|
+
os.chdir(original_cwd)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _is_main_check(node: ast.AST) -> bool:
|
|
129
|
+
if not isinstance(node, ast.Compare):
|
|
130
|
+
return False
|
|
131
|
+
|
|
132
|
+
left_is_name = isinstance(node.left, ast.Name) and node.left.id == "__name__"
|
|
133
|
+
if not left_is_name or len(node.ops) != 1 or not isinstance(node.ops[0], ast.Eq):
|
|
134
|
+
return False
|
|
135
|
+
|
|
136
|
+
return any(
|
|
137
|
+
isinstance(comparator, ast.Constant) and comparator.value == "__main__"
|
|
138
|
+
for comparator in node.comparators
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _delegates_to_direct_run_guard(node: ast.AST) -> bool:
|
|
143
|
+
has_run_path = False
|
|
144
|
+
has_guard_path = False
|
|
145
|
+
for child in ast.walk(node):
|
|
146
|
+
if isinstance(child, ast.Attribute) and child.attr == "run_path":
|
|
147
|
+
has_run_path = True
|
|
148
|
+
if isinstance(child, ast.Constant) and child.value == "direct_run_guard.py":
|
|
149
|
+
has_guard_path = True
|
|
150
|
+
return has_run_path and has_guard_path
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import zipfile
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from setuptools import build_meta
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_wheel_contains_runtime_adapters_and_templates(tmp_path, monkeypatch):
|
|
11
|
+
"""Guard against package globs accidentally excluding ``kyber.runtimes``."""
|
|
12
|
+
monkeypatch.chdir(PROJECT_ROOT)
|
|
13
|
+
|
|
14
|
+
wheel_name = build_meta.build_wheel(str(tmp_path))
|
|
15
|
+
|
|
16
|
+
with zipfile.ZipFile(tmp_path / wheel_name) as wheel:
|
|
17
|
+
packaged_files = set(wheel.namelist())
|
|
18
|
+
|
|
19
|
+
assert {
|
|
20
|
+
"kyber/runtimes/__init__.py",
|
|
21
|
+
"kyber/runtimes/base.py",
|
|
22
|
+
"kyber/runtimes/python/adapter.py",
|
|
23
|
+
"kyber/runtimes/node/adapter.py",
|
|
24
|
+
"kyber/runtimes/go/adapter.py",
|
|
25
|
+
"kyber/runtimes/node/templates/package.json.j2",
|
|
26
|
+
"kyber/runtimes/go/templates/go.mod.j2",
|
|
27
|
+
} <= packaged_files
|
|
@@ -102,12 +102,18 @@ kyber/deployment/services/__init__.py
|
|
|
102
102
|
kyber/deployment/services/candidate.py
|
|
103
103
|
kyber/deployment/services/deployment.py
|
|
104
104
|
kyber/deployment/services/poller.py
|
|
105
|
+
kyber/runtimes/__init__.py
|
|
106
|
+
kyber/runtimes/base.py
|
|
107
|
+
kyber/runtimes/go/__init__.py
|
|
108
|
+
kyber/runtimes/go/adapter.py
|
|
105
109
|
kyber/runtimes/go/templates/go.mod.j2
|
|
106
110
|
kyber/runtimes/go/templates/kyber.circuit.json.j2
|
|
107
111
|
kyber/runtimes/go/templates/.kyber/runtime_wrapper.go.j2
|
|
108
112
|
kyber/runtimes/go/templates/src/handler.go.j2
|
|
109
113
|
kyber/runtimes/go/templates/tests/handler_test.go.j2
|
|
110
114
|
kyber/runtimes/go/templates/tests/fixtures/sample_event.json.j2
|
|
115
|
+
kyber/runtimes/node/__init__.py
|
|
116
|
+
kyber/runtimes/node/adapter.py
|
|
111
117
|
kyber/runtimes/node/templates/kyber.circuit.json.j2
|
|
112
118
|
kyber/runtimes/node/templates/package.json.j2
|
|
113
119
|
kyber/runtimes/node/templates/.kyber/runtime_wrapper.js.j2
|
|
@@ -115,6 +121,8 @@ kyber/runtimes/node/templates/src/handler.js.j2
|
|
|
115
121
|
kyber/runtimes/node/templates/tests/circuit.test.js.j2
|
|
116
122
|
kyber/runtimes/node/templates/tests/handler.test.js.j2
|
|
117
123
|
kyber/runtimes/node/templates/tests/fixtures/sample_event.json.j2
|
|
124
|
+
kyber/runtimes/python/__init__.py
|
|
125
|
+
kyber/runtimes/python/adapter.py
|
|
118
126
|
kyber/templates/__init__.py
|
|
119
127
|
kyber/templates/python_agent/direct_run_guard.py.j2
|
|
120
128
|
kyber/templates/python_agent/kyber.agent.yaml.j2
|
|
@@ -142,6 +150,7 @@ kyber/tests/test_defaults_versioning.py
|
|
|
142
150
|
kyber/tests/test_deploy_manifest.py
|
|
143
151
|
kyber/tests/test_deploy_progress.py
|
|
144
152
|
kyber/tests/test_deployment_workflow.py
|
|
153
|
+
kyber/tests/test_distribution.py
|
|
145
154
|
kyber/tests/test_egress_validation.py
|
|
146
155
|
kyber/tests/test_expanded_config_tier_permissions.py
|
|
147
156
|
kyber/tests/test_expanded_validation.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "kyber-cli"
|
|
7
|
-
version = "4.0.
|
|
7
|
+
version = "4.0.2"
|
|
8
8
|
description = "Kyber Developer Experience CLI — deploy agents in one command"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -48,7 +48,12 @@ kyber = "kyber.cli:cli"
|
|
|
48
48
|
[tool.setuptools.packages.find]
|
|
49
49
|
where = ["."]
|
|
50
50
|
include = ["kyber*"]
|
|
51
|
-
exclude = [
|
|
51
|
+
exclude = [
|
|
52
|
+
"kyber.memory*",
|
|
53
|
+
"kyber.tools*",
|
|
54
|
+
"kyber.runtime",
|
|
55
|
+
"kyber.runtime.*",
|
|
56
|
+
]
|
|
52
57
|
|
|
53
58
|
[tool.setuptools.package-data]
|
|
54
59
|
kyber = [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|