patchrelay 0.8.6 → 0.8.8

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "service": "patchrelay",
3
- "version": "0.8.6",
4
- "commit": "c79c544a7789",
5
- "builtAt": "2026-03-19T11:44:33.599Z"
3
+ "version": "0.8.8",
4
+ "commit": "bb19f4030c2a",
5
+ "builtAt": "2026-03-19T12:17:38.751Z"
6
6
  }
@@ -22,6 +22,7 @@ export class CodexAppServerClient extends EventEmitter {
22
22
  config;
23
23
  logger;
24
24
  spawnProcess;
25
+ static DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
25
26
  child;
26
27
  nextRequestId = 1;
27
28
  pending = new Map();
@@ -210,8 +211,25 @@ export class CodexAppServerClient extends EventEmitter {
210
211
  throw new Error("Codex app-server is not running");
211
212
  }
212
213
  const id = this.nextRequestId++;
214
+ const requestTimeoutMs = this.config.requestTimeoutMs ?? CodexAppServerClient.DEFAULT_REQUEST_TIMEOUT_MS;
213
215
  const promise = new Promise((resolve, reject) => {
214
- this.pending.set(id, { resolve, reject });
216
+ const timeout = setTimeout(() => {
217
+ if (!this.pending.delete(id)) {
218
+ return;
219
+ }
220
+ reject(new Error(`Codex app-server request timed out after ${requestTimeoutMs}ms`));
221
+ }, requestTimeoutMs);
222
+ timeout.unref?.();
223
+ this.pending.set(id, {
224
+ resolve: (value) => {
225
+ clearTimeout(timeout);
226
+ resolve(value);
227
+ },
228
+ reject: (error) => {
229
+ clearTimeout(timeout);
230
+ reject(error);
231
+ },
232
+ });
215
233
  });
216
234
  this.writeMessage({
217
235
  jsonrpc: "2.0",
package/dist/config.js CHANGED
@@ -114,6 +114,7 @@ const configSchema = z.object({
114
114
  args: z.array(z.string()).default(["app-server"]),
115
115
  shell_bin: z.string().optional(),
116
116
  source_bashrc: z.boolean().default(true),
117
+ request_timeout_ms: z.number().int().positive().default(30000),
117
118
  model: z.string().optional(),
118
119
  model_provider: z.string().optional(),
119
120
  service_name: z.string().default("patchrelay"),
@@ -461,6 +462,7 @@ export function loadConfig(configPath = process.env.PATCHRELAY_CONFIG ?? getDefa
461
462
  args: parsed.runner.codex.args,
462
463
  ...(parsed.runner.codex.shell_bin ? { shellBin: parsed.runner.codex.shell_bin } : {}),
463
464
  sourceBashrc: parsed.runner.codex.source_bashrc,
465
+ requestTimeoutMs: parsed.runner.codex.request_timeout_ms,
464
466
  ...(parsed.runner.codex.model ? { model: parsed.runner.codex.model } : {}),
465
467
  ...(parsed.runner.codex.model_provider ? { modelProvider: parsed.runner.codex.model_provider } : {}),
466
468
  ...(parsed.runner.codex.service_name ? { serviceName: parsed.runner.codex.service_name } : {}),
@@ -552,10 +552,27 @@ export class ServiceStageFinalizer {
552
552
  }
553
553
  async restartInterruptedRun(snapshot) {
554
554
  const liveCodex = snapshot.input.live?.codex;
555
+ const liveLinear = snapshot.input.live?.linear;
555
556
  const latestTurn = liveCodex?.status === "found" ? liveCodex.thread?.turns.at(-1) : undefined;
556
557
  if (latestTurn?.status !== "interrupted") {
557
558
  return false;
558
559
  }
560
+ if (liveLinear?.status === "known") {
561
+ const authoritativeStopState = resolveAuthoritativeLinearStopState({
562
+ ...(liveLinear.issue?.stateName ? { stateName: liveLinear.issue.stateName } : {}),
563
+ workflowStates: liveLinear.issue?.stateName
564
+ ? [
565
+ {
566
+ name: liveLinear.issue.stateName,
567
+ ...(liveLinear.issue.stateType ? { type: liveLinear.issue.stateType } : {}),
568
+ },
569
+ ]
570
+ : [],
571
+ });
572
+ if (authoritativeStopState) {
573
+ return false;
574
+ }
575
+ }
559
576
  if (snapshot.runLease.turnId && latestTurn.id !== snapshot.runLease.turnId) {
560
577
  return true;
561
578
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchrelay",
3
- "version": "0.8.6",
3
+ "version": "0.8.8",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {