patchrelay 0.12.7 → 0.12.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.
- package/dist/build-info.json +3 -3
- package/dist/codex-app-server.js +29 -3
- package/dist/http.js +8 -5
- package/dist/index.js +8 -7
- package/dist/service-runtime.js +2 -2
- package/dist/service.js +2 -2
- package/dist/webhook-handler.js +4 -2
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
package/dist/codex-app-server.js
CHANGED
|
@@ -48,6 +48,15 @@ export class CodexAppServerClient extends EventEmitter {
|
|
|
48
48
|
this.child = this.spawnProcess(launch.command, launch.args, {
|
|
49
49
|
stdio: ["pipe", "pipe", "pipe"],
|
|
50
50
|
});
|
|
51
|
+
this.child.stdin.on("error", (error) => {
|
|
52
|
+
this.logger.error({ error: sanitizeDiagnosticText(error.message) }, "Codex app-server stdin error");
|
|
53
|
+
});
|
|
54
|
+
this.child.stdout.on("error", (error) => {
|
|
55
|
+
this.logger.error({ error: sanitizeDiagnosticText(error.message) }, "Codex app-server stdout error");
|
|
56
|
+
});
|
|
57
|
+
this.child.stderr.on("error", (error) => {
|
|
58
|
+
this.logger.error({ error: sanitizeDiagnosticText(error.message) }, "Codex app-server stderr error");
|
|
59
|
+
});
|
|
51
60
|
this.child.stderr.on("data", (chunk) => {
|
|
52
61
|
const line = chunk.toString().trim();
|
|
53
62
|
if (line) {
|
|
@@ -75,6 +84,13 @@ export class CodexAppServerClient extends EventEmitter {
|
|
|
75
84
|
});
|
|
76
85
|
this.child.stdout.on("data", (chunk) => {
|
|
77
86
|
this.stdoutBuffer += chunk.toString("utf8");
|
|
87
|
+
if (this.stdoutBuffer.length > 50 * 1024 * 1024) {
|
|
88
|
+
this.logger.error({ bufferSize: this.stdoutBuffer.length }, "Codex app-server stdout buffer exceeded 50 MB — killing process");
|
|
89
|
+
this.stdoutBuffer = "";
|
|
90
|
+
this.rejectAllPending(new Error("Codex app-server stdout buffer overflow"));
|
|
91
|
+
this.child?.kill("SIGTERM");
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
78
94
|
this.drainMessages();
|
|
79
95
|
});
|
|
80
96
|
const initializeResponse = await this.sendRequest("initialize", {
|
|
@@ -96,14 +112,24 @@ export class CodexAppServerClient extends EventEmitter {
|
|
|
96
112
|
this.started = true;
|
|
97
113
|
}
|
|
98
114
|
async stop() {
|
|
99
|
-
|
|
115
|
+
const child = this.child;
|
|
116
|
+
if (!child) {
|
|
100
117
|
return;
|
|
101
118
|
}
|
|
102
119
|
this.logger.info("Stopping Codex app-server");
|
|
103
120
|
this.stopping = true;
|
|
104
|
-
this.child.kill("SIGTERM");
|
|
105
|
-
this.child = undefined;
|
|
106
121
|
this.started = false;
|
|
122
|
+
const exited = new Promise((resolve) => {
|
|
123
|
+
child.on("close", () => resolve());
|
|
124
|
+
});
|
|
125
|
+
child.kill("SIGTERM");
|
|
126
|
+
this.child = undefined;
|
|
127
|
+
// Wait for the child to exit, but don't block shutdown forever.
|
|
128
|
+
const timeout = new Promise((resolve) => {
|
|
129
|
+
const timer = setTimeout(resolve, 10_000);
|
|
130
|
+
timer.unref?.();
|
|
131
|
+
});
|
|
132
|
+
await Promise.race([exited, timeout]);
|
|
107
133
|
}
|
|
108
134
|
async startThread(options) {
|
|
109
135
|
const params = {
|
package/dist/http.js
CHANGED
|
@@ -312,6 +312,12 @@ export async function buildHttpServer(config, service, logger) {
|
|
|
312
312
|
for (const event of service.listOperatorFeed(feedQuery)) {
|
|
313
313
|
writeEvent(event);
|
|
314
314
|
}
|
|
315
|
+
const cleanup = () => {
|
|
316
|
+
clearInterval(keepAlive);
|
|
317
|
+
unsubscribe();
|
|
318
|
+
if (!reply.raw.destroyed)
|
|
319
|
+
reply.raw.end();
|
|
320
|
+
};
|
|
315
321
|
const unsubscribe = service.subscribeOperatorFeed((event) => {
|
|
316
322
|
if (!matchesOperatorFeedEvent(event, feedQuery)) {
|
|
317
323
|
return;
|
|
@@ -321,11 +327,8 @@ export async function buildHttpServer(config, service, logger) {
|
|
|
321
327
|
const keepAlive = setInterval(() => {
|
|
322
328
|
reply.raw.write(": keepalive\n\n");
|
|
323
329
|
}, 15000);
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
unsubscribe();
|
|
327
|
-
reply.raw.end();
|
|
328
|
-
});
|
|
330
|
+
reply.raw.on("error", cleanup);
|
|
331
|
+
request.raw.on("close", cleanup);
|
|
329
332
|
});
|
|
330
333
|
app.get("/api/installations", async (_request, reply) => {
|
|
331
334
|
return reply.send({ ok: true, installations: service.listLinearInstallations() });
|
package/dist/index.js
CHANGED
|
@@ -62,15 +62,16 @@ async function main() {
|
|
|
62
62
|
secrets: config.secretSources,
|
|
63
63
|
}, "PatchRelay started");
|
|
64
64
|
const shutdown = async () => {
|
|
65
|
-
service.stop();
|
|
65
|
+
await service.stop();
|
|
66
66
|
await app.close();
|
|
67
67
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
const onSignal = (signal) => {
|
|
69
|
+
shutdown().catch((error) => {
|
|
70
|
+
logger.error({ signal, error: error instanceof Error ? error.message : String(error) }, "Shutdown error");
|
|
71
|
+
}).finally(() => { process.exitCode ??= 0; });
|
|
72
|
+
};
|
|
73
|
+
process.once("SIGINT", () => onSignal("SIGINT"));
|
|
74
|
+
process.once("SIGTERM", () => onSignal("SIGTERM"));
|
|
74
75
|
}
|
|
75
76
|
main().catch((error) => {
|
|
76
77
|
process.stderr.write(`${error instanceof Error ? error.stack : String(error)}\n`);
|
package/dist/service-runtime.js
CHANGED
|
@@ -44,10 +44,10 @@ export class ServiceRuntime {
|
|
|
44
44
|
throw error;
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
stop() {
|
|
47
|
+
async stop() {
|
|
48
48
|
this.ready = false;
|
|
49
49
|
this.clearBackgroundReconcile();
|
|
50
|
-
|
|
50
|
+
await this.codex.stop();
|
|
51
51
|
}
|
|
52
52
|
enqueueWebhookEvent(eventId, options) {
|
|
53
53
|
this.webhookQueue.enqueue(eventId, options);
|
package/dist/service.js
CHANGED
|
@@ -115,9 +115,9 @@ export class PatchRelayService {
|
|
|
115
115
|
await this.runtime.start();
|
|
116
116
|
this.mergeQueue.seedOnStartup();
|
|
117
117
|
}
|
|
118
|
-
stop() {
|
|
118
|
+
async stop() {
|
|
119
119
|
this.githubAppTokenManager?.stop();
|
|
120
|
-
this.runtime.stop();
|
|
120
|
+
await this.runtime.stop();
|
|
121
121
|
}
|
|
122
122
|
async createLinearOAuthStart(params) {
|
|
123
123
|
return await this.oauthService.createStart(params);
|
package/dist/webhook-handler.js
CHANGED
|
@@ -230,7 +230,8 @@ export class WebhookHandler {
|
|
|
230
230
|
summary: `Delivered follow-up prompt to active ${activeRun.runType} workflow`,
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
|
-
catch {
|
|
233
|
+
catch (error) {
|
|
234
|
+
this.logger.warn({ issueKey: trackedIssue?.issueKey, error: error instanceof Error ? error.message : String(error) }, "Failed to deliver follow-up prompt");
|
|
234
235
|
this.feed?.publish({
|
|
235
236
|
level: "warn",
|
|
236
237
|
kind: "agent",
|
|
@@ -288,7 +289,8 @@ export class WebhookHandler {
|
|
|
288
289
|
summary: `Delivered follow-up comment to active ${run.runType} workflow`,
|
|
289
290
|
});
|
|
290
291
|
}
|
|
291
|
-
catch {
|
|
292
|
+
catch (error) {
|
|
293
|
+
this.logger.warn({ issueKey: trackedIssue?.issueKey, error: error instanceof Error ? error.message : String(error) }, "Failed to deliver follow-up comment");
|
|
292
294
|
this.feed?.publish({
|
|
293
295
|
level: "warn",
|
|
294
296
|
kind: "comment",
|