@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.
@@ -2679,6 +2679,14 @@ async function switchServerProjectRootViaServer(context, projectRoot, options =
2679
2679
  }
2680
2680
  throw new CliError2(`Rig server did not switch to ${projectRoot} before timeout (${lastError instanceof Error ? lastError.message : String(lastError ?? "no status")}).`, 1);
2681
2681
  }
2682
+ async function listRunsViaServer(context, options = {}) {
2683
+ const url = new URL("http://rig.local/api/runs");
2684
+ if (options.limit !== undefined)
2685
+ url.searchParams.set("limit", String(options.limit));
2686
+ const payload = await requestServerJson(context, `${url.pathname}${url.search}`);
2687
+ const runs = Array.isArray(payload) ? payload : payload && typeof payload === "object" && !Array.isArray(payload) && Array.isArray(payload.runs) ? payload.runs : [];
2688
+ return runs.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry)));
2689
+ }
2682
2690
  async function getRunDetailsViaServer(context, runId) {
2683
2691
  const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}`);
2684
2692
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
@@ -4322,6 +4330,7 @@ function countDoctorFailures(checks) {
4322
4330
 
4323
4331
  // packages/cli/src/commands/init.ts
4324
4332
  var RIG_CONFIG_PACKAGE_DIST_TAG = "latest";
4333
+ var DEFAULT_REMOTE_RIG_URL = "https://where.rig-does.work";
4325
4334
  var RIG_CONFIG_DEV_DEPENDENCIES = {
4326
4335
  "@rig/core": `npm:@h-rig/core@${RIG_CONFIG_PACKAGE_DIST_TAG}`,
4327
4336
  "@rig/standard-plugin": `npm:@h-rig/standard-plugin@${RIG_CONFIG_PACKAGE_DIST_TAG}`
@@ -4426,6 +4435,19 @@ function readGhAuthToken() {
4426
4435
  }
4427
4436
  return result.stdout.trim();
4428
4437
  }
4438
+ function refreshGhProjectScopesAndReadToken() {
4439
+ const result = spawnSync("gh", ["auth", "refresh", "--scopes", "read:project"], {
4440
+ encoding: "utf8",
4441
+ stdio: ["inherit", "pipe", "pipe"]
4442
+ });
4443
+ if (result.status !== 0)
4444
+ return null;
4445
+ try {
4446
+ return readGhAuthToken();
4447
+ } catch {
4448
+ return null;
4449
+ }
4450
+ }
4429
4451
  async function loadClackPrompts() {
4430
4452
  return await import("@clack/prompts");
4431
4453
  }
@@ -4521,12 +4543,27 @@ async function promptManualProjectStatusMapping(prompts) {
4521
4543
  }
4522
4544
  return statuses;
4523
4545
  }
4524
- async function promptGitHubProjectConfig(context, prompts, repoSlug, githubToken) {
4546
+ function projectScopeError(value) {
4547
+ const text2 = typeof value === "string" ? value : JSON.stringify(value ?? "");
4548
+ return /INSUFFICIENT_SCOPES|read:project|required scopes/i.test(text2);
4549
+ }
4550
+ function optionName(option) {
4551
+ return String(option.name ?? option.label ?? option.id ?? "").trim();
4552
+ }
4553
+ function autoProjectStatusValue(options, key, label) {
4554
+ const candidates = [DEFAULT_PROJECT_STATUS_OPTIONS[key], label].filter((value) => Boolean(value)).map((value) => value.trim().toLowerCase());
4555
+ const match = options.find((option) => candidates.includes(optionName(option).toLowerCase()));
4556
+ if (!match)
4557
+ return null;
4558
+ return String(match.id ?? match.name);
4559
+ }
4560
+ async function promptGitHubProjectConfig(context, prompts, repoSlug, githubToken, refreshProjectToken) {
4525
4561
  const projectChoice = await promptSelect(prompts, {
4526
4562
  message: "GitHub Projects status sync",
4563
+ initialValue: "select",
4527
4564
  options: [
4528
- { value: "off", label: "Off" },
4529
4565
  { value: "select", label: "Select accessible ProjectV2" },
4566
+ { value: "off", label: "Off" },
4530
4567
  { value: "manual", label: "Enter ProjectV2 ids manually" }
4531
4568
  ]
4532
4569
  });
@@ -4542,16 +4579,22 @@ async function promptGitHubProjectConfig(context, prompts, repoSlug, githubToken
4542
4579
  const owner = repoOwnerFromSlug(repoSlug);
4543
4580
  if (!owner)
4544
4581
  throw new CliError2(`Cannot derive GitHub owner from repo slug ${repoSlug}.`, 1);
4545
- const projectsPayload = await listGitHubProjectsForInit(context, owner, githubToken).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error), projects: [] }));
4546
- const projects = recordArray(projectsPayload, "projects");
4582
+ let activeToken = githubToken?.trim() || null;
4583
+ let projectsPayload = await listGitHubProjectsForInit(context, owner, activeToken).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error), projects: [] }));
4584
+ let projects = recordArray(projectsPayload, "projects");
4585
+ if (projects.length === 0 && projectScopeError(projectsPayload.error) && refreshProjectToken) {
4586
+ prompts.outro?.("GitHub token is missing read:project; refreshing gh auth scopes and retrying Projects.");
4587
+ const refreshedToken = refreshProjectToken();
4588
+ if (refreshedToken) {
4589
+ activeToken = refreshedToken;
4590
+ projectsPayload = await listGitHubProjectsForInit(context, owner, activeToken).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error), projects: [] }));
4591
+ projects = recordArray(projectsPayload, "projects");
4592
+ }
4593
+ }
4547
4594
  if (projects.length === 0) {
4548
- const error = typeof projectsPayload.error === "string" ? ` (${projectsPayload.error})` : "";
4549
- prompts.outro?.(`No accessible GitHub Projects were returned${error}; falling back to manual ProjectV2 ids.`);
4550
- return {
4551
- githubProject: await promptRequiredText(prompts, { message: "GitHub ProjectV2 id", placeholder: "PVT_..." }),
4552
- githubProjectStatusField: await promptRequiredText(prompts, { message: "Project Status field id", placeholder: "field_status" }),
4553
- githubProjectStatuses: await promptManualProjectStatusMapping(prompts)
4554
- };
4595
+ const error = typeof projectsPayload.error === "string" ? ` (${String(projectsPayload.error).replace(/\s+/g, " ").slice(0, 240)})` : "";
4596
+ prompts.outro?.(`No accessible GitHub Projects were returned${error}; continuing with GitHub Projects status sync off.`);
4597
+ return { githubProject: "off", ...activeToken ? { githubToken: activeToken } : {} };
4555
4598
  }
4556
4599
  const selectedProjectId = await promptSelect(prompts, {
4557
4600
  message: "GitHub ProjectV2 project",
@@ -4565,23 +4608,34 @@ async function promptGitHubProjectConfig(context, prompts, repoSlug, githubToken
4565
4608
  ]
4566
4609
  });
4567
4610
  const projectId = selectedProjectId === "manual" ? await promptRequiredText(prompts, { message: "GitHub ProjectV2 id", placeholder: "PVT_..." }) : selectedProjectId;
4568
- const fieldPayload = await getGitHubProjectStatusFieldForInit(context, projectId, githubToken).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error) }));
4611
+ const fieldPayload = await getGitHubProjectStatusFieldForInit(context, projectId, activeToken).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error) }));
4569
4612
  const fieldPayloadRecord = fieldPayload && typeof fieldPayload === "object" && !Array.isArray(fieldPayload) ? fieldPayload : {};
4570
4613
  const rawField = fieldPayloadRecord.field;
4571
4614
  const field = rawField && typeof rawField === "object" && !Array.isArray(rawField) ? rawField : null;
4572
4615
  const fieldId = typeof field?.id === "string" && field.id.trim() ? field.id : await promptRequiredText(prompts, { message: "Project Status field id", placeholder: "field_status" });
4573
4616
  const options = Array.isArray(field?.options) ? field.options.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))) : [];
4574
4617
  if (options.length === 0) {
4575
- return { githubProject: projectId, githubProjectStatusField: fieldId, githubProjectStatuses: await promptManualProjectStatusMapping(prompts) };
4618
+ return {
4619
+ githubProject: projectId,
4620
+ githubProjectStatusField: fieldId,
4621
+ githubProjectStatuses: await promptManualProjectStatusMapping(prompts),
4622
+ ...activeToken ? { githubToken: activeToken } : {}
4623
+ };
4576
4624
  }
4577
4625
  const statuses = {};
4578
4626
  for (const [key, label] of Object.entries(PROJECT_STATUS_PROMPTS)) {
4579
- statuses[key] = await promptSelect(prompts, {
4627
+ const auto = autoProjectStatusValue(options, key, label);
4628
+ statuses[key] = auto ?? await promptSelect(prompts, {
4580
4629
  message: `Project status option for ${label}`,
4581
- options: options.map((option) => ({ value: String(option.id ?? option.name), label: String(option.name ?? option.id) }))
4630
+ options: options.map((option) => ({ value: String(option.id ?? option.name), label: optionName(option) }))
4582
4631
  });
4583
4632
  }
4584
- return { githubProject: projectId, githubProjectStatusField: fieldId, githubProjectStatuses: Object.keys(statuses).length > 0 ? statuses : undefined };
4633
+ return {
4634
+ githubProject: projectId,
4635
+ githubProjectStatusField: fieldId,
4636
+ githubProjectStatuses: Object.keys(statuses).length > 0 ? statuses : undefined,
4637
+ ...activeToken ? { githubToken: activeToken } : {}
4638
+ };
4585
4639
  }
4586
4640
  function sleep2(ms) {
4587
4641
  return new Promise((resolve17) => setTimeout(resolve17, ms));
@@ -4912,12 +4966,13 @@ async function runInteractiveControlPlaneInit(context, prompts) {
4912
4966
  });
4913
4967
  const serverChoice = await promptSelect(prompts, {
4914
4968
  message: "Rig server",
4969
+ initialValue: "remote",
4915
4970
  options: [
4916
- { value: "local", label: "Local server", hint: "run on this machine" },
4917
- { value: "remote", label: "Remote server", hint: "connect to an HTTPS Rig server" }
4971
+ { value: "remote", label: "Remote server", hint: "connect to an HTTPS Rig server" },
4972
+ { value: "local", label: "Local server", hint: "run on this machine" }
4918
4973
  ]
4919
4974
  });
4920
- const remoteUrl = serverChoice === "remote" ? await promptRequiredText(prompts, { message: "Remote Rig server URL", placeholder: "https://rig.example.com" }) : undefined;
4975
+ const remoteUrl = serverChoice === "remote" ? await promptRequiredText(prompts, { message: "Remote Rig server URL", placeholder: DEFAULT_REMOTE_RIG_URL, initialValue: DEFAULT_REMOTE_RIG_URL }) : undefined;
4921
4976
  let remoteCheckout;
4922
4977
  if (serverChoice === "remote") {
4923
4978
  const checkout = await promptSelect(prompts, {
@@ -4949,31 +5004,35 @@ async function runInteractiveControlPlaneInit(context, prompts) {
4949
5004
  { value: "skip", label: "Skip for now" }
4950
5005
  ]
4951
5006
  });
5007
+ let remoteGhTokenConfirmed = false;
4952
5008
  if (serverChoice === "remote" && authMethod === "gh") {
4953
5009
  if (!prompts.confirm)
4954
5010
  throw new CliError2("Remote gh-token import requires explicit confirmation.", 1);
4955
5011
  const confirmed = await prompts.confirm({
4956
5012
  message: `This sends a GitHub token from this machine to ${remoteUrl}. Continue?`,
4957
- initialValue: false
5013
+ initialValue: true
4958
5014
  });
4959
5015
  if (prompts.isCancel(confirmed) || confirmed !== true) {
4960
5016
  throw new CliError2("Remote gh-token import cancelled.", 1);
4961
5017
  }
5018
+ remoteGhTokenConfirmed = true;
4962
5019
  }
4963
5020
  const githubToken = authMethod === "token" ? await promptRequiredText(prompts, { message: "GitHub token", placeholder: "ghp_..." }) : authMethod === "gh" ? readGhAuthToken() : undefined;
4964
- const projectConfig = await promptGitHubProjectConfig(context, prompts, repoSlug, githubToken);
5021
+ const projectConfig = await promptGitHubProjectConfig(context, prompts, repoSlug, githubToken, authMethod === "gh" ? refreshGhProjectScopesAndReadToken : undefined);
5022
+ const effectiveGithubToken = projectConfig.githubToken ?? githubToken;
4965
5023
  const result = await runControlPlaneInit(context, {
4966
5024
  server: serverChoice,
4967
5025
  remoteUrl,
4968
5026
  repoSlug,
4969
- githubToken,
5027
+ githubToken: effectiveGithubToken,
4970
5028
  githubAuthMethod: authMethod,
4971
5029
  githubProject: projectConfig.githubProject,
4972
5030
  githubProjectStatusField: projectConfig.githubProjectStatusField,
4973
5031
  githubProjectStatuses: projectConfig.githubProjectStatuses,
4974
5032
  remoteCheckout,
4975
5033
  repair,
4976
- privateStateOnly
5034
+ privateStateOnly,
5035
+ yes: remoteGhTokenConfirmed || undefined
4977
5036
  });
4978
5037
  const details = result.details && typeof result.details === "object" && !Array.isArray(result.details) ? result.details : {};
4979
5038
  const deviceAuth = details.deviceAuth && typeof details.deviceAuth === "object" && !Array.isArray(details.deviceAuth) ? details.deviceAuth : null;
@@ -6148,6 +6207,42 @@ var CANONICAL_STAGES = [
6148
6207
  function logDetail(log3) {
6149
6208
  return typeof log3.detail === "string" ? log3.detail.trim() : "";
6150
6209
  }
6210
+ function parseProviderProtocolLog(title, detail) {
6211
+ if (title.trim().toLowerCase() !== "agent output")
6212
+ return null;
6213
+ if (!detail.startsWith("{") || !detail.endsWith("}"))
6214
+ return null;
6215
+ try {
6216
+ const record = JSON.parse(detail);
6217
+ if (!record || typeof record !== "object" || Array.isArray(record))
6218
+ return null;
6219
+ const type = record.type;
6220
+ return typeof type === "string" && [
6221
+ "assistant",
6222
+ "message_start",
6223
+ "message_update",
6224
+ "message_end",
6225
+ "stream_event",
6226
+ "tool_result",
6227
+ "tool_execution_start",
6228
+ "tool_execution_update",
6229
+ "tool_execution_end",
6230
+ "turn_start",
6231
+ "turn_end"
6232
+ ].includes(type) ? record : null;
6233
+ } catch {
6234
+ return null;
6235
+ }
6236
+ }
6237
+ function renderProviderProtocolLog(record) {
6238
+ const type = typeof record.type === "string" ? record.type : "";
6239
+ if (type === "tool_execution_start" || type === "tool_execution_update" || type === "tool_execution_end") {
6240
+ const toolName = String(record.toolName ?? record.name ?? "tool");
6241
+ 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";
6242
+ return `[Pi tool] ${toolName} ${status}`;
6243
+ }
6244
+ return null;
6245
+ }
6151
6246
  function entryId(entry, fallback) {
6152
6247
  return typeof entry.id === "string" && entry.id.trim() ? entry.id : fallback;
6153
6248
  }
@@ -6192,12 +6287,16 @@ function createPiRunStreamRenderer(output = process.stdout) {
6192
6287
  if (entry.type === "assistant_message" && typeof entry.text === "string") {
6193
6288
  const text2 = entry.text;
6194
6289
  const previousText = assistantTextById.get(id) ?? "";
6290
+ if (!previousText && text2.trim()) {
6291
+ writeLine("[Pi assistant]");
6292
+ }
6195
6293
  if (text2.startsWith(previousText)) {
6196
6294
  const delta = text2.slice(previousText.length);
6197
6295
  if (delta)
6198
6296
  output.write(delta);
6199
6297
  } else if (text2.trim() && text2 !== previousText) {
6200
- writeLine(`
6298
+ if (previousText)
6299
+ writeLine(`
6201
6300
  [Pi assistant]`);
