zcode-acp-server 0.14.3 → 0.17.1

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 (93) hide show
  1. package/README.md +109 -9
  2. package/README.zh-CN.md +91 -9
  3. package/dist/backend/index.d.ts +1 -0
  4. package/dist/backend/index.d.ts.map +1 -1
  5. package/dist/backend/index.js +1 -0
  6. package/dist/backend/index.js.map +1 -1
  7. package/dist/backend/sandbox.d.ts +92 -23
  8. package/dist/backend/sandbox.d.ts.map +1 -1
  9. package/dist/backend/sandbox.js +265 -70
  10. package/dist/backend/sandbox.js.map +1 -1
  11. package/dist/cli.d.ts +2 -0
  12. package/dist/cli.d.ts.map +1 -1
  13. package/dist/cli.js +10 -1
  14. package/dist/cli.js.map +1 -1
  15. package/dist/config/auto-compact.d.ts.map +1 -1
  16. package/dist/config/auto-compact.js +6 -4
  17. package/dist/config/auto-compact.js.map +1 -1
  18. package/dist/config/mcp-discovery.d.ts.map +1 -1
  19. package/dist/config/mcp-discovery.js +7 -5
  20. package/dist/config/mcp-discovery.js.map +1 -1
  21. package/dist/handlers/background-tasks.d.ts.map +1 -1
  22. package/dist/handlers/background-tasks.js +2 -2
  23. package/dist/handlers/background-tasks.js.map +1 -1
  24. package/dist/handlers/dispatch.d.ts.map +1 -1
  25. package/dist/handlers/dispatch.js +4 -4
  26. package/dist/handlers/dispatch.js.map +1 -1
  27. package/dist/handlers/replay.d.ts.map +1 -1
  28. package/dist/handlers/replay.js +11 -5
  29. package/dist/handlers/replay.js.map +1 -1
  30. package/dist/handlers/sandbox-allow.d.ts +71 -0
  31. package/dist/handlers/sandbox-allow.d.ts.map +1 -0
  32. package/dist/handlers/sandbox-allow.js +299 -0
  33. package/dist/handlers/sandbox-allow.js.map +1 -0
  34. package/dist/handlers/server-requests.d.ts.map +1 -1
  35. package/dist/handlers/server-requests.js +7 -5
  36. package/dist/handlers/server-requests.js.map +1 -1
  37. package/dist/handlers/session.d.ts +14 -1
  38. package/dist/handlers/session.d.ts.map +1 -1
  39. package/dist/handlers/session.js +193 -20
  40. package/dist/handlers/session.js.map +1 -1
  41. package/dist/handlers/slash.d.ts.map +1 -1
  42. package/dist/handlers/slash.js +15 -13
  43. package/dist/handlers/slash.js.map +1 -1
  44. package/dist/i18n.d.ts +111 -0
  45. package/dist/i18n.d.ts.map +1 -0
  46. package/dist/i18n.js +222 -0
  47. package/dist/i18n.js.map +1 -0
  48. package/dist/index.d.ts +18 -0
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +114 -15
  51. package/dist/index.js.map +1 -1
  52. package/dist/interaction/adapter.d.ts.map +1 -1
  53. package/dist/interaction/adapter.js +10 -7
  54. package/dist/interaction/adapter.js.map +1 -1
  55. package/dist/remote/config.d.ts +7 -0
  56. package/dist/remote/config.d.ts.map +1 -1
  57. package/dist/remote/config.js +2 -0
  58. package/dist/remote/config.js.map +1 -1
  59. package/dist/remote/endpoint.d.ts.map +1 -1
  60. package/dist/remote/endpoint.js +66 -11
  61. package/dist/remote/endpoint.js.map +1 -1
  62. package/dist/remote/hub-server.d.ts +15 -0
  63. package/dist/remote/hub-server.d.ts.map +1 -1
  64. package/dist/remote/hub-server.js +205 -1
  65. package/dist/remote/hub-server.js.map +1 -1
  66. package/dist/repl/App.d.ts.map +1 -1
  67. package/dist/repl/App.js +3 -2
  68. package/dist/repl/App.js.map +1 -1
  69. package/dist/repl/model.d.ts +2 -0
  70. package/dist/repl/model.d.ts.map +1 -1
  71. package/dist/repl/model.js.map +1 -1
  72. package/dist/repl/run.d.ts.map +1 -1
  73. package/dist/repl/run.js +5 -0
  74. package/dist/repl/run.js.map +1 -1
  75. package/dist/server.d.ts +78 -1
  76. package/dist/server.d.ts.map +1 -1
  77. package/dist/server.js +114 -3
  78. package/dist/server.js.map +1 -1
  79. package/dist/tasks-index.d.ts +27 -0
  80. package/dist/tasks-index.d.ts.map +1 -1
  81. package/dist/tasks-index.js +72 -3
  82. package/dist/tasks-index.js.map +1 -1
  83. package/docs/REMOTE-CLIENTS.md +43 -0
  84. package/docs/TROUBLESHOOTING.md +9 -3
  85. package/package.json +13 -12
  86. package/dist/remote/session-liveness.d.ts +0 -19
  87. package/dist/remote/session-liveness.d.ts.map +0 -1
  88. package/dist/remote/session-liveness.js +0 -70
  89. package/dist/remote/session-liveness.js.map +0 -1
  90. package/dist/repl/mouse.d.ts +0 -49
  91. package/dist/repl/mouse.d.ts.map +0 -1
  92. package/dist/repl/mouse.js +0 -165
  93. package/dist/repl/mouse.js.map +0 -1
