@h-rig/cli 0.0.6-alpha.21 → 0.0.6-alpha.23

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.
@@ -618,6 +618,7 @@ function buildPiRigBridgeEnv(input) {
618
618
  RIG_SERVER_RUN_ID: input.runId,
619
619
  RIG_TASK_ID: input.taskId,
620
620
  RIG_RUNTIME_ADAPTER: "pi",
621
+ RIG_STEERING_POLL_MS: "0",
621
622
  ...input.serverUrl ? { RIG_SERVER_URL: input.serverUrl } : {},
622
623
  ...input.authToken ? { RIG_AUTH_TOKEN: input.authToken } : {},
623
624
  ...githubBridgeEnv(githubToken)
@@ -1220,6 +1221,69 @@ function appendAssistantTimelineFromRecord(input) {
1220
1221
  }
1221
1222
  return nextAssistantText;
1222
1223
  }
1224
+ function appendPiRpcProtocolLogFromRecord(input) {
1225
+ const type = typeof input.record.type === "string" ? input.record.type : "";
1226
+ if (type === "response") {
1227
+ const command = typeof input.record.command === "string" ? input.record.command : "rpc";
1228
+ const success = input.record.success !== false;
1229
+ if (success && command !== "prompt" && command !== "steer" && command !== "follow_up" && command !== "set_session_name") {
1230
+ return true;
1231
+ }
1232
+ appendRunLog(input.projectRoot, input.runId, {
1233
+ id: input.nextRunLogId(),
1234
+ title: success ? "Pi RPC response" : "Pi RPC error",
1235
+ detail: success ? `${command}: accepted` : `${command}: ${String(input.record.error ?? "failed")}`,
1236
+ tone: success ? "tool" : "error",
1237
+ status: input.status,
1238
+ payload: input.record,
1239
+ createdAt: new Date().toISOString()
1240
+ });
1241
+ emitServerRunEvent({ type: "log", runId: input.runId, title: success ? "Pi RPC response" : "Pi RPC error" });
1242
+ return true;
1243
+ }
1244
+ if (type !== "extension_ui_request")
1245
+ return false;
1246
+ const method = typeof input.record.method === "string" ? input.record.method : "ui";
1247
+ let title = "Pi UI event";
1248
+ let detail = method;
1249
+ let tone = "info";
1250
+ if (method === "notify") {
1251
+ title = "Pi notification";
1252
+ detail = String(input.record.message ?? "");
1253
+ tone = input.record.notifyType === "error" ? "error" : "info";
1254
+ } else if (method === "setStatus") {
1255
+ title = "Pi UI status";
1256
+ detail = `${String(input.record.statusKey ?? "status")}: ${String(input.record.statusText ?? "cleared")}`;
1257
+ tone = "tool";
1258
+ } else if (method === "setWidget") {
1259
+ title = "Pi UI widget";
1260
+ const lines = Array.isArray(input.record.widgetLines) ? input.record.widgetLines.map((line) => String(line)).join(" | ") : "cleared";
1261
+ detail = `${String(input.record.widgetKey ?? "widget")}: ${lines}`.slice(0, 500);
1262
+ tone = "tool";
1263
+ } else if (method === "setTitle") {
1264
+ title = "Pi UI title";
1265
+ detail = String(input.record.title ?? "");
1266
+ tone = "tool";
1267
+ } else if (method === "set_editor_text") {
1268
+ title = "Pi editor update";
1269
+ detail = String(input.record.text ?? "").slice(0, 500);
1270
+ tone = "tool";
1271
+ } else {
1272
+ title = "Pi UI request";
1273
+ detail = `${method}: ${String(input.record.title ?? input.record.message ?? "")}`.trim();
1274
+ }
1275
+ appendRunLog(input.projectRoot, input.runId, {
1276
+ id: input.nextRunLogId(),
1277
+ title,
1278
+ detail,
1279
+ tone,
1280
+ status: input.status,
1281
+ payload: input.record,
1282
+ createdAt: new Date().toISOString()
1283
+ });
1284
+ emitServerRunEvent({ type: "log", runId: input.runId, title });
1285
+ return true;
1286
+ }
1223
1287
  function appendPiToolTimelineFromRecord(input) {
1224
1288
  const type = typeof input.record.type === "string" ? input.record.type : "";
1225
1289
  if (type !== "tool_execution_start" && type !== "tool_execution_update" && type !== "tool_execution_end")
@@ -1238,7 +1302,7 @@ function appendPiToolTimelineFromRecord(input) {
1238
1302
  }
1239
1303
  function isNonRenderablePiProtocolRecord(record) {
1240
1304
  const type = typeof record.type === "string" ? record.type : "";
1241
- 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");
1305
+ return type === "agent_start" || type === "agent_end" || 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");
1242
1306
  }
1243
1307
  function appendToolTimelineFromLog(input) {
1244
1308
  const title = typeof input.log.title === "string" ? input.log.title : "";
@@ -1401,11 +1465,7 @@ async function executeRigOwnedTaskRun(context, input) {
1401
1465
  ...input.model ? ["--model", input.model] : [],
1402
1466
  "--prompt"
1403
1467
  ] : input.runtimeAdapter === "pi" ? [
1404
- "--print",
1405
- "--verbose",
1406
- "--mode",
1407
- "json",
1408
- "--no-session",
1468
+ "__rig_pi_session_daemon__",
1409
1469
  ...input.model ? ["--model", input.model] : []
1410
1470
  ] : [
1411
1471
  "--print",
@@ -1502,7 +1562,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
1502
1562
  projectRoot: context.projectRoot,
1503
1563
  runId: input.runId,
1504
1564
  stage,
1505
- detail: stage === "Launch Pi" ? "Pi runtime bridge starting with pi-rig environment." : stage === "Plan" ? `${planningClassification.planningRequired ? "recorded" : "skipped"} (${planningClassification.reason}; size=${planningClassification.size}; risk=${planningClassification.risk})` : stage === "Implement" ? "Pi implementation pass is running." : null,
1565
+ detail: stage === "Launch Pi" ? "Worker Pi SDK session daemon starting; local frontend will attach over Rig-proxied WebSocket." : stage === "Plan" ? `${planningClassification.planningRequired ? "recorded" : "skipped"} (${planningClassification.reason}; size=${planningClassification.size}; risk=${planningClassification.risk})` : stage === "Implement" ? "Pi implementation pass is running in the worker runtime." : null,
1506
1566
  status: stage === "Implement" || stage === "Launch Pi" ? "running" : "completed"
1507
1567
  });
1508
1568
  }