6202
6301
  output.write(text2);
6203
6302
  }
@@ -6228,6 +6327,13 @@ function createPiRunStreamRenderer(output = process.stdout) {
6228
6327
  const detail = logDetail(entry);
6229
6328
  if (!detail)
6230
6329
  continue;
6330
+ const protocolRecord = parseProviderProtocolLog(title, detail);
6331
+ if (protocolRecord) {
6332
+ const protocolLine = renderProviderProtocolLog(protocolRecord);
6333
+ if (protocolLine)
6334
+ writeLine(protocolLine);
6335
+ continue;
6336
+ }
6231
6337
  writeLine(`[${title || "Rig log"}] ${detail}`);
6232
6338
  }
6233
6339
  }
@@ -6375,6 +6481,28 @@ function normalizeRemoteRunDetails(payload) {
6375
6481
  ...Array.isArray(payload.userInputs) ? { userInputs: payload.userInputs } : {}
6376
6482
  };
6377
6483
  }
6484
+ var REMOTE_TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged"]);
6485
+ function isRemoteConnectionSelected(projectRoot) {
6486
+ return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
6487
+ }
6488
+ async function listRunsForSelectedConnection(context, options = {}) {
6489
+ if (isRemoteConnectionSelected(context.projectRoot)) {
6490
+ return { runs: await listRunsViaServer(context, options), source: "server" };
6491
+ }
6492
+ return { runs: listAuthorityRuns3(context.projectRoot), source: "local" };
6493
+ }
6494
+ function runStringField(run, key, fallback = "") {
6495
+ const value = run[key];
6496
+ return typeof value === "string" && value.trim() ? value : fallback;
6497
+ }
6498
+ function runDisplayTitle(run) {
6499
+ return runStringField(run, "title", runStringField(run, "taskId", "(untitled)"));
6500
+ }
6501
+ function buildServerRunStatus(runs) {
6502
+ const activeRuns = runs.filter((run) => !REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
6503
+ const recentRuns = runs.filter((run) => REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
6504
+ return { activeRuns, recentRuns, runs };
6505
+ }
6378
6506
  function shouldPromptForEpicSelection(context, command, promptEpic, noEpicPrompt) {
6379
6507
  if (noEpicPrompt) {
6380
6508
  return false;
@@ -6440,17 +6568,17 @@ async function executeRun(context, args) {
6440
6568
  switch (command) {
6441
6569
  case "list": {
6442
6570
  requireNoExtraArgs(rest, "bun run rig run list");
6443
- const runs = listAuthorityRuns3(context.projectRoot);
6571
+ const { runs, source } = await listRunsForSelectedConnection(context, { limit: 100 });
6444
6572
  if (context.outputMode === "text") {
6445
6573
  if (runs.length === 0) {
6446
- console.log("No runs recorded in .rig/runs.");
6574
+ console.log(source === "server" ? "No runs recorded on the selected Rig server." : "No runs recorded in .rig/runs.");
6447
6575
  } else {
6448
6576
  for (const run of runs) {
6449
- console.log(`- ${run.runId} \xB7 ${run.status} \xB7 ${run.title}`);
6577
+ console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runDisplayTitle(run)}`);
6450
6578
  }
6451
6579
  }
6452
6580
  }
6453
- return { ok: true, group: "run", command, details: { runs } };
6581
+ return { ok: true, group: "run", command, details: { runs, source } };
6454
6582
  }
6455
6583
  case "delete": {
6456
6584
  let pending = rest;
@@ -6587,17 +6715,19 @@ async function executeRun(context, args) {
6587
6715
  }
6588
6716
  return { ok: true, group: "run", command };
6589
6717
  }
6590
- const summary = runStatus(context.projectRoot, runtimeContext);
6718
+ const summary = isRemoteConnectionSelected(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
6719
+ const activeRuns = Array.isArray(summary.activeRuns) ? summary.activeRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
6720
+ const recentRuns = Array.isArray(summary.recentRuns) ? summary.recentRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
6591
6721
  if (context.outputMode === "text") {
6592
- console.log(`Active runs: ${summary.activeRuns.length}`);
6593
- for (const run of summary.activeRuns) {
6594
- console.log(`- ${run.runId} \xB7 ${run.status} \xB7 ${run.taskId ?? run.title}`);
6722
+ console.log(`Active runs: ${activeRuns.length}`);
6723
+ for (const run of activeRuns) {
6724
+ console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
6595
6725
  }
6596
- if (summary.recentRuns.length > 0) {
6726
+ if (recentRuns.length > 0) {
6597
6727
  console.log("");
6598
6728
  console.log("Recent runs:");
6599
- for (const run of summary.recentRuns) {
6600
- console.log(`- ${run.runId} \xB7 ${run.status} \xB7 ${run.taskId ?? run.title}`);
6729
+ for (const run of recentRuns) {
6730
+ console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
6601
6731
  }
6602
6732
  }
6603
6733
  }
@@ -8033,6 +8163,26 @@ function appendAssistantTimelineFromRecord(input) {
8033
8163
  }
8034
8164
  return nextAssistantText;
8035
8165
  }
8166
+ function appendPiToolTimelineFromRecord(input) {
8167
+ const type = typeof input.record.type === "string" ? input.record.type : "";
8168
+ if (type !== "tool_execution_start" && type !== "tool_execution_update" && type !== "tool_execution_end")
8169
+ return false;
8170
+ const toolCallId = typeof input.record.toolCallId === "string" && input.record.toolCallId.trim() ? input.record.toolCallId.trim() : `${Date.now()}`;
8171
+ const toolName = typeof input.record.toolName === "string" && input.record.toolName.trim() ? input.record.toolName.trim() : "tool";
8172
+ const result = input.record.result && typeof input.record.result === "object" && !Array.isArray(input.record.result) ? input.record.result : null;
8173
+ appendRunTimeline(input.projectRoot, input.runId, {
8174
+ id: `tool:${toolCallId}:${type}`,
8175
+ type,
8176
+ toolName,
8177
+ status: type === "tool_execution_end" ? input.record.isError === true || result?.isError === true ? "failed" : "completed" : "running",
8178
+ createdAt: new Date().toISOString()
8179
+ });
8180
+ return true;
8181
+ }
8182
+ function isNonRenderablePiProtocolRecord(record) {
8183
+ const type = typeof record.type === "string" ? record.type : "";
8184
+ 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");
8185
+ }
8036
8186
  function appendToolTimelineFromLog(input) {
8037
8187
  const title = typeof input.log.title === "string" ? input.log.title : "";
8038
8188
  if (title !== "Tool activity")
@@ -8558,6 +8708,10 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
8558
8708
  try {
8559
8709
  const record = JSON.parse(trimmed);
8560
8710
  const liveLogStatus = reviewStarted ? "reviewing" : verificationStarted ? "validating" : "running";
8711
+ if (input.runtimeAdapter === "pi" && appendPiToolTimelineFromRecord({ projectRoot: context.projectRoot, runId: input.runId, record })) {
8712
+ emitServerRunEvent({ type: "timeline", runId: input.runId });
8713
+ return;
8714
+ }
8561
8715
  const providerLogs = input.runtimeAdapter === "codex" ? buildCodexLogsFromRecord({
8562
8716
  runId: input.runId,
8563
8717
  record,
@@ -8629,6 +8783,9 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
8629
8783
  return;
8630
8784
  }
8631
8785
  }
8786
+ if (input.runtimeAdapter === "pi" && isNonRenderablePiProtocolRecord(record)) {
8787
+ return;
8788
+ }
8632
8789
  if (record.type === "assistant") {
8633
8790
  const message2 = record.message && typeof record.message === "object" ? record.message : record;
8634
8791
  const content = Array.isArray(message2.content) ? message2.content : [];