cloudagent-daemon 0.2.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.
Files changed (32) hide show
  1. cloudagent_daemon-0.2.1/.gitignore +89 -0
  2. cloudagent_daemon-0.2.1/LICENSE +21 -0
  3. cloudagent_daemon-0.2.1/PKG-INFO +322 -0
  4. cloudagent_daemon-0.2.1/README.md +290 -0
  5. cloudagent_daemon-0.2.1/pyproject.toml +67 -0
  6. cloudagent_daemon-0.2.1/src/cloudagent_daemon/__init__.py +1 -0
  7. cloudagent_daemon-0.2.1/src/cloudagent_daemon/__main__.py +4 -0
  8. cloudagent_daemon-0.2.1/src/cloudagent_daemon/claude_runner.py +1068 -0
  9. cloudagent_daemon-0.2.1/src/cloudagent_daemon/cli.py +833 -0
  10. cloudagent_daemon-0.2.1/src/cloudagent_daemon/config.py +197 -0
  11. cloudagent_daemon-0.2.1/src/cloudagent_daemon/doctor.py +534 -0
  12. cloudagent_daemon-0.2.1/src/cloudagent_daemon/frame_dispatch.py +216 -0
  13. cloudagent_daemon-0.2.1/src/cloudagent_daemon/http_outbound.py +80 -0
  14. cloudagent_daemon-0.2.1/src/cloudagent_daemon/jsonl_logging.py +98 -0
  15. cloudagent_daemon-0.2.1/src/cloudagent_daemon/login.py +34 -0
  16. cloudagent_daemon-0.2.1/src/cloudagent_daemon/main_loop.py +891 -0
  17. cloudagent_daemon-0.2.1/src/cloudagent_daemon/mcp_bridge.py +441 -0
  18. cloudagent_daemon-0.2.1/src/cloudagent_daemon/metrics.py +315 -0
  19. cloudagent_daemon-0.2.1/src/cloudagent_daemon/metrics_server.py +149 -0
  20. cloudagent_daemon-0.2.1/src/cloudagent_daemon/outbound_queue.py +289 -0
  21. cloudagent_daemon-0.2.1/src/cloudagent_daemon/paths.py +204 -0
  22. cloudagent_daemon-0.2.1/src/cloudagent_daemon/protocol.py +141 -0
  23. cloudagent_daemon-0.2.1/src/cloudagent_daemon/runtime_detect.py +135 -0
  24. cloudagent_daemon-0.2.1/src/cloudagent_daemon/service.py +355 -0
  25. cloudagent_daemon-0.2.1/src/cloudagent_daemon/spawn_outbox.py +443 -0
  26. cloudagent_daemon-0.2.1/src/cloudagent_daemon/spawn_queue.py +200 -0
  27. cloudagent_daemon-0.2.1/src/cloudagent_daemon/sse_client.py +439 -0
  28. cloudagent_daemon-0.2.1/src/cloudagent_daemon/transport.py +105 -0
  29. cloudagent_daemon-0.2.1/src/cloudagent_daemon/unix_socket.py +278 -0
  30. cloudagent_daemon-0.2.1/src/cloudagent_daemon/workspace.py +441 -0
  31. cloudagent_daemon-0.2.1/src/cloudagent_daemon/ws_client.py +431 -0
  32. cloudagent_daemon-0.2.1/uv.lock +849 -0
