agentic-runner 3.0.0__tar.gz → 3.1.1__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.
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/PKG-INFO +1 -1
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/__init__.py +1 -1
- agentic_runner-3.1.1/src/agentic_runner/build.py +33 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/registration.py +23 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/testing/control_plane.py +4 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workstation.py +1 -18
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/.gitignore +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/LICENSE +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/README.md +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/pyproject.toml +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/activities.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/attempts.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/callback.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/child_watcher.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/cli.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/config.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/credentials.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/device_login_activities.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/egress.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/heartbeat_link.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/hooks.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/host_store.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/__init__.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/git/__init__.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/git/contracts.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/git/evidence.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/git/fake_workspace.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/git/workspace.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/github/__init__.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/github/auth.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/github/fake_client.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/github/gh_client.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/lifecycle.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/llm_proxy.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/mcp.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/message_store.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/private_state.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/py.typed +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/recipient_key_secret.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/runtime/__init__.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/runtime/verifier_command.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/sealed_box.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/service.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/testing/__init__.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/testing/__main__.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/testing/plugin.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/testing/test_conformance.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/testing/workflow.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/tiny_http.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/triage_activities.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/user_sources.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/__init__.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/_runtime_support.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/agent_runtime.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/claude_runtime.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/codex_runtime.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/command_policy.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/contract_device_login.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/contract_isolation.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/fastapi_client.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/harness_usage.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/mcp_config.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/settings.py +0 -0
- {agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/skills.py +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""This build's own digest: the ``build_id`` a Runner reports and a release publishes.
|
|
2
|
+
|
|
3
|
+
Its own module, with no Runner import, because registration (the bootstrap request) and
|
|
4
|
+
the workstation (the heartbeat attestation) both need it and the workstation imports
|
|
5
|
+
registration. The release pipeline calls it on the installed wheel and on the image, so
|
|
6
|
+
any change to how it is computed changes every published ``build-id.txt`` with it.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from hashlib import sha256
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
import agentic_runner
|
|
15
|
+
|
|
16
|
+
__all__ = ["build_id"]
|
|
17
|
+
|
|
18
|
+
_PACKAGE = Path(agentic_runner.__file__).parent
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def build_id(package: Path = _PACKAGE) -> str:
|
|
22
|
+
"""The SHA-256 of the package's ``.py`` sources, path and bytes, in sorted order.
|
|
23
|
+
|
|
24
|
+
Self-reported build identity (12 B7), not a signature: the consoles say
|
|
25
|
+
"self-reported" beside it. Only ``.py`` files count, so a wheel, the image and a
|
|
26
|
+
Homebrew install of one release give the same value whatever bytecode each compiled.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
digest = sha256()
|
|
30
|
+
for source in sorted(package.rglob("*.py")):
|
|
31
|
+
digest.update(source.relative_to(package).as_posix().encode())
|
|
32
|
+
digest.update(source.read_bytes())
|
|
33
|
+
return digest.hexdigest()
|
|
@@ -33,6 +33,7 @@ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
|
|
33
33
|
from pydantic import BaseModel, ConfigDict
|
|
34
34
|
|
|
35
35
|
from agentic_runner import __version__ as runner_version
|
|
36
|
+
from agentic_runner.build import build_id
|
|
36
37
|
from agentic_runner.private_state import private_read, private_write
|
|
37
38
|
from agentic_runner_contracts import __version__ as contracts_version
|
|
38
39
|
from agentic_runner_contracts.channel_messages import TRANSCRIPT_DELIVERIES_PATH, TranscriptDelivery
|
|
@@ -68,6 +69,7 @@ INTAKE_IGNORED_PATH = "/api/runner/v1/runners/intake/ignored"
|
|
|
68
69
|
# The refusal a revoked Runner's heartbeat earns (06 §2: revocation *is* the refused
|
|
69
70
|
# heartbeat). The one reason this process stops on rather than retries.
|
|
70
71
|
RUNNER_REVOKED_REASON = "runner_revoked"
|
|
72
|
+
CONTROL_PLANE_OLDER_REASON = "control_plane_older"
|
|
71
73
|
|
|
72
74
|
# What the state directory holds after a successful bootstrap. One file, mode 0600: the
|
|
73
75
|
# private key is in it, and a Runner that loses it re-bootstraps rather than recovering.
|
|
@@ -252,6 +254,7 @@ class RunnerRegistrationClient:
|
|
|
252
254
|
runner_version=runner_version,
|
|
253
255
|
recipient_key=recipient_key,
|
|
254
256
|
max_concurrent_directives=max_concurrent_directives,
|
|
257
|
+
build_id=build_id(),
|
|
255
258
|
)
|
|
256
259
|
payload = await self._post(BOOTSTRAP_PATH, content=request.model_dump_json(), headers={})
|
|
257
260
|
response = BootstrapResponse.model_validate(payload)
|
|
@@ -344,9 +347,29 @@ def _refusal(response: httpx.Response) -> tuple[str, str]:
|
|
|
344
347
|
detail = None
|
|
345
348
|
if isinstance(detail, dict) and "reason" in detail:
|
|
346
349
|
return str(detail["reason"]), str(detail.get("detail", detail["reason"]))
|
|
350
|
+
if unknown := _fields_the_control_plane_does_not_know(response.status_code, detail):
|
|
351
|
+
return CONTROL_PLANE_OLDER_REASON, (
|
|
352
|
+
f"the control plane is older than this Runner (agentic-runner {runner_version}, "
|
|
353
|
+
f"agentic-runner-contracts {contracts_version}): it does not know "
|
|
354
|
+
f"{', '.join(unknown)}. Install the agentic-runner release that matches the "
|
|
355
|
+
"control plane, or ask your Organisation's Admin to upgrade it."
|
|
356
|
+
)
|
|
347
357
|
return "refused", f"{response.status_code}: {response.text[:200]}"
|
|
348
358
|
|
|
349
359
|
|
|
360
|
+
def _fields_the_control_plane_does_not_know(status_code: int, detail: Any) -> list[str]:
|
|
361
|
+
# A strict request model (extra="forbid") answering 422 with nothing but
|
|
362
|
+
# `extra_forbidden` errors is version skew, not a bad token: this Runner's contracts
|
|
363
|
+
# added fields the control plane's pinned contracts have not caught up to (RR-13).
|
|
364
|
+
if status_code != 422 or not isinstance(detail, list) or not detail:
|
|
365
|
+
return []
|
|
366
|
+
if not all(
|
|
367
|
+
isinstance(error, dict) and error.get("type") == "extra_forbidden" for error in detail
|
|
368
|
+
):
|
|
369
|
+
return []
|
|
370
|
+
return [str(error.get("loc", ["?"])[-1]) for error in detail]
|
|
371
|
+
|
|
372
|
+
|
|
350
373
|
class SignedIntakeStream:
|
|
351
374
|
""":class:`agentic_runner.user_sources.IntakeStream` over the signed outbound stream."""
|
|
352
375
|
|
|
@@ -175,6 +175,10 @@ class FakeControlPlane:
|
|
|
175
175
|
"isolation_modes": sorted({b.isolation_mode.value for b in self.bootstraps}),
|
|
176
176
|
"heartbeats": len(self.heartbeats),
|
|
177
177
|
"heartbeat_runner_ids": sorted({str(r) for r in self.heartbeat_runner_ids}),
|
|
178
|
+
"bootstrap_build_ids": sorted({b.build_id or "" for b in self.bootstraps}),
|
|
179
|
+
"heartbeat_build_ids": sorted(
|
|
180
|
+
{h.attestation.build_id if h.attestation else "" for h in self.heartbeats}
|
|
181
|
+
),
|
|
178
182
|
"directive_tokens": len(self.directive_tokens),
|
|
179
183
|
"evidence": len(self.evidence),
|
|
180
184
|
"refusals": [f"{r.method} {r.path} {r.status} {r.reason}" for r in self.refusals],
|
|
@@ -36,7 +36,6 @@ import tempfile
|
|
|
36
36
|
from collections.abc import Callable, Mapping, Sequence
|
|
37
37
|
from dataclasses import dataclass
|
|
38
38
|
from datetime import UTC, datetime
|
|
39
|
-
from hashlib import sha256
|
|
40
39
|
from pathlib import Path
|
|
41
40
|
from typing import Any, Final
|
|
42
41
|
from xml.sax.saxutils import escape
|
|
@@ -44,8 +43,8 @@ from xml.sax.saxutils import escape
|
|
|
44
43
|
import httpx
|
|
45
44
|
from pydantic import BaseModel, ConfigDict
|
|
46
45
|
|
|
47
|
-
import agentic_runner
|
|
48
46
|
from agentic_runner import service
|
|
47
|
+
from agentic_runner.build import build_id
|
|
49
48
|
from agentic_runner.host_store import open_workstation_store
|
|
50
49
|
from agentic_runner.lifecycle import LifecycleOutbox
|
|
51
50
|
from agentic_runner.registration import load_state
|
|
@@ -333,22 +332,6 @@ def cli_versions(found: Mapping[str, str], *, run: Run = subprocess.run) -> list
|
|
|
333
332
|
# ------------------------------------------------------------------ attestation
|
|
334
333
|
|
|
335
334
|
|
|
336
|
-
def build_id() -> str:
|
|
337
|
-
"""A digest of this build's own source: self-reported build identity (12 B7).
|
|
338
|
-
|
|
339
|
-
Not a signature and not claimed to be one -- the consoles say "self-reported" beside
|
|
340
|
-
it. What it buys is that two Runners reporting the same version but running
|
|
341
|
-
different code show different ids.
|
|
342
|
-
"""
|
|
343
|
-
|
|
344
|
-
package = Path(agentic_runner.__file__).parent
|
|
345
|
-
digest = sha256()
|
|
346
|
-
for source in sorted(package.rglob("*.py")):
|
|
347
|
-
digest.update(source.relative_to(package).as_posix().encode())
|
|
348
|
-
digest.update(source.read_bytes())
|
|
349
|
-
return digest.hexdigest()[:16]
|
|
350
|
-
|
|
351
|
-
|
|
352
335
|
def os_release() -> str:
|
|
353
336
|
system = re.sub(r"[^a-z0-9_]", "", platform_module.system().lower())[:16] or "unknown"
|
|
354
337
|
release = re.sub(r"[^0-9A-Za-z._+-]", "", platform_module.release())[:48]
|
|
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
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/git/__init__.py
RENAMED
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/git/contracts.py
RENAMED
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/git/evidence.py
RENAMED
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/git/fake_workspace.py
RENAMED
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/git/workspace.py
RENAMED
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/github/__init__.py
RENAMED
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/github/auth.py
RENAMED
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/github/fake_client.py
RENAMED
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/integrations/github/gh_client.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
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/runtime/verifier_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/testing/test_conformance.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/_runtime_support.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/contract_device_login.py
RENAMED
|
File without changes
|
{agentic_runner-3.0.0 → agentic_runner-3.1.1}/src/agentic_runner/workers/contract_isolation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|