package/README.md CHANGED
@@ -9,6 +9,14 @@ A standalone [Agent Client Protocol](https://agentclientprotocol.com/) (ACP) ser
9
9
 
10
10
  The server launches the ZCode headless app-server (`zcode app-server --stdio`) as a subprocess, translates its internal event stream into ACP `session/update` notifications, and bridges ZCode's interaction channel to ACP — preferring `elicitation/create` when the client supports it, and falling back to `session/request_permission` otherwise — so an editor gets a first-class, native coding-agent experience.
11
11
 
12
+ ## Why zcode-acp
13
+
14
+ - **Native editor experience** — streaming diffs, permission prompts and plan mode in Zed / JetBrains' own agent panel. No side-by-side terminal.
15
+ - **The official harness, not a reimplementation** — drives the real `zcode app-server`: native tools, skills, MCP and slash commands, auto-compaction, session resume/fork.
16
+ - **Beyond the editor** — a full bilingual terminal REPL (`zcode-acp`, English/中文, works over SSH), phone/web access to the same sessions (`zcode-acp-remote`), opt-in writes-only sandbox. Credentials stay in `~/.zcode`.
17
+
18
+ Because it drives the real ZCode client, your GLM Coding Plan comes along untouched — current perks (the 150% quota bonus, priority routing over raw API) and the plan's flat-rate economics apply exactly as in the official app. No API keys in editor settings.
19
+
12
20
  ## Status
13
21
 
14
22
  In active development. Core bridging, slash commands and ZCode extensions,
@@ -26,15 +34,27 @@ in place; see the project board for what's next.
26
34
  ## Install
27
35
 
28
36
  ```bash
29
- git clone <repo-url>
37
+ npm install -g zcode-acp-server
38
+ ```
39
+
40
+ This installs both bins: `zcode-acp-server` (what your editor launches) and
41
+ `zcode-acp` (the unified CLI). Configure your ACP client to launch it — see
42
+ **Configure Zed** below or your editor's ACP docs.
43
+
44
+ <details>
45
+ <summary>Install from source instead</summary>
46
+
47
+ ```bash
48
+ git clone https://github.com/william0wang/zcode-acp.git
30
49
  cd zcode-acp-server
31
50
  pnpm install
32
51
  pnpm build
33
52
  ```
34
53
 
35
54
  The compiled entry point is `dist/index.js` (also exposed as the
36
- `zcode-acp-server` bin). Configure your ACP client to launch it — see
37
- **Configure Zed** below or your editor's ACP docs.
55
+ `zcode-acp-server` bin).
56
+
57
+ </details>
38
58
 
39
59
  ## Configure Zed
40
60
 
@@ -46,11 +66,10 @@ Add the server to Zed as a custom agent server. In `~/.config/zed/settings.json`
46
66
  "agent_servers": {
47
67
  "ZCode": {
48
68
  "type": "custom",
49
- "command": "node",
50
- "args": ["/absolute/path/to/zcode-acp-server/dist/index.js"],
69
+ "command": "zcode-acp-server",
51
70
  "env": {
52
- // Point at the ZCode CLI bundled inside the desktop app (not on PATH by default).
53
- // See the platform-specific path below.
71
+ // Only needed for custom installs the CLI is auto-discovered from
72
+ // the desktop app bundle or PATH (see the table below).
54
73
  "ZCODE_BIN": "/Applications/ZCode.app/Contents/Resources/glm/zcode.cjs",
55
74
  },
56
75
  },
@@ -58,6 +77,9 @@ Add the server to Zed as a custom agent server. In `~/.config/zed/settings.json`
58
77
  }
