agentic-runner 3.23.1__tar.gz → 3.24.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.
Files changed (78) hide show
  1. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/PKG-INFO +2 -2
  2. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/pyproject.toml +1 -1
  3. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/__init__.py +1 -1
  4. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/claude_runtime.py +63 -22
  5. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/skills.py +4 -2
  6. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/.gitignore +0 -0
  7. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/LICENSE +0 -0
  8. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/README.md +0 -0
  9. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/activities.py +0 -0
  10. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/attempts.py +0 -0
  11. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/auth_mode.py +0 -0
  12. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/build.py +0 -0
  13. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/callback.py +0 -0
  14. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/child_watcher.py +0 -0
  15. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/cli.py +0 -0
  16. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/cli_floor.py +0 -0
  17. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/config.py +0 -0
  18. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/credentials.py +0 -0
  19. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/device_login_activities.py +0 -0
  20. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/egress.py +0 -0
  21. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/harness_self_test.py +0 -0
  22. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/heartbeat_link.py +0 -0
  23. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/hooks.py +0 -0
  24. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/host_store.py +0 -0
  25. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/__init__.py +0 -0
  26. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/git/__init__.py +0 -0
  27. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/git/contracts.py +0 -0
  28. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/git/evidence.py +0 -0
  29. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/git/fake_workspace.py +0 -0
  30. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/git/workspace.py +0 -0
  31. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/github/__init__.py +0 -0
  32. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/github/auth.py +0 -0
  33. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/github/fake_client.py +0 -0
  34. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/github/gh_client.py +0 -0
  35. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/oauth/__init__.py +0 -0
  36. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/integrations/oauth/fake_provider.py +0 -0
  37. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/launch.py +0 -0
  38. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/lifecycle.py +0 -0
  39. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/llm_proxy.py +0 -0
  40. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/mcp.py +0 -0
  41. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/message_store.py +0 -0
  42. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/oauth_connectors.py +0 -0
  43. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/private_state.py +0 -0
  44. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/py.typed +0 -0
  45. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/recipient_key_secret.py +0 -0
  46. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/registration.py +0 -0
  47. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/runner_limit.py +0 -0
  48. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/runtime/__init__.py +0 -0
  49. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/runtime/verifier_command.py +0 -0
  50. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/sealed_box.py +0 -0
  51. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/service.py +0 -0
  52. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/skill.py +0 -0
  53. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/skills/agentic-runner-setup/SKILL.md +0 -0
  54. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/testing/__init__.py +0 -0
  55. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/testing/__main__.py +0 -0
  56. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/testing/control_plane.py +0 -0
  57. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/testing/plugin.py +0 -0
  58. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/testing/test_conformance.py +0 -0
  59. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/testing/workflow.py +0 -0
  60. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/tiny_http.py +0 -0
  61. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/triage_activities.py +0 -0
  62. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/usage_windows.py +0 -0
  63. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/user_sources.py +0 -0
  64. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/__init__.py +0 -0
  65. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/_runtime_support.py +0 -0
  66. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/acp_runtime.py +0 -0
  67. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/agent_runtime.py +0 -0
  68. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/claude_sign_in.py +0 -0
  69. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/codex_runtime.py +0 -0
  70. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/command_policy.py +0 -0
  71. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/contract_device_login.py +0 -0
  72. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/contract_isolation.py +0 -0
  73. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/fastapi_client.py +0 -0
  74. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/harness_outcome.py +0 -0
  75. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/harness_usage.py +0 -0
  76. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/mcp_config.py +0 -0
  77. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workers/settings.py +0 -0
  78. {agentic_runner-3.23.1 → agentic_runner-3.24.0}/src/agentic_runner/workstation.py +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agentic-runner
3
- Version: 3.23.1
3
+ Version: 3.24.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.23.1
8
+ Requires-Dist: agentic-runner-contracts==3.24.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.23.1",
13
+ "agentic-runner-contracts==3.24.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.
@@ -7,6 +7,6 @@ stay on the platform; this package imports none of them, and a CI partition test
7
7
  (``tests/test_package_partition.py``) fails the build if that changes.
8
8
  """
9
9
 
10
- __version__ = "3.23.1"
10
+ __version__ = "3.24.0"
11
11
 
12
12
  __all__ = ["__version__"]
@@ -1,11 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
+ import os
4
5
  import re
5
6
  import uuid
6
7
  from collections.abc import Awaitable, Callable
7
8
  from typing import Final
8
9
 
10
+ from agentic_runner.llm_proxy import PROXY_ENV_NAMES
9
11
  from agentic_runner.workers._runtime_support import (
10
12
  SubprocessResult,
11
13
  apply_extra_env,
@@ -27,6 +29,7 @@ from agentic_runner.workers.agent_runtime import (
27
29
  ResumableAgentRuntime,
28
30
  RuntimeCapabilities,
29
31
  )
32
+ from agentic_runner.workers.claude_sign_in import launcher_argv
30
33
  from agentic_runner.workers.contract_isolation import DirectiveSandbox
31
34
  from agentic_runner.workers.mcp_config import claude_mcp_config
32
35
  from agentic_runner.workers.settings import WorkerSettings
@@ -56,17 +59,17 @@ _SECRET_VALUE_PATTERNS: Final[tuple[re.Pattern[str], ...]] = (
56
59
  class ClaudeRuntime(ResumableAgentRuntime):
57
60
  """Worker-local Claude Code CLI runtime.
