@h-rig/runtime 0.0.6-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/README.md +27 -0
  2. package/dist/bin/rig-agent-dispatch.js +9615 -0
  3. package/dist/bin/rig-agent.js +9512 -0
  4. package/dist/bin/rig-browser-tool.js +269 -0
  5. package/dist/src/agent-mode.js +48 -0
  6. package/dist/src/baked-secrets.js +121 -0
  7. package/dist/src/binary-build-worker.js +312 -0
  8. package/dist/src/binary-run.js +540 -0
  9. package/dist/src/boundaries.js +1 -0
  10. package/dist/src/build-time-config.js +25 -0
  11. package/dist/src/control-plane/agent-roles.js +27 -0
  12. package/dist/src/control-plane/agent-wrapper.js +9621 -0
  13. package/dist/src/control-plane/authority-files.js +582 -0
  14. package/dist/src/control-plane/browser-contract.js +135 -0
  15. package/dist/src/control-plane/controlled-bash.js +1111 -0
  16. package/dist/src/control-plane/errors.js +13 -0
  17. package/dist/src/control-plane/harness-main.js +10828 -0
  18. package/dist/src/control-plane/hook-materializer.js +75 -0
  19. package/dist/src/control-plane/hooks/audit-trail.js +353 -0
  20. package/dist/src/control-plane/hooks/completion-verification.js +7552 -0
  21. package/dist/src/control-plane/hooks/import-guard.js +890 -0
  22. package/dist/src/control-plane/hooks/inject-context.js +4189 -0
  23. package/dist/src/control-plane/hooks/post-edit-lint.js +43 -0
  24. package/dist/src/control-plane/hooks/safety-guard.js +910 -0
  25. package/dist/src/control-plane/hooks/scope-guard.js +907 -0
  26. package/dist/src/control-plane/hooks/shared.js +44 -0
  27. package/dist/src/control-plane/hooks/submodule-branch.js +7797 -0
  28. package/dist/src/control-plane/hooks/task-runtime-start.js +7799 -0
  29. package/dist/src/control-plane/hooks/test-integrity-guard.js +891 -0
  30. package/dist/src/control-plane/materialize-task-config.js +453 -0
  31. package/dist/src/control-plane/memory-sync/cli.js +2019 -0
  32. package/dist/src/control-plane/memory-sync/db.js +753 -0
  33. package/dist/src/control-plane/memory-sync/embed.js +281 -0
  34. package/dist/src/control-plane/memory-sync/index.js +2049 -0
  35. package/dist/src/control-plane/memory-sync/query.js +294 -0
  36. package/dist/src/control-plane/memory-sync/read.js +784 -0
  37. package/dist/src/control-plane/memory-sync/types.js +6 -0
  38. package/dist/src/control-plane/memory-sync/write.js +1547 -0
  39. package/dist/src/control-plane/native/git-native.js +490 -0
  40. package/dist/src/control-plane/native/git-ops.js +2860 -0
  41. package/dist/src/control-plane/native/harness-cli.js +9721 -0
  42. package/dist/src/control-plane/native/pr-automation.js +373 -0
  43. package/dist/src/control-plane/native/profile-ops.js +481 -0
  44. package/dist/src/control-plane/native/repo-ops.js +2342 -0
  45. package/dist/src/control-plane/native/root-resolver.js +66 -0
  46. package/dist/src/control-plane/native/run-ops.js +3281 -0
  47. package/dist/src/control-plane/native/runtime-native-sidecar.js +299 -0
  48. package/dist/src/control-plane/native/runtime-native.js +392 -0
  49. package/dist/src/control-plane/native/scope-rules.js +17 -0
  50. package/dist/src/control-plane/native/task-ops.js +6320 -0
  51. package/dist/src/control-plane/native/task-state.js +1512 -0
  52. package/dist/src/control-plane/native/utils.js +535 -0
  53. package/dist/src/control-plane/native/validator-binaries.js +889 -0
  54. package/dist/src/control-plane/native/validator.js +2197 -0
  55. package/dist/src/control-plane/native/verifier.js +3249 -0
  56. package/dist/src/control-plane/native/workspace-ops.js +1635 -0
  57. package/dist/src/control-plane/plugin-host-context.js +334 -0
  58. package/dist/src/control-plane/project-main-pre-run-sync.js +630 -0
  59. package/dist/src/control-plane/provider/claude-stream-records.js +158 -0
  60. package/dist/src/control-plane/provider/codex-app-server.js +885 -0
  61. package/dist/src/control-plane/provider/codex-exec-records.js +203 -0
  62. package/dist/src/control-plane/provider/rig-task-run-skill.js +39 -0
  63. package/dist/src/control-plane/provider/runtime-instructions.js +96 -0
  64. package/dist/src/control-plane/remote.js +854 -0
  65. package/dist/src/control-plane/repos/index.js +473 -0
  66. package/dist/src/control-plane/repos/layout.js +124 -0
  67. package/dist/src/control-plane/repos/mirror/bootstrap.js +268 -0
  68. package/dist/src/control-plane/repos/mirror/refresh.js +398 -0
  69. package/dist/src/control-plane/repos/mirror/state.js +167 -0
  70. package/dist/src/control-plane/repos/registry.js +77 -0
  71. package/dist/src/control-plane/repos/types.js +1 -0
  72. package/dist/src/control-plane/runtime/agent-mode.js +48 -0
  73. package/dist/src/control-plane/runtime/baked-secrets.js +120 -0
  74. package/dist/src/control-plane/runtime/claude-tool-router-binary.js +343 -0
  75. package/dist/src/control-plane/runtime/claude-tool-router.js +520 -0
  76. package/dist/src/control-plane/runtime/context.js +216 -0
  77. package/dist/src/control-plane/runtime/events.js +218 -0
  78. package/dist/src/control-plane/runtime/guard-types.js +6 -0
  79. package/dist/src/control-plane/runtime/guard.js +880 -0
  80. package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +1194 -0
  81. package/dist/src/control-plane/runtime/image/index.js +2255 -0
  82. package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +1191 -0
  83. package/dist/src/control-plane/runtime/image.js +2255 -0
  84. package/dist/src/control-plane/runtime/index.js +8511 -0
  85. package/dist/src/control-plane/runtime/isolation/discovery.js +599 -0
  86. package/dist/src/control-plane/runtime/isolation/home.js +1217 -0
  87. package/dist/src/control-plane/runtime/isolation/index.js +8193 -0
  88. package/dist/src/control-plane/runtime/isolation/runner.js +2651 -0
  89. package/dist/src/control-plane/runtime/isolation/shared.js +501 -0
  90. package/dist/src/control-plane/runtime/isolation/toolchain.js +1892 -0
  91. package/dist/src/control-plane/runtime/isolation/types.js +1 -0
  92. package/dist/src/control-plane/runtime/isolation/worktree.js +509 -0
  93. package/dist/src/control-plane/runtime/isolation.js +8193 -0
  94. package/dist/src/control-plane/runtime/overlay.js +67 -0
  95. package/dist/src/control-plane/runtime/plugin-mode.js +41 -0
  96. package/dist/src/control-plane/runtime/plugins.js +1131 -0
  97. package/dist/src/control-plane/runtime/provisioning-env.js +220 -0
  98. package/dist/src/control-plane/runtime/queue.js +8358 -0
  99. package/dist/src/control-plane/runtime/rig-shell.js +205 -0
  100. package/dist/src/control-plane/runtime/rig-tools.js +182 -0
  101. package/dist/src/control-plane/runtime/runner-context.js +1 -0
  102. package/dist/src/control-plane/runtime/runtime-paths.js +184 -0
  103. package/dist/src/control-plane/runtime/sandbox/backend-bwrap.js +311 -0
  104. package/dist/src/control-plane/runtime/sandbox/backend-none.js +21 -0
  105. package/dist/src/control-plane/runtime/sandbox/backend-seatbelt.js +268 -0
  106. package/dist/src/control-plane/runtime/sandbox/backend.js +1718 -0
  107. package/dist/src/control-plane/runtime/sandbox/orchestrator.js +1745 -0
  108. package/dist/src/control-plane/runtime/sandbox/utils.js +137 -0
  109. package/dist/src/control-plane/runtime/sandbox-backend-bwrap.js +311 -0
  110. package/dist/src/control-plane/runtime/sandbox-backend-none.js +21 -0
  111. package/dist/src/control-plane/runtime/sandbox-backend-seatbelt.js +268 -0
  112. package/dist/src/control-plane/runtime/sandbox-backend.js +1718 -0
  113. package/dist/src/control-plane/runtime/sandbox-orchestrator.js +1745 -0
  114. package/dist/src/control-plane/runtime/sandbox-utils.js +137 -0
  115. package/dist/src/control-plane/runtime/snapshot/index.js +454 -0
  116. package/dist/src/control-plane/runtime/snapshot/sidecar.js +502 -0
  117. package/dist/src/control-plane/runtime/snapshot/task-run.js +1578 -0
  118. package/dist/src/control-plane/runtime/snapshot-sidecar.js +498 -0
  119. package/dist/src/control-plane/runtime/snapshot.js +454 -0
  120. package/dist/src/control-plane/runtime/task-run-snapshot.js +1578 -0
  121. package/dist/src/control-plane/runtime/tool-gateway.js +422 -0
  122. package/dist/src/control-plane/runtime/tooling/browser-tools.js +32 -0
  123. package/dist/src/control-plane/runtime/tooling/claude-router-binary.js +343 -0
  124. package/dist/src/control-plane/runtime/tooling/claude-router.js +524 -0
  125. package/dist/src/control-plane/runtime/tooling/file-tools.js +182 -0
  126. package/dist/src/control-plane/runtime/tooling/gateway.js +422 -0
  127. package/dist/src/control-plane/runtime/tooling/index.js +1290 -0
  128. package/dist/src/control-plane/runtime/tooling/shell.js +205 -0
  129. package/dist/src/control-plane/runtime/types.js +1 -0
  130. package/dist/src/control-plane/setup-version.js +14 -0
  131. package/dist/src/control-plane/state-sync/index.js +1509 -0
  132. package/dist/src/control-plane/state-sync/read.js +856 -0
  133. package/dist/src/control-plane/state-sync/reconcile.js +260 -0
  134. package/dist/src/control-plane/state-sync/repo.js +302 -0
  135. package/dist/src/control-plane/state-sync/types.js +111 -0
  136. package/dist/src/control-plane/state-sync/write.js +1469 -0
  137. package/dist/src/control-plane/task-fields.js +38 -0
  138. package/dist/src/control-plane/task-source-bootstrap.js +46 -0
  139. package/dist/src/control-plane/task-source.js +30 -0
  140. package/dist/src/control-plane/tasks/legacy-task-config-source.js +130 -0
  141. package/dist/src/control-plane/tasks/plugin-task-source.js +103 -0
  142. package/dist/src/control-plane/tasks/source-aware-task-config-source.js +611 -0
  143. package/dist/src/control-plane/tasks/source-lifecycle.js +1093 -0
  144. package/dist/src/control-plane/tasks/task-record-reader.js +9 -0
  145. package/dist/src/control-plane/validators/boundary/public-apis.js +107 -0
  146. package/dist/src/control-plane/validators/integration/_shared.js +51 -0
  147. package/dist/src/control-plane/validators/integration/adm-audit-http.js +85 -0
  148. package/dist/src/control-plane/validators/integration/adm-auth-http.js +78 -0
  149. package/dist/src/control-plane/validators/integration/adm-issuer-http.js +80 -0
  150. package/dist/src/control-plane/validators/integration/adm-migration.js +78 -0
  151. package/dist/src/control-plane/validators/integration/adm-scaffold.js +78 -0
  152. package/dist/src/control-plane/validators/runtime-registration.js +64 -0
  153. package/dist/src/control-plane/validators/shared.js +683 -0
  154. package/dist/src/events.js +218 -0
  155. package/dist/src/execution.js +35 -0
  156. package/dist/src/index.js +1633 -0
  157. package/dist/src/layout.js +145 -0
  158. package/dist/src/local-server.js +202 -0
  159. package/dist/src/plugins.js +329 -0
  160. package/dist/src/remote-http.js +83 -0
  161. package/dist/src/runtime-context.js +216 -0
  162. package/dist/src/types.js +1 -0
  163. package/native/darwin-arm64/bin/rig-git +0 -0
  164. package/native/darwin-arm64/bin/rig-shell +0 -0
  165. package/native/darwin-arm64/bin/rig-tools +0 -0
  166. package/native/darwin-arm64/lib/runtime-native-darwin-arm64.dylib +0 -0
  167. package/native/darwin-arm64/lib/runtime-native.dylib +0 -0
  168. package/native/darwin-arm64/manifest.json +1 -0
  169. package/native/linux-x64/bin/rig-git +0 -0
  170. package/native/linux-x64/bin/rig-shell +0 -0
  171. package/native/linux-x64/bin/rig-tools +0 -0
  172. package/native/linux-x64/lib/runtime-native-linux-x64.so +0 -0
  173. package/native/linux-x64/lib/runtime-native.so +0 -0
  174. package/native/linux-x64/manifest.json +1 -0
  175. package/package.json +74 -0
  176. package/skills/rig-task-run.md +71 -0
