@orcha-ai/runtime-bridge 0.1.38 → 0.1.39
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.
- package/README.md +50 -332
- package/bin/orcha-runtime-bridge.js +21 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,384 +1,102 @@
|
|
|
1
1
|
# Orcha Runtime Bridge
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
agent runtimes outside the Python API process.
|
|
3
|
+
Bridge connects a user's device and discovers Codex, Claude Code and configured OpenClaw agents. Cloud Node Runtime infrastructure is managed separately in `cloud-agent-runtime/` and the Runtime Nodes page.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
third-party ACP package: JSON-RPC framing, request ids, notifications,
|
|
8
|
-
runtime permission requests, and process lifecycle are implemented under
|
|
9
|
-
`src/acp/`.
|
|
5
|
+
## Connect a device
|
|
10
6
|
|
|
11
|
-
|
|
12
|
-
computer
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
runs the bundled Linux Bubblewrap broker probe. Every prompt/dispatch is bound
|
|
16
|
-
to a control-plane `runId` and frozen sandbox policy, and the actual Runtime
|
|
17
|
-
process is started by the broker inside an empty-root namespace. Missing
|
|
18
|
-
Bubblewrap, `prlimit`, Egress Proxy, trusted workspace, or a failed escape probe
|
|
19
|
-
keeps the node visible for diagnostics but unavailable for dispatch. It never
|
|
20
|
-
falls back to spawning Codex/OpenClaw/Claude directly on the host.
|
|
21
|
-
|
|
22
|
-
The broker does not mount `/usr/local` or other operator directories by
|
|
23
|
-
default. Install runtime CLIs under a dedicated immutable directory, list it in
|
|
24
|
-
`ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS`, and repeat it in each target's
|
|
25
|
-
`toolchainRoots`. This keeps the executable surface explicit and avoids
|
|
26
|
-
exposing unrelated host installations or credentials.
|
|
27
|
-
|
|
28
|
-
## Install
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
npm install -g @orcha-ai/runtime-bridge
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Runtime Bridge requires Node.js 22.19 or newer. Managed sandbox execution also
|
|
35
|
-
requires Linux with Bubblewrap, `prlimit`, `ip`, and `socat`. External Runtime
|
|
36
|
-
Nodes execute operator-configured agents directly on Linux, macOS, or Windows.
|
|
37
|
-
An OpenClaw Gateway must separately satisfy its host version's requirements.
|
|
38
|
-
|
|
39
|
-
Run it with:
|
|
7
|
+
1. Open **智能体 → 添加智能体 → 从我的设备添加** in the current tenant.
|
|
8
|
+
2. Install or update the npm package on the computer with your agents installed. Node.js 22.19 or newer is required.
|
|
9
|
+
3. Copy and run the one-time connection command. Bridge starts in the background; the terminal can be closed.
|
|
10
|
+
4. Select discovered agents, confirm names and local directories, then add.
|
|
40
11
|
|
|
41
12
|
```bash
|
|
42
|
-
orcha-runtime-bridge
|
|
13
|
+
npm install -g @orcha-ai/runtime-bridge@latest
|
|
14
|
+
orcha-runtime-bridge connect --url https://orcha.example.com --pair-code ONE_TIME_CODE
|
|
43
15
|
```
|
|
44
16
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
npx @orcha-ai/runtime-bridge
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Build And Pack
|
|
52
|
-
|
|
53
|
-
The bridge is plain Node.js ESM. The build step bundles and minifies the runtime
|
|
54
|
-
CLI into `bin/orcha-runtime-bridge.js`, then prepares a clean release directory.
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
npm run build
|
|
58
|
-
npm run pack:local
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
`npm run build` writes `dist/package`. `npm run pack:local` creates the local
|
|
62
|
-
npm tarball under `dist/`. The release package includes the minified `bin/`
|
|
63
|
-
runtime, the bundled `openclaw-plugin/`, `README.md`, and `.env.example`; it does not publish `src/`, build
|
|
64
|
-
scripts, test scripts, or the local `.env` file.
|
|
65
|
-
|
|
66
|
-
### 0.1.38 Release
|
|
67
|
-
|
|
68
|
-
Updates the Runtime Node registration handshake to `orcha-runtime-node.v2`.
|
|
69
|
-
Deploy this release with the Orcha backend that accepts v2; that backend rejects
|
|
70
|
-
older Bridge clients using v1. The standalone execution protocol remains
|
|
71
|
-
`orcha.runtime-execution/v1`.
|
|
72
|
-
|
|
73
|
-
The npm Bridge package is released separately from the managed Runtime container
|
|
74
|
-
images. After publishing, upgrade each external Runtime Node's installed package
|
|
75
|
-
and reload its Bridge process using the existing env file as described in
|
|
76
|
-
[Background Process](#background-process).
|
|
77
|
-
|
|
78
|
-
After `npm run check`, `npm test`, and `npm run pack:local` succeed, publish the
|
|
79
|
-
prepared tarball from this directory:
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
npm publish ./dist/orcha-ai-runtime-bridge-0.1.38.tgz --access public --registry=https://registry.npmjs.org
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### 0.1.37 Release
|
|
86
|
-
|
|
87
|
-
Packages task-scoped Orcha MCP access for delegated Codex and OpenClaw group
|
|
88
|
-
members, including credential refresh, operation reattachment, cancellation,
|
|
89
|
-
and session cleanup. The tarball includes the bundled OpenClaw Gateway plugin;
|
|
90
|
-
install and configure it as described in [Delegated group member tools](#delegated-group-member-tools).
|
|
91
|
-
Local adapter fixtures cover these integrations; a real OpenClaw Gateway has
|
|
92
|
-
not yet been verified.
|
|
93
|
-
|
|
94
|
-
### 0.1.36 Release
|
|
17
|
+
The code expires after 10 minutes and is consumed once. The device belongs to the signed-in user and tenant. Imported agents are private by default and use existing sharing settings. Shared users still execute on the owner's device.
|
|
95
18
|
|
|
96
|
-
|
|
97
|
-
Each verification check requires a positive integer `requiredMatches` and
|
|
98
|
-
counts distinct successful tool call IDs. Results report `requiredMatches`,
|
|
99
|
-
`observedMatches`, and `toolCallIds` instead of the previous single `toolCallId`.
|
|
100
|
-
Callers and result consumers must use these fields when upgrading from 0.1.35.
|
|
101
|
-
|
|
102
|
-
## Configure
|
|
19
|
+
For subsequent connections, omit the consumed code:
|
|
103
20
|
|
|
104
21
|
```bash
|
|
105
|
-
|
|
106
|
-
# Edit .env and fill ORCHA_RUNTIME_ORCHA_URL / ORCHA_RUNTIME_NODE_TOKEN / targets.
|
|
107
|
-
orcha-runtime-bridge
|
|
22
|
+
orcha-runtime-bridge connect --url https://orcha.example.com
|
|
108
23
|
```
|
|
109
24
|
|
|
110
|
-
|
|
25
|
+
`connect` exchanges the one-time code in the foreground, then starts the existing daemon manager with the saved profile. The code and device credential are not passed to the background command. Reconnecting an already running device returns its existing process; stop it first before replacing its pairing.
|
|
111
26
|
|
|
112
|
-
|
|
113
|
-
forever, or any third-party package.
|
|
27
|
+
Manage the device from any terminal directory with the same server address:
|
|
114
28
|
|
|
115
29
|
```bash
|
|
116
|
-
|
|
117
|
-
orcha-runtime-bridge
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
orcha-runtime-bridge status --env-file /etc/orcha/runtime-node.env
|
|
121
|
-
|
|
122
|
-
# Reload after editing the env file or upgrading the package.
|
|
123
|
-
orcha-runtime-bridge reload --env-file /etc/orcha/runtime-node.env
|
|
124
|
-
|
|
125
|
-
# Stop.
|
|
126
|
-
orcha-runtime-bridge stop --env-file /etc/orcha/runtime-node.env
|
|
30
|
+
orcha-runtime-bridge status --url https://orcha.example.com
|
|
31
|
+
orcha-runtime-bridge reload --url https://orcha.example.com
|
|
32
|
+
orcha-runtime-bridge stop --url https://orcha.example.com
|
|
33
|
+
orcha-runtime-bridge start --url https://orcha.example.com
|
|
127
34
|
```
|
|
128
35
|
|
|
129
|
-
`
|
|
130
|
-
and stderr to `ORCHA_RUNTIME_LOG_FILE`. Both paths can be set in the env file or
|
|
131
|
-
overridden on the command line:
|
|
36
|
+
The server-specific PID and log files live beside the device profile under `~/.orcha/devices/`; `--pid-file` and `--log-file` override them. `status` reports the local process state; the Orcha page reports whether the device is online. Use `connect --foreground --url ...` for diagnosis after stopping its background process. Closing the terminal does not stop the daemon; shutting down the computer does. This command does not install an OS login/startup service. Legacy env-configured `start/status/reload/stop --env-file ...` keep their existing behavior.
|
|
132
37
|
|
|
133
|
-
|
|
134
|
-
orcha-runtime-bridge start \
|
|
135
|
-
--env-file /etc/orcha/runtime-node.env \
|
|
136
|
-
--pid-file /var/run/orcha-runtime-bridge.pid \
|
|
137
|
-
--log-file /var/log/orcha-runtime-bridge.log
|
|
138
|
-
```
|
|
38
|
+
The credential and local launch configuration live under `~/.orcha/devices/<server-hash>.json`, written atomically with mode 0600. A new pairing for the same server replaces that local profile. Disconnect the previous device in Orcha to revoke its credential. Discovery does not upload vendor credentials, command paths, environment maps or transcripts.
|
|
139
39
|
|
|
140
|
-
|
|
141
|
-
which is the right mode for systemd, Docker, launchd, and supervised services.
|
|
40
|
+
Remote deployments require HTTPS; HTTP is allowed only on loopback. Bridge opens an outbound WebSocket to `/api/agent-runtime-bridge/ws`. The device needs no inbound port. The reverse proxy must forward WebSocket upgrades to the Runtime Gateway.
|
|
142
41
|
|
|
143
|
-
|
|
144
|
-
`ORCHA_RUNTIME_LOG_FILE` on start and then once per hour, using each JSON log
|
|
145
|
-
line's `ts` field. Non-JSON lines and lines without a parseable timestamp are
|
|
146
|
-
kept. Configure with:
|
|
42
|
+
## Discovery and execution
|
|
147
43
|
|
|
148
|
-
|
|
149
|
-
ORCHA_RUNTIME_LOG_RETENTION_DAYS=3
|
|
150
|
-
ORCHA_RUNTIME_LOG_CLEANUP_INTERVAL_MS=3600000
|
|
151
|
-
```
|
|
44
|
+
Discovery checks executables in absolute PATH entries and runs fixed probes:
|
|
152
45
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
46
|
+
- Codex: `--version`, `login status`.
|
|
47
|
+
- Claude Code: `--version`, `auth status` (JSON is the default).
|
|
48
|
+
- OpenClaw: `--version`, `agents list --json`, `health --json`.
|
|
156
49
|
|
|
157
|
-
|
|
158
|
-
controls the delay between attempts, and `ORCHA_RUNTIME_CONNECT_TIMEOUT_MS`
|
|
159
|
-
controls how long one WebSocket handshake may wait before the node closes it and
|
|
160
|
-
tries again.
|
|
50
|
+
Missing installations are absent; failed probes are explicit errors. Login and Gateway setup happen locally. Discovery does not install applications, sign in, run a model prompt or scan the entire disk. Detection does not guarantee vendor quota or future model calls.
|
|
161
51
|
|
|
162
|
-
|
|
52
|
+
Codex/Claude Code use a user-selected existing local directory. OpenClaw keeps its existing agent ID and directory; its private session key uses that ID, not Orcha's generated Agent code. Core cannot supply arbitrary launch commands. Every selection and directory is validated before one atomic profile update. Core serializes imports by locking the device credential to prevent duplicate Agents.
|
|
163
53
|
|
|
164
|
-
|
|
54
|
+
Codex device targets use `exec --skip-git-repo-check --json` so ordinary directories work as well as Git repositories. Existing device profiles created without this flag need their Codex target arguments updated locally and Bridge reloaded; updating the npm package alone does not rewrite saved profiles.
|
|
165
55
|
|
|
166
|
-
and
|
|
56
|
+
Targets are namespaced by device code and candidate digest. Chat, group delegation, workflow dispatch and recovery are pinned to that device; an offline or revoked device never falls back to a different computer. External execution uses the local CLI's own permissions, not Orcha's cloud Docker Sandbox.
|
|
167
57
|
|
|
168
|
-
|
|
169
|
-
- `agents/dispatch`
|
|
170
|
-
- `sessions/prompt`
|
|
171
|
-
- `sessions/policy`
|
|
172
|
-
- `sessions/cancel`
|
|
173
|
-
- `permissions/respond`
|
|
58
|
+
The automated discovery path is exercised on macOS/Linux. On Windows, use WSL with the CLIs installed there; native `.cmd`/`.bat` launchers are not supported by the shell-free process adapter.
|
|
174
59
|
|
|
175
|
-
|
|
60
|
+
Official probe references: [Codex CLI](https://developers.openai.com/codex/cli/reference/), [Claude Code CLI](https://code.claude.com/docs/en/cli-reference), [OpenClaw agents](https://docs.openclaw.ai/cli/agents).
|
|
176
61
|
|
|
177
|
-
|
|
178
|
-
created. `ORCHA_RUNTIME_INITIALIZE_TIMEOUT_MS` controls that handshake only
|
|
179
|
-
(30 seconds by default); it is independent from the task/prompt timeout. A
|
|
180
|
-
target can override it with `"initializeTimeoutMs"`. Target processes use
|
|
181
|
-
`cwd`, then `workspace`, then the request workspace as their working directory.
|
|
62
|
+
## Protocol and cutover
|
|
182
63
|
|
|
183
|
-
|
|
184
|
-
Runtime Bridge. In production use separate protected environment files: the
|
|
185
|
-
proxy file contains only its socket, token, and limits; the bridge file contains
|
|
186
|
-
the Node identity plus the matching proxy socket/token. The proxy accepts
|
|
187
|
-
`ORCHA_RUNTIME_EGRESS_PROXY_SOCKET` and `ORCHA_RUNTIME_EGRESS_PROXY_TOKEN`, and
|
|
188
|
-
listens only on that Unix Socket.
|
|
64
|
+
The existing `orcha-runtime-node.v2` transport negotiates `devices/discover` and `devices/configure` alongside execution/session methods. Existing Node and ServiceToken records are reused. Core checks ownership, exact node/candidate identity, target namespace and the returned selections before creating Agents.
|
|
189
65
|
|
|
190
|
-
|
|
191
|
-
orcha-runtime-egress-proxy --env-file /etc/orcha/runtime-egress.env
|
|
192
|
-
orcha-runtime-bridge start --env-file /etc/orcha/runtime-node.env
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
The proxy must run under its own OS account in production. The bridge uses its
|
|
196
|
-
admin token only to create and revoke short-lived Run-bound grants; sandboxed
|
|
197
|
-
commands receive only the individual grant credential. A node whose proxy or
|
|
198
|
-
escape probe is unavailable remains registered for diagnostics but cannot
|
|
199
|
-
receive work.
|
|
200
|
-
|
|
201
|
-
```json
|
|
202
|
-
{
|
|
203
|
-
"codex": {
|
|
204
|
-
"type": "cli",
|
|
205
|
-
"command": "/opt/orcha-runtime-tools/bin/codex",
|
|
206
|
-
"toolchainRoots": ["/opt/orcha-runtime-tools"],
|
|
207
|
-
"args": ["exec", "--json"],
|
|
208
|
-
"promptMode": "stdin",
|
|
209
|
-
"outputMode": "json-lines",
|
|
210
|
-
"workspace": "/workspaces/project-a"
|
|
211
|
-
},
|
|
212
|
-
"openclaw": {
|
|
213
|
-
"type": "openclaw",
|
|
214
|
-
"command": "openclaw",
|
|
215
|
-
"workspace": "/workspaces/project-a",
|
|
216
|
-
"maxSessions": 1,
|
|
217
|
-
"releaseAfterPrompt": true,
|
|
218
|
-
"sessionIdleTtlMs": 60000,
|
|
219
|
-
"mcpServers": []
|
|
220
|
-
},
|
|
221
|
-
"custom-acp": {
|
|
222
|
-
"type": "stdio-acp",
|
|
223
|
-
"command": "node",
|
|
224
|
-
"args": ["/path/to/runtime.js"],
|
|
225
|
-
"framing": "line"
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
```
|
|
66
|
+
Legacy manual external-node registration is rejected. Platform service tokens create only cloud Node Runtime nodes. Arbitrary `runtimeTargetCode` is no longer an Agent creation path. The explicit cleanup procedure is in [智能体管理与构建](../docs/新文档/05-智能体/01-智能体管理与构建.md).
|
|
229
67
|
|
|
230
|
-
|
|
231
|
-
They do not require a Bridge-managed process sandbox and remain dispatchable on
|
|
232
|
-
Linux, macOS, and Windows. Keep target commands, workspaces, credentials, and OS
|
|
233
|
-
permissions under the operator's control.
|
|
234
|
-
|
|
235
|
-
If a request references a missing target, the bridge returns
|
|
236
|
-
`RUNTIME_TARGET_NOT_FOUND`. The built-in `echo` adapter is available only when
|
|
237
|
-
you explicitly configure a target with `"type": "echo"`.
|
|
238
|
-
|
|
239
|
-
Target types:
|
|
240
|
-
|
|
241
|
-
- `stdio-acp`: spawn a runtime process and speak Orcha ACP over stdio JSON-RPC.
|
|
242
|
-
- `openclaw`: built-in `openclaw acp --session ...` command adapter.
|
|
243
|
-
- `cli`: run an independent CLI per prompt and wrap stdout as session updates.
|
|
244
|
-
- `echo`: local test adapter.
|
|
245
|
-
|
|
246
|
-
For `cli` targets, `agents/dispatch` requests are treated as task execution and
|
|
247
|
-
emit only final text by default. Direct `sessions/prompt` requests keep normal
|
|
248
|
-
streaming text for interactive chat. Set `"dispatchFinalTextOnly": false` on a
|
|
249
|
-
target to opt out for task execution, or `"finalTextOnly": true` as the target
|
|
250
|
-
default when a request does not provide its own text-streaming policy.
|
|
251
|
-
|
|
252
|
-
For ACP-compatible targets (`stdio-acp`, `acp`, and `openclaw`), task dispatch
|
|
253
|
-
is treated as one-shot execution and releases the runtime process after each
|
|
254
|
-
completed prompt by default. Direct `sessions/prompt` requests keep the normal
|
|
255
|
-
target lifecycle. Set `"dispatchReleaseAfterPrompt": false` on a target only
|
|
256
|
-
when task dispatch should intentionally reuse the same ACP process.
|
|
257
|
-
|
|
258
|
-
Generic ACP-compatible targets receive `mcpServers` in `session/new`. When
|
|
259
|
-
omitted in target config, the bridge sends an empty array. OpenClaw targets
|
|
260
|
-
always receive an empty `mcpServers` array, because the field is required by the
|
|
261
|
-
ACP schema while OpenClaw bridge mode requires actual MCP servers to be
|
|
262
|
-
configured on the OpenClaw gateway or agent instead.
|
|
263
|
-
|
|
264
|
-
### Delegated group member tools
|
|
265
|
-
|
|
266
|
-
Group delegation uses one independent `runId`, session, and correlation for
|
|
267
|
-
each member task. Its task-scoped Orcha MCP credential grants only that member's
|
|
268
|
-
authorized capabilities. It is kept in memory and refreshed by attaching to the
|
|
269
|
-
existing operation. Lost operations fail explicitly; the Bridge never starts a
|
|
270
|
-
second prompt to simulate recovery. Permission changes cancel the old task;
|
|
271
|
-
native authorization or input pauses are not automatically approved or resumed.
|
|
272
|
-
|
|
273
|
-
For a Codex CLI target, the adapter adds a required HTTP MCP server through
|
|
274
|
-
per-process `-c` configuration and a private loopback proxy. Codex receives a
|
|
275
|
-
temporary proxy credential through `ORCHA_TASK_MCP_TOKEN`; upstream credentials
|
|
276
|
-
remain in Bridge memory. This does not edit the operator's Codex configuration.
|
|
277
|
-
This adapter requires a direct external Runtime Node; its loopback transport is
|
|
278
|
-
not supported inside a Bridge-managed sandbox. See [Codex MCP configuration](https://developers.openai.com/codex/mcp).
|
|
279
|
-
|
|
280
|
-
OpenClaw requires the bundled Gateway tool plugin. Build the Bridge, then install
|
|
281
|
-
the **built** plugin directory on the OpenClaw host:
|
|
68
|
+
## Build and validate
|
|
282
69
|
|
|
283
70
|
```bash
|
|
71
|
+
npm ci
|
|
72
|
+
npm run check
|
|
73
|
+
npm test
|
|
284
74
|
npm run build
|
|
285
|
-
openclaw plugins install /absolute/path/to/runtime-bridge/dist/package/openclaw-plugin
|
|
286
75
|
```
|
|
287
76
|
|
|
288
|
-
|
|
289
|
-
installed plugin entries and allowlists:
|
|
77
|
+
Build produces `bin/orcha-runtime-bridge.js` and the clean npm package in `dist/package`, including the OpenClaw plugin. Bridge is distributed through npm; backend images do not bundle a separate browser download.
|
|
290
78
|
|
|
291
|
-
|
|
292
|
-
{
|
|
293
|
-
"enabled": true,
|
|
294
|
-
"config": { "allowedOrchaMcpUrl": "https://orcha.example.com/api/mcp/orcha" }
|
|
295
|
-
}
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
If plugin or tool allowlists are configured, permit `orcha-runtime` and its four
|
|
299
|
-
`orcha_` tools for the intended OpenClaw Agent. The plugin binds tools only to
|
|
300
|
-
the trusted host `agentId` and task `sessionKey`; ordinary sessions receive none.
|
|
301
|
-
Its manifest declares all four tools and activates the binding route at startup.
|
|
302
|
-
Follow the host's [plugin installation](https://docs.openclaw.ai/cli/plugins/install)
|
|
303
|
-
and [runtime verification](https://docs.openclaw.ai/plugins/building-plugins) steps,
|
|
304
|
-
including loading the new code in the running Gateway. Pin and verify the actual
|
|
305
|
-
host version before enabling dispatch; this package does not claim a tested
|
|
306
|
-
OpenClaw version range yet.
|
|
307
|
-
|
|
308
|
-
Add these fields to the existing OpenClaw Runtime Target:
|
|
309
|
-
|
|
310
|
-
```json
|
|
311
|
-
{
|
|
312
|
-
"type": "openclaw",
|
|
313
|
-
"command": "openclaw",
|
|
314
|
-
"mcpBridgeUrl": "http://127.0.0.1:18789/plugins/orcha-runtime/mcp-bindings",
|
|
315
|
-
"mcpBridgeTokenEnv": "ORCHA_OPENCLAW_GATEWAY_TOKEN"
|
|
316
|
-
}
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
Set `ORCHA_OPENCLAW_GATEWAY_TOKEN` in the Bridge host environment to the Gateway
|
|
320
|
-
authentication credential. The binding URL must reach that same Gateway. Orcha's
|
|
321
|
-
Agent code must match the OpenClaw Agent id. Do not configure a shared fixed
|
|
322
|
-
`--session`: delegated sessions use `agent:<agentCode>:delegation-<runId>`.
|
|
323
|
-
The Gateway credential authorizes binding management; each tool call uses the
|
|
324
|
-
separate, short-lived member credential supplied by Core. Missing configuration,
|
|
325
|
-
rejected credentials, or a lost binding produces an explicit task failure.
|
|
326
|
-
Bindings expire and are released on completion, failure, or cancellation.
|
|
327
|
-
|
|
328
|
-
`npm test` verifies both adapters with local protocol fixtures. An optional real
|
|
329
|
-
Codex check performs a model call using the installed CLI's login and a temporary
|
|
330
|
-
MCP server:
|
|
79
|
+
Version 0.1.39 adds background device pairing and ordinary-directory Codex execution without changing the runtime protocol. Publish this version before deploying the npm onboarding page; deploying Orcha does not publish npm automatically. Build and validate the release tarball before publishing:
|
|
331
80
|
|
|
332
81
|
```bash
|
|
333
|
-
|
|
82
|
+
npm run pack:local
|
|
83
|
+
npm publish ./dist/orcha-ai-runtime-bridge-0.1.39.tgz --access public --registry=https://registry.npmjs.org
|
|
334
84
|
```
|
|
335
85
|
|
|
336
|
-
|
|
337
|
-
acceptance on the configured nodes. This repository does not install the plugin
|
|
338
|
-
or change credentials on remote hosts.
|
|
339
|
-
|
|
340
|
-
OpenClaw targets use request metadata `agentCode` as the local OpenClaw agent
|
|
341
|
-
id, producing sessions like `agent:<agentCode>:<sessionId>`. When `agentCode`
|
|
342
|
-
is missing, the bridge falls back to a plain `orcha-<sessionId>` session.
|
|
343
|
-
|
|
344
|
-
OpenClaw may start browser processes under the hood, so the bridge applies
|
|
345
|
-
stricter defaults for this target type:
|
|
346
|
-
|
|
347
|
-
- `maxSessions`: defaults to `1` for OpenClaw.
|
|
348
|
-
- `releaseAfterPrompt`: defaults to `true` for OpenClaw, stopping the runtime
|
|
349
|
-
process after each prompt.
|
|
350
|
-
- `sessionIdleTtlMs`: defaults to `60000` for OpenClaw.
|
|
86
|
+
After updating the npm package on a device, run `orcha-runtime-bridge reload --url ...` to switch the existing background process to the installed version. The earlier manually downloaded foreground process must be stopped before connecting with npm to avoid duplicate connections.
|
|
351
87
|
|
|
352
|
-
|
|
353
|
-
reports each target's configured capacity, busy sessions, reclaimable idle
|
|
354
|
-
sessions, in-flight reservations, and currently available sessions on every
|
|
355
|
-
heartbeat. Orcha selects a compatible node from that live capacity; the bridge
|
|
356
|
-
still performs the final atomic reservation before starting a runtime.
|
|
88
|
+
Tests cover discovery errors, paths, public-field filtering, immutable commands, exact OpenClaw IDs, atomic configuration, capacity, reconnect, MCP lifecycle and cancellation. The live Codex model test is opt-in; fixtures do not certify a real vendor account or OpenClaw Gateway version.
|
|
357
89
|
|
|
358
|
-
|
|
90
|
+
## Delegated group member tools
|
|
359
91
|
|
|
360
|
-
|
|
361
|
-
ORCHA_RUNTIME_SESSION_IDLE_TTL_MS=600000
|
|
362
|
-
ORCHA_RUNTIME_SESSION_CLEANUP_INTERVAL_MS=60000
|
|
363
|
-
ORCHA_RUNTIME_MAX_SESSIONS_PER_TARGET=8
|
|
364
|
-
ORCHA_RUNTIME_OPENCLAW_SESSION_IDLE_TTL_MS=60000
|
|
365
|
-
ORCHA_RUNTIME_OPENCLAW_MAX_SESSIONS=1
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
Supported stdio framing:
|
|
369
|
-
|
|
370
|
-
- `line`: one JSON-RPC frame per line.
|
|
371
|
-
- `content-length`: `Content-Length: N` headers, compatible with LSP-style stdio transports.
|
|
92
|
+
Codex supports task-scoped Orcha MCP through the existing local transport adapter. OpenClaw additionally requires the bundled Gateway plugin, a trusted binding endpoint and Gateway authentication. Discovery/import does not install the plugin or configure these credentials. Claude Code's delegated dynamic MCP adapter remains unsupported and returns an explicit error.
|
|
372
93
|
|
|
373
|
-
|
|
94
|
+
For OpenClaw, install the built plugin, set `plugins.entries.orcha-runtime.enabled` to `true` and its `config.allowedOrchaMcpUrl` to the Orcha MCP URL. Preserve existing plugins and allowlists, permit the `orcha_` tools for the local Agent, then follow the host version's plugin reload procedure:
|
|
374
95
|
|
|
375
96
|
```bash
|
|
376
|
-
|
|
97
|
+
openclaw plugins install /absolute/path/to/runtime-bridge/dist/package/openclaw-plugin
|
|
377
98
|
```
|
|
378
99
|
|
|
379
|
-
|
|
380
|
-
managed by the host:
|
|
100
|
+
Advanced local target configuration retains `mcpBridgeUrl` (the Gateway `/plugins/orcha-runtime/mcp-bindings` route) and `mcpBridgeTokenEnv` (the existing local environment variable holding Gateway authentication). Configure these in the connected device profile while Bridge is stopped, then reconnect. Tokens stay on the device. Orcha's per-run MCP credential is separate and short-lived. The binding uses the discovered local Agent ID; grants are task-scoped and released on termination. Missing configuration, rejected credentials or a lost binding fails explicitly.
|
|
381
101
|
|
|
382
|
-
|
|
383
|
-
ORCHA_RUNTIME_ENV_FILE=/etc/orcha/runtime-node.env npm start
|
|
384
|
-
```
|
|
102
|
+
The env-configured `run`/`start` commands and HTTP adapter remain for adapter development. They do not authorize legacy manual external nodes to register with current Core; user devices use `connect` or `start --url` with a saved pairing.
|
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{spawn as
|
|
3
|
-
`):""}var
|
|
2
|
+
import{spawn as xa}from"node:child_process";import{closeSync as Ca,existsSync as Gn,mkdirSync as ba,openSync as Aa,readFileSync as sr,rmSync as Na,statSync as Fn,writeFileSync as zn}from"node:fs";import{dirname as Ma,resolve as ar}from"node:path";import{fileURLToPath as Ua}from"node:url";import{createHash as _r}from"node:crypto";import{mkdir as as,readFile as cs,writeFile as us,rename as ls}from"node:fs/promises";import{join as mr}from"node:path";import{homedir as ds,hostname as fs}from"node:os";import{execFile as ts}from"node:child_process";import{access as es,realpath as rs}from"node:fs/promises";import{constants as ns}from"node:fs";import{delimiter as ss,join as fr,isAbsolute as pr}from"node:path";import{homedir as dr}from"node:os";async function is(e,t=process.env){let r=process.platform==="win32"?[".exe",".cmd",".bat",""]:[""];for(let n of(t.PATH||"").split(ss).filter(pr))for(let s of r){let i=fr(n,`${e}${s}`);try{return await es(i,ns.X_OK),i}catch{}}return null}function os(e,t){return new Promise(r=>ts(e,t,{timeout:8e3,maxBuffer:1024*1024,windowsHide:!0},(n,s)=>r({code:n?n.code:0,stdout:String(s||"")})))}async function ne(e){let t=e==="~"?dr():e.startsWith("~/")?fr(dr(),e.slice(2)):e;if(!pr(t))throw new Error("\u5DE5\u4F5C\u76EE\u5F55\u5FC5\u987B\u662F\u8BBE\u5907\u4E0A\u7684\u7EDD\u5BF9\u8DEF\u5F84\u6216 ~/ \u5F00\u5934\u7684\u8DEF\u5F84");let r=await rs(t),{stat:n}=await import("node:fs/promises");if(!(await n(r)).isDirectory())throw new Error("\u5DE5\u4F5C\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6\u5939");return r}async function hr({find:e=is,run:t=os,cwd:r=process.cwd()}={}){return(await Promise.all(["codex","claude","openclaw"].map(async s=>{let i=await e(s);if(!i)return[];let o={codex:"Codex",claude:"Claude Code",openclaw:"OpenClaw"}[s],c=await t(i,["--version"]),l=c.code===0&&c.stdout.match(/\d+\.\d+\.\d+[^\s]*/)?.[0]||"",d={id:s,name:o,framework:s,version:l,workspace:r,managed:!1};if(c.code!==0)return[{...d,status:"error",message:"\u7A0B\u5E8F\u65E0\u6CD5\u542F\u52A8\uFF0C\u8BF7\u5728\u672C\u673A\u68C0\u67E5\u5B89\u88C5"}];if(s==="openclaw"){let h=await t(i,["agents","list","--json"]),g;try{g=JSON.parse(h.stdout)}catch{}if(h.code!==0||!Array.isArray(g))return[{...d,status:"error",message:"\u65E0\u6CD5\u8BFB\u53D6 OpenClaw \u667A\u80FD\u4F53\uFF0C\u8BF7\u68C0\u67E5\u672C\u673A\u914D\u7F6E"}];let y=await t(i,["health","--json"]);return g.filter(R=>typeof R.id=="string"&&typeof R.workspace=="string").slice(0,32).map(R=>({...d,id:`openclaw:${R.id}`,name:R.name||R.identityName||R.id,workspace:R.workspace,managed:!0,localAgentId:R.id,command:i,status:y.code===0?"ready":"needs_setup",message:y.code===0?"":"\u8BF7\u5148\u5728\u672C\u673A\u542F\u52A8\u5E76\u914D\u7F6E OpenClaw Gateway"}))}let f=await t(i,s==="codex"?["login","status"]:["auth","status"]),p=f.code===0?"ready":f.code===1?"needs_login":"error";return[{...d,command:i,status:p,message:p==="needs_login"?`\u8BF7\u5728\u672C\u673A\u8FD0\u884C ${s} ${s==="codex"?"login":"auth login"}`:p==="error"?"\u767B\u5F55\u72B6\u6001\u68C0\u6D4B\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5 CLI \u7248\u672C":""}]}))).flat()}async function gr(e,t){let r=`${e}.${process.pid}.tmp`;await us(r,JSON.stringify(t),{mode:384}),await ls(r,e)}function ie(e){let t=new URL(e);if(t.username||t.password||t.search||t.hash||t.protocol!=="https:"&&!(t.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(t.hostname)))throw new Error("\u8FDE\u63A5\u5730\u5740\u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1B\u4EC5\u672C\u673A\u5F00\u53D1\u5141\u8BB8 HTTP");let r=mr(ds(),".orcha","devices"),n=mr(r,_r("sha256").update(t.toString()).digest("hex").slice(0,20));return{address:t,root:r,profile:`${n}.json`,pidFile:`${n}.pid`,logFile:`${n}.log`}}async function St(e,{url:t,pairCode:r}){let{address:n,root:s,profile:i}=ie(t||e.orchaUrl);await as(s,{recursive:!0,mode:448});let o;if(r){let c=await fetch(new URL("api/agent-devices/pairings/exchange",`${n.toString().replace(/\/+$/,"")}/`),{method:"POST",redirect:"error",headers:{"content-type":"application/json"},signal:AbortSignal.timeout(15e3),body:JSON.stringify({code:r,name:fs()})}),l=await c.json();if(!c.ok||!l.success)throw new Error(l.message||l.detail||"\u8BBE\u5907\u8FDE\u63A5\u5931\u8D25");o={...l.data,targets:{}},await gr(i,o)}else try{o=JSON.parse(await cs(i,"utf8"))}catch{throw new Error("\u6CA1\u6709\u5DF2\u8FDE\u63A5\u8BBE\u5907\uFF0C\u8BF7\u4ECE\u667A\u80FD\u4F53\u9875\u9762\u751F\u6210\u8FDE\u63A5\u7801")}e.orchaUrl=n.toString().replace(/\/+$/,""),e.mode="node",e.nodeId=o.nodeCode,e.nodeName=o.nodeName,e.nodeToken=o.token,e.targets=o.targets,e.defaultTargetCode="",e.deviceConnection=new se(e,o,async()=>gr(i,o))}var se=class{constructor(t,r,n,s=hr){this.config=t,this.profile=r,this.persist=n,this.discover=s}async candidates(){return{candidates:(await this.discover()).map(({command:r,localAgentId:n,...s})=>s)}}async configure(t,r){if(!Array.isArray(t.selections)||!t.selections.length||t.selections.length>32)throw new Error("\u6DFB\u52A0\u9879\u65E0\u6548");let n=new Map((await this.discover()).map(l=>[l.id,l])),s={...r.targets},i=[],o=new Set;for(let l of t.selections){let d=n.get(l.candidateId);if(!d||d.status!=="ready"||o.has(d.id))throw new Error("\u53D1\u73B0\u7ED3\u679C\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u68C0\u6D4B");o.add(d.id);let f=String(l.name||"").trim();if(!f||f.length>128)throw new Error("\u667A\u80FD\u4F53\u540D\u79F0\u65E0\u6548");let p=await ne(String(l.workspace||""));if(d.managed&&p!==await ne(d.workspace))throw new Error("\u5DF2\u6709\u667A\u80FD\u4F53\u5FC5\u987B\u6CBF\u7528\u672C\u673A\u5DE5\u4F5C\u76EE\u5F55");let h=`${this.config.nodeId}:${_r("sha256").update(d.id).digest("hex").slice(0,20)}`;if([...r.sessions.values()].some(g=>g.targetCode===h))throw new Error("\u6B64\u667A\u80FD\u4F53\u4ECD\u6709\u4F1A\u8BDD\uFF0C\u8BF7\u5148\u7ED3\u675F\u4F1A\u8BDD\u518D\u4FEE\u6539\u63A5\u5165");s[h]={name:f,workspace:p,command:d.command,type:d.managed?"openclaw":"cli",...d.managed?{openclawAgentId:d.localAgentId}:d.framework==="codex"?{terminalProtocol:"codex",args:["exec","--skip-git-repo-check","--json"],promptMode:"stdin",outputMode:"json-lines",captureLastMessage:!0}:{terminalProtocol:"claude",args:["-p","--output-format","json","--no-session-persistence"],promptMode:"args",outputMode:"json-lines"}},i.push({candidateId:d.id,name:f,workspace:p,targetCode:h,framework:d.framework})}let c=this.profile.targets;this.profile.targets=s;try{await this.persist()}catch(l){throw this.profile.targets=c,l}return r.targets=s,this.config.targets=s,r.notifyCapacityChanged(),{agents:i}}};import{createHash as Eo,randomUUID as Gt}from"node:crypto";var tt="0.1.39";function dt(){return new Date().toISOString()}function U(e,t=2){return String(e).padStart(t,"0")}function yr(e){let t=e>=0?"+":"-",r=Math.abs(e);return`${t}${U(Math.floor(r/60))}:${U(r%60)}`}function ps(e){let t=-e.getTimezoneOffset();return[`${e.getFullYear()}-${U(e.getMonth()+1)}-${U(e.getDate())}`,`T${U(e.getHours())}:${U(e.getMinutes())}:${U(e.getSeconds())}.${U(e.getMilliseconds(),3)}`,yr(t)].join("")}function hs(e,t){let r=new Intl.DateTimeFormat("en-US",{timeZone:t,hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}),n={};for(let s of r.formatToParts(e))s.type!=="literal"&&(n[s.type]=Number(s.value));return n}function ms(e,t){let r=hs(e,t),n=Date.UTC(r.year,r.month-1,r.day,r.hour,r.minute,r.second,e.getMilliseconds()),s=Math.round((n-e.getTime())/6e4);return[`${r.year}-${U(r.month)}-${U(r.day)}`,`T${U(r.hour)}:${U(r.minute)}:${U(r.second)}.${U(e.getMilliseconds(),3)}`,yr(s)].join("")}function gs(e=new Date){let t=a(process.env.ORCHA_RUNTIME_LOG_TIMEZONE||process.env.TZ||"Asia/Shanghai");try{return ms(e,t)}catch{return ps(e)}}function u(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function a(e){return String(e??"").trim()}function _(e,t){let r=Number.parseInt(String(e??""),10);return Number.isFinite(r)?r:t}function b(e){return Array.isArray(e)?e.map(String):[]}function et(e,t,r=process.cwd()){let n=u(e)?e:{};return a(n.cwd)||a(n.workspace)||a(t)||a(r)||process.cwd()}var Et="[redacted]",_s=/(authorization|api[_-]?key|credential|password|secret|token)/i;function Ot(e){return _s.test(a(e))}function Tr(e,t=[]){let r=String(e??"");for(let n of t){let s=String(n??"");s.length>=4&&(r=r.split(s).join(Et))}return r.replace(/((?:authorization|api[_-]?key|credential|password|secret|token)\s*[:=]\s*)(?:"[^"]*"|'[^']*'|[^\s,;]+)/gi,`$1${Et}`).replace(/([?&](?:api[_-]?key|credential|password|secret|token)=)[^&\s]+/gi,`$1${Et}`)}function V(e,t=new WeakSet){if(e==null)return e;if(typeof e=="bigint")return e.toString();if(typeof e!="object")return e;if(e instanceof Date)return e.toISOString();if(e instanceof Error){if(t.has(e))return"[circular]";t.add(e);let s={name:e.name,message:e.message};e.stack&&(s.stack=e.stack);for(let i of Object.keys(e))s[i]=V(e[i],t);return t.delete(e),s}if(t.has(e))return"[circular]";if(t.add(e),Array.isArray(e)){let s=e.map(i=>V(i,t));return t.delete(e),s}let r={},n=Ot(e.name||e.key);for(let[s,i]of Object.entries(e))r[s]=Ot(s)||n&&s.toLowerCase()==="value"?Et:V(i,t);return t.delete(e),r}function wr(e,t=4e3){let r=JSON.stringify(V(e))??String(e);return!Number.isFinite(t)||r.length<=t?r:`${r.slice(0,t)}...`}function m(e,t,r,n={}){let s={ts:gs(),level:e,module:t,msg:r,...u(n)?V(n):{}};console.error(JSON.stringify(s))}function It(e){return Array.isArray(e)?e.map(t=>u(t)?t.type==="text"?a(t.text):t.type==="file"?a(t.uri):t.type==="image"?a(t.uri):"":"").filter(Boolean).join(`
|
|
3
|
+
`):""}var xt=class{constructor(t){this.agent=t,this.sessionCounter=0}async sessionNew(){return this.sessionCounter+=1,{sessionId:`echo-${this.agent.agentId}-${this.sessionCounter}`}}async sessionPrompt(t,r){let n=It(t.prompt);return r({sessionId:t.sessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:n?`Echo runtime received: ${n}`:"Echo runtime received an empty prompt."}}}),{stopReason:"end_turn"}}async sessionCancel(){return{ok:!0}}};import{spawn as ys}from"node:child_process";var ft="2.0",oe=3e4,Ts=4e3;function Ct(e,t){let r=Object.entries(u(t)?t:{}).filter(([n])=>Ot(n)).map(([,n])=>n);return Tr(e,r)}function ws(e){return{code:Number.isInteger(e?.code)?e.code:-32e3,message:a(e?.message)||String(e),data:u(e?.data)?e.data:void 0}}function Rs(e){if(!u(e))return new Error(String(e||"runtime error"));let t=a(e.message)||"runtime error",r="data"in e?wr(e.data,4e3):"",n=new Error(r?`${t}; data=${r}`:t);return n.rpcCode=e.code,n.data=e.data,n}function Ss(e){return u(e)&&"id"in e&&!("method"in e)}function Es(e){return u(e)&&typeof e.method=="string"&&"id"in e}function Os(e){return u(e)&&typeof e.method=="string"&&!("id"in e)}var bt=class{constructor({command:t,args:r=[],cwd:n,env:s,label:i,framing:o="line",detached:c=!0}){this.command=t,this.args=Array.isArray(r)?r.map(String):[],this.cwd=n||process.cwd(),this.env=u(s)?{...s}:{...process.env},this.label=i||t,this.framing=o==="content-length"?"content-length":"line",this.detached=c!==!1,this.child=null,this.exited=!1,this.exitCode=null,this.exitSignal=null,this.stopPromise=null,this.stderrTail="",this.spawnError=null,this.lineBuffer="",this.headerBuffer=Buffer.alloc(0),this.seq=0,this.pending=new Map,this.notificationHandlers=new Map,this.requestHandlers=new Map,this.exitHandlers=new Set}async start({initialize:t=!0,initializeParams:r={},initializeTimeoutMs:n=oe}={}){if(!(this.child&&!this.exited)&&(this.exited=!1,this.exitCode=null,this.exitSignal=null,this.stderrTail="",this.spawnError=null,this.child=ys(this.command,this.args,{cwd:this.cwd,env:this.env,stdio:["pipe","pipe","pipe"],detached:this.detached}),this.child.stdout.on("data",s=>this.onStdout(s)),this.child.stderr.setEncoding("utf8"),this.child.stderr.on("data",s=>{this.stderrTail=`${this.stderrTail}${s}`.slice(-Ts);let i=Ct(s.trimEnd(),this.env);i&&m("debug","runtime.stderr","runtime stderr",{target:this.label,text:i})}),this.child.on("exit",(s,i)=>this.handleExit(s,i)),this.child.on("error",s=>{this.spawnError=s,this.rejectAll(s)}),t)){let s=Math.max(1,_(n,oe));try{await this.call("initialize",{protocolVersion:1,clientCapabilities:{},...r},s)}catch(i){let o=this.startupFailureDetail(),c=Ct(i?.message||i,this.env);m("warn","runtime.initialize","runtime initialize failed",{target:this.label,timeoutMs:s,cause:c,...o}),await this.stop("initialize failed",{termTimeoutMs:1e3,killTimeoutMs:1e3});let l=o.stderr?`; stderr: ${o.stderr}`:`; command=${o.command}; cwd=${o.cwd}`;throw Object.assign(new Error(`runtime initialize failed: ${c}${l}`,{cause:i}),{code:"RUNTIME_INITIALIZE_FAILED",detail:o})}}}startupFailureDetail(){return{command:this.command,cwd:this.cwd,exited:this.exited,exitCode:this.exitCode,exitSignal:this.exitSignal,...this.spawnError?{spawnError:Ct(this.spawnError.message,this.env)}:{},...this.stderrTail.trim()?{stderr:Ct(this.stderrTail.trim(),this.env)}:{}}}onStdout(t){if(this.framing==="content-length"){this.onContentLengthData(Buffer.isBuffer(t)?t:Buffer.from(t));return}this.onLineData(t.toString("utf8"))}onLineData(t){this.lineBuffer+=t;let r=this.lineBuffer.split(/\r?\n/);this.lineBuffer=r.pop()||"";for(let n of r){let s=n.trim();s&&this.dispatchRaw(s)}}onContentLengthData(t){for(this.headerBuffer=Buffer.concat([this.headerBuffer,t]);this.headerBuffer.length>0;){let r=this.headerBuffer.indexOf(`\r
|
|
4
4
|
\r
|
|
5
|
-
`);if(r<0)return;let s=this.headerBuffer.subarray(0,r).toString("utf8").match(/content-length:\s*(\d+)/i);if(!s){
|
|
5
|
+
`);if(r<0)return;let s=this.headerBuffer.subarray(0,r).toString("utf8").match(/content-length:\s*(\d+)/i);if(!s){m("warn","runtime.protocol","missing Content-Length header",{target:this.label}),this.headerBuffer=Buffer.alloc(0);return}let i=Number.parseInt(s[1],10),o=r+4,c=o+i;if(this.headerBuffer.length<c)return;let l=this.headerBuffer.subarray(o,c).toString("utf8");this.headerBuffer=this.headerBuffer.subarray(c),this.dispatchRaw(l)}}dispatchRaw(t){let r;try{r=JSON.parse(t)}catch(n){m("warn","runtime.protocol","invalid JSON frame",{target:this.label,error:String(n)});return}this.dispatch(r)}dispatch(t){if(Ss(t)){this.resolveResponse(t);return}if(Es(t)){this.handleRequest(t);return}Os(t)&&this.handleNotification(t)}resolveResponse(t){let r=String(t.id),n=this.pending.get(r);n&&(clearTimeout(n.timer),this.pending.delete(r),t.error?(m("warn","runtime.protocol","runtime rpc error",{target:this.label,method:n.method,requestId:r,error:t.error}),n.reject(Rs(t.error))):n.resolve(t.result))}async handleRequest(t){let r=this.requestHandlers.get(t.method);if(!r){this.writeFrame({jsonrpc:ft,id:t.id,error:{code:-32601,message:`method not found: ${t.method}`}});return}try{let n=await r(u(t.params)?t.params:{},t);this.writeFrame({jsonrpc:ft,id:t.id,result:n??{}})}catch(n){this.writeFrame({jsonrpc:ft,id:t.id,error:ws(n)})}}handleNotification(t){let r=this.notificationHandlers.get(t.method);if(r)for(let n of r)n(u(t.params)?t.params:{},t)}call(t,r={},n=oe){if(!this.child||!this.child.stdin||this.exited)return Promise.reject(new Error("runtime process is not running"));let s=`${t}_${++this.seq}`,i={jsonrpc:ft,id:s,method:t,params:r};return new Promise((o,c)=>{let l=setTimeout(()=>{this.pending.delete(s),c(new Error(`${t} timed out after ${n}ms`))},n);this.pending.set(s,{resolve:o,reject:c,timer:l,method:t}),this.writeFrame(i,d=>{d&&(clearTimeout(l),this.pending.delete(s),c(d))})})}notify(t,r={}){this.writeFrame({jsonrpc:ft,method:t,params:r})}writeFrame(t,r){if(!this.child?.stdin||this.exited){r?.(new Error("runtime process is not running"));return}let n=JSON.stringify(t),s=this.framing==="content-length"?`Content-Length: ${Buffer.byteLength(n,"utf8")}\r
|
|
6
6
|
\r
|
|
7
7
|
${n}`:`${n}
|
|
8
|
-
`;this.child.stdin.write(s,r)}onNotification(t,r){let n=this.notificationHandlers.get(t)||new Set;return n.add(r),this.notificationHandlers.set(t,n),()=>{n.delete(r),n.size===0&&this.notificationHandlers.delete(t)}}onRequest(t,r){return this.requestHandlers.set(t,r),()=>this.requestHandlers.delete(t)}onExit(t){return this.exitHandlers.add(t),()=>this.exitHandlers.delete(t)}rejectAll(t){for(let r of this.pending.values())clearTimeout(r.timer),r.reject(t);this.pending.clear()}handleExit(t,r){this.exited=!0,this.exitCode=t,this.exitSignal=r,this.rejectAll(new Error(`runtime exited before response (${t}/${r})`));for(let n of this.exitHandlers)n(t,r)}async waitForExit(t=5e3){return!this.child||this.exited?!0:await new Promise(r=>{let n=setTimeout(()=>{s(),r(!1)},t);n.unref?.();let s=()=>{clearTimeout(n),this.exitHandlers.delete(i)},i=()=>{s(),r(!0)};this.exitHandlers.add(i),this.exited&&i()})}signal(t){if(!this.child||this.exited)return!1;let r=this.child.pid;if(!r)return!1;try{return this.detached&&process.platform!=="win32"?process.kill(-r,t):this.child.kill(t),!0}catch(n){if(n?.code==="ESRCH")return this.exited=!0,!1;try{return this.child.kill(t),!0}catch(s){return s?.code!=="ESRCH"&&h("warn","runtime","runtime signal failed",{target:this.label,pid:r,signal:t,error:String(s)}),!1}}}async stop(t="stop",{termTimeoutMs:r=5e3,killTimeoutMs:n=2e3}={}){if(!(!this.child||this.exited)){if(this.stopPromise)return await this.stopPromise;this.stopPromise=(async()=>{if(!this.child||this.exited)return;let s=this.child.pid;h("info","runtime","stopping runtime",{target:this.label,reason:t,pid:s}),this.rejectAll(new Error(`runtime stopped: ${t}`)),this.signal("SIGTERM"),!await this.waitForExit(r)&&this.child&&!this.exited&&(h("warn","runtime","runtime did not exit after SIGTERM; force killing",{target:this.label,reason:t,pid:s}),this.signal("SIGKILL"),await this.waitForExit(n))})();try{await this.stopPromise}finally{this.stopPromise=null}}}};import{randomUUID as fr}from"node:crypto";import{existsSync as es,readFileSync as rs,realpathSync as ur,statSync as ns}from"node:fs";import{basename as pr,extname as mr,isAbsolute as pt,join as ss,relative as hr,resolve as lr}from"node:path";var is=25*1024*1024;function gr(e,t=""){let r=a(t);if(r)return r;let n=mr(a(e)).toLowerCase();return n===".jpg"||n===".jpeg"?"image/jpeg":n===".webp"?"image/webp":n===".gif"?"image/gif":"image/png"}function _r(e,t){let r=typeof e=="string"?e.trim():"";return!r||r==="<omitted>"?"":r.startsWith("data:")?r:`data:${t};base64,${r.replace(/\s+/g,"")}`}function bt(e){if(Array.isArray(e))return e.map(a).filter(Boolean);let t=a(e);return t?[t]:[]}function os(e,t){let r=hr(t,e);return r===""||!!r&&!r.startsWith("..")&&!pt(r)}function as(e,t){let r=a(e);if(!r||!es(r))return"";try{let n=ur(r);for(let s of t)try{let i=ur(s);if(os(n,i))return n}catch{}}catch{return""}return""}function cs(e,t){let r=a(e);if(!r||!pt(r))return r;for(let n of Array.isArray(t)?t:[]){if(!u(n))continue;let s=a(n.runtimeRoot),i=a(n.hostRoot);if(!s||!i||!pt(s)||!pt(i))continue;let o=hr(lr(s),lr(r));if(o===""||!o.startsWith("..")&&!pt(o))return o?ss(i,o):i}return r}function ee(e,t,r={}){let n=a(e);return!n||n.startsWith("data:")||/^https?:\/\//i.test(n)?n:us(n,t,r)}function us(e,t,r={}){let n=[...bt(r.trustedFileRoots),...bt(r.trustedFileRoot),...bt(r.artifactRoots),...bt(r.artifactRoot)],s=as(cs(e,r.pathMappings),n);if(!s)return"";try{let i=ns(s);return!i.isFile()||i.size<=0||i.size>is?"":`data:${t};base64,${rs(s).toString("base64")}`}catch{return""}}function C(...e){for(let t of e){let r=a(t);if(r)return r}return""}function ls(e,t,r,n){let s=r.toLowerCase();if(s==="image"||s==="picture")return!0;let i=C(n,e.previewUrl,e.fileUrl,e.imageUrl,e.dataUrl,e.url,e.uri,t.previewUrl,t.fileUrl,t.imageUrl,t.dataUrl,t.url,t.uri),o=mr(i.split("?",1)[0].split("#",1)[0]).toLowerCase();return[".png",".jpg",".jpeg",".webp",".gif"].includes(o)}function ne(e,t={}){let{source:r="runtime_image_generation_event"}=t;if(!u(e))return null;let n=u(e.payload)?e.payload:{},s=a(e.type),i=a(n.type);if(!(s==="event_msg"&&i==="image_generation_end"||s==="response_item"&&i==="image_generation_call"))return null;let o=C(n.call_id,n.id),c=C(n.saved_path,n.savedPath),l=C(n.revised_prompt,n.revisedPrompt),d=gr(c,n.mimeType||n.mime_type),f=_r(n.result,d)||ee(c,d,t);if(!f)return null;let p=f.startsWith("data:")?f:"",m=c?pr(c):`${o||fr()}.png`;return{artifactType:"image",type:"image",fieldKey:"image",title:m||"Generated image",summary:l||"Generated image",content:{prompt:l||void 0,dataUrl:p||void 0,imageUrl:f,previewUrl:f,fileUrl:f,mimeType:d},dataUrl:p||void 0,previewUrl:f,fileUrl:f,metadata:{source:r,eventType:i,callId:o||void 0,savedPath:c||void 0,filename:m,mimeType:d,revisedPrompt:l||void 0}}}function ds(e){let t=u(e)?e:{},r=[];for(let n of["_artifacts","artifacts"]){let s=t[n];Array.isArray(s)&&r.push(...s)}for(let n of["_artifact","artifact"]){let s=t[n];u(s)&&r.push(s)}return r}function fs(e,t={}){let{source:r="runtime_artifact"}=t,n=u(e)?e:{};if(!Object.keys(n).length)return null;let s=u(n.content)?{...n.content}:{},i=u(n.metadata)?{...n.metadata}:{},o=C(n.saved_path,n.savedPath,s.saved_path,s.savedPath,i.savedPath),c=C(n.mimeType,n.mime_type,s.mimeType,s.mime_type,i.mimeType),l=C(n.artifactType,n.artifact_type,n.type,n.kind,s.type,o?"image":"file"),d=ls(n,s,l,o),f=d?gr(o,c):c;if(d){let A=C(n.dataUrl,s.dataUrl),T=A.startsWith("data:")?A:"",R=C(n.imageUrl,n.previewUrl,n.fileUrl,n.downloadUrl,n.url,n.uri,s.imageUrl,s.previewUrl,s.fileUrl,s.downloadUrl,s.url,s.uri),w=_r(n.result??s.result,f)||T||ee(o,f,t)||ee(R,f,t);w&&(w.startsWith("data:")&&(s.dataUrl||=w),s.imageUrl||=w,s.previewUrl||=w,s.fileUrl||=w,f&&(s.mimeType||=f))}for(let[A,T]of[["prompt","prompt"],["previewUrl","previewUrl"],["fileUrl","fileUrl"],["downloadUrl","downloadUrl"],["imageUrl","imageUrl"],["dataUrl","dataUrl"],["url","url"],["uri","uri"],["mimeType","mimeType"],["mime_type","mimeType"]]){let R=n[A];R!=null&&R!==""&&!(T in s)&&(s[T]=R)}let p=C(n.fileUrl,n.downloadUrl,n.imageUrl,n.dataUrl,n.url,n.uri,s.fileUrl,s.downloadUrl,s.imageUrl,s.dataUrl,s.url,s.uri),m=C(n.previewUrl,n.imageUrl,n.dataUrl,n.url,n.fileUrl,n.uri,s.previewUrl,s.imageUrl,s.dataUrl,s.url,s.fileUrl,s.uri),g=C(n.dataUrl,s.dataUrl,p.startsWith("data:")?p:"",m.startsWith("data:")?m:""),y=C(n.filename,i.filename,o?pr(o):""),x=C(n.fieldKey,n.field_key,s.fieldKey,i.fieldKey,d?"image":"artifact");return{...n,artifactType:l,type:n.type||l,fieldKey:x,title:C(n.title,y,"Runtime artifact"),summary:C(n.summary,s.prompt,n.title,y,"Runtime artifact"),content:s,dataUrl:g||void 0,fileUrl:p||void 0,previewUrl:m||void 0,metadata:{...i,source:C(i.source,r),savedPath:o||i.savedPath,filename:y||i.filename,mimeType:f||i.mimeType}}}function At(e,t){if(!t||!e)return;let r=u(t.metadata)?t.metadata:{},n=C(r.savedPath,r.callId,t.previewUrl,t.fileUrl)||fr(),s=e.get(n);if(!s){e.set(n,t);return}s.content={...u(s.content)?s.content:{},...u(t.content)?t.content:{}},s.metadata={...u(s.metadata)?s.metadata:{},...r},s.previewUrl=t.previewUrl||s.previewUrl,s.fileUrl=t.fileUrl||s.fileUrl,s.summary=t.summary||s.summary,s.title=t.title||s.title}function re(e,t,r={}){for(let n of ds(e))At(t,fs(n,r))}function se(e){if(!u(e)||!u(e.payload))return u(e)?e:{value:e};let t=a(e.payload.type);if(t!=="image_generation_end"&&t!=="image_generation_call")return e;let r={...e.payload};return typeof r.result=="string"&&r.result&&(r.result="<omitted>",r.resultLength=e.payload.result.length),{...e,payload:r}}function dr(e,t,r){if(!u(e))return e;let n=u(e.event)?e.event:null;return n?(At(t,ne(n,r)),{...e,event:se(n)}):e}function Tr(e,t,r={}){if(!u(e))return e;re(e,t,r);let n=dr(e,t,r),s=u(n.update)?dr(n.update,t,r):null;return s&&s!==n.update&&(n={...n,update:s}),n}function yr(e,t,r={}){let n=u(e)?{...e}:{};re(n,t,r),re(u(n.output)?n.output:{},t,r);let s=[...t?.values?.()||[]];return s.length&&(n._artifacts=s),delete n.artifacts,n}function Rr(e,t){let r=_(e,t);return r>0?r:t}var et=class{constructor(t,r,n={},s={}){this.agent=t,this.target=r,this.callbacks=n,this.options=s,this.proc=null,this.launch=null,this.launchCleanup=null,this.permissionHandlers=new Map}async ensureStarted(){if(this.proc)return;let t=a(this.target.command);if(!t)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let r={command:t,args:b(this.target.args),cwd:tt(this.target,this.agent.workspace),environment:u(this.target.env)?this.target.env:{}},n=this.options.prepareLaunch?await this.options.prepareLaunch(r):{...r,environment:{...process.env,...r.environment},cleanup:async()=>{}};this.launch=n,this.launchCleanup=n.cleanup,this.proc=new Ct({command:n.command,args:n.args,cwd:n.cwd,env:n.environment,label:`${this.agent.agentId}:${this.agent.targetCode}`,framing:a(this.target.framing||"line")}),this.proc.onRequest("session/request_permission",s=>this.handlePermissionRequest(s)),this.proc.onRequest("session/requestPermission",s=>this.handlePermissionRequest(s));try{await this.proc.start({initialize:this.target.initialize!==!1,initializeTimeoutMs:Rr(this.target.initializeTimeoutMs,Rr(this.options.initializeTimeoutMs,3e4)),initializeParams:{clientInfo:{name:"orcha-runtime-bridge",version:Q},...u(this.target.initializeParams)?this.target.initializeParams:{}}})}catch(s){throw await this.proc?.stop("runtime startup failed"),this.proc=null,await this.cleanupLaunch(),s}}async sessionNew(t={}){return await this.ensureStarted(),this.proc.call("session/new",this.sessionNewParams(t))}sessionNewParams(t={}){let r=Array.isArray(t.mcpServers)?t.mcpServers:Array.isArray(this.target.mcpServers)?this.target.mcpServers:[];return{...t,mcpServers:r}}async sessionPrompt(t,r){await this.ensureStarted();let n=a(t.sessionId),s=new Map,i=this.artifactOptions(),o=this.proc.onNotification("session/update",l=>{let d=a(l.sessionId);(!d||d===n)&&r(Tr(l,s,i))}),c=async l=>this.callbacks.onPermissionRequest?.({agent:this.agent,runtimeSessionId:n,request:l,emitUpdate:r})||{outcome:"denied",reason:"permission handler is not configured"};n&&this.permissionHandlers.set(n,c),this.permissionHandlers.set("*",c);try{let l=await this.proc.call("session/prompt",t,this.options.sessionPromptTimeoutMs);return yr(l,s,i)}finally{o(),n&&this.permissionHandlers.delete(n),this.permissionHandlers.delete("*")}}async sessionCancel(t){return await this.ensureStarted(),this.proc.call("session/cancel",t,5e3).catch(()=>({ok:!0}))}async handlePermissionRequest(t){let r=a(t.sessionId),n=this.permissionHandlers.get(r)||this.permissionHandlers.get("*");return n?n(t):{outcome:"denied",reason:"no active Orcha permission handler"}}artifactSource(){return a(this.target.type||"acp")==="openclaw"?"openclaw_image_generation":"acp_runtime_image_generation"}artifactOptions(){let t=u(this.target.env)?this.target.env:{};return{source:this.artifactSource(),trustedFileRoots:[a(this.launch?.artifactDirectory),a(this.launch?.homeDirectory),a(this.target.artifactRoot),a(this.target.artifactDir),a(this.target.runtimeArtifactRoot),a(t.ORCHA_RUNTIME_ARTIFACT_DIR),...b(this.target.trustedArtifactRoots),...b(this.target.trustedFileRoots),...b(this.target.artifactRoots),...b(this.target.artifactFileRoots)].filter(Boolean),pathMappings:Array.isArray(this.launch?.pathMappings)?this.launch.pathMappings:[]}}async stop(t){try{await this.proc?.stop(t)}finally{this.proc=null,await this.cleanupLaunch()}}async cleanupLaunch(){let t=this.launchCleanup;this.launchCleanup=null,this.launch=null,await t?.()}};import{createServer as ps}from"node:http";import{randomBytes as ms}from"node:crypto";var wr=["find_capabilities","describe_capability","execute_capability","inspect_result"],hs=8*1024*1024;function Nt(e,t){if(!Array.isArray(e)||e.length!==1)throw new Error("one task-scoped Orcha MCP server is required");let r=e[0],n=new URL(r.url);if(r.name!=="orcha"||r.type!=="http"||!["http:","https:"].includes(n.protocol)||n.username||n.password||n.hash||t&&n.href!==new URL(t).href)throw new Error("Orcha MCP server does not match the trusted binding");let s=Object.fromEntries((r.headers||[]).map(({name:i,value:o})=>[i.toLowerCase(),o]));if(!String(s.authorization||"").startsWith("Bearer "))throw new Error("Orcha MCP task credentials are missing");return{url:n.href,headers:{...s,"content-type":"application/json",accept:"application/json"}}}async function Er(e){let t=0,r=[];for await(let n of e){if(t+=n.length,t>hs)throw new Error("MCP payload exceeds the size limit");r.push(Buffer.from(n))}return JSON.parse(Buffer.concat(r).toString("utf8"))}async function Or(e,t,r){let n=await fetch(e.url,{method:"POST",headers:e.headers,body:JSON.stringify(t),redirect:"error",signal:AbortSignal.any([AbortSignal.timeout(36e5),...r?[r]:[]])});if(!n.ok)throw new Error(`Orcha MCP request failed (${n.status})`);if(n.status===202||n.status===204)return null;let s=await Er(n.body);if(!s||s.jsonrpc!=="2.0"||s.id!==t.id)throw new Error("Orcha MCP response identity mismatch");return s}async function Sr(e,t){let r=await Or(e,{jsonrpc:"2.0",id:"orcha-bind-tools",method:"tools/list"},t),n=r?.result?.tools;if(r?.error||!Array.isArray(n)||n.length!==wr.length||wr.some(s=>!n.some(i=>i.name===s&&i.inputSchema?.type==="object")))throw new Error("Orcha MCP did not expose its four authorized control tools");return n}async function Ir(e){let t=Nt(e),r=new AbortController;await Sr(t,r.signal);let n=ms(32).toString("hex"),s=ps(async(i,o)=>{if(i.url!=="/mcp"||i.headers.authorization!==`Bearer ${n}`){o.writeHead(403).end();return}if(i.method!=="POST"){o.writeHead(405).end();return}try{let c=await Er(i);if(!c||c.jsonrpc!=="2.0"||typeof c.method!="string")throw new Error("Invalid MCP request");let l=await Or(t,c,r.signal);o.writeHead(l===null?202:200,{"content-type":"application/json"}),o.end(l===null?"":JSON.stringify(l))}catch{o.writeHead(502,{"content-type":"application/json"}).end(JSON.stringify({error:"The task-scoped Orcha MCP connection failed"}))}});return await new Promise((i,o)=>{s.once("error",o),s.listen(0,"127.0.0.1",i)}),{url:`http://127.0.0.1:${s.address().port}/mcp`,token:n,async refresh(i){let o=Nt(i,t.url);await Sr(o,r.signal),t=o},async close(){r.abort(),s.closeAllConnections(),await new Promise(i=>s.close(i))}}}var Mt=class{constructor(t,r){this.target=t,this.identity=r,this.bound=!1}async request(t,r,n=!1){let s=a(this.target.mcpBridgeUrl),i=a(this.target.mcpBridgeTokenEnv),o=this.target.env?.[i]||process.env[i];if(!s||!i||!o)throw Object.assign(new Error("OpenClaw requires the Orcha tool plugin, mcpBridgeUrl and mcpBridgeTokenEnv"),{code:"OPENCLAW_MCP_NOT_CONFIGURED"});let c=new URL(s);if(!["http:","https:"].includes(c.protocol)||c.username||c.password||c.pathname!=="/plugins/orcha-runtime/mcp-bindings"||c.search||c.hash)throw new Error("OpenClaw MCP binding URL must be the trusted Gateway plugin route");let l=await fetch(c,{method:t,redirect:"error",signal:AbortSignal.timeout(3e4),headers:{authorization:`Bearer ${o}`,"content-type":"application/json",...n?{"if-match":this.identity.runId}:{}},body:JSON.stringify(r)});if(!l.ok)throw Object.assign(new Error(`OpenClaw Orcha tool binding failed (${l.status})`),{code:"OPENCLAW_MCP_BINDING_FAILED"})}async bind(t,r=!1){Nt(t),await this.request("PUT",{...this.identity,mcpServer:t[0]},r),this.bound=!0}async close(){this.bound&&(await this.request("DELETE",{runId:this.identity.runId,sessionKey:this.identity.sessionKey}),this.bound=!1)}};function ie(e){let t=u(e.metadata)?e.metadata:{};return a(t.agentCode)}function xr(e,t){let r=ie(e);return r?`agent:${r}:${t}`:`orcha-${t}`}var Ut=class extends et{constructor(t,r,n,s={},i={}){let o=a(n).replace(/[^A-Za-z0-9._-]+/g,"-")||"default",c=a(r.command)||"openclaw",l=Array.isArray(r.args)?r.args.map(String):[],d=l.length>0?l:["acp","--session",xr(t,o)];super(t,{...r,command:c,args:d},s,i),this.boundSessionKey=xr(t,o),this.binding=null}async sessionNew(t={}){if(t.mcpServers?.length&&t.metadata?.source==="conversation_delegation"){let r=[...this.target.args],n=r.indexOf("--session"),s=r.find(l=>l.startsWith("--session=")),i=s?s.slice(10):n<0?null:r[n+1];if(i&&i!==this.boundSessionKey)throw Object.assign(new Error("OpenClaw --session must match this Orcha task's private session"),{code:"OPENCLAW_SESSION_BINDING_CONFLICT"});i===null&&r.push("--session",this.boundSessionKey),this.target.args=r;let o=a(this.options.runId),c=Number(this.options.sandboxPolicy?.maxRuntimeSeconds||this.options.sessionPromptTimeoutMs/1e3||3600);if(!o||!ie(this.agent))throw new Error("OpenClaw MCP requires a trusted task and Agent identity");this.binding=new Mt(this.target,{runId:o,sessionKey:this.boundSessionKey,agentCode:ie(this.agent),expiresAt:new Date(Date.now()+c*1e3).toISOString()}),await this.binding.bind(t.mcpServers)}try{return await super.sessionNew(t)}catch(r){throw await this.binding?.close(),r}}async refreshMcpServers(t){if(!this.binding)throw Object.assign(new Error("The original OpenClaw task binding is unavailable"),{code:"RUNTIME_OPERATION_NOT_FOUND"});await this.binding.bind(t,!0)}async stop(t){try{await super.stop(t)}finally{await this.binding?.close()}}sessionNewParams(t={}){return{...t,mcpServers:[]}}};import{spawn as kr}from"node:child_process";import{randomUUID as rt}from"node:crypto";import{existsSync as Lr,mkdirSync as gs,readdirSync as Dr,readFileSync as vr,realpathSync as ht,rmSync as _s,rmdirSync as Ts,statSync as ys,unlinkSync as Rs}from"node:fs";import{homedir as ws,tmpdir as Hr}from"node:os";import{basename as le,dirname as Ss,join as $,resolve as br}from"node:path";async function Cr(e){let t=await Ir(e),r="ORCHA_TASK_MCP_TOKEN";return{args:["-c",`mcp_servers.orcha={url=${JSON.stringify(t.url)},bearer_token_env_var=${JSON.stringify(r)},required=true}`],environment:{[r]:t.token},refresh:n=>t.refresh(n),close:()=>t.close()}}var Es=36e5,$r=5e3,Os=2*60*1e3,Is=2*60*1e3,xs=12,Cs=1e3,bs=1500,As=1e3,Pt=24*60*60*1e3,mt=new Set(["final_answer","final","complete","completed","done"]),Ns=new Set(["function_call","function_call_output","custom_tool_call","custom_tool_call_output","local_shell_call","local_shell_call_output","mcp_tool_call","mcp_tool_call_output","web_search_call","image_generation_call","image_generation_end"]),Ms=new Set(["context_compacted","context_compaction","context_compressed"]);function Lt(e,t){if(e?.pid){if(process.platform==="win32"){let r=["/PID",String(e.pid),"/T"];t==="SIGKILL"&&r.push("/F");try{kr("taskkill",r,{stdio:"ignore",windowsHide:!0}).unref?.()}catch{try{e.kill(t)}catch{}}return}try{process.kill(-e.pid,t)}catch(r){if(r?.code==="ESRCH")return;try{e.kill(t)}catch{}}}}function oe(e){Lt(e,"SIGTERM");let t=setTimeout(()=>Lt(e,"SIGKILL"),$r);return t.unref?.(),t}function D(e){if(typeof e=="string")return e;if(Array.isArray(e))return e.map(t=>D(t)).join("");if(!u(e))return"";for(let t of["text","delta","output_text","content","message","output"]){let r=D(e[t]);if(r)return r}return""}function Fr(e){if(!u(e))return"";let t=u(e.payload)?e.payload:{};if(a(e.type)==="event_msg"){if(a(t.type)==="agent_message")return a(t.message);if(a(t.type)==="task_complete")return a(t.last_agent_message)}if(a(e.type)==="response_item"&&a(t.type)==="message"&&a(t.role)==="assistant")return D(t.content)||D(t.message);if(a(e.type)==="result")return D(e.result);let r=D(e.delta)||D(e.text)||D(e.content);if(r)return r;let n=u(e.item)?e.item:{};return["message","agent_message"].includes(a(n.type))||a(n.role)==="assistant"?D(n.content)||D(n.text)||D(n.message):""}function Br(e,t={}){return ne(e,{source:"codex_cli_image_generation",...t})}function qr(e,t){At(e.artifacts,t)}function jr(e){return V(se(e))}function de(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type);if(r==="event_msg"&&n==="task_complete")return!0;let s=a(t.phase||t.status||t.stage).toLowerCase();if(r==="event_msg"&&n==="agent_message"||r==="response_item"&&n==="message"&&a(t.role)==="assistant")return mt.has(s);let i=u(e.item)?e.item:{};return r==="item.completed"&&a(i.type)==="agent_message"?!0:r==="result"&&e.is_error!==!0?a(e.result).length>0:!1}function Ar(e){let t=a(e.terminalProtocol||e.eventProtocol).toLowerCase();if(t)return t;let r=le(a(e.command)).replace(/\.exe$/i,"").toLowerCase();return r==="codex"||r==="claude"?r:""}function Nr(e,t,r){let n=u(t.error)?t.error:{},s=a(n.message)||D(t.error)||a(t.result)||a(t.message)||r;return Object.assign(new Error(s),{code:e})}function Us(e,t){if(!u(e))return null;let r=a(e.type).toLowerCase();if(t==="codex")return r==="turn.completed"?{status:"completed",result:{stopReason:"end_turn"}}:r==="turn.failed"?{status:"failed",error:Nr("RUNTIME_CODEX_TURN_FAILED",e,"Codex turn failed")}:null;if(t==="claude"&&r==="result"){let n=a(e.subtype).toLowerCase();return e.is_error===!0||n.startsWith("error")||["failed","failure"].includes(n)?{status:"failed",error:Nr("RUNTIME_CLAUDE_RESULT_FAILED",e,"Claude result failed")}:{status:"completed",result:{stopReason:"end_turn",...a(e.result)?{output:a(e.result)}:{}}}}return null}function Mr(e){return u(e)?a(e.phase||e.status||e.stage).toLowerCase():""}function Ps(e){if(!u(e)||de(e))return!1;let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type),s=Mr(t);if(r==="event_msg"&&n==="agent_message"||r==="response_item"&&n==="message"&&a(t.role)==="assistant")return!!(s&&!mt.has(s));let i=u(e.item)?e.item:{},o=Mr(i);return a(i.role)==="assistant"||a(i.type)==="message"?!!(o&&!mt.has(o)):!1}function ks(e,t,r){return r.captureLastMessage===!1||t.includes("--output-last-message")||t.includes("-o")?!1:r.captureLastMessage===!0?!0:le(e)==="codex"}function Ls(e,t){return t.collectCodexTranscriptArtifacts===!1?!1:t.collectCodexTranscriptArtifacts===!0?!0:le(e)==="codex"}function Kr(e){return Math.max(20,_(e.codexTranscriptPollMs||e.transcriptPollMs,Cs))}function Ds(e){return Math.max(0,_(e.codexFinalOutputWaitMs||e.finalOutputWaitMs,bs))}function Dt(e){if(typeof e=="boolean")return e;let t=a(e).toLowerCase();return["true","1","yes","y","on"].includes(t)?!0:["false","0","no","n","off"].includes(t)?!1:null}function fe(e){let t=u(e?.metadata)?e.metadata:{};return u(t._runtimeBridge)?t._runtimeBridge:{}}function ae(e){return a(fe(e).promptKind).toLowerCase()}function vs(e,t){for(let r of[e.codexTranscriptStreaming,e.streamCodexTranscript]){let n=Dt(r);if(n!=null)return n}return ae(t)==="chat"}function Hs(e,t){let r=fe(e);for(let s of[r.emitThoughtChunks,r.streamThoughts]){let i=Dt(s);if(i!=null)return i}let n=ae(e);if(n&&n!=="chat")return!1;for(let s of[t.emitThoughtChunks,t.streamThoughts]){let i=Dt(s);if(i!=null)return i}return ae(e)==="chat"}function $s(e){let t=fe(e);for(let r of[t.finalTextOnly,t.finalOutputOnly]){let n=Dt(r);if(n!=null)return n}return null}function Fs(e,t){let r=$s(e);return r??(t.finalTextOnly===!0||t.finalOutputOnly===!0?!0:(t.finalTextOnly===!1||t.finalOutputOnly===!1,!1))}function Bs(e,t){return!e.finalTextOnly||t}function Gr(e,t,r,n,s=n){return!n||e.emittedTexts.has(s)?!1:(e.emittedTexts.add(s),r({sessionId:t,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:n}}}),!0)}function zr(e,t,r,n){return!n||e.emittedThoughtTexts.has(n)?!1:(e.emittedThoughtTexts.add(n),r({sessionId:t,update:{sessionUpdate:"agent_thought_chunk",content:{type:"text",text:n}}}),!0)}function qs(e,t,r,n=new Set){return{target:e,promptText:t,startedAtMs:r,baselinePaths:n,matchedPath:"",disabled:!1,processedLines:new Map}}function js(e,t){let r=u(e.env)?e.env:{},n=a(e.artifactRoot||e.artifactDir||e.runtimeArtifactRoot||r.ORCHA_RUNTIME_ARTIFACT_DIR)||$(Hr(),"orcha-runtime-artifacts"),s=a(t).replace(/[^A-Za-z0-9._-]+/g,"-").slice(0,80)||rt(),i=$(n,s),o=$(i,rt());return gs(o,{recursive:!0}),{root:o,realRoot:ht(o),sessionRoot:i,realSessionRoot:ht(i)}}function Ks(e){let t=a(e?.artifactDirectory);if(!t)throw new Error("sandbox launch did not provide an artifact directory");return{root:t,realRoot:ht(t),sessionRoot:"",realSessionRoot:""}}function Vr(e){return a(u(e)?e.root:e)}function Ur(e){let t=Vr(e),r=a(u(e)?e.sessionRoot:Ss(t)),n=a(u(e)?e.realSessionRoot:"");if(r)try{if(n&&ht(r)!==n)return;Ts(r)}catch{}}function Gs(e,t={}){let r=Vr(e),n=a(u(e)?e.realRoot:"");if(r){try{if(n&&ht(r)!==n){h("warn","runtime.cli","runtime artifact directory cleanup skipped; path changed",{...t,artifactRoot:r});return}}catch{Ur(e);return}try{_s(r,{recursive:!0,force:!0})}catch(s){h("warn","runtime.cli","runtime artifact directory cleanup failed",{...t,artifactRoot:r,error:String(s?.message||s)});return}Ur(e)}}function zs(e,t,r=null){return{trustedFileRoots:[t,a(r?.artifactDirectory),a(r?.homeDirectory),...b(e.trustedArtifactRoots),...b(e.trustedFileRoots),...b(e.artifactRoots),...b(e.artifactFileRoots)].filter(Boolean),pathMappings:Array.isArray(r?.pathMappings)?r.pathMappings:[]}}function Wr(e){let t=a(e.codexSessionsRoot||e.codexSessionRoot);if(t)return t;let r=u(e.env)?e.env:{},n=a(e.codexHome||r.CODEX_HOME||process.env.CODEX_HOME)||$(ws(),".codex");return $(n,"sessions")}function Vs(e,t){let r=new Date(t),n=String(r.getFullYear()),s=String(r.getMonth()+1).padStart(2,"0"),i=String(r.getDate()).padStart(2,"0");return $(e,n,s,i)}function Jr(e,t,r){let n=new Set;for(let s of[t-Pt,t,t+Pt,r-Pt,r,r+Pt])n.add(Vs(e,s));return[...n].filter(s=>Lr(s))}function Ws(e,t,r){let n=Wr(e),s=t-Os,i=r+Is,o=[];for(let c of Jr(n,t,r)){let l=[];try{l=Dr(c)}catch{continue}for(let d of l){if(!d.endsWith(".jsonl"))continue;let f=$(c,d);try{let p=ys(f);if(!p.isFile()||p.mtimeMs<s||p.mtimeMs>i)continue;o.push({path:f,mtimeMs:p.mtimeMs})}catch{}}}return o.sort((c,l)=>l.mtimeMs-c.mtimeMs).slice(0,xs)}function Js(e,t,r=t){let n=Wr(e),s=new Set;for(let i of Jr(n,t,r)){let o=[];try{o=Dr(i)}catch{continue}for(let c of o)c.endsWith(".jsonl")&&s.add($(i,c))}return s}function ce(e,t,r=0){if(!(r>8||e===null||e===void 0)){if(typeof e=="string"){e&&t.push(e);return}if(Array.isArray(e)){for(let n of e)ce(n,t,r+1);return}if(u(e))for(let n of["payload","item","text","delta","output_text","content","message","output","input","prompt","last_agent_message","revised_prompt"])n in e&&ce(e[n],t,r+1)}}function Xr(e){return a(e).replace(/\s+/g," ")}function Xs(e){let t=Xr(e);if(!t)return[];if(t.length<=200)return[t];let r=160,n=[0,Math.floor((t.length-r)/2),t.length-r],s=new Set,i=[];for(let o of n){let c=t.slice(Math.max(0,o),Math.max(0,o)+r).trim();c.length>=40&&!s.has(c)&&(s.add(c),i.push(c))}return i}function Ys(e,t){let r=Xs(t);if(!r.length)return!1;let n=[];for(let i of e)ce(i,n);let s=Xr(n.join(" "));return r.every(i=>s.includes(i))}function Zs(e){return e.find(t=>u(t)&&a(t.type)==="session_meta"&&u(t.payload))||null}function Qs(e){let t=u(e?.payload)?e.payload:{},r=a(e?.timestamp||t.timestamp),n=Date.parse(r);return Number.isFinite(n)?n:Number.NaN}function ti(e){let t=a(e.originator),r=a(e.source);if(t!=="codex_exec"&&r!=="exec"||a(e.parent_thread_id))return!1;let n=a(e.thread_source);if(n&&n!=="user")return!1;let s=a(e.session_id),i=a(e.id);return!(s&&i&&s!==i)}function ei(e,t,r){if(!Ys(e,t.promptText))return!1;let n=Zs(e);if(!n)return!1;let s=n.payload;if(!ti(s))return!1;let i=Qs(n);if(!Number.isFinite(i)||i<t.startedAtMs-5e3||i>r+5e3)return!1;let o=a(t.target.cwd),c=a(s.cwd);return!(o&&c&&br(o)!==br(c))}function Pr(e){try{return ni(vr(e,"utf8"))}catch{return null}}function ri(e,t,r){if(!e||e.disabled)return null;if(e.matchedPath){let s=Pr(e.matchedPath);return s?{path:e.matchedPath,events:s}:null}let n=[];for(let s of Ws(e.target,e.startedAtMs,r)){if(e.baselinePaths.has(s.path))continue;let i=Pr(s.path);!i||!ei(i,e,r)||n.push({path:s.path,events:i})}return n.length!==1?(n.length>1&&(e.disabled=!0,h("warn","runtime.cli","codex transcript fallback disabled; multiple matching transcripts",{target:e.target.targetCode,sessionId:t,transcriptCount:n.length})),null):(e.matchedPath=n[0].path,h("info","runtime.cli","codex transcript stream attached",{target:e.target.targetCode,sessionId:t}),n[0])}function ni(e){let t=[];for(let r of e.split(/\r?\n/)){let n=r.trim();if(n)try{t.push(JSON.parse(n))}catch{}}return t}function si(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type);return r==="event_msg"&&n==="image_generation_end"||r==="response_item"&&n==="image_generation_call"}function ii(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{};return a(e.type)==="response_item"&&Ns.has(a(t.type))}function oi(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{};return Ms.has(a(t.type))}function ai(e,t,r,n){let s=Fr(e),i=de(e),o=0,c=0,l=0;if(s&&!i&&t.emitThoughtChunks&&zr(t,r,n,s)&&(l=1),s&&i){let d=t.emittedTexts.size?`
|
|
8
|
+
`;this.child.stdin.write(s,r)}onNotification(t,r){let n=this.notificationHandlers.get(t)||new Set;return n.add(r),this.notificationHandlers.set(t,n),()=>{n.delete(r),n.size===0&&this.notificationHandlers.delete(t)}}onRequest(t,r){return this.requestHandlers.set(t,r),()=>this.requestHandlers.delete(t)}onExit(t){return this.exitHandlers.add(t),()=>this.exitHandlers.delete(t)}rejectAll(t){for(let r of this.pending.values())clearTimeout(r.timer),r.reject(t);this.pending.clear()}handleExit(t,r){this.exited=!0,this.exitCode=t,this.exitSignal=r,this.rejectAll(new Error(`runtime exited before response (${t}/${r})`));for(let n of this.exitHandlers)n(t,r)}async waitForExit(t=5e3){return!this.child||this.exited?!0:await new Promise(r=>{let n=setTimeout(()=>{s(),r(!1)},t);n.unref?.();let s=()=>{clearTimeout(n),this.exitHandlers.delete(i)},i=()=>{s(),r(!0)};this.exitHandlers.add(i),this.exited&&i()})}signal(t){if(!this.child||this.exited)return!1;let r=this.child.pid;if(!r)return!1;try{return this.detached&&process.platform!=="win32"?process.kill(-r,t):this.child.kill(t),!0}catch(n){if(n?.code==="ESRCH")return this.exited=!0,!1;try{return this.child.kill(t),!0}catch(s){return s?.code!=="ESRCH"&&m("warn","runtime","runtime signal failed",{target:this.label,pid:r,signal:t,error:String(s)}),!1}}}async stop(t="stop",{termTimeoutMs:r=5e3,killTimeoutMs:n=2e3}={}){if(!(!this.child||this.exited)){if(this.stopPromise)return await this.stopPromise;this.stopPromise=(async()=>{if(!this.child||this.exited)return;let s=this.child.pid;m("info","runtime","stopping runtime",{target:this.label,reason:t,pid:s}),this.rejectAll(new Error(`runtime stopped: ${t}`)),this.signal("SIGTERM"),!await this.waitForExit(r)&&this.child&&!this.exited&&(m("warn","runtime","runtime did not exit after SIGTERM; force killing",{target:this.label,reason:t,pid:s}),this.signal("SIGKILL"),await this.waitForExit(n))})();try{await this.stopPromise}finally{this.stopPromise=null}}}};import{randomUUID as Or}from"node:crypto";import{existsSync as Is,readFileSync as xs,realpathSync as Rr,statSync as Cs}from"node:fs";import{basename as Ir,extname as xr,isAbsolute as pt,join as bs,relative as Cr,resolve as Sr}from"node:path";var As=25*1024*1024;function br(e,t=""){let r=a(t);if(r)return r;let n=xr(a(e)).toLowerCase();return n===".jpg"||n===".jpeg"?"image/jpeg":n===".webp"?"image/webp":n===".gif"?"image/gif":"image/png"}function Ar(e,t){let r=typeof e=="string"?e.trim():"";return!r||r==="<omitted>"?"":r.startsWith("data:")?r:`data:${t};base64,${r.replace(/\s+/g,"")}`}function At(e){if(Array.isArray(e))return e.map(a).filter(Boolean);let t=a(e);return t?[t]:[]}function Ns(e,t){let r=Cr(t,e);return r===""||!!r&&!r.startsWith("..")&&!pt(r)}function Ms(e,t){let r=a(e);if(!r||!Is(r))return"";try{let n=Rr(r);for(let s of t)try{let i=Rr(s);if(Ns(n,i))return n}catch{}}catch{return""}return""}function Us(e,t){let r=a(e);if(!r||!pt(r))return r;for(let n of Array.isArray(t)?t:[]){if(!u(n))continue;let s=a(n.runtimeRoot),i=a(n.hostRoot);if(!s||!i||!pt(s)||!pt(i))continue;let o=Cr(Sr(s),Sr(r));if(o===""||!o.startsWith("..")&&!pt(o))return o?bs(i,o):i}return r}function ae(e,t,r={}){let n=a(e);return!n||n.startsWith("data:")||/^https?:\/\//i.test(n)?n:Ps(n,t,r)}function Ps(e,t,r={}){let n=[...At(r.trustedFileRoots),...At(r.trustedFileRoot),...At(r.artifactRoots),...At(r.artifactRoot)],s=Ms(Us(e,r.pathMappings),n);if(!s)return"";try{let i=Cs(s);return!i.isFile()||i.size<=0||i.size>As?"":`data:${t};base64,${xs(s).toString("base64")}`}catch{return""}}function C(...e){for(let t of e){let r=a(t);if(r)return r}return""}function ks(e,t,r,n){let s=r.toLowerCase();if(s==="image"||s==="picture")return!0;let i=C(n,e.previewUrl,e.fileUrl,e.imageUrl,e.dataUrl,e.url,e.uri,t.previewUrl,t.fileUrl,t.imageUrl,t.dataUrl,t.url,t.uri),o=xr(i.split("?",1)[0].split("#",1)[0]).toLowerCase();return[".png",".jpg",".jpeg",".webp",".gif"].includes(o)}function ue(e,t={}){let{source:r="runtime_image_generation_event"}=t;if(!u(e))return null;let n=u(e.payload)?e.payload:{},s=a(e.type),i=a(n.type);if(!(s==="event_msg"&&i==="image_generation_end"||s==="response_item"&&i==="image_generation_call"))return null;let o=C(n.call_id,n.id),c=C(n.saved_path,n.savedPath),l=C(n.revised_prompt,n.revisedPrompt),d=br(c,n.mimeType||n.mime_type),f=Ar(n.result,d)||ae(c,d,t);if(!f)return null;let p=f.startsWith("data:")?f:"",h=c?Ir(c):`${o||Or()}.png`;return{artifactType:"image",type:"image",fieldKey:"image",title:h||"Generated image",summary:l||"Generated image",content:{prompt:l||void 0,dataUrl:p||void 0,imageUrl:f,previewUrl:f,fileUrl:f,mimeType:d},dataUrl:p||void 0,previewUrl:f,fileUrl:f,metadata:{source:r,eventType:i,callId:o||void 0,savedPath:c||void 0,filename:h,mimeType:d,revisedPrompt:l||void 0}}}function Ls(e){let t=u(e)?e:{},r=[];for(let n of["_artifacts","artifacts"]){let s=t[n];Array.isArray(s)&&r.push(...s)}for(let n of["_artifact","artifact"]){let s=t[n];u(s)&&r.push(s)}return r}function Ds(e,t={}){let{source:r="runtime_artifact"}=t,n=u(e)?e:{};if(!Object.keys(n).length)return null;let s=u(n.content)?{...n.content}:{},i=u(n.metadata)?{...n.metadata}:{},o=C(n.saved_path,n.savedPath,s.saved_path,s.savedPath,i.savedPath),c=C(n.mimeType,n.mime_type,s.mimeType,s.mime_type,i.mimeType),l=C(n.artifactType,n.artifact_type,n.type,n.kind,s.type,o?"image":"file"),d=ks(n,s,l,o),f=d?br(o,c):c;if(d){let A=C(n.dataUrl,s.dataUrl),T=A.startsWith("data:")?A:"",w=C(n.imageUrl,n.previewUrl,n.fileUrl,n.downloadUrl,n.url,n.uri,s.imageUrl,s.previewUrl,s.fileUrl,s.downloadUrl,s.url,s.uri),S=Ar(n.result??s.result,f)||T||ae(o,f,t)||ae(w,f,t);S&&(S.startsWith("data:")&&(s.dataUrl||=S),s.imageUrl||=S,s.previewUrl||=S,s.fileUrl||=S,f&&(s.mimeType||=f))}for(let[A,T]of[["prompt","prompt"],["previewUrl","previewUrl"],["fileUrl","fileUrl"],["downloadUrl","downloadUrl"],["imageUrl","imageUrl"],["dataUrl","dataUrl"],["url","url"],["uri","uri"],["mimeType","mimeType"],["mime_type","mimeType"]]){let w=n[A];w!=null&&w!==""&&!(T in s)&&(s[T]=w)}let p=C(n.fileUrl,n.downloadUrl,n.imageUrl,n.dataUrl,n.url,n.uri,s.fileUrl,s.downloadUrl,s.imageUrl,s.dataUrl,s.url,s.uri),h=C(n.previewUrl,n.imageUrl,n.dataUrl,n.url,n.fileUrl,n.uri,s.previewUrl,s.imageUrl,s.dataUrl,s.url,s.fileUrl,s.uri),g=C(n.dataUrl,s.dataUrl,p.startsWith("data:")?p:"",h.startsWith("data:")?h:""),y=C(n.filename,i.filename,o?Ir(o):""),R=C(n.fieldKey,n.field_key,s.fieldKey,i.fieldKey,d?"image":"artifact");return{...n,artifactType:l,type:n.type||l,fieldKey:R,title:C(n.title,y,"Runtime artifact"),summary:C(n.summary,s.prompt,n.title,y,"Runtime artifact"),content:s,dataUrl:g||void 0,fileUrl:p||void 0,previewUrl:h||void 0,metadata:{...i,source:C(i.source,r),savedPath:o||i.savedPath,filename:y||i.filename,mimeType:f||i.mimeType}}}function Nt(e,t){if(!t||!e)return;let r=u(t.metadata)?t.metadata:{},n=C(r.savedPath,r.callId,t.previewUrl,t.fileUrl)||Or(),s=e.get(n);if(!s){e.set(n,t);return}s.content={...u(s.content)?s.content:{},...u(t.content)?t.content:{}},s.metadata={...u(s.metadata)?s.metadata:{},...r},s.previewUrl=t.previewUrl||s.previewUrl,s.fileUrl=t.fileUrl||s.fileUrl,s.summary=t.summary||s.summary,s.title=t.title||s.title}function ce(e,t,r={}){for(let n of Ls(e))Nt(t,Ds(n,r))}function le(e){if(!u(e)||!u(e.payload))return u(e)?e:{value:e};let t=a(e.payload.type);if(t!=="image_generation_end"&&t!=="image_generation_call")return e;let r={...e.payload};return typeof r.result=="string"&&r.result&&(r.result="<omitted>",r.resultLength=e.payload.result.length),{...e,payload:r}}function Er(e,t,r){if(!u(e))return e;let n=u(e.event)?e.event:null;return n?(Nt(t,ue(n,r)),{...e,event:le(n)}):e}function Nr(e,t,r={}){if(!u(e))return e;ce(e,t,r);let n=Er(e,t,r),s=u(n.update)?Er(n.update,t,r):null;return s&&s!==n.update&&(n={...n,update:s}),n}function Mr(e,t,r={}){let n=u(e)?{...e}:{};ce(n,t,r),ce(u(n.output)?n.output:{},t,r);let s=[...t?.values?.()||[]];return s.length&&(n._artifacts=s),delete n.artifacts,n}function Ur(e,t){let r=_(e,t);return r>0?r:t}var rt=class{constructor(t,r,n={},s={}){this.agent=t,this.target=r,this.callbacks=n,this.options=s,this.proc=null,this.launch=null,this.launchCleanup=null,this.permissionHandlers=new Map}async ensureStarted(){if(this.proc)return;let t=a(this.target.command);if(!t)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let r={command:t,args:b(this.target.args),cwd:et(this.target,this.agent.workspace),environment:u(this.target.env)?this.target.env:{}},n=this.options.prepareLaunch?await this.options.prepareLaunch(r):{...r,environment:{...process.env,...r.environment},cleanup:async()=>{}};this.launch=n,this.launchCleanup=n.cleanup,this.proc=new bt({command:n.command,args:n.args,cwd:n.cwd,env:n.environment,label:`${this.agent.agentId}:${this.agent.targetCode}`,framing:a(this.target.framing||"line")}),this.proc.onRequest("session/request_permission",s=>this.handlePermissionRequest(s)),this.proc.onRequest("session/requestPermission",s=>this.handlePermissionRequest(s));try{await this.proc.start({initialize:this.target.initialize!==!1,initializeTimeoutMs:Ur(this.target.initializeTimeoutMs,Ur(this.options.initializeTimeoutMs,3e4)),initializeParams:{clientInfo:{name:"orcha-runtime-bridge",version:tt},...u(this.target.initializeParams)?this.target.initializeParams:{}}})}catch(s){throw await this.proc?.stop("runtime startup failed"),this.proc=null,await this.cleanupLaunch(),s}}async sessionNew(t={}){return await this.ensureStarted(),this.proc.call("session/new",this.sessionNewParams(t))}sessionNewParams(t={}){let r=Array.isArray(t.mcpServers)?t.mcpServers:Array.isArray(this.target.mcpServers)?this.target.mcpServers:[];return{...t,mcpServers:r}}async sessionPrompt(t,r){await this.ensureStarted();let n=a(t.sessionId),s=new Map,i=this.artifactOptions(),o=this.proc.onNotification("session/update",l=>{let d=a(l.sessionId);(!d||d===n)&&r(Nr(l,s,i))}),c=async l=>this.callbacks.onPermissionRequest?.({agent:this.agent,runtimeSessionId:n,request:l,emitUpdate:r})||{outcome:"denied",reason:"permission handler is not configured"};n&&this.permissionHandlers.set(n,c),this.permissionHandlers.set("*",c);try{let l=await this.proc.call("session/prompt",t,this.options.sessionPromptTimeoutMs);return Mr(l,s,i)}finally{o(),n&&this.permissionHandlers.delete(n),this.permissionHandlers.delete("*")}}async sessionCancel(t){return await this.ensureStarted(),this.proc.call("session/cancel",t,5e3).catch(()=>({ok:!0}))}async handlePermissionRequest(t){let r=a(t.sessionId),n=this.permissionHandlers.get(r)||this.permissionHandlers.get("*");return n?n(t):{outcome:"denied",reason:"no active Orcha permission handler"}}artifactSource(){return a(this.target.type||"acp")==="openclaw"?"openclaw_image_generation":"acp_runtime_image_generation"}artifactOptions(){let t=u(this.target.env)?this.target.env:{};return{source:this.artifactSource(),trustedFileRoots:[a(this.launch?.artifactDirectory),a(this.launch?.homeDirectory),a(this.target.artifactRoot),a(this.target.artifactDir),a(this.target.runtimeArtifactRoot),a(t.ORCHA_RUNTIME_ARTIFACT_DIR),...b(this.target.trustedArtifactRoots),...b(this.target.trustedFileRoots),...b(this.target.artifactRoots),...b(this.target.artifactFileRoots)].filter(Boolean),pathMappings:Array.isArray(this.launch?.pathMappings)?this.launch.pathMappings:[]}}async stop(t){try{await this.proc?.stop(t)}finally{this.proc=null,await this.cleanupLaunch()}}async cleanupLaunch(){let t=this.launchCleanup;this.launchCleanup=null,this.launch=null,await t?.()}};import{createServer as vs}from"node:http";import{randomBytes as Hs}from"node:crypto";var Pr=["find_capabilities","describe_capability","execute_capability","inspect_result"],$s=8*1024*1024;function Mt(e,t){if(!Array.isArray(e)||e.length!==1)throw new Error("one task-scoped Orcha MCP server is required");let r=e[0],n=new URL(r.url);if(r.name!=="orcha"||r.type!=="http"||!["http:","https:"].includes(n.protocol)||n.username||n.password||n.hash||t&&n.href!==new URL(t).href)throw new Error("Orcha MCP server does not match the trusted binding");let s=Object.fromEntries((r.headers||[]).map(({name:i,value:o})=>[i.toLowerCase(),o]));if(!String(s.authorization||"").startsWith("Bearer "))throw new Error("Orcha MCP task credentials are missing");return{url:n.href,headers:{...s,"content-type":"application/json",accept:"application/json"}}}async function Lr(e){let t=0,r=[];for await(let n of e){if(t+=n.length,t>$s)throw new Error("MCP payload exceeds the size limit");r.push(Buffer.from(n))}return JSON.parse(Buffer.concat(r).toString("utf8"))}async function Dr(e,t,r){let n=await fetch(e.url,{method:"POST",headers:e.headers,body:JSON.stringify(t),redirect:"error",signal:AbortSignal.any([AbortSignal.timeout(36e5),...r?[r]:[]])});if(!n.ok)throw new Error(`Orcha MCP request failed (${n.status})`);if(n.status===202||n.status===204)return null;let s=await Lr(n.body);if(!s||s.jsonrpc!=="2.0"||s.id!==t.id)throw new Error("Orcha MCP response identity mismatch");return s}async function kr(e,t){let r=await Dr(e,{jsonrpc:"2.0",id:"orcha-bind-tools",method:"tools/list"},t),n=r?.result?.tools;if(r?.error||!Array.isArray(n)||n.length!==Pr.length||Pr.some(s=>!n.some(i=>i.name===s&&i.inputSchema?.type==="object")))throw new Error("Orcha MCP did not expose its four authorized control tools");return n}async function vr(e){let t=Mt(e),r=new AbortController;await kr(t,r.signal);let n=Hs(32).toString("hex"),s=vs(async(i,o)=>{if(i.url!=="/mcp"||i.headers.authorization!==`Bearer ${n}`){o.writeHead(403).end();return}if(i.method!=="POST"){o.writeHead(405).end();return}try{let c=await Lr(i);if(!c||c.jsonrpc!=="2.0"||typeof c.method!="string")throw new Error("Invalid MCP request");let l=await Dr(t,c,r.signal);o.writeHead(l===null?202:200,{"content-type":"application/json"}),o.end(l===null?"":JSON.stringify(l))}catch{o.writeHead(502,{"content-type":"application/json"}).end(JSON.stringify({error:"The task-scoped Orcha MCP connection failed"}))}});return await new Promise((i,o)=>{s.once("error",o),s.listen(0,"127.0.0.1",i)}),{url:`http://127.0.0.1:${s.address().port}/mcp`,token:n,async refresh(i){let o=Mt(i,t.url);await kr(o,r.signal),t=o},async close(){r.abort(),s.closeAllConnections(),await new Promise(i=>s.close(i))}}}var Ut=class{constructor(t,r){this.target=t,this.identity=r,this.bound=!1}async request(t,r,n=!1){let s=a(this.target.mcpBridgeUrl),i=a(this.target.mcpBridgeTokenEnv),o=this.target.env?.[i]||process.env[i];if(!s||!i||!o)throw Object.assign(new Error("OpenClaw requires the Orcha tool plugin, mcpBridgeUrl and mcpBridgeTokenEnv"),{code:"OPENCLAW_MCP_NOT_CONFIGURED"});let c=new URL(s);if(!["http:","https:"].includes(c.protocol)||c.username||c.password||c.pathname!=="/plugins/orcha-runtime/mcp-bindings"||c.search||c.hash)throw new Error("OpenClaw MCP binding URL must be the trusted Gateway plugin route");let l=await fetch(c,{method:t,redirect:"error",signal:AbortSignal.timeout(3e4),headers:{authorization:`Bearer ${o}`,"content-type":"application/json",...n?{"if-match":this.identity.runId}:{}},body:JSON.stringify(r)});if(!l.ok)throw Object.assign(new Error(`OpenClaw Orcha tool binding failed (${l.status})`),{code:"OPENCLAW_MCP_BINDING_FAILED"})}async bind(t,r=!1){Mt(t),await this.request("PUT",{...this.identity,mcpServer:t[0]},r),this.bound=!0}async close(){this.bound&&(await this.request("DELETE",{runId:this.identity.runId,sessionKey:this.identity.sessionKey}),this.bound=!1)}};function de(e){let t=u(e.metadata)?e.metadata:{};return a(t.agentCode)}function Hr(e,t,r){let n=a(r?.openclawAgentId)||de(e);return n?`agent:${n}:${t}`:`orcha-${t}`}var Pt=class extends rt{constructor(t,r,n,s={},i={}){let o=a(n).replace(/[^A-Za-z0-9._-]+/g,"-")||"default",c=a(r.command)||"openclaw",l=Array.isArray(r.args)?r.args.map(String):[],d=l.length>0?l:["acp","--session",Hr(t,o,r)];super(t,{...r,command:c,args:d},s,i),this.boundSessionKey=Hr(t,o,r),this.binding=null}async sessionNew(t={}){if(t.mcpServers?.length&&t.metadata?.source==="conversation_delegation"){let r=[...this.target.args],n=r.indexOf("--session"),s=r.find(l=>l.startsWith("--session=")),i=s?s.slice(10):n<0?null:r[n+1];if(i&&i!==this.boundSessionKey)throw Object.assign(new Error("OpenClaw --session must match this Orcha task's private session"),{code:"OPENCLAW_SESSION_BINDING_CONFLICT"});i===null&&r.push("--session",this.boundSessionKey),this.target.args=r;let o=a(this.options.runId),c=Number(this.options.sandboxPolicy?.maxRuntimeSeconds||this.options.sessionPromptTimeoutMs/1e3||3600);if(!o||!de(this.agent))throw new Error("OpenClaw MCP requires a trusted task and Agent identity");this.binding=new Ut(this.target,{runId:o,sessionKey:this.boundSessionKey,agentCode:a(this.target.openclawAgentId)||de(this.agent),expiresAt:new Date(Date.now()+c*1e3).toISOString()}),await this.binding.bind(t.mcpServers)}try{return await super.sessionNew(t)}catch(r){throw await this.binding?.close(),r}}async refreshMcpServers(t){if(!this.binding)throw Object.assign(new Error("The original OpenClaw task binding is unavailable"),{code:"RUNTIME_OPERATION_NOT_FOUND"});await this.binding.bind(t,!0)}async stop(t){try{await super.stop(t)}finally{await this.binding?.close()}}sessionNewParams(t={}){return{...t,mcpServers:[]}}};import{spawn as zr}from"node:child_process";import{randomUUID as nt}from"node:crypto";import{existsSync as Vr,mkdirSync as Fs,readdirSync as Jr,readFileSync as Wr,realpathSync as mt,rmSync as Bs,rmdirSync as qs,statSync as js,unlinkSync as Ks}from"node:fs";import{homedir as Gs,tmpdir as Xr}from"node:os";import{basename as ge,dirname as zs,join as $,resolve as Fr}from"node:path";async function $r(e){let t=await vr(e),r="ORCHA_TASK_MCP_TOKEN";return{args:["-c",`mcp_servers.orcha={url=${JSON.stringify(t.url)},bearer_token_env_var=${JSON.stringify(r)},required=true}`],environment:{[r]:t.token},refresh:n=>t.refresh(n),close:()=>t.close()}}var Vs=36e5,Yr=5e3,Js=2*60*1e3,Ws=2*60*1e3,Xs=12,Ys=1e3,Zs=1500,Qs=1e3,kt=24*60*60*1e3,ht=new Set(["final_answer","final","complete","completed","done"]),ti=new Set(["function_call","function_call_output","custom_tool_call","custom_tool_call_output","local_shell_call","local_shell_call_output","mcp_tool_call","mcp_tool_call_output","web_search_call","image_generation_call","image_generation_end"]),ei=new Set(["context_compacted","context_compaction","context_compressed"]);function Dt(e,t){if(e?.pid){if(process.platform==="win32"){let r=["/PID",String(e.pid),"/T"];t==="SIGKILL"&&r.push("/F");try{zr("taskkill",r,{stdio:"ignore",windowsHide:!0}).unref?.()}catch{try{e.kill(t)}catch{}}return}try{process.kill(-e.pid,t)}catch(r){if(r?.code==="ESRCH")return;try{e.kill(t)}catch{}}}}function fe(e){Dt(e,"SIGTERM");let t=setTimeout(()=>Dt(e,"SIGKILL"),Yr);return t.unref?.(),t}function D(e){if(typeof e=="string")return e;if(Array.isArray(e))return e.map(t=>D(t)).join("");if(!u(e))return"";for(let t of["text","delta","output_text","content","message","output"]){let r=D(e[t]);if(r)return r}return""}function Zr(e){if(!u(e))return"";let t=u(e.payload)?e.payload:{};if(a(e.type)==="event_msg"){if(a(t.type)==="agent_message")return a(t.message);if(a(t.type)==="task_complete")return a(t.last_agent_message)}if(a(e.type)==="response_item"&&a(t.type)==="message"&&a(t.role)==="assistant")return D(t.content)||D(t.message);if(a(e.type)==="result")return D(e.result);let r=D(e.delta)||D(e.text)||D(e.content);if(r)return r;let n=u(e.item)?e.item:{};return["message","agent_message"].includes(a(n.type))||a(n.role)==="assistant"?D(n.content)||D(n.text)||D(n.message):""}function Qr(e,t={}){return ue(e,{source:"codex_cli_image_generation",...t})}function tn(e,t){Nt(e.artifacts,t)}function en(e){return V(le(e))}function _e(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type);if(r==="event_msg"&&n==="task_complete")return!0;let s=a(t.phase||t.status||t.stage).toLowerCase();if(r==="event_msg"&&n==="agent_message"||r==="response_item"&&n==="message"&&a(t.role)==="assistant")return ht.has(s);let i=u(e.item)?e.item:{};return r==="item.completed"&&a(i.type)==="agent_message"?!0:r==="result"&&e.is_error!==!0?a(e.result).length>0:!1}function Br(e){let t=a(e.terminalProtocol||e.eventProtocol).toLowerCase();if(t)return t;let r=ge(a(e.command)).replace(/\.exe$/i,"").toLowerCase();return r==="codex"||r==="claude"?r:""}function qr(e,t,r){let n=u(t.error)?t.error:{},s=a(n.message)||D(t.error)||a(t.result)||a(t.message)||r;return Object.assign(new Error(s),{code:e})}function ri(e,t){if(!u(e))return null;let r=a(e.type).toLowerCase();if(t==="codex")return r==="turn.completed"?{status:"completed",result:{stopReason:"end_turn"}}:r==="turn.failed"?{status:"failed",error:qr("RUNTIME_CODEX_TURN_FAILED",e,"Codex turn failed")}:null;if(t==="claude"&&r==="result"){let n=a(e.subtype).toLowerCase();return e.is_error===!0||n.startsWith("error")||["failed","failure"].includes(n)?{status:"failed",error:qr("RUNTIME_CLAUDE_RESULT_FAILED",e,"Claude result failed")}:{status:"completed",result:{stopReason:"end_turn",...a(e.result)?{output:a(e.result)}:{}}}}return null}function jr(e){return u(e)?a(e.phase||e.status||e.stage).toLowerCase():""}function ni(e){if(!u(e)||_e(e))return!1;let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type),s=jr(t);if(r==="event_msg"&&n==="agent_message"||r==="response_item"&&n==="message"&&a(t.role)==="assistant")return!!(s&&!ht.has(s));let i=u(e.item)?e.item:{},o=jr(i);return a(i.role)==="assistant"||a(i.type)==="message"?!!(o&&!ht.has(o)):!1}function si(e,t,r){return r.captureLastMessage===!1||t.includes("--output-last-message")||t.includes("-o")?!1:r.captureLastMessage===!0?!0:ge(e)==="codex"}function ii(e,t){return t.collectCodexTranscriptArtifacts===!1?!1:t.collectCodexTranscriptArtifacts===!0?!0:ge(e)==="codex"}function rn(e){return Math.max(20,_(e.codexTranscriptPollMs||e.transcriptPollMs,Ys))}function oi(e){return Math.max(0,_(e.codexFinalOutputWaitMs||e.finalOutputWaitMs,Zs))}function vt(e){if(typeof e=="boolean")return e;let t=a(e).toLowerCase();return["true","1","yes","y","on"].includes(t)?!0:["false","0","no","n","off"].includes(t)?!1:null}function ye(e){let t=u(e?.metadata)?e.metadata:{};return u(t._runtimeBridge)?t._runtimeBridge:{}}function pe(e){return a(ye(e).promptKind).toLowerCase()}function ai(e,t){for(let r of[e.codexTranscriptStreaming,e.streamCodexTranscript]){let n=vt(r);if(n!=null)return n}return pe(t)==="chat"}function ci(e,t){let r=ye(e);for(let s of[r.emitThoughtChunks,r.streamThoughts]){let i=vt(s);if(i!=null)return i}let n=pe(e);if(n&&n!=="chat")return!1;for(let s of[t.emitThoughtChunks,t.streamThoughts]){let i=vt(s);if(i!=null)return i}return pe(e)==="chat"}function ui(e){let t=ye(e);for(let r of[t.finalTextOnly,t.finalOutputOnly]){let n=vt(r);if(n!=null)return n}return null}function li(e,t){let r=ui(e);return r??(t.finalTextOnly===!0||t.finalOutputOnly===!0?!0:(t.finalTextOnly===!1||t.finalOutputOnly===!1,!1))}function di(e,t){return!e.finalTextOnly||t}function nn(e,t,r,n,s=n){return!n||e.emittedTexts.has(s)?!1:(e.emittedTexts.add(s),r({sessionId:t,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:n}}}),!0)}function sn(e,t,r,n){return!n||e.emittedThoughtTexts.has(n)?!1:(e.emittedThoughtTexts.add(n),r({sessionId:t,update:{sessionUpdate:"agent_thought_chunk",content:{type:"text",text:n}}}),!0)}function fi(e,t,r,n=new Set){return{target:e,promptText:t,startedAtMs:r,baselinePaths:n,matchedPath:"",disabled:!1,processedLines:new Map}}function pi(e,t){let r=u(e.env)?e.env:{},n=a(e.artifactRoot||e.artifactDir||e.runtimeArtifactRoot||r.ORCHA_RUNTIME_ARTIFACT_DIR)||$(Xr(),"orcha-runtime-artifacts"),s=a(t).replace(/[^A-Za-z0-9._-]+/g,"-").slice(0,80)||nt(),i=$(n,s),o=$(i,nt());return Fs(o,{recursive:!0}),{root:o,realRoot:mt(o),sessionRoot:i,realSessionRoot:mt(i)}}function hi(e){let t=a(e?.artifactDirectory);if(!t)throw new Error("sandbox launch did not provide an artifact directory");return{root:t,realRoot:mt(t),sessionRoot:"",realSessionRoot:""}}function on(e){return a(u(e)?e.root:e)}function Kr(e){let t=on(e),r=a(u(e)?e.sessionRoot:zs(t)),n=a(u(e)?e.realSessionRoot:"");if(r)try{if(n&&mt(r)!==n)return;qs(r)}catch{}}function mi(e,t={}){let r=on(e),n=a(u(e)?e.realRoot:"");if(r){try{if(n&&mt(r)!==n){m("warn","runtime.cli","runtime artifact directory cleanup skipped; path changed",{...t,artifactRoot:r});return}}catch{Kr(e);return}try{Bs(r,{recursive:!0,force:!0})}catch(s){m("warn","runtime.cli","runtime artifact directory cleanup failed",{...t,artifactRoot:r,error:String(s?.message||s)});return}Kr(e)}}function gi(e,t,r=null){return{trustedFileRoots:[t,a(r?.artifactDirectory),a(r?.homeDirectory),...b(e.trustedArtifactRoots),...b(e.trustedFileRoots),...b(e.artifactRoots),...b(e.artifactFileRoots)].filter(Boolean),pathMappings:Array.isArray(r?.pathMappings)?r.pathMappings:[]}}function an(e){let t=a(e.codexSessionsRoot||e.codexSessionRoot);if(t)return t;let r=u(e.env)?e.env:{},n=a(e.codexHome||r.CODEX_HOME||process.env.CODEX_HOME)||$(Gs(),".codex");return $(n,"sessions")}function _i(e,t){let r=new Date(t),n=String(r.getFullYear()),s=String(r.getMonth()+1).padStart(2,"0"),i=String(r.getDate()).padStart(2,"0");return $(e,n,s,i)}function cn(e,t,r){let n=new Set;for(let s of[t-kt,t,t+kt,r-kt,r,r+kt])n.add(_i(e,s));return[...n].filter(s=>Vr(s))}function yi(e,t,r){let n=an(e),s=t-Js,i=r+Ws,o=[];for(let c of cn(n,t,r)){let l=[];try{l=Jr(c)}catch{continue}for(let d of l){if(!d.endsWith(".jsonl"))continue;let f=$(c,d);try{let p=js(f);if(!p.isFile()||p.mtimeMs<s||p.mtimeMs>i)continue;o.push({path:f,mtimeMs:p.mtimeMs})}catch{}}}return o.sort((c,l)=>l.mtimeMs-c.mtimeMs).slice(0,Xs)}function Ti(e,t,r=t){let n=an(e),s=new Set;for(let i of cn(n,t,r)){let o=[];try{o=Jr(i)}catch{continue}for(let c of o)c.endsWith(".jsonl")&&s.add($(i,c))}return s}function he(e,t,r=0){if(!(r>8||e===null||e===void 0)){if(typeof e=="string"){e&&t.push(e);return}if(Array.isArray(e)){for(let n of e)he(n,t,r+1);return}if(u(e))for(let n of["payload","item","text","delta","output_text","content","message","output","input","prompt","last_agent_message","revised_prompt"])n in e&&he(e[n],t,r+1)}}function un(e){return a(e).replace(/\s+/g," ")}function wi(e){let t=un(e);if(!t)return[];if(t.length<=200)return[t];let r=160,n=[0,Math.floor((t.length-r)/2),t.length-r],s=new Set,i=[];for(let o of n){let c=t.slice(Math.max(0,o),Math.max(0,o)+r).trim();c.length>=40&&!s.has(c)&&(s.add(c),i.push(c))}return i}function Ri(e,t){let r=wi(t);if(!r.length)return!1;let n=[];for(let i of e)he(i,n);let s=un(n.join(" "));return r.every(i=>s.includes(i))}function Si(e){return e.find(t=>u(t)&&a(t.type)==="session_meta"&&u(t.payload))||null}function Ei(e){let t=u(e?.payload)?e.payload:{},r=a(e?.timestamp||t.timestamp),n=Date.parse(r);return Number.isFinite(n)?n:Number.NaN}function Oi(e){let t=a(e.originator),r=a(e.source);if(t!=="codex_exec"&&r!=="exec"||a(e.parent_thread_id))return!1;let n=a(e.thread_source);if(n&&n!=="user")return!1;let s=a(e.session_id),i=a(e.id);return!(s&&i&&s!==i)}function Ii(e,t,r){if(!Ri(e,t.promptText))return!1;let n=Si(e);if(!n)return!1;let s=n.payload;if(!Oi(s))return!1;let i=Ei(n);if(!Number.isFinite(i)||i<t.startedAtMs-5e3||i>r+5e3)return!1;let o=a(t.target.cwd),c=a(s.cwd);return!(o&&c&&Fr(o)!==Fr(c))}function Gr(e){try{return Ci(Wr(e,"utf8"))}catch{return null}}function xi(e,t,r){if(!e||e.disabled)return null;if(e.matchedPath){let s=Gr(e.matchedPath);return s?{path:e.matchedPath,events:s}:null}let n=[];for(let s of yi(e.target,e.startedAtMs,r)){if(e.baselinePaths.has(s.path))continue;let i=Gr(s.path);!i||!Ii(i,e,r)||n.push({path:s.path,events:i})}return n.length!==1?(n.length>1&&(e.disabled=!0,m("warn","runtime.cli","codex transcript fallback disabled; multiple matching transcripts",{target:e.target.targetCode,sessionId:t,transcriptCount:n.length})),null):(e.matchedPath=n[0].path,m("info","runtime.cli","codex transcript stream attached",{target:e.target.targetCode,sessionId:t}),n[0])}function Ci(e){let t=[];for(let r of e.split(/\r?\n/)){let n=r.trim();if(n)try{t.push(JSON.parse(n))}catch{}}return t}function bi(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type);return r==="event_msg"&&n==="image_generation_end"||r==="response_item"&&n==="image_generation_call"}function Ai(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{};return a(e.type)==="response_item"&&ti.has(a(t.type))}function Ni(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{};return ei.has(a(t.type))}function Mi(e,t,r,n){let s=Zr(e),i=_e(e),o=0,c=0,l=0;if(s&&!i&&t.emitThoughtChunks&&sn(t,r,n,s)&&(l=1),s&&i){let d=t.emittedTexts.size?`
|
|
9
9
|
|
|
10
|
-
${s}`:s;
|
|
11
|
-
`,at,M,o,r);let H=await
|
|
12
|
-
`}}})}}}async sessionCancel(t){let r=a(t.sessionId),n=this.active.get(r);return n?(
|
|
13
|
-
`)}function en(e,t,r=""){if(!rn(e))return e==null?null:{required:!0,status:"failed",outcome:a(e?.outcome),goalContractHash:"",checks:[],errorCode:"invalid_goal_contract"};let n=xe(e),s=e.verificationPlan.required===!0;if(a(r)&&a(r)!==n)return{required:s,status:"failed",outcome:e.outcome,goalContractHash:n,checks:[],errorCode:"goal_contract_hash_mismatch"};if(!s)return{required:!1,status:"not_required",outcome:e.outcome,goalContractHash:n,checks:[]};let i=Si(t),o=e.verificationPlan.checks.map(l=>Ai(l,i));return{required:!0,status:o.some(l=>l.status==="failed")?"failed":o.some(l=>l.status==="missing")?"missing":"passed",outcome:e.outcome,goalContractHash:n,checks:o}}function rn(e){if(!u(e)||e.schemaVersion!==Ti||!a(e.outcome))return!1;let t=e.verificationPlan;if(!u(t)||typeof t.required!="boolean"||!Array.isArray(t.checks)||t.required&&t.checks.length===0)return!1;let r=new Set;for(let n of t.checks)if(!u(n)||!a(n.id)||r.has(a(n.id))||(r.add(a(n.id)),!Array.isArray(n.toolNames)||n.toolNames.length===0||n.toolNames.some(s=>!a(s)))||!Number.isSafeInteger(n.requiredMatches)||n.requiredMatches<1||n.arguments!==void 0&&!u(n.arguments))return!1;return!0}function Si(e){let t=new Map,r=[];for(let n of Array.isArray(e)?e:[]){let s=u(n?.update)?n.update:{},i=a(s.sessionUpdate);if(i==="runtime_event"){Ei(s.event,t,r);continue}if(i==="tool_call"){let o=$t(s)||`tool-${r.length+1}`,c=Ht(t,r,o),l=Oe(s,s.name||s.toolName||s.kind);c.toolName=l.toolName,c.arguments=l.arguments,c.status=gt(s.status),c.evidence=Bt(s);continue}if(i==="tool_call_update"){let o=$t(s);if(!o)continue;let c=Ht(t,r,o),l=Oe(s,s.name||s.toolName||s.kind);c.toolName||=l.toolName,Object.keys(c.arguments).length===0&&(c.arguments=l.arguments),c.status=gt(s.status),c.evidence.push(...Bt(s))}}return r}function Ei(e,t,r){let n=u(e)&&u(e.payload)?e.payload:u(e)?e:{},s=a(n.type);if(["function_call","custom_tool_call","local_shell_call","mcp_tool_call"].includes(s)){let c=$t(n)||`runtime-${r.length+1}`,l=Ht(t,r,c),d=Oe(n,n.name||n.tool||s,s);l.toolName=d.toolName,l.arguments=d.arguments,l.status=gt(n.status),l.evidence.push(...Bt(n));return}if(!["function_call_output","custom_tool_call_output","local_shell_call_output","mcp_tool_call_output"].includes(s))return;let i=$t(n);if(!i)return;let o=Ht(t,r,i);o.status=Ci(n,o.toolName),o.evidence.push(...Bt(n))}function Ht(e,t,r){let n=e.get(r);return n||(n={toolCallId:r,toolName:"",arguments:{},status:"unknown",evidence:[]},e.set(r,n),t.push(n)),n}function Oi(e){let t=a(e).toLowerCase();return wi.get(t)||t}function Oe(e,t,r=""){let n=Ii(e),s=a(r)==="mcp_tool_call"||a(e?.kind).toLowerCase()==="mcp",i=u(e?._meta)?e._meta:{},o=a(e?.server||e?.serverName||e?.server_name||e?.mcpServer||i.server||i.serverName).toLowerCase();if(s&&o==="orcha"){let c=a(e?.tool||e?.toolName||e?.name||t);return{toolName:"plugin_operation",arguments:{...n,...c?{operationCode:c}:{}}}}return{toolName:Oi(t),arguments:n}}function $t(e){return u(e)?a(e.call_id||e.callId||e.toolCallId||e.id):""}function Ii(e){if(!u(e))return{};for(let r of["arguments","args","rawInput","input","params","parameters"]){let n=xi(e[r]);if(n)return n}let t={};for(let r of["cmd","command","cwd","operationCode","path","query","url"])e[r]!==void 0&&(t[r]=e[r]);return t}function xi(e){if(u(e))return structuredClone(e);if(typeof e!="string")return null;try{let t=JSON.parse(e);return u(t)?t:null}catch{return null}}function Ci(e,t){if(!u(e))return"unknown";let r=Ft(e,0,{parseCliExitCode:t==="run_command"||t==="apply_patch"});return r.includes("failed")?"failed":r.includes("success")?"success":"unknown"}function Ft(e,t=0,r={}){if(t>8||e===null||e===void 0)return[];if(typeof e=="string")return bi(e,t,r);if(Array.isArray(e))return e.flatMap(o=>Ft(o,t+1,r));if(!u(e))return[];let n=[];typeof e.isError=="boolean"&&n.push(e.isError?"failed":"success"),typeof e.ok=="boolean"&&n.push(e.ok?"success":"failed"),typeof e.success=="boolean"&&n.push(e.success?"success":"failed");let s=gt(e.status);s!=="unknown"&&n.push(s);let i=e.exitCode??e.exit_code;typeof i=="number"&&Number.isFinite(i)&&n.push(i===0?"success":"failed");for(let o of["output","result","structuredContent","content"])e[o]!==void 0&&n.push(...Ft(e[o],t+1,r));return n}function bi(e,t,r){let n=e.trim();if(!n)return[];try{return Ft(JSON.parse(n),t+1,r)}catch{}if(r.parseCliExitCode!==!0)return[];let s=[];for(let i of n.matchAll(/(?:process\s+exited\s+with\s+code|exit\s+code\s*:?)\s*(-?\d+)/gi))s.push(Number(i[1])===0?"success":"failed");return s}function gt(e){let t=a(e).toLowerCase();return yi.has(t)?"success":Ri.has(t)?"failed":"unknown"}function Bt(e){if(!u(e))return[];let t=u(e.output)?e.output:{},r=[e.verificationEvidence,u(e.verification)?e.verification.evidence:null,t.verificationEvidence,u(t.verification)?t.verification.evidence:null],n=[];for(let s of r)for(let i of Array.isArray(s)?s:s?[s]:[])!u(i)||!a(i.id)||n.push({id:a(i.id),status:gt(i.status??(i.passed===!0?"passed":i.passed===!1?"failed":"")),...a(i.message)?{message:a(i.message)}:{}});return n}function Ai(e,t){let r=t.filter(o=>e.toolNames.includes(o.toolName)&&Ie(e.arguments||{},o.arguments)),n=a(e.evidenceId),s=r.filter(o=>o.status==="success"&&(!n||o.evidence.some(c=>c.id===n&&c.status==="success")));if(s.length>=e.requiredMatches)return Ee(e,"passed",s,`Runtime tool evidence passed ${s.length} times.`);let i=r.filter(o=>o.status==="failed"||n&&o.evidence.some(c=>c.id===n&&c.status==="failed"));return s.length===0&&i.length?Ee(e,"failed",i,"Runtime tool evidence failed."):Ee(e,"missing",s,`Only ${s.length}/${e.requiredMatches} required tool executions passed.`)}function Ee(e,t,r,n){let s=r.map(i=>i.toolCallId).filter(Boolean);return{id:e.id,status:t,message:n,...a(e.description)?{description:a(e.description)}:{},toolNames:e.toolNames,requiredMatches:e.requiredMatches,observedMatches:s.length,toolCallIds:s,...u(e.arguments)?{arguments:e.arguments}:{},...a(e.evidenceId)?{evidenceId:a(e.evidenceId)}:{}}}function Ie(e,t){return Array.isArray(e)?Array.isArray(t)&&e.length===t.length&&e.every((r,n)=>Ie(r,t[n])):u(e)?u(t)?Object.entries(e).every(([r,n])=>Object.hasOwn(t,r)&&Ie(n,t[r])):!1:Object.is(e,t)}function q(e){if(e===null||typeof e=="boolean")return JSON.stringify(e);if(typeof e=="string")return Qr(e);if(typeof e=="number"){if(!Number.isFinite(e))throw new Error("invalid_jcs_number");return JSON.stringify(Object.is(e,-0)?0:e)}if(Array.isArray(e))return`[${Array.from({length:e.length},(t,r)=>{if(!Object.hasOwn(e,r))throw new Error("invalid_jcs_json_value");return q(e[r])}).join(",")}]`;if(u(e))return`{${Object.keys(e).sort().map(t=>`${Qr(t)}:${q(e[t])}`).join(",")}}`;throw new Error("invalid_jcs_json_value")}function Qr(e){return Ni(e),JSON.stringify(e)}function Ni(e){for(let t=0;t<e.length;t+=1){let r=e.charCodeAt(t);if(r>=55296&&r<=56319){let n=e.charCodeAt(t+1);if(!(n>=56320&&n<=57343))throw new Error("invalid_jcs_unicode");t+=1}else if(r>=56320&&r<=57343)throw new Error("invalid_jcs_unicode")}}import{spawn as Mi}from"node:child_process";import{createHash as Ui,randomUUID as Pi}from"node:crypto";import{constants as ki}from"node:fs";import{access as Li,mkdir as Ce,readdir as Di,realpath as _t,rm as vi,stat as Hi}from"node:fs/promises";import $i from"node:http";import{tmpdir as Fi}from"node:os";import{isAbsolute as Tt,join as nt,relative as nn,resolve as Ae}from"node:path";var Ne=1,Bi="orcha.process-isolation/v1",Me="orcha.egress-proxy/v1",qi="--disable-wasm-trap-handler",qt={read_only:0,workspace_write:1,workspace_network:2},be={read_only:["read_only","denied"],workspace_write:["workspace_write","denied"],workspace_network:["workspace_write","restricted"]},ji=new Set([".env",".git-credentials",".netrc",".npmrc",".pypirc","credentials.json","secrets.json","id_rsa","id_ed25519"]);function W(e){if(!u(e))throw S("RUNTIME_SANDBOX_POLICY_REQUIRED","sandboxPolicy is required");let t=structuredClone(e),r=a(t.accessMode),n=a(t.accessModeCeiling);if(!(r in be)||!(n in be))throw S("RUNTIME_SANDBOX_POLICY_INVALID","unsupported runtime access mode");if(qt[r]>qt[n])throw S("RUNTIME_SANDBOX_POLICY_INVALID","access mode exceeds its ceiling");let[s,i]=be[r];if(t.filesystemMode!==s||t.networkMode!==i)throw S("RUNTIME_SANDBOX_POLICY_INVALID","runtime access profile does not match its mode");if(Number(t.policySchemaVersion)!==Ne||!Number.isInteger(Number(t.policyRevision))||Number(t.policyRevision)<1)throw S("RUNTIME_SANDBOX_POLICY_INVALID","unsupported sandbox policy schema or revision");for(let[c,l]of Object.entries({outsideWorkspaceAccess:"denied",hostAccess:"denied",hostEnvironmentAccess:"denied",dockerSocketAccess:"denied",environmentMode:"allowlist"}))if(t[c]!==l)throw S("RUNTIME_SANDBOX_POLICY_INVALID",`${c} cannot be relaxed`);let o=u(t.processIsolation)?t.processIsolation:{};if(o.mode!=="required"||o.backend==="direct")throw S("RUNTIME_SANDBOX_POLICY_INVALID","strong process isolation is required");if(Array.isArray(t.alwaysApprovedApprovalKeys)&&t.alwaysApprovedApprovalKeys.length)throw S("RUNTIME_SANDBOX_POLICY_INVALID","persistent runtime approvals are forbidden");return t}function sn(e,t){let r=W(e),n=W(t);return qt[n.accessMode]<qt[r.accessMode]}async function on(e){if(!e.sandboxRequired)return{dispatchable:!0,enforced:!1,backend:"direct",daemonStatus:"not_required",daemonProtocolVersion:"",policySchemaVersions:[Ne],runtimePolicyUpdates:!1,workspaceSync:!1,egressProxy:!1,reason:"external_runtime_sandbox_not_required"};let t=await cn(e.sandboxBrokerCommand,process.env.PATH||"");if(!t)throw S("RUNTIME_SANDBOX_UNAVAILABLE","sandbox broker is not executable");let r=await Wi(t,b(e.sandboxBrokerArguments),e.sandboxProbeTimeoutMs);if(r.enforced!==!0||a(r.protocolVersion)!=="orcha.runtime-sandbox-broker/v1"||!["bubblewrap","broker"].includes(a(r.backend)))throw S("RUNTIME_SANDBOX_UNAVAILABLE","sandbox broker did not report enforced isolation");let n=u(r.probes)?r.probes:{};for(let s of["emptyRoot","outsideWorkspaceDenied","hostFilesystemDenied","sensitiveFilesDenied","environmentAllowlist","dockerSocketDenied","networkNamespace","workspaceReadOnly","workspaceWrite","resourceLimits"])if(n[s]!==!0)throw S("RUNTIME_SANDBOX_UNAVAILABLE",`sandbox broker probe failed: ${s}`);return e.egressProxyRequired&&await Yi(e),{dispatchable:!0,enforced:!0,backend:a(r.backend),daemonStatus:"ok",daemonProtocolVersion:a(r.protocolVersion||"orcha.runtime-sandbox-broker/v1"),policySchemaVersions:[Ne],runtimePolicyUpdates:!0,workspaceSync:!1,egressProxy:e.egressProxyRequired}}async function Ue(e,t,r){let n=a(t.workspace||t.cwd),s=a(r),i=n||(t.allowRequestWorkspace===!0?s:"");if(!i||!Tt(i))throw S("RUNTIME_WORKSPACE_NOT_CONFIGURED","runtime target must configure an absolute trusted workspace");let o=await _t(i);if(!(await Hi(o)).isDirectory())throw S("RUNTIME_WORKSPACE_INVALID","runtime workspace is not a directory");if(!(e.trustedWorkspaceRoots.length?await Promise.all(e.trustedWorkspaceRoots.map(d=>_t(d))):[o]).some(d=>ke(d,o)))throw S("RUNTIME_WORKSPACE_OUTSIDE_TRUSTED_ROOT","runtime workspace is outside trusted roots");return o}async function an({config:e,target:t,command:r,args:n,cwd:s,environment:i,runId:o,agentId:c,sessionId:l,sandboxPolicy:d}){if(!e.sandboxRequired)return{command:r,args:[...n],cwd:s,environment:{...process.env,...i},tempDirectory:"",isolation:{enforced:!1,backend:"development_direct"},cleanup:async()=>{}};let f=W(d),p=await Ue(e,t,s),m=await _t(s);if(!ke(p,m))throw S("RUNTIME_WORKSPACE_CWD_INVALID","runtime cwd is outside its workspace");let g=await cn(e.sandboxBrokerCommand,process.env.PATH||"");if(!g)throw S("RUNTIME_SANDBOX_UNAVAILABLE","sandbox broker is not executable");let y=`runtime-${Ui("sha256").update(String(o)).digest("hex").slice(0,32)}`,x=Ae(e.sandboxTempRoot||nt(Fi(),"orcha-runtime-sandboxes"));await Ce(x,{recursive:!0,mode:448});let A=nt(x,`${y}-${Pi()}`),T=nt(A,"home"),R=nt(A,"artifacts");await Ce(T,{recursive:!0,mode:448}),await Ce(R,{recursive:!0,mode:448});let w=f.networkMode==="restricted"?await Ji(e,{runId:String(o),instanceId:y,policyRevision:Number(f.policyRevision),ttlMs:Math.min(_(f.maxRuntimeSeconds,900)*1e3,e.egressGrantMaxTtlMs),maxTransferBytes:_(f.maxNetworkBytes,64*1024*1024)}):null,O={PATH:a(i.PATH||process.env.PATH),LANG:a(i.LANG||process.env.LANG||"C.UTF-8"),HOME:"/tmp/home",TMPDIR:"/tmp",USER:"orcha",LOGNAME:"orcha",SHELL:"/bin/sh",ORCHA_AGENT_ID:String(c),ORCHA_SESSION_ID:String(l),ORCHA_RUN_ID:String(o),ORCHA_RUNTIME_ARTIFACT_DIR:"/tmp/artifacts",...Gi(t,i)};O.HOME="/tmp/home",O.TMPDIR="/tmp",O.ORCHA_RUNTIME_ARTIFACT_DIR="/tmp/artifacts",O.NODE_OPTIONS=qi;let P={schemaVersion:Bi,runId:String(o),instanceId:y,workspace:p,cwd:m,filesystemMode:f.filesystemMode,networkMode:f.networkMode,environmentMode:"allowlist",deniedRelativePaths:await zi(p),temporaryDirectory:A,egressProxy:w,environment:O,resourceLimits:Vi(f),readOnlyToolchainRoots:await Ki(e,t)},v=!1,N=async()=>{if(!v){v=!0;try{w&&await Xi(e,w,{runId:String(o),instanceId:y})}finally{await vi(A,{recursive:!0,force:!0})}}};return{command:g,args:[...b(e.sandboxBrokerArguments),"--",r,...n],cwd:m,environment:{PATH:process.env.PATH||"",LANG:process.env.LANG||"C.UTF-8",ORCHA_PROCESS_ISOLATION_REQUEST:JSON.stringify(P)},tempDirectory:A,homeDirectory:T,artifactDirectory:R,pathMappings:[{runtimeRoot:"/tmp/artifacts",hostRoot:R},{runtimeRoot:"/tmp/home",hostRoot:T}],isolation:{enforced:!0,backend:"broker",instanceId:y,policyRevision:f.policyRevision},cleanup:N}}async function Ki(e,t){let r=b(t.toolchainRoots||t.sandboxToolchainRoots);if(!r.length)return[];let n=await Promise.all(b(e.trustedToolchainRoots).map(i=>_t(i)));if(!n.length)throw S("RUNTIME_TOOLCHAIN_ROOT_NOT_TRUSTED","target toolchain roots require ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS");let s=[];for(let i of r){if(!Tt(i))throw S("RUNTIME_TOOLCHAIN_ROOT_INVALID","toolchain roots must be absolute");let o=await _t(i);if(!n.some(c=>ke(c,o)))throw S("RUNTIME_TOOLCHAIN_ROOT_NOT_TRUSTED","toolchain root is outside trusted roots");s.push(o)}return[...new Set(s)]}function Gi(e,t){let r=u(e.env)?e.env:{},n={};for(let[s,i]of Object.entries(r))/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&i!=null&&(n[s]=String(i));for(let s of["ORCHA_RUNTIME_PROMPT","ORCHA_RUNTIME_ARTIFACT_DIR"])t[s]!=null&&(n[s]=String(t[s]));return n}async function zi(e){let t=[],r=0,n=async s=>{let i;try{i=await Di(s,{withFileTypes:!0})}catch(o){if(s===e)throw o;return}for(let o of i){if(r+=1,r>1e4)throw S("RUNTIME_WORKSPACE_SCAN_LIMIT_EXCEEDED","workspace contains more than 10000 entries");let c=nt(s,o.name),l=nn(e,c),d=o.name.toLowerCase();(ji.has(d)||d.startsWith(".env."))&&t.push(l),o.isDirectory()&&!o.isSymbolicLink()&&await n(c)}};return await n(e),t.sort()}function Vi(e){return{maxCpuSeconds:Math.max(1,_(e.maxRuntimeSeconds,900)),maxMemoryBytes:_(e.maxMemoryBytes,2*1024*1024*1024),maxProcesses:_(e.maxProcesses,128),maxOpenFiles:_(e.maxOpenFiles,1024),maxFileBytes:_(e.maxFileBytes,64*1024*1024)}}async function Wi(e,t,r){return await new Promise((n,s)=>{let i=Mi(e,[...t,"--probe"],{env:{PATH:process.env.PATH||"",LANG:"C.UTF-8"},stdio:["ignore","pipe","pipe"],windowsHide:!0}),o=[],c=[];i.stdout.on("data",d=>o.push(Buffer.from(d))),i.stderr.on("data",d=>c.push(Buffer.from(d)));let l=setTimeout(()=>i.kill("SIGKILL"),Math.max(1e3,r));i.once("error",s),i.once("close",d=>{if(clearTimeout(l),d!==0){s(S("RUNTIME_SANDBOX_UNAVAILABLE",Buffer.concat(c).toString("utf8").trim()||`sandbox probe exited with ${d}`));return}try{n(JSON.parse(Buffer.concat(o).toString("utf8")))}catch{s(S("RUNTIME_SANDBOX_UNAVAILABLE","sandbox probe returned invalid JSON"))}})})}async function cn(e,t){let r=a(e);if(!r)return"";let n=Tt(r)?[r]:String(t||"").split(":").filter(Boolean).map(s=>nt(s,r));for(let s of n)try{return await Li(s,ki.X_OK),s}catch{}return""}async function Ji(e,t){if(!e.egressProxyRequired)throw S("RUNTIME_EGRESS_UNAVAILABLE","restricted network requires the Egress Proxy");let r=await Pe(e,"POST","/v1/grants",{protocolVersion:Me,...t}),n={socketPath:e.egressProxySocket,grantId:a(r.grantId),credential:a(r.credential)};if(!n.grantId||!n.credential)throw S("RUNTIME_EGRESS_UNAVAILABLE","Egress Proxy returned an invalid grant");return n}async function Xi(e,t,r){await Pe(e,"POST",`/v1/grants/${encodeURIComponent(t.grantId)}/revoke`,{protocolVersion:Me,...r}).catch(()=>{})}async function Yi(e){let t=await Pe(e,"GET","/health");if(t.status!=="ok"||t.proxy!=="orcha-egress-proxy"||t.protocolVersion!==Me)throw S("RUNTIME_EGRESS_UNAVAILABLE","Egress Proxy is unavailable or incompatible")}async function Pe(e,t,r,n){if(!Tt(e.egressProxySocket)||!e.egressProxyToken)throw S("RUNTIME_EGRESS_UNAVAILABLE","Egress Proxy socket and token are required");return await new Promise((s,i)=>{let o=$i.request({socketPath:e.egressProxySocket,path:r,method:t,headers:{Authorization:`Bearer ${e.egressProxyToken}`,Accept:"application/json",...n?{"Content-Type":"application/json"}:{}}},c=>{let l=[],d=0;c.on("data",f=>{d+=f.length,d>1048576?o.destroy(new Error("egress response is too large")):l.push(Buffer.from(f))}),c.once("end",()=>{try{let f=JSON.parse(Buffer.concat(l).toString("utf8")||"{}");(c.statusCode||500)>=400?i(S("RUNTIME_EGRESS_UNAVAILABLE",a(f.error)||"Egress Proxy rejected the request")):s(f)}catch(f){i(f)}})});o.once("error",i),o.setTimeout(3e3,()=>o.destroy(new Error("Egress Proxy request timed out"))),n?o.end(JSON.stringify(n)):o.end()})}function ke(e,t){let r=nn(Ae(e),Ae(t));return r===""||!r.startsWith("..")&&!Tt(r)}function S(e,t){return Object.assign(new Error(t),{code:e})}var Le=24e3,De=8,ve=50,He=6e3,Qi=new Set(["fail","failed","failure","error","errored","timeout","timed_out","cancelled","canceled","aborted"]),to=10*60*1e3,eo=60*1e3,ro=8,no=30*60*1e3,so=60*1e3,io=1,fn=2400,oo=new Set(["max_tokens","max_output_tokens","length"]),ao=new Set(["agent_message_chunk","tool_call","tool_call_update"]),co=new Set(["agentId","taskId","executionId","sessionId","nodeId","targetCode","framework","workspace","instructions"]),uo=/(^|[_-])(token|secret|password|authorization|api[-_]?key|private[-_]?key|credential|cookie|jwt|access[-_]?token|refresh[-_]?token|service[-_]?token|execution[-_]?token)([_-]|$)/i;function lo(e){if(!u(e))return{};let t={};for(let r of["name","code","serverName","serverCode","type","transport","url","command","protocolVersion"]){let n=a(e[r]);n&&(t[r]=n)}return t}function fo(e){return(Array.isArray(e)?e:[]).map(lo).sort((t,r)=>{let n=q(t),s=q(r);return n<s?-1:n>s?1:0})}function po(e){return!u(e)||e.verificationPlan?.required!==!0?!1:(Array.isArray(e.verificationPlan.checks)?e.verificationPlan.checks:[]).some(r=>u(r)&&Array.isArray(r.toolNames)&&r.toolNames.some(n=>a(n)==="plugin_operation"))}function mo(e,t,r){let n=u(e?._meta)?e._meta:{};return{...u(e)?e:{},sessionId:t,update:u(e?.update)?e.update:{},_meta:{...n,orchaAgentId:r.agentId,runtimeSessionId:r.runtimeSessionId,bridgeUpdateId:Kt()}}}function L(e){return e==null||e===""?!1:typeof e=="string"?a(e)!=="":Array.isArray(e)?e.length>0:u(e)?Object.keys(e).length>0:!0}function pn(e){let t=a(e).toLowerCase().replace(/[.。!!]+$/g,"").replace(/[\s-]+/g,"_");return Qi.has(t)}function G(e,t){let r=_(e,t);return Number.isFinite(r)&&r>0?r:t}function yt(e,t=!1){if(typeof e=="boolean")return e;let r=a(e).toLowerCase();return["true","1","yes","y","on"].includes(r)?!0:["false","0","no","n","off"].includes(r)?!1:t}function K(e){return a(e?.type||"echo")}function mn(e){let t=K(e);return t==="acp"||t==="stdio-acp"||t==="openclaw"}function Be(e){if(u(e)){if(Object.prototype.hasOwnProperty.call(e,"releaseAfterPrompt"))return e.releaseAfterPrompt;if(Object.prototype.hasOwnProperty.call(e,"disposeAfterPrompt"))return e.disposeAfterPrompt}}function ho(e){let t=String(e||"");if(uo.test(t))return!0;let r=t.replace(/[^a-z0-9]/gi,"").toLowerCase();return r.endsWith("token")||r.endsWith("secret")||r.endsWith("password")||r.endsWith("apikey")||r.endsWith("privatekey")||r==="authorization"||r==="cookie"||r==="jwt"||r.includes("credential")}function qe(e,t=0){if(e==null||typeof e=="number"||typeof e=="boolean")return e;if(typeof e=="string"){if(e.length<=He)return e;let r=e.length-He;return`${e.slice(0,He)}... [truncated ${r} characters]`}if(t>=De)return Array.isArray(e)?`[array truncated at depth ${De}, items=${e.length}]`:u(e)?`[object truncated at depth ${De}, keys=${Object.keys(e).length}]`:String(e);if(Array.isArray(e)){let r=e.slice(0,ve).map(n=>qe(n,t+1));return e.length>ve&&r.push(`[truncated ${e.length-ve} items]`),r}if(u(e)){let r={};for(let[n,s]of Object.entries(e))r[n]=ho(n)?"[REDACTED]":qe(s,t+1);return r}return String(e)}var go=new Set(["type","executionId","taskId","task","traceId","requestId","agentCode","stage","phase","nodeId","nodeType","capabilityCode","operationCode","outputType","artifactType","input","inputs","rejection","previous","artifactRefs","outputSchema","executionPolicy","resultContract"]);function _o(e){if(!u(e))return e;let t={};for(let r of go)L(e[r])&&(t[r]=e[r]);return t}function To(e){if(!u(e))return e;let t={...e};return u(t.renderedPayload)&&(t.renderedPayload=_o(t.renderedPayload)),t}function yo(e){let t=u(e)?e:{},r={};L(t.metadata)&&(r.metadata=To(t.metadata));for(let[n,s]of Object.entries(t))co.has(n)||n==="metadata"||L(s)&&(r[n]=s);return r}function Ro(e){let t=u(e)?e:{},r=u(t.metadata)?t.metadata:{},n=u(r.renderedPayload)?r.renderedPayload:{};return u(t.resultContract)?t.resultContract:u(n.resultContract)?n.resultContract:{}}function hn(e){return a(Ro(e).kind).toLowerCase()==="decision"}function wo(e){return e?.dispatchFinalTextOnly===!0||e?.dispatchFinalOutputOnly===!0?!0:e?.dispatchFinalTextOnly===!1||e?.dispatchFinalOutputOnly===!1?!1:K(e)==="cli"}function un(e){let t=e?.dispatchReleaseAfterPrompt??e?.dispatchDisposeAfterPrompt;return yt(t,mn(e))}function So(e,t){let r=u(e?.metadata)?{...e.metadata}:{},n=u(r._runtimeBridge)?{...r._runtimeBridge}:{},s=Be(n);return r._runtimeBridge={...n,promptKind:"dispatch",finalTextOnly:wo(t),releaseAfterPrompt:s===void 0?un(t):yt(s,un(t)),requiresRuntimeResult:hn(e)},r}function Eo(e){let t=yo(e);if(!L(t))return"";let r=JSON.stringify(qe(t),null,2);if(r.length<=Le)return r;let n=r.length-Le;return`${r.slice(0,Le)}
|
|
14
|
-
... [truncated ${n} characters]`}function
|
|
15
|
-
`:"";t+=`${s}${n}`}}return t.trim()}function
|
|
16
|
-
`?1:0)).trim()}function
|
|
17
|
-
`)}function Lo(e,t){let r=u(t)?{...t}:{},n=Tn(e?._artifacts,t?._artifacts);return n.length>0&&(r._artifacts=n),r}function Do(e,t){return{...e,_meta:{...u(e?._meta)?e._meta:{},runtimeProtocolRetry:{attempted:!0,recovered:!0,reason:ze(t)||"max_tokens"}}}}function vo(e,t){let r=typeof e?.output=="string"?e.output:Ge(t),n=new k("runtime_output_truncated","Runtime Result \u8FBE\u5230\u6700\u5927\u8F93\u51FA\u957F\u5EA6\uFF0C\u7D27\u51D1\u91CD\u8BD5\u540E\u4ECD\u672A\u5B8C\u6574\u8FD4\u56DE",r);return n.detail={...n.detail,stopReason:ze(e)||"max_tokens",retryAttempted:!0},n}var zt=class{constructor(t){this.config=t,this.targets=t.targets||{},this.agents=new Map,this.sessions=new Map,this.startingSessions=new Set,this.targetReservations=new Map,this.runtimeSessionIndex=new Map,this.pendingPermissions=new Map,this.operations=new Map,this.startedAt=dt(),this.sandboxCapabilities={dispatchable:t.sandboxRequired!==!0,enforced:!1,backend:t.sandboxRequired?"unavailable":"direct",daemonStatus:t.sandboxRequired?"pending":"not_required",policySchemaVersions:[1],runtimePolicyUpdates:t.sandboxRequired===!0,workspaceSync:!1,egressProxy:!1},this.cleanupTimer=null,this.onCapacityChanged=null,this.startSessionCleanup()}async start(){try{this.sandboxCapabilities=await on(this.config)}catch(t){this.sandboxCapabilities={...this.sandboxCapabilities,dispatchable:!1,enforced:!1,backend:"unavailable",daemonStatus:"unavailable",reason:a(t?.code||t?.message||t)||"sandbox_probe_failed"},h("error","runtime-bridge","runtime node sandbox probe failed; node will not accept work",{reason:this.sandboxCapabilities.reason})}return this.sandboxCapabilities}assertDispatchable(){if(this.config.sandboxRequired&&!(this.sandboxCapabilities.dispatchable===!0&&this.sandboxCapabilities.enforced===!0))throw Object.assign(new Error("runtime node strong sandbox is unavailable"),{code:"RUNTIME_NODE_SANDBOX_UNAVAILABLE"})}operationIdentity(t,r,n){let s=u(t.goalContract)?xe(t.goalContract):a(t.goalContractHash),i=Zi("sha256").update(q({prompt:Array.isArray(t.prompt)?t.prompt:[],mcpServers:fo(t.mcpServers),metadata:u(t.metadata)?t.metadata:{}})).digest("hex");return{agentId:r,runId:a(t.runId),sessionId:n,targetCode:a(t.targetCode||t.framework),workspace:a(t.workspace),goalContractHash:s,requestHash:i}}assertOperationIdentity(t,r,n,s){let i=this.operationIdentity(r,n,s),o=Object.keys(t.identity).find(c=>t.identity[c]!==i[c]);if(o)throw Object.assign(new Error(`runtime operation correlation conflict: ${t.correlationId}`),{code:"RUNTIME_OPERATION_CORRELATION_CONFLICT",field:o})}createOperation(t,r,n,s){let i={correlationId:t,agentId:n,sessionId:s,identity:this.operationIdentity(r,n,s),sandboxPolicy:u(r.sandboxPolicy)?structuredClone(r.sandboxPolicy):null,status:"running",updates:[],listeners:new Set,waiters:[],response:null,error:null,mcpServers:r.mcpServers,createdAtMs:Date.now(),completedAtMs:null};return this.operations.set(t,i),i}async attachOperation(t,r={}){let n=()=>{if(r.onUpdate)for(let s of t.updates)r.onUpdate(s)};if(t.status==="completed")return n(),t.response;if(t.status==="failed")throw n(),t.error;r.onUpdate&&t.listeners.add(r.onUpdate);try{return n(),await new Promise((s,i)=>t.waiters.push({resolve:s,reject:i}))}finally{r.onUpdate&&t.listeners.delete(r.onUpdate)}}completeOperation(t,r){if(t.status==="running"){t.status="completed",t.response=r,t.mcpServers=null,t.completedAtMs=Date.now();for(let n of t.waiters.splice(0))n.resolve(r);t.listeners.clear()}}promptResponse(t,r,n,s,i,o=s){let c=u(t.metadata)?t.metadata:{},l=u(c._runtimeBridge)?c._runtimeBridge:{},d=yn(i,o,l),f=en(t.goalContract,s,t.goalContractHash);return{sessionId:n,runtimeSessionId:r.runtimeSessionId,result:d,updates:s,...f?{verification:f}:{}}}failOperation(t,r){if(t.status!=="running")return;let n=r instanceof Error?r:Object.assign(new Error(String(r||"runtime operation failed")),{code:"RUNTIME_NODE_ERROR"});t.status="failed",t.error=n,t.mcpServers=null,t.completedAtMs=Date.now();for(let s of t.waiters.splice(0))s.reject(n);t.listeners.clear()}cleanupOperations(t=Date.now()){let r=G(this.config.operationTtlMs,no);for(let[n,s]of this.operations)s.status!=="running"&&t-(s.completedAtMs||s.createdAtMs)>r&&this.operations.delete(n)}targetFor(t){let r=a(t)||this.config.defaultTargetCode,n=this.targets[r];if(!r||!u(n)){let s=new Error(`runtime target is not configured: ${r||"<empty>"}`);throw s.code="RUNTIME_TARGET_NOT_FOUND",s}return{code:r,target:n}}targetIdleTtlMs(t){let n=K(t)==="openclaw"?G(this.config.openClawSessionIdleTtlMs,so):G(this.config.sessionIdleTtlMs,to);return G(t?.sessionIdleTtlMs??t?.idleTtlMs,n)}targetMaxSessions(t){let n=K(t)==="openclaw"?G(this.config.openClawMaxSessions,io):G(this.config.maxSessionsPerTarget,ro);return G(t?.maxSessions,n)}targetReservationCount(t){return Number(this.targetReservations.get(t)||0)}notifyCapacityChanged(){try{this.onCapacityChanged?.()}catch(t){h("warn","runtime-bridge","capacity heartbeat callback failed",{error:String(t)})}}targetCapacitySnapshot(t=!0){return Object.entries(this.targets).map(([r,n])=>{let s=[...this.sessions.values()].filter(f=>f.targetCode===r),i=s.filter(f=>f.busy).length,o=s.length-i,c=this.targetReservationCount(r),l=this.targetMaxSessions(n),d=t?Math.max(0,l-i-c):0;return{targetCode:r,targetName:a(n?.name||n?.targetName||r),targetType:a(n?.type||"echo"),status:t?d>0?"available":"busy":"unavailable",maxSessions:l,busySessions:i,idleSessions:o,reservedSessions:c,availableSessions:d}})}targetReleaseAfterPrompt(t,r={}){let n=K(t),s=u(r?._runtimeBridge)?r._runtimeBridge:{},i=Be(s);return i!==void 0?yt(i,!1):yt(t?.releaseAfterPrompt??t?.disposeAfterPrompt,n==="openclaw")}promptReleaseAfterPrompt(t,r={}){if(this.config.sandboxRequired)return!0;let n=u(r?._runtimeBridge)?r._runtimeBridge:{},s=Be(n);return s!==void 0?yt(s,t.releaseAfterPrompt):t.releaseAfterPrompt}startSessionCleanup(){let t=G(this.config.sessionCleanupIntervalMs,eo);t<=0||(this.cleanupTimer=setInterval(()=>{this.cleanupExpiredSessions().catch(r=>{h("warn","runtime-bridge","runtime session cleanup failed",{error:String(r)})})},t),this.cleanupTimer.unref?.())}sessionCountForTarget(t){let r=0;for(let n of this.sessions.values())n.targetCode===t&&(r+=1);return r}idleTargetSessions(t){return[...this.sessions.entries()].filter(([,r])=>r.targetCode===t&&!r.busy).sort((r,n)=>(r[1].lastUsedAtMs||0)-(n[1].lastUsedAtMs||0))}async closeSession(t,r="session_closed"){let n=this.sessions.get(t);if(!n)return!1;try{await n.runtime?.stop?.(r)}catch(s){h("warn","runtime-bridge","runtime session stop failed",{sessionId:n.sessionId,runtimeSessionId:n.runtimeSessionId,targetCode:n.targetCode,runtimeKind:n.runtimeKind,error:String(s)})}return this.sessions.delete(t),this.runtimeSessionIndex.delete(`${n.agentId}:${n.runtimeSessionId}`),this.notifyCapacityChanged(),h("info","runtime-bridge","runtime session closed",{sessionId:n.sessionId,runtimeSessionId:n.runtimeSessionId,targetCode:n.targetCode,runtimeKind:n.runtimeKind,reason:r}),!0}async closeAllSessions(t="bridge_shutdown"){for(let r of[...this.sessions.keys()])await this.closeSession(r,t)}async stop(t="bridge_stop"){this.cleanupTimer&&clearInterval(this.cleanupTimer),this.cleanupTimer=null,await this.closeAllSessions(t)}async cleanupExpiredSessions(t=Date.now()){for(let[r,n]of[...this.sessions.entries()])n.busy||t-(n.lastUsedAtMs||n.createdAtMs||t)>n.idleTtlMs&&await this.closeSession(r,"idle_timeout")}async reserveTargetSlot(t,r){let n=this.targetMaxSessions(r);for(;this.sessionCountForTarget(t)+this.targetReservationCount(t)>=n;){let s=this.idleTargetSessions(t);if(!s.length){let i=new Error(`runtime target session limit reached: ${t}`);throw i.code="RUNTIME_TARGET_SESSION_LIMIT",i}await this.closeSession(s[0][0],"target_session_limit")}this.targetReservations.set(t,this.targetReservationCount(t)+1),this.notifyCapacityChanged()}releaseTargetSlot(t){let r=Math.max(0,this.targetReservationCount(t)-1);r>0?this.targetReservations.set(t,r):this.targetReservations.delete(t),this.notifyCapacityChanged()}async createAgent(t){let r=a(t.agentId);if(!r)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});let{code:n,target:s}=this.targetFor(t.targetCode||t.framework),i=this.agents.get(r);if(i&&i.targetCode!==n)throw Object.assign(new Error(`runtime agent target conflict: ${r}`),{code:"RUNTIME_AGENT_TARGET_CONFLICT"});let o=this.config.sandboxRequired?await Ue(this.config,s,t.workspace):a(t.workspace),c={agentId:r,targetCode:n,framework:a(t.framework||n),workspace:o,metadata:u(t.metadata)?t.metadata:{},createdAt:dt(),runtimeKind:K(s)};return this.agents.set(r,c),{agent:c}}runtimeFor(t,r,n={}){let{target:s}=this.targetFor(t.targetCode),i=K(s),o={onPermissionRequest:l=>n.source==="conversation_delegation"?{outcome:"denied",reason:"External group member permission continuation is not supported"}:this.requestPermission(l)},c={sessionPromptTimeoutMs:this.config.sessionPromptTimeoutMs,initializeTimeoutMs:this.config.initializeTimeoutMs,sandboxRequired:this.config.sandboxRequired,runId:n.runId,sandboxPolicy:n.sandboxPolicy,...this.config.sandboxRequired?{prepareLaunch:l=>an({config:this.config,target:s,...l,runId:n.runId,agentId:t.agentId,sessionId:r,sandboxPolicy:n.sandboxPolicy})}:{}};return i==="stdio-acp"||i==="acp"?new et(t,s,o,c):i==="openclaw"?new Ut(t,s,r,o,c):i==="cli"?new vt(t,s,c):new It(t)}async prompt(t,r={}){if(this.assertDispatchable(),this.config.sandboxRequired){let c=a(t.runId);if(!c)throw Object.assign(new Error("runId is required"),{code:"BAD_REQUEST"});t={...t,runId:c,sandboxPolicy:W(t.sandboxPolicy)}}let n=a(t.agentId),s=a(t.sessionId)||Kt(),i=a(t.correlationId);if(!n)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});if(this.cleanupOperations(),i){let c=this.operations.get(i);if(c){if(this.assertOperationIdentity(c,t,n,s),c.status==="running"&&t.metadata?.source==="conversation_delegation"){c.mcpServers=t.mcpServers;let l=this.sessions.get(`${n}:${s}`);if(l){if(!l.runtime.refreshMcpServers)throw Object.assign(new Error("This runtime cannot refresh task MCP credentials"),{code:"unsupported_dynamic_mcp"});await l.runtime.refreshMcpServers(t.mcpServers)}}return this.attachOperation(c,r)}if(t.attachOnly===!0)throw Object.assign(new Error(`runtime operation is no longer available: ${i}`),{code:"RUNTIME_OPERATION_NOT_FOUND"})}else if(t.attachOnly===!0)throw Object.assign(new Error("correlationId is required for attachOnly"),{code:"BAD_REQUEST"});let o=i?this.createOperation(i,t,n,s):null;if(o){let c=this.attachOperation(o,r);return(async()=>{try{await this._promptOwned(t,{},o,n,s)}catch(l){let d=o.status==="completed";this.failOperation(o,l),d&&h("warn","runtime-bridge","runtime cleanup failed after operation completion",{correlationId:o.correlationId,error:String(l)})}})(),await c}return await this._promptOwned(t,r,o,n,s)}async _promptOwned(t,r,n,s,i){let o=a(t.runId),c=this.config.sandboxRequired?W(n?.sandboxPolicy||t.sandboxPolicy):null,l=this.agents.get(s),d=this.targetFor(t.targetCode||t.framework||l?.targetCode);if(l&&l.targetCode!==d.code)throw Object.assign(new Error(`runtime agent target conflict: ${s}`),{code:"RUNTIME_AGENT_TARGET_CONFLICT"});if(K(d.target)==="cli"&&po(t.goalContract))throw Object.assign(new Error("CLI runtimes do not support per-run dynamic MCP required by plugin_operation"),{code:"unsupported_dynamic_mcp"});let f=l||(await this.createAgent({agentId:s,targetCode:d.code,framework:t.framework,workspace:t.workspace,metadata:t.metadata})).agent;if(!this.config.sandboxRequired){let T=a(t.workspace);T&&T!==f.workspace&&(f.workspace=T)}let p=`${s}:${i}`;await this.cleanupExpiredSessions();let m=this.sessions.get(p),g=null;if(m&&m.targetCode!==d.code)throw Object.assign(new Error(`runtime session target conflict: ${i}`),{code:"RUNTIME_SESSION_TARGET_CONFLICT"});if(m&&this.config.sandboxRequired&&m.runId!==o)throw Object.assign(new Error(`runtime session cannot be shared across runs: ${i}`),{code:"RUNTIME_SESSION_RUN_CONFLICT"});if(!m){if(this.startingSessions.has(p))throw Object.assign(new Error(`runtime session is already starting: ${i}`),{code:"RUNTIME_SESSION_BUSY"});this.startingSessions.add(p);let{code:T,target:R}=d,w;try{await this.reserveTargetSlot(T,R),g=T;let O=this.runtimeFor(f,i,{runId:o,sandboxPolicy:c,source:t.metadata?.source});w=O;let P=n?.mcpServers||t.mcpServers||[],v=await O.sessionNew({cwd:tt(R,f.workspace),mcpServers:P,metadata:u(t.metadata)?t.metadata:{}});if(n&&n.status!=="running")throw Object.assign(new Error("Runtime operation was cancelled before prompt dispatch"),{code:"RUNTIME_OPERATION_CANCELLED"});let N=Date.now();m={agentId:s,sessionId:i,runtime:O,targetCode:T,runtimeKind:K(R),runId:o,sandboxPolicy:c?structuredClone(c):null,runtimeSessionId:a(u(v)?v.sessionId:"")||i,idleTtlMs:this.targetIdleTtlMs(R),releaseAfterPrompt:this.config.sandboxRequired?!0:this.targetReleaseAfterPrompt(R,t.metadata),createdAtMs:N,lastUsedAtMs:N,busy:!1,createdAt:dt()},this.sessions.set(p,m),this.runtimeSessionIndex.set(`${s}:${m.runtimeSessionId}`,m),n?.mcpServers!==P&&n?.mcpServers&&O.refreshMcpServers&&await O.refreshMcpServers(n.mcpServers)}catch(O){throw this.sessions.get(p)?.runtime===w?await this.closeSession(p,"session_start_failed"):await w?.stop("session_start_failed"),g&&(this.releaseTargetSlot(g),g=null),O}finally{this.startingSessions.delete(p)}}if(m.busy){let T=new Error(`runtime session is already running: ${i}`);throw T.code="RUNTIME_SESSION_BUSY",T}m.busy=!0,g&&this.releaseTargetSlot(g),this.notifyCapacityChanged(),m.operationCorrelationId=n?.correlationId||null,m.lastUsedAtMs=Date.now();let y=n?.updates||[],x=T=>{let R=mo(T,i,m);if(y.push(R),n)for(let w of n.listeners)try{w?.(R)}catch(O){h("warn","runtime-bridge","runtime operation update listener failed",{correlationId:n.correlationId,error:String(O)})}else r.onUpdate?.(R)},A=T=>{if(!(!n||n.status!=="running"||!u(T))){if(T.status==="failed"){let R=T.error;if(R instanceof Error){this.failOperation(n,R);return}let w=u(R)?R:{},O=Object.assign(new Error(a(w.message||T.message)||"runtime terminal failure"),{code:a(w.code||T.code)||"RUNTIME_TERMINAL_FAILED"});this.failOperation(n,O);return}this.completeOperation(n,this.promptResponse(t,m,i,y,u(T.result)?T.result:{stopReason:"end_turn"}))}};try{let T=tn(t.goalContract),R=Array.isArray(t.prompt)?[...t.prompt]:[];T&&R.unshift({type:"text",text:T,metadata:{source:"orcha_goal_contract"}});let w=u(t.metadata)?t.metadata:{},O=u(w._runtimeBridge)?w._runtimeBridge:{},P=await m.runtime.sessionPrompt({sessionId:m.runtimeSessionId,prompt:R,metadata:w},x,A),v=y,N=null;if(mn({type:m.runtimeKind})&&Po(P,y,O)){N=P;let Y=y.length,at=await m.runtime.sessionPrompt({sessionId:m.runtimeSessionId,prompt:[{type:"text",text:ko()}],metadata:w,_meta:{thinking:"off"}},x,A);P=Lo(N,at),v=y.slice(Y)}let E;try{E=this.promptResponse(t,m,i,y,P,v)}catch(Y){throw N&&Rn(P)?vo(P,v):Y}return N&&(E.result=Do(E.result,N)),n&&this.completeOperation(n,E),E}finally{m.busy=!1,this.notifyCapacityChanged(),m.operationCorrelationId===n?.correlationId&&(m.operationCorrelationId=null),m.lastUsedAtMs=Date.now(),this.promptReleaseAfterPrompt(m,u(t.metadata)?t.metadata:{})&&await this.closeSession(p,"release_after_prompt"),n&&(n.mcpServers=null)}}async updatePolicy(t){if(this.assertDispatchable(),!this.config.sandboxRequired)throw Object.assign(new Error("runtime sandbox policy updates require an enforced sandbox"),{code:"RUNTIME_NODE_SANDBOX_UNAVAILABLE"});let r=a(t.agentId),n=a(t.runId),s=a(t.sessionId),i=a(t.correlationId);if(!r||!n||!s||!i)throw Object.assign(new Error("agentId, runId, sessionId and correlationId are required"),{code:"BAD_REQUEST"});let o=W(t.sandboxPolicy),c=this.operations.get(i);if(c&&(c.agentId!==r||c.sessionId!==s||c.identity.runId!==n))throw Object.assign(new Error(`runtime operation policy identity conflict: ${i}`),{code:"RUNTIME_OPERATION_CORRELATION_CONFLICT"});let l=`${r}:${s}`,d=this.sessions.get(l);if(d&&d.runId!==n)throw Object.assign(new Error(`runtime session policy identity conflict: ${s}`),{code:"RUNTIME_SESSION_RUN_CONFLICT"});let f=d?.sandboxPolicy||c?.sandboxPolicy;if(!f)throw Object.assign(new Error(`runtime operation is no longer available: ${i}`),{code:"RUNTIME_OPERATION_NOT_FOUND"});let p=Number(f.policyRevision),m=Number(o.policyRevision);if(m<p)throw Object.assign(new Error("runtime sandbox policy revision is stale"),{code:"RUNTIME_POLICY_REVISION_CONFLICT",currentPolicyRevision:p});if(m===p){if(q(f)!==q(o))throw Object.assign(new Error("runtime sandbox policy revision payload conflicts"),{code:"RUNTIME_POLICY_REVISION_CONFLICT",currentPolicyRevision:p});return{updated:!1,idempotent:!0,policyRevision:p,accessMode:f.accessMode}}let g=sn(f,o);c&&(c.sandboxPolicy=structuredClone(o)),d&&(d.sandboxPolicy=structuredClone(o));let y=!1;return g&&d?.busy===!0&&(await d.runtime.sessionCancel({sessionId:d.runtimeSessionId}),y=await this.closeSession(l,"sandbox_policy_downgrade")),{updated:!0,policyRevision:m,accessMode:o.accessMode,activeCommandCancelled:y,deferredToNextLaunch:!g&&d?.busy===!0}}async cancel(t){let r=a(t.agentId),n=a(t.sessionId),s=a(t.correlationId);if(s){let c=this.operations.get(s);if(!c||c.status!=="running")return{cancelled:!1,correlationId:s,reason:"operation_not_running"};if(c.agentId!==r||c.sessionId!==n)throw Object.assign(new Error(`runtime operation cancellation identity conflict: ${s}`),{code:"RUNTIME_OPERATION_CORRELATION_CONFLICT"});let l=this.sessions.get(`${r}:${n}`);return!l||l.busy!==!0||l.operationCorrelationId!==s?(this.failOperation(c,Object.assign(new Error("Runtime operation cancelled before dispatch"),{code:"RUNTIME_OPERATION_CANCELLED"})),{cancelled:!0,correlationId:s,reason:"cancelled_before_dispatch"}):(await l.runtime.sessionCancel({sessionId:l.runtimeSessionId}),await this.closeSession(`${r}:${n}`,"cancelled"),{cancelled:!0,correlationId:s})}let i=`${r}:${n}`,o=this.sessions.get(i);return o?(await o.runtime.sessionCancel({sessionId:o.runtimeSessionId}),await this.closeSession(i,"cancelled"),{cancelled:!0}):{cancelled:!1}}async dispatch(t,r={}){let n=a(t.agentId),s=a(t.taskId),i=a(t.executionId);if(!n||!s)throw Object.assign(new Error("agentId and taskId are required"),{status:400,code:"BAD_REQUEST"});let o=a(t.sessionId)||`dispatch-${i||s}`,c=a(t.instructions),l=Eo(t),d=hn(t),{target:f}=this.targetFor(t.targetCode||t.framework),p=[{type:"text",text:["Task dispatch received.",`taskId: ${s}`,i?`executionId: ${i}`:"",c?`instructions: ${c}`:"",l?"orchaContext:":"",l,l?"Use orchaContext as the source of truth for upstream outputs, review reports, artifacts, and workflow metadata.":"","Follow the execution protocol in instructions exactly.","When embedding a generated artifact in final Markdown, use the Orcha artifact placeholder as the link target: orcha-artifact://<fieldKey>/<index>.","Example: use  for the first generated image artifact.","Do not use local filesystem paths, file:// URLs, or data: URLs in final Markdown; Orcha replaces artifact placeholders after ingestion.",d?`For decision results, put the raw report between ${_e} and ${Te}.`:"",d?`Then put a JSON object containing _decision between ${ye} and ${Re}.`:"",d?"Do not JSON-escape the report. Keep output out of the CONTROL JSON, and put every protocol marker on its own line.":"",d?`Keep the report within ${fn} Unicode characters so the CONTROL block fits before the output limit.`:"","Return only the final answer required by that protocol.","Do not include process notes, logs, or explanations."].filter(Boolean).join(`
|
|
18
|
-
`)}];return this.prompt({...t,agentId:n,sessionId:o,prompt:p,metadata:So(t,f)},r)}async requestPermission({agent:t,runtimeSessionId:r,request:n,emitUpdate:s}){let i=Kt(),c=this.runtimeSessionIndex.get(`${t.agentId}:${r}`)?.sessionId||r||Kt(),l={permissionId:i,agentId:t.agentId,sessionId:c,runtimeSessionId:r,request:u(n)?n:{},status:"pending",createdAt:dt()};return s?.({sessionId:r,update:{sessionUpdate:"permission_request",permission:l}}),await new Promise(d=>{let f=_(n?.timeoutMs,this.config.permissionRequestTimeoutMs),p=setTimeout(()=>{this.pendingPermissions.delete(i),d({permissionId:i,outcome:"denied",response:{reason:"permission request timed out"}})},f);this.pendingPermissions.set(i,{timer:p,resolve:d,permission:l})})}async respondPermission(t){let r=a(t.permissionId),n=this.pendingPermissions.get(r),s=a(t.outcome||"approved")||"approved";return n?(clearTimeout(n.timer),this.pendingPermissions.delete(r),n.resolve({permissionId:r,outcome:s,response:u(t.response)?t.response:{},userId:a(t.userId),metadata:u(t.metadata)?t.metadata:{}}),{accepted:!0,permissionId:r,outcome:s}):{accepted:!1,permissionId:r,outcome:s}}health(){return{status:this.config.sandboxRequired&&!this.sandboxCapabilities.dispatchable?"unavailable":"ok",bridgeVersion:Q,startedAt:this.startedAt,agents:[...this.agents.values()].map(t=>({agentId:t.agentId,targetCode:t.targetCode,framework:t.framework,runtimeKind:t.runtimeKind})),sessions:this.sessions.size,pendingPermissions:this.pendingPermissions.size,targets:Object.keys(this.targets),sandboxCapabilities:this.sandboxCapabilities}}};import Ho from"node:http";import $o from"node:https";import{randomBytes as wn}from"node:crypto";var it=1,J=3,Fo=1e4,Vt=class{constructor(t,r={}){this.url=t,this.readyState=0,this.socket=null,this.request=null,this.buffer=Buffer.alloc(0),this.listeners=new Map,this.connectTimeoutMs=Bo(r.connectTimeoutMs,Fo),this.connectTimer=null,this.connect()}addEventListener(t,r){let n=this.listeners.get(t)||new Set;n.add(r),this.listeners.set(t,n)}emit(t,r={}){let n=this.listeners.get(t);if(n)for(let s of n)s(r)}connect(){let t=new URL(this.url),r=t.protocol==="wss:"?$o:Ho,n=wn(16).toString("base64"),s=r.request({protocol:t.protocol==="wss:"?"https:":"http:",hostname:t.hostname,port:t.port||(t.protocol==="wss:"?443:80),path:`${t.pathname}${t.search}`,method:"GET",headers:{Connection:"Upgrade",Upgrade:"websocket","Sec-WebSocket-Key":n,"Sec-WebSocket-Version":"13"}});this.request=s,this.startConnectTimer(s),s.on("upgrade",(i,o,c)=>{if(this.clearConnectTimer(),this.readyState===J){o.destroy();return}this.socket=o,this.readyState=it,o.on("data",l=>this.onData(l)),o.on("close",()=>this.onClose()),o.on("error",l=>{this.readyState!==J&&this.emit("error",{error:l,message:l.message,type:"error"}),this.onClose()}),c?.length&&this.onData(c),this.emit("open")}),s.on("response",i=>{this.clearConnectTimer(),this.emit("error",{message:`websocket upgrade failed: HTTP ${i.statusCode}`,type:"error"}),i.resume(),this.onClose()}),s.on("error",i=>{this.clearConnectTimer(),this.readyState!==J&&this.emit("error",{error:i,message:i.message,type:"error"}),this.onClose()}),s.end()}startConnectTimer(t){this.connectTimeoutMs<=0||(this.connectTimer=setTimeout(()=>{if(this.readyState===it||this.readyState===J)return;let r=`websocket connect timeout after ${this.connectTimeoutMs}ms`;this.emit("error",{message:r,type:"timeout"}),this.onClose(),t.destroy(new Error(r))},this.connectTimeoutMs),this.connectTimer.unref?.())}clearConnectTimer(){this.connectTimer&&(clearTimeout(this.connectTimer),this.connectTimer=null)}send(t){!this.socket||this.readyState!==it||this.socket.write(Ve(1,Buffer.from(String(t),"utf8")))}close(){if(this.readyState!==J){if(this.clearConnectTimer(),!this.socket){this.request?.destroy(),this.onClose();return}try{this.readyState===it&&this.socket.write(Ve(8,Buffer.alloc(0))),this.socket.end()}catch{this.socket.destroy()}this.onClose()}}onClose(){this.readyState!==J&&(this.clearConnectTimer(),this.readyState=J,this.request=null,this.emit("close"))}onData(t){for(this.buffer=Buffer.concat([this.buffer,t]);this.buffer.length>=2;){let r=this.buffer[0],n=this.buffer[1],s=r&15,i=(n&128)!==0,o=n&127,c=2;if(o===126){if(this.buffer.length<c+2)return;o=this.buffer.readUInt16BE(c),c+=2}else if(o===127){if(this.buffer.length<c+8)return;let f=this.buffer.readUInt32BE(c),p=this.buffer.readUInt32BE(c+4);o=f*2**32+p,c+=8}let l=c;if(i&&(c+=4),this.buffer.length<c+o)return;let d=this.buffer.subarray(c,c+o);if(i){let f=this.buffer.subarray(l,l+4);d=Buffer.from(d.map((p,m)=>p^f[m%4]))}this.buffer=this.buffer.subarray(c+o),s===1?this.emit("message",{data:d.toString("utf8")}):s===8?this.close():s===9&&this.socket?.write(Ve(10,d))}}};function Bo(e,t){let r=Number.parseInt(String(e??""),10);return Number.isFinite(r)&&r>=0?r:t}function Ve(e,t){let r=t.length,n=2;r>=126&&r<=65535?n+=2:r>65535&&(n+=8);let s=wn(4),i=Buffer.alloc(n+4+r);i[0]=128|e;let o=2;r<126?i[1]=128|r:r<=65535?(i[1]=254,i.writeUInt16BE(r,o),o+=2):(i[1]=255,i.writeUInt32BE(Math.floor(r/2**32),o),i.writeUInt32BE(r>>>0,o+4),o+=8),s.copy(i,o),o+=4;for(let c=0;c<r;c+=1)i[o+c]=t[c]^s[c%4];return i}function qo(e){let t=new URL(e);if(t.protocol==="http:")t.protocol="ws:";else if(t.protocol==="https:")t.protocol="wss:";else if(t.protocol!=="ws:"&&t.protocol!=="wss:")throw new Error(`unsupported ORCHA_RUNTIME_ORCHA_URL protocol: ${t.protocol}`);return t.pathname=`${t.pathname.replace(/\/+$/,"")}/api/agent-runtime-bridge/ws`,t.search="",t.toString()}function jo(e,t=!0){return Object.entries(e||{}).map(([r,n])=>({targetCode:r,targetName:a(n?.name||n?.targetName||r),targetType:a(n?.type||"echo"),status:t?"available":"unavailable"}))}var We=Object.freeze(["health","agents/create","agents/dispatch","sessions/prompt","sessions/policy","sessions/cancel","permissions/respond"]),Wt=class{constructor(t,r){this.config=t,this.bridge=r,this.ws=null,this.stopped=!1,this.connected=!1,this.reconnectTimer=null,this.heartbeatTimer=null,this.capacityHeartbeatTimer=null,this.bridge.onCapacityChanged=()=>this.scheduleCapacityHeartbeat()}sandboxCapabilities(){return this.bridge.sandboxCapabilities||{dispatchable:this.config.sandboxRequired!==!0,enforced:!1,backend:"development_direct",daemonStatus:"development_only",policySchemaVersions:[1],runtimePolicyUpdates:!0,workspaceSync:!1,egressProxy:!1}}runtimeTargets(){let t=this.sandboxCapabilities().dispatchable===!0;return typeof this.bridge.targetCapacitySnapshot=="function"?this.bridge.targetCapacitySnapshot(t):jo(this.config.targets,t)}start(){this.connect()}stop(){this.stopped=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null,this.capacityHeartbeatTimer&&clearTimeout(this.capacityHeartbeatTimer),this.capacityHeartbeatTimer=null,this.bridge.onCapacityChanged=null,this.ws?.close()}connect(){if(this.stopped)return;let t=qo(this.config.orchaUrl),r=new Vt(t,{connectTimeoutMs:this.config.connectTimeoutMs});this.ws=r,r.addEventListener("open",()=>{if(this.ws!==r||this.stopped){r.close();return}this.authenticate(r)}),r.addEventListener("message",n=>this.handleMessage(n.data,r)),r.addEventListener("close",()=>this.scheduleReconnect("close",r)),r.addEventListener("error",n=>{h("warn","orcha-client","runtime node websocket error",{error:String(n?.message||n?.type||n)})})}authenticate(t=this.ws){this.send({type:"runtime_node.authenticate",token:this.config.nodeToken,nodeId:this.config.nodeId,nodeName:this.config.nodeName,version:Q,protocolVersion:"orcha-runtime-node.v2",defaultTargetCode:this.config.defaultTargetCode,supportedMethods:We,sandboxCapabilities:this.sandboxCapabilities(),targets:this.runtimeTargets()},t)}scheduleReconnect(t,r=this.ws){r&&this.ws!==r||(this.connected=!1,this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null,this.capacityHeartbeatTimer&&clearTimeout(this.capacityHeartbeatTimer),this.capacityHeartbeatTimer=null,r&&this.ws===r&&(this.ws=null),!this.stopped&&(this.reconnectTimer||(h("info","orcha-client","runtime node disconnected; reconnect scheduled",{reason:t,reconnectMs:this.config.reconnectMs}),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},this.config.reconnectMs))))}async handleMessage(t,r=this.ws){if(r&&this.ws!==r)return;let n;try{n=JSON.parse(String(t))}catch(s){h("warn","orcha-client","invalid Orcha websocket frame",{error:String(s)});return}if(u(n)){if(n.type==="runtime_node.authenticated"){if(r&&this.ws!==r)return;this.connected=!0,this.startHeartbeat(r),h("info","orcha-client","runtime node authenticated",{nodeId:this.config.nodeId,connectionId:n.connectionId});return}if(n.type==="orcha.runtime.request"){await this.handleRequest(n);return}n.type==="runtime_node.ping"&&this.send({type:"runtime_node.pong",ts:new Date().toISOString(),supportedMethods:We,sandboxCapabilities:this.sandboxCapabilities(),targets:this.runtimeTargets()})}}startHeartbeat(t){this.heartbeatTimer&&clearInterval(this.heartbeatTimer);let r=Math.max(1e3,Number(this.config.heartbeatIntervalMs||15e3)),n=()=>this.sendCapacityHeartbeat(t);n(),this.heartbeatTimer=setInterval(n,r),this.heartbeatTimer.unref?.()}scheduleCapacityHeartbeat(){if(!this.connected||this.capacityHeartbeatTimer)return;let t=Math.max(25,Math.min(1e3,Number(this.config.capacityHeartbeatDebounceMs||100)));this.capacityHeartbeatTimer=setTimeout(()=>{this.capacityHeartbeatTimer=null,this.sendCapacityHeartbeat()},t),this.capacityHeartbeatTimer.unref?.()}sendCapacityHeartbeat(t=this.ws){return this.connected?this.send({type:"runtime_node.heartbeat",ts:new Date().toISOString(),supportedMethods:We,sandboxCapabilities:this.sandboxCapabilities(),targets:this.runtimeTargets()},t):!1}async handleRequest(t){let r=a(t.id),n=a(t.method),s=u(t.params)?t.params:{};try{let i=await this.invoke(n,s,r);this.send({type:"orcha.runtime.response",id:r,ok:!0,result:i})}catch(i){this.send({type:"orcha.runtime.response",id:r,ok:!1,error:{code:i.code||"RUNTIME_NODE_ERROR",message:i.message||String(i),...i.detail===void 0?{}:{detail:i.detail}}})}}async invoke(t,r,n){if(t==="health")return this.bridge.health();if(t==="agents/create")return this.bridge.createAgent(r);if(t==="agents/dispatch")return this.bridge.dispatch(r,{onUpdate:s=>this.sendUpdate(n,s)});if(t==="sessions/prompt")return this.bridge.prompt(r,{onUpdate:s=>this.sendUpdate(n,s)});if(t==="sessions/policy")return this.bridge.updatePolicy(r);if(t==="sessions/cancel")return this.bridge.cancel(r);if(t==="permissions/respond")return this.bridge.respondPermission(r);throw Object.assign(new Error(`unsupported Orcha runtime method: ${t}`),{code:"METHOD_NOT_FOUND"})}sendUpdate(t,r){this.send({type:"orcha.runtime.event",requestId:t,eventType:"runtime.update",payload:r})}send(t,r=this.ws){return!r||r!==this.ws||r.readyState!==it?!1:(r.send(JSON.stringify(t)),!0)}};import{existsSync as Sn,readFileSync as Ko}from"node:fs";import{dirname as Go,resolve as Jt}from"node:path";import{fileURLToPath as zo}from"node:url";var Vo=/^[A-Za-z_][A-Za-z0-9_]*$/;function En(e=process.env,t=process.cwd()){let r=a(e.ORCHA_RUNTIME_ENV_FILE),n=r?Jt(t,r):Jt(t,".env");if(!Sn(n))return r&&h("warn","config","runtime env file not found",{path:n}),{loaded:!1,path:n,keys:[]};let s=[],i=Ko(n,"utf8");for(let o of i.split(/\r?\n/)){let c=Xo(o);if(!c)continue;let[l,d]=c;Object.prototype.hasOwnProperty.call(e,l)||(e[l]=d,s.push(l))}return h("info","config","runtime env file loaded",{path:n,keyCount:s.length}),{loaded:!0,path:n,keys:s}}function On(e=process.env){let t=a(e.ORCHA_RUNTIME_MODE||(e.ORCHA_RUNTIME_ORCHA_URL?"node":"server")),r=a(e.ORCHA_RUNTIME_BRIDGE_HOST||"127.0.0.1"),n=!1,s=Go(zo(import.meta.url)),i=Jt(s,"sandbox","broker.js"),o=Jt(s,"orcha-runtime-sandbox-broker.js"),c=Sn(i)?i:o,l=a(e.ORCHA_RUNTIME_SANDBOX_BROKER_COMMAND);return{mode:t,host:r,port:_(e.ORCHA_RUNTIME_BRIDGE_PORT,5588),token:e.ORCHA_RUNTIME_BRIDGE_TOKEN||"",orchaUrl:a(e.ORCHA_RUNTIME_ORCHA_URL),nodeToken:e.ORCHA_RUNTIME_NODE_TOKEN||e.ORCHA_RUNTIME_BRIDGE_TOKEN||"",nodeId:a(e.ORCHA_RUNTIME_NODE_ID||e.HOSTNAME||"local-runtime-node"),nodeName:a(e.ORCHA_RUNTIME_NODE_NAME||e.ORCHA_RUNTIME_NODE_ID||e.HOSTNAME||"Local Runtime Node"),reconnectMs:_(e.ORCHA_RUNTIME_RECONNECT_MS,3e3),connectTimeoutMs:_(e.ORCHA_RUNTIME_CONNECT_TIMEOUT_MS||e.ORCHA_RUNTIME_WS_CONNECT_TIMEOUT_MS,1e4),defaultTargetCode:e.ORCHA_RUNTIME_DEFAULT_TARGET||"echo",requestLimitBytes:_(e.ORCHA_RUNTIME_REQUEST_LIMIT_BYTES,1048576),initializeTimeoutMs:_(e.ORCHA_RUNTIME_INITIALIZE_TIMEOUT_MS,3e4),sessionPromptTimeoutMs:_(e.ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS,36e5),permissionRequestTimeoutMs:_(e.ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS,3e5),sessionIdleTtlMs:_(e.ORCHA_RUNTIME_SESSION_IDLE_TTL_MS,6e5),sessionCleanupIntervalMs:_(e.ORCHA_RUNTIME_SESSION_CLEANUP_INTERVAL_MS,6e4),maxSessionsPerTarget:_(e.ORCHA_RUNTIME_MAX_SESSIONS_PER_TARGET,8),openClawSessionIdleTtlMs:_(e.ORCHA_RUNTIME_OPENCLAW_SESSION_IDLE_TTL_MS,6e4),openClawMaxSessions:_(e.ORCHA_RUNTIME_OPENCLAW_MAX_SESSIONS,1),heartbeatIntervalMs:_(e.ORCHA_RUNTIME_HEARTBEAT_INTERVAL_MS,15e3),sandboxRequired:n,sandboxBrokerCommand:l||process.execPath,sandboxBrokerArguments:Je(e.ORCHA_RUNTIME_SANDBOX_BROKER_ARGUMENTS,"ORCHA_RUNTIME_SANDBOX_BROKER_ARGUMENTS",l?[]:[c]),sandboxProbeTimeoutMs:_(e.ORCHA_RUNTIME_SANDBOX_PROBE_TIMEOUT_MS,1e4),sandboxTempRoot:a(e.ORCHA_RUNTIME_SANDBOX_TEMP_ROOT),trustedWorkspaceRoots:Je(e.ORCHA_RUNTIME_TRUSTED_WORKSPACE_ROOTS,"ORCHA_RUNTIME_TRUSTED_WORKSPACE_ROOTS"),trustedToolchainRoots:Je(e.ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS,"ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS"),egressProxyRequired:Jo(e.ORCHA_RUNTIME_EGRESS_PROXY_REQUIRED,t==="node"),egressProxySocket:a(e.ORCHA_RUNTIME_EGRESS_PROXY_SOCKET),egressProxyToken:a(e.ORCHA_RUNTIME_EGRESS_PROXY_TOKEN),egressGrantMaxTtlMs:_(e.ORCHA_RUNTIME_EGRESS_GRANT_MAX_TTL_MS,9e5),targets:Wo(e.ORCHA_RUNTIME_TARGETS_JSON||"")}}function Wo(e){if(!a(e))return{};try{let t=JSON.parse(e);if(u(t))return t}catch(t){h("warn","config","invalid ORCHA_RUNTIME_TARGETS_JSON",{error:String(t)})}return{}}function Jo(e,t){let r=a(e).toLowerCase();if(!r)return t;if(["true","1","yes","on"].includes(r))return!0;if(["false","0","no","off"].includes(r))return!1;throw new Error(`invalid boolean configuration value: ${r}`)}function Je(e,t,r=[]){let n=a(e);if(!n)return[...r];let s;try{s=JSON.parse(n)}catch{throw new Error(`${t} must be a JSON string array`)}if(!Array.isArray(s)||s.some(i=>typeof i!="string"))throw new Error(`${t} must be a JSON string array`);return s.map(i=>i.trim()).filter(Boolean)}function Xo(e){let t=e.trim();if(!t||t.startsWith("#"))return null;let r=t.startsWith("export ")?t.slice(7).trimStart():t,n=r.indexOf("=");if(n<=0)return null;let s=r.slice(0,n).trim();if(!Vo.test(s))return null;let i=Yo(r.slice(n+1).trim());return[s,i]}function Yo(e){if(!e)return"";let t=e[0];if((t==='"'||t==="'")&&e.endsWith(t)){let r=e.slice(1,-1);return t==='"'?Zo(r):r}return Qo(e).trim()}function Zo(e){return e.replaceAll("\\n",`
|
|
19
|
-
`).replaceAll("\\r","\r").replaceAll("\\t"," ").replaceAll('\\"','"').replaceAll("\\\\","\\")}function
|
|
20
|
-
`),console.log(JSON.stringify({status:"started",pid:
|
|
21
|
-
`);
|
|
22
|
-
`:""),
|
|
10
|
+
${s}`:s;nn(t,r,n,d,s)&&(o=1,c=1)}return s&&i&&(t.finalTextSeen=!0),tn(t,Qr(e,t.artifactOptions)),(bi(e)||Ai(e)||Ni(e)||i)&&n({sessionId:r,update:{sessionUpdate:"runtime_event",event:en(e)}}),{textCount:o,finalTextCount:c,thoughtCount:l}}function me(e,t,r,n,s=Date.now()){if(!t)return{artifactCount:0,transcriptCount:0,textCount:0,finalTextCount:0,thoughtCount:0};let i=e.artifacts.size,o=0,c=0,l=0,d=0,f=xi(t,r,s);if(f){let p=Math.min(t.processedLines.get(f.path)||0,f.events.length),h=e.artifacts.size;for(let g of f.events.slice(p)){let y=Mi(g,e,r,n);c+=y.textCount,l+=y.finalTextCount,d+=y.thoughtCount}t.processedLines.set(f.path,f.events.length),(f.events.length>p||e.artifacts.size>h)&&(o=1)}return{artifactCount:e.artifacts.size-i,transcriptCount:o,textCount:c,finalTextCount:l,thoughtCount:d}}function Ui(e,{remove:t=!0}={}){if(!e||!Vr(e))return"";try{return Wr(e,"utf8").trim()}catch{return""}finally{t&&Lt(e)}}function Lt(e){if(e)try{Ks(e)}catch{}}function Pi(e,t){return{artifactCount:(e?.artifactCount||0)+(t?.artifactCount||0),transcriptCount:(e?.transcriptCount||0)+(t?.transcriptCount||0),textCount:(e?.textCount||0)+(t?.textCount||0),finalTextCount:(e?.finalTextCount||0)+(t?.finalTextCount||0),thoughtCount:(e?.thoughtCount||0)+(t?.thoughtCount||0)}}function ki(e){return new Promise(t=>setTimeout(t,e))}function Li(e,t,r,n){return n?(e.finalTextSeen=!0,e.emittedTexts.has(n)||(e.emittedTexts.add(n),r({sessionId:t,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:n}}})),!0):!1}async function Di(e,t,r,n,s,i){let o=me(e,t,r,n,Date.now()),c=()=>Li(e,r,n,Ui(s,{remove:!1}));if(c()||e.finalTextSeen)return Lt(s),o;let l=oi(i);if(l<=0||!t&&!s)return Lt(s),o;let d=Date.now()+l,f=Math.min(rn(i),100);for(;!e.finalTextSeen&&Date.now()<d&&(await ki(Math.min(f,Math.max(0,d-Date.now()))),o=Pi(o,me(e,t,r,n,Date.now())),!c()););return Lt(s),o}var Ht=class{constructor(t,r,n={}){this.agent=t,this.target=r,this.options=n,this.active=new Map}async sessionNew(t={}){let r=t.mcpServers||[];if(r.length&&t.metadata?.source==="conversation_delegation"&&Br(this.target)==="codex"){if(this.options.prepareLaunch)throw Object.assign(new Error("Codex task MCP requires a reachable node-local transport; this sandbox launcher does not provide one"),{code:"unsupported_dynamic_mcp"});this.taskMcp=await $r(r)}else if(r.length&&t.metadata?.source==="conversation_delegation")throw Object.assign(new Error("This CLI adapter does not support task-scoped MCP"),{code:"unsupported_dynamic_mcp"});return{sessionId:`cli-${this.agent.agentId}-${nt()}`}}async refreshMcpServers(t){if(!this.taskMcp)throw Object.assign(new Error("The original Codex MCP binding is unavailable"),{code:"RUNTIME_OPERATION_NOT_FOUND"});await this.taskMcp.refresh(t)}async sessionPrompt(t,r,n){let s=Date.now(),i=a(this.target.command);if(!i)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let o=a(t.sessionId)||nt(),c=It(t.prompt),l=a(this.target.promptMode||"stdin"),d=[...this.taskMcp?.args||[],...this.buildArgs(l,c)],f=et(this.target,this.agent.workspace),p=typeof this.options.prepareLaunch=="function",g=si(i,d,this.target)?p?`/tmp/orcha-runtime-last-message-${nt()}.txt`:$(Xr(),`orcha-runtime-last-message-${nt()}.txt`):"";g&&d.push("--output-last-message",g);let y={...u(this.target.env)?this.target.env:{},...this.taskMcp?.environment||{},...l==="env"?{ORCHA_RUNTIME_PROMPT:c}:{},ORCHA_AGENT_ID:this.agent.agentId,ORCHA_SESSION_ID:o},R=p?await this.options.prepareLaunch({command:i,args:d,cwd:f,environment:y}):{command:i,args:d,cwd:f,environment:{...process.env,...y},cleanup:async()=>{}},A=p?hi(R):pi(this.target,o),T=A.root,w=gi(this.target,T,R),S=ii(i,this.target),I={...this.target,targetCode:this.agent.targetCode,cwd:f,...p?{codexHome:$(R.homeDirectory,".codex")}:{}},P=S?Ti(I,s):new Set,v=p&&g?$(R.tempDirectory,g.slice(5)):g,N=_(this.target.timeoutMs||this.target.sessionPromptTimeoutMs,_(this.options.sessionPromptTimeoutMs,Vs));p||(R.environment.ORCHA_RUNTIME_ARTIFACT_DIR=T);let O=zr(R.command,R.args,{cwd:R.cwd,env:R.environment,stdio:["pipe","pipe","pipe"],detached:process.platform!=="win32",windowsHide:!0});this.active.set(o,O),m("info","runtime.cli","runtime prompt started",{target:this.agent.targetCode,sessionId:o,pid:O.pid,timeoutMs:N,isolation:R.isolation});let Z="",at=a(this.target.outputMode||"text"),M={artifacts:new Map,emittedTexts:new Set,emittedThoughtTexts:new Set,value:"",artifactOptions:w,finalTextSeen:!1,finalTextOnly:li(t,this.target),emitThoughtChunks:ci(t,this.target),terminalOutcome:null,terminalProtocol:Br(this.target),emitTerminal:null},te=S?fi(I,c,s,P):null;return O.stdout.setEncoding("utf8"),O.stdout.on("data",Q=>this.handleStdout(Q,at,M,o,r)),O.stderr.setEncoding("utf8"),O.stderr.on("data",Q=>{Z+=Q,this.target.emitStderr===!0&&r({sessionId:o,update:{sessionUpdate:"runtime_stderr_chunk",content:{type:"text",text:Q}}})}),l==="stdin"?O.stdin.end(c):O.stdin.end(),await new Promise((Q,ee)=>{let ct=!1,cr=!1,Rt=null,ut=null,re=te&&ai(this.target,t)?setInterval(()=>{try{me(M,te,o,r)}catch(x){m("warn","runtime.cli","codex transcript stream poll failed",{target:this.agent.targetCode,sessionId:o,error:String(x?.message||x)})}},rn(this.target)):null;re?.unref?.();let ur=setTimeout(()=>{cr=!0,m("warn","runtime.cli","runtime prompt timed out; terminating child",{target:this.agent.targetCode,sessionId:o,pid:O.pid,timeoutMs:N}),Dt(O,"SIGTERM"),Rt=setTimeout(()=>{m("warn","runtime.cli","runtime prompt force killing child",{target:this.agent.targetCode,sessionId:o,pid:O.pid}),Dt(O,"SIGKILL")},Yr),Rt.unref?.(),lt(Object.assign(new Error(`runtime CLI timed out after ${N}ms`),{code:"RUNTIME_CLI_TIMEOUT"}))},N);ur.unref?.();let lr=async()=>{clearTimeout(ur),ut&&clearTimeout(ut),re&&clearInterval(re),Rt&&!cr&&clearTimeout(Rt),mi(A,{target:this.agent.targetCode,sessionId:o}),this.active.delete(o),M.emitTerminal=null,await R.cleanup?.()},Zn=x=>{ct||(ct=!0,lr().then(()=>Q(x),ee))},lt=x=>{ct||(ct=!0,lr().then(()=>ee(x),F=>{m("warn","runtime.cli","sandbox launch cleanup failed",{target:this.agent.targetCode,sessionId:o,error:String(F?.message||F)}),ee(x)}))};M.emitTerminal=x=>{let F={...u(x.result)?x.result:{},_artifacts:[...M.artifacts.values()]};try{n?.({...x,result:F})}catch(z){m("warn","runtime.cli","runtime terminal listener failed",{target:this.agent.targetCode,sessionId:o,error:String(z?.message||z)})}let H=Math.max(0,_(this.target.terminalExitGraceMs,Qs));ut=setTimeout(()=>{ut=null,!(ct||this.active.get(o)!==O)&&(m("warn","runtime.cli","runtime stayed alive after terminal event; terminating child",{target:this.agent.targetCode,sessionId:o,pid:O.pid,terminalProtocol:M.terminalProtocol,graceMs:H}),fe(O))},H),ut.unref?.()},O.on("error",x=>{m("warn","runtime.cli","runtime child error",{target:this.agent.targetCode,sessionId:o,pid:O.pid,error:String(x?.message||x)}),lt(x)}),O.on("exit",(x,F)=>{(async()=>{at==="json-lines"&&M.value.trim()&&this.handleStdout(`
|
|
11
|
+
`,at,M,o,r);let H=await Di(M,te,o,r,v,this.target);(H.artifactCount>0||H.textCount>0||H.thoughtCount>0)&&m("info","runtime.cli","codex transcript updates collected",{target:this.agent.targetCode,sessionId:o,artifactCount:H.artifactCount,textCount:H.textCount,finalTextCount:H.finalTextCount,thoughtCount:H.thoughtCount,transcriptCount:H.transcriptCount});let z=Z.trim();if(z&&m("debug","runtime.cli","runtime stderr",{target:this.agent.targetCode,sessionId:o,stderr:z}),m("info","runtime.cli","runtime prompt finished",{target:this.agent.targetCode,sessionId:o,pid:O.pid,exitCode:x,signal:F,artifactCount:M.artifacts.size,finalTextSeen:M.finalTextSeen}),M.terminalOutcome?.status==="failed"){lt(M.terminalOutcome.error);return}if(x!==0&&M.terminalOutcome?.status!=="completed"){let Qn=Object.assign(new Error(`runtime CLI exited with code ${x??"unknown"}${F?` (${F})`:""}`),{code:"RUNTIME_CLI_EXIT_NONZERO",exitCode:x,signal:F});lt(Qn);return}Zn({stopReason:"end_turn",exitCode:x,signal:F,_artifacts:[...M.artifacts.values()],...z?{stderr:z}:{}})})().catch(lt)})})}buildArgs(t,r){let n=b(this.target.args);return t==="args"?[...n,r]:n}handleStdout(t,r,n,s,i){if(r!=="json-lines"){i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:t}}});return}n.value+=t;let o=n.value.split(/\r?\n/);n.value=o.pop()||"";for(let c of o){let l=c.trim();if(l)try{let d=JSON.parse(l);tn(n,Qr(d,n.artifactOptions)),i({sessionId:s,update:{sessionUpdate:"runtime_event",event:en(d)}});let f=Zr(d),p=_e(d);f&&n.emitThoughtChunks&&!p&&ni(d)?sn(n,s,i,f):f&&di(n,p)&&nn(n,s,i,f),f&&p&&(n.finalTextSeen=!0);let h=ri(d,n.terminalProtocol);h&&!n.terminalOutcome&&(h.status==="failed"||n.finalTextSeen||n.artifacts.size>0)&&(n.terminalOutcome=h,n.emitTerminal?.(h))}catch{i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`${c}
|
|
12
|
+
`}}})}}}async sessionCancel(t){let r=a(t.sessionId),n=this.active.get(r);return n?(m("info","runtime.cli","cancelling runtime child",{target:this.agent.targetCode,sessionId:r,pid:n.pid}),fe(n),{ok:!0,cancelled:!0}):{ok:!0,cancelled:!1}}async stop(t="stop"){for(let[r,n]of this.active.entries())m("info","runtime.cli","stopping runtime child",{target:this.agent.targetCode,sessionId:r,pid:n.pid,reason:t}),fe(n);this.active.clear(),await this.taskMcp?.close(),this.taskMcp=null}};var Te="ORCHA_RUNTIME_OUTPUT_START",we="ORCHA_RUNTIME_OUTPUT_END",Re="ORCHA_RUNTIME_CONTROL_START",Se="ORCHA_RUNTIME_CONTROL_END",Ee=Te,Oe=we,Ie=Re,xe=Se,Ce=[Te,we,Re,Se],vi=new Set(["_artifacts","_decision","_meta"]),Hi=new RegExp(`(?:^|(?<=[\\r\\n]))[ \\t]*(?<marker>${Ce.join("|")})[ \\t]*(?=\\r\\n?|\\n|$)`,"g"),k=class extends Error{constructor(t,r,n){super(r),this.name="RuntimeResultProtocolError",this.code=t,this.detail={rawOutput:n}}};function dn(e){let t=typeof e=="string"?e.trimStart():"";return Ce.some(r=>t.startsWith(r))}function be(e){if(typeof e!="string")return null;let t=e,r=$i(t);if(![...r.values()].some(g=>g.length>0))return null;let n=[],s=[];for(let[g,y]of r)y.length===0?n.push(g):y.length>1&&s.push(g);if(n.length>0||s.length>0){let g=[];throw n.length>0&&g.push(`\u7F3A\u5C11 ${n.join(", ")}`),s.length>0&&g.push(`\u91CD\u590D ${s.join(", ")}`),new k("invalid_markers",`Runtime Result \u534F\u8BAE\u6807\u8BB0\u4E0D\u5B8C\u6574\uFF1A${g.join("\uFF1B")}`,t)}let i=r.get(Te)[0],o=r.get(we)[0],c=r.get(Re)[0],l=r.get(Se)[0];if(!(i.end<=o.start&&o.end<=c.start&&c.end<=l.start))throw new k("invalid_marker_order","Runtime Result \u534F\u8BAE\u6807\u8BB0\u987A\u5E8F\u9519\u8BEF\uFF1A\u5FC5\u987B\u5148\u8F93\u51FA OUTPUT \u5757\uFF0C\u518D\u8F93\u51FA CONTROL \u5757",t);let d=Fi(t.slice(i.end,o.start));if(!d.trim())throw new k("empty_output","Runtime Result OUTPUT \u5757\u4E0D\u80FD\u4E3A\u7A7A",t);let f=t.slice(c.end,l.start).trim();if(!f)throw new k("empty_control","Runtime Result CONTROL \u5757\u4E0D\u80FD\u4E3A\u7A7A",t);let p;try{p=JSON.parse(f)}catch(g){throw new k("invalid_control_json",`Runtime Result CONTROL \u5757\u4E0D\u662F\u5408\u6CD5 JSON\uFF1A${String(g?.message||g)}`,t)}if(!ln(p))throw new k("invalid_control_type","Runtime Result CONTROL \u5757\u5FC5\u987B\u662F JSON \u5BF9\u8C61",t);let h=Object.keys(p).filter(g=>!vi.has(g)).sort();if(h.length>0)throw new k("invalid_control_keys",`Runtime Result CONTROL \u5757\u5305\u542B\u975E\u6807\u51C6\u5B57\u6BB5\uFF1A${h.join(", ")}`,t);if("_artifacts"in p&&!Array.isArray(p._artifacts))throw new k("invalid_control_field_type","Runtime Result CONTROL \u5757\u7684 _artifacts \u5FC5\u987B\u662F JSON \u6570\u7EC4",t);for(let g of["_decision","_meta"])if(g in p&&!ln(p[g]))throw new k("invalid_control_field_type",`Runtime Result CONTROL \u5757\u7684 ${g} \u5FC5\u987B\u662F JSON \u5BF9\u8C61`,t);return{output:d,...p}}function $i(e){let t=new Map(Ce.map(r=>[r,[]]));for(let r of e.matchAll(Hi))t.get(r.groups.marker).push({start:r.index,end:r.index+r[0].length});return t}function Fi(e){let t=e.match(/^(?:\r\n|\r|\n)/)?.[0]||"",r=t?e.slice(t.length):e;return t&&r.endsWith(t)?r.slice(0,-t.length):r}function ln(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}import{createHash as Bi}from"node:crypto";var qi="orcha.goal-contract/v1",ji=new Set(["complete","completed","done","ok","passed","success","succeeded"]),Ki=new Set(["aborted","blocked","cancelled","canceled","denied","error","failed","failure","timeout","timed_out"]),Gi=new Map([["exec_command","run_command"],["local_shell_call","run_command"],["run_command","run_command"],["apply_patch","apply_patch"],["read_file","read_file"],["list_files","list_files"],["plugin_operation","plugin_operation"]]);function Ue(e){return Bi("sha256").update(q(e)).digest("hex")}function pn(e){if(!mn(e))return"";let t=["The following Orcha goal contract is immutable for this turn. Do not narrow its outcome or constraints.",`<goal_contract>${JSON.stringify(e)}</goal_contract>`];return e.verificationPlan?.required===!0&&t.push("Every verification check must be satisfied by a real successful tool call from one of its toolNames.","Each check requires requiredMatches distinct successful tool call IDs; repeated updates for one call count once.","A final text claim is not verification; missing or failed tool evidence prevents completion."),t.join(`
|
|
13
|
+
`)}function hn(e,t,r=""){if(!mn(e))return e==null?null:{required:!0,status:"failed",outcome:a(e?.outcome),goalContractHash:"",checks:[],errorCode:"invalid_goal_contract"};let n=Ue(e),s=e.verificationPlan.required===!0;if(a(r)&&a(r)!==n)return{required:s,status:"failed",outcome:e.outcome,goalContractHash:n,checks:[],errorCode:"goal_contract_hash_mismatch"};if(!s)return{required:!1,status:"not_required",outcome:e.outcome,goalContractHash:n,checks:[]};let i=zi(t),o=e.verificationPlan.checks.map(l=>Qi(l,i));return{required:!0,status:o.some(l=>l.status==="failed")?"failed":o.some(l=>l.status==="missing")?"missing":"passed",outcome:e.outcome,goalContractHash:n,checks:o}}function mn(e){if(!u(e)||e.schemaVersion!==qi||!a(e.outcome))return!1;let t=e.verificationPlan;if(!u(t)||typeof t.required!="boolean"||!Array.isArray(t.checks)||t.required&&t.checks.length===0)return!1;let r=new Set;for(let n of t.checks)if(!u(n)||!a(n.id)||r.has(a(n.id))||(r.add(a(n.id)),!Array.isArray(n.toolNames)||n.toolNames.length===0||n.toolNames.some(s=>!a(s)))||!Number.isSafeInteger(n.requiredMatches)||n.requiredMatches<1||n.arguments!==void 0&&!u(n.arguments))return!1;return!0}function zi(e){let t=new Map,r=[];for(let n of Array.isArray(e)?e:[]){let s=u(n?.update)?n.update:{},i=a(s.sessionUpdate);if(i==="runtime_event"){Vi(s.event,t,r);continue}if(i==="tool_call"){let o=Ft(s)||`tool-${r.length+1}`,c=$t(t,r,o),l=Ne(s,s.name||s.toolName||s.kind);c.toolName=l.toolName,c.arguments=l.arguments,c.status=gt(s.status),c.evidence=qt(s);continue}if(i==="tool_call_update"){let o=Ft(s);if(!o)continue;let c=$t(t,r,o),l=Ne(s,s.name||s.toolName||s.kind);c.toolName||=l.toolName,Object.keys(c.arguments).length===0&&(c.arguments=l.arguments),c.status=gt(s.status),c.evidence.push(...qt(s))}}return r}function Vi(e,t,r){let n=u(e)&&u(e.payload)?e.payload:u(e)?e:{},s=a(n.type);if(["function_call","custom_tool_call","local_shell_call","mcp_tool_call"].includes(s)){let c=Ft(n)||`runtime-${r.length+1}`,l=$t(t,r,c),d=Ne(n,n.name||n.tool||s,s);l.toolName=d.toolName,l.arguments=d.arguments,l.status=gt(n.status),l.evidence.push(...qt(n));return}if(!["function_call_output","custom_tool_call_output","local_shell_call_output","mcp_tool_call_output"].includes(s))return;let i=Ft(n);if(!i)return;let o=$t(t,r,i);o.status=Yi(n,o.toolName),o.evidence.push(...qt(n))}function $t(e,t,r){let n=e.get(r);return n||(n={toolCallId:r,toolName:"",arguments:{},status:"unknown",evidence:[]},e.set(r,n),t.push(n)),n}function Ji(e){let t=a(e).toLowerCase();return Gi.get(t)||t}function Ne(e,t,r=""){let n=Wi(e),s=a(r)==="mcp_tool_call"||a(e?.kind).toLowerCase()==="mcp",i=u(e?._meta)?e._meta:{},o=a(e?.server||e?.serverName||e?.server_name||e?.mcpServer||i.server||i.serverName).toLowerCase();if(s&&o==="orcha"){let c=a(e?.tool||e?.toolName||e?.name||t);return{toolName:"plugin_operation",arguments:{...n,...c?{operationCode:c}:{}}}}return{toolName:Ji(t),arguments:n}}function Ft(e){return u(e)?a(e.call_id||e.callId||e.toolCallId||e.id):""}function Wi(e){if(!u(e))return{};for(let r of["arguments","args","rawInput","input","params","parameters"]){let n=Xi(e[r]);if(n)return n}let t={};for(let r of["cmd","command","cwd","operationCode","path","query","url"])e[r]!==void 0&&(t[r]=e[r]);return t}function Xi(e){if(u(e))return structuredClone(e);if(typeof e!="string")return null;try{let t=JSON.parse(e);return u(t)?t:null}catch{return null}}function Yi(e,t){if(!u(e))return"unknown";let r=Bt(e,0,{parseCliExitCode:t==="run_command"||t==="apply_patch"});return r.includes("failed")?"failed":r.includes("success")?"success":"unknown"}function Bt(e,t=0,r={}){if(t>8||e===null||e===void 0)return[];if(typeof e=="string")return Zi(e,t,r);if(Array.isArray(e))return e.flatMap(o=>Bt(o,t+1,r));if(!u(e))return[];let n=[];typeof e.isError=="boolean"&&n.push(e.isError?"failed":"success"),typeof e.ok=="boolean"&&n.push(e.ok?"success":"failed"),typeof e.success=="boolean"&&n.push(e.success?"success":"failed");let s=gt(e.status);s!=="unknown"&&n.push(s);let i=e.exitCode??e.exit_code;typeof i=="number"&&Number.isFinite(i)&&n.push(i===0?"success":"failed");for(let o of["output","result","structuredContent","content"])e[o]!==void 0&&n.push(...Bt(e[o],t+1,r));return n}function Zi(e,t,r){let n=e.trim();if(!n)return[];try{return Bt(JSON.parse(n),t+1,r)}catch{}if(r.parseCliExitCode!==!0)return[];let s=[];for(let i of n.matchAll(/(?:process\s+exited\s+with\s+code|exit\s+code\s*:?)\s*(-?\d+)/gi))s.push(Number(i[1])===0?"success":"failed");return s}function gt(e){let t=a(e).toLowerCase();return ji.has(t)?"success":Ki.has(t)?"failed":"unknown"}function qt(e){if(!u(e))return[];let t=u(e.output)?e.output:{},r=[e.verificationEvidence,u(e.verification)?e.verification.evidence:null,t.verificationEvidence,u(t.verification)?t.verification.evidence:null],n=[];for(let s of r)for(let i of Array.isArray(s)?s:s?[s]:[])!u(i)||!a(i.id)||n.push({id:a(i.id),status:gt(i.status??(i.passed===!0?"passed":i.passed===!1?"failed":"")),...a(i.message)?{message:a(i.message)}:{}});return n}function Qi(e,t){let r=t.filter(o=>e.toolNames.includes(o.toolName)&&Me(e.arguments||{},o.arguments)),n=a(e.evidenceId),s=r.filter(o=>o.status==="success"&&(!n||o.evidence.some(c=>c.id===n&&c.status==="success")));if(s.length>=e.requiredMatches)return Ae(e,"passed",s,`Runtime tool evidence passed ${s.length} times.`);let i=r.filter(o=>o.status==="failed"||n&&o.evidence.some(c=>c.id===n&&c.status==="failed"));return s.length===0&&i.length?Ae(e,"failed",i,"Runtime tool evidence failed."):Ae(e,"missing",s,`Only ${s.length}/${e.requiredMatches} required tool executions passed.`)}function Ae(e,t,r,n){let s=r.map(i=>i.toolCallId).filter(Boolean);return{id:e.id,status:t,message:n,...a(e.description)?{description:a(e.description)}:{},toolNames:e.toolNames,requiredMatches:e.requiredMatches,observedMatches:s.length,toolCallIds:s,...u(e.arguments)?{arguments:e.arguments}:{},...a(e.evidenceId)?{evidenceId:a(e.evidenceId)}:{}}}function Me(e,t){return Array.isArray(e)?Array.isArray(t)&&e.length===t.length&&e.every((r,n)=>Me(r,t[n])):u(e)?u(t)?Object.entries(e).every(([r,n])=>Object.hasOwn(t,r)&&Me(n,t[r])):!1:Object.is(e,t)}function q(e){if(e===null||typeof e=="boolean")return JSON.stringify(e);if(typeof e=="string")return fn(e);if(typeof e=="number"){if(!Number.isFinite(e))throw new Error("invalid_jcs_number");return JSON.stringify(Object.is(e,-0)?0:e)}if(Array.isArray(e))return`[${Array.from({length:e.length},(t,r)=>{if(!Object.hasOwn(e,r))throw new Error("invalid_jcs_json_value");return q(e[r])}).join(",")}]`;if(u(e))return`{${Object.keys(e).sort().map(t=>`${fn(t)}:${q(e[t])}`).join(",")}}`;throw new Error("invalid_jcs_json_value")}function fn(e){return to(e),JSON.stringify(e)}function to(e){for(let t=0;t<e.length;t+=1){let r=e.charCodeAt(t);if(r>=55296&&r<=56319){let n=e.charCodeAt(t+1);if(!(n>=56320&&n<=57343))throw new Error("invalid_jcs_unicode");t+=1}else if(r>=56320&&r<=57343)throw new Error("invalid_jcs_unicode")}}import{spawn as eo}from"node:child_process";import{createHash as ro,randomUUID as no}from"node:crypto";import{constants as so}from"node:fs";import{access as io,mkdir as Pe,readdir as oo,realpath as _t,rm as ao,stat as co}from"node:fs/promises";import uo from"node:http";import{tmpdir as lo}from"node:os";import{isAbsolute as yt,join as st,relative as gn,resolve as Le}from"node:path";var De=1,fo="orcha.process-isolation/v1",ve="orcha.egress-proxy/v1",po="--disable-wasm-trap-handler",jt={read_only:0,workspace_write:1,workspace_network:2},ke={read_only:["read_only","denied"],workspace_write:["workspace_write","denied"],workspace_network:["workspace_write","restricted"]},ho=new Set([".env",".git-credentials",".netrc",".npmrc",".pypirc","credentials.json","secrets.json","id_rsa","id_ed25519"]);function J(e){if(!u(e))throw E("RUNTIME_SANDBOX_POLICY_REQUIRED","sandboxPolicy is required");let t=structuredClone(e),r=a(t.accessMode),n=a(t.accessModeCeiling);if(!(r in ke)||!(n in ke))throw E("RUNTIME_SANDBOX_POLICY_INVALID","unsupported runtime access mode");if(jt[r]>jt[n])throw E("RUNTIME_SANDBOX_POLICY_INVALID","access mode exceeds its ceiling");let[s,i]=ke[r];if(t.filesystemMode!==s||t.networkMode!==i)throw E("RUNTIME_SANDBOX_POLICY_INVALID","runtime access profile does not match its mode");if(Number(t.policySchemaVersion)!==De||!Number.isInteger(Number(t.policyRevision))||Number(t.policyRevision)<1)throw E("RUNTIME_SANDBOX_POLICY_INVALID","unsupported sandbox policy schema or revision");for(let[c,l]of Object.entries({outsideWorkspaceAccess:"denied",hostAccess:"denied",hostEnvironmentAccess:"denied",dockerSocketAccess:"denied",environmentMode:"allowlist"}))if(t[c]!==l)throw E("RUNTIME_SANDBOX_POLICY_INVALID",`${c} cannot be relaxed`);let o=u(t.processIsolation)?t.processIsolation:{};if(o.mode!=="required"||o.backend==="direct")throw E("RUNTIME_SANDBOX_POLICY_INVALID","strong process isolation is required");if(Array.isArray(t.alwaysApprovedApprovalKeys)&&t.alwaysApprovedApprovalKeys.length)throw E("RUNTIME_SANDBOX_POLICY_INVALID","persistent runtime approvals are forbidden");return t}function _n(e,t){let r=J(e),n=J(t);return jt[n.accessMode]<jt[r.accessMode]}async function yn(e){if(!e.sandboxRequired)return{dispatchable:!0,enforced:!1,backend:"direct",daemonStatus:"not_required",daemonProtocolVersion:"",policySchemaVersions:[De],runtimePolicyUpdates:!1,workspaceSync:!1,egressProxy:!1,reason:"external_runtime_sandbox_not_required"};let t=await wn(e.sandboxBrokerCommand,process.env.PATH||"");if(!t)throw E("RUNTIME_SANDBOX_UNAVAILABLE","sandbox broker is not executable");let r=await To(t,b(e.sandboxBrokerArguments),e.sandboxProbeTimeoutMs);if(r.enforced!==!0||a(r.protocolVersion)!=="orcha.runtime-sandbox-broker/v1"||!["bubblewrap","broker"].includes(a(r.backend)))throw E("RUNTIME_SANDBOX_UNAVAILABLE","sandbox broker did not report enforced isolation");let n=u(r.probes)?r.probes:{};for(let s of["emptyRoot","outsideWorkspaceDenied","hostFilesystemDenied","sensitiveFilesDenied","environmentAllowlist","dockerSocketDenied","networkNamespace","workspaceReadOnly","workspaceWrite","resourceLimits"])if(n[s]!==!0)throw E("RUNTIME_SANDBOX_UNAVAILABLE",`sandbox broker probe failed: ${s}`);return e.egressProxyRequired&&await So(e),{dispatchable:!0,enforced:!0,backend:a(r.backend),daemonStatus:"ok",daemonProtocolVersion:a(r.protocolVersion||"orcha.runtime-sandbox-broker/v1"),policySchemaVersions:[De],runtimePolicyUpdates:!0,workspaceSync:!1,egressProxy:e.egressProxyRequired}}async function He(e,t,r){let n=a(t.workspace||t.cwd),s=a(r),i=n||(t.allowRequestWorkspace===!0?s:"");if(!i||!yt(i))throw E("RUNTIME_WORKSPACE_NOT_CONFIGURED","runtime target must configure an absolute trusted workspace");let o=await _t(i);if(!(await co(o)).isDirectory())throw E("RUNTIME_WORKSPACE_INVALID","runtime workspace is not a directory");if(!(e.trustedWorkspaceRoots.length?await Promise.all(e.trustedWorkspaceRoots.map(d=>_t(d))):[o]).some(d=>Fe(d,o)))throw E("RUNTIME_WORKSPACE_OUTSIDE_TRUSTED_ROOT","runtime workspace is outside trusted roots");return o}async function Tn({config:e,target:t,command:r,args:n,cwd:s,environment:i,runId:o,agentId:c,sessionId:l,sandboxPolicy:d}){if(!e.sandboxRequired)return{command:r,args:[...n],cwd:s,environment:{...process.env,...i},tempDirectory:"",isolation:{enforced:!1,backend:"development_direct"},cleanup:async()=>{}};let f=J(d),p=await He(e,t,s),h=await _t(s);if(!Fe(p,h))throw E("RUNTIME_WORKSPACE_CWD_INVALID","runtime cwd is outside its workspace");let g=await wn(e.sandboxBrokerCommand,process.env.PATH||"");if(!g)throw E("RUNTIME_SANDBOX_UNAVAILABLE","sandbox broker is not executable");let y=`runtime-${ro("sha256").update(String(o)).digest("hex").slice(0,32)}`,R=Le(e.sandboxTempRoot||st(lo(),"orcha-runtime-sandboxes"));await Pe(R,{recursive:!0,mode:448});let A=st(R,`${y}-${no()}`),T=st(A,"home"),w=st(A,"artifacts");await Pe(T,{recursive:!0,mode:448}),await Pe(w,{recursive:!0,mode:448});let S=f.networkMode==="restricted"?await wo(e,{runId:String(o),instanceId:y,policyRevision:Number(f.policyRevision),ttlMs:Math.min(_(f.maxRuntimeSeconds,900)*1e3,e.egressGrantMaxTtlMs),maxTransferBytes:_(f.maxNetworkBytes,64*1024*1024)}):null,I={PATH:a(i.PATH||process.env.PATH),LANG:a(i.LANG||process.env.LANG||"C.UTF-8"),HOME:"/tmp/home",TMPDIR:"/tmp",USER:"orcha",LOGNAME:"orcha",SHELL:"/bin/sh",ORCHA_AGENT_ID:String(c),ORCHA_SESSION_ID:String(l),ORCHA_RUN_ID:String(o),ORCHA_RUNTIME_ARTIFACT_DIR:"/tmp/artifacts",...go(t,i)};I.HOME="/tmp/home",I.TMPDIR="/tmp",I.ORCHA_RUNTIME_ARTIFACT_DIR="/tmp/artifacts",I.NODE_OPTIONS=po;let P={schemaVersion:fo,runId:String(o),instanceId:y,workspace:p,cwd:h,filesystemMode:f.filesystemMode,networkMode:f.networkMode,environmentMode:"allowlist",deniedRelativePaths:await _o(p),temporaryDirectory:A,egressProxy:S,environment:I,resourceLimits:yo(f),readOnlyToolchainRoots:await mo(e,t)},v=!1,N=async()=>{if(!v){v=!0;try{S&&await Ro(e,S,{runId:String(o),instanceId:y})}finally{await ao(A,{recursive:!0,force:!0})}}};return{command:g,args:[...b(e.sandboxBrokerArguments),"--",r,...n],cwd:h,environment:{PATH:process.env.PATH||"",LANG:process.env.LANG||"C.UTF-8",ORCHA_PROCESS_ISOLATION_REQUEST:JSON.stringify(P)},tempDirectory:A,homeDirectory:T,artifactDirectory:w,pathMappings:[{runtimeRoot:"/tmp/artifacts",hostRoot:w},{runtimeRoot:"/tmp/home",hostRoot:T}],isolation:{enforced:!0,backend:"broker",instanceId:y,policyRevision:f.policyRevision},cleanup:N}}async function mo(e,t){let r=b(t.toolchainRoots||t.sandboxToolchainRoots);if(!r.length)return[];let n=await Promise.all(b(e.trustedToolchainRoots).map(i=>_t(i)));if(!n.length)throw E("RUNTIME_TOOLCHAIN_ROOT_NOT_TRUSTED","target toolchain roots require ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS");let s=[];for(let i of r){if(!yt(i))throw E("RUNTIME_TOOLCHAIN_ROOT_INVALID","toolchain roots must be absolute");let o=await _t(i);if(!n.some(c=>Fe(c,o)))throw E("RUNTIME_TOOLCHAIN_ROOT_NOT_TRUSTED","toolchain root is outside trusted roots");s.push(o)}return[...new Set(s)]}function go(e,t){let r=u(e.env)?e.env:{},n={};for(let[s,i]of Object.entries(r))/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&i!=null&&(n[s]=String(i));for(let s of["ORCHA_RUNTIME_PROMPT","ORCHA_RUNTIME_ARTIFACT_DIR"])t[s]!=null&&(n[s]=String(t[s]));return n}async function _o(e){let t=[],r=0,n=async s=>{let i;try{i=await oo(s,{withFileTypes:!0})}catch(o){if(s===e)throw o;return}for(let o of i){if(r+=1,r>1e4)throw E("RUNTIME_WORKSPACE_SCAN_LIMIT_EXCEEDED","workspace contains more than 10000 entries");let c=st(s,o.name),l=gn(e,c),d=o.name.toLowerCase();(ho.has(d)||d.startsWith(".env."))&&t.push(l),o.isDirectory()&&!o.isSymbolicLink()&&await n(c)}};return await n(e),t.sort()}function yo(e){return{maxCpuSeconds:Math.max(1,_(e.maxRuntimeSeconds,900)),maxMemoryBytes:_(e.maxMemoryBytes,2*1024*1024*1024),maxProcesses:_(e.maxProcesses,128),maxOpenFiles:_(e.maxOpenFiles,1024),maxFileBytes:_(e.maxFileBytes,64*1024*1024)}}async function To(e,t,r){return await new Promise((n,s)=>{let i=eo(e,[...t,"--probe"],{env:{PATH:process.env.PATH||"",LANG:"C.UTF-8"},stdio:["ignore","pipe","pipe"],windowsHide:!0}),o=[],c=[];i.stdout.on("data",d=>o.push(Buffer.from(d))),i.stderr.on("data",d=>c.push(Buffer.from(d)));let l=setTimeout(()=>i.kill("SIGKILL"),Math.max(1e3,r));i.once("error",s),i.once("close",d=>{if(clearTimeout(l),d!==0){s(E("RUNTIME_SANDBOX_UNAVAILABLE",Buffer.concat(c).toString("utf8").trim()||`sandbox probe exited with ${d}`));return}try{n(JSON.parse(Buffer.concat(o).toString("utf8")))}catch{s(E("RUNTIME_SANDBOX_UNAVAILABLE","sandbox probe returned invalid JSON"))}})})}async function wn(e,t){let r=a(e);if(!r)return"";let n=yt(r)?[r]:String(t||"").split(":").filter(Boolean).map(s=>st(s,r));for(let s of n)try{return await io(s,so.X_OK),s}catch{}return""}async function wo(e,t){if(!e.egressProxyRequired)throw E("RUNTIME_EGRESS_UNAVAILABLE","restricted network requires the Egress Proxy");let r=await $e(e,"POST","/v1/grants",{protocolVersion:ve,...t}),n={socketPath:e.egressProxySocket,grantId:a(r.grantId),credential:a(r.credential)};if(!n.grantId||!n.credential)throw E("RUNTIME_EGRESS_UNAVAILABLE","Egress Proxy returned an invalid grant");return n}async function Ro(e,t,r){await $e(e,"POST",`/v1/grants/${encodeURIComponent(t.grantId)}/revoke`,{protocolVersion:ve,...r}).catch(()=>{})}async function So(e){let t=await $e(e,"GET","/health");if(t.status!=="ok"||t.proxy!=="orcha-egress-proxy"||t.protocolVersion!==ve)throw E("RUNTIME_EGRESS_UNAVAILABLE","Egress Proxy is unavailable or incompatible")}async function $e(e,t,r,n){if(!yt(e.egressProxySocket)||!e.egressProxyToken)throw E("RUNTIME_EGRESS_UNAVAILABLE","Egress Proxy socket and token are required");return await new Promise((s,i)=>{let o=uo.request({socketPath:e.egressProxySocket,path:r,method:t,headers:{Authorization:`Bearer ${e.egressProxyToken}`,Accept:"application/json",...n?{"Content-Type":"application/json"}:{}}},c=>{let l=[],d=0;c.on("data",f=>{d+=f.length,d>1048576?o.destroy(new Error("egress response is too large")):l.push(Buffer.from(f))}),c.once("end",()=>{try{let f=JSON.parse(Buffer.concat(l).toString("utf8")||"{}");(c.statusCode||500)>=400?i(E("RUNTIME_EGRESS_UNAVAILABLE",a(f.error)||"Egress Proxy rejected the request")):s(f)}catch(f){i(f)}})});o.once("error",i),o.setTimeout(3e3,()=>o.destroy(new Error("Egress Proxy request timed out"))),n?o.end(JSON.stringify(n)):o.end()})}function Fe(e,t){let r=gn(Le(e),Le(t));return r===""||!r.startsWith("..")&&!yt(r)}function E(e,t){return Object.assign(new Error(t),{code:e})}var Be=24e3,qe=8,je=50,Ke=6e3,Oo=new Set(["fail","failed","failure","error","errored","timeout","timed_out","cancelled","canceled","aborted"]),Io=10*60*1e3,xo=60*1e3,Co=8,bo=30*60*1e3,Ao=60*1e3,No=1,On=2400,Mo=new Set(["max_tokens","max_output_tokens","length"]),Uo=new Set(["agent_message_chunk","tool_call","tool_call_update"]),Po=new Set(["agentId","taskId","executionId","sessionId","nodeId","targetCode","framework","workspace","instructions"]),ko=/(^|[_-])(token|secret|password|authorization|api[-_]?key|private[-_]?key|credential|cookie|jwt|access[-_]?token|refresh[-_]?token|service[-_]?token|execution[-_]?token)([_-]|$)/i;function Lo(e){if(!u(e))return{};let t={};for(let r of["name","code","serverName","serverCode","type","transport","url","command","protocolVersion"]){let n=a(e[r]);n&&(t[r]=n)}return t}function Do(e){return(Array.isArray(e)?e:[]).map(Lo).sort((t,r)=>{let n=q(t),s=q(r);return n<s?-1:n>s?1:0})}function vo(e){return!u(e)||e.verificationPlan?.required!==!0?!1:(Array.isArray(e.verificationPlan.checks)?e.verificationPlan.checks:[]).some(r=>u(r)&&Array.isArray(r.toolNames)&&r.toolNames.some(n=>a(n)==="plugin_operation"))}function Ho(e,t,r){let n=u(e?._meta)?e._meta:{};return{...u(e)?e:{},sessionId:t,update:u(e?.update)?e.update:{},_meta:{...n,orchaAgentId:r.agentId,runtimeSessionId:r.runtimeSessionId,bridgeUpdateId:Gt()}}}function L(e){return e==null||e===""?!1:typeof e=="string"?a(e)!=="":Array.isArray(e)?e.length>0:u(e)?Object.keys(e).length>0:!0}function In(e){let t=a(e).toLowerCase().replace(/[.。!!]+$/g,"").replace(/[\s-]+/g,"_");return Oo.has(t)}function G(e,t){let r=_(e,t);return Number.isFinite(r)&&r>0?r:t}function Tt(e,t=!1){if(typeof e=="boolean")return e;let r=a(e).toLowerCase();return["true","1","yes","y","on"].includes(r)?!0:["false","0","no","n","off"].includes(r)?!1:t}function K(e){return a(e?.type||"echo")}function xn(e){let t=K(e);return t==="acp"||t==="stdio-acp"||t==="openclaw"}function Ve(e){if(u(e)){if(Object.prototype.hasOwnProperty.call(e,"releaseAfterPrompt"))return e.releaseAfterPrompt;if(Object.prototype.hasOwnProperty.call(e,"disposeAfterPrompt"))return e.disposeAfterPrompt}}function $o(e){let t=String(e||"");if(ko.test(t))return!0;let r=t.replace(/[^a-z0-9]/gi,"").toLowerCase();return r.endsWith("token")||r.endsWith("secret")||r.endsWith("password")||r.endsWith("apikey")||r.endsWith("privatekey")||r==="authorization"||r==="cookie"||r==="jwt"||r.includes("credential")}function Je(e,t=0){if(e==null||typeof e=="number"||typeof e=="boolean")return e;if(typeof e=="string"){if(e.length<=Ke)return e;let r=e.length-Ke;return`${e.slice(0,Ke)}... [truncated ${r} characters]`}if(t>=qe)return Array.isArray(e)?`[array truncated at depth ${qe}, items=${e.length}]`:u(e)?`[object truncated at depth ${qe}, keys=${Object.keys(e).length}]`:String(e);if(Array.isArray(e)){let r=e.slice(0,je).map(n=>Je(n,t+1));return e.length>je&&r.push(`[truncated ${e.length-je} items]`),r}if(u(e)){let r={};for(let[n,s]of Object.entries(e))r[n]=$o(n)?"[REDACTED]":Je(s,t+1);return r}return String(e)}var Fo=new Set(["type","executionId","taskId","task","traceId","requestId","agentCode","stage","phase","nodeId","nodeType","capabilityCode","operationCode","outputType","artifactType","input","inputs","rejection","previous","artifactRefs","outputSchema","executionPolicy","resultContract"]);function Bo(e){if(!u(e))return e;let t={};for(let r of Fo)L(e[r])&&(t[r]=e[r]);return t}function qo(e){if(!u(e))return e;let t={...e};return u(t.renderedPayload)&&(t.renderedPayload=Bo(t.renderedPayload)),t}function jo(e){let t=u(e)?e:{},r={};L(t.metadata)&&(r.metadata=qo(t.metadata));for(let[n,s]of Object.entries(t))Po.has(n)||n==="metadata"||L(s)&&(r[n]=s);return r}function Ko(e){let t=u(e)?e:{},r=u(t.metadata)?t.metadata:{},n=u(r.renderedPayload)?r.renderedPayload:{};return u(t.resultContract)?t.resultContract:u(n.resultContract)?n.resultContract:{}}function Cn(e){return a(Ko(e).kind).toLowerCase()==="decision"}function Go(e){return e?.dispatchFinalTextOnly===!0||e?.dispatchFinalOutputOnly===!0?!0:e?.dispatchFinalTextOnly===!1||e?.dispatchFinalOutputOnly===!1?!1:K(e)==="cli"}function Rn(e){let t=e?.dispatchReleaseAfterPrompt??e?.dispatchDisposeAfterPrompt;return Tt(t,xn(e))}function zo(e,t){let r=u(e?.metadata)?{...e.metadata}:{},n=u(r._runtimeBridge)?{...r._runtimeBridge}:{},s=Ve(n);return r._runtimeBridge={...n,promptKind:"dispatch",finalTextOnly:Go(t),releaseAfterPrompt:s===void 0?Rn(t):Tt(s,Rn(t)),requiresRuntimeResult:Cn(e)},r}function Vo(e){let t=jo(e);if(!L(t))return"";let r=JSON.stringify(Je(t),null,2);if(r.length<=Be)return r;let n=r.length-Be;return`${r.slice(0,Be)}
|
|
14
|
+
... [truncated ${n} characters]`}function Xe(e){if(!u(e))return"";let t=u(e.update)?e.update:e,n=(u(t.content)?t.content:{}).text??t.text;return n==null?"":String(n)}function We(e){if(!u(e))return"";let t=u(e.update)?e.update:e;return a(t.sessionUpdate)}function Ye(e){if(!Array.isArray(e))return"";let t=!1,r=[],n=[],s=[],i=()=>{r.length>0&&(n.push(r),r=[])};for(let c of e){let l=We(c),d=Xe(c);if(!l){d&&s.push(d);continue}if(t=!0,l==="agent_message_chunk"){d&&r.push(d);continue}(l==="agent_thought_chunk"||l==="user_message_chunk"||l==="tool_call"||l==="tool_call_update"||l==="plan")&&i()}if(i(),!t)return it(s);let o=n[n.length-1]||[];return it(o)}function Jo(e){return Array.isArray(e)?e.map(Xe).filter(t=>t!==""):[]}function zt(e){return Array.isArray(e)?e.some(r=>We(r))?e.filter(r=>Uo.has(We(r))).map(Xe).filter(r=>r!==""):Jo(e):[]}function Wo(e){if(!u(e))return null;let t=u(e.update)?e.update:e;return a(t.sessionUpdate)!=="runtime_event"?null:u(t.event)?t.event:null}function Xo(e){if(!u(e))return"";let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type);if(r==="event_msg"){if(n==="task_complete")return a(t.last_agent_message||t.message||t.output);if(n==="agent_message"){let s=a(t.phase||t.status||t.stage).toLowerCase();if(["final_answer","final","complete","completed","done"].includes(s))return a(t.message||t.text||t.content)}}return""}function Yo(e){if(!Array.isArray(e))return"";for(let t=e.length-1;t>=0;t-=1){let r=Xo(Wo(e[t]));if(r)return r}return""}function it(e){let t="";for(let r of e){let n=String(r||"");if(n)if(!t)t=n;else if(n.length>t.length&&n.startsWith(t))t=n;else{let s=dn(n)&&!/[\r\n]$/.test(t)?`
|
|
15
|
+
`:"";t+=`${s}${n}`}}return t.trim()}function Zo(e){let t=String(e||"").trim();if(!t)return"";let r=t.match(/(?:^|\n)#{1,3}\s+\S/);return!r||r.index===0?t:t.slice(r.index+(t[r.index]===`
|
|
16
|
+
`?1:0)).trim()}function Sn(e){let t=String(e||"").trim();if(!t)return null;try{let r=JSON.parse(t);if(u(r)&&(bn(r)||L(r._artifacts)||L(r.artifacts)||L(r._decision)||L(r._meta)))return r}catch{}return null}function wt(e){try{return be(e)}catch{return null}}function Kt(...e){let t=null;for(let r of e)try{if(be(r))return}catch(n){t||=n}if(t)throw t}function Ge(e){let t=String(e||"").trim();if(!t)return null;let r=wt(t);if(r)return r;let n=[...t.matchAll(/```(?:json)?\s*([\s\S]*?)```/gi)];for(let s=n.length-1;s>=0;s-=1){let i=Sn(n[s][1]);if(i)return i}if(!t.endsWith("}"))return null;for(let s=t.lastIndexOf("{");s>=0;s=t.lastIndexOf("{",s-1)){let i=Sn(t.slice(s));if(i)return i}return null}function Qo(e){let t=wt(Ye(e));if(t)return t;let r=zt(e);for(let n=r.length-1;n>=0;n-=1){let s=wt(r[n]);if(s)return s}return wt(it(r))}function bn(e){if(!u(e))return!1;if(L(e.output))return!0;for(let t of["content","text","message","summary"])if(a(e[t]))return!0;return!!(In(e.status)||a(e.error)||a(e.errorMessage))}function B(e){let t=u(e)?{...e}:{};return(!Array.isArray(t._artifacts)||t._artifacts.length===0)&&Array.isArray(t.artifacts)&&t.artifacts.length>0&&(t._artifacts=t.artifacts),delete t.artifacts,t}function ta(e){return u(e)?typeof(u(e._decision)?e._decision:u(e.decision)?e.decision:e).passed=="boolean":!1}function An(e){return u(e)?u(e._decision)&&typeof e._decision.passed=="boolean"?!0:ta(e.output):!1}function ze(e,t,r){let n=u(e)?{...e}:{};if(!L(n.output)){for(let s of["summary","message","content","text"])if(a(n[s])){n.output=a(n[s]);break}}return!L(n.output)&&a(r)&&(n.output=a(r)),{...n,_meta:{...u(n._meta)?n._meta:{},runtimeOutputSource:t,requiredRuntimeResult:!0,finalMessagePreview:a(r).slice(0,1e3)}}}var ea=["dataUrl","dataURL","contentDataUrl","contentDataURL","contentBase64","base64","data"];function En(e){if(!u(e))return"";let t=u(e.content)?e.content:{},r=u(e.metadata)?e.metadata:{};return a(e.fieldKey||e.field_key||t.fieldKey||r.fieldKey)}function ra(e,t){let r=u(e.content)?e.content:{},n=u(t.content)?t.content:{},s={...e,...t,content:{...r,...n},metadata:{...u(e.metadata)?e.metadata:{},...u(t.metadata)?t.metadata:{}}};for(let i of ea)L(e[i])&&(s[i]=e[i]),L(r[i])&&(s.content[i]=r[i]);return s}function Nn(e,t){let r=Array.isArray(e)?e.filter(u):[],n=Array.isArray(t)?t.filter(u):[];if(!r.length)return n;if(!n.length)return r;let s=[...r],i=new Map;for(let c=0;c<r.length;c+=1){let l=En(r[c]),d=i.get(l)||[];d.push(c),i.set(l,d)}let o=new Map;for(let c of n){let l=En(c),d=o.get(l)||0;o.set(l,d+1);let f=i.get(l)?.[d];f===void 0?s.push(c):s[f]=ra(s[f],c)}return s}function j(e,t,r){let n={...e,...t,_meta:{...u(e._meta)?e._meta:{},...u(t._meta)?t._meta:{},runtimeOutputSource:r}};return(Array.isArray(e._artifacts)||Array.isArray(t._artifacts))&&(n._artifacts=Nn(e._artifacts,t._artifacts)),n}function Mn(e,t,r={}){let n=a(r.promptKind),s=r.requiresRuntimeResult===!0,i=s||n==="dispatch",o=B(e),c=typeof o.output=="string"?wt(o.output):null;if(c)return j(o,B(c),"result_block");let l=Yo(t),d=l?Ge(l):null,f=i?Qo(t):null;if(bn(o))return In(o.status)||a(o.error)||a(o.errorMessage)?o:n==="dispatch"&&d?j(o,B(d),"final_event"):n==="dispatch"&&f?j(o,B(f),"updates"):!s||An(o)?o:d?j(o,B(d),"final_event"):f?j(o,B(f),"updates"):(Kt(o.output,l,it(zt(t))),ze(o,"result",o.output));if(d)return j(o,B(d),"final_event");if(f)return j(o,B(f),"updates");if(l)return s?(Kt(l,it(zt(t))),ze(o,"final_event",l)):{...o,output:l,_meta:{...u(o._meta)?o._meta:{},runtimeOutputSource:"final_event"}};let p=Ye(t),h=Ge(p);if(h)return j(o,B(h),"updates");let g=Zo(p);if(!g)return s&&Kt(it(zt(t))),o;let y=Ge(g);return y?j(o,B(y),"updates"):s?(Kt(p,g),ze(o,"updates",g)):{...o,output:g,_meta:{...u(o._meta)?o._meta:{},runtimeOutputSource:"updates"}}}function Ze(e){return u(e)?a(e.stopReason||e.stop_reason).toLowerCase():""}function Un(e){return Mo.has(Ze(e))}function na(e,t,r){if(r.promptKind!=="dispatch"||r.requiresRuntimeResult!==!0||!Un(e))return!1;try{return!An(Mn(e,t,r))}catch{return!0}}function sa(){return["Your previous final response reached the output limit before the Runtime Result protocol was complete.","Re-emit the complete final Runtime Result from scratch using the conclusion you already reached.","Do not repeat analysis, process notes, tool calls, or task work.",`Keep the OUTPUT report within ${On} Unicode characters.`,`Output ${Ee}, ${Oe}, ${Ie}, and ${xe} on their own lines.`,"The CONTROL block must be valid JSON containing _decision and must be fully closed.","Return only the two protocol blocks."].join(`
|
|
17
|
+
`)}function ia(e,t){let r=u(t)?{...t}:{},n=Nn(e?._artifacts,t?._artifacts);return n.length>0&&(r._artifacts=n),r}function oa(e,t){return{...e,_meta:{...u(e?._meta)?e._meta:{},runtimeProtocolRetry:{attempted:!0,recovered:!0,reason:Ze(t)||"max_tokens"}}}}function aa(e,t){let r=typeof e?.output=="string"?e.output:Ye(t),n=new k("runtime_output_truncated","Runtime Result \u8FBE\u5230\u6700\u5927\u8F93\u51FA\u957F\u5EA6\uFF0C\u7D27\u51D1\u91CD\u8BD5\u540E\u4ECD\u672A\u5B8C\u6574\u8FD4\u56DE",r);return n.detail={...n.detail,stopReason:Ze(e)||"max_tokens",retryAttempted:!0},n}var Vt=class{constructor(t){this.config=t,this.targets=t.targets||{},this.agents=new Map,this.sessions=new Map,this.startingSessions=new Set,this.targetReservations=new Map,this.runtimeSessionIndex=new Map,this.pendingPermissions=new Map,this.operations=new Map,this.startedAt=dt(),this.sandboxCapabilities={dispatchable:t.sandboxRequired!==!0,enforced:!1,backend:t.sandboxRequired?"unavailable":"direct",daemonStatus:t.sandboxRequired?"pending":"not_required",policySchemaVersions:[1],runtimePolicyUpdates:t.sandboxRequired===!0,workspaceSync:!1,egressProxy:!1},this.cleanupTimer=null,this.onCapacityChanged=null,this.startSessionCleanup()}async start(){try{this.sandboxCapabilities=await yn(this.config)}catch(t){this.sandboxCapabilities={...this.sandboxCapabilities,dispatchable:!1,enforced:!1,backend:"unavailable",daemonStatus:"unavailable",reason:a(t?.code||t?.message||t)||"sandbox_probe_failed"},m("error","runtime-bridge","runtime node sandbox probe failed; node will not accept work",{reason:this.sandboxCapabilities.reason})}return this.sandboxCapabilities}assertDispatchable(){if(this.config.sandboxRequired&&!(this.sandboxCapabilities.dispatchable===!0&&this.sandboxCapabilities.enforced===!0))throw Object.assign(new Error("runtime node strong sandbox is unavailable"),{code:"RUNTIME_NODE_SANDBOX_UNAVAILABLE"})}operationIdentity(t,r,n){let s=u(t.goalContract)?Ue(t.goalContract):a(t.goalContractHash),i=Eo("sha256").update(q({prompt:Array.isArray(t.prompt)?t.prompt:[],mcpServers:Do(t.mcpServers),metadata:u(t.metadata)?t.metadata:{}})).digest("hex");return{agentId:r,runId:a(t.runId),sessionId:n,targetCode:a(t.targetCode||t.framework),workspace:a(t.workspace),goalContractHash:s,requestHash:i}}assertOperationIdentity(t,r,n,s){let i=this.operationIdentity(r,n,s),o=Object.keys(t.identity).find(c=>t.identity[c]!==i[c]);if(o)throw Object.assign(new Error(`runtime operation correlation conflict: ${t.correlationId}`),{code:"RUNTIME_OPERATION_CORRELATION_CONFLICT",field:o})}createOperation(t,r,n,s){let i={correlationId:t,agentId:n,sessionId:s,identity:this.operationIdentity(r,n,s),sandboxPolicy:u(r.sandboxPolicy)?structuredClone(r.sandboxPolicy):null,status:"running",updates:[],listeners:new Set,waiters:[],response:null,error:null,mcpServers:r.mcpServers,createdAtMs:Date.now(),completedAtMs:null};return this.operations.set(t,i),i}async attachOperation(t,r={}){let n=()=>{if(r.onUpdate)for(let s of t.updates)r.onUpdate(s)};if(t.status==="completed")return n(),t.response;if(t.status==="failed")throw n(),t.error;r.onUpdate&&t.listeners.add(r.onUpdate);try{return n(),await new Promise((s,i)=>t.waiters.push({resolve:s,reject:i}))}finally{r.onUpdate&&t.listeners.delete(r.onUpdate)}}completeOperation(t,r){if(t.status==="running"){t.status="completed",t.response=r,t.mcpServers=null,t.completedAtMs=Date.now();for(let n of t.waiters.splice(0))n.resolve(r);t.listeners.clear()}}promptResponse(t,r,n,s,i,o=s){let c=u(t.metadata)?t.metadata:{},l=u(c._runtimeBridge)?c._runtimeBridge:{},d=Mn(i,o,l),f=hn(t.goalContract,s,t.goalContractHash);return{sessionId:n,runtimeSessionId:r.runtimeSessionId,result:d,updates:s,...f?{verification:f}:{}}}failOperation(t,r){if(t.status!=="running")return;let n=r instanceof Error?r:Object.assign(new Error(String(r||"runtime operation failed")),{code:"RUNTIME_NODE_ERROR"});t.status="failed",t.error=n,t.mcpServers=null,t.completedAtMs=Date.now();for(let s of t.waiters.splice(0))s.reject(n);t.listeners.clear()}cleanupOperations(t=Date.now()){let r=G(this.config.operationTtlMs,bo);for(let[n,s]of this.operations)s.status!=="running"&&t-(s.completedAtMs||s.createdAtMs)>r&&this.operations.delete(n)}targetFor(t){let r=a(t)||this.config.defaultTargetCode,n=this.targets[r];if(!r||!u(n)){let s=new Error(`runtime target is not configured: ${r||"<empty>"}`);throw s.code="RUNTIME_TARGET_NOT_FOUND",s}return{code:r,target:n}}targetIdleTtlMs(t){let n=K(t)==="openclaw"?G(this.config.openClawSessionIdleTtlMs,Ao):G(this.config.sessionIdleTtlMs,Io);return G(t?.sessionIdleTtlMs??t?.idleTtlMs,n)}targetMaxSessions(t){let n=K(t)==="openclaw"?G(this.config.openClawMaxSessions,No):G(this.config.maxSessionsPerTarget,Co);return G(t?.maxSessions,n)}targetReservationCount(t){return Number(this.targetReservations.get(t)||0)}notifyCapacityChanged(){try{this.onCapacityChanged?.()}catch(t){m("warn","runtime-bridge","capacity heartbeat callback failed",{error:String(t)})}}targetCapacitySnapshot(t=!0){return Object.entries(this.targets).map(([r,n])=>{let s=[...this.sessions.values()].filter(f=>f.targetCode===r),i=s.filter(f=>f.busy).length,o=s.length-i,c=this.targetReservationCount(r),l=this.targetMaxSessions(n),d=t?Math.max(0,l-i-c):0;return{targetCode:r,targetName:a(n?.name||n?.targetName||r),targetType:a(n?.type||"echo"),status:t?d>0?"available":"busy":"unavailable",maxSessions:l,busySessions:i,idleSessions:o,reservedSessions:c,availableSessions:d}})}targetReleaseAfterPrompt(t,r={}){let n=K(t),s=u(r?._runtimeBridge)?r._runtimeBridge:{},i=Ve(s);return i!==void 0?Tt(i,!1):Tt(t?.releaseAfterPrompt??t?.disposeAfterPrompt,n==="openclaw")}promptReleaseAfterPrompt(t,r={}){if(this.config.sandboxRequired)return!0;let n=u(r?._runtimeBridge)?r._runtimeBridge:{},s=Ve(n);return s!==void 0?Tt(s,t.releaseAfterPrompt):t.releaseAfterPrompt}startSessionCleanup(){let t=G(this.config.sessionCleanupIntervalMs,xo);t<=0||(this.cleanupTimer=setInterval(()=>{this.cleanupExpiredSessions().catch(r=>{m("warn","runtime-bridge","runtime session cleanup failed",{error:String(r)})})},t),this.cleanupTimer.unref?.())}sessionCountForTarget(t){let r=0;for(let n of this.sessions.values())n.targetCode===t&&(r+=1);return r}idleTargetSessions(t){return[...this.sessions.entries()].filter(([,r])=>r.targetCode===t&&!r.busy).sort((r,n)=>(r[1].lastUsedAtMs||0)-(n[1].lastUsedAtMs||0))}async closeSession(t,r="session_closed"){let n=this.sessions.get(t);if(!n)return!1;try{await n.runtime?.stop?.(r)}catch(s){m("warn","runtime-bridge","runtime session stop failed",{sessionId:n.sessionId,runtimeSessionId:n.runtimeSessionId,targetCode:n.targetCode,runtimeKind:n.runtimeKind,error:String(s)})}return this.sessions.delete(t),this.runtimeSessionIndex.delete(`${n.agentId}:${n.runtimeSessionId}`),this.notifyCapacityChanged(),m("info","runtime-bridge","runtime session closed",{sessionId:n.sessionId,runtimeSessionId:n.runtimeSessionId,targetCode:n.targetCode,runtimeKind:n.runtimeKind,reason:r}),!0}async closeAllSessions(t="bridge_shutdown"){for(let r of[...this.sessions.keys()])await this.closeSession(r,t)}async stop(t="bridge_stop"){this.cleanupTimer&&clearInterval(this.cleanupTimer),this.cleanupTimer=null,await this.closeAllSessions(t)}async cleanupExpiredSessions(t=Date.now()){for(let[r,n]of[...this.sessions.entries()])n.busy||t-(n.lastUsedAtMs||n.createdAtMs||t)>n.idleTtlMs&&await this.closeSession(r,"idle_timeout")}async reserveTargetSlot(t,r){let n=this.targetMaxSessions(r);for(;this.sessionCountForTarget(t)+this.targetReservationCount(t)>=n;){let s=this.idleTargetSessions(t);if(!s.length){let i=new Error(`runtime target session limit reached: ${t}`);throw i.code="RUNTIME_TARGET_SESSION_LIMIT",i}await this.closeSession(s[0][0],"target_session_limit")}this.targetReservations.set(t,this.targetReservationCount(t)+1),this.notifyCapacityChanged()}releaseTargetSlot(t){let r=Math.max(0,this.targetReservationCount(t)-1);r>0?this.targetReservations.set(t,r):this.targetReservations.delete(t),this.notifyCapacityChanged()}async createAgent(t){let r=a(t.agentId);if(!r)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});let{code:n,target:s}=this.targetFor(t.targetCode||t.framework),i=this.agents.get(r);if(i&&i.targetCode!==n)throw Object.assign(new Error(`runtime agent target conflict: ${r}`),{code:"RUNTIME_AGENT_TARGET_CONFLICT"});let o=this.config.sandboxRequired?await He(this.config,s,t.workspace):a(t.workspace),c={agentId:r,targetCode:n,framework:a(t.framework||n),workspace:o,metadata:u(t.metadata)?t.metadata:{},createdAt:dt(),runtimeKind:K(s)};return this.agents.set(r,c),{agent:c}}runtimeFor(t,r,n={}){let{target:s}=this.targetFor(t.targetCode),i=K(s),o={onPermissionRequest:l=>n.source==="conversation_delegation"?{outcome:"denied",reason:"External group member permission continuation is not supported"}:this.requestPermission(l)},c={sessionPromptTimeoutMs:this.config.sessionPromptTimeoutMs,initializeTimeoutMs:this.config.initializeTimeoutMs,sandboxRequired:this.config.sandboxRequired,runId:n.runId,sandboxPolicy:n.sandboxPolicy,...this.config.sandboxRequired?{prepareLaunch:l=>Tn({config:this.config,target:s,...l,runId:n.runId,agentId:t.agentId,sessionId:r,sandboxPolicy:n.sandboxPolicy})}:{}};return i==="stdio-acp"||i==="acp"?new rt(t,s,o,c):i==="openclaw"?new Pt(t,s,r,o,c):i==="cli"?new Ht(t,s,c):new xt(t)}async prompt(t,r={}){if(this.assertDispatchable(),this.config.sandboxRequired){let c=a(t.runId);if(!c)throw Object.assign(new Error("runId is required"),{code:"BAD_REQUEST"});t={...t,runId:c,sandboxPolicy:J(t.sandboxPolicy)}}let n=a(t.agentId),s=a(t.sessionId)||Gt(),i=a(t.correlationId);if(!n)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});if(this.cleanupOperations(),i){let c=this.operations.get(i);if(c){if(this.assertOperationIdentity(c,t,n,s),c.status==="running"&&t.metadata?.source==="conversation_delegation"){c.mcpServers=t.mcpServers;let l=this.sessions.get(`${n}:${s}`);if(l){if(!l.runtime.refreshMcpServers)throw Object.assign(new Error("This runtime cannot refresh task MCP credentials"),{code:"unsupported_dynamic_mcp"});await l.runtime.refreshMcpServers(t.mcpServers)}}return this.attachOperation(c,r)}if(t.attachOnly===!0)throw Object.assign(new Error(`runtime operation is no longer available: ${i}`),{code:"RUNTIME_OPERATION_NOT_FOUND"})}else if(t.attachOnly===!0)throw Object.assign(new Error("correlationId is required for attachOnly"),{code:"BAD_REQUEST"});let o=i?this.createOperation(i,t,n,s):null;if(o){let c=this.attachOperation(o,r);return(async()=>{try{await this._promptOwned(t,{},o,n,s)}catch(l){let d=o.status==="completed";this.failOperation(o,l),d&&m("warn","runtime-bridge","runtime cleanup failed after operation completion",{correlationId:o.correlationId,error:String(l)})}})(),await c}return await this._promptOwned(t,r,o,n,s)}async _promptOwned(t,r,n,s,i){let o=a(t.runId),c=this.config.sandboxRequired?J(n?.sandboxPolicy||t.sandboxPolicy):null,l=this.agents.get(s),d=this.targetFor(t.targetCode||t.framework||l?.targetCode);if(l&&l.targetCode!==d.code)throw Object.assign(new Error(`runtime agent target conflict: ${s}`),{code:"RUNTIME_AGENT_TARGET_CONFLICT"});if(K(d.target)==="cli"&&vo(t.goalContract))throw Object.assign(new Error("CLI runtimes do not support per-run dynamic MCP required by plugin_operation"),{code:"unsupported_dynamic_mcp"});let f=l||(await this.createAgent({agentId:s,targetCode:d.code,framework:t.framework,workspace:t.workspace,metadata:t.metadata})).agent;if(!this.config.sandboxRequired){let T=a(t.workspace);T&&T!==f.workspace&&(f.workspace=T)}let p=`${s}:${i}`;await this.cleanupExpiredSessions();let h=this.sessions.get(p),g=null;if(h&&h.targetCode!==d.code)throw Object.assign(new Error(`runtime session target conflict: ${i}`),{code:"RUNTIME_SESSION_TARGET_CONFLICT"});if(h&&this.config.sandboxRequired&&h.runId!==o)throw Object.assign(new Error(`runtime session cannot be shared across runs: ${i}`),{code:"RUNTIME_SESSION_RUN_CONFLICT"});if(!h){if(this.startingSessions.has(p))throw Object.assign(new Error(`runtime session is already starting: ${i}`),{code:"RUNTIME_SESSION_BUSY"});this.startingSessions.add(p);let{code:T,target:w}=d,S;try{await this.reserveTargetSlot(T,w),g=T;let I=this.runtimeFor(f,i,{runId:o,sandboxPolicy:c,source:t.metadata?.source});S=I;let P=n?.mcpServers||t.mcpServers||[],v=await I.sessionNew({cwd:et(w,f.workspace),mcpServers:P,metadata:u(t.metadata)?t.metadata:{}});if(n&&n.status!=="running")throw Object.assign(new Error("Runtime operation was cancelled before prompt dispatch"),{code:"RUNTIME_OPERATION_CANCELLED"});let N=Date.now();h={agentId:s,sessionId:i,runtime:I,targetCode:T,runtimeKind:K(w),runId:o,sandboxPolicy:c?structuredClone(c):null,runtimeSessionId:a(u(v)?v.sessionId:"")||i,idleTtlMs:this.targetIdleTtlMs(w),releaseAfterPrompt:this.config.sandboxRequired?!0:this.targetReleaseAfterPrompt(w,t.metadata),createdAtMs:N,lastUsedAtMs:N,busy:!1,createdAt:dt()},this.sessions.set(p,h),this.runtimeSessionIndex.set(`${s}:${h.runtimeSessionId}`,h),n?.mcpServers!==P&&n?.mcpServers&&I.refreshMcpServers&&await I.refreshMcpServers(n.mcpServers)}catch(I){throw this.sessions.get(p)?.runtime===S?await this.closeSession(p,"session_start_failed"):await S?.stop("session_start_failed"),g&&(this.releaseTargetSlot(g),g=null),I}finally{this.startingSessions.delete(p)}}if(h.busy){let T=new Error(`runtime session is already running: ${i}`);throw T.code="RUNTIME_SESSION_BUSY",T}h.busy=!0,g&&this.releaseTargetSlot(g),this.notifyCapacityChanged(),h.operationCorrelationId=n?.correlationId||null,h.lastUsedAtMs=Date.now();let y=n?.updates||[],R=T=>{let w=Ho(T,i,h);if(y.push(w),n)for(let S of n.listeners)try{S?.(w)}catch(I){m("warn","runtime-bridge","runtime operation update listener failed",{correlationId:n.correlationId,error:String(I)})}else r.onUpdate?.(w)},A=T=>{if(!(!n||n.status!=="running"||!u(T))){if(T.status==="failed"){let w=T.error;if(w instanceof Error){this.failOperation(n,w);return}let S=u(w)?w:{},I=Object.assign(new Error(a(S.message||T.message)||"runtime terminal failure"),{code:a(S.code||T.code)||"RUNTIME_TERMINAL_FAILED"});this.failOperation(n,I);return}this.completeOperation(n,this.promptResponse(t,h,i,y,u(T.result)?T.result:{stopReason:"end_turn"}))}};try{let T=pn(t.goalContract),w=Array.isArray(t.prompt)?[...t.prompt]:[];T&&w.unshift({type:"text",text:T,metadata:{source:"orcha_goal_contract"}});let S=u(t.metadata)?t.metadata:{},I=u(S._runtimeBridge)?S._runtimeBridge:{},P=await h.runtime.sessionPrompt({sessionId:h.runtimeSessionId,prompt:w,metadata:S},R,A),v=y,N=null;if(xn({type:h.runtimeKind})&&na(P,y,I)){N=P;let Z=y.length,at=await h.runtime.sessionPrompt({sessionId:h.runtimeSessionId,prompt:[{type:"text",text:sa()}],metadata:S,_meta:{thinking:"off"}},R,A);P=ia(N,at),v=y.slice(Z)}let O;try{O=this.promptResponse(t,h,i,y,P,v)}catch(Z){throw N&&Un(P)?aa(P,v):Z}return N&&(O.result=oa(O.result,N)),n&&this.completeOperation(n,O),O}finally{h.busy=!1,this.notifyCapacityChanged(),h.operationCorrelationId===n?.correlationId&&(h.operationCorrelationId=null),h.lastUsedAtMs=Date.now(),this.promptReleaseAfterPrompt(h,u(t.metadata)?t.metadata:{})&&await this.closeSession(p,"release_after_prompt"),n&&(n.mcpServers=null)}}async updatePolicy(t){if(this.assertDispatchable(),!this.config.sandboxRequired)throw Object.assign(new Error("runtime sandbox policy updates require an enforced sandbox"),{code:"RUNTIME_NODE_SANDBOX_UNAVAILABLE"});let r=a(t.agentId),n=a(t.runId),s=a(t.sessionId),i=a(t.correlationId);if(!r||!n||!s||!i)throw Object.assign(new Error("agentId, runId, sessionId and correlationId are required"),{code:"BAD_REQUEST"});let o=J(t.sandboxPolicy),c=this.operations.get(i);if(c&&(c.agentId!==r||c.sessionId!==s||c.identity.runId!==n))throw Object.assign(new Error(`runtime operation policy identity conflict: ${i}`),{code:"RUNTIME_OPERATION_CORRELATION_CONFLICT"});let l=`${r}:${s}`,d=this.sessions.get(l);if(d&&d.runId!==n)throw Object.assign(new Error(`runtime session policy identity conflict: ${s}`),{code:"RUNTIME_SESSION_RUN_CONFLICT"});let f=d?.sandboxPolicy||c?.sandboxPolicy;if(!f)throw Object.assign(new Error(`runtime operation is no longer available: ${i}`),{code:"RUNTIME_OPERATION_NOT_FOUND"});let p=Number(f.policyRevision),h=Number(o.policyRevision);if(h<p)throw Object.assign(new Error("runtime sandbox policy revision is stale"),{code:"RUNTIME_POLICY_REVISION_CONFLICT",currentPolicyRevision:p});if(h===p){if(q(f)!==q(o))throw Object.assign(new Error("runtime sandbox policy revision payload conflicts"),{code:"RUNTIME_POLICY_REVISION_CONFLICT",currentPolicyRevision:p});return{updated:!1,idempotent:!0,policyRevision:p,accessMode:f.accessMode}}let g=_n(f,o);c&&(c.sandboxPolicy=structuredClone(o)),d&&(d.sandboxPolicy=structuredClone(o));let y=!1;return g&&d?.busy===!0&&(await d.runtime.sessionCancel({sessionId:d.runtimeSessionId}),y=await this.closeSession(l,"sandbox_policy_downgrade")),{updated:!0,policyRevision:h,accessMode:o.accessMode,activeCommandCancelled:y,deferredToNextLaunch:!g&&d?.busy===!0}}async cancel(t){let r=a(t.agentId),n=a(t.sessionId),s=a(t.correlationId);if(s){let c=this.operations.get(s);if(!c||c.status!=="running")return{cancelled:!1,correlationId:s,reason:"operation_not_running"};if(c.agentId!==r||c.sessionId!==n)throw Object.assign(new Error(`runtime operation cancellation identity conflict: ${s}`),{code:"RUNTIME_OPERATION_CORRELATION_CONFLICT"});let l=this.sessions.get(`${r}:${n}`);return!l||l.busy!==!0||l.operationCorrelationId!==s?(this.failOperation(c,Object.assign(new Error("Runtime operation cancelled before dispatch"),{code:"RUNTIME_OPERATION_CANCELLED"})),{cancelled:!0,correlationId:s,reason:"cancelled_before_dispatch"}):(await l.runtime.sessionCancel({sessionId:l.runtimeSessionId}),await this.closeSession(`${r}:${n}`,"cancelled"),{cancelled:!0,correlationId:s})}let i=`${r}:${n}`,o=this.sessions.get(i);return o?(await o.runtime.sessionCancel({sessionId:o.runtimeSessionId}),await this.closeSession(i,"cancelled"),{cancelled:!0}):{cancelled:!1}}async dispatch(t,r={}){let n=a(t.agentId),s=a(t.taskId),i=a(t.executionId);if(!n||!s)throw Object.assign(new Error("agentId and taskId are required"),{status:400,code:"BAD_REQUEST"});let o=a(t.sessionId)||`dispatch-${i||s}`,c=a(t.instructions),l=Vo(t),d=Cn(t),{target:f}=this.targetFor(t.targetCode||t.framework),p=[{type:"text",text:["Task dispatch received.",`taskId: ${s}`,i?`executionId: ${i}`:"",c?`instructions: ${c}`:"",l?"orchaContext:":"",l,l?"Use orchaContext as the source of truth for upstream outputs, review reports, artifacts, and workflow metadata.":"","Follow the execution protocol in instructions exactly.","When embedding a generated artifact in final Markdown, use the Orcha artifact placeholder as the link target: orcha-artifact://<fieldKey>/<index>.","Example: use  for the first generated image artifact.","Do not use local filesystem paths, file:// URLs, or data: URLs in final Markdown; Orcha replaces artifact placeholders after ingestion.",d?`For decision results, put the raw report between ${Ee} and ${Oe}.`:"",d?`Then put a JSON object containing _decision between ${Ie} and ${xe}.`:"",d?"Do not JSON-escape the report. Keep output out of the CONTROL JSON, and put every protocol marker on its own line.":"",d?`Keep the report within ${On} Unicode characters so the CONTROL block fits before the output limit.`:"","Return only the final answer required by that protocol.","Do not include process notes, logs, or explanations."].filter(Boolean).join(`
|
|
18
|
+
`)}];return this.prompt({...t,agentId:n,sessionId:o,prompt:p,metadata:zo(t,f)},r)}async requestPermission({agent:t,runtimeSessionId:r,request:n,emitUpdate:s}){let i=Gt(),c=this.runtimeSessionIndex.get(`${t.agentId}:${r}`)?.sessionId||r||Gt(),l={permissionId:i,agentId:t.agentId,sessionId:c,runtimeSessionId:r,request:u(n)?n:{},status:"pending",createdAt:dt()};return s?.({sessionId:r,update:{sessionUpdate:"permission_request",permission:l}}),await new Promise(d=>{let f=_(n?.timeoutMs,this.config.permissionRequestTimeoutMs),p=setTimeout(()=>{this.pendingPermissions.delete(i),d({permissionId:i,outcome:"denied",response:{reason:"permission request timed out"}})},f);this.pendingPermissions.set(i,{timer:p,resolve:d,permission:l})})}async respondPermission(t){let r=a(t.permissionId),n=this.pendingPermissions.get(r),s=a(t.outcome||"approved")||"approved";return n?(clearTimeout(n.timer),this.pendingPermissions.delete(r),n.resolve({permissionId:r,outcome:s,response:u(t.response)?t.response:{},userId:a(t.userId),metadata:u(t.metadata)?t.metadata:{}}),{accepted:!0,permissionId:r,outcome:s}):{accepted:!1,permissionId:r,outcome:s}}health(){return{status:this.config.sandboxRequired&&!this.sandboxCapabilities.dispatchable?"unavailable":"ok",bridgeVersion:tt,startedAt:this.startedAt,agents:[...this.agents.values()].map(t=>({agentId:t.agentId,targetCode:t.targetCode,framework:t.framework,runtimeKind:t.runtimeKind})),sessions:this.sessions.size,pendingPermissions:this.pendingPermissions.size,targets:Object.keys(this.targets),sandboxCapabilities:this.sandboxCapabilities}}};import ca from"node:http";import ua from"node:https";import{randomBytes as Pn}from"node:crypto";var ot=1,W=3,la=1e4,Jt=class{constructor(t,r={}){this.url=t,this.readyState=0,this.socket=null,this.request=null,this.buffer=Buffer.alloc(0),this.listeners=new Map,this.connectTimeoutMs=da(r.connectTimeoutMs,la),this.connectTimer=null,this.connect()}addEventListener(t,r){let n=this.listeners.get(t)||new Set;n.add(r),this.listeners.set(t,n)}emit(t,r={}){let n=this.listeners.get(t);if(n)for(let s of n)s(r)}connect(){let t=new URL(this.url),r=t.protocol==="wss:"?ua:ca,n=Pn(16).toString("base64"),s=r.request({protocol:t.protocol==="wss:"?"https:":"http:",hostname:t.hostname,port:t.port||(t.protocol==="wss:"?443:80),path:`${t.pathname}${t.search}`,method:"GET",headers:{Connection:"Upgrade",Upgrade:"websocket","Sec-WebSocket-Key":n,"Sec-WebSocket-Version":"13"}});this.request=s,this.startConnectTimer(s),s.on("upgrade",(i,o,c)=>{if(this.clearConnectTimer(),this.readyState===W){o.destroy();return}this.socket=o,this.readyState=ot,o.on("data",l=>this.onData(l)),o.on("close",()=>this.onClose()),o.on("error",l=>{this.readyState!==W&&this.emit("error",{error:l,message:l.message,type:"error"}),this.onClose()}),c?.length&&this.onData(c),this.emit("open")}),s.on("response",i=>{this.clearConnectTimer(),this.emit("error",{message:`websocket upgrade failed: HTTP ${i.statusCode}`,type:"error"}),i.resume(),this.onClose()}),s.on("error",i=>{this.clearConnectTimer(),this.readyState!==W&&this.emit("error",{error:i,message:i.message,type:"error"}),this.onClose()}),s.end()}startConnectTimer(t){this.connectTimeoutMs<=0||(this.connectTimer=setTimeout(()=>{if(this.readyState===ot||this.readyState===W)return;let r=`websocket connect timeout after ${this.connectTimeoutMs}ms`;this.emit("error",{message:r,type:"timeout"}),this.onClose(),t.destroy(new Error(r))},this.connectTimeoutMs),this.connectTimer.unref?.())}clearConnectTimer(){this.connectTimer&&(clearTimeout(this.connectTimer),this.connectTimer=null)}send(t){!this.socket||this.readyState!==ot||this.socket.write(Qe(1,Buffer.from(String(t),"utf8")))}close(){if(this.readyState!==W){if(this.clearConnectTimer(),!this.socket){this.request?.destroy(),this.onClose();return}try{this.readyState===ot&&this.socket.write(Qe(8,Buffer.alloc(0))),this.socket.end()}catch{this.socket.destroy()}this.onClose()}}onClose(){this.readyState!==W&&(this.clearConnectTimer(),this.readyState=W,this.request=null,this.emit("close"))}onData(t){for(this.buffer=Buffer.concat([this.buffer,t]);this.buffer.length>=2;){let r=this.buffer[0],n=this.buffer[1],s=r&15,i=(n&128)!==0,o=n&127,c=2;if(o===126){if(this.buffer.length<c+2)return;o=this.buffer.readUInt16BE(c),c+=2}else if(o===127){if(this.buffer.length<c+8)return;let f=this.buffer.readUInt32BE(c),p=this.buffer.readUInt32BE(c+4);o=f*2**32+p,c+=8}let l=c;if(i&&(c+=4),this.buffer.length<c+o)return;let d=this.buffer.subarray(c,c+o);if(i){let f=this.buffer.subarray(l,l+4);d=Buffer.from(d.map((p,h)=>p^f[h%4]))}this.buffer=this.buffer.subarray(c+o),s===1?this.emit("message",{data:d.toString("utf8")}):s===8?this.close():s===9&&this.socket?.write(Qe(10,d))}}};function da(e,t){let r=Number.parseInt(String(e??""),10);return Number.isFinite(r)&&r>=0?r:t}function Qe(e,t){let r=t.length,n=2;r>=126&&r<=65535?n+=2:r>65535&&(n+=8);let s=Pn(4),i=Buffer.alloc(n+4+r);i[0]=128|e;let o=2;r<126?i[1]=128|r:r<=65535?(i[1]=254,i.writeUInt16BE(r,o),o+=2):(i[1]=255,i.writeUInt32BE(Math.floor(r/2**32),o),i.writeUInt32BE(r>>>0,o+4),o+=8),s.copy(i,o),o+=4;for(let c=0;c<r;c+=1)i[o+c]=t[c]^s[c%4];return i}function fa(e){let t=new URL(e);if(t.protocol==="http:")t.protocol="ws:";else if(t.protocol==="https:")t.protocol="wss:";else if(t.protocol!=="ws:"&&t.protocol!=="wss:")throw new Error(`unsupported ORCHA_RUNTIME_ORCHA_URL protocol: ${t.protocol}`);return t.pathname=`${t.pathname.replace(/\/+$/,"")}/api/agent-runtime-bridge/ws`,t.search="",t.toString()}function pa(e,t=!0){return Object.entries(e||{}).map(([r,n])=>({targetCode:r,targetName:a(n?.name||n?.targetName||r),targetType:a(n?.type||"echo"),status:t?"available":"unavailable"}))}var ha=Object.freeze(["health","agents/create","agents/dispatch","sessions/prompt","sessions/policy","sessions/cancel","permissions/respond"]),Wt=class{constructor(t,r){this.config=t,this.bridge=r,this.ws=null,this.stopped=!1,this.connected=!1,this.reconnectTimer=null,this.heartbeatTimer=null,this.capacityHeartbeatTimer=null,this.bridge.onCapacityChanged=()=>this.scheduleCapacityHeartbeat()}sandboxCapabilities(){return this.bridge.sandboxCapabilities||{dispatchable:this.config.sandboxRequired!==!0,enforced:!1,backend:"development_direct",daemonStatus:"development_only",policySchemaVersions:[1],runtimePolicyUpdates:!0,workspaceSync:!1,egressProxy:!1}}supportedMethods(){return[...ha,...this.config.deviceConnection?["devices/discover","devices/configure"]:[]]}runtimeTargets(){let t=this.sandboxCapabilities().dispatchable===!0;return typeof this.bridge.targetCapacitySnapshot=="function"?this.bridge.targetCapacitySnapshot(t):pa(this.config.targets,t)}start(){this.connect()}stop(){this.stopped=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null,this.capacityHeartbeatTimer&&clearTimeout(this.capacityHeartbeatTimer),this.capacityHeartbeatTimer=null,this.bridge.onCapacityChanged=null,this.ws?.close()}connect(){if(this.stopped)return;let t=fa(this.config.orchaUrl),r=new Jt(t,{connectTimeoutMs:this.config.connectTimeoutMs});this.ws=r,r.addEventListener("open",()=>{if(this.ws!==r||this.stopped){r.close();return}this.authenticate(r)}),r.addEventListener("message",n=>this.handleMessage(n.data,r)),r.addEventListener("close",()=>this.scheduleReconnect("close",r)),r.addEventListener("error",n=>{m("warn","orcha-client","runtime node websocket error",{error:String(n?.message||n?.type||n)})})}authenticate(t=this.ws){this.send({type:"runtime_node.authenticate",token:this.config.nodeToken,nodeId:this.config.nodeId,nodeName:this.config.nodeName,version:tt,protocolVersion:"orcha-runtime-node.v2",defaultTargetCode:this.config.defaultTargetCode,supportedMethods:this.supportedMethods(),sandboxCapabilities:this.sandboxCapabilities(),targets:this.runtimeTargets()},t)}scheduleReconnect(t,r=this.ws){r&&this.ws!==r||(this.connected=!1,this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null,this.capacityHeartbeatTimer&&clearTimeout(this.capacityHeartbeatTimer),this.capacityHeartbeatTimer=null,r&&this.ws===r&&(this.ws=null),!this.stopped&&(this.reconnectTimer||(m("info","orcha-client","runtime node disconnected; reconnect scheduled",{reason:t,reconnectMs:this.config.reconnectMs}),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},this.config.reconnectMs))))}async handleMessage(t,r=this.ws){if(r&&this.ws!==r)return;let n;try{n=JSON.parse(String(t))}catch(s){m("warn","orcha-client","invalid Orcha websocket frame",{error:String(s)});return}if(u(n)){if(n.type==="runtime_node.authenticated"){if(r&&this.ws!==r)return;this.connected=!0,this.startHeartbeat(r),m("info","orcha-client","runtime node authenticated",{nodeId:this.config.nodeId,connectionId:n.connectionId});return}if(n.type==="orcha.runtime.request"){await this.handleRequest(n);return}n.type==="runtime_node.ping"&&this.send({type:"runtime_node.pong",ts:new Date().toISOString(),supportedMethods:this.supportedMethods(),sandboxCapabilities:this.sandboxCapabilities(),targets:this.runtimeTargets()})}}startHeartbeat(t){this.heartbeatTimer&&clearInterval(this.heartbeatTimer);let r=Math.max(1e3,Number(this.config.heartbeatIntervalMs||15e3)),n=()=>this.sendCapacityHeartbeat(t);n(),this.heartbeatTimer=setInterval(n,r),this.heartbeatTimer.unref?.()}scheduleCapacityHeartbeat(){if(!this.connected||this.capacityHeartbeatTimer)return;let t=Math.max(25,Math.min(1e3,Number(this.config.capacityHeartbeatDebounceMs||100)));this.capacityHeartbeatTimer=setTimeout(()=>{this.capacityHeartbeatTimer=null,this.sendCapacityHeartbeat()},t),this.capacityHeartbeatTimer.unref?.()}sendCapacityHeartbeat(t=this.ws){return this.connected?this.send({type:"runtime_node.heartbeat",ts:new Date().toISOString(),supportedMethods:this.supportedMethods(),sandboxCapabilities:this.sandboxCapabilities(),targets:this.runtimeTargets()},t):!1}async handleRequest(t){let r=a(t.id),n=a(t.method),s=u(t.params)?t.params:{};try{let i=await this.invoke(n,s,r);this.send({type:"orcha.runtime.response",id:r,ok:!0,result:i})}catch(i){this.send({type:"orcha.runtime.response",id:r,ok:!1,error:{code:i.code||"RUNTIME_NODE_ERROR",message:i.message||String(i),...i.detail===void 0?{}:{detail:i.detail}}})}}async invoke(t,r,n){if(t==="devices/discover"&&this.config.deviceConnection)return this.config.deviceConnection.candidates();if(t==="devices/configure"&&this.config.deviceConnection)return this.config.deviceConnection.configure(r,this.bridge);if(t==="health")return this.bridge.health();if(t==="agents/create")return this.bridge.createAgent(r);if(t==="agents/dispatch")return this.bridge.dispatch(r,{onUpdate:s=>this.sendUpdate(n,s)});if(t==="sessions/prompt")return this.bridge.prompt(r,{onUpdate:s=>this.sendUpdate(n,s)});if(t==="sessions/policy")return this.bridge.updatePolicy(r);if(t==="sessions/cancel")return this.bridge.cancel(r);if(t==="permissions/respond")return this.bridge.respondPermission(r);throw Object.assign(new Error(`unsupported Orcha runtime method: ${t}`),{code:"METHOD_NOT_FOUND"})}sendUpdate(t,r){this.send({type:"orcha.runtime.event",requestId:t,eventType:"runtime.update",payload:r})}send(t,r=this.ws){return!r||r!==this.ws||r.readyState!==ot?!1:(r.send(JSON.stringify(t)),!0)}};import{existsSync as kn,readFileSync as ma}from"node:fs";import{dirname as ga,resolve as Xt}from"node:path";import{fileURLToPath as _a}from"node:url";var ya=/^[A-Za-z_][A-Za-z0-9_]*$/;function Ln(e=process.env,t=process.cwd()){let r=a(e.ORCHA_RUNTIME_ENV_FILE),n=r?Xt(t,r):Xt(t,".env");if(!kn(n))return r&&m("warn","config","runtime env file not found",{path:n}),{loaded:!1,path:n,keys:[]};let s=[],i=ma(n,"utf8");for(let o of i.split(/\r?\n/)){let c=Ra(o);if(!c)continue;let[l,d]=c;Object.prototype.hasOwnProperty.call(e,l)||(e[l]=d,s.push(l))}return m("info","config","runtime env file loaded",{path:n,keyCount:s.length}),{loaded:!0,path:n,keys:s}}function Dn(e=process.env){let t=a(e.ORCHA_RUNTIME_MODE||(e.ORCHA_RUNTIME_ORCHA_URL?"node":"server")),r=a(e.ORCHA_RUNTIME_BRIDGE_HOST||"127.0.0.1"),n=!1,s=ga(_a(import.meta.url)),i=Xt(s,"sandbox","broker.js"),o=Xt(s,"orcha-runtime-sandbox-broker.js"),c=kn(i)?i:o,l=a(e.ORCHA_RUNTIME_SANDBOX_BROKER_COMMAND);return{mode:t,host:r,port:_(e.ORCHA_RUNTIME_BRIDGE_PORT,5588),token:e.ORCHA_RUNTIME_BRIDGE_TOKEN||"",orchaUrl:a(e.ORCHA_RUNTIME_ORCHA_URL),nodeToken:e.ORCHA_RUNTIME_NODE_TOKEN||e.ORCHA_RUNTIME_BRIDGE_TOKEN||"",nodeId:a(e.ORCHA_RUNTIME_NODE_ID||e.HOSTNAME||"local-runtime-node"),nodeName:a(e.ORCHA_RUNTIME_NODE_NAME||e.ORCHA_RUNTIME_NODE_ID||e.HOSTNAME||"Local Runtime Node"),reconnectMs:_(e.ORCHA_RUNTIME_RECONNECT_MS,3e3),connectTimeoutMs:_(e.ORCHA_RUNTIME_CONNECT_TIMEOUT_MS||e.ORCHA_RUNTIME_WS_CONNECT_TIMEOUT_MS,1e4),defaultTargetCode:e.ORCHA_RUNTIME_DEFAULT_TARGET||"echo",requestLimitBytes:_(e.ORCHA_RUNTIME_REQUEST_LIMIT_BYTES,1048576),initializeTimeoutMs:_(e.ORCHA_RUNTIME_INITIALIZE_TIMEOUT_MS,3e4),sessionPromptTimeoutMs:_(e.ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS,36e5),permissionRequestTimeoutMs:_(e.ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS,3e5),sessionIdleTtlMs:_(e.ORCHA_RUNTIME_SESSION_IDLE_TTL_MS,6e5),sessionCleanupIntervalMs:_(e.ORCHA_RUNTIME_SESSION_CLEANUP_INTERVAL_MS,6e4),maxSessionsPerTarget:_(e.ORCHA_RUNTIME_MAX_SESSIONS_PER_TARGET,8),openClawSessionIdleTtlMs:_(e.ORCHA_RUNTIME_OPENCLAW_SESSION_IDLE_TTL_MS,6e4),openClawMaxSessions:_(e.ORCHA_RUNTIME_OPENCLAW_MAX_SESSIONS,1),heartbeatIntervalMs:_(e.ORCHA_RUNTIME_HEARTBEAT_INTERVAL_MS,15e3),sandboxRequired:n,sandboxBrokerCommand:l||process.execPath,sandboxBrokerArguments:tr(e.ORCHA_RUNTIME_SANDBOX_BROKER_ARGUMENTS,"ORCHA_RUNTIME_SANDBOX_BROKER_ARGUMENTS",l?[]:[c]),sandboxProbeTimeoutMs:_(e.ORCHA_RUNTIME_SANDBOX_PROBE_TIMEOUT_MS,1e4),sandboxTempRoot:a(e.ORCHA_RUNTIME_SANDBOX_TEMP_ROOT),trustedWorkspaceRoots:tr(e.ORCHA_RUNTIME_TRUSTED_WORKSPACE_ROOTS,"ORCHA_RUNTIME_TRUSTED_WORKSPACE_ROOTS"),trustedToolchainRoots:tr(e.ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS,"ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS"),egressProxyRequired:wa(e.ORCHA_RUNTIME_EGRESS_PROXY_REQUIRED,t==="node"),egressProxySocket:a(e.ORCHA_RUNTIME_EGRESS_PROXY_SOCKET),egressProxyToken:a(e.ORCHA_RUNTIME_EGRESS_PROXY_TOKEN),egressGrantMaxTtlMs:_(e.ORCHA_RUNTIME_EGRESS_GRANT_MAX_TTL_MS,9e5),targets:Ta(e.ORCHA_RUNTIME_TARGETS_JSON||"")}}function Ta(e){if(!a(e))return{};try{let t=JSON.parse(e);if(u(t))return t}catch(t){m("warn","config","invalid ORCHA_RUNTIME_TARGETS_JSON",{error:String(t)})}return{}}function wa(e,t){let r=a(e).toLowerCase();if(!r)return t;if(["true","1","yes","on"].includes(r))return!0;if(["false","0","no","off"].includes(r))return!1;throw new Error(`invalid boolean configuration value: ${r}`)}function tr(e,t,r=[]){let n=a(e);if(!n)return[...r];let s;try{s=JSON.parse(n)}catch{throw new Error(`${t} must be a JSON string array`)}if(!Array.isArray(s)||s.some(i=>typeof i!="string"))throw new Error(`${t} must be a JSON string array`);return s.map(i=>i.trim()).filter(Boolean)}function Ra(e){let t=e.trim();if(!t||t.startsWith("#"))return null;let r=t.startsWith("export ")?t.slice(7).trimStart():t,n=r.indexOf("=");if(n<=0)return null;let s=r.slice(0,n).trim();if(!ya.test(s))return null;let i=Sa(r.slice(n+1).trim());return[s,i]}function Sa(e){if(!e)return"";let t=e[0];if((t==='"'||t==="'")&&e.endsWith(t)){let r=e.slice(1,-1);return t==='"'?Ea(r):r}return Oa(e).trim()}function Ea(e){return e.replaceAll("\\n",`
|
|
19
|
+
`).replaceAll("\\r","\r").replaceAll("\\t"," ").replaceAll('\\"','"').replaceAll("\\\\","\\")}function Oa(e){let t=!1,r=!1;for(let n=0;n<e.length;n+=1){let s=e[n],i=e[n-1];if(s==="'"&&!r)t=!t;else if(s==='"'&&!t&&i!=="\\")r=!r;else if(s==="#"&&!t&&!r&&/\s/.test(i||""))return e.slice(0,n)}return e}import{createServer as Ia}from"node:http";function Yt(e,t,r){let n=JSON.stringify(r);e.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(n)}),e.end(n)}function X(e={}){return{ok:!0,...e}}function er(e,t,r){return{ok:!1,error:{code:e,message:t,...r===void 0?{}:{detail:r}}}}async function vn(e,t){let r=[],n=0;for await(let i of e){if(n+=i.length,n>t)throw Object.assign(new Error("request body too large"),{status:413,code:"REQUEST_TOO_LARGE"});r.push(i)}if(r.length===0)return{};let s=Buffer.concat(r).toString("utf8");if(!s.trim())return{};try{let i=JSON.parse(s);if(!u(i))throw Object.assign(new Error("JSON body must be an object"),{status:400,code:"BAD_JSON"});return i}catch(i){throw i.status?i:Object.assign(new Error(`invalid JSON body: ${i.message}`),{status:400,code:"BAD_JSON"})}}function Hn(e,t){if(!t)return;if((e.headers.authorization||"")!==`Bearer ${t}`)throw Object.assign(new Error("runtime bridge token is invalid"),{status:401,code:"UNAUTHORIZED"})}function $n(e,t){let r={"GET /health":async()=>X(t.health()),"POST /agents/create":async n=>X(await t.createAgent(n)),"POST /agents/dispatch":async n=>X(await t.dispatch(n)),"POST /sessions/prompt":async n=>X(await t.prompt(n)),"POST /sessions/cancel":async n=>X(await t.cancel(n)),"POST /permissions/respond":async n=>X(await t.respondPermission(n))};return Ia(async(n,s)=>{let i=new URL(n.url||"/",`http://${n.headers.host||`${e.host}:${e.port}`}`),o=`${n.method||"GET"} ${i.pathname}`,c=r[o];if(!c){Yt(s,404,er("NOT_FOUND",`No route for ${o}`));return}try{Hn(n,e.token);let l=n.method==="GET"?{}:await vn(n,e.requestLimitBytes);Yt(s,200,await c(l))}catch(l){let d=l.status||500,f=l.code||"BRIDGE_INTERNAL";Yt(s,d,er(f,l.message||String(l),l.detail))}})}var Pa=Ua(import.meta.url),ka=".orcha-runtime-bridge.pid",La=".orcha-runtime-bridge.log",Da=3,va=36e5,{command:Ha,options:Vn}=Ba(process.argv.slice(2));qa(Vn);Ln();var $a=Dn();await Jn(Ha,$a,Vn);async function Jn(e,t,r){if(r.url){let s=ie(r.url);r.pidFile||(process.env.ORCHA_RUNTIME_PID_FILE=s.pidFile),r.logFile||(process.env.ORCHA_RUNTIME_LOG_FILE=s.logFile)}let n=()=>["connect","--url",t.orchaUrl,"--foreground"];switch(e){case"connect":if(r.pairCode&&Y(Qt(Zt())))throw new Error("\u8BBE\u5907\u8FDE\u63A5\u4ECD\u5728\u540E\u53F0\u8FD0\u884C\uFF0C\u8BF7\u5148\u6267\u884C stop --url \u540E\u91CD\u65B0\u914D\u5BF9");await St(t,r),r.foreground?await rr(t):nr(n());return;case"run":case"foreground":r.url&&await St(t,r),await rr(t);return;case"start":if(r.url)return Jn("connect",t,r);if(r.foreground){await rr(t);return}nr();return;case"reload":case"restart":r.url&&await St(t,{url:r.url}),await qn({quiet:!0}),nr(r.url?n():void 0);return;case"stop":await qn();return;case"status":Fa();return;case"help":case"--help":case"-h":za();return;default:throw new Error(`Unknown command: ${e}`)}}async function rr(e){ja();let t=new Vt(e);if(await t.start(),e.mode==="server"){let n=$n(e,t);Bn({bridge:t,server:n}),n.listen(e.port,e.host,()=>{m("info","runtime-bridge","Orcha runtime bridge HTTP server started",{host:e.host,port:e.port,targets:Object.keys(t.targets)})});return}if(!e.orchaUrl)throw new Error("ORCHA_RUNTIME_ORCHA_URL is required in runtime node mode");let r=new Wt(e,t);Bn({bridge:t,client:r}),r.start(),m("info","runtime-bridge","Orcha runtime node started",{nodeId:e.nodeId,nodeName:e.nodeName,orchaUrl:e.orchaUrl,targets:Object.keys(t.targets)})}function Bn({bridge:e,client:t,server:r}){let n=!1,s=i=>{if(n)return;n=!0;let o=Number(e?.sessions?.size||0)>0;m("info","runtime-bridge","runtime bridge shutting down",{signal:i});try{t?.stop?.()}catch(c){m("warn","runtime-bridge","runtime client stop failed",{error:String(c)})}Promise.resolve(e?.stop?.(`process_${String(i||"shutdown").toLowerCase()}`)).catch(c=>{m("warn","runtime-bridge","runtime bridge stop failed",{error:String(c)})}).finally(()=>{try{r?.close?.()}catch(c){m("warn","runtime-bridge","runtime server close failed",{error:String(c)})}}),setTimeout(()=>process.exit(0),o?8500:200)};process.once("SIGTERM",()=>s("SIGTERM")),process.once("SIGINT",()=>s("SIGINT"))}function nr(e=["run"]){let t=Zt(),r=Wn(),n=Qt(t);if(n&&Y(n)){console.log(JSON.stringify({status:"already_running",pid:n,pidFile:t,logFile:r}));return}n&&or(t),Kn(t),Kn(r),ir(r);let s=Aa(r,"a"),i={...process.env,ORCHA_RUNTIME_PID_FILE:t,ORCHA_RUNTIME_LOG_FILE:r},o=xa(process.execPath,[Pa,...e,"--pid-file",t,"--log-file",r],{cwd:process.cwd(),detached:!0,env:i,stdio:["ignore",s,s]});o.unref(),Ca(s),zn(t,`${o.pid}
|
|
20
|
+
`),console.log(JSON.stringify({status:"started",pid:o.pid,pidFile:t,logFile:r}))}async function qn({quiet:e=!1}={}){let t=Zt(),r=Qt(t);if(!r){e||console.log(JSON.stringify({status:"not_running",pidFile:t}));return}if(!Y(r)){or(t),e||console.log(JSON.stringify({status:"not_running",pid:r,pidFile:t}));return}process.kill(r,"SIGTERM"),!await jn(r,1e4)&&Y(r)&&(process.kill(r,"SIGKILL"),await jn(r,3e3)),or(t),e||console.log(JSON.stringify({status:"stopped",pid:r,pidFile:t}))}function Fa(){let e=Zt(),t=Wn(),r=Qt(e),n=!!(r&&Y(r));console.log(JSON.stringify({status:n?"running":"not_running",running:n,pid:n?r:null,pidFile:e,logFile:t}))}function Ba(e){let t=[],r={};for(let s=0;s<e.length;s+=1){let i=e[s];i==="--url"?r.url=e[++s]:i==="--pair-code"?r.pairCode=e[++s]:i==="--daemon"?r.daemon=!0:i==="--foreground"?r.foreground=!0:i==="--env-file"?r.envFile=e[++s]:i==="--pid-file"?r.pidFile=e[++s]:i==="--log-file"?r.logFile=e[++s]:t.push(i)}return{command:t[0]||"run",options:r}}function qa(e){e.envFile&&(process.env.ORCHA_RUNTIME_ENV_FILE=e.envFile),e.pidFile&&(process.env.ORCHA_RUNTIME_PID_FILE=e.pidFile),e.logFile&&(process.env.ORCHA_RUNTIME_LOG_FILE=e.logFile)}function Zt(){return ar(process.cwd(),process.env.ORCHA_RUNTIME_PID_FILE||ka)}function Wn(){return ar(process.cwd(),process.env.ORCHA_RUNTIME_LOG_FILE||La)}function ja(){let e=process.env.ORCHA_RUNTIME_LOG_FILE;if(!e)return;let t=Xn();if(t<=0)return;let r=ar(process.cwd(),e);ir(r,t);let n=Ga();n<=0||setInterval(()=>ir(r,t),n).unref()}function ir(e,t=Xn()){if(t<=0||!Gn(e))return;let r=0,n="";try{if(r=Fn(e).size,r<=0)return;n=sr(e,"utf8")}catch(d){m("warn","runtime-bridge","runtime log cleanup skipped",{logFile:e,error:String(d)});return}let s=Date.now()-t*24*60*60*1e3,i=n.split(/\r?\n/),o=[],c=0;for(let d of i)d&&(Ka(d,s)?o.push(d):c+=1);if(c===0)return;let l="";try{Fn(e).size>r&&(l=sr(e,"utf8").slice(n.length));let f=[...o,...l.split(/\r?\n/).filter(Boolean)].join(`
|
|
21
|
+
`);zn(e,f?`${f}
|
|
22
|
+
`:""),m("info","runtime-bridge","runtime log cleanup completed",{logFile:e,retentionDays:t,removed:c})}catch(d){m("warn","runtime-bridge","runtime log cleanup failed",{logFile:e,error:String(d)})}}function Ka(e,t){try{let r=JSON.parse(e);if(!r||typeof r!="object")return!0;let n=typeof r.ts=="string"?Date.parse(r.ts):Number.NaN;return!Number.isFinite(n)||n>=t}catch{return!0}}function Xn(){return Yn(process.env.ORCHA_RUNTIME_LOG_RETENTION_DAYS,Da)}function Ga(){return Yn(process.env.ORCHA_RUNTIME_LOG_CLEANUP_INTERVAL_MS,va)}function Yn(e,t){let r=Number.parseInt(String(e??""),10);return Number.isFinite(r)&&r>=0?r:t}function Qt(e){if(!Gn(e))return null;let t=Number.parseInt(sr(e,"utf8").trim(),10);return Number.isInteger(t)&&t>0?t:null}function Y(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t?.code==="EPERM"}}async function jn(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!Y(e))return!0;await new Promise(n=>setTimeout(n,100))}return!Y(e)}function Kn(e){ba(Ma(e),{recursive:!0})}function or(e){try{Na(e,{force:!0})}catch{}}function za(){console.log(`Usage: orcha-runtime-bridge [command] [options]
|
|
23
23
|
|
|
24
24
|
Commands:
|
|
25
|
+
connect Pair or reconnect this device, then run in the background.
|
|
25
26
|
run, foreground Run in the foreground. This is the default.
|
|
26
27
|
start Start in the background and write a pid file.
|
|
27
28
|
reload, restart Stop the background process and start it again.
|
|
@@ -29,8 +30,10 @@ Commands:
|
|
|
29
30
|
status Print background process status as JSON.
|
|
30
31
|
|
|
31
32
|
Options:
|
|
33
|
+
--url <url> Orcha address for device connection.
|
|
34
|
+
--pair-code <code> One-time code from the Agents page (first connection only).
|
|
32
35
|
--env-file <path> Load runtime environment from this file.
|
|
33
36
|
--pid-file <path> Override ORCHA_RUNTIME_PID_FILE.
|
|
34
37
|
--log-file <path> Override ORCHA_RUNTIME_LOG_FILE.
|
|
35
|
-
--foreground
|
|
38
|
+
--foreground Run "connect" or "start" in the foreground for diagnostics.
|
|
36
39
|
`)}
|