@h-rig/cli 0.0.6-alpha.17 → 0.0.6-alpha.19
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 +192 -35
- package/dist/src/commands/_operator-surface.js +48 -1
- package/dist/src/commands/_operator-view.js +48 -1
- package/dist/src/commands/_server-client.js +9 -0
- package/dist/src/commands/init.js +74 -23
- package/dist/src/commands/run.js +91 -12
- package/dist/src/commands/task-run-driver.js +27 -0
- package/dist/src/commands/task.js +48 -1
- package/dist/src/commands.js +192 -35
- package/dist/src/index.js +192 -35
- package/package.json +5 -5
package/dist/src/index.js
CHANGED
|
@@ -2882,6 +2882,14 @@ async function switchServerProjectRootViaServer(context, projectRoot, options =
|
|
|
2882
2882
|
}
|
|
2883
2883
|
throw new CliError2(`Rig server did not switch to ${projectRoot} before timeout (${lastError instanceof Error ? lastError.message : String(lastError ?? "no status")}).`, 1);
|
|
2884
2884
|
}
|
|
2885
|
+
async function listRunsViaServer(context, options = {}) {
|
|
2886
|
+
const url = new URL("http://rig.local/api/runs");
|
|
2887
|
+
if (options.limit !== undefined)
|
|
2888
|
+
url.searchParams.set("limit", String(options.limit));
|
|
2889
|
+
const payload = await requestServerJson(context, `${url.pathname}${url.search}`);
|
|
2890
|
+
const runs = Array.isArray(payload) ? payload : payload && typeof payload === "object" && !Array.isArray(payload) && Array.isArray(payload.runs) ? payload.runs : [];
|
|
2891
|
+
return runs.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry)));
|
|
2892
|
+
}
|
|
2885
2893
|
async function getRunDetailsViaServer(context, runId) {
|
|
2886
2894
|
const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}`);
|
|
2887
2895
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
@@ -4525,6 +4533,7 @@ function countDoctorFailures(checks) {
|
|
|
4525
4533
|
|
|
4526
4534
|
// packages/cli/src/commands/init.ts
|
|
4527
4535
|
var RIG_CONFIG_PACKAGE_DIST_TAG = "latest";
|
|
4536
|
+
var DEFAULT_REMOTE_RIG_URL = "https://where.rig-does.work";
|
|
4528
4537
|
var RIG_CONFIG_DEV_DEPENDENCIES = {
|
|
4529
4538
|
"@rig/core": `npm:@h-rig/core@${RIG_CONFIG_PACKAGE_DIST_TAG}`,
|
|
4530
4539
|
"@rig/standard-plugin": `npm:@h-rig/standard-plugin@${RIG_CONFIG_PACKAGE_DIST_TAG}`
|
|
@@ -4629,6 +4638,19 @@ function readGhAuthToken() {
|
|
|
4629
4638
|
}
|
|
4630
4639
|
return result.stdout.trim();
|
|
4631
4640
|
}
|
|
4641
|
+
function refreshGhProjectScopesAndReadToken() {
|
|
4642
|
+
const result = spawnSync("gh", ["auth", "refresh", "--scopes", "read:project"], {
|
|
4643
|
+
encoding: "utf8",
|
|
4644
|
+
stdio: ["inherit", "pipe", "pipe"]
|
|
4645
|
+
});
|
|
4646
|
+
if (result.status !== 0)
|
|
4647
|
+
return null;
|
|
4648
|
+
try {
|
|
4649
|
+
return readGhAuthToken();
|
|
4650
|
+
} catch {
|
|
4651
|
+
return null;
|
|
4652
|
+
}
|
|
4653
|
+
}
|
|
4632
4654
|
async function loadClackPrompts() {
|
|
4633
4655
|
return await import("@clack/prompts");
|
|
4634
4656
|
}
|
|
@@ -4724,12 +4746,27 @@ async function promptManualProjectStatusMapping(prompts) {
|
|
|
4724
4746
|
}
|
|
4725
4747
|
return statuses;
|
|
4726
4748
|
}
|
|
4727
|
-
|
|
4749
|
+
function projectScopeError(value) {
|
|
4750
|
+
const text2 = typeof value === "string" ? value : JSON.stringify(value ?? "");
|
|
4751
|
+
return /INSUFFICIENT_SCOPES|read:project|required scopes/i.test(text2);
|
|
4752
|
+
}
|
|
4753
|
+
function optionName(option) {
|
|
4754
|
+
return String(option.name ?? option.label ?? option.id ?? "").trim();
|
|
4755
|
+
}
|
|
4756
|
+
function autoProjectStatusValue(options, key, label) {
|
|
4757
|
+
const candidates = [DEFAULT_PROJECT_STATUS_OPTIONS[key], label].filter((value) => Boolean(value)).map((value) => value.trim().toLowerCase());
|
|
4758
|
+
const match = options.find((option) => candidates.includes(optionName(option).toLowerCase()));
|
|
4759
|
+
if (!match)
|
|
4760
|
+
return null;
|
|
4761
|
+
return String(match.id ?? match.name);
|
|
4762
|
+
}
|
|
4763
|
+
async function promptGitHubProjectConfig(context, prompts, repoSlug, githubToken, refreshProjectToken) {
|
|
4728
4764
|
const projectChoice = await promptSelect(prompts, {
|
|
4729
4765
|
message: "GitHub Projects status sync",
|
|
4766
|
+
initialValue: "select",
|
|
4730
4767
|
options: [
|
|
4731
|
-
{ value: "off", label: "Off" },
|
|
4732
4768
|
{ value: "select", label: "Select accessible ProjectV2" },
|
|
4769
|
+
{ value: "off", label: "Off" },
|
|
4733
4770
|
{ value: "manual", label: "Enter ProjectV2 ids manually" }
|
|
4734
4771
|
]
|
|
4735
4772
|
});
|
|
@@ -4745,16 +4782,22 @@ async function promptGitHubProjectConfig(context, prompts, repoSlug, githubToken
|
|
|
4745
4782
|
const owner = repoOwnerFromSlug(repoSlug);
|
|
4746
4783
|
if (!owner)
|
|
4747
4784
|
throw new CliError2(`Cannot derive GitHub owner from repo slug ${repoSlug}.`, 1);
|
|
4748
|
-
|
|
4749
|
-
|
|
4785
|
+
let activeToken = githubToken?.trim() || null;
|
|
4786
|
+
let projectsPayload = await listGitHubProjectsForInit(context, owner, activeToken).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error), projects: [] }));
|
|
4787
|
+
let projects = recordArray(projectsPayload, "projects");
|
|
4788
|
+
if (projects.length === 0 && projectScopeError(projectsPayload.error) && refreshProjectToken) {
|
|
4789
|
+
prompts.outro?.("GitHub token is missing read:project; refreshing gh auth scopes and retrying Projects.");
|
|
4790
|
+
const refreshedToken = refreshProjectToken();
|
|
4791
|
+
if (refreshedToken) {
|
|
4792
|
+
activeToken = refreshedToken;
|
|
4793
|
+
projectsPayload = await listGitHubProjectsForInit(context, owner, activeToken).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error), projects: [] }));
|
|
4794
|
+
projects = recordArray(projectsPayload, "projects");
|
|
4795
|
+
}
|
|
4796
|
+
}
|
|
4750
4797
|
if (projects.length === 0) {
|
|
4751
|
-
const error = typeof projectsPayload.error === "string" ? ` (${projectsPayload.error})` : "";
|
|
4752
|
-
prompts.outro?.(`No accessible GitHub Projects were returned${error};
|
|
4753
|
-
return {
|
|
4754
|
-
githubProject: await promptRequiredText(prompts, { message: "GitHub ProjectV2 id", placeholder: "PVT_..." }),
|
|
4755
|
-
githubProjectStatusField: await promptRequiredText(prompts, { message: "Project Status field id", placeholder: "field_status" }),
|
|
4756
|
-
githubProjectStatuses: await promptManualProjectStatusMapping(prompts)
|
|
4757
|
-
};
|
|
4798
|
+
const error = typeof projectsPayload.error === "string" ? ` (${String(projectsPayload.error).replace(/\s+/g, " ").slice(0, 240)})` : "";
|
|
4799
|
+
prompts.outro?.(`No accessible GitHub Projects were returned${error}; continuing with GitHub Projects status sync off.`);
|
|
4800
|
+
return { githubProject: "off", ...activeToken ? { githubToken: activeToken } : {} };
|
|
4758
4801
|
}
|
|
4759
4802
|
const selectedProjectId = await promptSelect(prompts, {
|
|
4760
4803
|
message: "GitHub ProjectV2 project",
|
|
@@ -4768,23 +4811,34 @@ async function promptGitHubProjectConfig(context, prompts, repoSlug, githubToken
|
|
|
4768
4811
|
]
|
|
4769
4812
|
});
|
|
4770
4813
|
const projectId = selectedProjectId === "manual" ? await promptRequiredText(prompts, { message: "GitHub ProjectV2 id", placeholder: "PVT_..." }) : selectedProjectId;
|
|
4771
|
-
const fieldPayload = await getGitHubProjectStatusFieldForInit(context, projectId,
|
|
4814
|
+
const fieldPayload = await getGitHubProjectStatusFieldForInit(context, projectId, activeToken).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error) }));
|
|
4772
4815
|
const fieldPayloadRecord = fieldPayload && typeof fieldPayload === "object" && !Array.isArray(fieldPayload) ? fieldPayload : {};
|
|
4773
4816
|
const rawField = fieldPayloadRecord.field;
|
|
4774
4817
|
const field = rawField && typeof rawField === "object" && !Array.isArray(rawField) ? rawField : null;
|
|
4775
4818
|
const fieldId = typeof field?.id === "string" && field.id.trim() ? field.id : await promptRequiredText(prompts, { message: "Project Status field id", placeholder: "field_status" });
|
|
4776
4819
|
const options = Array.isArray(field?.options) ? field.options.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))) : [];
|
|
4777
4820
|
if (options.length === 0) {
|
|
4778
|
-
return {
|
|
4821
|
+
return {
|
|
4822
|
+
githubProject: projectId,
|
|
4823
|
+
githubProjectStatusField: fieldId,
|
|
4824
|
+
githubProjectStatuses: await promptManualProjectStatusMapping(prompts),
|
|
4825
|
+
...activeToken ? { githubToken: activeToken } : {}
|
|
4826
|
+
};
|
|
4779
4827
|
}
|
|
4780
4828
|
const statuses = {};
|
|
4781
4829
|
for (const [key, label] of Object.entries(PROJECT_STATUS_PROMPTS)) {
|
|
4782
|
-
|
|
4830
|
+
const auto = autoProjectStatusValue(options, key, label);
|
|
4831
|
+
statuses[key] = auto ?? await promptSelect(prompts, {
|
|
4783
4832
|
message: `Project status option for ${label}`,
|
|
4784
|
-
options: options.map((option) => ({ value: String(option.id ?? option.name), label:
|
|
4833
|
+
options: options.map((option) => ({ value: String(option.id ?? option.name), label: optionName(option) }))
|
|
4785
4834
|
});
|
|
4786
4835
|
}
|
|
4787
|
-
return {
|
|
4836
|
+
return {
|
|
4837
|
+
githubProject: projectId,
|
|
4838
|
+
githubProjectStatusField: fieldId,
|
|
4839
|
+
githubProjectStatuses: Object.keys(statuses).length > 0 ? statuses : undefined,
|
|
4840
|
+
...activeToken ? { githubToken: activeToken } : {}
|
|
4841
|
+
};
|
|
4788
4842
|
}
|
|
4789
4843
|
function sleep2(ms) {
|
|
4790
4844
|
return new Promise((resolve18) => setTimeout(resolve18, ms));
|
|
@@ -5115,12 +5169,13 @@ async function runInteractiveControlPlaneInit(context, prompts) {
|
|
|
5115
5169
|
});
|
|
5116
5170
|
const serverChoice = await promptSelect(prompts, {
|
|
5117
5171
|
message: "Rig server",
|
|
5172
|
+
initialValue: "remote",
|
|
5118
5173
|
options: [
|
|
5119
|
-
{ value: "
|
|
5120
|
-
{ value: "
|
|
5174
|
+
{ value: "remote", label: "Remote server", hint: "connect to an HTTPS Rig server" },
|
|
5175
|
+
{ value: "local", label: "Local server", hint: "run on this machine" }
|
|
5121
5176
|
]
|
|
5122
5177
|
});
|
|
5123
|
-
const remoteUrl = serverChoice === "remote" ? await promptRequiredText(prompts, { message: "Remote Rig server URL", placeholder:
|
|
5178
|
+
const remoteUrl = serverChoice === "remote" ? await promptRequiredText(prompts, { message: "Remote Rig server URL", placeholder: DEFAULT_REMOTE_RIG_URL, initialValue: DEFAULT_REMOTE_RIG_URL }) : undefined;
|
|
5124
5179
|
let remoteCheckout;
|
|
5125
5180
|
if (serverChoice === "remote") {
|
|
5126
5181
|
const checkout = await promptSelect(prompts, {
|
|
@@ -5152,31 +5207,35 @@ async function runInteractiveControlPlaneInit(context, prompts) {
|
|
|
5152
5207
|
{ value: "skip", label: "Skip for now" }
|
|
5153
5208
|
]
|
|
5154
5209
|
});
|
|
5210
|
+
let remoteGhTokenConfirmed = false;
|
|
5155
5211
|
if (serverChoice === "remote" && authMethod === "gh") {
|
|
5156
5212
|
if (!prompts.confirm)
|
|
5157
5213
|
throw new CliError2("Remote gh-token import requires explicit confirmation.", 1);
|
|
5158
5214
|
const confirmed = await prompts.confirm({
|
|
5159
5215
|
message: `This sends a GitHub token from this machine to ${remoteUrl}. Continue?`,
|
|
5160
|
-
initialValue:
|
|
5216
|
+
initialValue: true
|
|
5161
5217
|
});
|
|
5162
5218
|
if (prompts.isCancel(confirmed) || confirmed !== true) {
|
|
5163
5219
|
throw new CliError2("Remote gh-token import cancelled.", 1);
|
|
5164
5220
|
}
|
|
5221
|
+
remoteGhTokenConfirmed = true;
|
|
5165
5222
|
}
|
|
5166
5223
|
const githubToken = authMethod === "token" ? await promptRequiredText(prompts, { message: "GitHub token", placeholder: "ghp_..." }) : authMethod === "gh" ? readGhAuthToken() : undefined;
|
|
5167
|
-
const projectConfig = await promptGitHubProjectConfig(context, prompts, repoSlug, githubToken);
|
|
5224
|
+
const projectConfig = await promptGitHubProjectConfig(context, prompts, repoSlug, githubToken, authMethod === "gh" ? refreshGhProjectScopesAndReadToken : undefined);
|
|
5225
|
+
const effectiveGithubToken = projectConfig.githubToken ?? githubToken;
|
|
5168
5226
|
const result = await runControlPlaneInit(context, {
|
|
5169
5227
|
server: serverChoice,
|
|
5170
5228
|
remoteUrl,
|
|
5171
5229
|
repoSlug,
|
|
5172
|
-
githubToken,
|
|
5230
|
+
githubToken: effectiveGithubToken,
|
|
5173
5231
|
githubAuthMethod: authMethod,
|
|
5174
5232
|
githubProject: projectConfig.githubProject,
|
|
5175
5233
|
githubProjectStatusField: projectConfig.githubProjectStatusField,
|
|
5176
5234
|
githubProjectStatuses: projectConfig.githubProjectStatuses,
|
|
5177
5235
|
remoteCheckout,
|
|
5178
5236
|
repair,
|
|
5179
|
-
privateStateOnly
|
|
5237
|
+
privateStateOnly,
|
|
5238
|
+
yes: remoteGhTokenConfirmed || undefined
|
|
5180
5239
|
});
|
|
5181
5240
|
const details = result.details && typeof result.details === "object" && !Array.isArray(result.details) ? result.details : {};
|
|
5182
5241
|
const deviceAuth = details.deviceAuth && typeof details.deviceAuth === "object" && !Array.isArray(details.deviceAuth) ? details.deviceAuth : null;
|
|
@@ -6351,6 +6410,42 @@ var CANONICAL_STAGES = [
|
|
|
6351
6410
|
function logDetail(log3) {
|
|
6352
6411
|
return typeof log3.detail === "string" ? log3.detail.trim() : "";
|
|
6353
6412
|
}
|
|
6413
|
+
function parseProviderProtocolLog(title, detail) {
|
|
6414
|
+
if (title.trim().toLowerCase() !== "agent output")
|
|
6415
|
+
return null;
|
|
6416
|
+
if (!detail.startsWith("{") || !detail.endsWith("}"))
|
|
6417
|
+
return null;
|
|
6418
|
+
try {
|
|
6419
|
+
const record = JSON.parse(detail);
|
|
6420
|
+
if (!record || typeof record !== "object" || Array.isArray(record))
|
|
6421
|
+
return null;
|
|
6422
|
+
const type = record.type;
|
|
6423
|
+
return typeof type === "string" && [
|
|
6424
|
+
"assistant",
|
|
6425
|
+
"message_start",
|
|
6426
|
+
"message_update",
|
|
6427
|
+
"message_end",
|
|
6428
|
+
"stream_event",
|
|
6429
|
+
"tool_result",
|
|
6430
|
+
"tool_execution_start",
|
|
6431
|
+
"tool_execution_update",
|
|
6432
|
+
"tool_execution_end",
|
|
6433
|
+
"turn_start",
|
|
6434
|
+
"turn_end"
|
|
6435
|
+
].includes(type) ? record : null;
|
|
6436
|
+
} catch {
|
|
6437
|
+
return null;
|
|
6438
|
+
}
|
|
6439
|
+
}
|
|
6440
|
+
function renderProviderProtocolLog(record) {
|
|
6441
|
+
const type = typeof record.type === "string" ? record.type : "";
|
|
6442
|
+
if (type === "tool_execution_start" || type === "tool_execution_update" || type === "tool_execution_end") {
|
|
6443
|
+
const toolName = String(record.toolName ?? record.name ?? "tool");
|
|
6444
|
+
const status = type === "tool_execution_start" ? "started" : type === "tool_execution_end" ? record.isError === true || record.result && typeof record.result === "object" && !Array.isArray(record.result) && record.result.isError === true ? "failed" : "completed" : "running";
|
|
6445
|
+
return `[Pi tool] ${toolName} ${status}`;
|
|
6446
|
+
}
|
|
6447
|
+
return null;
|
|
6448
|
+
}
|
|
6354
6449
|
function entryId(entry, fallback) {
|
|
6355
6450
|
return typeof entry.id === "string" && entry.id.trim() ? entry.id : fallback;
|
|
6356
6451
|
}
|
|
@@ -6395,12 +6490,16 @@ function createPiRunStreamRenderer(output = process.stdout) {
|
|
|
6395
6490
|
if (entry.type === "assistant_message" && typeof entry.text === "string") {
|
|
6396
6491
|
const text2 = entry.text;
|
|
6397
6492
|
const previousText = assistantTextById.get(id) ?? "";
|
|
6493
|
+
if (!previousText && text2.trim()) {
|
|
6494
|
+
writeLine("[Pi assistant]");
|
|
6495
|
+
}
|
|
6398
6496
|
if (text2.startsWith(previousText)) {
|
|
6399
6497
|
const delta = text2.slice(previousText.length);
|
|
6400
6498
|
if (delta)
|
|
6401
6499
|
output.write(delta);
|
|
6402
6500
|
} else if (text2.trim() && text2 !== previousText) {
|
|
6403
|
-
|
|
6501
|
+
if (previousText)
|
|
6502
|
+
writeLine(`
|
|
6404
6503
|
[Pi assistant]`);
|
|
6405
6504
|
output.write(text2);
|
|
6406
6505
|
}
|
|
@@ -6431,6 +6530,13 @@ function createPiRunStreamRenderer(output = process.stdout) {
|
|
|
6431
6530
|
const detail = logDetail(entry);
|
|
6432
6531
|
if (!detail)
|
|
6433
6532
|
continue;
|
|
6533
|
+
const protocolRecord = parseProviderProtocolLog(title, detail);
|
|
6534
|
+
if (protocolRecord) {
|
|
6535
|
+
const protocolLine = renderProviderProtocolLog(protocolRecord);
|
|
6536
|
+
if (protocolLine)
|
|
6537
|
+
writeLine(protocolLine);
|
|
6538
|
+
continue;
|
|
6539
|
+
}
|
|
6434
6540
|
writeLine(`[${title || "Rig log"}] ${detail}`);
|
|
6435
6541
|
}
|
|
6436
6542
|
}
|
|
@@ -6578,6 +6684,28 @@ function normalizeRemoteRunDetails(payload) {
|
|
|
6578
6684
|
...Array.isArray(payload.userInputs) ? { userInputs: payload.userInputs } : {}
|
|
6579
6685
|
};
|
|
6580
6686
|
}
|
|
6687
|
+
var REMOTE_TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged"]);
|
|
6688
|
+
function isRemoteConnectionSelected(projectRoot) {
|
|
6689
|
+
return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
|
|
6690
|
+
}
|
|
6691
|
+
async function listRunsForSelectedConnection(context, options = {}) {
|
|
6692
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
6693
|
+
return { runs: await listRunsViaServer(context, options), source: "server" };
|
|
6694
|
+
}
|
|
6695
|
+
return { runs: listAuthorityRuns3(context.projectRoot), source: "local" };
|
|
6696
|
+
}
|
|
6697
|
+
function runStringField(run, key, fallback = "") {
|
|
6698
|
+
const value = run[key];
|
|
6699
|
+
return typeof value === "string" && value.trim() ? value : fallback;
|
|
6700
|
+
}
|
|
6701
|
+
function runDisplayTitle(run) {
|
|
6702
|
+
return runStringField(run, "title", runStringField(run, "taskId", "(untitled)"));
|
|
6703
|
+
}
|
|
6704
|
+
function buildServerRunStatus(runs) {
|
|
6705
|
+
const activeRuns = runs.filter((run) => !REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
|
|
6706
|
+
const recentRuns = runs.filter((run) => REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
|
|
6707
|
+
return { activeRuns, recentRuns, runs };
|
|
6708
|
+
}
|
|
6581
6709
|
function shouldPromptForEpicSelection(context, command, promptEpic, noEpicPrompt) {
|
|
6582
6710
|
if (noEpicPrompt) {
|
|
6583
6711
|
return false;
|
|
@@ -6643,17 +6771,17 @@ async function executeRun(context, args) {
|
|
|
6643
6771
|
switch (command) {
|
|
6644
6772
|
case "list": {
|
|
6645
6773
|
requireNoExtraArgs(rest, "bun run rig run list");
|
|
6646
|
-
const runs =
|
|
6774
|
+
const { runs, source } = await listRunsForSelectedConnection(context, { limit: 100 });
|
|
6647
6775
|
if (context.outputMode === "text") {
|
|
6648
6776
|
if (runs.length === 0) {
|
|
6649
|
-
console.log("No runs recorded in .rig/runs.");
|
|
6777
|
+
console.log(source === "server" ? "No runs recorded on the selected Rig server." : "No runs recorded in .rig/runs.");
|
|
6650
6778
|
} else {
|
|
6651
6779
|
for (const run of runs) {
|
|
6652
|
-
console.log(`- ${run
|
|
6780
|
+
console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runDisplayTitle(run)}`);
|
|
6653
6781
|
}
|
|
6654
6782
|
}
|
|
6655
6783
|
}
|
|
6656
|
-
return { ok: true, group: "run", command, details: { runs } };
|
|
6784
|
+
return { ok: true, group: "run", command, details: { runs, source } };
|
|
6657
6785
|
}
|
|
6658
6786
|
case "delete": {
|
|
6659
6787
|
let pending = rest;
|
|
@@ -6790,17 +6918,19 @@ async function executeRun(context, args) {
|
|
|
6790
6918
|
}
|
|
6791
6919
|
return { ok: true, group: "run", command };
|
|
6792
6920
|
}
|
|
6793
|
-
const summary = runStatus(context.projectRoot, runtimeContext);
|
|
6921
|
+
const summary = isRemoteConnectionSelected(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
|
|
6922
|
+
const activeRuns = Array.isArray(summary.activeRuns) ? summary.activeRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
6923
|
+
const recentRuns = Array.isArray(summary.recentRuns) ? summary.recentRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
6794
6924
|
if (context.outputMode === "text") {
|
|
6795
|
-
console.log(`Active runs: ${
|
|
6796
|
-
for (const run of
|
|
6797
|
-
console.log(`- ${run
|
|
6925
|
+
console.log(`Active runs: ${activeRuns.length}`);
|
|
6926
|
+
for (const run of activeRuns) {
|
|
6927
|
+
console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
|
|
6798
6928
|
}
|
|
6799
|
-
if (
|
|
6929
|
+
if (recentRuns.length > 0) {
|
|
6800
6930
|
console.log("");
|
|
6801
6931
|
console.log("Recent runs:");
|
|
6802
|
-
for (const run of
|
|
6803
|
-
console.log(`- ${run
|
|
6932
|
+
for (const run of recentRuns) {
|
|
6933
|
+
console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
|
|
6804
6934
|
}
|
|
6805
6935
|
}
|
|
6806
6936
|
}
|
|
@@ -8236,6 +8366,26 @@ function appendAssistantTimelineFromRecord(input) {
|
|
|
8236
8366
|
}
|
|
8237
8367
|
return nextAssistantText;
|
|
8238
8368
|
}
|
|
8369
|
+
function appendPiToolTimelineFromRecord(input) {
|
|
8370
|
+
const type = typeof input.record.type === "string" ? input.record.type : "";
|
|
8371
|
+
if (type !== "tool_execution_start" && type !== "tool_execution_update" && type !== "tool_execution_end")
|
|
8372
|
+
return false;
|
|
8373
|
+
const toolCallId = typeof input.record.toolCallId === "string" && input.record.toolCallId.trim() ? input.record.toolCallId.trim() : `${Date.now()}`;
|
|
8374
|
+
const toolName = typeof input.record.toolName === "string" && input.record.toolName.trim() ? input.record.toolName.trim() : "tool";
|
|
8375
|
+
const result = input.record.result && typeof input.record.result === "object" && !Array.isArray(input.record.result) ? input.record.result : null;
|
|
8376
|
+
appendRunTimeline(input.projectRoot, input.runId, {
|
|
8377
|
+
id: `tool:${toolCallId}:${type}`,
|
|
8378
|
+
type,
|
|
8379
|
+
toolName,
|
|
8380
|
+
status: type === "tool_execution_end" ? input.record.isError === true || result?.isError === true ? "failed" : "completed" : "running",
|
|
8381
|
+
createdAt: new Date().toISOString()
|
|
8382
|
+
});
|
|
8383
|
+
return true;
|
|
8384
|
+
}
|
|
8385
|
+
function isNonRenderablePiProtocolRecord(record) {
|
|
8386
|
+
const type = typeof record.type === "string" ? record.type : "";
|
|
8387
|
+
return type === "message_start" || type === "message_end" || type === "turn_start" || type === "turn_end" || type === "tool_result" || type === "message_update" && (!record.assistantMessageEvent || typeof record.assistantMessageEvent !== "object" || Array.isArray(record.assistantMessageEvent) || record.assistantMessageEvent.type !== "text_delta");
|
|
8388
|
+
}
|
|
8239
8389
|
function appendToolTimelineFromLog(input) {
|
|
8240
8390
|
const title = typeof input.log.title === "string" ? input.log.title : "";
|
|
8241
8391
|
if (title !== "Tool activity")
|
|
@@ -8761,6 +8911,10 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
8761
8911
|
try {
|
|
8762
8912
|
const record = JSON.parse(trimmed);
|
|
8763
8913
|
const liveLogStatus = reviewStarted ? "reviewing" : verificationStarted ? "validating" : "running";
|
|
8914
|
+
if (input.runtimeAdapter === "pi" && appendPiToolTimelineFromRecord({ projectRoot: context.projectRoot, runId: input.runId, record })) {
|
|
8915
|
+
emitServerRunEvent({ type: "timeline", runId: input.runId });
|
|
8916
|
+
return;
|
|
8917
|
+
}
|
|
8764
8918
|
const providerLogs = input.runtimeAdapter === "codex" ? buildCodexLogsFromRecord({
|
|
8765
8919
|
runId: input.runId,
|
|
8766
8920
|
record,
|
|
@@ -8832,6 +8986,9 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
8832
8986
|
return;
|
|
8833
8987
|
}
|
|
8834
8988
|
}
|
|
8989
|
+
if (input.runtimeAdapter === "pi" && isNonRenderablePiProtocolRecord(record)) {
|
|
8990
|
+
return;
|
|
8991
|
+
}
|
|
8835
8992
|
if (record.type === "assistant") {
|
|
8836
8993
|
const message2 = record.message && typeof record.message === "object" ? record.message : record;
|
|
8837
8994
|
const content = Array.isArray(message2.content) ? message2.content : [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h-rig/cli",
|
|
3
|
-
"version": "0.0.6-alpha.
|
|
3
|
+
"version": "0.0.6-alpha.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Rig package",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@clack/prompts": "^1.2.0",
|
|
26
|
-
"@rig/core": "npm:@h-rig/core@0.0.6-alpha.
|
|
27
|
-
"@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.
|
|
28
|
-
"@rig/client": "npm:@h-rig/client@0.0.6-alpha.
|
|
29
|
-
"@rig/server": "npm:@h-rig/server@0.0.6-alpha.
|
|
26
|
+
"@rig/core": "npm:@h-rig/core@0.0.6-alpha.19",
|
|
27
|
+
"@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.19",
|
|
28
|
+
"@rig/client": "npm:@h-rig/client@0.0.6-alpha.19",
|
|
29
|
+
"@rig/server": "npm:@h-rig/server@0.0.6-alpha.19",
|
|
30
30
|
"picocolors": "^1.1.1"
|
|
31
31
|
}
|
|
32
32
|
}
|