59
78
  ```
60
79
 
80
+ Running from source instead? Use `"command": "node"` with
81
+ `"args": ["/absolute/path/to/zcode-acp-server/dist/index.js"]`.
82
+
61
83
  Restart Zed and pick **ZCode** from the agent dropdown.
62
84
 
63
85
  ### `ZCODE_BIN` per platform
@@ -97,6 +119,56 @@ most setups need no `ZCODE_BIN` at all — set it only for custom installs:
97
119
  | `ZCODE_ACP_HUB_PORT` | `8377` | Port of the machine-level hub daemon. Map exactly this one port in your tunnel. |
98
120
  | `ZCODE_ACP_HUB_HOST` | `127.0.0.1` | Hub bind address. `0.0.0.0` exposes a token-only, unencrypted surface — only for a containerized tunnel agent on a private interface (see [Remote Access](#remote-access)). |
99
121
  | `ZCODE_ACP_REMOTE_PORT` | `8378` | First loopback port for the bridge's ACP endpoint. Each bridge (each editor window) auto-increments to the next free port. |
122
+ | `ZCODE_ACP_SANDBOX` | _(unset)_ | Set to `1` to confine the agent's file writes with a macOS Seatbelt sandbox globally; per-project, set `"enabled": true` in `<workspace>/.zcode/acp/sandbox.json` instead (see [Sandbox](#sandbox)). |
123
+ | `ZCODE_ACP_LANG` | _(inherited)_ | Language of the bridge's user-facing strings (popups, status/hint lines, command menu descriptions): `zh` or `en`. When unset, the bridge inherits the ZCode app's language (`localePreference`/`locale` in `~/.zcode/v2/setting.json`), then falls back to the `LC_ALL`/`LC_MESSAGES`/`LANG` locale, defaulting to English. |
124
+
125
+ ## Sandbox
126
+
127
+ Two switches arm the sandbox (macOS only), whichever comes first:
128
+
129
+ - globally: `ZCODE_ACP_SANDBOX=1`, or
130
+ - per project: `"enabled": true` in `<workspace>/.zcode/acp/sandbox.json`.
131
+ The bridge auto-creates that file with `"enabled": false` the first time
132
+ you open the workspace — flip the flag to opt this project in, no global
133
+ env needed. Flipping it mid-run takes effect on the next prompt (the
134
+ backend restarts sandboxed); flipping back takes effect the next time the
135
+ backend restarts on its own.
136
+
137
+ Once armed, the zcode backend subprocess — and every Bash/Edit/Write it
138
+ performs, including all child processes — runs wrapped in a
139
+ Seatbelt (`sandbox-exec`) profile that denies file writes everywhere except:
140
+
141
+ - the workspace root(s) of your live sessions,
142
+ - `~/.zcode*` (the backend's own sessions/db/logs),
143
+ - the system temp directory and regenerable tool caches (`~/Library/Caches`,
144
+ `~/.cache`, `~/.npm`, `~/Library/pnpm`, `~/.node-gyp`),
145
+ - paths granted via the per-project config or the allow popup.
146
+
147
+ Reads and process execution stay open: deletion (`rm`, `mv`, truncation) is a
148
+ write-class syscall, so the write denial stops it regardless of which binary
149
+ performs it — including `/bin/rm`, `python shutil.rmtree`, or shell
150
+ redirections.
151
+
152
+ When a write outside the whitelist is attempted, the tool fails with
153
+ `Operation not permitted` and the bridge asks via the editor's permission
154
+ popup with four choices: allow **once**, allow **always**, reject **once**,
155
+ reject **always**. The "always" choices are persisted by the bridge into
156
+ `<workspace>/.zcode/acp/sandbox.json` (created on first run — allows to the
157
+ `allow` list, rejections to a `deny` list that suppresses future asks; edit
158
+ the file to undo either). "Once" choices and dismissed popups persist
159
+ nothing and will ask again. The agent itself cannot edit
160
+ that file — the sandbox denies
161
+ writes to `.zcode/acp/` inside the workspace while the bridge (outside the
162
+ sandbox) writes it on your behalf. After an allow, the backend restarts with
163
+ the widened profile (a few seconds; the bridge auto-continues the interrupted
164
+ task). Set `"strictGit": true` in the config to also put `.git` behind the
165
+ popup.
166
+
167
+ This targets accident prevention, not malice: indirect escapes (an
168
+ agent-edited `.bashrc`, build scripts, or git hooks that you later run
169
+ yourself outside the sandbox) are out of scope — treat its output like any
170
+ other code review. Verify a profile manually with
171
+ `bash scripts/verify-sandbox.sh` (macOS, after `pnpm build`).
100
172
 
101
173
  ## Remote Access
102
174
 
@@ -145,12 +217,38 @@ discovery ~30s after it stops.
145
217
 
146
218
  ```text
147
219
  GET /api/instances → [{"id","port","pid","startedAt","workspace",
148
- "sessions":[{"sessionId","title?","updatedAt"}]}]
220
+ "origin","sessions":[{"sessionId","title?","updatedAt"}]}]
149
221
  GET /api/instances?probe=1 → same list, but unreachable bridges are pruned first
150
222
  WS /acp?instance=<id> → proxied to that bridge's endpoint
151
223
  GET /api/instances/{id}/fs/… → read-only session files (list + raw bytes, ADR-0004)
152
224
  ```
153
225
 
226
+ `origin` labels how an instance was started: `"editor"` (a bridge an editor
227
+ spawned over stdio) or `"serve"` (a headless bridge created remotely, see
228
+ below).
229
+
230
+ **Remote session-create** (ADR-0014). A remote client can start a NEW agent
231
+ session in any of the machine's known projects — no editor required:
232
+
233
+ ```text
234
+ GET /api/projects → [{"workspacePath","sessions","lastActive"}]
235
+ POST /api/instances {workspacePath} → {"id","reused"}
236
+ ```
237
+
238
+ `/api/projects` aggregates the App's tasks index: every workspace that ever
239
+ ran a session (system temp trees, `~/.zcode` itself, and vanished
240
+ directories filtered out), newest activity first. The list gates the POST —
241
+ paths outside it get 403 (a convenience bound, not a security boundary: a
242
+ token holder can already drive an editor-bridge session in any cwd; the
243
+ trust boundary is the token). On create the hub
244
+ spawns `zcode-acp serve` — a headless bridge — in the project's cwd; it
245
+ registers back within seconds and is reachable like any other instance. A
246
+ live serve instance for the same workspace is reused instead of re-spawned
247
+ (`reused:true`). The serve bridge lives for remote interest only: it exits
248
+ ~10 minutes after the last client detaches and the last turn finishes, and
249
+ its `session/new` always uses the project cwd regardless of what a client
250
+ sends.
251
+
154
252
  `sessions` lists the project's **currently running** conversations (live
155
253
  editor tabs and remote attachments) under the same ACP session ids the
156
254
  editor uses — attaching by id joins the conversation's live notification
@@ -380,7 +478,7 @@ Editor configs referencing `zcode-acp-server` keep working unchanged.
380
478
 
381
479
  This server is compatible with the [ACP Registry](https://agentclientprotocol.com/get-started/registry). It advertises a single `agent`-type auth method at `initialize` time — the GLM API key is read from `~/.zcode/v2/config.json` by the ZCode backend, so **no editor-side credentials are required**.
382
480
 
383
- The registry submission assets live under [`registry/zcode-acp-server/`](registry/zcode-acp-server/) (`agent.json` + `icon.svg`). Once the package is published to npm, copy that directory into a fork of [`agentclientprotocol/registry`](https://github.com/agentclientprotocol/registry) and open a PR — the CI validates the `agent.json` schema, icon, and that `initialize` returns a non-empty `authMethods`.
481
+ The registry submission assets live under [`registry/zcode-acp/`](registry/zcode-acp/) (`agent.json` + `icon.svg`). Once the package is published to npm, copy that directory into a fork of [`agentclientprotocol/registry`](https://github.com/agentclientprotocol/registry) and open a PR — the CI validates the `agent.json` schema, icon, and that `initialize` returns a non-empty `authMethods`.
384
482
 
385
483
  ## Develop
386
484
 
@@ -443,6 +541,8 @@ recorded in [CHANGELOG.md](CHANGELOG.md).
443
541
 
444
542
  ## Related Projects
445
543
 
544
+ - [glm-acp-agent](https://github.com/stefandevo/glm-acp-agent) — a self-contained ACP agent that calls the GLM API directly; zcode-acp instead bridges the real `zcode app-server`, inheriting its full official harness.
545
+ - [claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp) / [codex-acp](https://github.com/agentclientprotocol/codex-acp) — official ACP adapters for the Claude and Codex CLIs; zcode-acp is the same idea for the ZCode CLI.
446
546
  - [zcode-open-bridge](https://github.com/tizerluo/zcode-open-bridge) — a community Python implementation that bridges ZCode to the MCP/ACP ecosystem. The design of this server references its bridge architecture and several handling strategies.
447
547
 
448
548
  ## Acknowledgements
package/README.zh-CN.md CHANGED
@@ -9,6 +9,14 @@
9
9
 
10
10
  本服务端以子进程方式启动 ZCode 无头 app-server(`zcode app-server --stdio`),将其内部事件流翻译为 ACP `session/update` 通知,并把 ZCode 的交互通道桥接到 ACP —— 当客户端支持时优先使用 `elicitation/create`,否则回退到 `session/request_permission` —— 从而让编辑器获得原生的、一流的编码助手体验。
11
11
 
12
+ ## 为什么选 zcode-acp
13
+
14
+ - **编辑器原生体验** —— 流式改动以真实 diff 呈现,权限确认、计划模式都走 Zed / JetBrains 自己的 agent 面板,无需并排终端。
15
+ - **官方 harness,而非重新实现** —— 驱动真实的 `zcode app-server`:原生工具、skills、MCP 与斜杠命令、自动压缩、会话恢复/分叉。
16
+ - **不止于编辑器** —— 完整的双语终端 REPL(`zcode-acp`,中/英可切换,SSH 下可用),手机/网页访问相同会话(`zcode-acp-remote`),可选的只限写入沙箱。凭据留在 `~/.zcode`。
17
+
18
+ 由于驱动的是真实 ZCode 客户端,你现有的 GLM Coding Plan 原样生效——当前的套餐权益(150% 额度加成、高于直连 API 的请求优先级)和包月计费方式都和在官方 App 中一致。编辑器设置无需任何 API key。
19
+
12
20
  ## 状态
13
21
 
14
22
  早期开发中。核心框架已就绪,功能正在陆续加入。进度请看项目看板。
@@ -23,14 +31,25 @@
23
31
  ## 安装
24
32
 
25
33
  ```bash
