agentic-runner 3.27.0__tar.gz → 3.28.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.27.0 → agentic_runner-3.28.1}/PKG-INFO +5 -4
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/README.md +3 -2
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/pyproject.toml +1 -1
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/__init__.py +1 -1
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/cli.py +61 -38
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workstation.py +113 -1
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/.gitignore +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/LICENSE +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/activities.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/attempts.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/auth_mode.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/build.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/callback.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/child_watcher.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/cli_floor.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/config.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/credentials.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/egress.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/harness_self_test.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/heartbeat_link.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/hooks.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/host_store.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/__init__.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/git/__init__.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/git/contracts.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/git/evidence.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/git/fake_workspace.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/git/workspace.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/github/__init__.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/github/auth.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/github/fake_client.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/github/gh_client.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/oauth/__init__.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/oauth/fake_provider.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/launch.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/lifecycle.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/llm_contracts.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/llm_proxy.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/mcp.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/message_store.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/oauth_connectors.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/pool_key.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/private_state.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/py.typed +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/recipient_key_secret.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/registration.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/runner_limit.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/runtime/__init__.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/runtime/verifier_command.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/sealed_box.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/service.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/sign_in.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/skill.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/skills/agentic-runner-setup/SKILL.md +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/testing/__init__.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/testing/__main__.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/testing/control_plane.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/testing/plugin.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/testing/test_conformance.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/testing/workflow.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/tiny_http.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/triage_activities.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/usage_windows.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/user_sources.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/__init__.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/_runtime_support.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/acp_runtime.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/agent_runtime.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/claude_runtime.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/claude_sign_in.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/codex_runtime.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/command_policy.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/contract_isolation.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/fastapi_client.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/harness_logins.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/harness_outcome.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/harness_usage.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/mcp_config.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/settings.py +0 -0
- {agentic_runner-3.27.0 → agentic_runner-3.28.1}/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.28.1
|
|
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==3.
|
|
8
|
+
Requires-Dist: agentic-runner-contracts==3.28.1
|
|
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
|
|
@@ -47,7 +47,8 @@ root: Python, git, `codex`, `claude`, nothing else) and installs with
|
|
|
47
47
|
`charts/agentic-runner`.
|
|
48
48
|
|
|
49
49
|
On a workstation it is a per-user login agent, one per Runner:
|
|
50
|
-
`agentic-runner install | start | stop | status <name>`
|
|
51
|
-
logon task; never `sudo`), with Credential References in
|
|
50
|
+
`agentic-runner install | start | stop | status <name>` and `agentic-runner list`
|
|
51
|
+
(LaunchAgent, systemd user unit or logon task; never `sudo`), with Credential References in
|
|
52
|
+
the OS credential store.
|
|
52
53
|
|
|
53
54
|
Licensed under AGPL-3.0-only.
|
|
@@ -28,7 +28,8 @@ root: Python, git, `codex`, `claude`, nothing else) and installs with
|
|
|
28
28
|
`charts/agentic-runner`.
|
|
29
29
|
|
|
30
30
|
On a workstation it is a per-user login agent, one per Runner:
|
|
31
|
-
`agentic-runner install | start | stop | status <name>`
|
|
32
|
-
logon task; never `sudo`), with Credential References in
|
|
31
|
+
`agentic-runner install | start | stop | status <name>` and `agentic-runner list`
|
|
32
|
+
(LaunchAgent, systemd user unit or logon task; never `sudo`), with Credential References in
|
|
33
|
+
the OS credential store.
|
|
33
34
|
|
|
34
35
|
Licensed under AGPL-3.0-only.
|
|
@@ -10,7 +10,7 @@ dependencies = [
|
|
|
10
10
|
# Exactly this release's contracts: the two ship as one version, and an unpinned
|
|
11
11
|
# requirement let `uv tool upgrade` keep an older contracts wheel the Runner cannot
|
|
12
12
|
# import from (QTS-1473). `scripts/set-version.py` moves it with the version.
|
|
13
|
-
"agentic-runner-contracts==3.
|
|
13
|
+
"agentic-runner-contracts==3.28.1",
|
|
14
14
|
# Imported directly by `registration.py` (the Ed25519 identity that signs every
|
|
15
15
|
# heartbeat); already present transitively through pyjwt[crypto], declared because
|
|
16
16
|
# we import it.
|
|
@@ -11,10 +11,10 @@ namespace and queue this process was assigned. It is idempotent by state file --
|
|
|
11
11
|
restart re-reads what is already there rather than registering a second Runner against
|
|
12
12
|
the Organisation's cap.
|
|
13
13
|
|
|
14
|
-
``install | start | stop | status <name
|
|
15
|
-
Runner (PRD issue 47, ``workstation.py``): one login agent per Runner, managed
|
|
16
|
-
who hosts it, with no ``sudo`` anywhere. ``<name>`` is the Runner's, the one the
|
|
17
|
-
lists it under (QTS-1773).
|
|
14
|
+
``install | start | stop | status <name>``, ``credential set`` and ``list`` are the
|
|
15
|
+
workstation Runner (PRD issue 47, ``workstation.py``): one login agent per Runner, managed
|
|
16
|
+
by the user who hosts it, with no ``sudo`` anywhere. ``<name>`` is the Runner's, the one the
|
|
17
|
+
console lists it under (QTS-1773); a machine with one Runner needs none (QTS-1774).
|
|
18
18
|
|
|
19
19
|
``sign-in [claude|codex]`` gives a person's own Runner their LLM access: their subscription,
|
|
20
20
|
through the vendor's own sign-in in this terminal, or an API key stored in the Runner's
|
|
@@ -107,6 +107,7 @@ _NAME_HELP = (
|
|
|
107
107
|
"this Runner's name: the console lists it under this name, and every command on this "
|
|
108
108
|
"machine takes it"
|
|
109
109
|
)
|
|
110
|
+
_INSTALLED_NAME_HELP = "the Runner's name; omitted when this machine runs one Runner"
|
|
110
111
|
|
|
111
112
|
|
|
112
113
|
def _old_org_flag(parser: argparse.ArgumentParser) -> None:
|
|
@@ -211,14 +212,19 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
211
212
|
driven = subcommands.add_parser(
|
|
212
213
|
service_verb, help=f"{service_verb} one workstation Runner's login agent"
|
|
213
214
|
)
|
|
214
|
-
driven.add_argument("name", help=
|
|
215
|
+
driven.add_argument("name", nargs="?", help=_INSTALLED_NAME_HELP)
|
|
215
216
|
driven.add_argument("--root", default=None, type=Path)
|
|
216
217
|
|
|
218
|
+
listed = subcommands.add_parser(
|
|
219
|
+
"list", help="the workstation Runners installed on this machine, and which are running"
|
|
220
|
+
)
|
|
221
|
+
listed.add_argument("--root", default=None, type=Path)
|
|
222
|
+
|
|
217
223
|
credential = subcommands.add_parser(
|
|
218
224
|
"credential", help="install a Credential Reference value into this host's store"
|
|
219
225
|
)
|
|
220
226
|
credential.add_argument("action", choices=("set",))
|
|
221
|
-
credential.add_argument("name", help=
|
|
227
|
+
credential.add_argument("name", nargs="?", help=_INSTALLED_NAME_HELP)
|
|
222
228
|
credential.add_argument("reference")
|
|
223
229
|
credential.add_argument("--root", default=None, type=Path)
|
|
224
230
|
|
|
@@ -233,7 +239,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
233
239
|
status = subcommands.add_parser(
|
|
234
240
|
"status", help="print this installation's versions and Recipient Key fingerprint"
|
|
235
241
|
)
|
|
236
|
-
status.add_argument("name", nargs="?", help=
|
|
242
|
+
status.add_argument("name", nargs="?", help=_INSTALLED_NAME_HELP)
|
|
237
243
|
status.add_argument("--root", default=None, type=Path)
|
|
238
244
|
|
|
239
245
|
sign_in = subcommands.add_parser(
|
|
@@ -256,7 +262,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
256
262
|
sign_in.add_argument(
|
|
257
263
|
"--name",
|
|
258
264
|
default=None,
|
|
259
|
-
help="the workstation Runner's name, when this
|
|
265
|
+
help="the workstation Runner's name, when this machine runs more than one",
|
|
260
266
|
)
|
|
261
267
|
_old_org_flag(sign_in)
|
|
262
268
|
sign_in.add_argument("--root", default=None, type=Path, help=argparse.SUPPRESS)
|
|
@@ -351,9 +357,21 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
351
357
|
return workstation.run_process(
|
|
352
358
|
_runner_paths(arguments), login_agent=arguments.login_agent
|
|
353
359
|
)
|
|
360
|
+
if installed := _installed_instead_of_run():
|
|
361
|
+
print(
|
|
362
|
+
f"this machine runs {', '.join(installed)} as login agents: start one with "
|
|
363
|
+
"`agentic-runner start <name>`. `run` serves a Runner its environment sets "
|
|
364
|
+
"up, as in a container",
|
|
365
|
+
file=sys.stderr,
|
|
366
|
+
)
|
|
367
|
+
return 2
|
|
354
368
|
return asyncio.run(service.run(attestation=_image_attestation(), install=_run_install()))
|
|
355
369
|
if arguments.command in {"install", "start", "stop", "credential"}:
|
|
356
370
|
return _workstation(arguments)
|
|
371
|
+
if arguments.command == "list":
|
|
372
|
+
for line in workstation.list_lines(arguments.root or workstation.default_root()):
|
|
373
|
+
print(line)
|
|
374
|
+
return 0
|
|
357
375
|
if arguments.command == "recipient-key":
|
|
358
376
|
api, kube_ns = in_cluster()
|
|
359
377
|
pair = ensure_recipient_key(
|
|
@@ -364,9 +382,17 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
364
382
|
)
|
|
365
383
|
return 0
|
|
366
384
|
if arguments.command == "status":
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
385
|
+
if arguments.name or (
|
|
386
|
+
not _in_container()
|
|
387
|
+
and workstation.installed_names(arguments.root or workstation.default_root())
|
|
388
|
+
):
|
|
389
|
+
try:
|
|
390
|
+
lines = workstation.status_lines(_runner_paths(arguments))
|
|
391
|
+
except ValueError as error:
|
|
392
|
+
print(error, file=sys.stderr)
|
|
393
|
+
return 2
|
|
394
|
+
else:
|
|
395
|
+
lines = status_lines()
|
|
370
396
|
for line in lines:
|
|
371
397
|
print(line)
|
|
372
398
|
return 0
|
|
@@ -389,16 +415,33 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
389
415
|
return _callback(arguments)
|
|
390
416
|
|
|
391
417
|
|
|
392
|
-
def _runner_paths(
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
418
|
+
def _runner_paths(
|
|
419
|
+
arguments: argparse.Namespace, *, how: str = "name one"
|
|
420
|
+
) -> workstation.RunnerPaths:
|
|
421
|
+
"""``<name>``, or the one Runner this machine runs -- nothing to remember (QTS-1774)."""
|
|
422
|
+
|
|
423
|
+
root = arguments.root or workstation.default_root()
|
|
424
|
+
if not arguments.name:
|
|
425
|
+
return workstation.only_runner(root, how=how)
|
|
426
|
+
return workstation.RunnerPaths(root=root, name=workstation.validate_name(arguments.name))
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
def _installed_instead_of_run() -> list[str]:
|
|
430
|
+
"""The Runners installed here, when a bare ``run`` would start none of them.
|
|
431
|
+
|
|
432
|
+
An installed Runner is its login agent's process; ``run`` without ``--name`` registers
|
|
433
|
+
from the environment, and on a workstation that holds neither a token nor an identity
|
|
434
|
+
it could only fail without saying what to type instead (QTS-1774).
|
|
435
|
+
"""
|
|
436
|
+
|
|
437
|
+
if _in_container() or registration_token_from_env() or load_state(_state_dir()):
|
|
438
|
+
return []
|
|
439
|
+
return workstation.installed_names(workstation.default_root())
|
|
397
440
|
|
|
398
441
|
|
|
399
442
|
def _workstation(arguments: argparse.Namespace) -> int:
|
|
400
|
-
paths = _runner_paths(arguments)
|
|
401
443
|
try:
|
|
444
|
+
paths = _runner_paths(arguments)
|
|
402
445
|
if arguments.command == "install":
|
|
403
446
|
return _install(arguments, paths)
|
|
404
447
|
if arguments.command == "start":
|
|
@@ -482,7 +525,7 @@ def _sign_in(arguments: argparse.Namespace) -> int:
|
|
|
482
525
|
store: KeyStore
|
|
483
526
|
if arguments.name or not _in_container():
|
|
484
527
|
try:
|
|
485
|
-
paths =
|
|
528
|
+
paths = _runner_paths(arguments, how="name one with --name")
|
|
486
529
|
except ValueError as error:
|
|
487
530
|
print(error, file=sys.stderr)
|
|
488
531
|
return 2
|
|
@@ -495,26 +538,6 @@ def _sign_in(arguments: argparse.Namespace) -> int:
|
|
|
495
538
|
return asyncio.run(service.sign_in(arguments.runtime, store=store, method=arguments.method))
|
|
496
539
|
|
|
497
540
|
|
|
498
|
-
def _sign_in_paths(arguments: argparse.Namespace) -> workstation.RunnerPaths:
|
|
499
|
-
"""``--name``, or the one Runner this workstation runs -- no id to type."""
|
|
500
|
-
|
|
501
|
-
if arguments.name:
|
|
502
|
-
return _runner_paths(arguments)
|
|
503
|
-
root = arguments.root or workstation.default_root()
|
|
504
|
-
installed = (
|
|
505
|
-
sorted(path.name for path in root.iterdir() if (path / "workstation.json").is_file())
|
|
506
|
-
if root.is_dir()
|
|
507
|
-
else []
|
|
508
|
-
)
|
|
509
|
-
if len(installed) != 1:
|
|
510
|
-
raise ValueError(
|
|
511
|
-
"no workstation Runner is installed here"
|
|
512
|
-
if not installed
|
|
513
|
-
else f"this workstation runs {', '.join(installed)}: name one with --name"
|
|
514
|
-
)
|
|
515
|
-
return workstation.RunnerPaths(root=root, name=installed[0])
|
|
516
|
-
|
|
517
|
-
|
|
518
541
|
def _install(arguments: argparse.Namespace, paths: workstation.RunnerPaths) -> int:
|
|
519
542
|
if not arguments.control_plane:
|
|
520
543
|
print(f"--control-plane (or {CONTROL_PLANE_ENV}) is required", file=sys.stderr)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""The workstation Runner: one login agent per Runner (PRD issue 47, map ticket 23).
|
|
2
2
|
|
|
3
|
-
``agentic-runner install | start | stop | status <name
|
|
3
|
+
``agentic-runner install | start | stop | status <name>`` and ``list``. Everything a CI-runner
|
|
4
4
|
precedent does on a developer machine and nothing a daemon would need:
|
|
5
5
|
|
|
6
6
|
* **One process per Runner** (23 item 3), each with its own state directory, identity,
|
|
@@ -47,16 +47,20 @@ from xml.sax.saxutils import escape
|
|
|
47
47
|
import httpx
|
|
48
48
|
from pydantic import BaseModel, ConfigDict
|
|
49
49
|
|
|
50
|
+
from agentic_runner import __version__ as runner_version
|
|
50
51
|
from agentic_runner import service
|
|
51
52
|
from agentic_runner.build import build_id
|
|
52
53
|
from agentic_runner.cli_floor import CLI_FLOORS, CLI_NAMES, meets_floor, parse_cli_version
|
|
53
54
|
from agentic_runner.config import CONFIG_FILE_ENV
|
|
54
55
|
from agentic_runner.host_store import open_workstation_store
|
|
55
56
|
from agentic_runner.lifecycle import LifecycleOutbox
|
|
57
|
+
from agentic_runner.llm_contracts import load_llm_contracts
|
|
56
58
|
from agentic_runner.pool_key import parse_pool_key, save_pool_key
|
|
59
|
+
from agentic_runner.private_state import UnsafeStateError
|
|
57
60
|
from agentic_runner.registration import load_state
|
|
58
61
|
from agentic_runner.service import HEARTBEAT_STAMP_NAME, PIDFILE_NAME
|
|
59
62
|
from agentic_runner.workers.acp_runtime import ACP_BRIDGES
|
|
63
|
+
from agentic_runner_contracts.public_metadata import NAMESPACE_PREFIX
|
|
60
64
|
from agentic_runner_contracts.runner_registration import (
|
|
61
65
|
RUNNER_NAME_PATTERN,
|
|
62
66
|
CliVersion,
|
|
@@ -84,7 +88,10 @@ __all__ = [
|
|
|
84
88
|
"default_root",
|
|
85
89
|
"install",
|
|
86
90
|
"install_channel",
|
|
91
|
+
"installed_names",
|
|
92
|
+
"list_lines",
|
|
87
93
|
"locate_clis",
|
|
94
|
+
"only_runner",
|
|
88
95
|
"parse_acp_cli_kinds",
|
|
89
96
|
"require_any_cli",
|
|
90
97
|
"run_environment",
|
|
@@ -132,6 +139,36 @@ def default_root(*, platform: str = sys.platform, environ: Mapping[str, str] = o
|
|
|
132
139
|
return (Path(state_home) if state_home else home / ".local" / "state") / "agentic-runner"
|
|
133
140
|
|
|
134
141
|
|
|
142
|
+
def installed_names(root: Path) -> list[str]:
|
|
143
|
+
"""Every Runner installed under ``root``, by name.
|
|
144
|
+
|
|
145
|
+
A directory whose name is not a Runner's is skipped: the guide moves an old install
|
|
146
|
+
aside as ``<name>.organisation`` before a new token, and that one is not a Runner here.
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
if not root.is_dir():
|
|
150
|
+
return []
|
|
151
|
+
return sorted(
|
|
152
|
+
path.name
|
|
153
|
+
for path in root.iterdir()
|
|
154
|
+
if re.fullmatch(RUNNER_NAME_PATTERN, path.name)
|
|
155
|
+
and RunnerPaths(root=root, name=path.name).settings_file.is_file()
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def only_runner(root: Path, *, how: str = "name one") -> RunnerPaths:
|
|
160
|
+
"""The one Runner installed here, so a command needs no name (QTS-1774)."""
|
|
161
|
+
|
|
162
|
+
names = installed_names(root)
|
|
163
|
+
if len(names) == 1:
|
|
164
|
+
return RunnerPaths(root=root, name=names[0])
|
|
165
|
+
if not names:
|
|
166
|
+
raise ValueError(f"no workstation Runner is installed under {root}")
|
|
167
|
+
raise ValueError(
|
|
168
|
+
f"this machine runs {', '.join(names)}: {how} (`agentic-runner list` shows each)"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
|
|
135
172
|
@dataclass(frozen=True)
|
|
136
173
|
class RunnerPaths:
|
|
137
174
|
"""``<root>/<name>/`` and everything the process keeps under it."""
|
|
@@ -184,6 +221,12 @@ class RunnerPaths:
|
|
|
184
221
|
def log(self) -> Path:
|
|
185
222
|
return self.state_dir / "runner.log"
|
|
186
223
|
|
|
224
|
+
@property
|
|
225
|
+
def started_version(self) -> Path:
|
|
226
|
+
# Written by the process, not `install`: every Runner here runs one console script,
|
|
227
|
+
# and after `uv tool upgrade` a Runner not restarted still runs the old version.
|
|
228
|
+
return self.state_dir / "runner-version"
|
|
229
|
+
|
|
187
230
|
@property
|
|
188
231
|
def socket_dir(self) -> Path:
|
|
189
232
|
# `sun_path` is ~104 bytes and "~/Library/Application Support/..." is most of
|
|
@@ -614,6 +657,74 @@ def status_lines(paths: RunnerPaths, *, now: datetime | None = None) -> list[str
|
|
|
614
657
|
return lines
|
|
615
658
|
|
|
616
659
|
|
|
660
|
+
_LIST_HEADER: Final = (
|
|
661
|
+
"NAME",
|
|
662
|
+
"ORGANISATION",
|
|
663
|
+
"CONTRACT",
|
|
664
|
+
"CONTROL PLANE",
|
|
665
|
+
"VERSION",
|
|
666
|
+
"LOGIN AGENT",
|
|
667
|
+
)
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
def list_lines(root: Path) -> list[str]:
|
|
671
|
+
"""``list``: one row per Runner installed here (QTS-1774).
|
|
672
|
+
|
|
673
|
+
Ids, not names: the Runner is told neither the Organisation's nor the Contract's name.
|
|
674
|
+
Eight characters, as the console shows a Runner's id beside its name (Spec: Runners
|
|
675
|
+
rev 7).
|
|
676
|
+
"""
|
|
677
|
+
|
|
678
|
+
names = installed_names(root)
|
|
679
|
+
if not names:
|
|
680
|
+
return [f"no workstation Runner is installed under {root}"]
|
|
681
|
+
rows = [
|
|
682
|
+
_LIST_HEADER,
|
|
683
|
+
*(_list_row_or_reason(RunnerPaths(root=root, name=name)) for name in names),
|
|
684
|
+
]
|
|
685
|
+
widths = [max(len(row[column]) for row in rows) for column in range(len(_LIST_HEADER) - 1)]
|
|
686
|
+
return [
|
|
687
|
+
" ".join([*(cell.ljust(width) for cell, width in zip(row, widths, strict=False)), row[-1]])
|
|
688
|
+
for row in rows
|
|
689
|
+
]
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
def _list_row_or_reason(paths: RunnerPaths) -> tuple[str, str, str, str, str, str]:
|
|
693
|
+
"""One install that cannot be read must not hide the others' rows (QTS-1910).
|
|
694
|
+
|
|
695
|
+
The first line only: a pydantic error runs to one line per field, and the row is one.
|
|
696
|
+
"""
|
|
697
|
+
|
|
698
|
+
try:
|
|
699
|
+
return _list_row(paths)
|
|
700
|
+
except (OSError, ValueError, UnsafeStateError) as error:
|
|
701
|
+
reason = str(error).splitlines()[0] if str(error) else type(error).__name__
|
|
702
|
+
return (paths.name, "-", "-", "-", "-", f"unreadable: {reason}")
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
def _list_row(paths: RunnerPaths) -> tuple[str, str, str, str, str, str]:
|
|
706
|
+
state = load_state(paths.state_dir)
|
|
707
|
+
contracts = load_llm_contracts(paths.state_dir)
|
|
708
|
+
try:
|
|
709
|
+
version = paths.started_version.read_text(encoding="utf-8").strip() or "-"
|
|
710
|
+
except OSError:
|
|
711
|
+
version = "-"
|
|
712
|
+
return (
|
|
713
|
+
paths.name,
|
|
714
|
+
state.temporal_namespace.removeprefix(NAMESPACE_PREFIX)[:8] if state else "-",
|
|
715
|
+
(
|
|
716
|
+
"-"
|
|
717
|
+
if not contracts
|
|
718
|
+
else str(contracts[0].contract_id)[:8]
|
|
719
|
+
if len(contracts) == 1
|
|
720
|
+
else f"{len(contracts)} Contracts"
|
|
721
|
+
),
|
|
722
|
+
WorkstationSettings.load(paths).control_plane_url,
|
|
723
|
+
version,
|
|
724
|
+
"running" if process_id(paths) else "stopped",
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
|
|
617
728
|
def next_step_lines(host_party: str) -> list[str]:
|
|
618
729
|
"""Where to go once the Runner is live (QTS-1314): the dogfood install ended at
|
|
619
730
|
``started`` and left the person with no idea what the console wanted next.
|
|
@@ -735,6 +846,7 @@ def run_process(paths: RunnerPaths, *, login_agent: bool) -> int:
|
|
|
735
846
|
return 1
|
|
736
847
|
for name, value in run_environment(paths, settings).items():
|
|
737
848
|
os.environ[name] = value
|
|
849
|
+
paths.started_version.write_text(runner_version, encoding="utf-8")
|
|
738
850
|
store = open_workstation_store(paths.name, fallback=paths.credentials)
|
|
739
851
|
attestation = collect_attestation(
|
|
740
852
|
channel=settings.install_channel,
|
|
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.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/git/__init__.py
RENAMED
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/git/contracts.py
RENAMED
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/git/evidence.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/git/workspace.py
RENAMED
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/github/__init__.py
RENAMED
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/github/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/integrations/github/gh_client.py
RENAMED
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.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
|
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/_runtime_support.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/claude_runtime.py
RENAMED
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/claude_sign_in.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/command_policy.py
RENAMED
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/contract_isolation.py
RENAMED
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/fastapi_client.py
RENAMED
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/harness_logins.py
RENAMED
|
File without changes
|
{agentic_runner-3.27.0 → agentic_runner-3.28.1}/src/agentic_runner/workers/harness_outcome.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|