@@ -0,0 +1,89 @@
1
+ .env
2
+ .env.*
3
+ # Allow env templates + non-secret env files to be committed (override .env.* rule above)
4
+ !.env.example
5
+ !**/.env.example
6
+ !**/.env.development
7
+ !**/.env.staging
8
+ !**/.env.production
9
+
10
+ # Local work-in-progress scratch dir (never committed)
11
+ abu/
12
+
13
+ # GSD workflow tool config (local only)
14
+ .planning/
15
+
16
+ __pycache__/
17
+ *.pyc
18
+ *.pyo
19
+ .pytest_cache/
20
+ .mypy_cache/
21
+ *.egg-info/
22
+ dist/
23
+ build/
24
+ .venv/
25
+ **/.venv/
26
+ **/.venv.*/
27
+ experiments/**/.venv*
28
+ experiments/**/venv*
29
+ experiments/**/__pycache__/
30
+ experiments/**/*.db
31
+ experiments/**/*.sqlite3
32
+ experiments/**/*.log
33
+ experiments/**/screenshots/
34
+ experiments/**/*-result.json
35
+ experiments/**/*-logs/
36
+ node_modules/
37
+ .next/
38
+ .turbo/
39
+ *.tsbuildinfo
40
+
41
+ # Local agent workspace configs (not shared across team)
42
+ .claude/
43
+ CLAUDE.md
44
+ # Exception: 子项目的 CLAUDE.md 是跨人共享的项目定位/原则文档(含 BFF 共用纪律等),入库
45
+ !one-company-fe/CLAUDE.md
46
+ !one-company-desktop/CLAUDE.md
47
+
48
+ # Git worktrees (local-only, isolated feature branches)
49
+ .worktrees/
50
+
51
+ # Local agent scratch output (UI checker screenshots, design data dumps, etc.)
52
+ .r2c/
53
+ one-company-fe/deploy
54
+ # tests/regression 是本地回归测试工作目录(test-cases / fixtures / runs / scripts)
55
+ one-company-fe/tests/regression/
56
+ # Local DB dumps / migration backups — never commit (may contain secrets)
57
+ backups/
58
+
59
+ # Onboarding PDFs — large binaries, distribute via OSS / 钉钉 instead
60
+ docs/m5/*.pdf
61
+
62
+ # screens 目录是浏览器手测产物
63
+ screens/
64
+ package-lock.json
65
+
66
+ # Next.js --experimental-https 自动生成的 mkcert 自签证书(local dev only)
67
+ **/certificates/
68
+
69
+ # 日报自动化相关 + 本地工作区个人配置(不提交到仓库)
70
+ /scripts/daily_report_simple.sh
71
+ /scripts/generate_daily_report.sh
72
+ /scripts/generate_smart_report.py
73
+ /scripts/README_DAILY_REPORT.md
74
+ /tmp/daily_report.log
75
+
76
+ # 个人 / 本地工作区文件 (Claude personality / cron 经验 / 个人 memory / 工作区 Python 配置)
77
+ /SOUL.md
78
+ /AGENTS.md
79
+ /USER.md
80
+ /memory/
81
+ /.cron-experience/
82
+ /.real/
83
+ /pyproject.toml
84
+ .qoder/
85
+
86
+ # playwright 测试相关
87
+ .playwright-mcp/
88
+ tests/
89
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 chaoyin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,322 @@
1
+ Metadata-Version: 2.4
2
+ Name: cloudagent-daemon
3
+ Version: 0.2.1
4
+ Summary: Local daemon for cloudagent — bridges Claude Code subprocesses to the cloudagent backend over WebSocket.
5
+ Project-URL: Homepage, https://cloudagent.chat
6
+ Project-URL: Repository, https://codeup.aliyun.com/69bd0a4d29ad98af4065ce71/cloudagent
7
+ Project-URL: Documentation, https://codeup.aliyun.com/69bd0a4d29ad98af4065ce71/cloudagent/docs/superpowers/specs
8
+ Author-email: chaoyin <tudoucyx@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai-coding-agent,claude-code,cloudagent,daemon
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Operating System :: MacOS
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development
18
+ Classifier: Topic :: System :: Distributed Computing
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: h2>=4
21
+ Requires-Dist: httpx-sse>=0.4
22
+ Requires-Dist: httpx>=0.27
23
+ Requires-Dist: mcp>=0.9
24
+ Requires-Dist: pydantic>=2.7
25
+ Requires-Dist: typer>=0.12
26
+ Requires-Dist: websockets>=12
27
+ Provides-Extra: dev
28
+ Requires-Dist: anyio>=4.0; extra == 'dev'
29
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
30
+ Requires-Dist: pytest>=8.0; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # cloudagent-daemon
34
+
35
+ Local daemon for cloudagent — runs on user's machine, bridges Claude Code
36
+ subprocesses to the cloudagent backend so that agents can work locally with
37
+ your machine's filesystem and tools.
38
+
39
+ **Architecture:** spawn-on-message model — daemon receives a `deliver` frame over
40
+ WebSocket, spawns `claude --resume <session_id>`, claude uses an MCP server
41
+ (also embedded in this daemon) to `send_message` / `list_messages` back to the
42
+ backend, and exits when its work is done.
43
+
44
+ ## Quick start (no clone)
45
+
46
+ The fastest way to run cloudagent-daemon, slock-style:
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
61
+
62
+ ```bash
63
+ # One-shot run (no install) — single line
64
+ uvx --from "git+ssh://git@codeup.aliyun.com:/69bd0a4d29ad98af4065ce71/cloudagent.git@daemon-v0.2.1#subdirectory=daemon_cli" cloudagent-daemon start --server-url https://api-fr.cloudagent.chat --api-key sk_machine_***
65
+ ```
66
+
67
+ ```bash
68
+ # Or install persistently — single line, install + start chained with &&
69
+ uv tool install --from "git+ssh://git@codeup.aliyun.com:/69bd0a4d29ad98af4065ce71/cloudagent.git@daemon-v0.2.1#subdirectory=daemon_cli" cloudagent-daemon && cloudagent-daemon start --server-url https://api-fr.cloudagent.chat --api-key sk_machine_***
70
+ ```
71
+
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
+ ```bash
77
+ uv tool install --reinstall --force --from "git+ssh://git@codeup.aliyun.com:/69bd0a4d29ad98af4065ce71/cloudagent.git@daemon-v0.2.1#subdirectory=daemon_cli" cloudagent-daemon
78
+ ```
79
+
80
+ Once published to PyPI, this becomes:
81
+
82
+ ```bash
83
+ uvx cloudagent-daemon start --server-url https://api-fr.cloudagent.chat --api-key sk_machine_***
84
+ # or
85
+ pipx install cloudagent-daemon
86
+ ```
87
+
88
+ ## Install
89
+
90
+ Requires Python 3.12+ and Claude Code CLI installed.
91
+
92
+ ```bash
93
+ pip install -e ./daemon_cli
94
+ # or after release:
95
+ # pipx install cloudagent-daemon
96
+ ```
97
+
98
+ ## Quick start
99
+
100
+ 1. Create a host machine in the cloudagent UI (or via REST):
101
+ ```bash
102
+ curl -X POST https://api.cloudagent.chat/v1/host-machines \
103
+ -H "Authorization: Bearer <your_user_jwt>" \
104
+ -H "Content-Type: application/json" \
105
+ -d '{"name":"my-mac","hostname":"mbp.local","os":"darwin","daemon_version":"0.1.0"}'
106
+ ```
107
+ Capture the `raw_key` from the response — it starts with `sk_machine_` and
108
+ is shown only once.
109
+
110
+ 2. Login:
111
+ ```bash
112
+ cloudagent-daemon login --server https://api.cloudagent.chat
113
+ # paste the sk_machine_*** key when prompted
114
+ ```
115
+
116
+ 3. Register a local agent (the agent must already exist in cloudagent with
117
+ `runtime=local_daemon` and `host_machine_id=<your host>`):
118
+ ```bash
119
+ cloudagent-daemon agent register --agent-id agent_01HXX --name Frontend
120
+ ```
121
+
122
+ 4. Start the daemon:
123
+ ```bash
124
+ cloudagent-daemon start &
125
+ cloudagent-daemon status
126
+ ```
127
+
128
+ You can also use a process manager like `launchd` (macOS) or `systemd`
129
+ (Linux) — see "Running as a service" below.
130
+
131
+ 5. From the cloudagent UI / API: send a message to the agent. The daemon will
132
+ spawn `claude` to handle it; check `~/.cloudagent/daemon/logs/` for traces.
133
+
134
+ ## One-shot mode
135
+
136
+ For ephemeral runs (CI / debug / quick demo), pass server + key inline — no
137
+ `login` step required and nothing is written to `~/.cloudagent/`:
138
+
139
+ ```bash
140
+ cloudagent-daemon start \
141
+ --server-url https://api.cloudagent.chat \
142
+ --api-key sk_machine_***
143
+
144
+ # Output:
145
+ # Detected runtimes:
146
+ # ✓ claude_code 2.1.137 (/opt/homebrew/bin/claude)
147
+ # Connecting to https://api.cloudagent.chat as host host_01HXX...
148
+ ```
149
+
150
+ `--server-url` and `--api-key` must be passed together; passing one without
151
+ the other exits with code 2. The daemon stops on Ctrl-C / SIGTERM and leaves
152
+ no state behind. For persistent setups, use `login` once + `start` after.
153
+
154
+ ## Layout
155
+
156
+ ```
157
+ ~/.cloudagent/
158
+ ├── daemon/
159
+ │ ├── config.json # server URL + machine API key + host_id
160
+ │ ├── state.json # last_seq + processed message IDs (for dedup)
161
+ │ ├── daemon.pid # PID of running daemon
162
+ │ ├── bridge.sock # unix socket for MCP bridge IPC
163
+ │ └── logs/
164
+ └── agents/
165
+ └── <agent_id>/
166
+ ├── MEMORY.md # agent's long-term memory
167
+ ├── notes/ # agent-managed
168
+ ├── workspace/ # agent's working directory
169
+ └── .meta/ # daemon-managed (identity, mcp config, etc.)
170
+ ```
171
+
172
+ ## Commands
173
+
174
+ | Command | Description |
175
+ |---|---|
176
+ | `cloudagent-daemon login --server URL` | Auth + persist machine key |
177
+ | `cloudagent-daemon start` | Run the daemon (foreground) |
178
+ | `cloudagent-daemon status` | Print PID + connection info |
179
+ | `cloudagent-daemon stop` | Send SIGTERM, wait for clean exit |
180
+ | `cloudagent-daemon install-service` | Install + start as launchd / systemd user service (auto-restart on crash, auto-start at login) |
181
+ | `cloudagent-daemon uninstall-service` | Stop + remove the launchd / systemd service unit |
182
+ | `cloudagent-daemon agent register --agent-id ID` | Create local workspace |
183
+ | `cloudagent-daemon agent unregister --agent-id ID` | Archive workspace |
184
+
185
+ ## Logs
186
+
187
+ `~/.cloudagent/daemon/logs/daemon-YYYY-MM-DD.log`. Tail with:
188
+
189
+ ```bash
190
+ tail -F ~/.cloudagent/daemon/logs/daemon-*.log
191
+ ```
192
+
193
+ ## Troubleshooting
194
+
195
+ - **`Login failed: 401`** — the `sk_machine_***` key was revoked. Create a new
196
+ one in the cloudagent UI (host machine settings).
197
+ - **`daemon not running` after `start &`** — check the log file. Common causes:
198
+ config missing (`login` first), backend unreachable, no claude binary on PATH.
199
+ - **`claude: command not found`** — install Claude Code: see https://claude.ai/code
200
+ - **`agent_status: crashed`** repeatedly — check `~/.cloudagent/agents/<id>/.meta/last-spawn.json`
201
+ for the stderr tail. Common causes: bad MCP config, claude binary version mismatch, agent's
202
+ cwd doesn't exist.
203
+ - **`Backpressure dropped`** — your daemon was offline for too long; the
204
+ cloudagent backend dropped queued messages past 100k.
205
+
206
+ ## Running as a service
207
+
208
+ The daemon ships with `install-service` / `uninstall-service` commands that
209
+ generate and load a launchd (macOS) or systemd (Linux) **user** unit configured
210
+ to **auto-restart on crash** (KeepAlive / Restart=always) and **auto-start at
211
+ login**. This is the commercial-grade default — the daemon never self-exits
212
+ unless you explicitly run `uninstall-service` (or stop it via the OS).
213
+
214
+ ### macOS / Linux
215
+
216
+ ```bash
217
+ # After login (server URL + key persisted in ~/.cloudagent/daemon/config.json):
218
+ cloudagent-daemon login --server https://api.cloudagent.chat --api-key sk_machine_***
219
+ cloudagent-daemon install-service
220
+
221
+ # Or one-shot — embed creds directly in the unit file:
222
+ cloudagent-daemon install-service \
223
+ --server-url https://api.cloudagent.chat \
224
+ --api-key sk_machine_*** \
225
+ --insecure # only if your server uses a self-signed cert
226
+ ```
227
+
228
+ The command writes:
229
+
230
+ - macOS: `~/Library/LaunchAgents/chat.cloudagent.daemon.plist` (KeepAlive=true)
231
+ - Linux: `~/.config/systemd/user/cloudagent-daemon.service` (Restart=always, RestartSec=5)
232
+
233
+ …then bootstraps + kickstarts (macOS) / `daemon-reload` + `enable --now` (Linux).
234
+ Logs:
235
+
236
+ ```bash
237
+ # macOS
238
+ tail -F ~/.cloudagent/daemon/logs/launchd.{out,err}.log
239
+
240
+ # Linux
241
+ journalctl --user -u cloudagent-daemon -f
242
+ ```
243
+
244
+ To remove:
245
+
246
+ ```bash
247
+ cloudagent-daemon uninstall-service
248
+ ```
249
+
250
+ ## Multi-profile (managing multiple backends)
251
+
252
+ You can register the same machine with several cloudagent backends (prod / fr /
253
+ staging / dev …) by giving each its own `--profile <name>`. Each profile gets
254
+ its own service unit, config, socket, workspace, and launchd / systemd label —
255
+ they coexist on disk and run as independent processes.
256
+
257
+ ```bash
258
+ # Default profile (no flag) keeps the legacy paths exactly as before:
259
+ cloudagent-daemon install-service \
260
+ --server-url https://api.cloudagent.chat --api-key sk_machine_xxx
261
+
262
+ # Register a second backend under profile "fr":
263
+ cloudagent-daemon install-service --profile fr \
264
+ --server-url https://api-fr.cloudagent.chat --api-key sk_machine_yyy --insecure
265
+
266
+ # Register a third under "staging":
267
+ cloudagent-daemon install-service --profile staging \
268
+ --server-url https://api-staging.cloudagent.chat --api-key sk_machine_zzz
269
+ ```
270
+
271
+ Inspect what's installed:
272
+
273
+ ```bash
274
+ cloudagent-daemon list-profiles
275
+ # ● default
276
+ # server: https://api.cloudagent.chat
277
+ # host_id: host_a1b2c3
278
+ # status: running pid=12345
279
+ # ● fr
280
+ # server: https://api-fr.cloudagent.chat
281
+ # host_id: host_d4e5f6
282
+ # status: running pid=12350
283
+ ```
284
+
285
+ All commands take `--profile <name>` (default is `default`):
286
+
287
+ ```bash
288
+ cloudagent-daemon status --profile fr
289
+ cloudagent-daemon doctor --profile fr
290
+ cloudagent-daemon stop --profile fr
291
+ cloudagent-daemon uninstall-service --profile fr
292
+ cloudagent-daemon agent register --profile fr --agent-id a1
293
+ ```
294
+
295
+ Profile names must match `[a-z0-9][a-z0-9-]{0,30}`. `default` is reserved.
296
+
297
+ ### Per-profile filesystem layout
298
+
299
+ | Resource | Default profile | Named profile `fr` |
300
+ |---|---|---|
301
+ | Config / state | `~/.cloudagent/daemon/{config,state}.json` | `~/.cloudagent/daemon/profiles/fr/{config,state}.json` |
302
+ | IPC socket | `~/.cloudagent/daemon/bridge.sock` | `~/.cloudagent/daemon/profiles/fr/bridge.sock` |
303
+ | Workspace | `~/.cloudagent/agents/` | `~/.cloudagent/agents-fr/` |
304
+ | Logs | `~/.cloudagent/daemon/logs/launchd.{out,err}.log` | `~/.cloudagent/daemon/profiles/fr/logs/launchd.{out,err}.log` |
305
+ | launchd label | `chat.cloudagent.daemon` | `chat.cloudagent.daemon.fr` |
306
+ | systemd unit | `cloudagent-daemon.service` | `cloudagent-daemon-fr.service` |
307
+
308
+ The default profile keeps the original paths byte-for-byte — existing installs
309
+ need no migration. Named profiles only show up after their first
310
+ `install-service --profile <name>`.
311
+
312
+ The active profile pins itself in `CLOUDAGENT_DAEMON_PROFILE` for any child
313
+ process the daemon spawns (mcp_bridge, claude subprocesses), so commands you
314
+ run inside an agent shell pick up the right profile automatically.
315
+
316
+ ## Spec
317
+
318
+ See `docs/superpowers/specs/2026-05-08-local-daemon-runtime-design.md`.
319
+
320
+ ## License
321
+
322
+ MIT — see [LICENSE](./LICENSE).