agentic-runner 3.15.0__tar.gz → 3.16.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.
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/PKG-INFO +6 -5
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/README.md +4 -3
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/pyproject.toml +4 -1
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/__init__.py +1 -1
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/activities.py +13 -7
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/cli.py +11 -7
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/mcp.py +1 -1
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/registration.py +19 -6
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/service.py +37 -7
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/skills/agentic-runner-setup/SKILL.md +6 -6
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/testing/plugin.py +2 -2
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/acp_runtime.py +33 -1
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/agent_runtime.py +6 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/claude_runtime.py +5 -3
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/codex_runtime.py +9 -2
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workstation.py +7 -7
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/.gitignore +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/LICENSE +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/attempts.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/auth_mode.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/build.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/callback.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/child_watcher.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/cli_floor.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/config.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/credentials.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/device_login_activities.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/egress.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/harness_self_test.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/heartbeat_link.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/hooks.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/host_store.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/__init__.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/git/__init__.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/git/contracts.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/git/evidence.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/git/fake_workspace.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/git/workspace.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/github/__init__.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/github/auth.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/github/fake_client.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/github/gh_client.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/oauth/__init__.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/oauth/fake_provider.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/lifecycle.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/llm_proxy.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/message_store.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/oauth_connectors.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/private_state.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/py.typed +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/recipient_key_secret.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/runtime/__init__.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/runtime/verifier_command.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/sealed_box.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/skill.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/testing/__init__.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/testing/__main__.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/testing/control_plane.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/testing/test_conformance.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/testing/workflow.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/tiny_http.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/triage_activities.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/usage_windows.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/user_sources.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/__init__.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/_runtime_support.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/claude_sign_in.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/command_policy.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/contract_device_login.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/contract_isolation.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/fastapi_client.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/harness_outcome.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/harness_usage.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/mcp_config.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/settings.py +0 -0
- {agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/skills.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agentic-runner
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.16.0
|
|
4
4
|
Summary: The Agentic OS Runner: an activity-only Temporal executor for workspaces, Agent Runtimes and verb seams
|
|
5
5
|
License-Expression: AGPL-3.0-only
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Requires-Python: >=3.12
|
|
8
|
-
Requires-Dist: agentic-runner-contracts
|
|
8
|
+
Requires-Dist: agentic-runner-contracts==3.16.0
|
|
9
9
|
Requires-Dist: cryptography<51,>=50
|
|
10
10
|
Requires-Dist: httpx<1.0,>=0.27
|
|
11
11
|
Requires-Dist: pydantic-settings<3.0,>=2.0
|
|
@@ -33,9 +33,10 @@ no intake. That inertness, not obfuscation, is the boundary (ADR-0013 §5).
|
|
|
33
33
|
|
|
34
34
|
## Running it
|
|
35
35
|
|
|
36
|
-
`agentic-runner run` is the process: it exchanges the
|
|
37
|
-
`AGENTIC_AGENT_TOKEN` for a durable
|
|
38
|
-
persisted under `AGENTIC_RUNNER_STATE_DIR`),
|
|
36
|
+
`agentic-runner run` is the process: it exchanges the Runner Registration Token in
|
|
37
|
+
`AGENTIC_RUNNER_REGISTRATION_TOKEN` (or, deprecated, `AGENTIC_AGENT_TOKEN`) for a durable
|
|
38
|
+
identity at `AGENTIC_CONTROL_PLANE_URL` (once, persisted under `AGENTIC_RUNNER_STATE_DIR`),
|
|
39
|
+
heartbeats every 30 s, connects to the
|
|
39
40
|
namespace it was handed with the Runner Token the heartbeat refreshes, and polls its own
|
|
40
41
|
`runner.{runner_id}` queue. `AGENTIC_RUNNER_ISOLATION` is `contract_uid` (default: every
|
|
41
42
|
Contract its own uid, needs `CAP_SETUID` — refused otherwise) or `none`. Readiness is
|
|
@@ -14,9 +14,10 @@ no intake. That inertness, not obfuscation, is the boundary (ADR-0013 §5).
|
|
|
14
14
|
|
|
15
15
|
## Running it
|
|
16
16
|
|
|
17
|
-
`agentic-runner run` is the process: it exchanges the
|
|
18
|
-
`AGENTIC_AGENT_TOKEN` for a durable
|
|
19
|
-
persisted under `AGENTIC_RUNNER_STATE_DIR`),
|
|
17
|
+
`agentic-runner run` is the process: it exchanges the Runner Registration Token in
|
|
18
|
+
`AGENTIC_RUNNER_REGISTRATION_TOKEN` (or, deprecated, `AGENTIC_AGENT_TOKEN`) for a durable
|
|
19
|
+
identity at `AGENTIC_CONTROL_PLANE_URL` (once, persisted under `AGENTIC_RUNNER_STATE_DIR`),
|
|
20
|
+
heartbeats every 30 s, connects to the
|
|
20
21
|
namespace it was handed with the Runner Token the heartbeat refreshes, and polls its own
|
|
21
22
|
`runner.{runner_id}` queue. `AGENTIC_RUNNER_ISOLATION` is `contract_uid` (default: every
|
|
22
23
|
Contract its own uid, needs `CAP_SETUID` — refused otherwise) or `none`. Readiness is
|
|
@@ -7,7 +7,10 @@ license-files = ["LICENSE"]
|
|
|
7
7
|
requires-python = ">=3.12"
|
|
8
8
|
dynamic = ["version"]
|
|
9
9
|
dependencies = [
|
|
10
|
-
|
|
10
|
+
# Exactly this release's contracts: the two ship as one version, and an unpinned
|
|
11
|
+
# requirement let `uv tool upgrade` keep an older contracts wheel the Runner cannot
|
|
12
|
+
# import from (QTS-1473). `scripts/set-version.py` moves it with the version.
|
|
13
|
+
"agentic-runner-contracts==3.16.0",
|
|
11
14
|
# Imported directly by `registration.py` (the Ed25519 identity that signs every
|
|
12
15
|
# heartbeat); already present transitively through pyjwt[crypto], declared because
|
|
13
16
|
# we import it.
|
|
@@ -604,8 +604,8 @@ class _RuntimeContextState:
|
|
|
604
604
|
# Which harness this Work Record runs, and so which per-Contract config root
|
|
605
605
|
# (`{contract_id}/harness/{cli_kind}`) its Directives read (ADR-0015 §4).
|
|
606
606
|
cli_kind: str = _DEFAULT_CLI_KIND
|
|
607
|
-
#
|
|
608
|
-
#
|
|
607
|
+
# The Agent's model, which every Directive runs (ADR-0021); None for the Runner's
|
|
608
|
+
# default for `cli_kind`.
|
|
609
609
|
model: str | None = None
|
|
610
610
|
# The Agent Runtime Profile's per-process memory ceiling (map ticket 17 A7), carried
|
|
611
611
|
# on the Profile's `command_policy` blob — the sandbox floor already lives there, and
|
|
@@ -1516,6 +1516,8 @@ def _codex_evidence_payload(
|
|
|
1516
1516
|
codex_result.error, _RUNTIME_EVIDENCE_STREAM_LIMIT_BYTES, notes, "error"
|
|
1517
1517
|
),
|
|
1518
1518
|
"command_hash": codex_result.command_hash,
|
|
1519
|
+
# What ran, which the Agent's configuration alone does not prove (ADR-0021).
|
|
1520
|
+
"model": codex_result.model or None,
|
|
1519
1521
|
"workspace": asdict(codex_result.evidence),
|
|
1520
1522
|
"persona_slug": persona_slug,
|
|
1521
1523
|
"persona_instructions_hash": _persona_instructions_hash(persona_instructions),
|
|
@@ -2121,6 +2123,7 @@ class RunnerRalphActivities:
|
|
|
2121
2123
|
auth_mode=attempt.auth_mode,
|
|
2122
2124
|
permission_fallback=runtime_state.permission_fallback,
|
|
2123
2125
|
acp_command=runtime_state.acp_command,
|
|
2126
|
+
model=runtime_state.model or "",
|
|
2124
2127
|
prompt=attempt.skills_preamble
|
|
2125
2128
|
+ _directive_prompt(
|
|
2126
2129
|
completion_criteria=runtime_state.completion_criteria,
|
|
@@ -5067,6 +5070,7 @@ class RunnerRalphActivities:
|
|
|
5067
5070
|
auth_mode=attempt.auth_mode,
|
|
5068
5071
|
permission_fallback=state.permission_fallback,
|
|
5069
5072
|
acp_command=state.acp_command,
|
|
5073
|
+
model=state.model or "",
|
|
5070
5074
|
prompt=attempt.skills_preamble
|
|
5071
5075
|
+ _learning_prompt(
|
|
5072
5076
|
request,
|
|
@@ -5333,6 +5337,7 @@ class RunnerRalphActivities:
|
|
|
5333
5337
|
auth_mode=attempt.auth_mode,
|
|
5334
5338
|
permission_fallback=state.permission_fallback,
|
|
5335
5339
|
acp_command=state.acp_command,
|
|
5340
|
+
model=state.model or "",
|
|
5336
5341
|
prompt=attempt.skills_preamble + await kind.prompt(state, prompt_notes),
|
|
5337
5342
|
base_branch=request.base_ref,
|
|
5338
5343
|
work_branch=state.work_branch,
|
|
@@ -5602,16 +5607,17 @@ class RunnerRalphActivities:
|
|
|
5602
5607
|
reports = [(usage_event, None)] if usage_event else []
|
|
5603
5608
|
else:
|
|
5604
5609
|
usage_event = extract_codex_turn_usage(result.stdout)
|
|
5605
|
-
reports = [(usage_event,
|
|
5610
|
+
reports = [(usage_event, result.model or None)] if usage_event else []
|
|
5606
5611
|
for usage_event, model_name in reports:
|
|
5607
5612
|
if runtime_state.cli_kind != "claude_code" and model_name is None:
|
|
5608
5613
|
# The backend 422s a Codex harness report with no model
|
|
5609
5614
|
# (`report_harness_usage` requires one to price it), and the `suppress`
|
|
5610
|
-
# below swallows that --
|
|
5611
|
-
#
|
|
5615
|
+
# below swallows that -- a Directive that ran Codex's own default model,
|
|
5616
|
+
# which its JSON stream never names, would otherwise lose this Usage
|
|
5617
|
+
# Record with no trace.
|
|
5612
5618
|
activity.logger.warning(
|
|
5613
|
-
"harness usage unreported: Agent %s
|
|
5614
|
-
"harness Directive (work record %s)",
|
|
5619
|
+
"harness usage unreported: Agent %s names no model, so its Codex "
|
|
5620
|
+
"harness Directive ran one the Runner cannot name (work record %s)",
|
|
5615
5621
|
runtime_state.agent_id,
|
|
5616
5622
|
work_record_id,
|
|
5617
5623
|
)
|
|
@@ -5,8 +5,8 @@ contracts version is the compatibility floor the control plane checks before it
|
|
|
5
5
|
Directive token (ADR-0013 §7). An operator debugging "why did this Runner stop getting
|
|
6
6
|
Directives" needs both numbers from one command.
|
|
7
7
|
|
|
8
|
-
``register`` is first boot (PRD issue 41): it presents the
|
|
9
|
-
environment, persists the durable identity the exchange hands back, and prints the
|
|
8
|
+
``register`` is first boot (PRD issue 41): it presents the Runner Registration Token from
|
|
9
|
+
the environment, persists the durable identity the exchange hands back, and prints the
|
|
10
10
|
namespace and queue this process was assigned. It is idempotent by state file -- a
|
|
11
11
|
restart re-reads what is already there rather than registering a second Runner against
|
|
12
12
|
the Organisation's cap.
|
|
@@ -61,8 +61,10 @@ from agentic_runner.service import (
|
|
|
61
61
|
ISOLATION_ENV,
|
|
62
62
|
RECIPIENT_KEY_ID_ENV,
|
|
63
63
|
RECIPIENT_PUBLIC_KEY_ENV,
|
|
64
|
+
REGISTRATION_TOKEN_ENV,
|
|
64
65
|
TAGS_ENV,
|
|
65
66
|
parse_tags,
|
|
67
|
+
registration_token_from_env,
|
|
66
68
|
)
|
|
67
69
|
from agentic_runner.workers.claude_sign_in import OAUTH_TOKEN, SIGN_IN_METHODS
|
|
68
70
|
from agentic_runner_contracts import __version__ as contracts_version
|
|
@@ -80,6 +82,7 @@ __all__ = [
|
|
|
80
82
|
"ISOLATION_ENV",
|
|
81
83
|
"RECIPIENT_KEY_ID_ENV",
|
|
82
84
|
"RECIPIENT_PUBLIC_KEY_ENV",
|
|
85
|
+
"REGISTRATION_TOKEN_ENV",
|
|
83
86
|
"STATE_DIR_ENV",
|
|
84
87
|
"TAGS_ENV",
|
|
85
88
|
"main",
|
|
@@ -144,7 +147,8 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
144
147
|
subcommands = parser.add_subparsers(dest="command")
|
|
145
148
|
|
|
146
149
|
subcommands.add_parser(
|
|
147
|
-
"register",
|
|
150
|
+
"register",
|
|
151
|
+
help="exchange the Runner Registration Token for this process's durable identity",
|
|
148
152
|
)
|
|
149
153
|
|
|
150
154
|
run = subcommands.add_parser("run", help="register if needed, then heartbeat and poll for work")
|
|
@@ -419,9 +423,9 @@ def _install(arguments: argparse.Namespace, paths: workstation.OrgPaths) -> int:
|
|
|
419
423
|
print(str(error), file=sys.stderr)
|
|
420
424
|
return 2
|
|
421
425
|
# Pasted, never a flag: a flag is in the process table for every uid on the box.
|
|
422
|
-
token =
|
|
423
|
-
"
|
|
424
|
-
"Organisation Runner): "
|
|
426
|
+
token = registration_token_from_env() or getpass.getpass(
|
|
427
|
+
"Runner Registration Token (yours from /me/runners, or the Organisation Admin's for "
|
|
428
|
+
"an Organisation Runner): "
|
|
425
429
|
)
|
|
426
430
|
settings = workstation.WorkstationSettings(
|
|
427
431
|
org=paths.org,
|
|
@@ -435,7 +439,7 @@ def _install(arguments: argparse.Namespace, paths: workstation.OrgPaths) -> int:
|
|
|
435
439
|
try:
|
|
436
440
|
lines = asyncio.run(
|
|
437
441
|
workstation.install(
|
|
438
|
-
paths, settings,
|
|
442
|
+
paths, settings, registration_token=token, start_service=not arguments.no_start
|
|
439
443
|
)
|
|
440
444
|
)
|
|
441
445
|
except (workstation.CliMissingError, RunnerRegistrationError, RuntimeError) as error:
|
|
@@ -56,7 +56,7 @@ MCP_PATH: Final[str] = "/mcp"
|
|
|
56
56
|
|
|
57
57
|
# What a Runner-hosted server inherits from the Runner besides its credential. A
|
|
58
58
|
# credential-bearing child must not also inherit the Runner's own environment (its
|
|
59
|
-
#
|
|
59
|
+
# Runner Registration Token, a git token): only what a program needs to start.
|
|
60
60
|
_HOSTED_ENV_ALLOWLIST: Final[tuple[str, ...]] = ("PATH", "HOME", "LANG", "TZ")
|
|
61
61
|
_DEFAULT_CALL_TIMEOUT_SECONDS: Final[float] = 300.0
|
|
62
62
|
# The heartbeat's own bound on `tool_servers`.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""The Runner's half of registration and heartbeat (PRD issue 41, ADR-0013 §8).
|
|
2
2
|
|
|
3
|
-
Outbound-only: this process dials the control plane, presents its
|
|
4
|
-
what comes back in its own state directory, and then says what it is every 30 s.
|
|
5
|
-
listens on a port here, which is also why revocation is entirely the control plane's --
|
|
3
|
+
Outbound-only: this process dials the control plane, presents its Runner Registration Token
|
|
4
|
+
once, keeps what comes back in its own state directory, and then says what it is every 30 s.
|
|
5
|
+
Nothing listens on a port here, which is also why revocation is entirely the control plane's --
|
|
6
6
|
the lever it pulls is the refused heartbeat.
|
|
7
7
|
|
|
8
8
|
Two things fail closed on this side, and both fail *before* anything registers:
|
|
@@ -70,6 +70,13 @@ INTAKE_IGNORED_PATH = "/api/runner/v1/runners/intake/ignored"
|
|
|
70
70
|
# heartbeat). The one reason this process stops on rather than retries.
|
|
71
71
|
RUNNER_REVOKED_REASON = "runner_revoked"
|
|
72
72
|
CONTROL_PLANE_OLDER_REASON = "control_plane_older"
|
|
73
|
+
# The bootstrap refusals that mean "this Runner Registration Token will never work": unknown,
|
|
74
|
+
# revoked, expired. A control plane before ADR-0021 names them `agent_token_*`.
|
|
75
|
+
_REGISTRATION_TOKEN_REASON_PREFIXES = ("registration_token_", "agent_token_")
|
|
76
|
+
REGISTRATION_TOKEN_REFUSED_HINT = (
|
|
77
|
+
"the Runner Registration Token is unknown, revoked or expired: mint a new one on the "
|
|
78
|
+
"Runners page and register with that"
|
|
79
|
+
)
|
|
73
80
|
|
|
74
81
|
# What the state directory holds after a successful bootstrap. One file, mode 0600: the
|
|
75
82
|
# private key is in it, and a Runner that loses it re-bootstraps rather than recovering.
|
|
@@ -83,6 +90,12 @@ class RunnerRegistrationError(RuntimeError):
|
|
|
83
90
|
super().__init__(message)
|
|
84
91
|
self.reason = reason
|
|
85
92
|
|
|
93
|
+
@property
|
|
94
|
+
def refuses_registration_token(self) -> bool:
|
|
95
|
+
"""Whether retrying with the same Runner Registration Token can never succeed."""
|
|
96
|
+
|
|
97
|
+
return self.reason.startswith(_REGISTRATION_TOKEN_REASON_PREFIXES)
|
|
98
|
+
|
|
86
99
|
|
|
87
100
|
class RunnerState(BaseModel):
|
|
88
101
|
"""What this process is, once registered. Persisted; reread on every restart.
|
|
@@ -236,18 +249,18 @@ class RunnerRegistrationClient:
|
|
|
236
249
|
async def bootstrap(
|
|
237
250
|
self,
|
|
238
251
|
*,
|
|
239
|
-
|
|
252
|
+
registration_token: str,
|
|
240
253
|
tags: dict[str, str],
|
|
241
254
|
isolation_mode: IsolationMode,
|
|
242
255
|
recipient_key: RecipientKey,
|
|
243
256
|
max_concurrent_directives: int = 1,
|
|
244
257
|
can_separate_uids: bool,
|
|
245
258
|
) -> tuple[RunnerState, BootstrapResponse]:
|
|
246
|
-
"""Exchange the
|
|
259
|
+
"""Exchange the Runner Registration Token for this process's durable identity."""
|
|
247
260
|
|
|
248
261
|
require_isolation_supported(isolation_mode, can_separate_uids=can_separate_uids)
|
|
249
262
|
request = BootstrapRequest(
|
|
250
|
-
|
|
263
|
+
registration_token=registration_token,
|
|
251
264
|
tags=tags,
|
|
252
265
|
isolation_mode=isolation_mode,
|
|
253
266
|
contracts_version=contracts_version,
|
|
@@ -85,6 +85,7 @@ from agentic_runner.private_state import (
|
|
|
85
85
|
require_private_files,
|
|
86
86
|
)
|
|
87
87
|
from agentic_runner.registration import (
|
|
88
|
+
REGISTRATION_TOKEN_REFUSED_HINT,
|
|
88
89
|
RUNNER_REVOKED_REASON,
|
|
89
90
|
STATE_FILENAME,
|
|
90
91
|
RunnerRegistrationClient,
|
|
@@ -148,6 +149,7 @@ __all__ = [
|
|
|
148
149
|
"READINESS_PORT_ENV",
|
|
149
150
|
"RECIPIENT_KEY_ID_ENV",
|
|
150
151
|
"RECIPIENT_PUBLIC_KEY_ENV",
|
|
152
|
+
"REGISTRATION_TOKEN_ENV",
|
|
151
153
|
"TAGS_ENV",
|
|
152
154
|
"TEMPORAL_TLS_ENV",
|
|
153
155
|
"ControlPlaneStream",
|
|
@@ -172,8 +174,10 @@ __all__ = [
|
|
|
172
174
|
_logger = logging.getLogger(__name__)
|
|
173
175
|
|
|
174
176
|
# The Helm values and the workstation installer both land here as environment (ADR-0013
|
|
175
|
-
# §8). The
|
|
176
|
-
# put it in the process table for every other uid on the host to read.
|
|
177
|
+
# §8). The Runner Registration Token is read from the environment and never from a flag: a
|
|
178
|
+
# flag would put it in the process table for every other uid on the host to read.
|
|
179
|
+
REGISTRATION_TOKEN_ENV = "AGENTIC_RUNNER_REGISTRATION_TOKEN"
|
|
180
|
+
# Its name before ADR-0021, still read so an installed Runner upgrades without an edit.
|
|
177
181
|
AGENT_TOKEN_ENV = "AGENTIC_AGENT_TOKEN"
|
|
178
182
|
CONTROL_PLANE_ENV = "AGENTIC_CONTROL_PLANE_URL"
|
|
179
183
|
TAGS_ENV = "AGENTIC_RUNNER_TAGS"
|
|
@@ -272,6 +276,24 @@ def _require_env(name: str) -> str:
|
|
|
272
276
|
return value
|
|
273
277
|
|
|
274
278
|
|
|
279
|
+
def registration_token_from_env() -> str:
|
|
280
|
+
"""``AGENTIC_RUNNER_REGISTRATION_TOKEN``, else the deprecated ``AGENTIC_AGENT_TOKEN``.
|
|
281
|
+
|
|
282
|
+
An empty string when neither is set, so a caller that can ask for it still asks.
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
if token := os.environ.get(REGISTRATION_TOKEN_ENV, "").strip():
|
|
286
|
+
return token
|
|
287
|
+
if token := os.environ.get(AGENT_TOKEN_ENV, "").strip():
|
|
288
|
+
print(
|
|
289
|
+
f"warning: {AGENT_TOKEN_ENV} is deprecated; set {REGISTRATION_TOKEN_ENV} instead",
|
|
290
|
+
file=sys.stderr,
|
|
291
|
+
flush=True,
|
|
292
|
+
)
|
|
293
|
+
return token
|
|
294
|
+
return ""
|
|
295
|
+
|
|
296
|
+
|
|
275
297
|
def _max_concurrent_directives() -> int:
|
|
276
298
|
return int(os.environ.get(MAX_CONCURRENT_DIRECTIVES_ENV, "").strip() or 1)
|
|
277
299
|
|
|
@@ -282,15 +304,16 @@ async def register(
|
|
|
282
304
|
can_separate_uids: bool,
|
|
283
305
|
client: httpx.AsyncClient | None = None,
|
|
284
306
|
control_plane: str | None = None,
|
|
285
|
-
|
|
307
|
+
registration_token: str | None = None,
|
|
286
308
|
isolation: IsolationMode | None = None,
|
|
287
309
|
) -> tuple[RunnerState, str]:
|
|
288
|
-
"""First boot (PRD issue 41): exchange the
|
|
310
|
+
"""First boot (PRD issue 41): exchange the Runner Registration Token for this
|
|
311
|
+
process's identity.
|
|
289
312
|
|
|
290
313
|
Idempotent by state file -- a restart re-reads what is already there rather than
|
|
291
314
|
registering a second Runner against the Organisation's cap (21 A7). The keyword
|
|
292
|
-
overrides are the workstation ``install`` (issue 47), which takes the
|
|
293
|
-
pasted at a prompt rather than from a Helm-set environment.
|
|
315
|
+
overrides are the workstation ``install`` (issue 47), which takes the Runner
|
|
316
|
+
Registration Token pasted at a prompt rather than from a Helm-set environment.
|
|
294
317
|
"""
|
|
295
318
|
|
|
296
319
|
existing = load_state(state_dir)
|
|
@@ -300,8 +323,13 @@ async def register(
|
|
|
300
323
|
registration = RunnerRegistrationClient(
|
|
301
324
|
base_url=control_plane or _require_env(CONTROL_PLANE_ENV), client=client
|
|
302
325
|
)
|
|
326
|
+
token = registration_token or registration_token_from_env()
|
|
327
|
+
if not token:
|
|
328
|
+
raise RunnerRegistrationError(
|
|
329
|
+
"configuration_missing", f"{REGISTRATION_TOKEN_ENV} is not set"
|
|
330
|
+
)
|
|
303
331
|
state, response = await registration.bootstrap(
|
|
304
|
-
|
|
332
|
+
registration_token=token,
|
|
305
333
|
tags=parse_tags(os.environ.get(TAGS_ENV, "")),
|
|
306
334
|
isolation_mode=isolation or isolation_mode(),
|
|
307
335
|
recipient_key=recipient,
|
|
@@ -1077,6 +1105,8 @@ async def _serve(
|
|
|
1077
1105
|
)
|
|
1078
1106
|
except RunnerRegistrationError as error:
|
|
1079
1107
|
print(f"registration refused ({error.reason}): {error}", flush=True)
|
|
1108
|
+
if error.refuses_registration_token:
|
|
1109
|
+
print(REGISTRATION_TOKEN_REFUSED_HINT, flush=True)
|
|
1080
1110
|
return 1
|
|
1081
1111
|
except UnsafeStateError as error:
|
|
1082
1112
|
print(f"refusing to start ({error.reason}): {error}", flush=True)
|
|
@@ -24,7 +24,7 @@ The prompt they pasted from the console holds these. Ask for any that is missing
|
|
|
24
24
|
pass to the Runner. Never call it or any other control plane address yourself.
|
|
25
25
|
- **Temporal address**: `host:port`, from the same page.
|
|
26
26
|
|
|
27
|
-
The **
|
|
27
|
+
The **Runner Registration Token** is not one of them. It is the reusable credential a Runner registers
|
|
28
28
|
with, and the person types it only where the Runner reads it, never into this
|
|
29
29
|
conversation.
|
|
30
30
|
|
|
@@ -34,10 +34,10 @@ conversation.
|
|
|
34
34
|
it does, in one line.
|
|
35
35
|
- **Stop on the first failure.** Show the exact error, link the doc section below that
|
|
36
36
|
covers it, and stop. Do not retry with other flags, do not work around it.
|
|
37
|
-
- **Never ask for the
|
|
38
|
-
said here reaches the model vendor and stays in this CLI's
|
|
39
|
-
reads a credential is one the person runs in their own
|
|
40
|
-
value there. If the person pastes a token or a key here anyway, do not use it: tell them
|
|
37
|
+
- **Never ask for the Runner Registration Token or any credential value in this
|
|
38
|
+
conversation.** Anything said here reaches the model vendor and stays in this CLI's
|
|
39
|
+
history. Every command that reads a credential is one the person runs in their own
|
|
40
|
+
terminal, and the person types the value there. If the person pastes a token or a key here anyway, do not use it: tell them
|
|
41
41
|
to revoke it in the console and mint or create a new one.
|
|
42
42
|
- You use only the `agentic-runner` command, the standard tools named in the docs (`uv`,
|
|
43
43
|
`docker`, `kubectl`, `helm`) and read-only checks such as `command -v`.
|
|
@@ -77,7 +77,7 @@ missing.
|
|
|
77
77
|
**This machine.** Follow
|
|
78
78
|
https://github.com/qtsone/agentic-runner/blob/main/docs/workstation.md#install. Install the
|
|
79
79
|
Runner, then show the person the command that registers it for the Organisation and ask
|
|
80
|
-
them to run it in their own terminal. The Runner asks them for the
|
|
80
|
+
them to run it in their own terminal. The Runner asks them for the Runner Registration Token there,
|
|
81
81
|
without showing it:
|
|
82
82
|
|
|
83
83
|
```sh
|
|
@@ -33,7 +33,7 @@ from agentic_runner.testing.control_plane import DEFAULT_NAMESPACE, FakeControlP
|
|
|
33
33
|
|
|
34
34
|
# A conformance Runner never runs a Directive that needs isolation or a credential, so it
|
|
35
35
|
# runs `none`, unprivileged, with every path under the test's own directory.
|
|
36
|
-
|
|
36
|
+
REGISTRATION_TOKEN = "conformance-registration-token-0123"
|
|
37
37
|
_RUN = "import sys; from agentic_runner.cli import main; sys.exit(main(['run']))"
|
|
38
38
|
|
|
39
39
|
|
|
@@ -90,7 +90,7 @@ class RunnerLauncher:
|
|
|
90
90
|
environment = {
|
|
91
91
|
**os.environ,
|
|
92
92
|
"AGENTIC_CONTROL_PLANE_URL": control_plane_url,
|
|
93
|
-
"
|
|
93
|
+
"AGENTIC_RUNNER_REGISTRATION_TOKEN": REGISTRATION_TOKEN,
|
|
94
94
|
"AGENTIC_RUNNER_ISOLATION": "none",
|
|
95
95
|
"AGENTIC_RUNNER_STATE_DIR": str(state),
|
|
96
96
|
"AGENTIC_RUNNER_WORKSPACE_ROOT": str(self.root / "workspaces"),
|
|
@@ -65,6 +65,7 @@ from __future__ import annotations
|
|
|
65
65
|
import asyncio
|
|
66
66
|
import contextlib
|
|
67
67
|
import json
|
|
68
|
+
import logging
|
|
68
69
|
import os
|
|
69
70
|
import re
|
|
70
71
|
import shlex
|
|
@@ -114,6 +115,8 @@ from agentic_runner_contracts.runner_registration import UsageWindow
|
|
|
114
115
|
|
|
115
116
|
__all__ = ["ACP_BRIDGES", "AcpBridge", "AcpRuntime", "profile_acp_executables"]
|
|
116
117
|
|
|
118
|
+
_logger = logging.getLogger(__name__)
|
|
119
|
+
|
|
117
120
|
|
|
118
121
|
@dataclass(frozen=True, slots=True)
|
|
119
122
|
class AcpBridge:
|
|
@@ -320,6 +323,7 @@ class AcpRuntime:
|
|
|
320
323
|
# Tests drive a fake ACP agent through this; production runs the pinned bridge.
|
|
321
324
|
self._bridge_argv = list(bridge_argv) if bridge_argv is not None else None
|
|
322
325
|
self._ask = ask
|
|
326
|
+
self._logged_model_ignored = False
|
|
323
327
|
|
|
324
328
|
@property
|
|
325
329
|
def _is_codex(self) -> bool:
|
|
@@ -329,6 +333,15 @@ class AcpRuntime:
|
|
|
329
333
|
def _is_claude(self) -> bool:
|
|
330
334
|
return self._cli_kind == "claude_code"
|
|
331
335
|
|
|
336
|
+
def _model(self, request: DirectiveRequest) -> str:
|
|
337
|
+
"""The model this turn runs, blank where the harness chooses its own."""
|
|
338
|
+
|
|
339
|
+
if self._is_claude:
|
|
340
|
+
return request.model or self._settings.CLAUDE_MODEL
|
|
341
|
+
if self._is_codex:
|
|
342
|
+
return request.model
|
|
343
|
+
return ""
|
|
344
|
+
|
|
332
345
|
@property
|
|
333
346
|
def _executable(self) -> str:
|
|
334
347
|
return self._bridge.executable if self._bridge is not None else self._cli_kind
|
|
@@ -450,6 +463,17 @@ class AcpRuntime:
|
|
|
450
463
|
turn = _Turn()
|
|
451
464
|
if self._bridge is None:
|
|
452
465
|
turn.notes.append(f"profile ACP command: {redact_secret_like_text(shlex.join(argv))}")
|
|
466
|
+
if request.model:
|
|
467
|
+
# The Runner knows no way to name a model to a harness it does not know,
|
|
468
|
+
# so the turn runs on that harness's own choice rather than not at all.
|
|
469
|
+
turn.notes.append(f"model ignored: {self._cli_kind} takes no model from the Runner")
|
|
470
|
+
if not self._logged_model_ignored:
|
|
471
|
+
self._logged_model_ignored = True
|
|
472
|
+
_logger.warning(
|
|
473
|
+
"%s takes no model from the Runner; its Directives run the harness's "
|
|
474
|
+
"own model",
|
|
475
|
+
self._cli_kind,
|
|
476
|
+
)
|
|
453
477
|
timed_out = False
|
|
454
478
|
async with contextlib.AsyncExitStack() as stack:
|
|
455
479
|
env = self._env(request, harness_root)
|
|
@@ -621,11 +645,18 @@ class AcpRuntime:
|
|
|
621
645
|
if self._is_claude:
|
|
622
646
|
session_params["_meta"] = {
|
|
623
647
|
"claudeCode": {
|
|
624
|
-
"options": {**_CLAUDE_SESSION_OPTIONS, "model": self.
|
|
648
|
+
"options": {**_CLAUDE_SESSION_OPTIONS, "model": self._model(request)}
|
|
625
649
|
}
|
|
626
650
|
}
|
|
627
651
|
session = await connection.request("session/new", session_params)
|
|
628
652
|
session_id = turn.session_id = str(session.get("sessionId") or "")
|
|
653
|
+
if self._is_codex and request.model:
|
|
654
|
+
# codex-acp starts a session on the harness root's model; this outranks it
|
|
655
|
+
# for the turn, and an unknown model is an ACP error that fails the turn.
|
|
656
|
+
await connection.request(
|
|
657
|
+
"session/set_config_option",
|
|
658
|
+
{"sessionId": session_id, "configId": "model", "value": request.model},
|
|
659
|
+
)
|
|
629
660
|
if self._is_claude and _offers_mode(session, _CLAUDE_MODE):
|
|
630
661
|
await connection.request(
|
|
631
662
|
"session/set_mode", {"sessionId": session_id, "modeId": _CLAUDE_MODE}
|
|
@@ -746,6 +777,7 @@ class AcpRuntime:
|
|
|
746
777
|
),
|
|
747
778
|
model_usage=model_usage,
|
|
748
779
|
usage_windows=turn.usage_windows,
|
|
780
|
+
model=self._model(request),
|
|
749
781
|
)
|
|
750
782
|
|
|
751
783
|
def _evidence(
|
|
@@ -106,6 +106,9 @@ class DirectiveRequest:
|
|
|
106
106
|
# The Profile-named ACP command (local-agents 18). Read only by the ACP runtime, and
|
|
107
107
|
# only for a `cli_kind` it pins no bridge for.
|
|
108
108
|
acp_command: tuple[str, ...] = ()
|
|
109
|
+
# The Agent's model, from its runtime context (ADR-0021). Blank runs the Runner's
|
|
110
|
+
# default for this `cli_kind`: `CLAUDE_MODEL` for Claude Code, Codex's own config.
|
|
111
|
+
model: str = ""
|
|
109
112
|
|
|
110
113
|
|
|
111
114
|
@dataclass(frozen=True, slots=True)
|
|
@@ -138,6 +141,9 @@ class DirectiveResult:
|
|
|
138
141
|
# The subscription usage windows the harness's own stream last reported, where it
|
|
139
142
|
# carries them (claude-agent-acp's rate-limit events, local-agents 10).
|
|
140
143
|
usage_windows: tuple[UsageWindow, ...] = ()
|
|
144
|
+
# The model the harness was told to run, for Evidence and usage. Blank when the
|
|
145
|
+
# harness chose its own: Codex on its config's default, a Profile-named ACP harness.
|
|
146
|
+
model: str = ""
|
|
141
147
|
|
|
142
148
|
|
|
143
149
|
# The permission mode of a runtime whose guard configuration is incomplete: it refuses
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/claude_runtime.py
RENAMED
|
@@ -103,7 +103,8 @@ class ClaudeRuntime(ResumableAgentRuntime):
|
|
|
103
103
|
evidence_limit_bytes=self._settings.CLAUDE_CLI_OUTPUT_LIMIT_BYTES,
|
|
104
104
|
)
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
model = request.model or self._settings.CLAUDE_MODEL
|
|
107
|
+
argv = _claude_argv(model)
|
|
107
108
|
if request.mcp_servers is not None:
|
|
108
109
|
# Only what the Grant let through: `--strict-mcp-config` ignores every other
|
|
109
110
|
# MCP source, so nothing in the harness root can add an ungranted server.
|
|
@@ -193,6 +194,7 @@ class ClaudeRuntime(ResumableAgentRuntime):
|
|
|
193
194
|
error=redacted_error,
|
|
194
195
|
command_hash=command_hash,
|
|
195
196
|
evidence=evidence,
|
|
197
|
+
model=model,
|
|
196
198
|
)
|
|
197
199
|
|
|
198
200
|
def has_session(self, session_id: str, sandbox: DirectiveSandbox | None) -> bool:
|
|
@@ -210,7 +212,7 @@ def _guard_mode(settings: WorkerSettings) -> str | None:
|
|
|
210
212
|
return None
|
|
211
213
|
|
|
212
214
|
|
|
213
|
-
def _claude_argv(
|
|
215
|
+
def _claude_argv(model: str) -> list[str]:
|
|
214
216
|
return [
|
|
215
217
|
"claude",
|
|
216
218
|
"--print",
|
|
@@ -218,7 +220,7 @@ def _claude_argv(settings: WorkerSettings) -> list[str]:
|
|
|
218
220
|
"--output-format",
|
|
219
221
|
"json",
|
|
220
222
|
"--model",
|
|
221
|
-
|
|
223
|
+
model,
|
|
222
224
|
"--dangerously-skip-permissions",
|
|
223
225
|
]
|
|
224
226
|
|
|
@@ -142,7 +142,7 @@ class CodexRuntime(ResumableAgentRuntime):
|
|
|
142
142
|
evidence_limit_bytes=self._settings.CODEX_CLI_OUTPUT_LIMIT_BYTES,
|
|
143
143
|
)
|
|
144
144
|
|
|
145
|
-
argv = _codex_argv(self._settings, allowlisted=allowlisted)
|
|
145
|
+
argv = _codex_argv(self._settings, allowlisted=allowlisted, model=request.model)
|
|
146
146
|
# Locked with no server bound too: otherwise a `[mcp_servers.*]` table in the
|
|
147
147
|
# Workspace or harness-root config.toml starts a process before any model turn (LA-19b).
|
|
148
148
|
argv[-1:-1] = codex_mcp_argv(request.mcp_servers or (), workspace_path)
|
|
@@ -267,6 +267,7 @@ class CodexRuntime(ResumableAgentRuntime):
|
|
|
267
267
|
error=redacted_error,
|
|
268
268
|
command_hash=command_hash,
|
|
269
269
|
evidence=evidence,
|
|
270
|
+
model=request.model,
|
|
270
271
|
)
|
|
271
272
|
|
|
272
273
|
def has_session(self, session_id: str, sandbox: DirectiveSandbox | None) -> bool:
|
|
@@ -320,7 +321,9 @@ def _guard_mode(settings: WorkerSettings, *, allowlisted: bool = False) -> str |
|
|
|
320
321
|
return None
|
|
321
322
|
|
|
322
323
|
|
|
323
|
-
def _codex_argv(
|
|
324
|
+
def _codex_argv(
|
|
325
|
+
settings: WorkerSettings, *, allowlisted: bool = False, model: str = ""
|
|
326
|
+
) -> list[str]:
|
|
324
327
|
argv = [
|
|
325
328
|
"codex",
|
|
326
329
|
"exec",
|
|
@@ -340,6 +343,10 @@ def _codex_argv(settings: WorkerSettings, *, allowlisted: bool = False) -> list[
|
|
|
340
343
|
if settings.CODEX_SANDBOX_MODE == "workspace-write":
|
|
341
344
|
network_access = "true" if allowlisted else "false"
|
|
342
345
|
argv += ["--config", f"sandbox_workspace_write.network_access={network_access}"]
|
|
346
|
+
if model:
|
|
347
|
+
# Outranks the harness root's `config.toml`; without it Codex runs that file's
|
|
348
|
+
# model, which is the Runner's default for `codex_cli`.
|
|
349
|
+
argv += ["--model", model]
|
|
343
350
|
argv.append("-")
|
|
344
351
|
return argv
|
|
345
352
|
|
|
@@ -624,7 +624,7 @@ async def install(
|
|
|
624
624
|
paths: OrgPaths,
|
|
625
625
|
settings: WorkstationSettings,
|
|
626
626
|
*,
|
|
627
|
-
|
|
627
|
+
registration_token: str,
|
|
628
628
|
platform: str = sys.platform,
|
|
629
629
|
home: Path | None = None,
|
|
630
630
|
start_service: bool = True,
|
|
@@ -633,11 +633,11 @@ async def install(
|
|
|
633
633
|
) -> list[str]:
|
|
634
634
|
"""Register this Organisation's process and install its login agent.
|
|
635
635
|
|
|
636
|
-
Registration happens here, once, with the
|
|
637
|
-
or the Organisation's Admin issued them (12 A6, QTS-1304) -- pasted at the
|
|
638
|
-
never stored: the identity bootstrap hands back is what every later start uses,
|
|
639
|
-
lost state directory means a reinstall and a re-delivery of any sealed value
|
|
640
|
-
by design.
|
|
636
|
+
Registration happens here, once, with the Runner Registration Token this user minted
|
|
637
|
+
on /me/runners or the Organisation's Admin issued them (12 A6, QTS-1304) -- pasted at the
|
|
638
|
+
prompt, never stored: the identity bootstrap hands back is what every later start uses,
|
|
639
|
+
and a lost state directory means a reinstall and a re-delivery of any sealed value
|
|
640
|
+
(22 A4), by design.
|
|
641
641
|
"""
|
|
642
642
|
|
|
643
643
|
require_any_cli(settings.path)
|
|
@@ -649,7 +649,7 @@ async def install(
|
|
|
649
649
|
can_separate_uids=False,
|
|
650
650
|
client=http_client,
|
|
651
651
|
control_plane=settings.control_plane_url,
|
|
652
|
-
|
|
652
|
+
registration_token=registration_token,
|
|
653
653
|
isolation=IsolationMode.NONE,
|
|
654
654
|
)
|
|
655
655
|
LifecycleOutbox(paths.state_dir).add(LifecycleKind.INSTALL, datetime.now(UTC))
|
|
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.15.0 → agentic_runner-3.16.0}/src/agentic_runner/device_login_activities.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/git/__init__.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/git/contracts.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/git/evidence.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/git/workspace.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/github/__init__.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/github/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/github/gh_client.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/integrations/oauth/__init__.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
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/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.15.0 → agentic_runner-3.16.0}/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
|
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/_runtime_support.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/claude_sign_in.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/command_policy.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/contract_device_login.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/contract_isolation.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/fastapi_client.py
RENAMED
|
File without changes
|
{agentic_runner-3.15.0 → agentic_runner-3.16.0}/src/agentic_runner/workers/harness_outcome.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|