agentic-runner 3.29.0__tar.gz → 3.30.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.29.0 → agentic_runner-3.30.0}/PKG-INFO +2 -2
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/pyproject.toml +1 -1
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/__init__.py +1 -1
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/cli.py +57 -1
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/service.py +23 -6
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workstation.py +54 -5
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/.gitignore +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/LICENSE +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/README.md +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/activities.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/attempts.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/auth_mode.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/build.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/callback.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/child_watcher.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/cli_floor.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/config.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/credentials.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/egress.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/harness_self_test.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/heartbeat_link.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/hooks.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/host_store.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/__init__.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/git/__init__.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/git/contracts.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/git/evidence.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/git/fake_workspace.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/git/workspace.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/github/__init__.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/github/auth.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/github/fake_client.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/github/gh_client.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/oauth/__init__.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/oauth/fake_provider.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/launch.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/lifecycle.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/llm_contracts.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/llm_proxy.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/mcp.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/message_store.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/oauth_connectors.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/organisation_name.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/pool_key.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/private_state.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/py.typed +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/recipient_key_secret.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/registration.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/runner_limit.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/runtime/__init__.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/runtime/verifier_command.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/sealed_box.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/sign_in.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/skill.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/skills/agentic-runner-setup/SKILL.md +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/testing/__init__.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/testing/__main__.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/testing/control_plane.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/testing/plugin.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/testing/test_conformance.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/testing/workflow.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/tiny_http.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/triage_activities.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/usage_windows.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/user_sources.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/__init__.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/_runtime_support.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/acp_runtime.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/agent_runtime.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/claude_runtime.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/claude_sign_in.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/codex_runtime.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/command_policy.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/contract_isolation.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/fastapi_client.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/harness_logins.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/harness_outcome.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/harness_usage.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/mcp_config.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/settings.py +0 -0
- {agentic_runner-3.29.0 → agentic_runner-3.30.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.30.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==3.
|
|
8
|
+
Requires-Dist: agentic-runner-contracts==3.30.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
|
|
@@ -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.30.0",
|
|
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,7 +11,7 @@ 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>``, ``credential set`` and ``list`` are the
|
|
14
|
+
``install | start | stop | restart | status <name>``, ``credential set`` and ``list`` are the
|
|
15
15
|
workstation Runner (PRD issue 47, ``workstation.py``): one login agent per Runner, managed
|
|
16
16
|
by the user who hosts it, with no ``sudo`` anywhere. ``<name>`` is the Runner's, the one the
|
|
17
17
|
console lists it under (QTS-1773); a machine with one Runner needs none (QTS-1774).
|
|
@@ -215,6 +215,17 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
215
215
|
driven.add_argument("name", nargs="?", help=_INSTALLED_NAME_HELP)
|
|
216
216
|
driven.add_argument("--root", default=None, type=Path)
|
|
217
217
|
|
|
218
|
+
restart = subcommands.add_parser(
|
|
219
|
+
"restart",
|
|
220
|
+
help="restart running workstation Runners on the agentic-runner installed now, as "
|
|
221
|
+
"after `uv tool upgrade`",
|
|
222
|
+
)
|
|
223
|
+
restart.add_argument("name", nargs="?", help=_INSTALLED_NAME_HELP)
|
|
224
|
+
which = restart.add_mutually_exclusive_group()
|
|
225
|
+
which.add_argument("--name", dest="name_flag", default=None, help=_INSTALLED_NAME_HELP)
|
|
226
|
+
which.add_argument("--all", action="store_true", help="every Runner running on this machine")
|
|
227
|
+
restart.add_argument("--root", default=None, type=Path)
|
|
228
|
+
|
|
218
229
|
listed = subcommands.add_parser(
|
|
219
230
|
"list", help="the workstation Runners installed on this machine, and which are running"
|
|
220
231
|
)
|
|
@@ -368,6 +379,8 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
368
379
|
return asyncio.run(service.run(attestation=_image_attestation(), install=_run_install()))
|
|
369
380
|
if arguments.command in {"install", "start", "stop", "credential"}:
|
|
370
381
|
return _workstation(arguments)
|
|
382
|
+
if arguments.command == "restart":
|
|
383
|
+
return _restart(arguments)
|
|
371
384
|
if arguments.command == "list":
|
|
372
385
|
for line in workstation.list_lines(arguments.root or workstation.default_root()):
|
|
373
386
|
print(line)
|
|
@@ -462,6 +475,49 @@ def _workstation(arguments: argparse.Namespace) -> int:
|
|
|
462
475
|
return 1
|
|
463
476
|
|
|
464
477
|
|
|
478
|
+
def _restart(arguments: argparse.Namespace) -> int:
|
|
479
|
+
"""``restart <name> | --name <name> | --all``: exit 2 names the Runners installed here.
|
|
480
|
+
|
|
481
|
+
A stopped Runner is not started: it was stopped on purpose, and ``systemctl restart``
|
|
482
|
+
would start it where ``launchctl kickstart`` refuses to, so the two OSes would differ.
|
|
483
|
+
"""
|
|
484
|
+
|
|
485
|
+
root = arguments.root or workstation.default_root()
|
|
486
|
+
name = arguments.name or arguments.name_flag
|
|
487
|
+
if arguments.all and name:
|
|
488
|
+
print("restart takes a name or --all, not both", file=sys.stderr)
|
|
489
|
+
return 2
|
|
490
|
+
try:
|
|
491
|
+
if arguments.all:
|
|
492
|
+
targets = [
|
|
493
|
+
workstation.RunnerPaths(root=root, name=installed)
|
|
494
|
+
for installed in workstation.installed_names(root)
|
|
495
|
+
]
|
|
496
|
+
if not targets:
|
|
497
|
+
raise ValueError(f"no workstation Runner is installed under {root}")
|
|
498
|
+
elif name:
|
|
499
|
+
targets = [workstation.installed_runner(root, name)]
|
|
500
|
+
else:
|
|
501
|
+
targets = [workstation.only_runner(root, how="name one, or restart --all")]
|
|
502
|
+
except ValueError as error:
|
|
503
|
+
print(error, file=sys.stderr)
|
|
504
|
+
return 2
|
|
505
|
+
failed = False
|
|
506
|
+
for paths in targets:
|
|
507
|
+
if workstation.process_id(paths) is None:
|
|
508
|
+
print(f"{paths.name} is stopped; `agentic-runner start {paths.name}` starts it")
|
|
509
|
+
failed = failed or not arguments.all
|
|
510
|
+
continue
|
|
511
|
+
try:
|
|
512
|
+
pid, version = workstation.restart(paths)
|
|
513
|
+
except (FileNotFoundError, RuntimeError) as error:
|
|
514
|
+
print(f"{paths.name}: restart failed: {error}", file=sys.stderr)
|
|
515
|
+
failed = True
|
|
516
|
+
continue
|
|
517
|
+
print(f"restarted {paths.name}: pid {pid}, agentic-runner {version}")
|
|
518
|
+
return 1 if failed else 0
|
|
519
|
+
|
|
520
|
+
|
|
465
521
|
def _image_attestation() -> HostAttestation:
|
|
466
522
|
"""What a container Runner says about itself, where issue 47 gave the workstation its
|
|
467
523
|
own: the CLIs it found are what the registry serves and routing matches on."""
|
|
@@ -1301,14 +1301,17 @@ async def sign_in(which: str | None, *, store: KeyStore, method: str = OAUTH_TOK
|
|
|
1301
1301
|
can = can_separate_uids()
|
|
1302
1302
|
try:
|
|
1303
1303
|
require_isolation_supported(mode, can_separate_uids=can)
|
|
1304
|
+
# `run` gives the settings this default; a sign-in must build the same ones, or a
|
|
1305
|
+
# workstation, whose environment sets only the control plane, is refused (QTS-2157).
|
|
1306
|
+
_default_callback_url(os.environ.get(CONTROL_PLANE_ENV, "").strip())
|
|
1304
1307
|
settings = get_worker_settings()
|
|
1305
1308
|
except RunnerRegistrationError as error:
|
|
1306
1309
|
print(f"refusing to sign in ({error.reason}): {error}", file=sys.stderr)
|
|
1307
1310
|
return 1
|
|
1308
|
-
except ValidationError:
|
|
1311
|
+
except ValidationError as error:
|
|
1309
1312
|
print(
|
|
1310
|
-
"refusing to sign in: run this with the Runner's
|
|
1311
|
-
"`kubectl exec`, or on the workstation that runs it)",
|
|
1313
|
+
f"refusing to sign in: {_invalid_settings(error)}; run this with the Runner's "
|
|
1314
|
+
"environment (`docker exec`, `kubectl exec`, or on the workstation that runs it)",
|
|
1312
1315
|
file=sys.stderr,
|
|
1313
1316
|
)
|
|
1314
1317
|
return 2
|
|
@@ -1336,6 +1339,22 @@ async def sign_in(which: str | None, *, store: KeyStore, method: str = OAUTH_TOK
|
|
|
1336
1339
|
_SIGN_IN_CLIS: Final[Mapping[str, str]] = {"claude_code": "claude", "codex_cli": "codex"}
|
|
1337
1340
|
|
|
1338
1341
|
|
|
1342
|
+
def _default_callback_url(control_plane: str) -> None:
|
|
1343
|
+
# The control plane the activities call back is the one this process registered
|
|
1344
|
+
# with, unless the operator points them at an internal address explicitly.
|
|
1345
|
+
if control_plane:
|
|
1346
|
+
os.environ.setdefault("INTERNAL_FASTAPI_BASE_URL", control_plane)
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
def _invalid_settings(error: ValidationError) -> str:
|
|
1350
|
+
"""``INTERNAL_FASTAPI_BASE_URL (Field required)``, one per field, never the value."""
|
|
1351
|
+
|
|
1352
|
+
return ", ".join(
|
|
1353
|
+
f"{'.'.join(str(part) for part in detail['loc'])} ({detail['msg']})"
|
|
1354
|
+
for detail in error.errors(include_input=False, include_url=False)
|
|
1355
|
+
)
|
|
1356
|
+
|
|
1357
|
+
|
|
1339
1358
|
async def run(
|
|
1340
1359
|
*,
|
|
1341
1360
|
http_client: httpx.AsyncClient | None = None,
|
|
@@ -1416,9 +1435,7 @@ async def _run(
|
|
|
1416
1435
|
except (RunnerRegistrationError, UnsafeStateError) as error:
|
|
1417
1436
|
print(f"refusing to start ({error.reason}): {error}", flush=True)
|
|
1418
1437
|
return 1
|
|
1419
|
-
|
|
1420
|
-
# with, unless the operator points them at an internal address explicitly.
|
|
1421
|
-
os.environ.setdefault("INTERNAL_FASTAPI_BASE_URL", control_plane)
|
|
1438
|
+
_default_callback_url(control_plane)
|
|
1422
1439
|
settings = get_worker_settings()
|
|
1423
1440
|
try:
|
|
1424
1441
|
attestation = with_profile_acp_cli_kinds(with_acp_bridges(attestation, settings), settings)
|
|
@@ -1,7 +1,7 @@
|
|
|
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>`` and ``list``. Everything
|
|
4
|
-
precedent does on a developer machine and nothing a daemon would need:
|
|
3
|
+
``agentic-runner install | start | stop | restart | status <name>`` and ``list``. Everything
|
|
4
|
+
a CI-runner 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,
|
|
7
7
|
namespace, Runner Token, hooks, credential store and Workspaces under ``<root>/<name>/``.
|
|
@@ -37,11 +37,12 @@ import shutil
|
|
|
37
37
|
import subprocess
|
|
38
38
|
import sys
|
|
39
39
|
import tempfile
|
|
40
|
+
import time
|
|
40
41
|
from collections.abc import Callable, Mapping, Sequence
|
|
41
42
|
from dataclasses import dataclass
|
|
42
43
|
from datetime import UTC, datetime
|
|
43
44
|
from pathlib import Path
|
|
44
|
-
from typing import Any, Final
|
|
45
|
+
from typing import Any, Final, Literal
|
|
45
46
|
from xml.sax.saxutils import escape
|
|
46
47
|
|
|
47
48
|
import httpx
|
|
@@ -91,11 +92,13 @@ __all__ = [
|
|
|
91
92
|
"install",
|
|
92
93
|
"install_channel",
|
|
93
94
|
"installed_names",
|
|
95
|
+
"installed_runner",
|
|
94
96
|
"list_lines",
|
|
95
97
|
"locate_clis",
|
|
96
98
|
"only_runner",
|
|
97
99
|
"parse_acp_cli_kinds",
|
|
98
100
|
"require_any_cli",
|
|
101
|
+
"restart",
|
|
99
102
|
"run_environment",
|
|
100
103
|
"run_process",
|
|
101
104
|
"service_definition",
|
|
@@ -158,6 +161,16 @@ def installed_names(root: Path) -> list[str]:
|
|
|
158
161
|
)
|
|
159
162
|
|
|
160
163
|
|
|
164
|
+
def installed_runner(root: Path, name: str) -> RunnerPaths:
|
|
165
|
+
"""``<name>``, refused with the names installed here when it is not one of them."""
|
|
166
|
+
|
|
167
|
+
names = installed_names(root)
|
|
168
|
+
if name in names:
|
|
169
|
+
return RunnerPaths(root=root, name=name)
|
|
170
|
+
installed = ", ".join(names) if names else "none"
|
|
171
|
+
raise ValueError(f"no Runner named {name!r} is installed under {root}; installed: {installed}")
|
|
172
|
+
|
|
173
|
+
|
|
161
174
|
def only_runner(root: Path, *, how: str = "name one") -> RunnerPaths:
|
|
162
175
|
"""The one Runner installed here, so a command needs no name (QTS-1774)."""
|
|
163
176
|
|
|
@@ -444,6 +457,7 @@ class ServiceDefinition:
|
|
|
444
457
|
install: list[list[str]]
|
|
445
458
|
start: list[list[str]]
|
|
446
459
|
stop: list[list[str]]
|
|
460
|
+
restart: list[list[str]]
|
|
447
461
|
|
|
448
462
|
|
|
449
463
|
def runner_command(name: str, root: Path) -> list[str]:
|
|
@@ -504,6 +518,9 @@ def _launch_agent(
|
|
|
504
518
|
install=[],
|
|
505
519
|
start=[["launchctl", "bootstrap", domain, str(plist)]],
|
|
506
520
|
stop=[["launchctl", "bootout", f"{domain}/{name}"]],
|
|
521
|
+
# One call, not bootout then bootstrap: launchd refuses a bootstrap of a label it
|
|
522
|
+
# still holds, and it holds it until the old process has drained.
|
|
523
|
+
restart=[["launchctl", "kickstart", "-k", f"{domain}/{name}"]],
|
|
507
524
|
)
|
|
508
525
|
|
|
509
526
|
|
|
@@ -546,6 +563,7 @@ def _systemd_user_unit(
|
|
|
546
563
|
],
|
|
547
564
|
start=[[*systemctl, "enable", "--now", unit_name]],
|
|
548
565
|
stop=[[*systemctl, "disable", "--now", unit_name]],
|
|
566
|
+
restart=[[*systemctl, "restart", unit_name]],
|
|
549
567
|
)
|
|
550
568
|
|
|
551
569
|
|
|
@@ -599,6 +617,10 @@ def _logon_task(
|
|
|
599
617
|
["schtasks", "/End", "/TN", task_name],
|
|
600
618
|
["schtasks", "/Change", "/TN", task_name, "/DISABLE"],
|
|
601
619
|
],
|
|
620
|
+
restart=[
|
|
621
|
+
["schtasks", "/End", "/TN", task_name],
|
|
622
|
+
["schtasks", "/Run", "/TN", task_name],
|
|
623
|
+
],
|
|
602
624
|
)
|
|
603
625
|
|
|
604
626
|
|
|
@@ -837,9 +859,36 @@ def stop(paths: RunnerPaths, **driver: Any) -> None:
|
|
|
837
859
|
_drive_service(paths, "stop", **driver)
|
|
838
860
|
|
|
839
861
|
|
|
862
|
+
def restart(
|
|
863
|
+
paths: RunnerPaths,
|
|
864
|
+
*,
|
|
865
|
+
timeout: float = 60.0,
|
|
866
|
+
sleep: Callable[[float], None] = time.sleep,
|
|
867
|
+
clock: Callable[[], float] = time.monotonic,
|
|
868
|
+
**driver: Any,
|
|
869
|
+
) -> tuple[int, str]:
|
|
870
|
+
"""Restart a running Runner and wait for its new process: ``(pid, version)``.
|
|
871
|
+
|
|
872
|
+
``uv tool upgrade`` replaces the console script, not the process, so a login agent keeps
|
|
873
|
+
running the old version until this (QTS-2158). The process writes its version before
|
|
874
|
+
its pidfile, so a new pid means the version beside it is the new process's.
|
|
875
|
+
"""
|
|
876
|
+
|
|
877
|
+
previous = process_id(paths)
|
|
878
|
+
_drive_service(paths, "restart", **driver)
|
|
879
|
+
deadline = clock() + timeout
|
|
880
|
+
while (pid := process_id(paths)) is None or pid == previous:
|
|
881
|
+
if clock() >= deadline:
|
|
882
|
+
raise RuntimeError(
|
|
883
|
+
f"no new process wrote {paths.pidfile} within {timeout:.0f}s; see {paths.log}"
|
|
884
|
+
)
|
|
885
|
+
sleep(0.5)
|
|
886
|
+
return pid, paths.started_version.read_text(encoding="utf-8").strip()
|
|
887
|
+
|
|
888
|
+
|
|
840
889
|
def _drive_service(
|
|
841
890
|
paths: RunnerPaths,
|
|
842
|
-
verb:
|
|
891
|
+
verb: Literal["start", "stop", "restart"],
|
|
843
892
|
*,
|
|
844
893
|
platform: str = sys.platform,
|
|
845
894
|
home: Path | None = None,
|
|
@@ -847,7 +896,7 @@ def _drive_service(
|
|
|
847
896
|
) -> None:
|
|
848
897
|
settings = WorkstationSettings.load(paths)
|
|
849
898
|
definition = service_definition(paths, settings, platform=platform, home=home)
|
|
850
|
-
drive(definition
|
|
899
|
+
drive(getattr(definition, verb), run=run)
|
|
851
900
|
|
|
852
901
|
|
|
853
902
|
def run_process(paths: RunnerPaths, *, login_agent: bool) -> int:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/git/__init__.py
RENAMED
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/git/contracts.py
RENAMED
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/git/evidence.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/git/workspace.py
RENAMED
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/github/__init__.py
RENAMED
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/github/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/integrations/github/gh_client.py
RENAMED
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.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.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/_runtime_support.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/claude_runtime.py
RENAMED
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/claude_sign_in.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/command_policy.py
RENAMED
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/contract_isolation.py
RENAMED
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/fastapi_client.py
RENAMED
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/harness_logins.py
RENAMED
|
File without changes
|
{agentic_runner-3.29.0 → agentic_runner-3.30.0}/src/agentic_runner/workers/harness_outcome.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|