@trim21/personal-pi-extensions 0.0.126 → 0.0.127
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/package.json +1 -1
- package/src/gh-readonly.ts +66 -7
package/package.json
CHANGED
package/src/gh-readonly.ts
CHANGED
|
@@ -141,6 +141,60 @@ export class GhError extends Error {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
/** How long `read-github-pr-status` waits for pending checks to resolve. */
|
|
145
|
+
const POLL_INTERVAL_MS = 30_000;
|
|
146
|
+
const POLL_TIMEOUT_MS = 30 * 60_000;
|
|
147
|
+
|
|
148
|
+
/** Sleep for `ms`, resolving early if `signal` is aborted. */
|
|
149
|
+
function sleep(ms: number, signal?: AbortSignal): Promise<void> {
|
|
150
|
+
return new Promise((resolve) => {
|
|
151
|
+
if (signal?.aborted) {
|
|
152
|
+
resolve();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const onAbort = () => {
|
|
156
|
+
clearTimeout(timer);
|
|
157
|
+
resolve();
|
|
158
|
+
};
|
|
159
|
+
const timer = setTimeout(() => {
|
|
160
|
+
signal?.removeEventListener("abort", onAbort);
|
|
161
|
+
resolve();
|
|
162
|
+
}, ms);
|
|
163
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Poll a `gh pr checks` query until it reaches a final state.
|
|
169
|
+
*
|
|
170
|
+
* `gh pr checks` exit codes: 0 = all passed, 1 = some failed, 8 = some pending.
|
|
171
|
+
* Pending (8) is polled every `intervalMs` until `timeoutMs` elapses, at which
|
|
172
|
+
* point the current result is returned as-is. Any other code is returned
|
|
173
|
+
* immediately; the caller decides whether it is an error.
|
|
174
|
+
*/
|
|
175
|
+
export async function pollChecksResult<R extends { code: number; stdout: string }>(
|
|
176
|
+
query: () => Promise<R>,
|
|
177
|
+
opts: { signal?: AbortSignal; intervalMs?: number; timeoutMs?: number } = {},
|
|
178
|
+
): Promise<R> {
|
|
179
|
+
const { signal, intervalMs = POLL_INTERVAL_MS, timeoutMs = POLL_TIMEOUT_MS } = opts;
|
|
180
|
+
const deadline = Date.now() + timeoutMs;
|
|
181
|
+
for (;;) {
|
|
182
|
+
if (signal?.aborted) {
|
|
183
|
+
throw new Error("read-github-pr-status aborted");
|
|
184
|
+
}
|
|
185
|
+
const result = await query();
|
|
186
|
+
if (result.code !== 8) {
|
|
187
|
+
// 0 = all passed, 1 = some failed, anything else is a real error
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
// Still pending — keep waiting unless the overall timeout expired
|
|
191
|
+
if (Date.now() >= deadline) {
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
194
|
+
await sleep(intervalMs, signal);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
144
198
|
/** Run `gh` and return stdout. On non-zero exit, throws a `GhError` carrying the toolcall input and raw command. */
|
|
145
199
|
async function ghExec(
|
|
146
200
|
args: string[],
|
|
@@ -592,13 +646,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
592
646
|
}),
|
|
593
647
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
594
648
|
const { number, repo } = params;
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
649
|
+
const args = ["pr", "checks", String(number), ...repoArgs(repo)];
|
|
650
|
+
|
|
651
|
+
// Pending is not an error — poll until checks fail or all pass.
|
|
652
|
+
const final = await pollChecksResult(() => runGh(args, { cwd: ctx.cwd, signal }), {
|
|
653
|
+
signal,
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
if (final.code !== 0 && final.code !== 1 && final.code !== 8) {
|
|
657
|
+
// Anything else is a real error (cancelled, auth, network, ...)
|
|
658
|
+
throw new GhError(args, final, params);
|
|
659
|
+
}
|
|
660
|
+
return toToolResult(final.stdout);
|
|
602
661
|
},
|
|
603
662
|
});
|
|
604
663
|
|