darwin-agentic-cloud 3.0.2__tar.gz → 3.0.3__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.
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/CHANGELOG.md +18 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/PKG-INFO +1 -1
- darwin_agentic_cloud-3.0.3/att.json +51 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/__init__.py +1 -1
- darwin_agentic_cloud-3.0.3/hello.py +1 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/pyproject.toml +1 -1
- darwin_agentic_cloud-3.0.3/tests/cli/test_run.py +314 -0
- darwin_agentic_cloud-3.0.3/tests/runtime/__init__.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/.dockerignore +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/.gitignore +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/CODE_OF_CONDUCT.md +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/CONTRIBUTING.md +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/DARWIN_AGENTIC_CLOUD_PHASE_2_PROGRESS_2of3.md +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/DARWIN_AGENTIC_CLOUD_PHASE_2_SPEC.md +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/Dockerfile +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/LAUNCH_POST_v3.0.0.md +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/LICENSE +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/Makefile +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/QUICKSTART.md +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/README.md +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/SECURITY.md +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/__init__.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/admin_cli.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/attestation.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/class_keys.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/cli.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/cost.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/hashing.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/mcp_server.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/router.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/runtime.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/runtime_v02.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/sandbox.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/schemas/__init__.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/schemas/attestation_v0_2.json +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/server.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/signing.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/storage.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/__init__.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/aws_batch.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/aws_batch_event.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/aws_lambda.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/aws_lambda_event.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/aws_pricing.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/base.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/identity.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/local_docker.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/modal.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/templates/demo.html +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/templates/demo_attestation.json +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/templates/docs.html +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/types.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/ui.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/docker-entrypoint.sh +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/docs/AGENT_INVENTORY.md +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/examples/example_workloads/hello.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/examples/hello.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/fly.toml +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/__init__.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/Dockerfile.batch-runner-python +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/Dockerfile.runner-node +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/Dockerfile.runner-python +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/__init__.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/batch_deploy.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/batch_runner.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/deploy.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/runner.mjs +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/runner.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/bake_demo_attestation.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/batch_smoketest.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/modal_smoketest.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/__init__.py +0 -0
- {darwin_agentic_cloud-3.0.2/tests/runtime → darwin_agentic_cloud-3.0.3/tests/cli}/__init__.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/fixtures/ec2_ondemand_m5xlarge.json +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/fixtures/ec2_spot_history_m5xlarge.json +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/runtime/test_router.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/runtime/test_runtime_v02.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/substrate/test_aws_batch.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/substrate/test_aws_lambda.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/substrate/test_aws_pricing.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/substrate/test_base.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/substrate/test_identity.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/substrate/test_local_docker.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/substrate/test_modal.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/test_admin_cli.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/test_attestation.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/test_class_keys.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/test_cost.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/test_server_signing.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/test_smoke.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/test_storage.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/test_ui.py +0 -0
- {darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/uv.lock +0 -0
|
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.0.3] — 2026-05-28
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- CLI integration tests for `darwin run` (`tests/cli/test_run.py`). 15 new tests
|
|
15
|
+
covering argument parsing (no-args error, help output, documented flags),
|
|
16
|
+
workload resolution (file path vs inline code, nonexistent-file fallback),
|
|
17
|
+
flag handling (--substrate, --cost-cap, --timeout, --memory, --language),
|
|
18
|
+
output formats (--save writes valid JSON, --json emits parseable output), and
|
|
19
|
+
smoke regression for the file-exists-and-inline-code happy paths. Tests use
|
|
20
|
+
`typer.testing.CliRunner` with the underlying `darwin.run()` mocked so they
|
|
21
|
+
run without Docker or AWS credentials.
|
|
22
|
+
- New `tests/cli/` directory + `__init__.py` for future per-verb CLI test files.
|
|
23
|
+
|
|
24
|
+
### Internal
|
|
25
|
+
|
|
26
|
+
- Test suite total: 388 → 403 passing.
|
|
27
|
+
|
|
10
28
|
## [3.0.2] — 2026-05-28
|
|
11
29
|
|
|
12
30
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: darwin-agentic-cloud
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.3
|
|
4
4
|
Summary: Darwin — adaptive software systems. Includes darwin.agenticcloud, the verifiable agentic cloud. Open-source compute for AI agents with cryptographically signed attestations.
|
|
5
5
|
Project-URL: Homepage, https://github.com/vje013/darwin-agentic-cloud
|
|
6
6
|
Project-URL: Repository, https://github.com/vje013/darwin-agentic-cloud
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"attestation_id": "att_1a83a636569e4e93",
|
|
3
|
+
"schema": "darwin.cloud/agenticcloud/attestation/v0.2",
|
|
4
|
+
"issued_at": "2026-05-29T01:10:03Z",
|
|
5
|
+
"workload_spec_hash": "4fa10188f2faa0d07f25cb38df5492424b7f154d874e02463216ea827ae1748a",
|
|
6
|
+
"execution_result": {
|
|
7
|
+
"output_hash": "67ecdb031db5e6529d6edd8d25eb20dd443162fd8b3fdf4b121dbfc82e7906be",
|
|
8
|
+
"substrate": {
|
|
9
|
+
"id": "local-docker-v0",
|
|
10
|
+
"version": "0.1.0",
|
|
11
|
+
"identity_signature": "c/zmytDvWNdHsirKXs6LYyuT0CyEEhuStDb+CbzxVfsIzU/lgCVGphYNYzE/s0/GKxoRthL4PHfbnJGgoe2XAQ==",
|
|
12
|
+
"identity_signer_type": "darwin-class-key",
|
|
13
|
+
"identity_signer_key_id": "dac-class-local-docker-v0-ca698355dcb631e3",
|
|
14
|
+
"evidence_schema_id": "darwin.cloud/evidence/local-docker/v1",
|
|
15
|
+
"evidence": {
|
|
16
|
+
"container_status": "ok",
|
|
17
|
+
"exit_code": 0,
|
|
18
|
+
"stdout_hash": "67ecdb031db5e6529d6edd8d25eb20dd443162fd8b3fdf4b121dbfc82e7906be",
|
|
19
|
+
"stderr_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
|
20
|
+
"wall_time_sec": 0.11720395088195801
|
|
21
|
+
},
|
|
22
|
+
"extensions": {},
|
|
23
|
+
"tee_required": false
|
|
24
|
+
},
|
|
25
|
+
"cost_usd": 1.172e-05,
|
|
26
|
+
"stdout": "hello from a real attestation\n",
|
|
27
|
+
"stderr": ""
|
|
28
|
+
},
|
|
29
|
+
"value_added_service": {
|
|
30
|
+
"identity_signing": {
|
|
31
|
+
"schema_compliant": true,
|
|
32
|
+
"keylist_url": "https://darwin-agentic-cloud.fly.dev/.well-known/substrate-keys.json"
|
|
33
|
+
},
|
|
34
|
+
"cost_cap_enforcement": {
|
|
35
|
+
"cap_usd": 0.1,
|
|
36
|
+
"estimated_usd_max": 0.003,
|
|
37
|
+
"actual_usd": 1.172e-05,
|
|
38
|
+
"within_cap": true,
|
|
39
|
+
"headroom_usd": 0.09998828
|
|
40
|
+
},
|
|
41
|
+
"routing_decision": {
|
|
42
|
+
"policy": "pick_by_cost",
|
|
43
|
+
"chosen_substrate_id": "local-docker-v0",
|
|
44
|
+
"chosen_reason": "lowest_estimated_cost ($0.003000)",
|
|
45
|
+
"candidates_considered": 1,
|
|
46
|
+
"rejected_substrates": []
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"signer_key_id": "dac-local-d1bf7cad25875cee",
|
|
50
|
+
"signature": "cyIS5v4zUkyIAyfISoBAYBZifIRQdAYX2ZU1o8KOSf/NGg/hC80lRqblFNCXRouETqeXL8A35UqJVx+2C8w+Bg=="
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
print("hello from a real attestation")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "darwin-agentic-cloud"
|
|
3
|
-
version = "3.0.
|
|
3
|
+
version = "3.0.3"
|
|
4
4
|
description = "Darwin — adaptive software systems. Includes darwin.agenticcloud, the verifiable agentic cloud. Open-source compute for AI agents with cryptographically signed attestations."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"""CLI integration tests for `darwin run`.
|
|
2
|
+
|
|
3
|
+
These tests exercise the Typer wrapper around `darwin.run()`. The
|
|
4
|
+
underlying `Runtime` is mocked so tests don't require a working Docker
|
|
5
|
+
daemon or AWS credentials. The point is to validate the CLI surface:
|
|
6
|
+
argument parsing, file resolution, flag handling, output formatting,
|
|
7
|
+
exit codes, and error messages.
|
|
8
|
+
|
|
9
|
+
See tests/runtime/test_runtime_v02.py for the underlying Runtime API
|
|
10
|
+
tests.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import re
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from unittest.mock import patch
|
|
19
|
+
|
|
20
|
+
import pytest
|
|
21
|
+
from typer.testing import CliRunner
|
|
22
|
+
|
|
23
|
+
from darwin.agenticcloud.cli import app
|
|
24
|
+
|
|
25
|
+
# ---------------------------------------------------------------------------
|
|
26
|
+
# Fixtures
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
_ANSI_RE = re.compile(r"\x1b\[[0-9;]*[a-zA-Z]")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _strip_ansi(s):
|
|
34
|
+
return _ANSI_RE.sub("", s)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@pytest.fixture
|
|
38
|
+
def runner() -> CliRunner:
|
|
39
|
+
"""Typer CLI runner that captures stdout and stderr."""
|
|
40
|
+
return CliRunner()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
_ANSI_RE = re.compile(r"\x1b\[[0-9;]*[a-zA-Z]")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _strip_ansi(s):
|
|
47
|
+
return _ANSI_RE.sub("", s)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@pytest.fixture
|
|
51
|
+
def fake_attestation() -> dict:
|
|
52
|
+
"""A minimal v0.2-shaped attestation that the CLI can render."""
|
|
53
|
+
return {
|
|
54
|
+
"schema": "darwin.cloud/agenticcloud/attestation/v0.2",
|
|
55
|
+
"attestation_id": "test-attestation-id-0001",
|
|
56
|
+
"issued_at": "2026-05-29T01:00:00Z",
|
|
57
|
+
"workload_spec_hash": "sha256:" + "a" * 64,
|
|
58
|
+
"execution_result": {
|
|
59
|
+
"status": "ok",
|
|
60
|
+
"stdout": "hello\n",
|
|
61
|
+
"output_hash": "sha256:" + "b" * 64,
|
|
62
|
+
"cost_usd": 0.000012,
|
|
63
|
+
"substrate": {
|
|
64
|
+
"id": "local-docker-v0",
|
|
65
|
+
"version": "0.1.0",
|
|
66
|
+
"evidence_schema_id": "darwin.cloud/evidence/local-docker/v1",
|
|
67
|
+
"identity_signer_type": "darwin-class-key",
|
|
68
|
+
"identity_signer_key_id": "dac-class-local-docker-v0-test",
|
|
69
|
+
"identity_signature": "test-signature-b64",
|
|
70
|
+
"evidence": {
|
|
71
|
+
"container_status": "ok",
|
|
72
|
+
"exit_code": 0,
|
|
73
|
+
"wall_time_sec": 0.1,
|
|
74
|
+
"stdout_hash": "sha256:" + "b" * 64,
|
|
75
|
+
"stderr_hash": "sha256:" + "e" * 64,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
"preflight_estimate": {"cost_usd_max": 0.0001},
|
|
79
|
+
},
|
|
80
|
+
"value_added_service": {
|
|
81
|
+
"identity_signing": {
|
|
82
|
+
"schema_compliant": True,
|
|
83
|
+
"keylist_url": "https://example/keys.json",
|
|
84
|
+
},
|
|
85
|
+
"cost_cap_enforcement": {
|
|
86
|
+
"cap_usd": 0.10,
|
|
87
|
+
"estimated_usd_max": 0.0001,
|
|
88
|
+
"actual_usd": 0.000012,
|
|
89
|
+
"within_cap": True,
|
|
90
|
+
"headroom_usd": 0.099988,
|
|
91
|
+
},
|
|
92
|
+
"routing_decision": {
|
|
93
|
+
"policy": "pick_by_cost",
|
|
94
|
+
"chosen_substrate_id": "local-docker-v0",
|
|
95
|
+
"chosen_reason": "lowest_estimated_cost ($0.0001)",
|
|
96
|
+
"candidates_considered": 1,
|
|
97
|
+
"rejected_substrates": [],
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
"signer_key_id": "dac-local-test-operator",
|
|
101
|
+
"signature": "test-outer-signature-b64",
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
_ANSI_RE = re.compile(r"\x1b\[[0-9;]*[a-zA-Z]")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _strip_ansi(s):
|
|
109
|
+
return _ANSI_RE.sub("", s)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@pytest.fixture
|
|
113
|
+
def mocked_run(fake_attestation):
|
|
114
|
+
"""Patch the underlying `darwin.run` to return our fake attestation.
|
|
115
|
+
|
|
116
|
+
Returns the patch object so individual tests can inspect call args
|
|
117
|
+
or override the return value if they need to test failure paths.
|
|
118
|
+
"""
|
|
119
|
+
with patch("darwin.run") as mock:
|
|
120
|
+
mock.return_value = fake_attestation
|
|
121
|
+
yield mock
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
_ANSI_RE = re.compile(r"\x1b\[[0-9;]*[a-zA-Z]")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _strip_ansi(s):
|
|
128
|
+
return _ANSI_RE.sub("", s)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@pytest.fixture
|
|
132
|
+
def hello_py(tmp_path: Path) -> Path:
|
|
133
|
+
"""A real `hello.py` file in a tmp directory."""
|
|
134
|
+
p = tmp_path / "hello.py"
|
|
135
|
+
p.write_text('print("hello")\n')
|
|
136
|
+
return p
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# ---------------------------------------------------------------------------
|
|
140
|
+
# Argument parsing
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class TestArgumentParsing:
|
|
145
|
+
"""The CLI surface: argument and flag handling."""
|
|
146
|
+
|
|
147
|
+
def test_run_with_no_args_exits_nonzero(self, runner: CliRunner):
|
|
148
|
+
"""`darwin run` with no workload arg should error cleanly."""
|
|
149
|
+
result = runner.invoke(app, ["run"])
|
|
150
|
+
assert result.exit_code != 0
|
|
151
|
+
# Typer/Click writes the "Missing argument" message to stdout
|
|
152
|
+
# in their styled error panel; accept either stream.
|
|
153
|
+
combined = _strip_ansi(result.stdout + (result.stderr or ""))
|
|
154
|
+
assert "Missing argument" in combined or "WORKLOAD" in combined
|
|
155
|
+
|
|
156
|
+
def test_run_help_exits_zero(self, runner: CliRunner):
|
|
157
|
+
"""`darwin run --help` always succeeds and prints usage."""
|
|
158
|
+
result = runner.invoke(app, ["run", "--help"])
|
|
159
|
+
assert result.exit_code == 0
|
|
160
|
+
assert "WORKLOAD" in _strip_ansi(result.stdout)
|
|
161
|
+
assert "--substrate" in _strip_ansi(result.stdout)
|
|
162
|
+
assert "--cost-cap" in _strip_ansi(result.stdout)
|
|
163
|
+
|
|
164
|
+
def test_run_help_lists_all_documented_flags(self, runner: CliRunner):
|
|
165
|
+
"""All public flags appear in help output."""
|
|
166
|
+
result = runner.invoke(app, ["run", "--help"])
|
|
167
|
+
for flag in [
|
|
168
|
+
"--substrate",
|
|
169
|
+
"--language",
|
|
170
|
+
"--cost-cap",
|
|
171
|
+
"--timeout",
|
|
172
|
+
"--memory",
|
|
173
|
+
"--save",
|
|
174
|
+
"--json",
|
|
175
|
+
]:
|
|
176
|
+
assert flag in _strip_ansi(result.stdout), f"flag {flag} missing from help"
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# ---------------------------------------------------------------------------
|
|
180
|
+
# File vs inline workload resolution
|
|
181
|
+
# ---------------------------------------------------------------------------
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class TestWorkloadResolution:
|
|
185
|
+
"""The CLI's "is this arg a file or a code string" heuristic."""
|
|
186
|
+
|
|
187
|
+
def test_run_with_existing_file_reads_contents(
|
|
188
|
+
self, runner: CliRunner, mocked_run, hello_py: Path
|
|
189
|
+
):
|
|
190
|
+
"""When the workload arg is an existing file path, its contents are executed."""
|
|
191
|
+
result = runner.invoke(app, ["run", str(hello_py)])
|
|
192
|
+
assert result.exit_code == 0, result.stdout
|
|
193
|
+
# Verify the underlying call was made with the FILE CONTENTS, not the filename.
|
|
194
|
+
call_args = mocked_run.call_args
|
|
195
|
+
code_arg = call_args.kwargs.get("code") or (call_args.args[0] if call_args.args else None)
|
|
196
|
+
assert code_arg is not None
|
|
197
|
+
assert 'print("hello")' in code_arg
|
|
198
|
+
assert code_arg != str(hello_py), "CLI should read file contents, not pass the filename"
|
|
199
|
+
|
|
200
|
+
def test_run_with_inline_code_passes_string_directly(self, runner: CliRunner, mocked_run):
|
|
201
|
+
"""When the workload arg isn't a file, it's treated as inline code."""
|
|
202
|
+
result = runner.invoke(app, ["run", 'print("inline")'])
|
|
203
|
+
assert result.exit_code == 0, result.stdout
|
|
204
|
+
call_args = mocked_run.call_args
|
|
205
|
+
code_arg = call_args.kwargs.get("code") or (call_args.args[0] if call_args.args else None)
|
|
206
|
+
assert code_arg == 'print("inline")'
|
|
207
|
+
|
|
208
|
+
def test_run_with_nonexistent_file_treats_as_inline(
|
|
209
|
+
self, runner: CliRunner, mocked_run, tmp_path: Path
|
|
210
|
+
):
|
|
211
|
+
"""A workload arg that LOOKS like a file path but doesn't exist falls back to inline."""
|
|
212
|
+
nonexistent = tmp_path / "does_not_exist.py"
|
|
213
|
+
runner.invoke(app, ["run", str(nonexistent)])
|
|
214
|
+
# CLI doesn't crash — it passes the string to the substrate, which will likely
|
|
215
|
+
# fail to execute. We check the CLI plumbing, not the substrate outcome.
|
|
216
|
+
# The important guarantee: we don't crash with FileNotFoundError on the CLI side.
|
|
217
|
+
call_args = mocked_run.call_args
|
|
218
|
+
if call_args is not None:
|
|
219
|
+
code_arg = call_args.kwargs.get("code") or (
|
|
220
|
+
call_args.args[0] if call_args.args else None
|
|
221
|
+
)
|
|
222
|
+
assert code_arg == str(nonexistent)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
# ---------------------------------------------------------------------------
|
|
226
|
+
# Flag handling
|
|
227
|
+
# ---------------------------------------------------------------------------
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class TestFlagHandling:
|
|
231
|
+
"""Every flag exposed by `darwin run` is wired correctly."""
|
|
232
|
+
|
|
233
|
+
def test_substrate_flag_is_passed_through(self, runner: CliRunner, mocked_run, hello_py: Path):
|
|
234
|
+
result = runner.invoke(app, ["run", str(hello_py), "--substrate", "local-docker-v0"])
|
|
235
|
+
assert result.exit_code == 0, result.stdout
|
|
236
|
+
kwargs = mocked_run.call_args.kwargs
|
|
237
|
+
assert kwargs.get("substrate") == "local-docker-v0"
|
|
238
|
+
|
|
239
|
+
def test_cost_cap_flag_is_passed_through(self, runner: CliRunner, mocked_run, hello_py: Path):
|
|
240
|
+
result = runner.invoke(app, ["run", str(hello_py), "--cost-cap", "0.5"])
|
|
241
|
+
assert result.exit_code == 0, result.stdout
|
|
242
|
+
kwargs = mocked_run.call_args.kwargs
|
|
243
|
+
assert kwargs.get("cost_cap") == 0.5
|
|
244
|
+
|
|
245
|
+
def test_timeout_flag_is_passed_through(self, runner: CliRunner, mocked_run, hello_py: Path):
|
|
246
|
+
result = runner.invoke(app, ["run", str(hello_py), "--timeout", "60"])
|
|
247
|
+
assert result.exit_code == 0, result.stdout
|
|
248
|
+
kwargs = mocked_run.call_args.kwargs
|
|
249
|
+
assert kwargs.get("timeout") == 60
|
|
250
|
+
|
|
251
|
+
def test_memory_flag_is_passed_through(self, runner: CliRunner, mocked_run, hello_py: Path):
|
|
252
|
+
result = runner.invoke(app, ["run", str(hello_py), "--memory", "1024"])
|
|
253
|
+
assert result.exit_code == 0, result.stdout
|
|
254
|
+
kwargs = mocked_run.call_args.kwargs
|
|
255
|
+
assert kwargs.get("memory_mb") == 1024
|
|
256
|
+
|
|
257
|
+
def test_language_flag_is_passed_through(self, runner: CliRunner, mocked_run, hello_py: Path):
|
|
258
|
+
result = runner.invoke(app, ["run", str(hello_py), "--language", "node"])
|
|
259
|
+
assert result.exit_code == 0, result.stdout
|
|
260
|
+
kwargs = mocked_run.call_args.kwargs
|
|
261
|
+
assert kwargs.get("language") == "node"
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
# ---------------------------------------------------------------------------
|
|
265
|
+
# Output formats
|
|
266
|
+
# ---------------------------------------------------------------------------
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class TestOutputFormats:
|
|
270
|
+
"""The CLI's --save and --json flags produce correct artifacts."""
|
|
271
|
+
|
|
272
|
+
def test_save_flag_writes_attestation_to_disk(
|
|
273
|
+
self, runner: CliRunner, mocked_run, hello_py: Path, tmp_path: Path
|
|
274
|
+
):
|
|
275
|
+
out_path = tmp_path / "att.json"
|
|
276
|
+
result = runner.invoke(app, ["run", str(hello_py), "--save", str(out_path)])
|
|
277
|
+
assert result.exit_code == 0, result.stdout
|
|
278
|
+
assert out_path.exists(), "—save target file was not created"
|
|
279
|
+
# The saved file must be valid JSON
|
|
280
|
+
saved = json.loads(out_path.read_text())
|
|
281
|
+
assert saved.get("attestation_id") == "test-attestation-id-0001"
|
|
282
|
+
assert saved.get("schema") == "darwin.cloud/agenticcloud/attestation/v0.2"
|
|
283
|
+
|
|
284
|
+
def test_json_flag_emits_parseable_json_only(
|
|
285
|
+
self, runner: CliRunner, mocked_run, hello_py: Path
|
|
286
|
+
):
|
|
287
|
+
result = runner.invoke(app, ["run", str(hello_py), "--json"])
|
|
288
|
+
assert result.exit_code == 0, result.stdout
|
|
289
|
+
# In --json mode, stdout should be pure JSON (parseable)
|
|
290
|
+
parsed = json.loads(result.stdout)
|
|
291
|
+
assert parsed.get("attestation_id") == "test-attestation-id-0001"
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
# ---------------------------------------------------------------------------
|
|
295
|
+
# Smoke / regression
|
|
296
|
+
# ---------------------------------------------------------------------------
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class TestSmoke:
|
|
300
|
+
"""Basic invocation paths that have failed in production before."""
|
|
301
|
+
|
|
302
|
+
def test_run_with_file_does_not_raise(self, runner: CliRunner, mocked_run, hello_py: Path):
|
|
303
|
+
"""Regression: `darwin run hello.py` from a directory where hello.py exists must complete."""
|
|
304
|
+
result = runner.invoke(app, ["run", str(hello_py)])
|
|
305
|
+
assert result.exception is None or result.exit_code == 0, (
|
|
306
|
+
f"unexpected exception: {result.exception!r}\nstdout: {result.stdout}"
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
def test_run_with_inline_code_does_not_raise(self, runner: CliRunner, mocked_run):
|
|
310
|
+
"""Regression: `darwin run 'print(...)'` must complete."""
|
|
311
|
+
result = runner.invoke(app, ["run", 'print("ok")'])
|
|
312
|
+
assert result.exception is None or result.exit_code == 0, (
|
|
313
|
+
f"unexpected exception: {result.exception!r}\nstdout: {result.stdout}"
|
|
314
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/DARWIN_AGENTIC_CLOUD_PHASE_2_SPEC.md
RENAMED
|
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
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/attestation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/runtime_v02.py
RENAMED
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/schemas/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/__init__.py
RENAMED
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/aws_batch.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/base.py
RENAMED
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/identity.py
RENAMED
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/substrate/modal.py
RENAMED
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/templates/demo.html
RENAMED
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/darwin/agenticcloud/templates/docs.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/examples/example_workloads/hello.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/Dockerfile.runner-node
RENAMED
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/infra/aws_runner/Dockerfile.runner-python
RENAMED
|
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
|
{darwin_agentic_cloud-3.0.2/tests/runtime → darwin_agentic_cloud-3.0.3/tests/cli}/__init__.py
RENAMED
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/fixtures/ec2_ondemand_m5xlarge.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/substrate/test_aws_lambda.py
RENAMED
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/substrate/test_aws_pricing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{darwin_agentic_cloud-3.0.2 → darwin_agentic_cloud-3.0.3}/tests/substrate/test_local_docker.py
RENAMED
|
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
|