26
- git clone <repo-url>
34
+ npm install -g zcode-acp-server
35
+ ```
36
+
37
+ 会同时安装两个 bin:`zcode-acp-server`(编辑器调用)和 `zcode-acp`(统一 CLI)。
38
+ 在你的 ACP 客户端里配置启动它 —— 见下方的 **在 Zed 中配置** 或你的编辑器的 ACP 文档。
39
+
40
+ <details>
41
+ <summary>改为从源码安装</summary>
42
+
43
+ ```bash
44
+ git clone https://github.com/william0wang/zcode-acp.git
27
45
  cd zcode-acp-server
28
46
  pnpm install
29
47
  pnpm build
30
48
  ```
31
49
 
32
- 编译产物入口为 `dist/index.js`(同时作为 `zcode-acp-server` bin 暴露)。在你的
33
- ACP 客户端里配置启动它 —— 见下方的 **在 Zed 中配置** 或你的编辑器的 ACP 文档。
50
+ 编译产物入口为 `dist/index.js`(同时作为 `zcode-acp-server` bin 暴露)。
51
+
52
+ </details>
34
53
 
35
54
  ## 在 Zed 中配置
36
55
 
@@ -42,11 +61,10 @@ ACP 客户端里配置启动它 —— 见下方的 **在 Zed 中配置** 或你
42
61
  "agent_servers": {
43
62
  "ZCode": {
44
63
  "type": "custom",
45
- "command": "node",
46
- "args": ["/absolute/path/to/zcode-acp-server/dist/index.js"],
64
+ "command": "zcode-acp-server",
47
65
  "env": {
48
- // 指向桌面应用内置的 ZCode CLI(默认不在 PATH 上)。
49
- // 各平台路径见下方表格。
66
+ // 仅自定义安装时需要——CLI 会从桌面应用内置路径或 PATH 自动发现
67
+ // (见下方表格)。
50
68
  "ZCODE_BIN": "/Applications/ZCode.app/Contents/Resources/glm/zcode.cjs",
51
69
  },
52
70
  },
@@ -54,6 +72,9 @@ ACP 客户端里配置启动它 —— 见下方的 **在 Zed 中配置** 或你
54
72
  }
55
73
  ```
56
74
 
75
+ 从源码运行?改用 `"command": "node"` 与
76
+ `"args": ["/absolute/path/to/zcode-acp-server/dist/index.js"]`。
77
+
57
78
  重启 Zed,然后从 agent 下拉菜单中选择 **ZCode**。
58
79
 
59
80
  ### 各平台的 `ZCODE_BIN` 路径
@@ -91,6 +112,46 @@ ZCode CLI 内置于桌面应用中,默认不会加到 `PATH`。用 `ZCODE_BIN`
91
112
  | `ZCODE_ACP_HUB_PORT` | `8377` | 机器级 `zcode-acp-hub` 的端口。隧道只映射这一个端口。 |
