@h-rig/cli 0.0.6-alpha.1 → 0.0.6-alpha.2
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.js +338 -204
- package/dist/src/commands/_doctor-checks.js +31 -13
- package/dist/src/commands/_operator-view.js +20 -2
- package/dist/src/commands/_preflight.js +25 -7
- package/dist/src/commands/_server-client.js +22 -4
- package/dist/src/commands/_snapshot-upload.js +26 -8
- package/dist/src/commands/doctor.js +31 -13
- package/dist/src/commands/github.js +21 -3
- package/dist/src/commands/init.js +142 -62
- package/dist/src/commands/run.js +26 -8
- package/dist/src/commands/server.js +20 -2
- package/dist/src/commands/setup.js +36 -18
- package/dist/src/commands/task-run-driver.js +59 -4
- package/dist/src/commands/task.js +28 -10
- package/dist/src/commands.js +331 -197
- package/dist/src/index.js +338 -204
- package/package.json +4 -4
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
4
|
// packages/cli/src/commands/setup.ts
|
|
5
|
-
import { existsSync as
|
|
6
|
-
import { resolve as
|
|
5
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readdirSync, writeFileSync as writeFileSync2 } from "fs";
|
|
6
|
+
import { resolve as resolve6 } from "path";
|
|
7
7
|
|
|
8
8
|
// packages/cli/src/runner.ts
|
|
9
9
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
@@ -171,8 +171,8 @@ async function buildPiSetupChecks(input = {}) {
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
// packages/cli/src/commands/_doctor-checks.ts
|
|
174
|
-
import { existsSync as
|
|
175
|
-
import { resolve as
|
|
174
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
175
|
+
import { resolve as resolve5 } from "path";
|
|
176
176
|
import { isSupportedBunVersion, MIN_SUPPORTED_BUN_VERSION } from "@rig/runtime/control-plane/setup-version";
|
|
177
177
|
|
|
178
178
|
// packages/cli/src/commands/_connection-state.ts
|
|
@@ -259,15 +259,33 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
259
259
|
|
|
260
260
|
// packages/cli/src/commands/_server-client.ts
|
|
261
261
|
import { spawnSync } from "child_process";
|
|
262
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
263
|
+
import { resolve as resolve4 } from "path";
|
|
262
264
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
263
265
|
var cachedGitHubBearerToken;
|
|
264
266
|
function cleanToken(value) {
|
|
265
267
|
const trimmed = value?.trim();
|
|
266
268
|
return trimmed ? trimmed : null;
|
|
267
269
|
}
|
|
268
|
-
function
|
|
270
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
271
|
+
const path = resolve4(projectRoot, ".rig", "state", "github-auth.json");
|
|
272
|
+
if (!existsSync3(path))
|
|
273
|
+
return null;
|
|
274
|
+
try {
|
|
275
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
276
|
+
return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
|
|
277
|
+
} catch {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
269
282
|
if (cachedGitHubBearerToken !== undefined)
|
|
270
283
|
return cachedGitHubBearerToken;
|
|
284
|
+
const privateSession = readPrivateRemoteSessionToken(projectRoot);
|
|
285
|
+
if (privateSession) {
|
|
286
|
+
cachedGitHubBearerToken = privateSession;
|
|
287
|
+
return cachedGitHubBearerToken;
|
|
288
|
+
}
|
|
271
289
|
const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
|
|
272
290
|
if (envToken) {
|
|
273
291
|
cachedGitHubBearerToken = envToken;
|
|
@@ -287,7 +305,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
287
305
|
if (selected?.connection.kind === "remote") {
|
|
288
306
|
return {
|
|
289
307
|
baseUrl: selected.connection.baseUrl,
|
|
290
|
-
authToken: readGitHubBearerTokenForRemote(),
|
|
308
|
+
authToken: readGitHubBearerTokenForRemote(projectRoot),
|
|
291
309
|
connectionKind: "remote"
|
|
292
310
|
};
|
|
293
311
|
}
|
|
@@ -387,11 +405,11 @@ function repoSlugFromConfig(config) {
|
|
|
387
405
|
function loadFallbackConfig(projectRoot) {
|
|
388
406
|
const candidates = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
|
|
389
407
|
for (const name of candidates) {
|
|
390
|
-
const path =
|
|
391
|
-
if (!
|
|
408
|
+
const path = resolve5(projectRoot, name);
|
|
409
|
+
if (!existsSync4(path))
|
|
392
410
|
continue;
|
|
393
411
|
try {
|
|
394
|
-
const source =
|
|
412
|
+
const source = readFileSync4(path, "utf8");
|
|
395
413
|
if (name.endsWith(".json"))
|
|
396
414
|
return JSON.parse(source);
|
|
397
415
|
const owner = source.match(/owner\s*:\s*["']([^"']+)["']/)?.[1];
|
|
@@ -470,7 +488,7 @@ async function runRigDoctorChecks(options) {
|
|
|
470
488
|
checks.push(check("bun", `bun >= ${MIN_SUPPORTED_BUN_VERSION}`, isSupportedBunVersion(bunVersion) ? "pass" : "fail", `found ${bunVersion}`, `Install Bun ${MIN_SUPPORTED_BUN_VERSION} or newer.`), check("git", "git", which("git") ? "pass" : "fail", which("git") ?? undefined, "Install git and ensure it is on PATH."), check("jq", "jq", which("jq") ? "pass" : "warn", which("jq") ?? undefined, "Install jq (for example `brew install jq`)."));
|
|
471
489
|
const loadedConfig = await loadConfig(projectRoot).catch(() => null);
|
|
472
490
|
const config = loadedConfig ?? loadFallbackConfig(projectRoot);
|
|
473
|
-
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) =>
|
|
491
|
+
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync4(resolve5(projectRoot, name)));
|
|
474
492
|
checks.push(config ? check("config", "rig.config loadable", "pass") : check("config", "rig.config loadable", hasConfigFile ? "fail" : "fail", hasConfigFile ? "config file exists but failed to load" : "missing rig.config.ts/json", "Run `rig init` or fix the config error."));
|
|
475
493
|
const taskSourceKind = config?.taskSource?.kind;
|
|
476
494
|
checks.push(taskSourceKind ? check("task-source", "task source configured", "pass", taskSourceKind) : check("task-source", "task source configured", "fail", "missing taskSource", "Configure taskSource in rig.config.ts."));
|
|
@@ -638,8 +656,8 @@ function runSetupInit(projectRoot) {
|
|
|
638
656
|
mkdirSync2(stateDir, { recursive: true });
|
|
639
657
|
mkdirSync2(logsDir, { recursive: true });
|
|
640
658
|
mkdirSync2(artifactsDir, { recursive: true });
|
|
641
|
-
const failuresPath =
|
|
642
|
-
if (!
|
|
659
|
+
const failuresPath = resolve6(stateDir, "failed_approaches.md");
|
|
660
|
+
if (!existsSync5(failuresPath)) {
|
|
643
661
|
writeFileSync2(failuresPath, `# Failed Approaches
|
|
644
662
|
|
|
645
663
|
`, "utf-8");
|
|
@@ -657,18 +675,18 @@ async function runSetupCheck(projectRoot) {
|
|
|
657
675
|
}
|
|
658
676
|
async function runSetupPreflight(projectRoot) {
|
|
659
677
|
await runSetupCheck(projectRoot);
|
|
660
|
-
const validationRoot =
|
|
661
|
-
if (
|
|
678
|
+
const validationRoot = resolve6(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
|
|
679
|
+
if (existsSync5(validationRoot)) {
|
|
662
680
|
const validators = readdirSync(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
663
681
|
for (const validator of validators) {
|
|
664
|
-
const script =
|
|
665
|
-
if (
|
|
682
|
+
const script = resolve6(validationRoot, validator.name, "validate.sh");
|
|
683
|
+
if (existsSync5(script)) {
|
|
666
684
|
console.log(`OK: validator script ${script}`);
|
|
667
685
|
}
|
|
668
686
|
}
|
|
669
687
|
}
|
|
670
|
-
const hooksRoot =
|
|
671
|
-
if (
|
|
688
|
+
const hooksRoot = resolve6(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
|
|
689
|
+
if (existsSync5(hooksRoot)) {
|
|
672
690
|
const hooks = readdirSync(hooksRoot).filter((name) => name.endsWith(".sh"));
|
|
673
691
|
for (const hook of hooks) {
|
|
674
692
|
console.log(`OK: hook ${hook}`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/cli/src/commands/task-run-driver.ts
|
|
3
|
-
import { copyFileSync, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, statSync } from "fs";
|
|
3
|
+
import { copyFileSync, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, statSync, writeFileSync } from "fs";
|
|
4
4
|
import { resolve as resolve4 } from "path";
|
|
5
5
|
import { spawn, spawnSync } from "child_process";
|
|
6
6
|
import { createInterface as createLineInterface } from "readline";
|
|
@@ -476,6 +476,14 @@ function buildTaskRunReviewEnv(config) {
|
|
|
476
476
|
...review?.provider ? { AI_REVIEW_PROVIDER: review.provider } : {}
|
|
477
477
|
};
|
|
478
478
|
}
|
|
479
|
+
function buildDirtyBaselineHandshakeEnv(input) {
|
|
480
|
+
if (input.baselineMode !== "dirty-snapshot")
|
|
481
|
+
return { RIG_BASELINE_MODE: input.baselineMode ?? "head" };
|
|
482
|
+
return {
|
|
483
|
+
RIG_BASELINE_MODE: "dirty-snapshot",
|
|
484
|
+
RIG_DIRTY_BASELINE_READY_FILE: resolve4(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
|
|
485
|
+
};
|
|
486
|
+
}
|
|
479
487
|
function positiveInt(value, fallback) {
|
|
480
488
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
481
489
|
}
|
|
@@ -1057,7 +1065,7 @@ function stringArrayField(record, key) {
|
|
|
1057
1065
|
async function executeRigOwnedTaskRun(context, input) {
|
|
1058
1066
|
const runtimeTaskId = input.taskId?.trim() || `adhoc-${input.runId}`;
|
|
1059
1067
|
const sourceTask = readRunSourceTaskContract(context.projectRoot, input.runId, input.taskId);
|
|
1060
|
-
|
|
1068
|
+
let prompt = buildRunPrompt({
|
|
1061
1069
|
projectRoot: context.projectRoot,
|
|
1062
1070
|
taskId: input.taskId,
|
|
1063
1071
|
fallbackTitle: input.title,
|
|
@@ -1157,7 +1165,22 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
1157
1165
|
const loadedAutomationConfig = await loadTaskRunAutomationConfig(context.projectRoot);
|
|
1158
1166
|
const automationConfig = input.prMode ? { ...loadedAutomationConfig ?? {}, pr: { ...loadedAutomationConfig?.pr ?? {}, mode: input.prMode } } : loadedAutomationConfig;
|
|
1159
1167
|
const planningClassification = classifyPlanningNeed({ config: automationConfig, sourceTask });
|
|
1160
|
-
|
|
1168
|
+
const planningArtifactPath = resolve4("artifacts", runtimeTaskId, "implementation-plan.md");
|
|
1169
|
+
const persistedPlanning = {
|
|
1170
|
+
...planningClassification,
|
|
1171
|
+
classifier: input.runtimeAdapter === "pi" ? "pi-rig-structured-policy" : "rig-structured-policy",
|
|
1172
|
+
artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
|
|
1173
|
+
classifiedAt: new Date().toISOString()
|
|
1174
|
+
};
|
|
1175
|
+
mkdirSync(resolve4(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
|
|
1176
|
+
writeFileSync(resolve4(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
|
|
1177
|
+
`, "utf8");
|
|
1178
|
+
patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
|
|
1179
|
+
prompt = `${prompt}
|
|
1180
|
+
|
|
1181
|
+
Rig planning classification:
|
|
1182
|
+
${JSON.stringify(persistedPlanning, null, 2)}
|
|
1183
|
+
${planningClassification.planningRequired ? `Before implementing, write a concise implementation plan to ${planningArtifactPath}. Treat that plan artifact as required acceptance evidence for the Plan stage.` : "Planning is not required for this run; briefly state why before implementation."}`;
|
|
1161
1184
|
if (input.runtimeAdapter === "pi") {
|
|
1162
1185
|
for (const stage of ["Connect", "GitHub/task sync", "Prepare workspace", "Launch Pi", "Plan", "Implement"]) {
|
|
1163
1186
|
appendPiStageLog({
|
|
@@ -1224,6 +1247,7 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
1224
1247
|
...sourceTask ? { RIG_SOURCE_TASK_JSON: JSON.stringify(sourceTask) } : {}
|
|
1225
1248
|
};
|
|
1226
1249
|
Object.assign(childEnv, buildTaskRunReviewEnv(automationConfig));
|
|
1250
|
+
Object.assign(childEnv, buildDirtyBaselineHandshakeEnv({ projectRoot: context.projectRoot, runId: input.runId, baselineMode: input.baselineMode }));
|
|
1227
1251
|
const automationLimits = resolveTaskRunAutomationLimits(automationConfig);
|
|
1228
1252
|
const maxAttempts = automationLimits.maxValidationAttempts;
|
|
1229
1253
|
const promoteToValidating = (detail) => {
|
|
@@ -1287,13 +1311,20 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
1287
1311
|
if (!dirtyBaselineApplied && input.baselineMode === "dirty-snapshot" && latestRuntimeWorkspace) {
|
|
1288
1312
|
dirtyBaselineApplied = true;
|
|
1289
1313
|
const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
|
|
1314
|
+
const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
|
|
1315
|
+
if (readyFile) {
|
|
1316
|
+
mkdirSync(resolve4(readyFile, ".."), { recursive: true });
|
|
1317
|
+
writeFileSync(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
|
|
1318
|
+
`, "utf8");
|
|
1319
|
+
}
|
|
1290
1320
|
appendRunLog(context.projectRoot, input.runId, {
|
|
1291
1321
|
id: `log:${input.runId}:dirty-baseline`,
|
|
1292
1322
|
title: "Dirty baseline snapshot",
|
|
1293
1323
|
detail: dirty.detail,
|
|
1294
1324
|
tone: dirty.applied ? "tool" : "info",
|
|
1295
1325
|
status: dirty.applied ? "completed" : "skipped",
|
|
1296
|
-
createdAt: new Date().toISOString()
|
|
1326
|
+
createdAt: new Date().toISOString(),
|
|
1327
|
+
payload: readyFile ? { readyFile } : undefined
|
|
1297
1328
|
});
|
|
1298
1329
|
emitServerRunEvent({ type: "log", runId: input.runId, title: "Dirty baseline snapshot" });
|
|
1299
1330
|
}
|
|
@@ -1765,6 +1796,29 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
|
|
|
1765
1796
|
});
|
|
1766
1797
|
throw new CliError2(terminalFailureDetail, exit.code ?? 1);
|
|
1767
1798
|
}
|
|
1799
|
+
if (planningClassification.planningRequired) {
|
|
1800
|
+
const planWorkspace = latestRuntimeWorkspace ?? context.projectRoot;
|
|
1801
|
+
const expectedPlanPath = resolve4(planWorkspace, planningArtifactPath);
|
|
1802
|
+
if (!existsSync2(expectedPlanPath)) {
|
|
1803
|
+
const failedAt = new Date().toISOString();
|
|
1804
|
+
const failureDetail = `Planning was required (${planningClassification.reason}) but ${planningArtifactPath} was not written before implementation completed.`;
|
|
1805
|
+
patchAuthorityRun(context.projectRoot, input.runId, {
|
|
1806
|
+
status: "needs_attention",
|
|
1807
|
+
completedAt: failedAt,
|
|
1808
|
+
errorText: failureDetail
|
|
1809
|
+
});
|
|
1810
|
+
appendRunLog(context.projectRoot, input.runId, {
|
|
1811
|
+
id: `log:${input.runId}:plan-artifact-missing`,
|
|
1812
|
+
title: "Required plan artifact missing",
|
|
1813
|
+
detail: failureDetail,
|
|
1814
|
+
tone: "error",
|
|
1815
|
+
status: "needs_attention",
|
|
1816
|
+
createdAt: failedAt
|
|
1817
|
+
});
|
|
1818
|
+
emitServerRunEvent({ type: "failed", runId: input.runId, error: failureDetail });
|
|
1819
|
+
throw new CliError2(failureDetail, 1);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1768
1822
|
const runPiPrFeedbackFix = async (message) => {
|
|
1769
1823
|
appendPiStageLog({
|
|
1770
1824
|
projectRoot: context.projectRoot,
|
|
@@ -1935,5 +1989,6 @@ export {
|
|
|
1935
1989
|
buildTaskRunReviewEnv,
|
|
1936
1990
|
buildPiValidationRetrySteeringPrompt,
|
|
1937
1991
|
buildPiRigBridgeEnv,
|
|
1992
|
+
buildDirtyBaselineHandshakeEnv,
|
|
1938
1993
|
applyDirtyBaselineSnapshot
|
|
1939
1994
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/cli/src/commands/task.ts
|
|
3
|
-
import { readFileSync as
|
|
3
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
4
4
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
5
5
|
import { createInterface as createInterface3 } from "readline/promises";
|
|
6
|
-
import { resolve as
|
|
6
|
+
import { resolve as resolve4 } from "path";
|
|
7
7
|
|
|
8
8
|
// packages/cli/src/runner.ts
|
|
9
9
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
@@ -189,15 +189,33 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
189
189
|
|
|
190
190
|
// packages/cli/src/commands/_server-client.ts
|
|
191
191
|
import { spawnSync } from "child_process";
|
|
192
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
193
|
+
import { resolve as resolve2 } from "path";
|
|
192
194
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
193
195
|
var cachedGitHubBearerToken;
|
|
194
196
|
function cleanToken(value) {
|
|
195
197
|
const trimmed = value?.trim();
|
|
196
198
|
return trimmed ? trimmed : null;
|
|
197
199
|
}
|
|
198
|
-
function
|
|
200
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
201
|
+
const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
|
|
202
|
+
if (!existsSync2(path))
|
|
203
|
+
return null;
|
|
204
|
+
try {
|
|
205
|
+
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
206
|
+
return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
|
|
207
|
+
} catch {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
199
212
|
if (cachedGitHubBearerToken !== undefined)
|
|
200
213
|
return cachedGitHubBearerToken;
|
|
214
|
+
const privateSession = readPrivateRemoteSessionToken(projectRoot);
|
|
215
|
+
if (privateSession) {
|
|
216
|
+
cachedGitHubBearerToken = privateSession;
|
|
217
|
+
return cachedGitHubBearerToken;
|
|
218
|
+
}
|
|
201
219
|
const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
|
|
202
220
|
if (envToken) {
|
|
203
221
|
cachedGitHubBearerToken = envToken;
|
|
@@ -217,7 +235,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
217
235
|
if (selected?.connection.kind === "remote") {
|
|
218
236
|
return {
|
|
219
237
|
baseUrl: selected.connection.baseUrl,
|
|
220
|
-
authToken: readGitHubBearerTokenForRemote(),
|
|
238
|
+
authToken: readGitHubBearerTokenForRemote(projectRoot),
|
|
221
239
|
connectionKind: "remote"
|
|
222
240
|
};
|
|
223
241
|
}
|
|
@@ -378,9 +396,9 @@ async function submitTaskRunViaServer(context, input) {
|
|
|
378
396
|
}
|
|
379
397
|
|
|
380
398
|
// packages/cli/src/commands/_pi-install.ts
|
|
381
|
-
import { existsSync as
|
|
399
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, rmSync } from "fs";
|
|
382
400
|
import { homedir as homedir2 } from "os";
|
|
383
|
-
import { resolve as
|
|
401
|
+
import { resolve as resolve3 } from "path";
|
|
384
402
|
var PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
|
|
385
403
|
async function defaultCommandRunner(command, options = {}) {
|
|
386
404
|
const proc = Bun.spawn(command, { cwd: options.cwd, stdout: "pipe", stderr: "pipe" });
|
|
@@ -392,7 +410,7 @@ async function defaultCommandRunner(command, options = {}) {
|
|
|
392
410
|
return { exitCode, stdout, stderr };
|
|
393
411
|
}
|
|
394
412
|
function resolvePiRigExtensionPath(homeDir) {
|
|
395
|
-
return
|
|
413
|
+
return resolve3(homeDir, ".pi", "agent", "extensions", "pi-rig");
|
|
396
414
|
}
|
|
397
415
|
function resolvePiHomeDir(inputHomeDir) {
|
|
398
416
|
return inputHomeDir ?? process.env.RIG_PI_HOME_DIR?.trim() ?? homedir2();
|
|
@@ -420,13 +438,13 @@ async function checkPiRigInstall(input = {}) {
|
|
|
420
438
|
piRig: { ok: true, label: "pi-rig global extension", detail: extensionPath }
|
|
421
439
|
};
|
|
422
440
|
}
|
|
423
|
-
const exists = input.exists ??
|
|
441
|
+
const exists = input.exists ?? existsSync3;
|
|
424
442
|
const runner = input.commandRunner ?? defaultCommandRunner;
|
|
425
443
|
const piResult = await safeRun(runner, ["pi", "--version"]);
|
|
426
444
|
const piListResult = piResult.exitCode === 0 ? await safeRun(runner, ["pi", "list"]) : { exitCode: 1, stdout: "", stderr: "" };
|
|
427
445
|
const listedPiRig = piListResult.exitCode === 0 && piListContainsPiRig(`${piListResult.stdout}
|
|
428
446
|
${piListResult.stderr}`);
|
|
429
|
-
const legacyBridge = exists(
|
|
447
|
+
const legacyBridge = exists(resolve3(extensionPath, "index.ts"));
|
|
430
448
|
const hasPiRig = listedPiRig;
|
|
431
449
|
return {
|
|
432
450
|
extensionPath,
|
|
@@ -1101,7 +1119,7 @@ async function executeTask(context, args, options) {
|
|
|
1101
1119
|
const fileFlag = takeOption(rest.slice(1), "--file");
|
|
1102
1120
|
let content;
|
|
1103
1121
|
if (fileFlag.value) {
|
|
1104
|
-
content =
|
|
1122
|
+
content = readFileSync4(resolve4(context.projectRoot, fileFlag.value), "utf-8");
|
|
1105
1123
|
} else {
|
|
1106
1124
|
content = await readStdin();
|
|
1107
1125
|
}
|