@@ -1543,6 +1603,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
1543
1603
  let latestProviderCommand = null;
1544
1604
  let latestRuntimeBranch = resumeMode && typeof existingRunRecord?.branch === "string" ? existingRunRecord.branch : null;
1545
1605
  let snapshotSidecarPromise = null;
1606
+ let wrapperManagesRuntimeSnapshot = false;
1546
1607
  let dirtyBaselineApplied = false;
1547
1608
  const childEnv = {
1548
1609
  ...process.env,
@@ -1595,6 +1656,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
1595
1656
  detail: detail ?? "Verifier review is running."
1596
1657
  });
1597
1658
  };
1659
+ const nextRunLogId = createRunLogIdFactory(input.runId);
1598
1660
  const handleWrapperEvent = (rawPayload) => {
1599
1661
  let event = null;
1600
1662
  try {
@@ -1610,6 +1672,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
1610
1672
  latestSessionDir = typeof payload.sessionDir === "string" ? payload.sessionDir : latestSessionDir;
1611
1673
  latestLogsDir = typeof payload.logsDir === "string" ? payload.logsDir : latestLogsDir;
1612
1674
  const runtimeId = typeof payload.runtimeId === "string" ? payload.runtimeId : null;
1675
+ wrapperManagesRuntimeSnapshot = payload.snapshotManaged === true;
1613
1676
  latestRuntimeBranch = runtimeId;
1614
1677
  provisioningAction.complete(latestRuntimeWorkspace ?? "Runtime ready.", {
1615
1678
  runtimeId: runtimeId ?? null,
@@ -1647,7 +1710,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
1647
1710
  });
1648
1711
  emitServerRunEvent({ type: "log", runId: input.runId, title: "Dirty baseline snapshot" });
1649
1712
  }
1650
- if (!snapshotSidecarPromise && runtimeId && loadRuntimeSnapshotConfig(context.projectRoot).enabled) {
1713
+ if (!wrapperManagesRuntimeSnapshot && !snapshotSidecarPromise && runtimeId && loadRuntimeSnapshotConfig(context.projectRoot).enabled) {
1651
1714
  snapshotSidecarPromise = (async () => {
1652
1715
  const { sidecar, error } = await resolveTaskRunSnapshotSidecar({
1653
1716
  projectRoot: context.projectRoot,
@@ -1729,9 +1792,68 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
1729
1792
  }
1730
1793
  return true;
1731
1794
  }
1795
+ if (event.type === "pi.sessiond.starting" || event.type === "pi.sessiond.ready" || event.type === "pi.session.event_stream.connected" || event.type === "pi.prompt.sent" || event.type === "pi.prompt.waiting" || event.type === "pi.session.agent_end" || event.type === "pi.session.error") {
1796
+ const title = event.type === "pi.sessiond.starting" ? "Starting worker Pi session daemon" : event.type === "pi.sessiond.ready" ? "Worker Pi daemon ready" : event.type === "pi.session.event_stream.connected" ? "Worker Pi event stream connected" : event.type === "pi.prompt.sent" ? "Delivered initial prompt to worker Pi" : event.type === "pi.prompt.waiting" ? "Worker Pi prompt waiting" : event.type === "pi.session.agent_end" ? "Worker Pi turn complete" : "Worker Pi session error";
1797
+ const detail = event.type === "pi.sessiond.ready" ? "Daemon accepted control connection; waiting for SDK session metadata." : event.type === "pi.sessiond.starting" ? String(payload.workspaceDir ?? "worker runtime") : event.type === "pi.prompt.sent" ? `${String(payload.bytes ?? "unknown")} prompt bytes sent.` : event.type === "pi.prompt.waiting" ? String(payload.reason ?? "empty prompt") : event.type === "pi.session.error" ? String(payload.message ?? "session error") : String(payload.sessionId ?? payload.runId ?? "worker Pi session");
1798
+ appendRunLog(context.projectRoot, input.runId, {
1799
+ id: nextRunLogId(),
1800
+ title,
1801
+ detail,
1802
+ tone: event.type === "pi.session.error" ? "error" : "info",
1803
+ status: reviewStarted ? "reviewing" : verificationStarted ? "validating" : "running",
1804
+ payload: {
1805
+ eventType: event.type,
1806
+ runId: typeof payload.runId === "string" ? payload.runId : null,
1807
+ runtimeId: typeof payload.runtimeId === "string" ? payload.runtimeId : null,
1808
+ sessionId: typeof payload.sessionId === "string" ? payload.sessionId : null
1809
+ },
1810
+ createdAt: new Date().toISOString()
1811
+ });
1812
+ emitServerRunEvent({ type: "log", runId: input.runId, title });
1813
+ return true;
1814
+ }
1815
+ if (event.type === "pi.session.ready") {
1816
+ const privateMetadata = payload.privateMetadata && typeof payload.privateMetadata === "object" && !Array.isArray(payload.privateMetadata) ? payload.privateMetadata : null;
1817
+ const publicMetadata = payload.metadata && typeof payload.metadata === "object" && !Array.isArray(payload.metadata) ? payload.metadata : null;
1818
+ if (privateMetadata) {
1819
+ patchAuthorityRun(context.projectRoot, input.runId, {
1820
+ piSession: publicMetadata,
1821
+ piSessionPrivate: privateMetadata
1822
+ });
1823
+ const sessionId = typeof publicMetadata?.sessionId === "string" ? publicMetadata.sessionId : typeof privateMetadata.public === "object" && privateMetadata.public && !Array.isArray(privateMetadata.public) ? String(privateMetadata.public.sessionId ?? "") : "";
1824
+ appendRunLog(context.projectRoot, input.runId, {
1825
+ id: `log:${input.runId}:pi-session-ready`,
1826
+ title: "Worker Pi session ready",
1827
+ detail: sessionId ? `Session ${sessionId} is ready for WebSocket attach.` : "Worker Pi SDK session daemon is ready for WebSocket attach.",
1828
+ tone: "info",
1829
+ status: "running",
1830
+ payload: {
1831
+ sessionId: sessionId || null,
1832
+ runtimeId: typeof payload.runtimeId === "string" ? payload.runtimeId : null
1833
+ },
1834
+ createdAt: new Date().toISOString()
1835
+ });
1836
+ emitServerRunEvent({ type: "log", runId: input.runId, title: "Worker Pi session ready" });
1837
+ }
1838
+ return true;
1839
+ }
1840
+ if (event.type === "pi.rpc.prompt.sent" || event.type === "pi.rpc.steering.delivered" || event.type === "pi.rpc.steering.poll.failed" || event.type === "pi.rpc.extension_ui.cancelled") {
1841
+ const title = event.type === "pi.rpc.prompt.sent" ? "Delivered initial prompt to worker Pi" : event.type === "pi.rpc.steering.delivered" ? "Delivered steering to worker Pi" : event.type === "pi.rpc.steering.poll.failed" ? "Worker Pi steering poll failed" : "Pi RPC UI request auto-cancelled";
1842
+ const detail = event.type === "pi.rpc.prompt.sent" ? `${String(payload.kind ?? "prompt")} prompt (${String(payload.bytes ?? "unknown")} bytes)` : event.type === "pi.rpc.steering.delivered" ? `${String(payload.actor ?? "operator")}: ${String(payload.message ?? "")}`.slice(0, 500) : event.type === "pi.rpc.steering.poll.failed" ? String(payload.error ?? "steering poll failed") : `${String(payload.method ?? "ui")}: ${String(payload.reason ?? "noninteractive worker session")}`;
1843
+ appendRunLog(context.projectRoot, input.runId, {
1844
+ id: nextRunLogId(),
1845
+ title,
1846
+ detail,
1847
+ tone: event.type === "pi.rpc.steering.poll.failed" ? "error" : "info",
1848
+ status: reviewStarted ? "reviewing" : verificationStarted ? "validating" : "running",
1849
+ payload,
1850
+ createdAt: new Date().toISOString()
1851
+ });
1852
+ emitServerRunEvent({ type: "log", runId: input.runId, title });
1853
+ return true;
1854
+ }
1732
1855
  return false;
1733
1856
  };
1734
- const nextRunLogId = createRunLogIdFactory(input.runId);
1735
1857
  const handleAgentStdoutLine = (line) => {
1736
1858
  const trimmed = line.trim();
1737
1859
  if (!trimmed)
@@ -1765,6 +1887,15 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
1765
1887
  try {
1766
1888
  const record = JSON.parse(trimmed);
1767
1889
  const liveLogStatus = reviewStarted ? "reviewing" : verificationStarted ? "validating" : "running";
1890
+ if (input.runtimeAdapter === "pi" && appendPiRpcProtocolLogFromRecord({
1891
+ projectRoot: context.projectRoot,
1892
+ runId: input.runId,
1893
+ record,
1894
+ status: liveLogStatus,
1895
+ nextRunLogId
1896
+ })) {
1897
+ return;
1898
+ }
1768
1899
  if (input.runtimeAdapter === "pi" && appendPiToolTimelineFromRecord({ projectRoot: context.projectRoot, runId: input.runId, record })) {
1769
1900
  emitServerRunEvent({ type: "timeline", runId: input.runId });
1770
1901
  return;
@@ -2237,7 +2368,7 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
2237
2368
  startedAt,
2238
2369
  finishedAt: requestedAt
2239
2370
  });
2240
- return;
2371
+ process.exit(0);
2241
2372
  }
2242
2373
  const runPiPrFeedbackFix = async (message) => {
2243
2374
  appendPiStageLog({