@h-rig/server 0.0.6-alpha.3 → 0.0.6-alpha.5
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/src/index.js
CHANGED
|
@@ -4383,11 +4383,23 @@ function assertNoActiveRunForTask(projectRoot, taskId, newRunId) {
|
|
|
4383
4383
|
return;
|
|
4384
4384
|
throw new Error(`Task ${taskId} already has an active Rig run: ${existing.runId}`);
|
|
4385
4385
|
}
|
|
4386
|
+
async function resolveSourceTaskForRun(projectRoot, taskId, readTasks) {
|
|
4387
|
+
const fromReader = (await readTasks(projectRoot)).find((task) => task.id === taskId) ?? null;
|
|
4388
|
+
if (fromReader)
|
|
4389
|
+
return fromReader;
|
|
4390
|
+
const projected = readTaskProjection(projectRoot)?.tasks.find((task) => String(task.id) === taskId) ?? null;
|
|
4391
|
+
if (projected)
|
|
4392
|
+
return projected;
|
|
4393
|
+
if (readTasks !== readWorkspaceTasks) {
|
|
4394
|
+
return (await readWorkspaceTasks(projectRoot)).find((task) => task.id === taskId) ?? null;
|
|
4395
|
+
}
|
|
4396
|
+
return null;
|
|
4397
|
+
}
|
|
4386
4398
|
async function createRunRecord(projectRoot, input, readTasks = readWorkspaceTasks) {
|
|
4387
4399
|
if ("taskId" in input && input.taskId) {
|
|
4388
4400
|
assertNoActiveRunForTask(projectRoot, input.taskId, input.runId);
|
|
4389
4401
|
}
|
|
4390
|
-
const sourceTask = "taskId" in input && input.taskId ?
|
|
4402
|
+
const sourceTask = "taskId" in input && input.taskId ? await resolveSourceTaskForRun(projectRoot, input.taskId, readTasks) : null;
|
|
4391
4403
|
const taskTitle = sourceTask?.title ?? ("taskId" in input && input.taskId ? input.taskId : null);
|
|
4392
4404
|
const runDir = resolveAuthorityRunDir3(projectRoot, input.runId);
|
|
4393
4405
|
const runRecord = {
|
|
@@ -4459,6 +4471,7 @@ async function startLocalRun(state, runId, options) {
|
|
|
4459
4471
|
throw new Error(`Run not found: ${runId}`);
|
|
4460
4472
|
}
|
|
4461
4473
|
const startedAt = new Date().toISOString();
|
|
4474
|
+
const resumeMode = options?.resume === true;
|
|
4462
4475
|
state.runProcesses.set(runId, {
|
|
4463
4476
|
runId,
|
|
4464
4477
|
child: null,
|
|
@@ -4475,9 +4488,9 @@ async function startLocalRun(state, runId, options) {
|
|
|
4475
4488
|
summary: run.title
|
|
4476
4489
|
});
|
|
4477
4490
|
appendRunLogEntry(state.projectRoot, runId, {
|
|
4478
|
-
id: `log:${runId}:prepare`,
|
|
4479
|
-
title: "Rig task run starting",
|
|
4480
|
-
detail: run.taskId ?? run.title,
|
|
4491
|
+
id: `log:${runId}:${resumeMode ? "resume" : "prepare"}`,
|
|
4492
|
+
title: resumeMode ? "Rig task run resuming" : "Rig task run starting",
|
|
4493
|
+
detail: resumeMode ? `Resuming ${run.taskId ?? run.title ?? runId} after server restart or operator resume.` : run.taskId ?? run.title,
|
|
4481
4494
|
tone: "info",
|
|
4482
4495
|
status: "preparing",
|
|
4483
4496
|
createdAt: startedAt
|
|
@@ -4559,6 +4572,10 @@ async function startLocalRun(state, runId, options) {
|
|
|
4559
4572
|
RIG_GITHUB_TOKEN: bridgeGitHubToken,
|
|
4560
4573
|
GITHUB_TOKEN: bridgeGitHubToken,
|
|
4561
4574
|
GH_TOKEN: bridgeGitHubToken
|
|
4575
|
+
} : {},
|
|
4576
|
+
...resumeMode ? {
|
|
4577
|
+
RIG_RUN_RESUME: "1",
|
|
4578
|
+
RIG_RUNTIME_ARTIFACT_CLEANUP: "preserve"
|
|
4562
4579
|
} : {}
|
|
4563
4580
|
},
|
|
4564
4581
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -4731,7 +4748,7 @@ async function resumeRunRecord(state, input) {
|
|
|
4731
4748
|
if (run.status === "completed") {
|
|
4732
4749
|
throw new Error("Completed runs cannot be resumed.");
|
|
4733
4750
|
}
|
|
4734
|
-
await startLocalRun(state, input.runId, { promptOverride: input.promptOverride ?? null });
|
|
4751
|
+
await startLocalRun(state, input.runId, { promptOverride: input.promptOverride ?? null, resume: input.restart !== true });
|
|
4735
4752
|
}
|
|
4736
4753
|
function appendRunMessage(projectRoot, input) {
|
|
4737
4754
|
const run = readAuthorityRun4(projectRoot, input.runId);
|
|
@@ -4815,34 +4832,12 @@ function removeTaskIdsFromQueueState(projectRoot, taskIds) {
|
|
|
4815
4832
|
writeQueueState(projectRoot, next);
|
|
4816
4833
|
return next;
|
|
4817
4834
|
}
|
|
4818
|
-
var
|
|
4819
|
-
function
|
|
4820
|
-
|
|
4821
|
-
for (const run of runs) {
|
|
4835
|
+
var RESUMABLE_LOCAL_RUN_STATUSES = new Set(["created", "preparing", "running", "validating", "reviewing"]);
|
|
4836
|
+
function collectResumableLocalRuns(state, runs) {
|
|
4837
|
+
return runs.filter((run) => {
|
|
4822
4838
|
const status = normalizeString(run.status)?.toLowerCase() ?? "";
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
if (run.mode !== "local" || !wasStartedByRigServer || !ORPHANABLE_LOCAL_RUN_STATUSES.has(status) || state.runProcesses.has(run.runId)) {
|
|
4826
|
-
continue;
|
|
4827
|
-
}
|
|
4828
|
-
const detail = "Recovered stale local run after Rig server restart; no live child process was attached to this server instance.";
|
|
4829
|
-
patchRunRecord(state.projectRoot, run.runId, {
|
|
4830
|
-
status: "failed",
|
|
4831
|
-
completedAt: run.completedAt ?? nowIso2,
|
|
4832
|
-
updatedAt: nowIso2,
|
|
4833
|
-
errorText: detail
|
|
4834
|
-
});
|
|
4835
|
-
appendRunLogEntry(state.projectRoot, run.runId, {
|
|
4836
|
-
id: `log:${run.runId}:stale-local-run`,
|
|
4837
|
-
title: "Run marked stale after server restart",
|
|
4838
|
-
detail,
|
|
4839
|
-
tone: "error",
|
|
4840
|
-
status: "failed",
|
|
4841
|
-
createdAt: nowIso2
|
|
4842
|
-
});
|
|
4843
|
-
changed = true;
|
|
4844
|
-
}
|
|
4845
|
-
return changed;
|
|
4839
|
+
return run.mode === "local" && RESUMABLE_LOCAL_RUN_STATUSES.has(status) && !state.runProcesses.has(run.runId);
|
|
4840
|
+
});
|
|
4846
4841
|
}
|
|
4847
4842
|
async function reconcileScheduler(state, reason) {
|
|
4848
4843
|
if (state.scheduler.reconciling) {
|
|
@@ -4857,7 +4852,20 @@ async function reconcileScheduler(state, reason) {
|
|
|
4857
4852
|
const queue = readQueueState(state.projectRoot);
|
|
4858
4853
|
const tasks = await state.snapshotService.getWorkspaceTasks();
|
|
4859
4854
|
let runs = listAuthorityRuns4(state.projectRoot);
|
|
4860
|
-
let changed =
|
|
4855
|
+
let changed = false;
|
|
4856
|
+
const resumableRuns = collectResumableLocalRuns(state, runs);
|
|
4857
|
+
for (const run of resumableRuns) {
|
|
4858
|
+
appendRunLogEntry(state.projectRoot, run.runId, {
|
|
4859
|
+
id: `log:${run.runId}:auto-resume:${Date.now()}`,
|
|
4860
|
+
title: "Run auto-resume scheduled",
|
|
4861
|
+
detail: `Rig server recovered nonterminal run ${run.runId} after ${reason}; resuming the same lifecycle instead of restarting it.`,
|
|
4862
|
+
tone: "info",
|
|
4863
|
+
status: "preparing",
|
|
4864
|
+
createdAt: new Date().toISOString()
|
|
4865
|
+
});
|
|
4866
|
+
await startLocalRun(state, run.runId, { resume: true });
|
|
4867
|
+
changed = true;
|
|
4868
|
+
}
|
|
4861
4869
|
if (changed) {
|
|
4862
4870
|
runs = listAuthorityRuns4(state.projectRoot);
|
|
4863
4871
|
}
|
|
@@ -7254,11 +7262,12 @@ data: ${JSON.stringify({ connectedAt: new Date().toISOString() })}
|
|
|
7254
7262
|
const runId = normalizeString(body.runId);
|
|
7255
7263
|
const createdAt = normalizeString(body.createdAt) ?? new Date().toISOString();
|
|
7256
7264
|
const promptOverride = normalizeString(body.promptOverride);
|
|
7265
|
+
const restart = body.restart === true;
|
|
7257
7266
|
if (!runId) {
|
|
7258
7267
|
return deps.badRequest("runId is required");
|
|
7259
7268
|
}
|
|
7260
7269
|
try {
|
|
7261
|
-
await deps.resumeRunRecord(state, { runId, createdAt, promptOverride });
|
|
7270
|
+
await deps.resumeRunRecord(state, { runId, createdAt, promptOverride, restart });
|
|
7262
7271
|
deps.broadcastSnapshotInvalidation(state);
|
|
7263
7272
|
return deps.jsonResponse({ ok: true, runId, createdAt });
|
|
7264
7273
|
} catch (error) {
|
|
@@ -1167,7 +1167,7 @@ var TERMINAL_RUN_STATUSES2 = new Set([
|
|
|
1167
1167
|
"needs-attention",
|
|
1168
1168
|
"stopped"
|
|
1169
1169
|
]);
|
|
1170
|
-
var
|
|
1170
|
+
var RESUMABLE_LOCAL_RUN_STATUSES = new Set(["created", "preparing", "running", "validating", "reviewing"]);
|
|
1171
1171
|
|
|
1172
1172
|
// packages/server/src/server-helpers/ws-router.ts
|
|
1173
1173
|
import {
|
|
@@ -3545,11 +3545,12 @@ data: ${JSON.stringify({ connectedAt: new Date().toISOString() })}
|
|
|
3545
3545
|
const runId = normalizeString(body.runId);
|
|
3546
3546
|
const createdAt = normalizeString(body.createdAt) ?? new Date().toISOString();
|
|
3547
3547
|
const promptOverride = normalizeString(body.promptOverride);
|
|
3548
|
+
const restart = body.restart === true;
|
|
3548
3549
|
if (!runId) {
|
|
3549
3550
|
return deps.badRequest("runId is required");
|
|
3550
3551
|
}
|
|
3551
3552
|
try {
|
|
3552
|
-
await deps.resumeRunRecord(state, { runId, createdAt, promptOverride });
|
|
3553
|
+
await deps.resumeRunRecord(state, { runId, createdAt, promptOverride, restart });
|
|
3553
3554
|
deps.broadcastSnapshotInvalidation(state);
|
|
3554
3555
|
return deps.jsonResponse({ ok: true, runId, createdAt });
|
|
3555
3556
|
} catch (error) {
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// packages/server/src/server-helpers/run-mutations.ts
|
|
3
3
|
import { spawn } from "child_process";
|
|
4
4
|
import { loadConfig } from "@rig/core/load-config";
|
|
5
|
-
import { existsSync as
|
|
6
|
-
import { dirname as dirname5, relative as relative2, resolve as
|
|
5
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync4, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
6
|
+
import { dirname as dirname5, relative as relative2, resolve as resolve10 } from "path";
|
|
7
7
|
import {
|
|
8
8
|
listAuthorityRuns as listAuthorityRuns7,
|
|
9
9
|
readAuthorityRun as readAuthorityRun8,
|
|
@@ -98,8 +98,8 @@ function normalizeStatus(value) {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
// packages/server/src/server.ts
|
|
101
|
-
import { existsSync as
|
|
102
|
-
import { dirname as dirname4, resolve as
|
|
101
|
+
import { existsSync as existsSync6, readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
102
|
+
import { dirname as dirname4, resolve as resolve8 } from "path";
|
|
103
103
|
import {
|
|
104
104
|
listAuthorityArtifactRoots,
|
|
105
105
|
listAuthorityRuns as listAuthorityRuns6,
|
|
@@ -295,6 +295,24 @@ var snapshotCache = new Map;
|
|
|
295
295
|
var contextCache = new Map;
|
|
296
296
|
var taskListCache = new Map;
|
|
297
297
|
|
|
298
|
+
// packages/server/src/server-helpers/task-projection.ts
|
|
299
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync, writeFileSync as writeFileSync3 } from "fs";
|
|
300
|
+
import { resolve as resolve5 } from "path";
|
|
301
|
+
function projectionPath(projectRoot) {
|
|
302
|
+
return resolve5(projectRoot, ".rig", "state", "task-projection.json");
|
|
303
|
+
}
|
|
304
|
+
function readTaskProjection(projectRoot) {
|
|
305
|
+
const file = projectionPath(projectRoot);
|
|
306
|
+
if (!existsSync3(file))
|
|
307
|
+
return null;
|
|
308
|
+
try {
|
|
309
|
+
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
310
|
+
return parsed && parsed.version === 1 && Array.isArray(parsed.tasks) ? parsed : null;
|
|
311
|
+
} catch {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
298
316
|
// packages/server/src/server-helpers/terminal-runtime.ts
|
|
299
317
|
import { WS_CHANNELS as WS_CHANNELS2 } from "@rig/contracts";
|
|
300
318
|
|
|
@@ -302,7 +320,7 @@ import { WS_CHANNELS as WS_CHANNELS2 } from "@rig/contracts";
|
|
|
302
320
|
import { RIG_WS_CHANNELS } from "@rig/contracts";
|
|
303
321
|
|
|
304
322
|
// packages/server/src/server-helpers/run-writers.ts
|
|
305
|
-
import { resolve as
|
|
323
|
+
import { resolve as resolve6 } from "path";
|
|
306
324
|
import {
|
|
307
325
|
appendJsonlRecord,
|
|
308
326
|
readAuthorityRun as readAuthorityRun3,
|
|
@@ -327,7 +345,7 @@ function patchRunRecord(projectRoot, runId, patch) {
|
|
|
327
345
|
...patch,
|
|
328
346
|
updatedAt: normalizeString(patch.updatedAt) ?? new Date().toISOString()
|
|
329
347
|
};
|
|
330
|
-
writeJsonFile2(
|
|
348
|
+
writeJsonFile2(resolve6(resolveAuthorityRunDir2(projectRoot, runId), "run.json"), next);
|
|
331
349
|
return next;
|
|
332
350
|
}
|
|
333
351
|
function buildRunStartPatch(startedAt) {
|
|
@@ -460,8 +478,8 @@ import {
|
|
|
460
478
|
|
|
461
479
|
// packages/server/src/server-helpers/github-auth-store.ts
|
|
462
480
|
import { randomBytes } from "crypto";
|
|
463
|
-
import { chmodSync, existsSync as
|
|
464
|
-
import { resolve as
|
|
481
|
+
import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
482
|
+
import { resolve as resolve7 } from "path";
|
|
465
483
|
function cleanString(value) {
|
|
466
484
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
467
485
|
}
|
|
@@ -492,10 +510,10 @@ function parseApiSessions(value) {
|
|
|
492
510
|
});
|
|
493
511
|
}
|
|
494
512
|
function readStoredAuth(stateFile) {
|
|
495
|
-
if (!
|
|
513
|
+
if (!existsSync4(stateFile))
|
|
496
514
|
return {};
|
|
497
515
|
try {
|
|
498
|
-
const parsed = JSON.parse(
|
|
516
|
+
const parsed = JSON.parse(readFileSync2(stateFile, "utf8"));
|
|
499
517
|
return {
|
|
500
518
|
...cleanString(parsed.token) ? { token: cleanString(parsed.token) } : {},
|
|
501
519
|
login: cleanString(parsed.login),
|
|
@@ -527,15 +545,15 @@ function newApiSessionToken() {
|
|
|
527
545
|
return `rig_${randomBytes(32).toString("base64url")}`;
|
|
528
546
|
}
|
|
529
547
|
function writeStoredAuth(stateFile, payload) {
|
|
530
|
-
|
|
531
|
-
|
|
548
|
+
mkdirSync4(resolve7(stateFile, ".."), { recursive: true });
|
|
549
|
+
writeFileSync4(stateFile, `${JSON.stringify(payload, null, 2)}
|
|
532
550
|
`, { encoding: "utf8", mode: 384 });
|
|
533
551
|
try {
|
|
534
552
|
chmodSync(stateFile, 384);
|
|
535
553
|
} catch {}
|
|
536
554
|
}
|
|
537
555
|
function resolveGitHubAuthStateFile(projectRoot) {
|
|
538
|
-
return
|
|
556
|
+
return resolve7(resolveServerAuthorityPaths(projectRoot).stateDir, "github-auth.json");
|
|
539
557
|
}
|
|
540
558
|
function createGitHubAuthStore(projectRoot) {
|
|
541
559
|
const stateFile = resolveGitHubAuthStateFile(projectRoot);
|
|
@@ -969,10 +987,10 @@ var CLUSTERS = {
|
|
|
969
987
|
};
|
|
970
988
|
|
|
971
989
|
// packages/server/src/server-helpers/task-config.ts
|
|
972
|
-
import { existsSync as
|
|
990
|
+
import { existsSync as existsSync5 } from "fs";
|
|
973
991
|
async function readTaskConfig(projectRoot) {
|
|
974
992
|
const taskConfigPath = resolveRigServerPaths(projectRoot).taskConfigPath;
|
|
975
|
-
if (!
|
|
993
|
+
if (!existsSync5(taskConfigPath)) {
|
|
976
994
|
return {};
|
|
977
995
|
}
|
|
978
996
|
try {
|
|
@@ -989,8 +1007,8 @@ var serverPathEnvQueue = Promise.resolve();
|
|
|
989
1007
|
async function withServerPathEnv(projectRoot, fn) {
|
|
990
1008
|
const waitForTurn = serverPathEnvQueue;
|
|
991
1009
|
let releaseTurn;
|
|
992
|
-
serverPathEnvQueue = new Promise((
|
|
993
|
-
releaseTurn =
|
|
1010
|
+
serverPathEnvQueue = new Promise((resolve9) => {
|
|
1011
|
+
releaseTurn = resolve9;
|
|
994
1012
|
});
|
|
995
1013
|
await waitForTurn;
|
|
996
1014
|
const paths = resolveServerAuthorityPaths(projectRoot);
|
|
@@ -1026,9 +1044,9 @@ async function withServerAuthorityEnvIfNeeded(projectRoot, fn) {
|
|
|
1026
1044
|
return withServerPathEnv(projectRoot, fn);
|
|
1027
1045
|
}
|
|
1028
1046
|
async function readWorkspaceTasks(projectRoot) {
|
|
1029
|
-
const issuesPath =
|
|
1047
|
+
const issuesPath = resolve8(resolveMonorepoRoot5(projectRoot), ".beads", "issues.jsonl");
|
|
1030
1048
|
const taskConfig = await readTaskConfig(projectRoot);
|
|
1031
|
-
if (!
|
|
1049
|
+
if (!existsSync6(issuesPath)) {
|
|
1032
1050
|
return [];
|
|
1033
1051
|
}
|
|
1034
1052
|
const latestById = new Map;
|
|
@@ -1074,7 +1092,7 @@ async function readWorkspaceTasks(projectRoot) {
|
|
|
1074
1092
|
if (false) {}
|
|
1075
1093
|
|
|
1076
1094
|
// packages/server/src/server-helpers/validation-failure.ts
|
|
1077
|
-
import { resolve as
|
|
1095
|
+
import { resolve as resolve9 } from "path";
|
|
1078
1096
|
import {
|
|
1079
1097
|
readJsonFile as readJsonFile4,
|
|
1080
1098
|
resolveTaskArtifactDirs
|
|
@@ -1088,7 +1106,7 @@ function summarizeRunValidationFailure(projectRoot, run) {
|
|
|
1088
1106
|
continue;
|
|
1089
1107
|
}
|
|
1090
1108
|
seen.add(artifactRoot);
|
|
1091
|
-
const summary = readJsonFile4(
|
|
1109
|
+
const summary = readJsonFile4(resolve9(artifactRoot, "validation-summary.json"), null);
|
|
1092
1110
|
if (!summary || summary.status !== "fail") {
|
|
1093
1111
|
continue;
|
|
1094
1112
|
}
|
|
@@ -1303,11 +1321,23 @@ function assertNoActiveRunForTask(projectRoot, taskId, newRunId) {
|
|
|
1303
1321
|
return;
|
|
1304
1322
|
throw new Error(`Task ${taskId} already has an active Rig run: ${existing.runId}`);
|
|
1305
1323
|
}
|
|
1324
|
+
async function resolveSourceTaskForRun(projectRoot, taskId, readTasks) {
|
|
1325
|
+
const fromReader = (await readTasks(projectRoot)).find((task) => task.id === taskId) ?? null;
|
|
1326
|
+
if (fromReader)
|
|
1327
|
+
return fromReader;
|
|
1328
|
+
const projected = readTaskProjection(projectRoot)?.tasks.find((task) => String(task.id) === taskId) ?? null;
|
|
1329
|
+
if (projected)
|
|
1330
|
+
return projected;
|
|
1331
|
+
if (readTasks !== readWorkspaceTasks) {
|
|
1332
|
+
return (await readWorkspaceTasks(projectRoot)).find((task) => task.id === taskId) ?? null;
|
|
1333
|
+
}
|
|
1334
|
+
return null;
|
|
1335
|
+
}
|
|
1306
1336
|
async function createRunRecord(projectRoot, input, readTasks = readWorkspaceTasks) {
|
|
1307
1337
|
if ("taskId" in input && input.taskId) {
|
|
1308
1338
|
assertNoActiveRunForTask(projectRoot, input.taskId, input.runId);
|
|
1309
1339
|
}
|
|
1310
|
-
const sourceTask = "taskId" in input && input.taskId ?
|
|
1340
|
+
const sourceTask = "taskId" in input && input.taskId ? await resolveSourceTaskForRun(projectRoot, input.taskId, readTasks) : null;
|
|
1311
1341
|
const taskTitle = sourceTask?.title ?? ("taskId" in input && input.taskId ? input.taskId : null);
|
|
1312
1342
|
const runDir = resolveAuthorityRunDir4(projectRoot, input.runId);
|
|
1313
1343
|
const runRecord = {
|
|
@@ -1341,11 +1371,11 @@ async function createRunRecord(projectRoot, input, readTasks = readWorkspaceTask
|
|
|
1341
1371
|
initiatedBy: input.initiatedBy ?? null,
|
|
1342
1372
|
...sourceTask ? { sourceTask: sourceTaskContract(sourceTask) } : {}
|
|
1343
1373
|
};
|
|
1344
|
-
|
|
1345
|
-
|
|
1374
|
+
mkdirSync6(runDir, { recursive: true });
|
|
1375
|
+
writeFileSync6(resolve10(runDir, "run.json"), `${JSON.stringify(runRecord, null, 2)}
|
|
1346
1376
|
`, "utf8");
|
|
1347
1377
|
if ("initialPrompt" in input && input.initialPrompt && input.initialPrompt.trim().length > 0) {
|
|
1348
|
-
|
|
1378
|
+
writeFileSync6(resolve10(runDir, "timeline.jsonl"), `${JSON.stringify({
|
|
1349
1379
|
id: `message-${Date.now()}`,
|
|
1350
1380
|
type: "user_message",
|
|
1351
1381
|
text: input.initialPrompt,
|
|
@@ -1379,6 +1409,7 @@ async function startLocalRun(state, runId, options) {
|
|
|
1379
1409
|
throw new Error(`Run not found: ${runId}`);
|
|
1380
1410
|
}
|
|
1381
1411
|
const startedAt = new Date().toISOString();
|
|
1412
|
+
const resumeMode = options?.resume === true;
|
|
1382
1413
|
state.runProcesses.set(runId, {
|
|
1383
1414
|
runId,
|
|
1384
1415
|
child: null,
|
|
@@ -1395,9 +1426,9 @@ async function startLocalRun(state, runId, options) {
|
|
|
1395
1426
|
summary: run.title
|
|
1396
1427
|
});
|
|
1397
1428
|
appendRunLogEntry(state.projectRoot, runId, {
|
|
1398
|
-
id: `log:${runId}:prepare`,
|
|
1399
|
-
title: "Rig task run starting",
|
|
1400
|
-
detail: run.taskId ?? run.title,
|
|
1429
|
+
id: `log:${runId}:${resumeMode ? "resume" : "prepare"}`,
|
|
1430
|
+
title: resumeMode ? "Rig task run resuming" : "Rig task run starting",
|
|
1431
|
+
detail: resumeMode ? `Resuming ${run.taskId ?? run.title ?? runId} after server restart or operator resume.` : run.taskId ?? run.title,
|
|
1401
1432
|
tone: "info",
|
|
1402
1433
|
status: "preparing",
|
|
1403
1434
|
createdAt: startedAt
|
|
@@ -1405,8 +1436,8 @@ async function startLocalRun(state, runId, options) {
|
|
|
1405
1436
|
broadcastRunLogAppended(state, runId, readLatestRawRunLog(state.projectRoot, runId));
|
|
1406
1437
|
broadcastSnapshotInvalidation(state);
|
|
1407
1438
|
const cliProjectRoot = resolveLocalRunCliProjectRoot(state.projectRoot);
|
|
1408
|
-
const cliEntryPoint =
|
|
1409
|
-
if (!
|
|
1439
|
+
const cliEntryPoint = resolve10(cliProjectRoot, "packages/cli/bin/rig.ts");
|
|
1440
|
+
if (!existsSync7(cliEntryPoint)) {
|
|
1410
1441
|
const completedAt = new Date().toISOString();
|
|
1411
1442
|
const failureSummary = `Rig task-run entrypoint missing at ${relative2(state.projectRoot, cliEntryPoint)}`;
|
|
1412
1443
|
patchRunRecord(state.projectRoot, runId, {
|
|
@@ -1479,6 +1510,10 @@ async function startLocalRun(state, runId, options) {
|
|
|
1479
1510
|
RIG_GITHUB_TOKEN: bridgeGitHubToken,
|
|
1480
1511
|
GITHUB_TOKEN: bridgeGitHubToken,
|
|
1481
1512
|
GH_TOKEN: bridgeGitHubToken
|
|
1513
|
+
} : {},
|
|
1514
|
+
...resumeMode ? {
|
|
1515
|
+
RIG_RUN_RESUME: "1",
|
|
1516
|
+
RIG_RUNTIME_ARTIFACT_CLEANUP: "preserve"
|
|
1482
1517
|
} : {}
|
|
1483
1518
|
},
|
|
1484
1519
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -1519,9 +1554,9 @@ async function startLocalRun(state, runId, options) {
|
|
|
1519
1554
|
handleRunProcessOutput(Buffer.isBuffer(data) ? data.toString("utf8") : String(data), "error", "Rig task run stderr");
|
|
1520
1555
|
});
|
|
1521
1556
|
try {
|
|
1522
|
-
const exit = await new Promise((
|
|
1523
|
-
child.once("error", (error) =>
|
|
1524
|
-
child.once("close", (code, signal) =>
|
|
1557
|
+
const exit = await new Promise((resolve11) => {
|
|
1558
|
+
child.once("error", (error) => resolve11({ code: 1, signal: null, error }));
|
|
1559
|
+
child.once("close", (code, signal) => resolve11({ code, signal }));
|
|
1525
1560
|
});
|
|
1526
1561
|
if (exit.error) {
|
|
1527
1562
|
throw new Error(`Failed to start task run: ${exit.error.message}`);
|
|
@@ -1621,17 +1656,17 @@ function resolveLocalRunCliProjectRoot(projectRoot) {
|
|
|
1621
1656
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
1622
1657
|
].filter((value) => !!value);
|
|
1623
1658
|
for (const candidate of envCandidates) {
|
|
1624
|
-
if (
|
|
1625
|
-
return
|
|
1659
|
+
if (existsSync7(resolve10(candidate, "packages/cli/bin/rig.ts"))) {
|
|
1660
|
+
return resolve10(candidate);
|
|
1626
1661
|
}
|
|
1627
1662
|
}
|
|
1628
|
-
if (
|
|
1663
|
+
if (existsSync7(resolve10(projectRoot, "packages/cli/bin/rig.ts"))) {
|
|
1629
1664
|
return projectRoot;
|
|
1630
1665
|
}
|
|
1631
1666
|
try {
|
|
1632
1667
|
const monorepoRoot = resolveMonorepoRoot6(projectRoot);
|
|
1633
1668
|
const outerProjectRoot = dirname5(dirname5(monorepoRoot));
|
|
1634
|
-
if (
|
|
1669
|
+
if (existsSync7(resolve10(outerProjectRoot, "packages/cli/bin/rig.ts"))) {
|
|
1635
1670
|
return outerProjectRoot;
|
|
1636
1671
|
}
|
|
1637
1672
|
} catch {}
|
|
@@ -1651,15 +1686,15 @@ async function resumeRunRecord(state, input) {
|
|
|
1651
1686
|
if (run.status === "completed") {
|
|
1652
1687
|
throw new Error("Completed runs cannot be resumed.");
|
|
1653
1688
|
}
|
|
1654
|
-
await startLocalRun(state, input.runId, { promptOverride: input.promptOverride ?? null });
|
|
1689
|
+
await startLocalRun(state, input.runId, { promptOverride: input.promptOverride ?? null, resume: input.restart !== true });
|
|
1655
1690
|
}
|
|
1656
1691
|
function appendRunMessage(projectRoot, input) {
|
|
1657
1692
|
const run = readAuthorityRun8(projectRoot, input.runId);
|
|
1658
1693
|
if (!run) {
|
|
1659
1694
|
throw new Error(`Run not found: ${input.runId}`);
|
|
1660
1695
|
}
|
|
1661
|
-
const timelinePath =
|
|
1662
|
-
const existingLines = fileExists(timelinePath) ?
|
|
1696
|
+
const timelinePath = resolve10(resolveAuthorityRunDir4(projectRoot, input.runId), "timeline.jsonl");
|
|
1697
|
+
const existingLines = fileExists(timelinePath) ? readFileSync4(timelinePath, "utf8").trim() : "";
|
|
1663
1698
|
const nextLine = JSON.stringify({
|
|
1664
1699
|
id: input.messageId,
|
|
1665
1700
|
type: "user_message",
|
|
@@ -1667,11 +1702,11 @@ function appendRunMessage(projectRoot, input) {
|
|
|
1667
1702
|
attachments: input.attachments ?? [],
|
|
1668
1703
|
createdAt: input.createdAt
|
|
1669
1704
|
});
|
|
1670
|
-
|
|
1705
|
+
writeFileSync6(timelinePath, existingLines.length > 0 ? `${existingLines}
|
|
1671
1706
|
${nextLine}
|
|
1672
1707
|
` : `${nextLine}
|
|
1673
1708
|
`, "utf8");
|
|
1674
|
-
writeJsonFile4(
|
|
1709
|
+
writeJsonFile4(resolve10(resolveAuthorityRunDir4(projectRoot, input.runId), "run.json"), {
|
|
1675
1710
|
...run,
|
|
1676
1711
|
updatedAt: input.createdAt
|
|
1677
1712
|
});
|
|
@@ -1697,7 +1732,7 @@ async function stopRunRecord(stateOrProjectRoot, input) {
|
|
|
1697
1732
|
completedAt: run.completedAt ?? input.createdAt,
|
|
1698
1733
|
updatedAt: input.createdAt
|
|
1699
1734
|
};
|
|
1700
|
-
writeJsonFile4(
|
|
1735
|
+
writeJsonFile4(resolve10(resolveAuthorityRunDir4(projectRoot, input.runId), "run.json"), nextRun);
|
|
1701
1736
|
if (run.status !== "completed" && run.taskId) {
|
|
1702
1737
|
const taskId = run.taskId;
|
|
1703
1738
|
(async () => {
|
|
@@ -1735,34 +1770,12 @@ function removeTaskIdsFromQueueState2(projectRoot, taskIds) {
|
|
|
1735
1770
|
writeQueueState(projectRoot, next);
|
|
1736
1771
|
return next;
|
|
1737
1772
|
}
|
|
1738
|
-
var
|
|
1739
|
-
function
|
|
1740
|
-
|
|
1741
|
-
for (const run of runs) {
|
|
1773
|
+
var RESUMABLE_LOCAL_RUN_STATUSES = new Set(["created", "preparing", "running", "validating", "reviewing"]);
|
|
1774
|
+
function collectResumableLocalRuns(state, runs) {
|
|
1775
|
+
return runs.filter((run) => {
|
|
1742
1776
|
const status = normalizeString(run.status)?.toLowerCase() ?? "";
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
if (run.mode !== "local" || !wasStartedByRigServer || !ORPHANABLE_LOCAL_RUN_STATUSES.has(status) || state.runProcesses.has(run.runId)) {
|
|
1746
|
-
continue;
|
|
1747
|
-
}
|
|
1748
|
-
const detail = "Recovered stale local run after Rig server restart; no live child process was attached to this server instance.";
|
|
1749
|
-
patchRunRecord(state.projectRoot, run.runId, {
|
|
1750
|
-
status: "failed",
|
|
1751
|
-
completedAt: run.completedAt ?? nowIso,
|
|
1752
|
-
updatedAt: nowIso,
|
|
1753
|
-
errorText: detail
|
|
1754
|
-
});
|
|
1755
|
-
appendRunLogEntry(state.projectRoot, run.runId, {
|
|
1756
|
-
id: `log:${run.runId}:stale-local-run`,
|
|
1757
|
-
title: "Run marked stale after server restart",
|
|
1758
|
-
detail,
|
|
1759
|
-
tone: "error",
|
|
1760
|
-
status: "failed",
|
|
1761
|
-
createdAt: nowIso
|
|
1762
|
-
});
|
|
1763
|
-
changed = true;
|
|
1764
|
-
}
|
|
1765
|
-
return changed;
|
|
1777
|
+
return run.mode === "local" && RESUMABLE_LOCAL_RUN_STATUSES.has(status) && !state.runProcesses.has(run.runId);
|
|
1778
|
+
});
|
|
1766
1779
|
}
|
|
1767
1780
|
async function reconcileScheduler(state, reason) {
|
|
1768
1781
|
if (state.scheduler.reconciling) {
|
|
@@ -1777,7 +1790,20 @@ async function reconcileScheduler(state, reason) {
|
|
|
1777
1790
|
const queue = readQueueState(state.projectRoot);
|
|
1778
1791
|
const tasks = await state.snapshotService.getWorkspaceTasks();
|
|
1779
1792
|
let runs = listAuthorityRuns7(state.projectRoot);
|
|
1780
|
-
let changed =
|
|
1793
|
+
let changed = false;
|
|
1794
|
+
const resumableRuns = collectResumableLocalRuns(state, runs);
|
|
1795
|
+
for (const run of resumableRuns) {
|
|
1796
|
+
appendRunLogEntry(state.projectRoot, run.runId, {
|
|
1797
|
+
id: `log:${run.runId}:auto-resume:${Date.now()}`,
|
|
1798
|
+
title: "Run auto-resume scheduled",
|
|
1799
|
+
detail: `Rig server recovered nonterminal run ${run.runId} after ${reason}; resuming the same lifecycle instead of restarting it.`,
|
|
1800
|
+
tone: "info",
|
|
1801
|
+
status: "preparing",
|
|
1802
|
+
createdAt: new Date().toISOString()
|
|
1803
|
+
});
|
|
1804
|
+
await startLocalRun(state, run.runId, { resume: true });
|
|
1805
|
+
changed = true;
|
|
1806
|
+
}
|
|
1781
1807
|
if (changed) {
|
|
1782
1808
|
runs = listAuthorityRuns7(state.projectRoot);
|
|
1783
1809
|
}
|
|
@@ -403,7 +403,7 @@ var TERMINAL_RUN_STATUSES2 = new Set([
|
|
|
403
403
|
"needs-attention",
|
|
404
404
|
"stopped"
|
|
405
405
|
]);
|
|
406
|
-
var
|
|
406
|
+
var RESUMABLE_LOCAL_RUN_STATUSES = new Set(["created", "preparing", "running", "validating", "reviewing"]);
|
|
407
407
|
|
|
408
408
|
// packages/server/src/server-helpers/http-router.ts
|
|
409
409
|
import {
|
package/dist/src/server.js
CHANGED
|
@@ -3876,11 +3876,23 @@ function assertNoActiveRunForTask(projectRoot, taskId, newRunId) {
|
|
|
3876
3876
|
return;
|
|
3877
3877
|
throw new Error(`Task ${taskId} already has an active Rig run: ${existing.runId}`);
|
|
3878
3878
|
}
|
|
3879
|
+
async function resolveSourceTaskForRun(projectRoot, taskId, readTasks) {
|
|
3880
|
+
const fromReader = (await readTasks(projectRoot)).find((task) => task.id === taskId) ?? null;
|
|
3881
|
+
if (fromReader)
|
|
3882
|
+
return fromReader;
|
|
3883
|
+
const projected = readTaskProjection(projectRoot)?.tasks.find((task) => String(task.id) === taskId) ?? null;
|
|
3884
|
+
if (projected)
|
|
3885
|
+
return projected;
|
|
3886
|
+
if (readTasks !== readWorkspaceTasks) {
|
|
3887
|
+
return (await readWorkspaceTasks(projectRoot)).find((task) => task.id === taskId) ?? null;
|
|
3888
|
+
}
|
|
3889
|
+
return null;
|
|
3890
|
+
}
|
|
3879
3891
|
async function createRunRecord(projectRoot, input, readTasks = readWorkspaceTasks) {
|
|
3880
3892
|
if ("taskId" in input && input.taskId) {
|
|
3881
3893
|
assertNoActiveRunForTask(projectRoot, input.taskId, input.runId);
|
|
3882
3894
|
}
|
|
3883
|
-
const sourceTask = "taskId" in input && input.taskId ?
|
|
3895
|
+
const sourceTask = "taskId" in input && input.taskId ? await resolveSourceTaskForRun(projectRoot, input.taskId, readTasks) : null;
|
|
3884
3896
|
const taskTitle = sourceTask?.title ?? ("taskId" in input && input.taskId ? input.taskId : null);
|
|
3885
3897
|
const runDir = resolveAuthorityRunDir3(projectRoot, input.runId);
|
|
3886
3898
|
const runRecord = {
|
|
@@ -3952,6 +3964,7 @@ async function startLocalRun(state, runId, options) {
|
|
|
3952
3964
|
throw new Error(`Run not found: ${runId}`);
|
|
3953
3965
|
}
|
|
3954
3966
|
const startedAt = new Date().toISOString();
|
|
3967
|
+
const resumeMode = options?.resume === true;
|
|
3955
3968
|
state.runProcesses.set(runId, {
|
|
3956
3969
|
runId,
|
|
3957
3970
|
child: null,
|
|
@@ -3968,9 +3981,9 @@ async function startLocalRun(state, runId, options) {
|
|
|
3968
3981
|
summary: run.title
|
|
3969
3982
|
});
|
|
3970
3983
|
appendRunLogEntry(state.projectRoot, runId, {
|
|
3971
|
-
id: `log:${runId}:prepare`,
|
|
3972
|
-
title: "Rig task run starting",
|
|
3973
|
-
detail: run.taskId ?? run.title,
|
|
3984
|
+
id: `log:${runId}:${resumeMode ? "resume" : "prepare"}`,
|
|
3985
|
+
title: resumeMode ? "Rig task run resuming" : "Rig task run starting",
|
|
3986
|
+
detail: resumeMode ? `Resuming ${run.taskId ?? run.title ?? runId} after server restart or operator resume.` : run.taskId ?? run.title,
|
|
3974
3987
|
tone: "info",
|
|
3975
3988
|
status: "preparing",
|
|
3976
3989
|
createdAt: startedAt
|
|
@@ -4052,6 +4065,10 @@ async function startLocalRun(state, runId, options) {
|
|
|
4052
4065
|
RIG_GITHUB_TOKEN: bridgeGitHubToken,
|
|
4053
4066
|
GITHUB_TOKEN: bridgeGitHubToken,
|
|
4054
4067
|
GH_TOKEN: bridgeGitHubToken
|
|
4068
|
+
} : {},
|
|
4069
|
+
...resumeMode ? {
|
|
4070
|
+
RIG_RUN_RESUME: "1",
|
|
4071
|
+
RIG_RUNTIME_ARTIFACT_CLEANUP: "preserve"
|
|
4055
4072
|
} : {}
|
|
4056
4073
|
},
|
|
4057
4074
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -4224,7 +4241,7 @@ async function resumeRunRecord(state, input) {
|
|
|
4224
4241
|
if (run.status === "completed") {
|
|
4225
4242
|
throw new Error("Completed runs cannot be resumed.");
|
|
4226
4243
|
}
|
|
4227
|
-
await startLocalRun(state, input.runId, { promptOverride: input.promptOverride ?? null });
|
|
4244
|
+
await startLocalRun(state, input.runId, { promptOverride: input.promptOverride ?? null, resume: input.restart !== true });
|
|
4228
4245
|
}
|
|
4229
4246
|
function appendRunMessage(projectRoot, input) {
|
|
4230
4247
|
const run = readAuthorityRun4(projectRoot, input.runId);
|
|
@@ -4308,34 +4325,12 @@ function removeTaskIdsFromQueueState(projectRoot, taskIds) {
|
|
|
4308
4325
|
writeQueueState(projectRoot, next);
|
|
4309
4326
|
return next;
|
|
4310
4327
|
}
|
|
4311
|
-
var
|
|
4312
|
-
function
|
|
4313
|
-
|
|
4314
|
-
for (const run of runs) {
|
|
4328
|
+
var RESUMABLE_LOCAL_RUN_STATUSES = new Set(["created", "preparing", "running", "validating", "reviewing"]);
|
|
4329
|
+
function collectResumableLocalRuns(state, runs) {
|
|
4330
|
+
return runs.filter((run) => {
|
|
4315
4331
|
const status = normalizeString(run.status)?.toLowerCase() ?? "";
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
if (run.mode !== "local" || !wasStartedByRigServer || !ORPHANABLE_LOCAL_RUN_STATUSES.has(status) || state.runProcesses.has(run.runId)) {
|
|
4319
|
-
continue;
|
|
4320
|
-
}
|
|
4321
|
-
const detail = "Recovered stale local run after Rig server restart; no live child process was attached to this server instance.";
|
|
4322
|
-
patchRunRecord(state.projectRoot, run.runId, {
|
|
4323
|
-
status: "failed",
|
|
4324
|
-
completedAt: run.completedAt ?? nowIso,
|
|
4325
|
-
updatedAt: nowIso,
|
|
4326
|
-
errorText: detail
|
|
4327
|
-
});
|
|
4328
|
-
appendRunLogEntry(state.projectRoot, run.runId, {
|
|
4329
|
-
id: `log:${run.runId}:stale-local-run`,
|
|
4330
|
-
title: "Run marked stale after server restart",
|
|
4331
|
-
detail,
|
|
4332
|
-
tone: "error",
|
|
4333
|
-
status: "failed",
|
|
4334
|
-
createdAt: nowIso
|
|
4335
|
-
});
|
|
4336
|
-
changed = true;
|
|
4337
|
-
}
|
|
4338
|
-
return changed;
|
|
4332
|
+
return run.mode === "local" && RESUMABLE_LOCAL_RUN_STATUSES.has(status) && !state.runProcesses.has(run.runId);
|
|
4333
|
+
});
|
|
4339
4334
|
}
|
|
4340
4335
|
async function reconcileScheduler(state, reason) {
|
|
4341
4336
|
if (state.scheduler.reconciling) {
|
|
@@ -4350,7 +4345,20 @@ async function reconcileScheduler(state, reason) {
|
|
|
4350
4345
|
const queue = readQueueState(state.projectRoot);
|
|
4351
4346
|
const tasks = await state.snapshotService.getWorkspaceTasks();
|
|
4352
4347
|
let runs = listAuthorityRuns4(state.projectRoot);
|
|
4353
|
-
let changed =
|
|
4348
|
+
let changed = false;
|
|
4349
|
+
const resumableRuns = collectResumableLocalRuns(state, runs);
|
|
4350
|
+
for (const run of resumableRuns) {
|
|
4351
|
+
appendRunLogEntry(state.projectRoot, run.runId, {
|
|
4352
|
+
id: `log:${run.runId}:auto-resume:${Date.now()}`,
|
|
4353
|
+
title: "Run auto-resume scheduled",
|
|
4354
|
+
detail: `Rig server recovered nonterminal run ${run.runId} after ${reason}; resuming the same lifecycle instead of restarting it.`,
|
|
4355
|
+
tone: "info",
|
|
4356
|
+
status: "preparing",
|
|
4357
|
+
createdAt: new Date().toISOString()
|
|
4358
|
+
});
|
|
4359
|
+
await startLocalRun(state, run.runId, { resume: true });
|
|
4360
|
+
changed = true;
|
|
4361
|
+
}
|
|
4354
4362
|
if (changed) {
|
|
4355
4363
|
runs = listAuthorityRuns4(state.projectRoot);
|
|
4356
4364
|
}
|
|
@@ -6747,11 +6755,12 @@ data: ${JSON.stringify({ connectedAt: new Date().toISOString() })}
|
|
|
6747
6755
|
const runId = normalizeString(body.runId);
|
|
6748
6756
|
const createdAt = normalizeString(body.createdAt) ?? new Date().toISOString();
|
|
6749
6757
|
const promptOverride = normalizeString(body.promptOverride);
|
|
6758
|
+
const restart = body.restart === true;
|
|
6750
6759
|
if (!runId) {
|
|
6751
6760
|
return deps.badRequest("runId is required");
|
|
6752
6761
|
}
|
|
6753
6762
|
try {
|
|
6754
|
-
await deps.resumeRunRecord(state, { runId, createdAt, promptOverride });
|
|
6763
|
+
await deps.resumeRunRecord(state, { runId, createdAt, promptOverride, restart });
|
|
6755
6764
|
deps.broadcastSnapshotInvalidation(state);
|
|
6756
6765
|
return deps.jsonResponse({ ok: true, runId, createdAt });
|
|
6757
6766
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h-rig/server",
|
|
3
|
-
"version": "0.0.6-alpha.
|
|
3
|
+
"version": "0.0.6-alpha.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Rig package",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"rig-server": "./dist/src/server.js"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.
|
|
29
|
-
"@rig/core": "npm:@h-rig/core@0.0.6-alpha.
|
|
30
|
-
"@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.
|
|
28
|
+
"@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.5",
|
|
29
|
+
"@rig/core": "npm:@h-rig/core@0.0.6-alpha.5",
|
|
30
|
+
"@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.5",
|
|
31
31
|
"effect": "4.0.0-beta.78"
|
|
32
32
|
}
|
|
33
33
|
}
|