cloudagent-daemon 0.2.1__tar.gz → 0.2.2__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.
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/PKG-INFO +21 -32
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/README.md +20 -31
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/pyproject.toml +1 -1
- cloudagent_daemon-0.2.2/src/cloudagent_daemon/__init__.py +1 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/claude_runner.py +36 -1
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/cli.py +39 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/config.py +39 -1
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/main_loop.py +5 -1
- cloudagent_daemon-0.2.1/src/cloudagent_daemon/__init__.py +0 -1
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/.gitignore +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/LICENSE +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/__main__.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/doctor.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/frame_dispatch.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/http_outbound.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/jsonl_logging.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/login.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/mcp_bridge.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/metrics.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/metrics_server.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/outbound_queue.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/paths.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/protocol.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/runtime_detect.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/service.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/spawn_outbox.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/spawn_queue.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/sse_client.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/transport.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/unix_socket.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/workspace.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/src/cloudagent_daemon/ws_client.py +0 -0
- {cloudagent_daemon-0.2.1 → cloudagent_daemon-0.2.2}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudagent-daemon
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Local daemon for cloudagent — bridges Claude Code subprocesses to the cloudagent backend over WebSocket.
|
|
5
5
|
Project-URL: Homepage, https://cloudagent.chat
|
|
6
6
|
Project-URL: Repository, https://codeup.aliyun.com/69bd0a4d29ad98af4065ce71/cloudagent
|
|
@@ -43,56 +43,45 @@ backend, and exits when its work is done.
|
|
|
43
43
|
|
|
44
44
|
## Quick start (no clone)
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Each command below is a SINGLE LINE — copy the whole line as-is.
|
|
49
|
-
Multi-line snippets with `\` continuations are fragile across copy-paste
|
|
50
|
-
(some terminals / web `<pre>` blocks drop the trailing `\` and break the
|
|
51
|
-
command into separate statements).
|
|
52
|
-
|
|
53
|
-
> **Tag-pinned releases.** The `@daemon-vX.Y.Z` ref below points at a frozen
|
|
54
|
-
> daemon release (annotated git tag). To upgrade later, re-run the same
|
|
55
|
-
> command with the latest tag — see `git ls-remote --tags origin "daemon-v*"`
|
|
56
|
-
> on the cloudagent repo, or [the releases list][releases]. Don't replace
|
|
57
|
-
> the tag with a branch name (e.g. `cy` / `m5`); branches move and can drag
|
|
58
|
-
> in unrelated work-in-progress.
|
|
59
|
-
|
|
60
|
-
[releases]: https://codeup.aliyun.com/69bd0a4d29ad98af4065ce71/cloudagent/-/tags?search=daemon-v
|
|
46
|
+
Published to PyPI as [`cloudagent-daemon`](https://pypi.org/project/cloudagent-daemon/).
|
|
47
|
+
Requires Python 3.12+ and Claude Code CLI on PATH.
|
|
61
48
|
|
|
62
49
|
```bash
|
|
63
|
-
# One-shot run (no install)
|
|
64
|
-
uvx
|
|
50
|
+
# One-shot run (no persistent install)
|
|
51
|
+
uvx cloudagent-daemon start --server-url https://api.cloudagent.chat --api-key sk_machine_***
|
|
65
52
|
```
|
|
66
53
|
|
|
67
54
|
```bash
|
|
68
|
-
#
|
|
69
|
-
uv tool install
|
|
55
|
+
# Persistent install — install + start chained with && (single line)
|
|
56
|
+
uv tool install cloudagent-daemon && cloudagent-daemon start --server-url https://api.cloudagent.chat --api-key sk_machine_***
|
|
70
57
|
```
|
|
71
58
|
|
|
72
|
-
To upgrade an existing install to the newest tag (forces re-resolve of the
|
|
73
|
-
git ref so a moved tag wouldn't silently stick on the old commit anyway —
|
|
74
|
-
but tags are immutable here, so the bump in the URL is the real signal):
|
|
75
|
-
|
|
76
59
|
```bash
|
|
77
|
-
|
|
60
|
+
# Or via pipx
|
|
61
|
+
pipx install cloudagent-daemon
|
|
78
62
|
```
|
|
79
63
|
|
|
80
|
-
|
|
64
|
+
To upgrade later:
|
|
81
65
|
|
|
82
66
|
```bash
|
|
83
|
-
|
|
67
|
+
uv tool upgrade cloudagent-daemon
|
|
84
68
|
# or
|
|
85
|
-
pipx
|
|
69
|
+
pipx upgrade cloudagent-daemon
|
|
86
70
|
```
|
|
87
71
|
|
|
88
|
-
|
|
72
|
+
### Developer install (from source)
|
|
73
|
+
|
|
74
|
+
Contributors working off the cloudagent repo can install the unreleased dev
|
|
75
|
+
tip directly from the `cy` branch — requires SSH access to the codeup mirror:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv tool install --from "git+ssh://git@codeup.aliyun.com:/69bd0a4d29ad98af4065ce71/cloudagent.git@cy#subdirectory=daemon_cli" cloudagent-daemon
|
|
79
|
+
```
|
|
89
80
|
|
|
90
|
-
|
|
81
|
+
Or editable install for local hacking:
|
|
91
82
|
|
|
92
83
|
```bash
|
|
93
84
|
pip install -e ./daemon_cli
|
|
94
|
-
# or after release:
|
|
95
|
-
# pipx install cloudagent-daemon
|
|
96
85
|
```
|
|
97
86
|
|
|
98
87
|
## Quick start
|
|
@@ -11,56 +11,45 @@ backend, and exits when its work is done.
|
|
|
11
11
|
|
|
12
12
|
## Quick start (no clone)
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Each command below is a SINGLE LINE — copy the whole line as-is.
|
|
17
|
-
Multi-line snippets with `\` continuations are fragile across copy-paste
|
|
18
|
-
(some terminals / web `<pre>` blocks drop the trailing `\` and break the
|
|
19
|
-
command into separate statements).
|
|
20
|
-
|
|
21
|
-
> **Tag-pinned releases.** The `@daemon-vX.Y.Z` ref below points at a frozen
|
|
22
|
-
> daemon release (annotated git tag). To upgrade later, re-run the same
|
|
23
|
-
> command with the latest tag — see `git ls-remote --tags origin "daemon-v*"`
|
|
24
|
-
> on the cloudagent repo, or [the releases list][releases]. Don't replace
|
|
25
|
-
> the tag with a branch name (e.g. `cy` / `m5`); branches move and can drag
|
|
26
|
-
> in unrelated work-in-progress.
|
|
27
|
-
|
|
28
|
-
[releases]: https://codeup.aliyun.com/69bd0a4d29ad98af4065ce71/cloudagent/-/tags?search=daemon-v
|
|
14
|
+
Published to PyPI as [`cloudagent-daemon`](https://pypi.org/project/cloudagent-daemon/).
|
|
15
|
+
Requires Python 3.12+ and Claude Code CLI on PATH.
|
|
29
16
|
|
|
30
17
|
```bash
|
|
31
|
-
# One-shot run (no install)
|
|
32
|
-
uvx
|
|
18
|
+
# One-shot run (no persistent install)
|
|
19
|
+
uvx cloudagent-daemon start --server-url https://api.cloudagent.chat --api-key sk_machine_***
|
|
33
20
|
```
|
|
34
21
|
|
|
35
22
|
```bash
|
|
36
|
-
#
|
|
37
|
-
uv tool install
|
|
23
|
+
# Persistent install — install + start chained with && (single line)
|
|
24
|
+
uv tool install cloudagent-daemon && cloudagent-daemon start --server-url https://api.cloudagent.chat --api-key sk_machine_***
|
|
38
25
|
```
|
|
39
26
|
|
|
40
|
-
To upgrade an existing install to the newest tag (forces re-resolve of the
|
|
41
|
-
git ref so a moved tag wouldn't silently stick on the old commit anyway —
|
|
42
|
-
but tags are immutable here, so the bump in the URL is the real signal):
|
|
43
|
-
|
|
44
27
|
```bash
|
|
45
|
-
|
|
28
|
+
# Or via pipx
|
|
29
|
+
pipx install cloudagent-daemon
|
|
46
30
|
```
|
|
47
31
|
|
|
48
|
-
|
|
32
|
+
To upgrade later:
|
|
49
33
|
|
|
50
34
|
```bash
|
|
51
|
-
|
|
35
|
+
uv tool upgrade cloudagent-daemon
|
|
52
36
|
# or
|
|
53
|
-
pipx
|
|
37
|
+
pipx upgrade cloudagent-daemon
|
|
54
38
|
```
|
|
55
39
|
|
|
56
|
-
|
|
40
|
+
### Developer install (from source)
|
|
41
|
+
|
|
42
|
+
Contributors working off the cloudagent repo can install the unreleased dev
|
|
43
|
+
tip directly from the `cy` branch — requires SSH access to the codeup mirror:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
uv tool install --from "git+ssh://git@codeup.aliyun.com:/69bd0a4d29ad98af4065ce71/cloudagent.git@cy#subdirectory=daemon_cli" cloudagent-daemon
|
|
47
|
+
```
|
|
57
48
|
|
|
58
|
-
|
|
49
|
+
Or editable install for local hacking:
|
|
59
50
|
|
|
60
51
|
```bash
|
|
61
52
|
pip install -e ./daemon_cli
|
|
62
|
-
# or after release:
|
|
63
|
-
# pipx install cloudagent-daemon
|
|
64
53
|
```
|
|
65
54
|
|
|
66
55
|
## Quick start
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cloudagent-daemon"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "Local daemon for cloudagent — bridges Claude Code subprocesses to the cloudagent backend over WebSocket."
|
|
9
9
|
authors = [{name = "chaoyin", email = "tudoucyx@gmail.com"}]
|
|
10
10
|
readme = "README.md"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.2"
|
|
@@ -198,10 +198,16 @@ class ClaudeRunner:
|
|
|
198
198
|
single_wake_timeout: float | None = None,
|
|
199
199
|
partial_publisher: PartialPublisher | None = None,
|
|
200
200
|
agent_to_session: "dict[str, str | None] | None" = None,
|
|
201
|
+
claude_permission_mode: str = "default",
|
|
201
202
|
) -> None:
|
|
202
203
|
self.outbound = outbound
|
|
203
204
|
self.workspace = workspace
|
|
204
205
|
self.claude_binary = claude_binary
|
|
206
|
+
# Claude CLI ``--permission-mode``. "default" → flag omitted
|
|
207
|
+
# (legacy behaviour: only the cloudagent MCP toolset is
|
|
208
|
+
# whitelisted via --allowedTools, Bash/Write/Edit gate). See
|
|
209
|
+
# DaemonConfig.claude_permission_mode for the per-mode contract.
|
|
210
|
+
self.claude_permission_mode = claude_permission_mode
|
|
205
211
|
# Allow tests to override the 90-min timeout without monkey-patching
|
|
206
212
|
# a class attribute. Defaults to spec value.
|
|
207
213
|
self._single_wake_timeout: float = (
|
|
@@ -541,7 +547,16 @@ The daemon discards stdout — only the mcp tool call reaches the user.
|
|
|
541
547
|
write are intentionally LEFT to the caller so they always
|
|
542
548
|
reflect the *last* attempt.
|
|
543
549
|
"""
|
|
544
|
-
|
|
550
|
+
raw_append = payload.get("append_system_prompt")
|
|
551
|
+
append_system_prompt = (
|
|
552
|
+
raw_append if isinstance(raw_append, str) and raw_append.strip() else None
|
|
553
|
+
)
|
|
554
|
+
cmd = self._build_cmd(
|
|
555
|
+
ws,
|
|
556
|
+
agent_id,
|
|
557
|
+
with_resume=with_resume,
|
|
558
|
+
append_system_prompt=append_system_prompt,
|
|
559
|
+
)
|
|
545
560
|
|
|
546
561
|
# Task #118 (2026-05-12) — spawn cwd is now the agent-specific
|
|
547
562
|
# cwd (per-agent override → host default → platform fallback).
|
|
@@ -773,12 +788,20 @@ Available cloudagent tools:
|
|
|
773
788
|
agent_id: str,
|
|
774
789
|
*,
|
|
775
790
|
with_resume: bool = True,
|
|
791
|
+
append_system_prompt: str | None = None,
|
|
776
792
|
) -> list[str]:
|
|
777
793
|
"""Build the ``claude`` argv list for one wake.
|
|
778
794
|
|
|
779
795
|
1k followup — ``with_resume=False`` forces the runner to omit
|
|
780
796
|
``--resume`` even if a stored ``last_session_id`` exists. The
|
|
781
797
|
retry path uses this after a stale-session crash.
|
|
798
|
+
|
|
799
|
+
``append_system_prompt`` is per-agent free-text (chairman-editable
|
|
800
|
+
via the agent dialog, stored in ``agents.metadata_['cloudagent:
|
|
801
|
+
append_system_prompt']`` and propagated through the deliver
|
|
802
|
+
payload). When non-empty it is appended verbatim to the operational
|
|
803
|
+
contract footer with a blank-line separator so it shows up at the
|
|
804
|
+
very tail of ``--append-system-prompt``.
|
|
782
805
|
"""
|
|
783
806
|
cmd: list[str] = [self.claude_binary]
|
|
784
807
|
last_session = ws.last_session_id() if with_resume else None
|
|
@@ -786,6 +809,8 @@ Available cloudagent tools:
|
|
|
786
809
|
cmd += ["--resume", last_session]
|
|
787
810
|
# 1i Bug F — inject operational contract via --append-system-prompt.
|
|
788
811
|
system_prompt = self.SYSTEM_PROMPT_APPEND.format(agent_id=agent_id)
|
|
812
|
+
if append_system_prompt and append_system_prompt.strip():
|
|
813
|
+
system_prompt = f"{system_prompt}\n\n{append_system_prompt.strip()}"
|
|
789
814
|
cmd += [
|
|
790
815
|
"--mcp-config",
|
|
791
816
|
str(ws.mcp_config_path()),
|
|
@@ -810,6 +835,16 @@ Available cloudagent tools:
|
|
|
810
835
|
"--append-system-prompt",
|
|
811
836
|
system_prompt,
|
|
812
837
|
]
|
|
838
|
+
# 2026-05-19 — opt-in permission relaxation for staff that must
|
|
839
|
+
# touch the filesystem / run build commands. "default" keeps the
|
|
840
|
+
# legacy headless behaviour (flag omitted; only the cloudagent
|
|
841
|
+
# MCP toolset runs unattended). "acceptEdits" / "bypassPermissions"
|
|
842
|
+
# come from DaemonConfig.claude_permission_mode. The spawn cwd is
|
|
843
|
+
# already pinned to the agent's workspace_root (see
|
|
844
|
+
# AgentWorkspaceLike.cwd / Task #118), so acceptEdits' auto-accept
|
|
845
|
+
# of file edits is naturally scoped to that working directory.
|
|
846
|
+
if self.claude_permission_mode != "default":
|
|
847
|
+
cmd += ["--permission-mode", self.claude_permission_mode]
|
|
813
848
|
return cmd
|
|
814
849
|
|
|
815
850
|
async def _consume_stdout(
|
|
@@ -74,6 +74,32 @@ def _resolve_cli_profile(profile: str | None) -> str:
|
|
|
74
74
|
raise typer.Exit(2)
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
#: Env var that overrides ``DaemonConfig.claude_permission_mode``. The
|
|
78
|
+
#: only permission knob available to one-shot mode (no config.json).
|
|
79
|
+
PERMISSION_MODE_ENV = "CLOUDAGENT_DAEMON_PERMISSION_MODE"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _apply_permission_mode_override(cfg): # type: ignore[no-untyped-def]
|
|
83
|
+
"""Return ``cfg`` with ``claude_permission_mode`` replaced by the
|
|
84
|
+
``CLOUDAGENT_DAEMON_PERMISSION_MODE`` env var when it is set.
|
|
85
|
+
|
|
86
|
+
The replacement goes through ``DaemonConfig`` construction so the
|
|
87
|
+
field_validator rejects unknown values (raised as ``ValueError``).
|
|
88
|
+
When the env var is unset / empty, ``cfg`` is returned unchanged.
|
|
89
|
+
"""
|
|
90
|
+
from .config import DaemonConfig
|
|
91
|
+
|
|
92
|
+
mode = os.environ.get(PERMISSION_MODE_ENV)
|
|
93
|
+
if not mode:
|
|
94
|
+
return cfg
|
|
95
|
+
return DaemonConfig(
|
|
96
|
+
server_url=cfg.server_url,
|
|
97
|
+
machine_api_key=cfg.machine_api_key,
|
|
98
|
+
host_id=cfg.host_id,
|
|
99
|
+
claude_permission_mode=mode,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
77
103
|
@app.command()
|
|
78
104
|
def login(
|
|
79
105
|
server: str = typer.Option(..., "--server", help="Backend server URL."),
|
|
@@ -265,6 +291,19 @@ def start(
|
|
|
265
291
|
)
|
|
266
292
|
raise typer.Exit(1)
|
|
267
293
|
|
|
294
|
+
# 2026-05-19 — CLOUDAGENT_DAEMON_PERMISSION_MODE env var overrides
|
|
295
|
+
# config.json's ``claude_permission_mode``. This is the ONLY knob
|
|
296
|
+
# available to one-shot mode (``start --server-url --api-key``),
|
|
297
|
+
# which never reads or writes a config.json.
|
|
298
|
+
try:
|
|
299
|
+
cfg = _apply_permission_mode_override(cfg)
|
|
300
|
+
except ValueError as exc:
|
|
301
|
+
typer.echo(
|
|
302
|
+
f"Error: invalid CLOUDAGENT_DAEMON_PERMISSION_MODE — {exc}",
|
|
303
|
+
err=True,
|
|
304
|
+
)
|
|
305
|
+
raise typer.Exit(2)
|
|
306
|
+
|
|
268
307
|
state = (
|
|
269
308
|
DaemonState.load_default(profile_name)
|
|
270
309
|
if DaemonState.default_path(profile_name).exists()
|
|
@@ -15,7 +15,7 @@ import tempfile
|
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
from typing import Self
|
|
17
17
|
|
|
18
|
-
from pydantic import BaseModel
|
|
18
|
+
from pydantic import BaseModel, field_validator
|
|
19
19
|
|
|
20
20
|
from .paths import (
|
|
21
21
|
DEFAULT_PROFILE,
|
|
@@ -51,6 +51,44 @@ class DaemonConfig(BaseModel):
|
|
|
51
51
|
machine_api_key: str
|
|
52
52
|
host_id: str
|
|
53
53
|
|
|
54
|
+
# Claude CLI permission mode for daemon-spawned staff agents.
|
|
55
|
+
# The daemon spawns each staff's ``claude`` subprocess with
|
|
56
|
+
# ``cwd`` already pinned to that agent's workspace_root (see
|
|
57
|
+
# AgentWorkspaceLike.cwd / Task #118), so the mode's effect is
|
|
58
|
+
# naturally scoped to the agent's project directory.
|
|
59
|
+
#
|
|
60
|
+
# "default" — (safe default) only the cloudagent MCP
|
|
61
|
+
# toolset runs unattended; Bash/Write/Edit
|
|
62
|
+
# prompt for permission, which in headless
|
|
63
|
+
# ``--print`` mode means they silently fail.
|
|
64
|
+
# Staff cannot touch the filesystem.
|
|
65
|
+
# "acceptEdits" — file edits (Write/Edit/MultiEdit/Notebook-
|
|
66
|
+
# Edit) are auto-accepted **within the
|
|
67
|
+
# workspace (cwd)** — edits outside the
|
|
68
|
+
# working directory still gate. Bash still
|
|
69
|
+
# prompts (so git commit / build stay
|
|
70
|
+
# blocked). This is "只在当前工作目录
|
|
71
|
+
# bypass 文件操作".
|
|
72
|
+
# "bypassPermissions" — every tool runs unattended. Required for
|
|
73
|
+
# staff that must run Bash (git commit,
|
|
74
|
+
# pipeline, build). Bash commands have no
|
|
75
|
+
# directory hard-boundary — a command body
|
|
76
|
+
# can cd out — so only enable this on a
|
|
77
|
+
# machine you are comfortable letting the
|
|
78
|
+
# staff agent operate.
|
|
79
|
+
claude_permission_mode: str = "default"
|
|
80
|
+
|
|
81
|
+
@field_validator("claude_permission_mode")
|
|
82
|
+
@classmethod
|
|
83
|
+
def _validate_permission_mode(cls, v: str) -> str:
|
|
84
|
+
allowed = {"default", "acceptEdits", "bypassPermissions"}
|
|
85
|
+
if v not in allowed:
|
|
86
|
+
raise ValueError(
|
|
87
|
+
f"claude_permission_mode must be one of {sorted(allowed)}, "
|
|
88
|
+
f"got {v!r}"
|
|
89
|
+
)
|
|
90
|
+
return v
|
|
91
|
+
|
|
54
92
|
# ------------------------------------------------------------------
|
|
55
93
|
# Path helpers
|
|
56
94
|
# ------------------------------------------------------------------
|
|
@@ -454,6 +454,7 @@ async def _run_sse_post(
|
|
|
454
454
|
claude_binary=claude_binary,
|
|
455
455
|
partial_publisher=_publish_partial,
|
|
456
456
|
agent_to_session=_agent_to_session,
|
|
457
|
+
claude_permission_mode=cfg.claude_permission_mode,
|
|
457
458
|
)
|
|
458
459
|
|
|
459
460
|
async def _queue_full(agent_id: str, message_id: str) -> None:
|
|
@@ -737,7 +738,10 @@ async def _run_legacy_ws(
|
|
|
737
738
|
outbound = OutboundQueue(transport=None, pending_tool_calls=pending_tool_calls)
|
|
738
739
|
|
|
739
740
|
runner = ClaudeRunner(
|
|
740
|
-
outbound=outbound,
|
|
741
|
+
outbound=outbound,
|
|
742
|
+
workspace=workspace,
|
|
743
|
+
claude_binary=claude_binary,
|
|
744
|
+
claude_permission_mode=cfg.claude_permission_mode,
|
|
741
745
|
)
|
|
742
746
|
|
|
743
747
|
async def _queue_full(agent_id: str, message_id: str) -> None:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.1"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|