@trim21/personal-pi-extensions 0.1.517 → 0.1.518

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/gh-readonly.ts +18 -75
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trim21/personal-pi-extensions",
3
- "version": "0.1.517",
3
+ "version": "0.1.518",
4
4
  "type": "module",
5
5
  "description": "Custom pi coding-agent extensions: bwrap sandbox, workspace guard, opencode edit, and more",
6
6
  "keywords": [
@@ -1134,86 +1134,30 @@ const PR_CHECKS_JSON_FIELDS = "name,state,bucket,startedAt,completedAt,link,work
1134
1134
  const CHECKS_POLL_INTERVAL_MS = 30_000;
1135
1135
  const CHECKS_WATCH_DEADLINE_MS = 600_000;
1136
1136
 
1137
- function bucketIcon(bucket: string): string {
1138
- switch (bucket) {
1139
- case "pass": {
1140
- return "✅";
1141
- }
1142
- case "fail": {
1143
- return "❌";
1144
- }
1145
- case "skipping": {
1146
- return "⏭️";
1147
- }
1148
- case "cancel": {
1149
- return "🚫";
1150
- }
1151
- default: {
1152
- return "🔄";
1153
- }
1154
- }
1155
- }
1156
-
1157
- function formatClock(ms: number): string {
1158
- const date = new Date(ms);
1159
- return [date.getHours(), date.getMinutes(), date.getSeconds()]
1160
- .map((n) => String(n).padStart(2, "0"))
1161
- .join(":");
1162
- }
1163
-
1164
- function pad2(n: number): string {
1165
- return String(n).padStart(2, "0");
1166
- }
1167
-
1168
- function formatDuration(totalSeconds: number): string {
1169
- const seconds = Math.floor(totalSeconds);
1170
- const h = Math.floor(seconds / 3600);
1171
- const m = Math.floor((seconds % 3600) / 60);
1172
- const s = seconds % 60;
1173
- if (h > 0) return `${h}h${pad2(m)}m${pad2(s)}s`;
1174
- if (m > 0) return `${m}m${pad2(s)}s`;
1175
- return `${s}s`;
1176
- }
1177
-
1178
1137
  /**
1179
- * Render one polling round of `gh pr checks` like the GitHub web UI: check
1180
- * name, workflow, status, start time and elapsed (total duration when the
1181
- * check completed, time-so-far while still pending). Pureno network.
1138
+ * Render one polling round of `gh pr checks` as a compact bullet list of the
1139
+ * checks still in flight: running ones first (`- [>]`), queued ones after
1140
+ * (`- [ ]`). Completed checks are hiddenthe header already reports the
1141
+ * completion count. Pure — no network.
1182
1142
  */
1183
- export function renderPrChecksTable(options: {
1143
+ export function renderPrChecksList(options: {
1184
1144
  prNumber: number | string;
1185
1145
  round: number;
1186
1146
  checks: readonly PrCheck[];
1187
- now: number;
1188
1147
  }): string {
1189
- const { prNumber, round, checks, now } = options;
1148
+ const { prNumber, round, checks } = options;
1190
1149
  const completed = checks.filter((c) => c.bucket !== "pending").length;
1191
1150
 
1192
- const rows = checks.map((check) => {
1151
+ const pending = checks.filter((c) => c.bucket === "pending");
1152
+ const ordered = [...pending.filter((c) => c.startedAt), ...pending.filter((c) => !c.startedAt)];
1153
+ const lines = ordered.map((check) => {
1193
1154
  const name = check.link ? `[${check.name}](${check.link})` : check.name;
1194
- let elapsed = "";
1195
- if (check.startedAt) {
1196
- const startMs = Date.parse(check.startedAt);
1197
- const endMs = check.completedAt ? Date.parse(check.completedAt) : now;
1198
- elapsed = formatDuration(Math.max(0, (endMs - startMs) / 1000));
1199
- }
1200
- const cells = [
1201
- `${bucketIcon(check.bucket)} ${name}`,
1202
- check.workflow ?? "—",
1203
- check.bucket,
1204
- check.startedAt ? formatClock(Date.parse(check.startedAt)) : "—",
1205
- elapsed,
1206
- ];
1207
- return `| ${cells.join(" | ")} |`;
1155
+ return `- [${check.startedAt ? ">" : " "}] ${name}`;
1208
1156
  });
1209
- const body = rows.length > 0 ? rows.join("\n") : "| _no checks reported_ | — | — | — | — |";
1157
+ const body =
1158
+ checks.length === 0 ? "- _no checks reported_" : lines.length > 0 ? lines.join("\n") : "";
1210
1159
 
1211
- return (
1212
- `### PR #${prNumber} checks — round ${round}: ${completed}/${checks.length} complete\n\n` +
1213
- `| Check | Workflow | Status | Started | Elapsed |\n` +
1214
- `|---|---|---|---|---|\n` +
1215
- body
1216
- );
1160
+ return `### PR #${prNumber} checks — round ${round}: ${completed}/${checks.length} complete${body ? `\n\n${body}` : ""}`;
1217
1161
  }
1218
1162
 
1219
1163
  function sleepInterruptibly(ms: number, signal: AbortSignal | undefined): Promise<void> {
@@ -1248,8 +1192,9 @@ export interface PollPrChecksOptions {
1248
1192
 
1249
1193
  /**
1250
1194
  * Poll `gh pr checks --json` until no check is pending (or a fail-fast
1251
- * failure, or the deadline), emitting a GitHub-UI-like table via `onUpdate`
1252
- * each round. In JSON mode gh exits 0 whenever it could fetch the checks —
1195
+ * failure, or the deadline), emitting a compact list of in-flight checks via
1196
+ * `onUpdate` each round. In JSON mode gh exits 0 whenever it could fetch the
1197
+ * checks —
1253
1198
  * completion is judged from the `bucket` field, not the exit code. A non-zero
1254
1199
  * exit (no checks reported, auth, network) is not fatal here: the caller
1255
1200
  * proceeds to the Actions API verification, which either produces the final
@@ -1282,9 +1227,7 @@ export async function pollPrChecks(options: PollPrChecksOptions): Promise<void>
1282
1227
  const checks: PrCheck[] = Value.Parse(Type.Array(prCheckSchema), JSON.parse(result.stdout));
1283
1228
 
1284
1229
  onUpdate?.({
1285
- content: [
1286
- { type: "text", text: renderPrChecksTable({ prNumber, round, checks, now: Date.now() }) },
1287
- ],
1230
+ content: [{ type: "text", text: renderPrChecksList({ prNumber, round, checks }) }],
1288
1231
  details: {},
1289
1232
  });
1290
1233
 
@@ -1852,7 +1795,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1852
1795
  label: "Watch GitHub PR Checks",
1853
1796
  description:
1854
1797
  "Watch CI status checks for a PR until they complete. Blocks until all checks finish or one fails. " +
1855
- "Each polling round streams a GitHub-UI-like check table (name, workflow, status, started, elapsed) via onUpdate. " +
1798
+ "Each polling round streams a compact bullet list of the checks still in flight via onUpdate. " +
1856
1799
  "Use this when you need to wait for CI to complete and see the final result.",
1857
1800
  promptSnippet: "Watch and wait for GitHub PR CI checks to complete",
1858
1801
  parameters: Type.Object({