@h-rig/runtime 0.0.6-alpha.21 → 0.0.6-alpha.23
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/dist/bin/rig-agent-dispatch.js +588 -28
- package/dist/src/control-plane/agent-wrapper.js +592 -28
- package/dist/src/control-plane/harness-main.js +142 -17
- package/dist/src/control-plane/hooks/completion-verification.js +142 -17
- package/dist/src/control-plane/native/harness-cli.js +142 -17
- package/dist/src/control-plane/native/pr-automation.js +142 -17
- package/dist/src/control-plane/native/pr-review-gate.js +142 -17
- package/dist/src/control-plane/native/run-ops.js +1 -1
- package/dist/src/control-plane/native/task-ops.js +142 -17
- package/dist/src/control-plane/native/verifier.js +142 -17
- package/dist/src/control-plane/pi-sessiond/bin.js +793 -0
- package/dist/src/control-plane/pi-sessiond/client.js +41 -0
- package/dist/src/control-plane/pi-sessiond/event-hub.js +59 -0
- package/dist/src/control-plane/pi-sessiond/extension-ui-context.js +198 -0
- package/dist/src/control-plane/pi-sessiond/launcher.js +163 -0
- package/dist/src/control-plane/pi-sessiond/server.js +802 -0
- package/dist/src/control-plane/pi-sessiond/session-service.js +540 -0
- package/dist/src/control-plane/pi-sessiond/types.js +1 -0
- package/dist/src/control-plane/runtime/index.js +17 -0
- package/dist/src/control-plane/runtime/isolation/home.js +17 -0
- package/dist/src/control-plane/runtime/isolation/index.js +17 -0
- package/dist/src/control-plane/runtime/isolation/runner.js +17 -0
- package/dist/src/control-plane/runtime/isolation.js +17 -0
- package/dist/src/control-plane/runtime/queue.js +17 -0
- package/package.json +7 -6
|
@@ -567,8 +567,9 @@ var init_backend_bwrap = __esm(() => {
|
|
|
567
567
|
});
|
|
568
568
|
|
|
569
569
|
// packages/runtime/src/control-plane/agent-wrapper.ts
|
|
570
|
-
import {
|
|
571
|
-
import {
|
|
570
|
+
import { createRequire } from "module";
|
|
571
|
+
import { resolve as resolve36 } from "path";
|
|
572
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync20, writeFileSync as writeFileSync13 } from "fs";
|
|
572
573
|
|
|
573
574
|
// packages/runtime/src/control-plane/runtime/context.ts
|
|
574
575
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -5517,6 +5518,21 @@ var GITHUB_KNOWN_HOSTS = [
|
|
|
5517
5518
|
"github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="
|
|
5518
5519
|
].join(`
|
|
5519
5520
|
`);
|
|
5521
|
+
function resolveControlPlaneSourceRoot(projectRoot) {
|
|
5522
|
+
const candidates = [
|
|
5523
|
+
process.env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
|
|
5524
|
+
process.env.RIG_HOST_PROJECT_ROOT?.trim(),
|
|
5525
|
+
resolve25(import.meta.dir, "../../../../.."),
|
|
5526
|
+
projectRoot
|
|
5527
|
+
].filter((value) => Boolean(value));
|
|
5528
|
+
for (const candidate of candidates) {
|
|
5529
|
+
const root = resolve25(candidate);
|
|
5530
|
+
if (existsSync24(resolve25(root, "packages/runtime/src/control-plane/pi-sessiond/bin.ts"))) {
|
|
5531
|
+
return root;
|
|
5532
|
+
}
|
|
5533
|
+
}
|
|
5534
|
+
return "";
|
|
5535
|
+
}
|
|
5520
5536
|
async function runtimeEnv(projectRoot, runtime) {
|
|
5521
5537
|
const bunBinaryPath = resolveBunBinaryPath();
|
|
5522
5538
|
const bunDir = resolveBunInstallDir(bunBinaryPath);
|
|
@@ -5562,9 +5578,11 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
5562
5578
|
const runtimeRigGit = resolve25(runtime.binDir, runtimeRigGitFileName());
|
|
5563
5579
|
const preferredShell = existsSync24(runtimeBash) ? runtimeBash : "/bin/bash";
|
|
5564
5580
|
const nativeRuntimeLibraryPath = await materializeNativeRuntimeLibrary(runtime.binDir);
|
|
5581
|
+
const controlPlaneSourceRoot = resolveControlPlaneSourceRoot(projectRoot);
|
|
5565
5582
|
const env = {
|
|
5566
5583
|
PROJECT_RIG_ROOT: projectRoot,
|
|
5567
5584
|
RIG_HOST_PROJECT_ROOT: projectRoot,
|
|
5585
|
+
...controlPlaneSourceRoot ? { RIG_CONTROL_PLANE_SOURCE_ROOT: controlPlaneSourceRoot } : {},
|
|
5568
5586
|
HOME: runtime.homeDir,
|
|
5569
5587
|
TMPDIR: runtime.tmpDir,
|
|
5570
5588
|
XDG_CACHE_HOME: runtime.cacheDir,
|
|
@@ -8883,7 +8901,165 @@ function formatJsonRpcError(error) {
|
|
|
8883
8901
|
return parts.join(" ");
|
|
8884
8902
|
}
|
|
8885
8903
|
|
|
8904
|
+
// packages/runtime/src/control-plane/pi-sessiond/launcher.ts
|
|
8905
|
+
import { randomBytes } from "crypto";
|
|
8906
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync19, readFileSync as readFileSync16, rmSync as rmSync13 } from "fs";
|
|
8907
|
+
import { dirname as dirname14, resolve as resolve35 } from "path";
|
|
8908
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8909
|
+
|
|
8910
|
+
// packages/runtime/src/control-plane/pi-sessiond/client.ts
|
|
8911
|
+
class RigPiSessionDaemonClient {
|
|
8912
|
+
baseUrl;
|
|
8913
|
+
token;
|
|
8914
|
+
constructor(options) {
|
|
8915
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
8916
|
+
this.token = options.token;
|
|
8917
|
+
}
|
|
8918
|
+
static fromConnection(connection, token) {
|
|
8919
|
+
if (connection.mode === "http")
|
|
8920
|
+
return new RigPiSessionDaemonClient({ baseUrl: connection.baseUrl, token });
|
|
8921
|
+
throw new Error("Unix-socket Rig Pi daemon connections are not implemented in this build; use loopback HTTP.");
|
|
8922
|
+
}
|
|
8923
|
+
async request(method, path, body) {
|
|
8924
|
+
const response = await fetch(`${this.baseUrl}${path.startsWith("/") ? path : `/${path}`}`, {
|
|
8925
|
+
method,
|
|
8926
|
+
headers: {
|
|
8927
|
+
authorization: `Bearer ${this.token}`,
|
|
8928
|
+
...body === undefined ? {} : { "content-type": "application/json" }
|
|
8929
|
+
},
|
|
8930
|
+
body: body === undefined ? undefined : JSON.stringify(body)
|
|
8931
|
+
});
|
|
8932
|
+
const text = await response.text();
|
|
8933
|
+
const payload = text.trim() ? JSON.parse(text) : undefined;
|
|
8934
|
+
if (!response.ok) {
|
|
8935
|
+
const message = payload && typeof payload === "object" && !Array.isArray(payload) && typeof payload.error === "string" ? payload.error : text || response.statusText;
|
|
8936
|
+
throw new Error(`Rig Pi session daemon request failed (${response.status}): ${message}`);
|
|
8937
|
+
}
|
|
8938
|
+
return payload;
|
|
8939
|
+
}
|
|
8940
|
+
webSocketUrl(path) {
|
|
8941
|
+
const url = new URL(`${this.baseUrl}${path.startsWith("/") ? path : `/${path}`}`);
|
|
8942
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
8943
|
+
url.searchParams.set("token", this.token);
|
|
8944
|
+
return url.toString();
|
|
8945
|
+
}
|
|
8946
|
+
}
|
|
8947
|
+
|
|
8948
|
+
// packages/runtime/src/control-plane/pi-sessiond/launcher.ts
|
|
8949
|
+
var BUILD_CONFIG2 = {};
|
|
8950
|
+
var BAKED_RIG_SOURCE_ROOT = BUILD_CONFIG2.RIG_SOURCE_ROOT ?? "";
|
|
8951
|
+
async function ensureRigPiSessionDaemon(input) {
|
|
8952
|
+
const rootDir = resolve35(input.rootDir);
|
|
8953
|
+
mkdirSync19(rootDir, { recursive: true });
|
|
8954
|
+
const readyFile = resolve35(rootDir, "ready.json");
|
|
8955
|
+
const existing = readDaemonReadyFile(readyFile);
|
|
8956
|
+
const existingHandle = existing ? await tryReady(existing) : null;
|
|
8957
|
+
if (existingHandle)
|
|
8958
|
+
return existingHandle;
|
|
8959
|
+
try {
|
|
8960
|
+
rmSync13(readyFile, { force: true });
|
|
8961
|
+
} catch {}
|
|
8962
|
+
const token = randomBytes(32).toString("hex");
|
|
8963
|
+
const binPath = resolveRigPiSessionDaemonBinPath(input.env);
|
|
8964
|
+
const bunPath = input.env.RIG_BUN_PATH || process.execPath;
|
|
8965
|
+
const proc = Bun.spawn([bunPath, binPath], {
|
|
8966
|
+
cwd: rootDir,
|
|
8967
|
+
env: {
|
|
8968
|
+
...input.env,
|
|
8969
|
+
RIG_PI_SESSIOND_ROOT: rootDir,
|
|
8970
|
+
RIG_PI_SESSIOND_TOKEN: token,
|
|
8971
|
+
RIG_PI_SESSIOND_READY_FILE: readyFile,
|
|
8972
|
+
RIG_PI_SESSIOND_HOST: "127.0.0.1",
|
|
8973
|
+
RIG_PI_SESSIOND_PORT: "0",
|
|
8974
|
+
...input.version ? { RIG_VERSION: input.version } : {},
|
|
8975
|
+
...input.commit ? { RIG_GIT_COMMIT: input.commit } : {}
|
|
8976
|
+
},
|
|
8977
|
+
stdin: "ignore",
|
|
8978
|
+
stdout: "ignore",
|
|
8979
|
+
stderr: "inherit"
|
|
8980
|
+
});
|
|
8981
|
+
proc.unref();
|
|
8982
|
+
const deadline = Date.now() + (input.timeoutMs ?? 15000);
|
|
8983
|
+
while (Date.now() < deadline) {
|
|
8984
|
+
const ready = readDaemonReadyFile(readyFile);
|
|
8985
|
+
const handle = ready ? await tryReady(ready) : null;
|
|
8986
|
+
if (handle)
|
|
8987
|
+
return handle;
|
|
8988
|
+
await sleep(100);
|
|
8989
|
+
}
|
|
8990
|
+
throw new Error(`Rig Pi session daemon did not become ready at ${readyFile}`);
|
|
8991
|
+
}
|
|
8992
|
+
function privateMetadataForDaemon(input) {
|
|
8993
|
+
return { public: input.publicMetadata, daemonConnection: input.connection };
|
|
8994
|
+
}
|
|
8995
|
+
async function tryReady(ready) {
|
|
8996
|
+
const host = typeof ready.host === "string" ? ready.host : "127.0.0.1";
|
|
8997
|
+
const port = typeof ready.port === "number" ? ready.port : Number(ready.port);
|
|
8998
|
+
const token = typeof ready.token === "string" ? ready.token : "";
|
|
8999
|
+
if (!Number.isFinite(port) || port <= 0 || !token)
|
|
9000
|
+
return null;
|
|
9001
|
+
const baseUrl = `http://${host}:${port}`;
|
|
9002
|
+
const client = new RigPiSessionDaemonClient({ baseUrl, token });
|
|
9003
|
+
try {
|
|
9004
|
+
await client.request("GET", "/health");
|
|
9005
|
+
} catch {
|
|
9006
|
+
return null;
|
|
9007
|
+
}
|
|
9008
|
+
return {
|
|
9009
|
+
client,
|
|
9010
|
+
connection: { mode: "http", baseUrl, tokenRef: tokenRefFromReady(ready) },
|
|
9011
|
+
token,
|
|
9012
|
+
ready
|
|
9013
|
+
};
|
|
9014
|
+
}
|
|
9015
|
+
function tokenRefFromReady(ready) {
|
|
9016
|
+
const token = typeof ready.token === "string" ? ready.token : "";
|
|
9017
|
+
return token ? `inline:${token}` : "missing";
|
|
9018
|
+
}
|
|
9019
|
+
function resolveRigPiSessionDaemonBinPath(env) {
|
|
9020
|
+
const explicit = env.RIG_PI_SESSIOND_BIN?.trim();
|
|
9021
|
+
if (explicit)
|
|
9022
|
+
return explicit;
|
|
9023
|
+
const roots = [
|
|
9024
|
+
env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
|
|
9025
|
+
BAKED_RIG_SOURCE_ROOT.trim(),
|
|
9026
|
+
process.env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
|
|
9027
|
+
process.env.RIG_HOST_PROJECT_ROOT?.trim(),
|
|
9028
|
+
process.env.PROJECT_RIG_ROOT?.trim()
|
|
9029
|
+
].filter((value) => Boolean(value));
|
|
9030
|
+
for (const root of roots) {
|
|
9031
|
+
const candidate = resolve35(root, "packages/runtime/src/control-plane/pi-sessiond/bin.ts");
|
|
9032
|
+
if (existsSync33(candidate))
|
|
9033
|
+
return candidate;
|
|
9034
|
+
}
|
|
9035
|
+
const moduleCandidate = fileURLToPath2(new URL("./bin.ts", import.meta.url));
|
|
9036
|
+
if (existsSync33(moduleCandidate))
|
|
9037
|
+
return moduleCandidate;
|
|
9038
|
+
throw new Error("Unable to locate rig-pi-sessiond entrypoint. Set RIG_PI_SESSIOND_BIN or RIG_CONTROL_PLANE_SOURCE_ROOT to the Rig source checkout.");
|
|
9039
|
+
}
|
|
9040
|
+
function readDaemonReadyFile(path) {
|
|
9041
|
+
if (!existsSync33(path))
|
|
9042
|
+
return null;
|
|
9043
|
+
try {
|
|
9044
|
+
const parsed = JSON.parse(readFileSync16(path, "utf8"));
|
|
9045
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
9046
|
+
} catch {
|
|
9047
|
+
return null;
|
|
9048
|
+
}
|
|
9049
|
+
}
|
|
9050
|
+
function sleep(ms) {
|
|
9051
|
+
return new Promise((resolveSleep) => setTimeout(resolveSleep, ms));
|
|
9052
|
+
}
|
|
9053
|
+
function resolveRigPiSessionDaemonRoot(stateDir) {
|
|
9054
|
+
const root = resolve35(stateDir, "pi-sessiond");
|
|
9055
|
+
mkdirSync19(dirname14(root), { recursive: true });
|
|
9056
|
+
if (!existsSync33(root))
|
|
9057
|
+
mkdirSync19(root, { recursive: true });
|
|
9058
|
+
return root;
|
|
9059
|
+
}
|
|
9060
|
+
|
|
8886
9061
|
// packages/runtime/src/control-plane/agent-wrapper.ts
|
|
9062
|
+
var requireFromRuntime = createRequire(import.meta.url);
|
|
8887
9063
|
async function finalizeRuntimeSnapshot(snapshotSidecar, providerCommand, exitCode, context) {
|
|
8888
9064
|
try {
|
|
8889
9065
|
await snapshotSidecar.finalize(providerCommand, exitCode);
|
|
@@ -8916,7 +9092,7 @@ async function startOptionalRuntimeSnapshotSidecar(runtime, startSidecar = start
|
|
|
8916
9092
|
}
|
|
8917
9093
|
}
|
|
8918
9094
|
async function runAgentWrapper(options = {}) {
|
|
8919
|
-
const projectRoot =
|
|
9095
|
+
const projectRoot = resolve36(options.projectRoot || process.env.PROJECT_RIG_ROOT || process.cwd());
|
|
8920
9096
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
8921
9097
|
const argv = options.argv || process.argv.slice(2);
|
|
8922
9098
|
if (argv.length === 0 || argv[0] === "--version" || argv[0] === "--help" || argv[0] === "help") {
|
|
@@ -8979,7 +9155,8 @@ async function runAgentWrapper(options = {}) {
|
|
|
8979
9155
|
return 1;
|
|
8980
9156
|
}
|
|
8981
9157
|
const providerArgs = buildProviderArgs(provider, runtime, argv);
|
|
8982
|
-
const
|
|
9158
|
+
const normalPiDaemonPath = provider === "pi" && process.env.RIG_PI_RPC_FALLBACK !== "1";
|
|
9159
|
+
const providerCommand = normalPiDaemonPath ? ["rig-pi-sessiond", ...providerArgs] : [providerBinary(provider), ...providerArgs];
|
|
8983
9160
|
emitWrapperEvent("provider.launch", {
|
|
8984
9161
|
provider,
|
|
8985
9162
|
runtimeId: runtime.id,
|
|
@@ -8991,11 +9168,11 @@ async function runAgentWrapper(options = {}) {
|
|
|
8991
9168
|
const bypassOuterRuntimeSandbox = shouldBypassProviderSandboxOnPlatform(provider, process.platform);
|
|
8992
9169
|
const runClaudeCompatUnsandboxed = provider === "claude-code" && bypassOuterRuntimeSandbox;
|
|
8993
9170
|
if (runClaudeCompatUnsandboxed && process.env.HOME?.trim()) {
|
|
8994
|
-
env.CLAUDE_HOME =
|
|
9171
|
+
env.CLAUDE_HOME = resolve36(process.env.HOME.trim(), ".claude");
|
|
8995
9172
|
env.RIG_CLAUDE_RUNTIME_HOME = runtime.claudeHomeDir;
|
|
8996
9173
|
}
|
|
8997
9174
|
if (provider === "pi") {
|
|
8998
|
-
env.PI_CODING_AGENT_DIR =
|
|
9175
|
+
env.PI_CODING_AGENT_DIR = resolve36(runtime.homeDir, ".pi", "agent");
|
|
8999
9176
|
env.PI_CODING_AGENT_SESSION_DIR = runtime.sessionDir;
|
|
9000
9177
|
}
|
|
9001
9178
|
env.RIG_RUNTIME_SANDBOX = "enforce";
|
|
@@ -9029,14 +9206,36 @@ async function runAgentWrapper(options = {}) {
|
|
|
9029
9206
|
},
|
|
9030
9207
|
command: providerCommand
|
|
9031
9208
|
})).command;
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9209
|
+
if (provider === "pi" && process.env.RIG_PI_RPC_FALLBACK !== "1") {
|
|
9210
|
+
const prompt = await readProcessStdin();
|
|
9211
|
+
exitCode = await runPiSessionDaemonProvider({
|
|
9212
|
+
projectRoot,
|
|
9213
|
+
runtime,
|
|
9214
|
+
env,
|
|
9215
|
+
prompt,
|
|
9216
|
+
runId: process.env.RIG_SERVER_RUN_ID?.trim() || process.env.RIG_RUN_ID?.trim() || undefined,
|
|
9217
|
+
sessionName: process.env.RIG_SERVER_RUN_ID?.trim() ? `Rig ${process.env.RIG_SERVER_RUN_ID.trim()}` : `Rig ${runtime.taskId}`
|
|
9218
|
+
});
|
|
9219
|
+
} else if (provider === "pi" && isPiRpcArgs(providerArgs)) {
|
|
9220
|
+
const prompt = await readProcessStdin();
|
|
9221
|
+
exitCode = await runPiRpcProviderFallback({
|
|
9222
|
+
command,
|
|
9223
|
+
cwd: runtime.workspaceDir,
|
|
9224
|
+
env,
|
|
9225
|
+
prompt,
|
|
9226
|
+
runId: process.env.RIG_SERVER_RUN_ID?.trim() || undefined,
|
|
9227
|
+
sessionName: process.env.RIG_SERVER_RUN_ID?.trim() ? `Rig ${process.env.RIG_SERVER_RUN_ID.trim()}` : `Rig ${runtime.taskId}`
|
|
9228
|
+
});
|
|
9229
|
+
} else {
|
|
9230
|
+
const proc = Bun.spawn(command, {
|
|
9231
|
+
cwd: runtime.workspaceDir,
|
|
9232
|
+
env,
|
|
9233
|
+
stdin: "inherit",
|
|
9234
|
+
stdout: "inherit",
|
|
9235
|
+
stderr: "inherit"
|
|
9236
|
+
});
|
|
9237
|
+
exitCode = await proc.exited;
|
|
9238
|
+
}
|
|
9040
9239
|
}
|
|
9041
9240
|
if (snapshotSidecar) {
|
|
9042
9241
|
await finalizeRuntimeSnapshot(snapshotSidecar, providerCommand, exitCode, {
|
|
@@ -9073,6 +9272,337 @@ async function runAgentWrapper(options = {}) {
|
|
|
9073
9272
|
}
|
|
9074
9273
|
return finalExitCode;
|
|
9075
9274
|
}
|
|
9275
|
+
function parseJsonRecord(line) {
|
|
9276
|
+
try {
|
|
9277
|
+
const parsed = JSON.parse(line);
|
|
9278
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
9279
|
+
} catch {
|
|
9280
|
+
return null;
|
|
9281
|
+
}
|
|
9282
|
+
}
|
|
9283
|
+
async function readProcessStdin() {
|
|
9284
|
+
if (process.stdin.isTTY)
|
|
9285
|
+
return "";
|
|
9286
|
+
return await new Promise((resolveRead) => {
|
|
9287
|
+
let data = "";
|
|
9288
|
+
process.stdin.setEncoding("utf8");
|
|
9289
|
+
process.stdin.on("data", (chunk) => {
|
|
9290
|
+
data += String(chunk);
|
|
9291
|
+
});
|
|
9292
|
+
process.stdin.on("end", () => resolveRead(data));
|
|
9293
|
+
process.stdin.resume();
|
|
9294
|
+
});
|
|
9295
|
+
}
|
|
9296
|
+
async function pumpReadableLines(stream, onLine) {
|
|
9297
|
+
if (!stream)
|
|
9298
|
+
return;
|
|
9299
|
+
const reader = stream.getReader();
|
|
9300
|
+
const decoder = new TextDecoder;
|
|
9301
|
+
let buffer = "";
|
|
9302
|
+
try {
|
|
9303
|
+
while (true) {
|
|
9304
|
+
const { done, value } = await reader.read();
|
|
9305
|
+
if (done)
|
|
9306
|
+
break;
|
|
9307
|
+
buffer += decoder.decode(value, { stream: true });
|
|
9308
|
+
const parts = buffer.split(/\r?\n/);
|
|
9309
|
+
buffer = parts.pop() ?? "";
|
|
9310
|
+
for (const part of parts)
|
|
9311
|
+
onLine(part);
|
|
9312
|
+
}
|
|
9313
|
+
buffer += decoder.decode();
|
|
9314
|
+
if (buffer)
|
|
9315
|
+
onLine(buffer);
|
|
9316
|
+
} finally {
|
|
9317
|
+
reader.releaseLock();
|
|
9318
|
+
}
|
|
9319
|
+
}
|
|
9320
|
+
function isBlockingPiRpcUiRequest(record) {
|
|
9321
|
+
if (record.type !== "extension_ui_request")
|
|
9322
|
+
return false;
|
|
9323
|
+
return record.method === "select" || record.method === "confirm" || record.method === "input" || record.method === "editor";
|
|
9324
|
+
}
|
|
9325
|
+
function writeRpcCommand(stdin, command) {
|
|
9326
|
+
stdin.write(`${JSON.stringify(command)}
|
|
9327
|
+
`);
|
|
9328
|
+
}
|
|
9329
|
+
function joinUrl(baseUrl, pathname) {
|
|
9330
|
+
return `${baseUrl.replace(/\/+$/, "")}${pathname.startsWith("/") ? pathname : `/${pathname}`}`;
|
|
9331
|
+
}
|
|
9332
|
+
async function readQueuedSteeringFromServer(input) {
|
|
9333
|
+
if (!input.serverUrl || !input.runId)
|
|
9334
|
+
return [];
|
|
9335
|
+
const headers = {};
|
|
9336
|
+
if (input.authToken)
|
|
9337
|
+
headers.authorization = `Bearer ${input.authToken}`;
|
|
9338
|
+
const response = await fetch(joinUrl(input.serverUrl, `/api/runs/${encodeURIComponent(input.runId)}/steering?ack=1`), { headers });
|
|
9339
|
+
if (!response.ok)
|
|
9340
|
+
return [];
|
|
9341
|
+
const payload = await response.json().catch(() => null);
|
|
9342
|
+
const messages = payload && typeof payload === "object" && !Array.isArray(payload) ? payload.messages : null;
|
|
9343
|
+
return Array.isArray(messages) ? messages.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))) : [];
|
|
9344
|
+
}
|
|
9345
|
+
function steeringMessageText(entry) {
|
|
9346
|
+
const message = typeof entry.message === "string" ? entry.message.trim() : "";
|
|
9347
|
+
return message || null;
|
|
9348
|
+
}
|
|
9349
|
+
function isPiRpcArgs(args) {
|
|
9350
|
+
return cliOptionValue(args, "--mode") === "rpc";
|
|
9351
|
+
}
|
|
9352
|
+
async function runPiSessionDaemonProvider(input) {
|
|
9353
|
+
const stdout = input.stdout ?? process.stdout;
|
|
9354
|
+
const stderr = input.stderr ?? process.stderr;
|
|
9355
|
+
const runId = input.runId ?? input.runtime.taskId;
|
|
9356
|
+
emitWrapperEvent("pi.sessiond.starting", {
|
|
9357
|
+
runId,
|
|
9358
|
+
runtimeId: input.runtime.id,
|
|
9359
|
+
workspaceDir: input.runtime.workspaceDir
|
|
9360
|
+
});
|
|
9361
|
+
const daemon = await ensureRigPiSessionDaemon({
|
|
9362
|
+
rootDir: resolveRigPiSessionDaemonRoot(input.runtime.stateDir),
|
|
9363
|
+
env: input.env,
|
|
9364
|
+
version: process.env.RIG_VERSION?.trim() || "dev",
|
|
9365
|
+
commit: process.env.RIG_GIT_COMMIT?.trim() || undefined
|
|
9366
|
+
});
|
|
9367
|
+
emitWrapperEvent("pi.sessiond.ready", {
|
|
9368
|
+
runId,
|
|
9369
|
+
runtimeId: input.runtime.id,
|
|
9370
|
+
connection: daemon.connection,
|
|
9371
|
+
ready: daemon.ready
|
|
9372
|
+
});
|
|
9373
|
+
const start = await daemon.client.request("POST", "/sessions", {
|
|
9374
|
+
runId,
|
|
9375
|
+
cwd: input.runtime.workspaceDir,
|
|
9376
|
+
agentDir: input.env.PI_CODING_AGENT_DIR || resolve36(input.runtime.homeDir, ".pi", "agent"),
|
|
9377
|
+
sessionDir: input.runtime.sessionDir,
|
|
9378
|
+
sessionName: input.sessionName
|
|
9379
|
+
});
|
|
9380
|
+
const privateMetadata = privateMetadataForDaemon({ publicMetadata: start.metadata, connection: daemon.connection });
|
|
9381
|
+
emitWrapperEvent("pi.session.ready", {
|
|
9382
|
+
runId,
|
|
9383
|
+
runtimeId: input.runtime.id,
|
|
9384
|
+
metadata: start.metadata,
|
|
9385
|
+
privateMetadata
|
|
9386
|
+
});
|
|
9387
|
+
const eventStream = waitForPiSessionEvents({
|
|
9388
|
+
url: daemon.client.webSocketUrl(`/sessions/${encodeURIComponent(start.metadata.sessionId)}/events`),
|
|
9389
|
+
stdout,
|
|
9390
|
+
stderr,
|
|
9391
|
+
runId
|
|
9392
|
+
});
|
|
9393
|
+
emitWrapperEvent("pi.session.event_stream.connected", { runId, sessionId: start.metadata.sessionId });
|
|
9394
|
+
const forwardSigterm = () => {
|
|
9395
|
+
daemon.client.request("POST", `/sessions/${encodeURIComponent(start.metadata.sessionId)}/abort`).catch(() => {
|
|
9396
|
+
return;
|
|
9397
|
+
});
|
|
9398
|
+
eventStream.close();
|
|
9399
|
+
};
|
|
9400
|
+
process.once("SIGTERM", forwardSigterm);
|
|
9401
|
+
try {
|
|
9402
|
+
if (input.prompt.trim()) {
|
|
9403
|
+
await daemon.client.request("POST", `/sessions/${encodeURIComponent(start.metadata.sessionId)}/prompt`, { text: input.prompt });
|
|
9404
|
+
emitWrapperEvent("pi.prompt.sent", { runId, sessionId: start.metadata.sessionId, bytes: Buffer.byteLength(input.prompt) });
|
|
9405
|
+
} else {
|
|
9406
|
+
emitWrapperEvent("pi.prompt.waiting", { runId, sessionId: start.metadata.sessionId, reason: "empty-initial-prompt" });
|
|
9407
|
+
}
|
|
9408
|
+
const result = await eventStream.done;
|
|
9409
|
+
if (result.error) {
|
|
9410
|
+
stderr.write(`[rig-agent] Pi session daemon stream failed: ${result.error}
|
|
9411
|
+
`);
|
|
9412
|
+
return 1;
|
|
9413
|
+
}
|
|
9414
|
+
return 0;
|
|
9415
|
+
} finally {
|
|
9416
|
+
process.off("SIGTERM", forwardSigterm);
|
|
9417
|
+
eventStream.close();
|
|
9418
|
+
}
|
|
9419
|
+
}
|
|
9420
|
+
function waitForPiSessionEvents(input) {
|
|
9421
|
+
let closed = false;
|
|
9422
|
+
let resolved = false;
|
|
9423
|
+
let socket = null;
|
|
9424
|
+
let resolveDone = () => {
|
|
9425
|
+
return;
|
|
9426
|
+
};
|
|
9427
|
+
const done = new Promise((resolveDoneInner) => {
|
|
9428
|
+
resolveDone = resolveDoneInner;
|
|
9429
|
+
});
|
|
9430
|
+
const finish = (value) => {
|
|
9431
|
+
if (resolved)
|
|
9432
|
+
return;
|
|
9433
|
+
resolved = true;
|
|
9434
|
+
resolveDone(value);
|
|
9435
|
+
};
|
|
9436
|
+
socket = new WebSocket(input.url);
|
|
9437
|
+
socket.addEventListener("message", (message) => {
|
|
9438
|
+
const text = typeof message.data === "string" ? message.data : Buffer.from(message.data).toString("utf8");
|
|
9439
|
+
input.stdout.write(`${text}
|
|
9440
|
+
`);
|
|
9441
|
+
const envelope = parseJsonRecord(text);
|
|
9442
|
+
if (!envelope)
|
|
9443
|
+
return;
|
|
9444
|
+
if (envelope.type === "pi.event") {
|
|
9445
|
+
const event = envelope.event && typeof envelope.event === "object" && !Array.isArray(envelope.event) ? envelope.event : null;
|
|
9446
|
+
if (event?.type === "agent_end") {
|
|
9447
|
+
emitWrapperEvent("pi.session.agent_end", { runId: input.runId, sessionId: envelope.sessionId });
|
|
9448
|
+
finish({});
|
|
9449
|
+
}
|
|
9450
|
+
}
|
|
9451
|
+
if (envelope.type === "error") {
|
|
9452
|
+
emitWrapperEvent("pi.session.error", { runId: input.runId, message: envelope.message, detail: envelope.detail ?? null });
|
|
9453
|
+
finish({ error: envelope.message });
|
|
9454
|
+
}
|
|
9455
|
+
});
|
|
9456
|
+
socket.addEventListener("error", () => {
|
|
9457
|
+
if (!closed)
|
|
9458
|
+
finish({ error: "WebSocket error" });
|
|
9459
|
+
});
|
|
9460
|
+
socket.addEventListener("close", () => {
|
|
9461
|
+
if (!closed && !resolved)
|
|
9462
|
+
finish({ error: "WebSocket closed before agent_end" });
|
|
9463
|
+
});
|
|
9464
|
+
return {
|
|
9465
|
+
done,
|
|
9466
|
+
close: () => {
|
|
9467
|
+
closed = true;
|
|
9468
|
+
try {
|
|
9469
|
+
socket?.close();
|
|
9470
|
+
} catch {}
|
|
9471
|
+
}
|
|
9472
|
+
};
|
|
9473
|
+
}
|
|
9474
|
+
async function runPiRpcProviderFallback(input) {
|
|
9475
|
+
const stdout = input.stdout ?? process.stdout;
|
|
9476
|
+
const stderr = input.stderr ?? process.stderr;
|
|
9477
|
+
const proc = Bun.spawn(input.command, {
|
|
9478
|
+
cwd: input.cwd,
|
|
9479
|
+
env: input.env,
|
|
9480
|
+
stdin: "pipe",
|
|
9481
|
+
stdout: "pipe",
|
|
9482
|
+
stderr: "pipe"
|
|
9483
|
+
});
|
|
9484
|
+
let sawAgentEnd = false;
|
|
9485
|
+
let promptError = null;
|
|
9486
|
+
let stdinOpen = true;
|
|
9487
|
+
let steeringPollStopped = false;
|
|
9488
|
+
const closeStdin = () => {
|
|
9489
|
+
if (!stdinOpen)
|
|
9490
|
+
return;
|
|
9491
|
+
stdinOpen = false;
|
|
9492
|
+
try {
|
|
9493
|
+
steeringPollStopped = true;
|
|
9494
|
+
proc.stdin.end();
|
|
9495
|
+
} catch {}
|
|
9496
|
+
};
|
|
9497
|
+
const send = (command) => {
|
|
9498
|
+
if (!stdinOpen)
|
|
9499
|
+
return;
|
|
9500
|
+
try {
|
|
9501
|
+
writeRpcCommand(proc.stdin, command);
|
|
9502
|
+
} catch (error) {
|
|
9503
|
+
promptError ??= error instanceof Error ? error.message : String(error);
|
|
9504
|
+
}
|
|
9505
|
+
};
|
|
9506
|
+
const forwardSigterm = () => {
|
|
9507
|
+
try {
|
|
9508
|
+
proc.kill("SIGTERM");
|
|
9509
|
+
} catch {}
|
|
9510
|
+
};
|
|
9511
|
+
process.once("SIGTERM", forwardSigterm);
|
|
9512
|
+
const pollSteering = async () => {
|
|
9513
|
+
const serverUrl = input.env.RIG_SERVER_URL || input.env.RIG_SERVER_BASE_URL;
|
|
9514
|
+
const authToken = input.env.RIG_AUTH_TOKEN || input.env.RIG_SERVER_AUTH_TOKEN;
|
|
9515
|
+
while (!steeringPollStopped && stdinOpen) {
|
|
9516
|
+
try {
|
|
9517
|
+
const messages = await readQueuedSteeringFromServer({ serverUrl, authToken, runId: input.runId });
|
|
9518
|
+
for (const message of messages) {
|
|
9519
|
+
const text = steeringMessageText(message);
|
|
9520
|
+
if (!text || !stdinOpen)
|
|
9521
|
+
continue;
|
|
9522
|
+
send({
|
|
9523
|
+
id: typeof message.id === "string" ? `rig_steer_${message.id}` : `rig_steer_${Date.now()}`,
|
|
9524
|
+
type: "prompt",
|
|
9525
|
+
message: text,
|
|
9526
|
+
streamingBehavior: "steer"
|
|
9527
|
+
});
|
|
9528
|
+
emitWrapperEvent("pi.rpc.steering.delivered", {
|
|
9529
|
+
runId: input.runId ?? null,
|
|
9530
|
+
steeringId: typeof message.id === "string" ? message.id : null,
|
|
9531
|
+
actor: typeof message.actor === "string" ? message.actor : "operator",
|
|
9532
|
+
message: text
|
|
9533
|
+
});
|
|
9534
|
+
}
|
|
9535
|
+
} catch (error) {
|
|
9536
|
+
emitWrapperEvent("pi.rpc.steering.poll.failed", {
|
|
9537
|
+
runId: input.runId ?? null,
|
|
9538
|
+
error: error instanceof Error ? error.message : String(error)
|
|
9539
|
+
});
|
|
9540
|
+
}
|
|
9541
|
+
await sleep2(1000);
|
|
9542
|
+
}
|
|
9543
|
+
};
|
|
9544
|
+
const stdoutPump = pumpReadableLines(proc.stdout, (line) => {
|
|
9545
|
+
stdout.write(`${line}
|
|
9546
|
+
`);
|
|
9547
|
+
const record = parseJsonRecord(line.trim());
|
|
9548
|
+
if (!record)
|
|
9549
|
+
return;
|
|
9550
|
+
if (record.type === "agent_end") {
|
|
9551
|
+
sawAgentEnd = true;
|
|
9552
|
+
closeStdin();
|
|
9553
|
+
return;
|
|
9554
|
+
}
|
|
9555
|
+
if (record.type === "response" && record.command === "prompt" && record.success === false) {
|
|
9556
|
+
promptError = typeof record.error === "string" ? record.error : "Pi RPC prompt failed.";
|
|
9557
|
+
closeStdin();
|
|
9558
|
+
return;
|
|
9559
|
+
}
|
|
9560
|
+
if (isBlockingPiRpcUiRequest(record)) {
|
|
9561
|
+
const id = typeof record.id === "string" ? record.id : "";
|
|
9562
|
+
if (id) {
|
|
9563
|
+
send({ type: "extension_ui_response", id, cancelled: true });
|
|
9564
|
+
emitWrapperEvent("pi.rpc.extension_ui.cancelled", {
|
|
9565
|
+
id,
|
|
9566
|
+
method: record.method,
|
|
9567
|
+
reason: "noninteractive Rig worker RPC session"
|
|
9568
|
+
});
|
|
9569
|
+
}
|
|
9570
|
+
}
|
|
9571
|
+
});
|
|
9572
|
+
const stderrPump = pumpReadableLines(proc.stderr, (line) => {
|
|
9573
|
+
stderr.write(`${line}
|
|
9574
|
+
`);
|
|
9575
|
+
});
|
|
9576
|
+
if (input.sessionName?.trim()) {
|
|
9577
|
+
send({ id: "rig_set_session_name", type: "set_session_name", name: input.sessionName.trim() });
|
|
9578
|
+
}
|
|
9579
|
+
const steeringPollPromise = pollSteering();
|
|
9580
|
+
if (input.prompt.trim()) {
|
|
9581
|
+
send({ id: "rig_initial_prompt", type: "prompt", message: input.prompt });
|
|
9582
|
+
emitWrapperEvent("pi.rpc.prompt.sent", {
|
|
9583
|
+
runId: input.runId ?? null,
|
|
9584
|
+
kind: "initial",
|
|
9585
|
+
bytes: Buffer.byteLength(input.prompt)
|
|
9586
|
+
});
|
|
9587
|
+
} else {
|
|
9588
|
+
closeStdin();
|
|
9589
|
+
}
|
|
9590
|
+
const exitCode = await proc.exited;
|
|
9591
|
+
process.off("SIGTERM", forwardSigterm);
|
|
9592
|
+
steeringPollStopped = true;
|
|
9593
|
+
await Promise.all([stdoutPump, stderrPump, steeringPollPromise]);
|
|
9594
|
+
if (promptError) {
|
|
9595
|
+
stderr.write(`[rig-agent] Pi RPC prompt failed: ${promptError}
|
|
9596
|
+
`);
|
|
9597
|
+
return exitCode === 0 ? 1 : exitCode;
|
|
9598
|
+
}
|
|
9599
|
+
if (input.prompt.trim() && !sawAgentEnd && exitCode === 0) {
|
|
9600
|
+
stderr.write(`[rig-agent] Pi RPC exited before emitting agent_end.
|
|
9601
|
+
`);
|
|
9602
|
+
return 1;
|
|
9603
|
+
}
|
|
9604
|
+
return exitCode;
|
|
9605
|
+
}
|
|
9076
9606
|
function resolveFinalProviderExitCode(input) {
|
|
9077
9607
|
if (input.providerExitCode !== 0) {
|
|
9078
9608
|
return input.providerExitCode;
|
|
@@ -9104,6 +9634,9 @@ function buildProviderArgs(provider, runtime, argv) {
|
|
|
9104
9634
|
}
|
|
9105
9635
|
if (provider === "pi") {
|
|
9106
9636
|
const piArgs = [...argv];
|
|
9637
|
+
if (piArgs.includes("__rig_pi_session_daemon__")) {
|
|
9638
|
+
return piArgs.filter((arg) => arg !== "__rig_pi_session_daemon__");
|
|
9639
|
+
}
|
|
9107
9640
|
const piProvider = cliOptionValue(piArgs, "--provider") || process.env.RIG_PI_PROVIDER?.trim() || "openai-codex";
|
|
9108
9641
|
if (!hasCliOption(piArgs, "--provider")) {
|
|
9109
9642
|
piArgs.unshift(piProvider);
|
|
@@ -9116,6 +9649,12 @@ function buildProviderArgs(provider, runtime, argv) {
|
|
|
9116
9649
|
piArgs.unshift(normalizePiModelForProvider(model, piProvider));
|
|
9117
9650
|
piArgs.unshift("--model");
|
|
9118
9651
|
}
|
|
9652
|
+
if (!hasCliOption(piArgs, "--mode")) {
|
|
9653
|
+
piArgs.push("--mode", process.env.RIG_PI_TRANSPORT?.trim() === "print" ? "json" : "rpc");
|
|
9654
|
+
if (process.env.RIG_PI_TRANSPORT?.trim() === "print" && !hasCliOption(piArgs, "--print")) {
|
|
9655
|
+
piArgs.push("--print");
|
|
9656
|
+
}
|
|
9657
|
+
}
|
|
9119
9658
|
return piArgs;
|
|
9120
9659
|
}
|
|
9121
9660
|
return [
|
|
@@ -9213,23 +9752,44 @@ function normalizePiModelForProvider(model, provider) {
|
|
|
9213
9752
|
}
|
|
9214
9753
|
return model;
|
|
9215
9754
|
}
|
|
9755
|
+
function resolveFromShellPath(binary) {
|
|
9756
|
+
const resolved = Bun.spawnSync(["sh", "-lc", `command -v ${binary}`], {
|
|
9757
|
+
stdout: "pipe",
|
|
9758
|
+
stderr: "ignore",
|
|
9759
|
+
stdin: "ignore",
|
|
9760
|
+
env: process.env
|
|
9761
|
+
});
|
|
9762
|
+
if (resolved.exitCode !== 0)
|
|
9763
|
+
return null;
|
|
9764
|
+
const path = resolved.stdout.toString().trim().split(/\r?\n/)[0]?.trim();
|
|
9765
|
+
return path || null;
|
|
9766
|
+
}
|
|
9767
|
+
function resolveBundledPiBinary() {
|
|
9768
|
+
try {
|
|
9769
|
+
const packageJson = requireFromRuntime.resolve("@earendil-works/pi-coding-agent/package.json");
|
|
9770
|
+
const binaryPath = resolve36(packageJson, "..", "dist", "cli.js");
|
|
9771
|
+
return existsSync34(binaryPath) ? binaryPath : null;
|
|
9772
|
+
} catch {
|
|
9773
|
+
return null;
|
|
9774
|
+
}
|
|
9775
|
+
}
|
|
9216
9776
|
function providerBinary(provider) {
|
|
9217
9777
|
if (provider === "codex") {
|
|
9218
|
-
return Bun.which("codex") || "codex";
|
|
9778
|
+
return resolveFromShellPath("codex") || Bun.which("codex") || "codex";
|
|
9219
9779
|
}
|
|
9220
9780
|
if (provider === "pi") {
|
|
9221
|
-
return Bun.which("pi") || "pi";
|
|
9781
|
+
return process.env.RIG_PI_BINARY?.trim() || resolveBundledPiBinary() || resolveFromShellPath("pi") || Bun.which("pi") || "pi";
|
|
9222
9782
|
}
|
|
9223
9783
|
try {
|
|
9224
9784
|
return resolveClaudeBinaryPath();
|
|
9225
9785
|
} catch {
|
|
9226
|
-
return Bun.which("claude") || "claude";
|
|
9786
|
+
return resolveFromShellPath("claude") || Bun.which("claude") || "claude";
|
|
9227
9787
|
}
|
|
9228
9788
|
}
|
|
9229
9789
|
function emitWrapperEvent(type, payload) {
|
|
9230
9790
|
console.log(`__RIG_WRAPPER_EVENT__${JSON.stringify({ type, payload, at: new Date().toISOString() })}`);
|
|
9231
9791
|
}
|
|
9232
|
-
function
|
|
9792
|
+
function sleep2(ms) {
|
|
9233
9793
|
return new Promise((resolveSleep) => setTimeout(resolveSleep, ms));
|
|
9234
9794
|
}
|
|
9235
9795
|
async function waitForDirtyBaselineReady(runtime, taskId) {
|
|
@@ -9244,11 +9804,11 @@ async function waitForDirtyBaselineReady(runtime, taskId) {
|
|
|
9244
9804
|
workspaceDir: runtime.workspaceDir,
|
|
9245
9805
|
readyFile
|
|
9246
9806
|
});
|
|
9247
|
-
while (!
|
|
9807
|
+
while (!existsSync34(readyFile)) {
|
|
9248
9808
|
if (Date.now() >= deadline) {
|
|
9249
9809
|
throw new Error(`Timed out waiting for dirty baseline ready file: ${readyFile}`);
|
|
9250
9810
|
}
|
|
9251
|
-
await
|
|
9811
|
+
await sleep2(50);
|
|
9252
9812
|
}
|
|
9253
9813
|
emitWrapperEvent("runtime.baseline.completed", {
|
|
9254
9814
|
runtimeId: runtime.id,
|
|
@@ -9312,9 +9872,9 @@ async function readPluginTaskStatus(projectRoot, taskId) {
|
|
|
9312
9872
|
}
|
|
9313
9873
|
}
|
|
9314
9874
|
function recordRuntimeHandoff(hostProjectRoot, runtime, taskId, exitCode) {
|
|
9315
|
-
const handoffDir =
|
|
9316
|
-
|
|
9317
|
-
const handoffPath =
|
|
9875
|
+
const handoffDir = resolve36(hostProjectRoot, ".rig/runtime/handoffs");
|
|
9876
|
+
mkdirSync20(handoffDir, { recursive: true });
|
|
9877
|
+
const handoffPath = resolve36(handoffDir, `${taskId}-${Date.now()}.json`);
|
|
9318
9878
|
const handoff = {
|
|
9319
9879
|
taskId,
|
|
9320
9880
|
runtimeId: runtime.id,
|
|
@@ -9380,13 +9940,13 @@ async function readTaskMetadata2(taskRoot, taskId) {
|
|
|
9380
9940
|
async function readTaskConfigHints(taskRoot, taskId) {
|
|
9381
9941
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
9382
9942
|
const candidates = [
|
|
9383
|
-
runtimeContext?.monorepoMainRoot ?
|
|
9384
|
-
process.env.MONOREPO_MAIN_ROOT?.trim() ?
|
|
9385
|
-
|
|
9386
|
-
|
|
9943
|
+
runtimeContext?.monorepoMainRoot ? resolve36(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
|
|
9944
|
+
process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve36(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
|
|
9945
|
+
resolve36(taskRoot, ".rig", "task-config.json"),
|
|
9946
|
+
resolve36(taskRoot, "rig", "task-config.json")
|
|
9387
9947
|
].filter(Boolean);
|
|
9388
9948
|
for (const configPath of candidates) {
|
|
9389
|
-
if (!
|
|
9949
|
+
if (!existsSync34(configPath)) {
|
|
9390
9950
|
continue;
|
|
9391
9951
|
}
|
|
9392
9952
|
try {
|