@h-rig/runtime 0.0.6-alpha.22 → 0.0.6-alpha.24
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 +333 -23
- package/dist/src/control-plane/agent-wrapper.js +336 -23
- 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 -7
|
@@ -568,8 +568,8 @@ var init_backend_bwrap = __esm(() => {
|
|
|
568
568
|
|
|
569
569
|
// packages/runtime/src/control-plane/agent-wrapper.ts
|
|
570
570
|
import { createRequire } from "module";
|
|
571
|
-
import { resolve as
|
|
572
|
-
import { existsSync as
|
|
571
|
+
import { resolve as resolve36 } from "path";
|
|
572
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync20, writeFileSync as writeFileSync13 } from "fs";
|
|
573
573
|
|
|
574
574
|
// packages/runtime/src/control-plane/runtime/context.ts
|
|
575
575
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -5786,6 +5786,21 @@ var GITHUB_KNOWN_HOSTS = [
|
|
|
5786
5786
|
"github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="
|
|
5787
5787
|
].join(`
|
|
5788
5788
|
`);
|
|
5789
|
+
function resolveControlPlaneSourceRoot(projectRoot) {
|
|
5790
|
+
const candidates = [
|
|
5791
|
+
process.env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
|
|
5792
|
+
process.env.RIG_HOST_PROJECT_ROOT?.trim(),
|
|
5793
|
+
resolve25(import.meta.dir, "../../../../.."),
|
|
5794
|
+
projectRoot
|
|
5795
|
+
].filter((value) => Boolean(value));
|
|
5796
|
+
for (const candidate of candidates) {
|
|
5797
|
+
const root = resolve25(candidate);
|
|
5798
|
+
if (existsSync24(resolve25(root, "packages/runtime/src/control-plane/pi-sessiond/bin.ts"))) {
|
|
5799
|
+
return root;
|
|
5800
|
+
}
|
|
5801
|
+
}
|
|
5802
|
+
return "";
|
|
5803
|
+
}
|
|
5789
5804
|
async function runtimeEnv(projectRoot, runtime) {
|
|
5790
5805
|
const bunBinaryPath = resolveBunBinaryPath();
|
|
5791
5806
|
const bunDir = resolveBunInstallDir(bunBinaryPath);
|
|
@@ -5831,9 +5846,11 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
5831
5846
|
const runtimeRigGit = resolve25(runtime.binDir, runtimeRigGitFileName());
|
|
5832
5847
|
const preferredShell = existsSync24(runtimeBash) ? runtimeBash : "/bin/bash";
|
|
5833
5848
|
const nativeRuntimeLibraryPath = await materializeNativeRuntimeLibrary(runtime.binDir);
|
|
5849
|
+
const controlPlaneSourceRoot = resolveControlPlaneSourceRoot(projectRoot);
|
|
5834
5850
|
const env = {
|
|
5835
5851
|
PROJECT_RIG_ROOT: projectRoot,
|
|
5836
5852
|
RIG_HOST_PROJECT_ROOT: projectRoot,
|
|
5853
|
+
...controlPlaneSourceRoot ? { RIG_CONTROL_PLANE_SOURCE_ROOT: controlPlaneSourceRoot } : {},
|
|
5837
5854
|
HOME: runtime.homeDir,
|
|
5838
5855
|
TMPDIR: runtime.tmpDir,
|
|
5839
5856
|
XDG_CACHE_HOME: runtime.cacheDir,
|
|
@@ -9152,6 +9169,163 @@ function formatJsonRpcError(error) {
|
|
|
9152
9169
|
return parts.join(" ");
|
|
9153
9170
|
}
|
|
9154
9171
|
|
|
9172
|
+
// packages/runtime/src/control-plane/pi-sessiond/launcher.ts
|
|
9173
|
+
import { randomBytes } from "crypto";
|
|
9174
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync19, readFileSync as readFileSync16, rmSync as rmSync13 } from "fs";
|
|
9175
|
+
import { dirname as dirname14, resolve as resolve35 } from "path";
|
|
9176
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9177
|
+
|
|
9178
|
+
// packages/runtime/src/control-plane/pi-sessiond/client.ts
|
|
9179
|
+
class RigPiSessionDaemonClient {
|
|
9180
|
+
baseUrl;
|
|
9181
|
+
token;
|
|
9182
|
+
constructor(options) {
|
|
9183
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
9184
|
+
this.token = options.token;
|
|
9185
|
+
}
|
|
9186
|
+
static fromConnection(connection, token) {
|
|
9187
|
+
if (connection.mode === "http")
|
|
9188
|
+
return new RigPiSessionDaemonClient({ baseUrl: connection.baseUrl, token });
|
|
9189
|
+
throw new Error("Unix-socket Rig Pi daemon connections are not implemented in this build; use loopback HTTP.");
|
|
9190
|
+
}
|
|
9191
|
+
async request(method, path, body) {
|
|
9192
|
+
const response = await fetch(`${this.baseUrl}${path.startsWith("/") ? path : `/${path}`}`, {
|
|
9193
|
+
method,
|
|
9194
|
+
headers: {
|
|
9195
|
+
authorization: `Bearer ${this.token}`,
|
|
9196
|
+
...body === undefined ? {} : { "content-type": "application/json" }
|
|
9197
|
+
},
|
|
9198
|
+
body: body === undefined ? undefined : JSON.stringify(body)
|
|
9199
|
+
});
|
|
9200
|
+
const text = await response.text();
|
|
9201
|
+
const payload = text.trim() ? JSON.parse(text) : undefined;
|
|
9202
|
+
if (!response.ok) {
|
|
9203
|
+
const message = payload && typeof payload === "object" && !Array.isArray(payload) && typeof payload.error === "string" ? payload.error : text || response.statusText;
|
|
9204
|
+
throw new Error(`Rig Pi session daemon request failed (${response.status}): ${message}`);
|
|
9205
|
+
}
|
|
9206
|
+
return payload;
|
|
9207
|
+
}
|
|
9208
|
+
webSocketUrl(path) {
|
|
9209
|
+
const url = new URL(`${this.baseUrl}${path.startsWith("/") ? path : `/${path}`}`);
|
|
9210
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
9211
|
+
url.searchParams.set("token", this.token);
|
|
9212
|
+
return url.toString();
|
|
9213
|
+
}
|
|
9214
|
+
}
|
|
9215
|
+
|
|
9216
|
+
// packages/runtime/src/control-plane/pi-sessiond/launcher.ts
|
|
9217
|
+
var BUILD_CONFIG2 = {};
|
|
9218
|
+
var BAKED_RIG_SOURCE_ROOT = BUILD_CONFIG2.RIG_SOURCE_ROOT ?? "";
|
|
9219
|
+
async function ensureRigPiSessionDaemon(input) {
|
|
9220
|
+
const rootDir = resolve35(input.rootDir);
|
|
9221
|
+
mkdirSync19(rootDir, { recursive: true });
|
|
9222
|
+
const readyFile = resolve35(rootDir, "ready.json");
|
|
9223
|
+
const existing = readDaemonReadyFile(readyFile);
|
|
9224
|
+
const existingHandle = existing ? await tryReady(existing) : null;
|
|
9225
|
+
if (existingHandle)
|
|
9226
|
+
return existingHandle;
|
|
9227
|
+
try {
|
|
9228
|
+
rmSync13(readyFile, { force: true });
|
|
9229
|
+
} catch {}
|
|
9230
|
+
const token = randomBytes(32).toString("hex");
|
|
9231
|
+
const binPath = resolveRigPiSessionDaemonBinPath(input.env);
|
|
9232
|
+
const bunPath = input.env.RIG_BUN_PATH || process.execPath;
|
|
9233
|
+
const proc = Bun.spawn([bunPath, binPath], {
|
|
9234
|
+
cwd: rootDir,
|
|
9235
|
+
env: {
|
|
9236
|
+
...input.env,
|
|
9237
|
+
RIG_PI_SESSIOND_ROOT: rootDir,
|
|
9238
|
+
RIG_PI_SESSIOND_TOKEN: token,
|
|
9239
|
+
RIG_PI_SESSIOND_READY_FILE: readyFile,
|
|
9240
|
+
RIG_PI_SESSIOND_HOST: "127.0.0.1",
|
|
9241
|
+
RIG_PI_SESSIOND_PORT: "0",
|
|
9242
|
+
...input.version ? { RIG_VERSION: input.version } : {},
|
|
9243
|
+
...input.commit ? { RIG_GIT_COMMIT: input.commit } : {}
|
|
9244
|
+
},
|
|
9245
|
+
stdin: "ignore",
|
|
9246
|
+
stdout: "ignore",
|
|
9247
|
+
stderr: "inherit"
|
|
9248
|
+
});
|
|
9249
|
+
proc.unref();
|
|
9250
|
+
const deadline = Date.now() + (input.timeoutMs ?? 15000);
|
|
9251
|
+
while (Date.now() < deadline) {
|
|
9252
|
+
const ready = readDaemonReadyFile(readyFile);
|
|
9253
|
+
const handle = ready ? await tryReady(ready) : null;
|
|
9254
|
+
if (handle)
|
|
9255
|
+
return handle;
|
|
9256
|
+
await sleep(100);
|
|
9257
|
+
}
|
|
9258
|
+
throw new Error(`Rig Pi session daemon did not become ready at ${readyFile}`);
|
|
9259
|
+
}
|
|
9260
|
+
function privateMetadataForDaemon(input) {
|
|
9261
|
+
return { public: input.publicMetadata, daemonConnection: input.connection };
|
|
9262
|
+
}
|
|
9263
|
+
async function tryReady(ready) {
|
|
9264
|
+
const host = typeof ready.host === "string" ? ready.host : "127.0.0.1";
|
|
9265
|
+
const port = typeof ready.port === "number" ? ready.port : Number(ready.port);
|
|
9266
|
+
const token = typeof ready.token === "string" ? ready.token : "";
|
|
9267
|
+
if (!Number.isFinite(port) || port <= 0 || !token)
|
|
9268
|
+
return null;
|
|
9269
|
+
const baseUrl = `http://${host}:${port}`;
|
|
9270
|
+
const client = new RigPiSessionDaemonClient({ baseUrl, token });
|
|
9271
|
+
try {
|
|
9272
|
+
await client.request("GET", "/health");
|
|
9273
|
+
} catch {
|
|
9274
|
+
return null;
|
|
9275
|
+
}
|
|
9276
|
+
return {
|
|
9277
|
+
client,
|
|
9278
|
+
connection: { mode: "http", baseUrl, tokenRef: tokenRefFromReady(ready) },
|
|
9279
|
+
token,
|
|
9280
|
+
ready
|
|
9281
|
+
};
|
|
9282
|
+
}
|
|
9283
|
+
function tokenRefFromReady(ready) {
|
|
9284
|
+
const token = typeof ready.token === "string" ? ready.token : "";
|
|
9285
|
+
return token ? `inline:${token}` : "missing";
|
|
9286
|
+
}
|
|
9287
|
+
function resolveRigPiSessionDaemonBinPath(env) {
|
|
9288
|
+
const explicit = env.RIG_PI_SESSIOND_BIN?.trim();
|
|
9289
|
+
if (explicit)
|
|
9290
|
+
return explicit;
|
|
9291
|
+
const roots = [
|
|
9292
|
+
env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
|
|
9293
|
+
BAKED_RIG_SOURCE_ROOT.trim(),
|
|
9294
|
+
process.env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
|
|
9295
|
+
process.env.RIG_HOST_PROJECT_ROOT?.trim(),
|
|
9296
|
+
process.env.PROJECT_RIG_ROOT?.trim()
|
|
9297
|
+
].filter((value) => Boolean(value));
|
|
9298
|
+
for (const root of roots) {
|
|
9299
|
+
const candidate = resolve35(root, "packages/runtime/src/control-plane/pi-sessiond/bin.ts");
|
|
9300
|
+
if (existsSync33(candidate))
|
|
9301
|
+
return candidate;
|
|
9302
|
+
}
|
|
9303
|
+
const moduleCandidate = fileURLToPath2(new URL("./bin.ts", import.meta.url));
|
|
9304
|
+
if (existsSync33(moduleCandidate))
|
|
9305
|
+
return moduleCandidate;
|
|
9306
|
+
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.");
|
|
9307
|
+
}
|
|
9308
|
+
function readDaemonReadyFile(path) {
|
|
9309
|
+
if (!existsSync33(path))
|
|
9310
|
+
return null;
|
|
9311
|
+
try {
|
|
9312
|
+
const parsed = JSON.parse(readFileSync16(path, "utf8"));
|
|
9313
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
9314
|
+
} catch {
|
|
9315
|
+
return null;
|
|
9316
|
+
}
|
|
9317
|
+
}
|
|
9318
|
+
function sleep(ms) {
|
|
9319
|
+
return new Promise((resolveSleep) => setTimeout(resolveSleep, ms));
|
|
9320
|
+
}
|
|
9321
|
+
function resolveRigPiSessionDaemonRoot(stateDir) {
|
|
9322
|
+
const root = resolve35(stateDir, "pi-sessiond");
|
|
9323
|
+
mkdirSync19(dirname14(root), { recursive: true });
|
|
9324
|
+
if (!existsSync33(root))
|
|
9325
|
+
mkdirSync19(root, { recursive: true });
|
|
9326
|
+
return root;
|
|
9327
|
+
}
|
|
9328
|
+
|
|
9155
9329
|
// packages/runtime/src/control-plane/agent-wrapper.ts
|
|
9156
9330
|
var requireFromRuntime = createRequire(import.meta.url);
|
|
9157
9331
|
async function finalizeRuntimeSnapshot(snapshotSidecar, providerCommand, exitCode, context) {
|
|
@@ -9186,7 +9360,7 @@ async function startOptionalRuntimeSnapshotSidecar(runtime, startSidecar = start
|
|
|
9186
9360
|
}
|
|
9187
9361
|
}
|
|
9188
9362
|
async function runAgentWrapper(options = {}) {
|
|
9189
|
-
const projectRoot =
|
|
9363
|
+
const projectRoot = resolve36(options.projectRoot || process.env.PROJECT_RIG_ROOT || process.cwd());
|
|
9190
9364
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
9191
9365
|
const argv = options.argv || process.argv.slice(2);
|
|
9192
9366
|
if (argv.length === 0 || argv[0] === "--version" || argv[0] === "--help" || argv[0] === "help") {
|
|
@@ -9249,7 +9423,8 @@ async function runAgentWrapper(options = {}) {
|
|
|
9249
9423
|
return 1;
|
|
9250
9424
|
}
|
|
9251
9425
|
const providerArgs = buildProviderArgs(provider, runtime, argv);
|
|
9252
|
-
const
|
|
9426
|
+
const normalPiDaemonPath = provider === "pi" && process.env.RIG_PI_RPC_FALLBACK !== "1";
|
|
9427
|
+
const providerCommand = normalPiDaemonPath ? ["rig-pi-sessiond", ...providerArgs] : [providerBinary(provider), ...providerArgs];
|
|
9253
9428
|
emitWrapperEvent("provider.launch", {
|
|
9254
9429
|
provider,
|
|
9255
9430
|
runtimeId: runtime.id,
|
|
@@ -9261,11 +9436,11 @@ async function runAgentWrapper(options = {}) {
|
|
|
9261
9436
|
const bypassOuterRuntimeSandbox = shouldBypassProviderSandboxOnPlatform(provider, process.platform);
|
|
9262
9437
|
const runClaudeCompatUnsandboxed = provider === "claude-code" && bypassOuterRuntimeSandbox;
|
|
9263
9438
|
if (runClaudeCompatUnsandboxed && process.env.HOME?.trim()) {
|
|
9264
|
-
env.CLAUDE_HOME =
|
|
9439
|
+
env.CLAUDE_HOME = resolve36(process.env.HOME.trim(), ".claude");
|
|
9265
9440
|
env.RIG_CLAUDE_RUNTIME_HOME = runtime.claudeHomeDir;
|
|
9266
9441
|
}
|
|
9267
9442
|
if (provider === "pi") {
|
|
9268
|
-
env.PI_CODING_AGENT_DIR =
|
|
9443
|
+
env.PI_CODING_AGENT_DIR = resolve36(runtime.homeDir, ".pi", "agent");
|
|
9269
9444
|
env.PI_CODING_AGENT_SESSION_DIR = runtime.sessionDir;
|
|
9270
9445
|
}
|
|
9271
9446
|
env.RIG_RUNTIME_SANDBOX = "enforce";
|
|
@@ -9299,9 +9474,19 @@ async function runAgentWrapper(options = {}) {
|
|
|
9299
9474
|
},
|
|
9300
9475
|
command: providerCommand
|
|
9301
9476
|
})).command;
|
|
9302
|
-
if (provider === "pi" &&
|
|
9477
|
+
if (provider === "pi" && process.env.RIG_PI_RPC_FALLBACK !== "1") {
|
|
9303
9478
|
const prompt = await readProcessStdin();
|
|
9304
|
-
exitCode = await
|
|
9479
|
+
exitCode = await runPiSessionDaemonProvider({
|
|
9480
|
+
projectRoot,
|
|
9481
|
+
runtime,
|
|
9482
|
+
env,
|
|
9483
|
+
prompt,
|
|
9484
|
+
runId: process.env.RIG_SERVER_RUN_ID?.trim() || process.env.RIG_RUN_ID?.trim() || undefined,
|
|
9485
|
+
sessionName: process.env.RIG_SERVER_RUN_ID?.trim() ? `Rig ${process.env.RIG_SERVER_RUN_ID.trim()}` : `Rig ${runtime.taskId}`
|
|
9486
|
+
});
|
|
9487
|
+
} else if (provider === "pi" && isPiRpcArgs(providerArgs)) {
|
|
9488
|
+
const prompt = await readProcessStdin();
|
|
9489
|
+
exitCode = await runPiRpcProviderFallback({
|
|
9305
9490
|
command,
|
|
9306
9491
|
cwd: runtime.workspaceDir,
|
|
9307
9492
|
env,
|
|
@@ -9432,7 +9617,129 @@ function steeringMessageText(entry) {
|
|
|
9432
9617
|
function isPiRpcArgs(args) {
|
|
9433
9618
|
return cliOptionValue(args, "--mode") === "rpc";
|
|
9434
9619
|
}
|
|
9435
|
-
async function
|
|
9620
|
+
async function runPiSessionDaemonProvider(input) {
|
|
9621
|
+
const stdout = input.stdout ?? process.stdout;
|
|
9622
|
+
const stderr = input.stderr ?? process.stderr;
|
|
9623
|
+
const runId = input.runId ?? input.runtime.taskId;
|
|
9624
|
+
emitWrapperEvent("pi.sessiond.starting", {
|
|
9625
|
+
runId,
|
|
9626
|
+
runtimeId: input.runtime.id,
|
|
9627
|
+
workspaceDir: input.runtime.workspaceDir
|
|
9628
|
+
});
|
|
9629
|
+
const daemon = await ensureRigPiSessionDaemon({
|
|
9630
|
+
rootDir: resolveRigPiSessionDaemonRoot(input.runtime.stateDir),
|
|
9631
|
+
env: input.env,
|
|
9632
|
+
version: process.env.RIG_VERSION?.trim() || "dev",
|
|
9633
|
+
commit: process.env.RIG_GIT_COMMIT?.trim() || undefined
|
|
9634
|
+
});
|
|
9635
|
+
emitWrapperEvent("pi.sessiond.ready", {
|
|
9636
|
+
runId,
|
|
9637
|
+
runtimeId: input.runtime.id,
|
|
9638
|
+
connection: daemon.connection,
|
|
9639
|
+
ready: daemon.ready
|
|
9640
|
+
});
|
|
9641
|
+
const start = await daemon.client.request("POST", "/sessions", {
|
|
9642
|
+
runId,
|
|
9643
|
+
cwd: input.runtime.workspaceDir,
|
|
9644
|
+
agentDir: input.env.PI_CODING_AGENT_DIR || resolve36(input.runtime.homeDir, ".pi", "agent"),
|
|
9645
|
+
sessionDir: input.runtime.sessionDir,
|
|
9646
|
+
sessionName: input.sessionName
|
|
9647
|
+
});
|
|
9648
|
+
const privateMetadata = privateMetadataForDaemon({ publicMetadata: start.metadata, connection: daemon.connection });
|
|
9649
|
+
emitWrapperEvent("pi.session.ready", {
|
|
9650
|
+
runId,
|
|
9651
|
+
runtimeId: input.runtime.id,
|
|
9652
|
+
metadata: start.metadata,
|
|
9653
|
+
privateMetadata
|
|
9654
|
+
});
|
|
9655
|
+
const eventStream = waitForPiSessionEvents({
|
|
9656
|
+
url: daemon.client.webSocketUrl(`/sessions/${encodeURIComponent(start.metadata.sessionId)}/events`),
|
|
9657
|
+
stdout,
|
|
9658
|
+
stderr,
|
|
9659
|
+
runId
|
|
9660
|
+
});
|
|
9661
|
+
emitWrapperEvent("pi.session.event_stream.connected", { runId, sessionId: start.metadata.sessionId });
|
|
9662
|
+
const forwardSigterm = () => {
|
|
9663
|
+
daemon.client.request("POST", `/sessions/${encodeURIComponent(start.metadata.sessionId)}/abort`).catch(() => {
|
|
9664
|
+
return;
|
|
9665
|
+
});
|
|
9666
|
+
eventStream.close();
|
|
9667
|
+
};
|
|
9668
|
+
process.once("SIGTERM", forwardSigterm);
|
|
9669
|
+
try {
|
|
9670
|
+
if (input.prompt.trim()) {
|
|
9671
|
+
await daemon.client.request("POST", `/sessions/${encodeURIComponent(start.metadata.sessionId)}/prompt`, { text: input.prompt });
|
|
9672
|
+
emitWrapperEvent("pi.prompt.sent", { runId, sessionId: start.metadata.sessionId, bytes: Buffer.byteLength(input.prompt) });
|
|
9673
|
+
} else {
|
|
9674
|
+
emitWrapperEvent("pi.prompt.waiting", { runId, sessionId: start.metadata.sessionId, reason: "empty-initial-prompt" });
|
|
9675
|
+
}
|
|
9676
|
+
const result = await eventStream.done;
|
|
9677
|
+
if (result.error) {
|
|
9678
|
+
stderr.write(`[rig-agent] Pi session daemon stream failed: ${result.error}
|
|
9679
|
+
`);
|
|
9680
|
+
return 1;
|
|
9681
|
+
}
|
|
9682
|
+
return 0;
|
|
9683
|
+
} finally {
|
|
9684
|
+
process.off("SIGTERM", forwardSigterm);
|
|
9685
|
+
eventStream.close();
|
|
9686
|
+
}
|
|
9687
|
+
}
|
|
9688
|
+
function waitForPiSessionEvents(input) {
|
|
9689
|
+
let closed = false;
|
|
9690
|
+
let resolved = false;
|
|
9691
|
+
let socket = null;
|
|
9692
|
+
let resolveDone = () => {
|
|
9693
|
+
return;
|
|
9694
|
+
};
|
|
9695
|
+
const done = new Promise((resolveDoneInner) => {
|
|
9696
|
+
resolveDone = resolveDoneInner;
|
|
9697
|
+
});
|
|
9698
|
+
const finish = (value) => {
|
|
9699
|
+
if (resolved)
|
|
9700
|
+
return;
|
|
9701
|
+
resolved = true;
|
|
9702
|
+
resolveDone(value);
|
|
9703
|
+
};
|
|
9704
|
+
socket = new WebSocket(input.url);
|
|
9705
|
+
socket.addEventListener("message", (message) => {
|
|
9706
|
+
const text = typeof message.data === "string" ? message.data : Buffer.from(message.data).toString("utf8");
|
|
9707
|
+
input.stdout.write(`${text}
|
|
9708
|
+
`);
|
|
9709
|
+
const envelope = parseJsonRecord(text);
|
|
9710
|
+
if (!envelope)
|
|
9711
|
+
return;
|
|
9712
|
+
if (envelope.type === "pi.event") {
|
|
9713
|
+
const event = envelope.event && typeof envelope.event === "object" && !Array.isArray(envelope.event) ? envelope.event : null;
|
|
9714
|
+
if (event?.type === "agent_end") {
|
|
9715
|
+
emitWrapperEvent("pi.session.agent_end", { runId: input.runId, sessionId: envelope.sessionId });
|
|
9716
|
+
finish({});
|
|
9717
|
+
}
|
|
9718
|
+
}
|
|
9719
|
+
if (envelope.type === "error") {
|
|
9720
|
+
emitWrapperEvent("pi.session.error", { runId: input.runId, message: envelope.message, detail: envelope.detail ?? null });
|
|
9721
|
+
finish({ error: envelope.message });
|
|
9722
|
+
}
|
|
9723
|
+
});
|
|
9724
|
+
socket.addEventListener("error", () => {
|
|
9725
|
+
if (!closed)
|
|
9726
|
+
finish({ error: "WebSocket error" });
|
|
9727
|
+
});
|
|
9728
|
+
socket.addEventListener("close", () => {
|
|
9729
|
+
if (!closed && !resolved)
|
|
9730
|
+
finish({ error: "WebSocket closed before agent_end" });
|
|
9731
|
+
});
|
|
9732
|
+
return {
|
|
9733
|
+
done,
|
|
9734
|
+
close: () => {
|
|
9735
|
+
closed = true;
|
|
9736
|
+
try {
|
|
9737
|
+
socket?.close();
|
|
9738
|
+
} catch {}
|
|
9739
|
+
}
|
|
9740
|
+
};
|
|
9741
|
+
}
|
|
9742
|
+
async function runPiRpcProviderFallback(input) {
|
|
9436
9743
|
const stdout = input.stdout ?? process.stdout;
|
|
9437
9744
|
const stderr = input.stderr ?? process.stderr;
|
|
9438
9745
|
const proc = Bun.spawn(input.command, {
|
|
@@ -9499,7 +9806,7 @@ async function runPiRpcProvider(input) {
|
|
|
9499
9806
|
error: error instanceof Error ? error.message : String(error)
|
|
9500
9807
|
});
|
|
9501
9808
|
}
|
|
9502
|
-
await
|
|
9809
|
+
await sleep2(1000);
|
|
9503
9810
|
}
|
|
9504
9811
|
};
|
|
9505
9812
|
const stdoutPump = pumpReadableLines(proc.stdout, (line) => {
|
|
@@ -9564,6 +9871,7 @@ async function runPiRpcProvider(input) {
|
|
|
9564
9871
|
}
|
|
9565
9872
|
return exitCode;
|
|
9566
9873
|
}
|
|
9874
|
+
var runPiRpcProvider = runPiRpcProviderFallback;
|
|
9567
9875
|
function resolveFinalProviderExitCode(input) {
|
|
9568
9876
|
if (input.providerExitCode !== 0) {
|
|
9569
9877
|
return input.providerExitCode;
|
|
@@ -9595,6 +9903,9 @@ function buildProviderArgs(provider, runtime, argv) {
|
|
|
9595
9903
|
}
|
|
9596
9904
|
if (provider === "pi") {
|
|
9597
9905
|
const piArgs = [...argv];
|
|
9906
|
+
if (piArgs.includes("__rig_pi_session_daemon__")) {
|
|
9907
|
+
return piArgs.filter((arg) => arg !== "__rig_pi_session_daemon__");
|
|
9908
|
+
}
|
|
9598
9909
|
const piProvider = cliOptionValue(piArgs, "--provider") || process.env.RIG_PI_PROVIDER?.trim() || "openai-codex";
|
|
9599
9910
|
if (!hasCliOption(piArgs, "--provider")) {
|
|
9600
9911
|
piArgs.unshift(piProvider);
|
|
@@ -9725,8 +10036,8 @@ function resolveFromShellPath(binary) {
|
|
|
9725
10036
|
function resolveBundledPiBinary() {
|
|
9726
10037
|
try {
|
|
9727
10038
|
const packageJson = requireFromRuntime.resolve("@earendil-works/pi-coding-agent/package.json");
|
|
9728
|
-
const binaryPath =
|
|
9729
|
-
return
|
|
10039
|
+
const binaryPath = resolve36(packageJson, "..", "dist", "cli.js");
|
|
10040
|
+
return existsSync34(binaryPath) ? binaryPath : null;
|
|
9730
10041
|
} catch {
|
|
9731
10042
|
return null;
|
|
9732
10043
|
}
|
|
@@ -9747,7 +10058,7 @@ function providerBinary(provider) {
|
|
|
9747
10058
|
function emitWrapperEvent(type, payload) {
|
|
9748
10059
|
console.log(`__RIG_WRAPPER_EVENT__${JSON.stringify({ type, payload, at: new Date().toISOString() })}`);
|
|
9749
10060
|
}
|
|
9750
|
-
function
|
|
10061
|
+
function sleep2(ms) {
|
|
9751
10062
|
return new Promise((resolveSleep) => setTimeout(resolveSleep, ms));
|
|
9752
10063
|
}
|
|
9753
10064
|
async function waitForDirtyBaselineReady(runtime, taskId) {
|
|
@@ -9762,11 +10073,11 @@ async function waitForDirtyBaselineReady(runtime, taskId) {
|
|
|
9762
10073
|
workspaceDir: runtime.workspaceDir,
|
|
9763
10074
|
readyFile
|
|
9764
10075
|
});
|
|
9765
|
-
while (!
|
|
10076
|
+
while (!existsSync34(readyFile)) {
|
|
9766
10077
|
if (Date.now() >= deadline) {
|
|
9767
10078
|
throw new Error(`Timed out waiting for dirty baseline ready file: ${readyFile}`);
|
|
9768
10079
|
}
|
|
9769
|
-
await
|
|
10080
|
+
await sleep2(50);
|
|
9770
10081
|
}
|
|
9771
10082
|
emitWrapperEvent("runtime.baseline.completed", {
|
|
9772
10083
|
runtimeId: runtime.id,
|
|
@@ -9865,9 +10176,9 @@ async function updateTaskSourceAfterRun(projectRoot, taskId, runtime) {
|
|
|
9865
10176
|
}
|
|
9866
10177
|
}
|
|
9867
10178
|
function recordRuntimeHandoff(hostProjectRoot, runtime, taskId, exitCode) {
|
|
9868
|
-
const handoffDir =
|
|
9869
|
-
|
|
9870
|
-
const handoffPath =
|
|
10179
|
+
const handoffDir = resolve36(hostProjectRoot, ".rig/runtime/handoffs");
|
|
10180
|
+
mkdirSync20(handoffDir, { recursive: true });
|
|
10181
|
+
const handoffPath = resolve36(handoffDir, `${taskId}-${Date.now()}.json`);
|
|
9871
10182
|
const handoff = {
|
|
9872
10183
|
taskId,
|
|
9873
10184
|
runtimeId: runtime.id,
|
|
@@ -9933,13 +10244,13 @@ async function readTaskMetadata2(taskRoot, taskId) {
|
|
|
9933
10244
|
async function readTaskConfigHints(taskRoot, taskId) {
|
|
9934
10245
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
9935
10246
|
const candidates = [
|
|
9936
|
-
runtimeContext?.monorepoMainRoot ?
|
|
9937
|
-
process.env.MONOREPO_MAIN_ROOT?.trim() ?
|
|
9938
|
-
|
|
9939
|
-
|
|
10247
|
+
runtimeContext?.monorepoMainRoot ? resolve36(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
|
|
10248
|
+
process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve36(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
|
|
10249
|
+
resolve36(taskRoot, ".rig", "task-config.json"),
|
|
10250
|
+
resolve36(taskRoot, "rig", "task-config.json")
|
|
9940
10251
|
].filter(Boolean);
|
|
9941
10252
|
for (const configPath of candidates) {
|
|
9942
|
-
if (!
|
|
10253
|
+
if (!existsSync34(configPath)) {
|
|
9943
10254
|
continue;
|
|
9944
10255
|
}
|
|
9945
10256
|
try {
|
|
@@ -9976,6 +10287,8 @@ export {
|
|
|
9976
10287
|
updateTaskSourceAfterRun,
|
|
9977
10288
|
startOptionalRuntimeSnapshotSidecar,
|
|
9978
10289
|
shouldBypassProviderSandboxOnPlatform,
|
|
10290
|
+
runPiSessionDaemonProvider,
|
|
10291
|
+
runPiRpcProviderFallback,
|
|
9979
10292
|
runPiRpcProvider,
|
|
9980
10293
|
runAgentWrapper,
|
|
9981
10294
|
resolveTaskFromBeads,
|