58
61
 
59
- Runs against the attempt's LLM proxy endpoint rather than a device-login session, so an
60
- unattended Persona can run without an expiring browser session (ADR-0006), and the
61
- subprocess holds only the attempt's bearer, never a provider key (QTS-1520). Like the
62
- Codex runtime it confines execution to the supplied workspace, refuses fail-closed unless
63
- the autonomous-permission guard is configured or the proxy endpoint is missing, and
64
- returns bounded, redacted evidence safe for control-plane storage.
62
+ An ``api_key`` Directive runs against the attempt's LLM proxy endpoint, so the
63
+ subprocess holds only the attempt's bearer, never a provider key (QTS-1520). A
64
+ ``subscription`` one (local-agents 07) runs on the sign-in in the Contract's harness
65
+ root, behind the sign-in launcher, so the token is read by the Contract's own process
66
+ and never by the Runner's. Like the Codex runtime it confines execution to the supplied
67
+ workspace, refuses fail-closed unless the autonomous-permission guard is configured and
68
+ the mode's credential is in place, and returns bounded, redacted evidence safe for
69
+ control-plane storage.
65
70
  """
66
71
 
67
- # Subscription mode for Claude Code is local-agents 07; until then a Contract with no
68
- # delivered key has nothing this runtime may run on.
69
- auth_modes = frozenset({AuthMode.API_KEY})
72
+ auth_modes = frozenset({AuthMode.API_KEY, AuthMode.SUBSCRIPTION})
70
73
  host_api_key = False
71
74
 
72
75
  def __init__(
@@ -95,7 +98,8 @@ class ClaudeRuntime(ResumableAgentRuntime):
95
98
  raise ValueError("workspace_path must be under WORKSPACE_ROOT")
96
99
 
97
100
  directive_workspace_id = workspace_id(workspace_path, workspace_root)
98
- guard_mode = _guard_mode(self._settings)
101
+ subscription = request.auth_mode == AuthMode.SUBSCRIPTION
102
+ guard_mode = _guard_mode(self._settings, subscription=subscription)
99
103
  if guard_mode is None:
100
104
  return _refused_result(
101
105
  workspace_id=directive_workspace_id,
@@ -103,7 +107,28 @@ class ClaudeRuntime(ResumableAgentRuntime):
103
107
  work_branch=request.work_branch,
104
108
  evidence_limit_bytes=self._settings.CLAUDE_CLI_OUTPUT_LIMIT_BYTES,
105
109
  )
106
- if not dict(request.extra_env).get("ANTHROPIC_BASE_URL"):
110
+ sandbox = request.sandbox
111
+ extra_env = request.extra_env
112
+ if subscription:
113
+ if sandbox is None:
114
+ # Without the Contract's harness root the CLI would read whatever login the
115
+ # Runner's own user holds: someone else's subscription, or none.
116
+ return _refused_result(
117
+ workspace_id=directive_workspace_id,
118
+ base_branch=request.base_branch,
119
+ work_branch=request.work_branch,
120
+ evidence_limit_bytes=self._settings.CLAUDE_CLI_OUTPUT_LIMIT_BYTES,
121
+ guard_mode="refused: subscription mode without a Contract harness root",
122
+ error=(
123
+ "a subscription Claude Code Directive needs its Contract's harness root"
124
+ ),
125
+ )
126
+ # A proxy pair here would send the sign-in's bearer to the proxy, which would
127
+ # then hold it; the activity sets none in this mode, and none gets through.
128
+ extra_env = tuple(
129
+ (name, value) for name, value in extra_env if name not in PROXY_ENV_NAMES
130
+ )
131
+ elif not dict(extra_env).get("ANTHROPIC_BASE_URL"):
107
132
  # The proxy pair is the only credential this runtime hands the harness; without
108
133
  # it the harness would fall back to whatever login or key it finds itself.
109
134
  return _refused_result(
@@ -116,10 +141,12 @@ class ClaudeRuntime(ResumableAgentRuntime):
116
141
  )
117
142
 
118
143
  model = request.model or self._settings.CLAUDE_MODEL
119
- argv = _claude_argv(model)
120
- if request.mcp_servers is not None:
144
+ argv = _claude_argv(model, subscription=subscription)
145
+ if request.mcp_servers is not None or subscription:
121
146
  # Only what the Grant let through: `--strict-mcp-config` ignores every other
122
- # MCP source, so nothing in the harness root can add an ungranted server.
147
+ # MCP source, so nothing in the harness root can add an ungranted server. A
148
+ # subscription turn always pins it: without `--bare` the CLI would otherwise
149
+ # read the Workspace's `.mcp.json` when the Grant names no server.
123
150
  if request.mcp_servers:
124
151
  argv += ["--mcp-config", claude_mcp_config(request.mcp_servers)]
125
152
  argv.append("--strict-mcp-config")
@@ -150,14 +177,18 @@ class ClaudeRuntime(ResumableAgentRuntime):
150
177
  evidence_limit_bytes=self._settings.CLAUDE_CLI_OUTPUT_LIMIT_BYTES,
151
178
  guard_mode=f"refused: command policy ({floor_refusal})",
152
179
  )
153
- # Per-Contract CLAUDE_CONFIG_DIR, never a fleet-wide one (ADR-0015 §4).
154
- sandbox = request.sandbox
155
- env: dict[str, str] = {}
180
+ if subscription:
181
+ assert sandbox is not None # refused above
182
+ argv = launcher_argv(sandbox.harness_config_dir, argv)
183
+ # Per-Contract CLAUDE_CONFIG_DIR, never a fleet-wide one (ADR-0015 §4). PATH is the
184
+ # Runner's own, as for the other runtimes: without it `claude` (in /usr/local/bin in
185
+ # the image) and its node shebang resolve against `os.defpath` only.
186
+ env: dict[str, str] = {"PATH": os.environ.get("PATH") or os.defpath}
156
187
  if sandbox is not None:
157
188
  env["CLAUDE_CONFIG_DIR"] = str(sandbox.harness_config_dir)
158
189
  env["HOME"] = str(sandbox.home_dir)
159
190
  env["TMPDIR"] = str(sandbox.tmp_dir)
160
- apply_extra_env(env, request.extra_env)
191
+ apply_extra_env(env, extra_env)
161
192
  notes: list[str] = []
162
193
  if started_session is not None and request.on_session_started is not None:
163
194
  request.on_session_started(started_session)
@@ -218,17 +249,27 @@ class ClaudeRuntime(ResumableAgentRuntime):
218
249
  return any(projects.glob(f"*/{session_id}.jsonl"))
219
250
 
220
251
 
221
- def _guard_mode(settings: WorkerSettings) -> str | None:
252
+ def _guard_mode(settings: WorkerSettings, *, subscription: bool = False) -> str | None:
222
253
  if settings.CLAUDE_DANGEROUSLY_SKIP_PERMISSIONS:
223
- return "auth=api-key; permission=skip-in-sandbox; output=json"
254
+ auth = "subscription" if subscription else "api-key"
255
+ return f"auth={auth}; permission=skip-in-sandbox; output=json"
224
256
  return None
225
257
 
226
258
 
227
- def _claude_argv(model: str) -> list[str]:
259
+ def _claude_argv(model: str, *, subscription: bool = False) -> list[str]:
260
+ """``--bare`` reads no OAuth login and no keychain, so a subscription turn cannot use
261
+ it. In its place, as the ACP runtime's ``settingSources: []`` (LA-12d item 2), no setting
262
+ source loads: the Workspace's and harness root's settings, hooks and ``CLAUDE.md`` stay
263
+ out, so neither can set ``env``, ``apiKeyHelper`` or a base URL that would swap the
264
+ sign-in for a key or send its bearer elsewhere. The login itself is not a setting and
265
+ still signs the requests.
266
+ """
267
+
268
+ settings_flags = ["--setting-sources", ""] if subscription else ["--bare"]
228
269
  return [
229
270
  "claude",
230
271
  "--print",
231
- "--bare",
272
+ *settings_flags,
232
273
  "--output-format",
233
274
  "json",
234
275
  "--model",
@@ -9,8 +9,10 @@ Runner's own argv, not assumed (local-agents 02 asked the same question over ACP
9
9
  - **Claude Code** (2.1.292): the Runner runs ``claude --print --bare``, and ``--bare`` drops
10
10
  the Skill tool. ``$CLAUDE_CONFIG_DIR/skills/<slug>/SKILL.md`` is then neither advertised
11
11
  nor resolved by ``/<slug>``, and ``--tools …,Skill`` does not bring the tool back. Claude
12
- Code therefore gets the bodies as a prompt preamble. Dropping ``--bare`` would also
13
- re-enable the Workspace's hooks and ``CLAUDE.md``, which is not this module's call.
12
+ Code therefore gets the bodies as a prompt preamble. A subscription Directive runs
13
+ without ``--bare`` but loads no setting source (``claude_runtime._claude_argv``), so the
14
+ harness root's ``skills`` directory is not read there either, and it gets the same
15
+ preamble.
14
16
 
15
17
  The harness root is per Contract, not per Directive, so two concurrent Directives of one
16
18
  Contract share its ``skills`` directory.
File without changes