92
113
  | `ZCODE_ACP_HUB_HOST` | `127.0.0.1` | hub 绑定地址。`0.0.0.0` 会暴露仅 token 保护的明文面——只用于容器化隧道 agent 所在的私网接口(见[远程访问](#远程访问))。 |
93
114
  | `ZCODE_ACP_REMOTE_PORT` | `8378` | bridge ACP 端点的起始回环端口。每个 bridge(每个编辑器窗口)自动递增取下一个空闲端口。 |
115
+ | `ZCODE_ACP_SANDBOX` | _(未设置)_ | 设为 `1` 全局启用 macOS Seatbelt 沙箱限制 Agent 的文件写入;项目级则在 `<工作区>/.zcode/acp/sandbox.json` 里设 `"enabled": true`(见[沙箱](#沙箱))。 |
116
+ | `ZCODE_ACP_LANG` | _(继承)_ | 桥的用户可见文案(弹窗、状态/提示行、命令菜单描述)语言:`zh` 或 `en`。未设置时继承 ZCode APP 的语言设置(`~/.zcode/v2/setting.json` 的 `localePreference`/`locale`),再退回 `LC_ALL`/`LC_MESSAGES`/`LANG` 区域设置,默认英文。 |
117
+
118
+ ## 沙箱
119
+
120
+ 两个开关任一生效(仅 macOS):
121
+
122
+ - 全局:`ZCODE_ACP_SANDBOX=1`;
123
+ - 项目级:`<工作区>/.zcode/acp/sandbox.json` 里设 `"enabled": true`。该文件
124
+ 在首次打开工作区时由桥自动创建(默认 `"enabled": false`)——把开关翻成
125
+ `true` 即可单独启用本项目,无需全局环境变量。运行中途翻开关,下一次
126
+ prompt 生效(后端以沙箱重启);翻回 `false` 则在后端下次自然重启时停用。
127
+
128
+ 启用后,zcode 后端子进程——连同它执行的每一次 Bash/Edit/Write 及所有子进
129
+ 程——被包进 Seatbelt(`sandbox-exec`)沙箱:除以下位置外**一律禁止文件写入**:
130
+
131
+ - 各活跃会话的工作区根目录;
132
+ - `~/.zcode*`(后端自身的会话/数据库/日志);
133
+ - 系统临时目录与可再生的工具缓存(`~/Library/Caches`、`~/.cache`、
134
+ `~/.npm`、`~/Library/pnpm`、`~/.node-gyp`);
135
+ - 项目配置或放行弹窗授权的路径。
136
+
137
+ 读取和进程执行不受限:删除(`rm`、`mv`、截断)属于写类系统调用,写禁令
138
+ 会拦下它——无论用哪个二进制执行(`/bin/rm`、Python `shutil.rmtree`、shell
139
+ 重定向都一样)。
140
+
141
+ 当 Agent 尝试写白名单之外的位置时,工具报 `Operation not permitted`,桥
142
+ 通过编辑器权限弹窗给出四个选项:**仅此一次**、**始终允许**、**拒绝一次**、
143
+ **始终拒绝**。两个“始终”由桥代写进 `<工作区>/.zcode/acp/sandbox.json`
144
+ (首次运行自动创建——放行记入 `allow` 列表,拒绝记入 `deny` 列表并不再
145
+ 询问;编辑该文件即可撤销);两个“一次”及关闭弹窗不保存任何东西,下次
146
+ 仍会询问。Agent 自己改不了这个文件——沙箱禁止写工作区内的
147
+ `.zcode/acp/`,而桥在沙箱外。放行
148
+ 后后端以加宽的 profile 重启(几秒),桥自动继续被中断的任务。配置里设
149
+ `"strictGit": true` 可让 `.git` 也走弹窗。
150
+
151
+ 沙箱目标是防误删误写,不是防恶意:间接逃逸(Agent 改了你的 `.bashrc`、构
152
+ 建脚本或 git hook,随后由你自己在沙箱外执行)不在防护范围——请像代码评审
153
+ 一样对待它的产出。可用 `bash scripts/verify-sandbox.sh` 手工验证
154
+ profile(macOS,先 `pnpm build`)。
94
155
 
95
156
  ## 远程访问
96
157
 
@@ -128,10 +189,29 @@ token 鉴权、实例发现、字节级 WebSocket 代理——不保存会话状
128
189
  心跳,心跳停止约 30 秒后从发现列表移除;客户端刷新时也可调用
129
190
  `GET /api/instances?probe=1` 主动探测,立即清理不可达的实例。
130
191
 
192
+ **远程创建会话**(ADR-0014)。远程客户端可以在本机的已知项目里直接开一个
193
+ 新会话——不需要任何编辑器在场:
194
+
195
+ ```text
196
+ GET /api/projects → [{"workspacePath","sessions","lastActive"}]
197
+ POST /api/instances {workspacePath} → {"id","reused"}
198
+ ```
199
+
200
+ `/api/projects` 聚合 App 的任务索引:所有跑过会话的项目(过滤系统临时
201
+ 目录、`~/.zcode` 自身和已不存在的目录),按最近活跃排序。这份列表约束
202
+ POST——列表之外的路径一律 403(注意这是便利性约束而非安全边界:持有
203
+ token 者本就能以任意 cwd 驱动 editor bridge 会话,真正的信任边界是
204
+ token 本身)。创建时 hub 会在项目目录下拉起 `zcode-acp serve`(无头 bridge),
205
+ 数秒内注册回 hub,之后像普通实例一样可连接;同项目已有存活的 serve 实例
206
+ 则直接复用(`reused:true`)。serve bridge 只为远程连接而活:最后一个客户端
207
+ 断开且最后一个 turn 结束约 10 分钟后自动退出;其 `session/new` 无论客户端
208
+ 传什么都使用项目目录(cwd 端到端钉死在项目内)。
209
+
131
210
  **语义。** 所有 agent 通知广播给每个已连接客户端;权限 / elicitation 请求
132
211
  发给所有客户端,**先应答者生效**,其余客户端收到 `$/cancel_request` 关闭
133
212
  对话框。同一会话的并发 prompt 与单编辑器一样串行化。任一客户端声明的能力
134
- 按 OR 合并。
213
+ 按 OR 合并。`/api/instances` 的每个实例带 `origin` 字段(`"editor"`=编辑器
214
+ stdio 桥,`"serve"`=远程创建的无头桥),客户端可据此标注。
135
215
 
136
216
  **隧道。** 面向单端口隧道(Cloudflare Tunnel、frp)设计:只映射 hub 端口。
137
217
  frp 的 `tcp` 模式原样透传 WebSocket;Cloudflare Tunnel 会断开空闲连接,
@@ -210,7 +290,7 @@ export OPENCODE_GO_AUTH_COOKIE="Fe26.2**你的cookie值"
210
290
 
211
291
  本服务端兼容 [ACP Registry](https://agentclientprotocol.com/get-started/registry)。它在 `initialize` 时声明一个 `agent` 类型的认证方法——GLM API key 由 ZCode 后端从 `~/.zcode/v2/config.json` 读取,**编辑器侧无需配置任何凭据**。
212
292
 
213
- Registry 提交资产位于 [`registry/zcode-acp-server/`](registry/zcode-acp-server/)(`agent.json` + `icon.svg`)。包发布到 npm 后,将该目录复制到 [`agentclientprotocol/registry`](https://github.com/agentclientprotocol/registry) 的 fork 中并提 PR——CI 会校验 `agent.json` schema、图标,以及 `initialize` 返回的 `authMethods` 非空。
293
+ Registry 提交资产位于 [`registry/zcode-acp/`](registry/zcode-acp/)(`agent.json` + `icon.svg`)。包发布到 npm 后,将该目录复制到 [`agentclientprotocol/registry`](https://github.com/agentclientprotocol/registry) 的 fork 中并提 PR——CI 会校验 `agent.json` schema、图标,以及 `initialize` 返回的 `authMethods` 非空。
214
294
 
215
295
  ## 开发
216
296
 
@@ -266,6 +346,8 @@ commit 约定和 PR 检查清单。重要变更记录在 [CHANGELOG.md](CHANGELO
266
346
 
267
347
  ## 相关项目
268
348
 
349
+ - [glm-acp-agent](https://github.com/stefandevo/glm-acp-agent) —— 自包含的 ACP agent,直接调用 GLM API;zcode-acp 则桥接真实的 `zcode app-server`,继承其完整的官方 harness。
350
+ - [claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp) / [codex-acp](https://github.com/agentclientprotocol/codex-acp) —— Claude 与 Codex CLI 的官方 ACP 适配器;zcode-acp 是同一思路在 ZCode CLI 上的实现。
269
351
  - [zcode-open-bridge](https://github.com/tizerluo/zcode-open-bridge) —— 一个社区 Python 实现,将 ZCode 接入 MCP/ACP 生态。本项目参考了它的桥接架构和若干处理策略。
270
352
 
271
353
  ## 致谢
@@ -3,5 +3,6 @@ export { ZcodeBackend, type ServerRequest, type EventListener } from "./client.j
3
3
  export { EventStreamListener, TurnMonitor, type NextId } from "./listener.js";
4
4
  export { resolveZcodeCommand } from "./resolve.js";
5
5
  export { loadZcodeCredentials, mergeEnvWithCreds, type ZcodeCredentials } from "./credentials.js";
6
+ export { SANDBOX_ENV, appendSandboxAllow, armSandboxArgv, buildSandboxProfile, collectSandboxWorkspaces, projectSandboxEnabled, readSandboxConfig, resetSandboxDecisionForTest, sandboxActive, sandboxConfigPath, type SandboxConfig, } from "./sandbox.js";
6
7
  export type { ZcodeRequest, ZcodeNotification, ZcodeResponse, ZcodeInbound, ZcodeSessionInfo, ZcodeCreateResult, ZcodeSessionListItem, ZcodeListResult, ZcodeEvent, ZcodeEventType, ZcodeSubscribeResult, ZcodeSnapshot, ZcodeProjection, ZcodeMessage, ZcodeMessagePart, ZcodeMessagesResult, ZcodeReadResult, ZcodeInteractionPermissionParams, ZcodeInteractionUserInputParams, ZcodeInteractionResponse, } from "./types.js";
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAClG,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,UAAU,EACV,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,gCAAgC,EAChC,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAClG,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,2BAA2B,EAC3B,aAAa,EACb,iBAAiB,EACjB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,UAAU,EACV,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,gCAAgC,EAChC,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
@@ -3,4 +3,5 @@ export { ZcodeBackend } from "./client.js";
3
3
  export { EventStreamListener, TurnMonitor } from "./listener.js";
4
4
  export { resolveZcodeCommand } from "./resolve.js";
5
5
  export { loadZcodeCredentials, mergeEnvWithCreds } from "./credentials.js";
6
+ export { SANDBOX_ENV, appendSandboxAllow, armSandboxArgv, buildSandboxProfile, collectSandboxWorkspaces, projectSandboxEnabled, readSandboxConfig, resetSandboxDecisionForTest, sandboxActive, sandboxConfigPath, } from "./sandbox.js";
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,OAAO,EAAE,YAAY,EAA0C,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAe,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAyB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,OAAO,EAAE,YAAY,EAA0C,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAe,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAyB,MAAM,kBAAkB,CAAC;AAClG,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,2BAA2B,EAC3B,aAAa,EACb,iBAAiB,GAElB,MAAM,cAAc,CAAC"}
@@ -2,12 +2,20 @@
2
2
  * Seatbelt sandbox for the zcode backend subprocess (ADR-0011).
3
3
  *
4
4
  * The backend runs every Bash/Edit/Write tool with the user's full
5
- * privileges; one careless command destroys real data. When
6
- * ZCODE_ACP_SANDBOX=1, the bridge wraps the single backend spawn point with
7
- * a generated `sandbox-exec` profile using a writes-only restriction model:
8
- * reads and process execution stay open, file writes are denied everywhere
9
- * except an explicit whitelist. Children inherit the sandbox, so one wrap
10
- * covers the backend, its tool subprocesses, and model workers.
5
+ * privileges; one careless command destroys real data. The bridge wraps the
6
+ * single backend spawn point with a generated `sandbox-exec` profile using a
7
+ * writes-only restriction model: reads and process execution stay open, file
8
+ * writes are denied everywhere except an explicit whitelist. Children inherit
9
+ * the sandbox, so one wrap covers the backend, its tool subprocesses, and
10
+ * model workers deletion (rm/mv/truncate) is a write-class syscall, so it
11
+ * is stopped by the write denial regardless of which binary performs it
12
+ * (name-banning executables would be trivially bypassed and is deliberately
13
+ * not done).
14
+ *
15
+ * Arming is dual-switch (see sandboxActive): ZCODE_ACP_SANDBOX=1 forces it
16
+ * globally, or a workspace opts in via `enabled: true` in its own
17
+ * .zcode/acp/sandbox.json — the template is auto-created with enabled:false,
18
+ * so opting in is always an explicit user edit.
11
19
  *
12
20
  * Whitelist (frozen at spawn, rebuilt on backend restart):
13
21
  * - workspace roots of all live sessions (union of server.sessionCwds)
@@ -16,6 +24,7 @@
16
24
  * - system temp + regenerable cache dirs (zero-value targets, constant
17
25
  * toolchain traffic)
18
26
  * - each project's `.zcode/acp/sandbox.json` `allow` list
27
+ * - bridge-lifetime once-allows granted via the dynamic allow flow
19
28
  *
20
29
  * `<workspace>/.zcode/acp/` is a DENY island inside every allowed workspace:
21
30
  * the sandbox forbids writes there while the bridge — outside the sandbox —
@@ -28,24 +37,54 @@
28
37
  /** The one and only env switch. Every other knob is project config. */
29
38
  export declare const SANDBOX_ENV = "ZCODE_ACP_SANDBOX";
30
39
  export interface SandboxConfig {
40
+ /**
41
+ * Project-level switch: true arms the sandbox for this workspace without
42
+ * the global env. The auto-created template ships false — opting in is an
43
+ * explicit user edit.
44
+ */
45
+ enabled: boolean;
31
46
  /** Absolute realpaths OUTSIDE the workspace granted permanent write. */
32
47
  allow: string[];
48
+ /**
49
+ * Absolute realpaths the user chose NEVER to grant ("永不放行") — the
50
+ * popup is suppressed for these. Visible config, not hidden memory: the
51
+ * user can review or undo a denial by editing this file.
52
+ */
53
+ deny: string[];
33
54
  /** true = .git sits behind the allow popup instead of default-writable. */
34
55
  strictGit: boolean;
35
56
  }
36
57
  /** Path of the per-project sandbox config inside a workspace root. */
37
58
  export declare function sandboxConfigPath(workspaceRoot: string): string;
38
59
  /**
39
- * Read the project sandbox config, auto-creating it with defaults on first
40
- * sandboxed run. Tolerates absent/garbage files (falls back to defaults)
41
- * a broken config must never keep the sandbox from arming.
60
+ * Read the project sandbox config, auto-creating the template (enabled:
61
+ * false) on first touch so the user finds the file and can flip the switch
62
+ * the PRESENCE of the file is never the switch, only `enabled` is, so the
63
+ * auto-create cannot arm anything by itself. A malformed or non-object file
64
+ * falls back to enabled:true WITHOUT rewriting it: corruption must fail
65
+ * CLOSED (the user opted in; losing that to a half-saved file would silently
66
+ * disarm), and clobbering the user's mid-edit bytes with a template would be
67
+ * worse than the transient read. A symlinked/hardlinked config is treated
68
+ * the same way (armed, persistence disabled) — see configIntegrityOk. So is
69
+ * a config that was armed and then became unreadable or disappeared — only
70
+ * the agent could do that from inside the sandbox.
42
71
  */
43
72
  export declare function readSandboxConfig(workspaceRoot: string): SandboxConfig;
44
73
  /**
45
74
  * Bridge-side persistence for "always allow" (the deny island keeps the
46
- * agent from writing this file itself). Dedupes by exact string.
75
+ * agent from writing this file itself). Round-trips the whole config so the
76
+ * enabled flag survives the write. Dedupes by exact string. Returns false
77
+ * when persistence is impossible (symlinked config, unwritable path) — the
78
+ * caller then downgrades to a bridge-lifetime once-allow.
79
+ */
80
+ export declare function appendSandboxAllow(workspaceRoot: string, allowedPath: string): boolean;
81
+ /**
82
+ * Bridge-side persistence for the popup's "永不放行" choice — the visible
83
+ * counterpart of appendSandboxAllow: a denied path is RECORDED in the
84
+ * config (never hidden in bridge memory), so the ask never resurfaces for
85
+ * it and the user can review or undo the decision by editing the file.
47
86
  */
48
- export declare function appendSandboxAllow(workspaceRoot: string, allowedPath: string): void;
87
+ export declare function appendSandboxDeny(workspaceRoot: string, deniedPath: string): boolean;
49
88
  /**
50
89
  * Resolve a path to its filesystem truth. Seatbelt matches real paths, so a
51
90
  * symlinked prefix (/tmp → /private/tmp) would silently fail to match —
@@ -58,13 +97,21 @@ export interface SandboxArmInput {
58
97
  root: string;
59
98
  config: SandboxConfig;
60
99
  }>;
61
- /** Extra writable roots from configs of workspaces not arming now. */
100
+ /** Extra writable roots: allowlists from other workspaces + once-allows. */
62
101
  extraAllow: string[];
102
+ /**
103
+ * Directory the profile file itself lives in — self-denied LAST so the
104
+ * sandboxed agent cannot race/symlink/occupy the next respawn's profile
105
+ * (see armSandboxArgv). $TMPDIR is agent-writable, so without this the
106
+ * profile path would be attacker-reachable.
107
+ */
108
+ profileDir?: string;
63
109
  }
64
110
  /**
65
- * Build the SBPL profile text. Deny-rules take precedence over allow-rules
66
- * (verified empirically), which is what makes the `.zcode/acp/` deny island
67
- * inside an allowed workspace stick.
111
+ * Build the SBPL profile text. SBPL resolves overlapping rules by LAST
112
+ * match (verified empirically: an allow emitted after a deny re-permits the
113
+ * write), so the layout is: base deny-all, then every allow, then the deny
114
+ * carve-outs (island, strictGit) LAST so nothing can override them.
68
115
  */
69
116
  export declare function buildSandboxProfile(input: SandboxArmInput): string;
70
117
  /** Resolved arm input for the CURRENT spawn: union of all live workspaces. */
@@ -76,16 +123,38 @@ export declare function collectSandboxWorkspaces(cwdRoots: Iterable<string>): {
76
123
  extraAllow: string[];
77
124
  };
78
125
  /**
79
- * Whether the sandbox is active for this bridge run: env set AND macOS.
80
- * Non-macOS with the env set warns once and returns false (unsandboxed).
81
- * Decided once; later env changes don't re-arm mid-run.
126
+ * The project-level switch: `enabled: true` inside the workspace's sandbox
127
+ * config (auto-created on first touch, template ships false). Reading also
128
+ * materializes the template for discovery. Once the sandbox is armed the
129
+ * deny island keeps the agent from flipping the switch back off.
130
+ */
131
+ export declare function projectSandboxEnabled(workspaceRoot: string): boolean;
132
+ /**
133
+ * Whether the sandbox should arm for this bridge: ZCODE_ACP_SANDBOX=1
134
+ * (global, cached) OR any given workspace root opted in via
135
+ * sandbox.json `enabled` (project switch, re-checked per call so a flip
136
+ * mid-run is seen). macOS-only: elsewhere a requested sandbox warns once and
137
+ * runs unsandboxed.
82
138
  */
83
- export declare function sandboxActive(): boolean;
84
- /** Test hook: reset the cached platform/env decision. */
139
+ export declare function sandboxActive(roots?: Iterable<string>): boolean;
140
+ /** Test hook: reset cached decisions and warn-once sets. */
85
141
  export declare function resetSandboxDecisionForTest(): void;
86
142
  /**
87
- * Wrap a backend argv with sandbox-exec. Writes the profile to a temp file
88
- * owned by this bridge process (regenerated per backend respawn).
143
+ * Arm a backend argv: build the profile into a FRESH unpredictable dir and
144
+ * wrap with sandbox-exec. The dir sits DIRECTLY under $HOME with a
145
+ * `.zcode-acp-sbx-` prefix — OUTSIDE every whitelisted path (it is a SIBLING
146
+ * of `~/.zcode`, not inside it). That location is the load-bearing defense:
147
+ * $TMPDIR and the cache dirs are agent-writable, and a PRIOR sandboxed
148
+ * generation (a setsid survivor of the old process group) keeps its own
149
+ * profile's allows — so a profile placed there could be raced, symlinked,
150
+ * FIFO'd, or occupied no matter how fresh its name (reproduced across
151
+ * generations even with mkdtemp + O_EXCL + a self-deny, which each generation
152
+ * only applies to its own dir). The agent can also kill the backend at will
153
+ * (signals are not file-writes) to control respawn timing; with the profile
154
+ * unreachable from ANY generation, that primitive buys nothing. O_EXCL ("wx")
155
+ * additionally refuses pre-placed symlinks from a pre-arming process, and
156
+ * the profile still self-denies its own dir last (defense in depth for the
157
+ * workspace-root-is-$HOME edge, where home itself is writable).
89
158
  */
90
- export declare function wrapWithSandbox(argv: string[], profile: string): string[];
159
+ export declare function armSandboxArgv(argv: string[], input: SandboxArmInput): string[];
91
160
  //# sourceMappingURL=sandbox.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/backend/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AASH,uEAAuE;AACvE,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAc/C,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,2EAA2E;IAC3E,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,CAoBtE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAgBnF;AAOD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAsB7C;AAOD,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAC3D,sEAAsE;IACtE,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CA0BlE;AAED,8EAA8E;AAC9E,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,GACzB;IAAE,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAqBtF;AAID;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAevC;AAED,yDAAyD;AACzD,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CASzE"}
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/backend/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAiBH,uEAAuE;AACvE,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAc/C,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB,wEAAwE;IACxE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;OAIG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,2EAA2E;IAC3E,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE/D;AAoCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,CA+EtE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAyBtF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAyBpF;AAOD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAsB7C;AAOD,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAC3D,4EAA4E;IAC5E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAqClE;AAED,8EAA8E;AAC9E,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG;IACpE,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAC3D,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAqBA;AAiBD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAE,QAAQ,CAAC,MAAM,CAAmB,GAAG,OAAO,CAchF;AAED,4DAA4D;AAC5D,wBAAgB,2BAA2B,IAAI,IAAI,CAMlD;AAKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM,EAAE,CAc/E"}