@@ -0,0 +1,524 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // packages/runtime/src/control-plane/runtime/tooling/claude-router.ts
5
+ import { existsSync, mkdirSync, statSync, writeFileSync } from "fs";
6
+ import { resolve } from "path";
7
+ import { createInterface } from "readline";
8
+ var CLAUDE_ROUTER_SERVER_NAME = "rig_runtime_tools";
9
+ var CLAUDE_DISABLED_FILE_TOOLS = [
10
+ "Read",
11
+ "Edit",
12
+ "Write",
13
+ "NotebookEdit",
14
+ "Glob",
15
+ "Grep"
16
+ ];
17
+ var ROUTER_VERSION = "0.1.0";
18
+ var CLAUDE_ROUTER_TOOL_DEFINITIONS = [
19
+ {
20
+ name: "read",
21
+ description: "Read a UTF-8 file from the current Rig task worktree, the outer control-plane repo ($PROJECT_RIG_ROOT), or the host monorepo checkout ($MONOREPO_MAIN_ROOT).",
22
+ inputSchema: {
23
+ type: "object",
24
+ properties: {
25
+ path: { type: "string", description: "Absolute or workspace-relative file path." },
26
+ offset: { type: "integer", minimum: 0 },
27
+ limit: { type: "integer", minimum: 1, maximum: 2097152 }
28
+ },
29
+ required: ["path"],
30
+ additionalProperties: false
31
+ }
32
+ },
33
+ {
34
+ name: "write",
35
+ description: "Write UTF-8 content to a file inside the current Rig task workspace only.",
36
+ inputSchema: {
37
+ type: "object",
38
+ properties: {
39
+ path: { type: "string", description: "Absolute or workspace-relative file path." },
40
+ content: { type: "string" },
41
+ create_parents: { type: "boolean" }
42
+ },
43
+ required: ["path", "content"],
44
+ additionalProperties: false
45
+ }
46
+ },
47
+ {
48
+ name: "edit",
49
+ description: "Replace one or more exact string occurrences in a UTF-8 file inside the current Rig task workspace only.",
50
+ inputSchema: {
51
+ type: "object",
52
+ properties: {
53
+ path: { type: "string", description: "Absolute or workspace-relative file path." },
54
+ old_string: { type: "string" },
55
+ new_string: { type: "string" },
56
+ replace_all: { type: "boolean" }
57
+ },
58
+ required: ["path", "old_string", "new_string"],
59
+ additionalProperties: false
60
+ }
61
+ },
62
+ {
63
+ name: "glob",
64
+ description: "Search files using a glob pattern across the current task worktree, $PROJECT_RIG_ROOT, or $MONOREPO_MAIN_ROOT.",
65
+ inputSchema: {
66
+ type: "object",
67
+ properties: {
68
+ pattern: { type: "string" },
69
+ path: { type: "string", description: "Optional workspace-relative search root." },
70
+ include_hidden: { type: "boolean" },
71
+ max_results: { type: "integer", minimum: 1, maximum: 5000 }
72
+ },
73
+ required: ["pattern"],
74
+ additionalProperties: false
75
+ }
76
+ },
77
+ {
78
+ name: "grep",
79
+ description: "Search file contents across the current task worktree, $PROJECT_RIG_ROOT, or $MONOREPO_MAIN_ROOT.",
80
+ inputSchema: {
81
+ type: "object",
82
+ properties: {
83
+ pattern: { type: "string" },
84
+ path: { type: "string", description: "Optional workspace-relative search root." },
85
+ literal: { type: "boolean" },
86
+ include_hidden: { type: "boolean" },
87
+ max_results: { type: "integer", minimum: 1, maximum: 500 },
88
+ glob: { type: "string", description: "Optional file glob filter passed through to ripgrep." }
89
+ },
90
+ required: ["pattern"],
91
+ additionalProperties: false
92
+ }
93
+ }
94
+ ];
95
+ function claudeRuntimeToolCliArgs(configPath) {
96
+ return [
97
+ "--disallowedTools",
98
+ CLAUDE_DISABLED_FILE_TOOLS.join(","),
99
+ "--mcp-config",
100
+ configPath
101
+ ];
102
+ }
103
+ function buildRuntimeToolRouterServerConfig(options) {
104
+ return {
105
+ type: "stdio",
106
+ command: resolve(options.binDir, "rig-tool-router"),
107
+ args: [],
108
+ env: {
109
+ RIG_RUNTIME_CONTEXT_FILE: options.contextFile,
110
+ RIG_RUNTIME_BIN_DIR: options.binDir
111
+ }
112
+ };
113
+ }
114
+ function escapeTomlString(value) {
115
+ return value.replaceAll("\\", "\\\\").replaceAll('"', "\\\"");
116
+ }
117
+ function tomlString(value) {
118
+ return `"${escapeTomlString(value)}"`;
119
+ }
120
+ function tomlStringArray(values) {
121
+ return `[${values.map((value) => tomlString(value)).join(", ")}]`;
122
+ }
123
+ function tomlInlineTable(entries) {
124
+ return `{ ${Object.entries(entries).map(([key, value]) => `${key} = ${tomlString(value)}`).join(", ")} }`;
125
+ }
126
+ function codexRuntimeToolCliArgs(options) {
127
+ const serverConfig = buildRuntimeToolRouterServerConfig(options);
128
+ return [
129
+ "-a",
130
+ "never",
131
+ "-c",
132
+ `mcp_servers.${CLAUDE_ROUTER_SERVER_NAME}.command=${tomlString(serverConfig.command)}`,
133
+ "-c",
134
+ `mcp_servers.${CLAUDE_ROUTER_SERVER_NAME}.args=${tomlStringArray(serverConfig.args)}`,
135
+ "-c",
136
+ `mcp_servers.${CLAUDE_ROUTER_SERVER_NAME}.env=${tomlInlineTable(serverConfig.env)}`
137
+ ];
138
+ }
139
+ function writeClaudeRuntimeToolRouterConfig(options) {
140
+ const configPath = resolve(options.stateDir, "claude-runtime-tools.mcp.json");
141
+ mkdirSync(options.stateDir, { recursive: true });
142
+ const payload = {
143
+ mcpServers: {
144
+ [CLAUDE_ROUTER_SERVER_NAME]: buildRuntimeToolRouterServerConfig(options)
145
+ }
146
+ };
147
+ writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}
148
+ `, "utf-8");
149
+ return configPath;
150
+ }
151
+ async function runClaudeToolRouterServer() {
152
+ const lineReader = createInterface({
153
+ input: process.stdin,
154
+ crlfDelay: Infinity
155
+ });
156
+ const inFlightToolCalls = new Set;
157
+ const trackToolCall = (call) => {
158
+ inFlightToolCalls.add(call);
159
+ call.finally(() => inFlightToolCalls.delete(call)).catch((err) => {
160
+ console.warn("[claude-router] in-flight tool call failure:", err);
161
+ });
162
+ };
163
+ for await (const line of lineReader) {
164
+ const trimmed = line.trim();
165
+ if (!trimmed) {
166
+ continue;
167
+ }
168
+ let request;
169
+ try {
170
+ request = JSON.parse(trimmed);
171
+ } catch {
172
+ continue;
173
+ }
174
+ if (!request.method) {
175
+ continue;
176
+ }
177
+ if (request.method === "notifications/initialized") {
178
+ continue;
179
+ }
180
+ if (request.method === "initialize") {
181
+ writeMessage({
182
+ jsonrpc: "2.0",
183
+ id: request.id ?? null,
184
+ result: {
185
+ protocolVersion: "2024-11-05",
186
+ capabilities: {
187
+ tools: {}
188
+ },
189
+ serverInfo: {
190
+ name: CLAUDE_ROUTER_SERVER_NAME,
191
+ version: ROUTER_VERSION
192
+ }
193
+ }
194
+ });
195
+ continue;
196
+ }
197
+ if (request.method === "ping") {
198
+ writeMessage({
199
+ jsonrpc: "2.0",
200
+ id: request.id ?? null,
201
+ result: {}
202
+ });
203
+ continue;
204
+ }
205
+ if (request.method === "tools/list") {
206
+ writeMessage({
207
+ jsonrpc: "2.0",
208
+ id: request.id ?? null,
209
+ result: {
210
+ tools: CLAUDE_ROUTER_TOOL_DEFINITIONS
211
+ }
212
+ });
213
+ continue;
214
+ }
215
+ if (request.method === "tools/call") {
216
+ const toolName = typeof request.params?.name === "string" ? request.params.name : "";
217
+ const args = isRecord(request.params?.arguments) ? request.params.arguments : {};
218
+ const requestId = request.id ?? null;
219
+ const toolCall = (async () => {
220
+ try {
221
+ const result = await invokeRuntimeTool(toolName, args);
222
+ writeMessage({
223
+ jsonrpc: "2.0",
224
+ id: requestId,
225
+ result
226
+ });
227
+ } catch (error) {
228
+ writeMessage({
229
+ jsonrpc: "2.0",
230
+ id: requestId,
231
+ error: {
232
+ code: -32603,
233
+ message: error instanceof Error ? error.message : String(error)
234
+ }
235
+ });
236
+ }
237
+ })();
238
+ trackToolCall(toolCall);
239
+ continue;
240
+ }
241
+ writeMessage({
242
+ jsonrpc: "2.0",
243
+ id: request.id ?? null,
244
+ error: {
245
+ code: -32601,
246
+ message: `Unsupported method: ${request.method}`
247
+ }
248
+ });
249
+ }
250
+ if (inFlightToolCalls.size > 0) {
251
+ await Promise.allSettled(Array.from(inFlightToolCalls));
252
+ }
253
+ }
254
+ async function invokeRuntimeTool(toolName, args, options = {}) {
255
+ if (toolName === "shell") {
256
+ return invokeRuntimeShellTool(args, options);
257
+ }
258
+ const invocationEnv = options.env ?? process.env;
259
+ const binaryPath = resolveRuntimeToolBinary(toolName, invocationEnv);
260
+ if (!binaryPath) {
261
+ return {
262
+ content: [
263
+ {
264
+ type: "text",
265
+ text: `Unknown Rig runtime tool: ${toolName}`
266
+ }
267
+ ],
268
+ isError: true
269
+ };
270
+ }
271
+ const proc = Bun.spawn([binaryPath], {
272
+ stdin: "pipe",
273
+ stdout: "pipe",
274
+ stderr: "pipe",
275
+ env: invocationEnv
276
+ });
277
+ const requestBody = `${JSON.stringify(args)}
278
+ `;
279
+ if (proc.stdin) {
280
+ await proc.stdin.write(requestBody);
281
+ await proc.stdin.end();
282
+ }
283
+ const [exitCode, stdout, stderr] = await Promise.all([
284
+ proc.exited,
285
+ readBunProcessPipe(proc.stdout),
286
+ readBunProcessPipe(proc.stderr)
287
+ ]);
288
+ if (exitCode !== 0) {
289
+ const text = [stdout.trim(), stderr.trim()].filter(Boolean).join(`
290
+ `) || `Tool ${toolName} exited with code ${exitCode}`;
291
+ return {
292
+ content: [{ type: "text", text }],
293
+ isError: true
294
+ };
295
+ }
296
+ let payload;
297
+ try {
298
+ payload = JSON.parse(stdout);
299
+ } catch {
300
+ return {
301
+ content: [{ type: "text", text: stdout.trim() || `(empty output from ${toolName})` }],
302
+ isError: false
303
+ };
304
+ }
305
+ if (payload.ok === false) {
306
+ return {
307
+ content: [{ type: "text", text: String(payload.message ?? `Tool ${toolName} failed`) }],
308
+ structuredContent: payload,
309
+ isError: true
310
+ };
311
+ }
312
+ return {
313
+ content: [{ type: "text", text: renderToolText(toolName, payload) }],
314
+ structuredContent: payload,
315
+ isError: false
316
+ };
317
+ }
318
+ async function readBunProcessPipe(pipe) {
319
+ if (typeof pipe === "number" || !pipe) {
320
+ return "";
321
+ }
322
+ return new Response(pipe).text();
323
+ }
324
+ function resolveRuntimeToolBinary(toolName, env) {
325
+ const binDir = env.RIG_RUNTIME_BIN_DIR?.trim() || "";
326
+ if (!binDir) {
327
+ return "";
328
+ }
329
+ const mapping = {
330
+ read: "rig-read",
331
+ write: "rig-write",
332
+ edit: "rig-edit",
333
+ glob: "rig-glob",
334
+ grep: "rig-grep"
335
+ };
336
+ const executable = mapping[toolName];
337
+ return executable ? resolve(binDir, executable) : "";
338
+ }
339
+ function renderToolText(toolName, payload) {
340
+ if (toolName === "shell") {
341
+ const command = typeof payload.command === "string" ? payload.command : "(unknown command)";
342
+ const stdout = typeof payload.stdout === "string" ? payload.stdout.trim() : "";
343
+ const stderr = typeof payload.stderr === "string" ? payload.stderr.trim() : "";
344
+ const exitCode = typeof payload.exit_code === "number" ? payload.exit_code : null;
345
+ const output = [stdout, stderr].filter(Boolean).join(`
346
+ `);
347
+ const summary = exitCode === null ? command : `${command}
348
+
349
+ exit_code=${String(exitCode)}`;
350
+ return output ? `${summary}
351
+
352
+ ${output}` : summary;
353
+ }
354
+ if (toolName === "read") {
355
+ const path = typeof payload.path === "string" ? payload.path : "(unknown path)";
356
+ const content = typeof payload.content === "string" ? payload.content : "";
357
+ const truncated = payload.truncated === true ? `
358
+
359
+ [truncated]` : "";
360
+ return `${path}
361
+
362
+ ${content}${truncated}`;
363
+ }
364
+ if (toolName === "glob") {
365
+ const matches = Array.isArray(payload.matches) ? payload.matches.filter((value) => typeof value === "string") : [];
366
+ return matches.length > 0 ? matches.join(`
367
+ `) : "(no matches)";
368
+ }
369
+ if (toolName === "grep") {
370
+ const matches = Array.isArray(payload.matches) ? payload.matches.filter(isRecord) : [];
371
+ if (matches.length === 0) {
372
+ return "(no matches)";
373
+ }
374
+ return matches.map((match) => `${String(match.path ?? "(unknown)")}:${String(match.line_number ?? "?")}: ${String(match.line ?? "")}`).join(`
375
+ `);
376
+ }
377
+ if (toolName === "write") {
378
+ return `Wrote ${String(payload.bytes_written ?? 0)} bytes to ${String(payload.path ?? "(unknown path)")}.`;
379
+ }
380
+ if (toolName === "edit") {
381
+ return `Edited ${String(payload.path ?? "(unknown path)")}; replacements: ${String(payload.replacements ?? 0)}.`;
382
+ }
383
+ return JSON.stringify(payload, null, 2);
384
+ }
385
+ async function invokeRuntimeShellTool(args, options = {}) {
386
+ const command = typeof args.command === "string" ? args.command.trim() : "";
387
+ if (!command) {
388
+ return {
389
+ content: [{ type: "text", text: "Missing required shell `command` string." }],
390
+ isError: true
391
+ };
392
+ }
393
+ const invocationEnv = options.env ?? process.env;
394
+ const shellName = args.shell === "sh" ? "sh" : args.shell === "zsh" ? "zsh" : "bash";
395
+ const shellBinary = resolveRuntimeShellBinary(shellName, invocationEnv);
396
+ if (!shellBinary) {
397
+ return {
398
+ content: [{ type: "text", text: `Missing Rig runtime shell binary for ${shellName}.` }],
399
+ isError: true
400
+ };
401
+ }
402
+ const workspaceRoot = resolve(invocationEnv.RIG_TASK_WORKSPACE?.trim() || process.cwd());
403
+ const requestedWorkdir = typeof args.workdir === "string" ? args.workdir.trim() : "";
404
+ const workdir = requestedWorkdir ? resolveWithinWorkspace(workspaceRoot, requestedWorkdir) : workspaceRoot;
405
+ if (!existsSync(workdir)) {
406
+ return {
407
+ content: [{
408
+ type: "text",
409
+ text: `Shell workdir does not exist inside the task workspace: ${requestedWorkdir || "."}`
410
+ }],
411
+ isError: true
412
+ };
413
+ }
414
+ try {
415
+ if (!statSync(workdir).isDirectory()) {
416
+ return {
417
+ content: [{
418
+ type: "text",
419
+ text: `Shell workdir is not a directory inside the task workspace: ${requestedWorkdir || "."}`
420
+ }],
421
+ isError: true
422
+ };
423
+ }
424
+ } catch (error) {
425
+ return {
426
+ content: [{
427
+ type: "text",
428
+ text: error instanceof Error ? error.message : String(error)
429
+ }],
430
+ isError: true
431
+ };
432
+ }
433
+ let proc = null;
434
+ try {
435
+ proc = Bun.spawn([shellBinary, shellName === "bash" ? "-lc" : "-c", command], {
436
+ cwd: workdir,
437
+ env: invocationEnv,
438
+ stdout: "pipe",
439
+ stderr: "pipe"
440
+ });
441
+ } catch (error) {
442
+ return {
443
+ content: [{
444
+ type: "text",
445
+ text: error instanceof Error ? error.message : String(error)
446
+ }],
447
+ isError: true
448
+ };
449
+ }
450
+ const [exitCode, stdout, stderr] = await Promise.all([
451
+ proc.exited,
452
+ readBunProcessPipe(proc.stdout),
453
+ readBunProcessPipe(proc.stderr)
454
+ ]);
455
+ const payload = {
456
+ ok: exitCode === 0,
457
+ shell: shellName,
458
+ cwd: workdir,
459
+ command,
460
+ stdout,
461
+ stderr,
462
+ exit_code: exitCode
463
+ };
464
+ return {
465
+ content: [{ type: "text", text: renderToolText("shell", payload) }],
466
+ structuredContent: payload,
467
+ isError: exitCode !== 0
468
+ };
469
+ }
470
+ function resolveRuntimeShellBinary(shellName, env) {
471
+ const binDir = env.RIG_RUNTIME_BIN_DIR?.trim() || "";
472
+ return binDir ? resolve(binDir, shellName) : "";
473
+ }
474
+ function resolveWithinWorkspace(workspaceRoot, target) {
475
+ const resolvedTarget = resolve(workspaceRoot, normalizeWorkspaceRelativeTarget(target));
476
+ const normalizedWorkspace = workspaceRoot.endsWith("/") ? workspaceRoot : `${workspaceRoot}/`;
477
+ const normalizedTarget = resolvedTarget.endsWith("/") ? resolvedTarget : `${resolvedTarget}/`;
478
+ if (resolvedTarget === workspaceRoot || normalizedTarget.startsWith(normalizedWorkspace)) {
479
+ return resolvedTarget;
480
+ }
481
+ throw new Error(`Shell workdir must stay inside the task workspace: ${target}`);
482
+ }
483
+ function normalizeWorkspaceRelativeTarget(target) {
484
+ const trimmed = target.trim();
485
+ if (!trimmed) {
486
+ return ".";
487
+ }
488
+ if (trimmed === "$MONOREPO_ROOT" || trimmed === "$RIG_TASK_WORKSPACE") {
489
+ return ".";
490
+ }
491
+ if (trimmed.startsWith("$MONOREPO_ROOT/")) {
492
+ return trimmed.slice("$MONOREPO_ROOT/".length);
493
+ }
494
+ if (trimmed.startsWith("$RIG_TASK_WORKSPACE/")) {
495
+ return trimmed.slice("$RIG_TASK_WORKSPACE/".length);
496
+ }
497
+ if (trimmed === "repos/spliter-monorepo") {
498
+ return ".";
499
+ }
500
+ if (trimmed.startsWith("repos/spliter-monorepo/")) {
501
+ return trimmed.slice("repos/spliter-monorepo/".length);
502
+ }
503
+ return trimmed;
504
+ }
505
+ function isRecord(value) {
506
+ return typeof value === "object" && value !== null && !Array.isArray(value);
507
+ }
508
+ function writeMessage(payload) {
509
+ process.stdout.write(`${JSON.stringify(payload)}
510
+ `);
511
+ }
512
+ if (import.meta.main) {
513
+ await runClaudeToolRouterServer();
514
+ }
515
+ export {
516
+ writeClaudeRuntimeToolRouterConfig,
517
+ runClaudeToolRouterServer,
518
+ invokeRuntimeTool,
519
+ codexRuntimeToolCliArgs,
520
+ claudeRuntimeToolCliArgs,
521
+ CLAUDE_ROUTER_TOOL_DEFINITIONS,
522
+ CLAUDE_ROUTER_SERVER_NAME,
523
+ CLAUDE_DISABLED_FILE_TOOLS
524
+ };
@@ -0,0 +1,182 @@
1
+ // @bun
2
+ // packages/runtime/src/control-plane/runtime/tooling/file-tools.ts
3
+ import { chmodSync, copyFileSync, existsSync, mkdirSync, rmSync, symlinkSync } from "fs";
4
+ import { tmpdir } from "os";
5
+ import { basename, dirname, resolve } from "path";
6
+ var sharedNativeToolsOutputDir = resolve(tmpdir(), "rig-native");
7
+ var sharedNativeToolsOutputPath = resolve(sharedNativeToolsOutputDir, `rig-tools-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
8
+ function runtimeRigToolsFileName() {
9
+ return `rig-tools${process.platform === "win32" ? ".exe" : ""}`;
10
+ }
11
+ function runtimeFileToolNames() {
12
+ return [
13
+ "rig-read",
14
+ "rig-write",
15
+ "rig-edit",
16
+ "rig-glob",
17
+ "rig-grep"
18
+ ];
19
+ }
20
+ async function ensureRigToolsBinaryPath(outputPath = sharedNativeToolsOutputPath) {
21
+ const sourcePath = resolveRigToolsSourcePath();
22
+ if (!sourcePath) {
23
+ const bundledBinary = resolveBundledRigToolsBinaryPath();
24
+ if (bundledBinary) {
25
+ return bundledBinary;
26
+ }
27
+ throw new Error("rig-tools.zig source file not found.");
28
+ }
29
+ const zigBinary = Bun.which("zig");
30
+ if (!zigBinary) {
31
+ throw new Error("zig is required to build native Rig file tools.");
32
+ }
33
+ mkdirSync(dirname(outputPath), { recursive: true });
34
+ const sourceDigest = await sha256File(sourcePath);
35
+ const buildKey = JSON.stringify({
36
+ version: 1,
37
+ zigBinary,
38
+ platform: process.platform,
39
+ arch: process.arch,
40
+ sourcePath,
41
+ sourceDigest
42
+ });
43
+ const manifestPath = nativeBuildManifestPath(outputPath);
44
+ const needsBuild = !existsSync(outputPath) || !await hasMatchingNativeBuildManifest(manifestPath, buildKey);
45
+ if (!needsBuild) {
46
+ return outputPath;
47
+ }
48
+ const build = Bun.spawn([
49
+ zigBinary,
50
+ "build-exe",
51
+ sourcePath,
52
+ "-O",
53
+ "ReleaseFast",
54
+ `-femit-bin=${outputPath}`
55
+ ], {
56
+ cwd: dirname(sourcePath),
57
+ stdout: "pipe",
58
+ stderr: "pipe"
59
+ });
60
+ const [exitCode, stdout, stderr] = await Promise.all([
61
+ build.exited,
62
+ new Response(build.stdout).text(),
63
+ new Response(build.stderr).text()
64
+ ]);
65
+ if (exitCode !== 0 || !existsSync(outputPath)) {
66
+ const details = [stderr.trim(), stdout.trim()].filter(Boolean).join(`
67
+ `);
68
+ throw new Error(`Failed to build native Rig file tools: ${details || `zig exited with code ${exitCode}`}`);
69
+ }
70
+ await Bun.write(manifestPath, `${JSON.stringify({ version: 1, buildKey }, null, 2)}
71
+ `);
72
+ return outputPath;
73
+ }
74
+ async function materializeRuntimeFileTools(targetDir) {
75
+ const sourcePath = await ensureRigToolsBinaryPath();
76
+ const targetPath = resolve(targetDir, runtimeRigToolsFileName());
77
+ mkdirSync(targetDir, { recursive: true });
78
+ const sourceDigest = await sha256File(sourcePath);
79
+ const buildKey = JSON.stringify({
80
+ version: 1,
81
+ sourcePath,
82
+ sourceDigest
83
+ });
84
+ const needsCopy = !existsSync(targetPath) || !await hasMatchingNativeBuildManifest(nativeBuildManifestPath(targetPath), buildKey);
85
+ if (needsCopy) {
86
+ copyFileSync(sourcePath, targetPath);
87
+ chmodSync(targetPath, 493);
88
+ await Bun.write(nativeBuildManifestPath(targetPath), `${JSON.stringify({ version: 1, buildKey }, null, 2)}
89
+ `);
90
+ }
91
+ for (const tool of runtimeFileToolNames()) {
92
+ const toolPath = resolve(targetDir, tool);
93
+ if (existsSync(toolPath)) {
94
+ rmSync(toolPath, { force: true, recursive: true });
95
+ }
96
+ symlinkSync(targetPath, toolPath);
97
+ }
98
+ return targetPath;
99
+ }
100
+ function resolveRigToolsSourcePath() {
101
+ for (const candidate of rigToolsSourceCandidates()) {
102
+ if (candidate && existsSync(candidate)) {
103
+ return candidate;
104
+ }
105
+ }
106
+ return null;
107
+ }
108
+ function resolveBundledRigToolsBinaryPath() {
109
+ for (const candidate of rigToolsBinaryCandidates()) {
110
+ if (candidate && existsSync(candidate)) {
111
+ return candidate;
112
+ }
113
+ }
114
+ return null;
115
+ }
116
+ function rigToolsSourceCandidates() {
117
+ const execDir = process.execPath?.trim() ? dirname(process.execPath.trim()) : "";
118
+ const cwd = process.cwd()?.trim() || "";
119
+ const projectRoot = process.env.PROJECT_RIG_ROOT?.trim() || "";
120
+ const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim() || "";
121
+ return [...new Set([
122
+ process.env.RIG_NATIVE_TOOLS_SOURCE?.trim() || "",
123
+ cwd ? resolve(cwd, "packages/runtime/native/rig-tools.zig") : "",
124
+ projectRoot ? resolve(projectRoot, "packages/runtime/native/rig-tools.zig") : "",
125
+ hostProjectRoot ? resolve(hostProjectRoot, "packages/runtime/native/rig-tools.zig") : "",
126
+ execDir ? resolve(execDir, "..", "..", "packages/runtime/native/rig-tools.zig") : "",
127
+ execDir ? resolve(execDir, "..", "native", "rig-tools.zig") : "",
128
+ resolve(import.meta.dir, "../../../../native/rig-tools.zig")
129
+ ].filter(Boolean))];
130
+ }
131
+ function nativePackageBinaryCandidates(fromDir, fileName) {
132
+ const candidates = [];
133
+ let cursor = resolve(fromDir);
134
+ for (let index = 0;index < 8; index += 1) {
135
+ candidates.push(resolve(cursor, "native", `${process.platform}-${process.arch}`, fileName), resolve(cursor, "native", `${process.platform}-${process.arch}`, "bin", fileName), resolve(cursor, "native", fileName), resolve(cursor, "native", "bin", fileName));
136
+ const parent = dirname(cursor);
137
+ if (parent === cursor)
138
+ break;
139
+ cursor = parent;
140
+ }
141
+ return candidates;
142
+ }
143
+ function rigToolsBinaryCandidates() {
144
+ const execDir = process.execPath?.trim() ? dirname(process.execPath.trim()) : "";
145
+ const fileName = runtimeRigToolsFileName();
146
+ return [...new Set([
147
+ process.env.RIG_NATIVE_TOOLS_BIN?.trim() || "",
148
+ ...nativePackageBinaryCandidates(import.meta.dir, fileName),
149
+ execDir ? resolve(execDir, fileName) : "",
150
+ execDir ? resolve(execDir, "..", fileName) : "",
151
+ execDir ? resolve(execDir, "..", "bin", fileName) : ""
152
+ ].filter(Boolean))];
153
+ }
154
+ function runtimeFileToolBasename(path) {
155
+ return basename(path);
156
+ }
157
+ function nativeBuildManifestPath(outputPath) {
158
+ return `${outputPath}.build-manifest.json`;
159
+ }
160
+ async function hasMatchingNativeBuildManifest(manifestPath, buildKey) {
161
+ if (!existsSync(manifestPath)) {
162
+ return false;
163
+ }
164
+ try {
165
+ const manifest = await Bun.file(manifestPath).json();
166
+ return manifest.version === 1 && manifest.buildKey === buildKey;
167
+ } catch {
168
+ return false;
169
+ }
170
+ }
171
+ async function sha256File(path) {
172
+ const hasher = new Bun.CryptoHasher("sha256");
173
+ hasher.update(await Bun.file(path).arrayBuffer());
174
+ return hasher.digest("hex");
175
+ }
176
+ export {
177
+ runtimeRigToolsFileName,
178
+ runtimeFileToolNames,
179
+ runtimeFileToolBasename,
180
+ materializeRuntimeFileTools,
181
+ ensureRigToolsBinaryPath
182
+ };