remote-ralph 0.1.0
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/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/index.js +1732 -0
- package/package.json +45 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1732 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
|
|
28
|
+
// node_modules/.pnpm/shell-quote@1.8.3/node_modules/shell-quote/quote.js
|
|
29
|
+
var require_quote = __commonJS({
|
|
30
|
+
"node_modules/.pnpm/shell-quote@1.8.3/node_modules/shell-quote/quote.js"(exports, module) {
|
|
31
|
+
"use strict";
|
|
32
|
+
module.exports = function quote(xs) {
|
|
33
|
+
return xs.map(function(s) {
|
|
34
|
+
if (s === "") {
|
|
35
|
+
return "''";
|
|
36
|
+
}
|
|
37
|
+
if (s && typeof s === "object") {
|
|
38
|
+
return s.op.replace(/(.)/g, "\\$1");
|
|
39
|
+
}
|
|
40
|
+
if (/["\s\\]/.test(s) && !/'/.test(s)) {
|
|
41
|
+
return "'" + s.replace(/(['])/g, "\\$1") + "'";
|
|
42
|
+
}
|
|
43
|
+
if (/["'\s]/.test(s)) {
|
|
44
|
+
return '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"';
|
|
45
|
+
}
|
|
46
|
+
return String(s).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
|
|
47
|
+
}).join(" ");
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// node_modules/.pnpm/shell-quote@1.8.3/node_modules/shell-quote/parse.js
|
|
53
|
+
var require_parse = __commonJS({
|
|
54
|
+
"node_modules/.pnpm/shell-quote@1.8.3/node_modules/shell-quote/parse.js"(exports, module) {
|
|
55
|
+
"use strict";
|
|
56
|
+
var CONTROL = "(?:" + [
|
|
57
|
+
"\\|\\|",
|
|
58
|
+
"\\&\\&",
|
|
59
|
+
";;",
|
|
60
|
+
"\\|\\&",
|
|
61
|
+
"\\<\\(",
|
|
62
|
+
"\\<\\<\\<",
|
|
63
|
+
">>",
|
|
64
|
+
">\\&",
|
|
65
|
+
"<\\&",
|
|
66
|
+
"[&;()|<>]"
|
|
67
|
+
].join("|") + ")";
|
|
68
|
+
var controlRE = new RegExp("^" + CONTROL + "$");
|
|
69
|
+
var META = "|&;()<> \\t";
|
|
70
|
+
var SINGLE_QUOTE = '"((\\\\"|[^"])*?)"';
|
|
71
|
+
var DOUBLE_QUOTE = "'((\\\\'|[^'])*?)'";
|
|
72
|
+
var hash = /^#$/;
|
|
73
|
+
var SQ = "'";
|
|
74
|
+
var DQ = '"';
|
|
75
|
+
var DS = "$";
|
|
76
|
+
var TOKEN = "";
|
|
77
|
+
var mult = 4294967296;
|
|
78
|
+
for (i = 0; i < 4; i++) {
|
|
79
|
+
TOKEN += (mult * Math.random()).toString(16);
|
|
80
|
+
}
|
|
81
|
+
var i;
|
|
82
|
+
var startsWithToken = new RegExp("^" + TOKEN);
|
|
83
|
+
function matchAll(s, r) {
|
|
84
|
+
var origIndex = r.lastIndex;
|
|
85
|
+
var matches = [];
|
|
86
|
+
var matchObj;
|
|
87
|
+
while (matchObj = r.exec(s)) {
|
|
88
|
+
matches.push(matchObj);
|
|
89
|
+
if (r.lastIndex === matchObj.index) {
|
|
90
|
+
r.lastIndex += 1;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
r.lastIndex = origIndex;
|
|
94
|
+
return matches;
|
|
95
|
+
}
|
|
96
|
+
function getVar(env, pre, key) {
|
|
97
|
+
var r = typeof env === "function" ? env(key) : env[key];
|
|
98
|
+
if (typeof r === "undefined" && key != "") {
|
|
99
|
+
r = "";
|
|
100
|
+
} else if (typeof r === "undefined") {
|
|
101
|
+
r = "$";
|
|
102
|
+
}
|
|
103
|
+
if (typeof r === "object") {
|
|
104
|
+
return pre + TOKEN + JSON.stringify(r) + TOKEN;
|
|
105
|
+
}
|
|
106
|
+
return pre + r;
|
|
107
|
+
}
|
|
108
|
+
function parseInternal(string3, env, opts) {
|
|
109
|
+
if (!opts) {
|
|
110
|
+
opts = {};
|
|
111
|
+
}
|
|
112
|
+
var BS = opts.escape || "\\";
|
|
113
|
+
var BAREWORD = "(\\" + BS + `['"` + META + `]|[^\\s'"` + META + "])+";
|
|
114
|
+
var chunker = new RegExp([
|
|
115
|
+
"(" + CONTROL + ")",
|
|
116
|
+
// control chars
|
|
117
|
+
"(" + BAREWORD + "|" + SINGLE_QUOTE + "|" + DOUBLE_QUOTE + ")+"
|
|
118
|
+
].join("|"), "g");
|
|
119
|
+
var matches = matchAll(string3, chunker);
|
|
120
|
+
if (matches.length === 0) {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
if (!env) {
|
|
124
|
+
env = {};
|
|
125
|
+
}
|
|
126
|
+
var commented = false;
|
|
127
|
+
return matches.map(function(match) {
|
|
128
|
+
var s = match[0];
|
|
129
|
+
if (!s || commented) {
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
if (controlRE.test(s)) {
|
|
133
|
+
return { op: s };
|
|
134
|
+
}
|
|
135
|
+
var quote = false;
|
|
136
|
+
var esc2 = false;
|
|
137
|
+
var out = "";
|
|
138
|
+
var isGlob = false;
|
|
139
|
+
var i2;
|
|
140
|
+
function parseEnvVar() {
|
|
141
|
+
i2 += 1;
|
|
142
|
+
var varend;
|
|
143
|
+
var varname;
|
|
144
|
+
var char = s.charAt(i2);
|
|
145
|
+
if (char === "{") {
|
|
146
|
+
i2 += 1;
|
|
147
|
+
if (s.charAt(i2) === "}") {
|
|
148
|
+
throw new Error("Bad substitution: " + s.slice(i2 - 2, i2 + 1));
|
|
149
|
+
}
|
|
150
|
+
varend = s.indexOf("}", i2);
|
|
151
|
+
if (varend < 0) {
|
|
152
|
+
throw new Error("Bad substitution: " + s.slice(i2));
|
|
153
|
+
}
|
|
154
|
+
varname = s.slice(i2, varend);
|
|
155
|
+
i2 = varend;
|
|
156
|
+
} else if (/[*@#?$!_-]/.test(char)) {
|
|
157
|
+
varname = char;
|
|
158
|
+
i2 += 1;
|
|
159
|
+
} else {
|
|
160
|
+
var slicedFromI = s.slice(i2);
|
|
161
|
+
varend = slicedFromI.match(/[^\w\d_]/);
|
|
162
|
+
if (!varend) {
|
|
163
|
+
varname = slicedFromI;
|
|
164
|
+
i2 = s.length;
|
|
165
|
+
} else {
|
|
166
|
+
varname = slicedFromI.slice(0, varend.index);
|
|
167
|
+
i2 += varend.index - 1;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return getVar(env, "", varname);
|
|
171
|
+
}
|
|
172
|
+
for (i2 = 0; i2 < s.length; i2++) {
|
|
173
|
+
var c = s.charAt(i2);
|
|
174
|
+
isGlob = isGlob || !quote && (c === "*" || c === "?");
|
|
175
|
+
if (esc2) {
|
|
176
|
+
out += c;
|
|
177
|
+
esc2 = false;
|
|
178
|
+
} else if (quote) {
|
|
179
|
+
if (c === quote) {
|
|
180
|
+
quote = false;
|
|
181
|
+
} else if (quote == SQ) {
|
|
182
|
+
out += c;
|
|
183
|
+
} else {
|
|
184
|
+
if (c === BS) {
|
|
185
|
+
i2 += 1;
|
|
186
|
+
c = s.charAt(i2);
|
|
187
|
+
if (c === DQ || c === BS || c === DS) {
|
|
188
|
+
out += c;
|
|
189
|
+
} else {
|
|
190
|
+
out += BS + c;
|
|
191
|
+
}
|
|
192
|
+
} else if (c === DS) {
|
|
193
|
+
out += parseEnvVar();
|
|
194
|
+
} else {
|
|
195
|
+
out += c;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
} else if (c === DQ || c === SQ) {
|
|
199
|
+
quote = c;
|
|
200
|
+
} else if (controlRE.test(c)) {
|
|
201
|
+
return { op: s };
|
|
202
|
+
} else if (hash.test(c)) {
|
|
203
|
+
commented = true;
|
|
204
|
+
var commentObj = { comment: string3.slice(match.index + i2 + 1) };
|
|
205
|
+
if (out.length) {
|
|
206
|
+
return [out, commentObj];
|
|
207
|
+
}
|
|
208
|
+
return [commentObj];
|
|
209
|
+
} else if (c === BS) {
|
|
210
|
+
esc2 = true;
|
|
211
|
+
} else if (c === DS) {
|
|
212
|
+
out += parseEnvVar();
|
|
213
|
+
} else {
|
|
214
|
+
out += c;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (isGlob) {
|
|
218
|
+
return { op: "glob", pattern: out };
|
|
219
|
+
}
|
|
220
|
+
return out;
|
|
221
|
+
}).reduce(function(prev, arg) {
|
|
222
|
+
return typeof arg === "undefined" ? prev : prev.concat(arg);
|
|
223
|
+
}, []);
|
|
224
|
+
}
|
|
225
|
+
module.exports = function parse3(s, env, opts) {
|
|
226
|
+
var mapped = parseInternal(s, env, opts);
|
|
227
|
+
if (typeof env !== "function") {
|
|
228
|
+
return mapped;
|
|
229
|
+
}
|
|
230
|
+
return mapped.reduce(function(acc, s2) {
|
|
231
|
+
if (typeof s2 === "object") {
|
|
232
|
+
return acc.concat(s2);
|
|
233
|
+
}
|
|
234
|
+
var xs = s2.split(RegExp("(" + TOKEN + ".*?" + TOKEN + ")", "g"));
|
|
235
|
+
if (xs.length === 1) {
|
|
236
|
+
return acc.concat(xs[0]);
|
|
237
|
+
}
|
|
238
|
+
return acc.concat(xs.filter(Boolean).map(function(x) {
|
|
239
|
+
if (startsWithToken.test(x)) {
|
|
240
|
+
return JSON.parse(x.split(TOKEN)[1]);
|
|
241
|
+
}
|
|
242
|
+
return x;
|
|
243
|
+
}));
|
|
244
|
+
}, []);
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// node_modules/.pnpm/shell-quote@1.8.3/node_modules/shell-quote/index.js
|
|
250
|
+
var require_shell_quote = __commonJS({
|
|
251
|
+
"node_modules/.pnpm/shell-quote@1.8.3/node_modules/shell-quote/index.js"(exports) {
|
|
252
|
+
"use strict";
|
|
253
|
+
exports.quote = require_quote();
|
|
254
|
+
exports.parse = require_parse();
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// src/index.ts
|
|
259
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
260
|
+
import { resolve } from "node:path";
|
|
261
|
+
|
|
262
|
+
// src/logger.ts
|
|
263
|
+
var LEVEL_PRIORITY = {
|
|
264
|
+
error: 0,
|
|
265
|
+
warn: 1,
|
|
266
|
+
info: 2,
|
|
267
|
+
debug: 3
|
|
268
|
+
};
|
|
269
|
+
var createLogger = (level) => {
|
|
270
|
+
const threshold = LEVEL_PRIORITY[level];
|
|
271
|
+
const noop = () => {
|
|
272
|
+
};
|
|
273
|
+
return {
|
|
274
|
+
error: threshold >= LEVEL_PRIORITY.error ? (...args) => console.error(...args) : noop,
|
|
275
|
+
warn: threshold >= LEVEL_PRIORITY.warn ? (...args) => console.error(...args) : noop,
|
|
276
|
+
info: threshold >= LEVEL_PRIORITY.info ? (...args) => console.log(...args) : noop,
|
|
277
|
+
debug: threshold >= LEVEL_PRIORITY.debug ? (...args) => console.log(...args) : noop
|
|
278
|
+
};
|
|
279
|
+
};
|
|
280
|
+
var instance;
|
|
281
|
+
var initLogger = (level) => {
|
|
282
|
+
instance = createLogger(level);
|
|
283
|
+
return instance;
|
|
284
|
+
};
|
|
285
|
+
var logger = () => {
|
|
286
|
+
if (!instance) throw new Error("Logger not initialized \u2014 call initLogger() first");
|
|
287
|
+
return instance;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// src/sleep.ts
|
|
291
|
+
var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
292
|
+
|
|
293
|
+
// src/agent.ts
|
|
294
|
+
var import_shell_quote = __toESM(require_shell_quote(), 1);
|
|
295
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
296
|
+
|
|
297
|
+
// src/subprocess.ts
|
|
298
|
+
import { spawnSync } from "node:child_process";
|
|
299
|
+
var run = (command, options) => {
|
|
300
|
+
const result = spawnSync(command, {
|
|
301
|
+
shell: true,
|
|
302
|
+
cwd: options?.cwd,
|
|
303
|
+
timeout: options?.timeout,
|
|
304
|
+
encoding: "utf-8"
|
|
305
|
+
});
|
|
306
|
+
if (result.error && "code" in result.error && result.error.code === "ETIMEDOUT") {
|
|
307
|
+
return {
|
|
308
|
+
exitCode: 1,
|
|
309
|
+
stdout: result.stdout ?? "",
|
|
310
|
+
stderr: result.stderr ?? ""
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
return {
|
|
314
|
+
exitCode: result.status ?? 1,
|
|
315
|
+
stdout: result.stdout ?? "",
|
|
316
|
+
stderr: result.stderr ?? ""
|
|
317
|
+
};
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
// src/github.ts
|
|
321
|
+
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
322
|
+
var resetToMain = () => {
|
|
323
|
+
const commands = ["git checkout main", "git clean -fd", "git pull"];
|
|
324
|
+
for (const cmd of commands) {
|
|
325
|
+
const result = run(cmd);
|
|
326
|
+
if (result.exitCode !== 0) {
|
|
327
|
+
throw new Error(`'${cmd}' failed (exit ${result.exitCode}): ${result.stderr}`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
var isPrOpen = (prLink) => {
|
|
332
|
+
const result = run(`gh pr view "${prLink}" --json state`);
|
|
333
|
+
if (result.exitCode !== 0) {
|
|
334
|
+
throw new Error(`gh pr view failed (exit ${result.exitCode}): ${result.stderr}`);
|
|
335
|
+
}
|
|
336
|
+
const data = JSON.parse(result.stdout);
|
|
337
|
+
if (!isRecord(data) || typeof data.state !== "string") {
|
|
338
|
+
throw new Error(`Unexpected gh pr view response: ${result.stdout}`);
|
|
339
|
+
}
|
|
340
|
+
return data.state === "OPEN";
|
|
341
|
+
};
|
|
342
|
+
var parsePrLink = (prLink) => {
|
|
343
|
+
const match = prLink.match(/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/);
|
|
344
|
+
if (!match) return null;
|
|
345
|
+
return { owner: match[1], repo: match[2], number: parseInt(match[3], 10) };
|
|
346
|
+
};
|
|
347
|
+
var hasMergeConflicts = (prLink) => {
|
|
348
|
+
const result = run(`gh pr view "${prLink}" --json mergeable --jq .mergeable`);
|
|
349
|
+
if (result.exitCode !== 0) {
|
|
350
|
+
throw new Error(
|
|
351
|
+
`gh pr view failed (exit ${result.exitCode}): ${result.stderr}`
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
return result.stdout.trim() === "CONFLICTING";
|
|
355
|
+
};
|
|
356
|
+
var fetchPrAuthor = (prLink) => {
|
|
357
|
+
const result = run(`gh pr view "${prLink}" --json author --jq .author.login`);
|
|
358
|
+
if (result.exitCode !== 0) {
|
|
359
|
+
throw new Error(
|
|
360
|
+
`gh pr view failed (exit ${result.exitCode}): ${result.stderr}`
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
const username = result.stdout.trim();
|
|
364
|
+
if (!username) {
|
|
365
|
+
throw new Error("Could not determine PR author");
|
|
366
|
+
}
|
|
367
|
+
return username;
|
|
368
|
+
};
|
|
369
|
+
var isReviewThread = (value) => {
|
|
370
|
+
if (!isRecord(value)) return false;
|
|
371
|
+
if (typeof value.isResolved !== "boolean") return false;
|
|
372
|
+
if (typeof value.path !== "string") return false;
|
|
373
|
+
if (!isRecord(value.comments) || !Array.isArray(value.comments.nodes))
|
|
374
|
+
return false;
|
|
375
|
+
const nodes = value.comments.nodes;
|
|
376
|
+
return nodes.every(
|
|
377
|
+
(c) => isRecord(c) && typeof c.databaseId === "number" && typeof c.body === "string" && typeof c.url === "string"
|
|
378
|
+
);
|
|
379
|
+
};
|
|
380
|
+
var isReviewThreadsResponse = (value) => {
|
|
381
|
+
if (!isRecord(value)) return false;
|
|
382
|
+
if (!isRecord(value.data)) return false;
|
|
383
|
+
if (!isRecord(value.data.repository)) return false;
|
|
384
|
+
if (!isRecord(value.data.repository.pullRequest)) return false;
|
|
385
|
+
const pr = value.data.repository.pullRequest;
|
|
386
|
+
if (!isRecord(pr.reviewThreads) || !Array.isArray(pr.reviewThreads.nodes))
|
|
387
|
+
return false;
|
|
388
|
+
const nodes = pr.reviewThreads.nodes;
|
|
389
|
+
return nodes.every(isReviewThread);
|
|
390
|
+
};
|
|
391
|
+
var fetchActionableThreads = ({
|
|
392
|
+
prLink,
|
|
393
|
+
agentUsername,
|
|
394
|
+
allowlist,
|
|
395
|
+
requireMention
|
|
396
|
+
}) => {
|
|
397
|
+
const parsed = parsePrLink(prLink);
|
|
398
|
+
if (!parsed) {
|
|
399
|
+
throw new Error(`Invalid PR link: ${prLink}`);
|
|
400
|
+
}
|
|
401
|
+
const query = `query { repository(owner: "${parsed.owner}", name: "${parsed.repo}") { pullRequest(number: ${parsed.number}) { reviewThreads(first: 100) { nodes { isResolved path line comments(first: 100) { nodes { databaseId body url author { login } } } } } } } }`;
|
|
402
|
+
const result = run(`gh api graphql -f query='${query}'`);
|
|
403
|
+
if (result.exitCode !== 0) {
|
|
404
|
+
throw new Error(
|
|
405
|
+
`gh api graphql failed (exit ${result.exitCode}): ${result.stderr}`
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
const data = JSON.parse(result.stdout);
|
|
409
|
+
if (!isReviewThreadsResponse(data)) {
|
|
410
|
+
throw new Error(`Unexpected GraphQL response: ${result.stdout}`);
|
|
411
|
+
}
|
|
412
|
+
const threads = data.data.repository.pullRequest.reviewThreads.nodes;
|
|
413
|
+
const isUnresolved = (thread) => !thread.isResolved;
|
|
414
|
+
const stripNonAllowlisted = (thread) => {
|
|
415
|
+
if (allowlist.length === 0) return thread;
|
|
416
|
+
const filtered = thread.comments.nodes.filter((c) => {
|
|
417
|
+
const login = c.author?.login;
|
|
418
|
+
if (!login) return false;
|
|
419
|
+
if (login === agentUsername) return true;
|
|
420
|
+
return allowlist.includes(login);
|
|
421
|
+
});
|
|
422
|
+
return { ...thread, comments: { nodes: filtered } };
|
|
423
|
+
};
|
|
424
|
+
const hasReviewerAsLastCommenter = (thread) => {
|
|
425
|
+
const comments = thread.comments.nodes;
|
|
426
|
+
if (comments.length === 0) return false;
|
|
427
|
+
return comments[comments.length - 1].author?.login !== agentUsername;
|
|
428
|
+
};
|
|
429
|
+
const latestCommentMentionsBot = (thread) => {
|
|
430
|
+
if (!requireMention) return true;
|
|
431
|
+
const comments = thread.comments.nodes;
|
|
432
|
+
if (comments.length === 0) return false;
|
|
433
|
+
return comments[comments.length - 1].body.includes(`@${agentUsername}`);
|
|
434
|
+
};
|
|
435
|
+
const toActionableThread = (thread) => ({
|
|
436
|
+
path: thread.path,
|
|
437
|
+
line: thread.line ?? void 0,
|
|
438
|
+
comments: thread.comments.nodes.map((c) => ({
|
|
439
|
+
id: c.databaseId,
|
|
440
|
+
body: c.body,
|
|
441
|
+
url: c.url,
|
|
442
|
+
author: c.author?.login ?? "unknown"
|
|
443
|
+
}))
|
|
444
|
+
});
|
|
445
|
+
logger().debug("GitHub PR data response:\n" + JSON.stringify(threads, null, " "));
|
|
446
|
+
logger().debug("Agent git username (derived from PR author): " + agentUsername);
|
|
447
|
+
return threads.filter(isUnresolved).map(stripNonAllowlisted).filter(hasReviewerAsLastCommenter).filter(latestCommentMentionsBot).map(toActionableThread);
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
// src/agent.ts
|
|
451
|
+
var PROMPT_PLACEHOLDER = "{prompt}";
|
|
452
|
+
var runAgent = (commandTemplate, prompt) => {
|
|
453
|
+
const tokens = (0, import_shell_quote.parse)(commandTemplate).filter((t) => typeof t === "string");
|
|
454
|
+
const quoted = `"${prompt.replace(/"/g, '\\"')}"`;
|
|
455
|
+
const args = tokens.map((t) => t.replace(PROMPT_PLACEHOLDER, quoted));
|
|
456
|
+
const result = spawnSync2(args[0], args.slice(1), { encoding: "utf-8" });
|
|
457
|
+
return {
|
|
458
|
+
exitCode: result.status ?? 1,
|
|
459
|
+
stdout: result.stdout ?? "",
|
|
460
|
+
stderr: result.stderr ?? ""
|
|
461
|
+
};
|
|
462
|
+
};
|
|
463
|
+
var PR_URL_PATTERN = /https:\/\/github\.com\/[^\s/]+\/[^\s/]+\/pull\/\d+/g;
|
|
464
|
+
var extractPrLink = (stdout) => {
|
|
465
|
+
const matches = stdout.match(PR_URL_PATTERN);
|
|
466
|
+
return matches ? matches[matches.length - 1] : null;
|
|
467
|
+
};
|
|
468
|
+
var buildImplementPrompt = (requirementsPath, pretext = "") => {
|
|
469
|
+
const pretextBlock = pretext ? `${pretext}
|
|
470
|
+
|
|
471
|
+
` : "";
|
|
472
|
+
return `${pretextBlock}Read the requirements JSON file at \`@${requirementsPath}\`.
|
|
473
|
+
Find the first item where \`passes\` is \`false\`.
|
|
474
|
+
Implement that item fully.
|
|
475
|
+
Before creating the PR, update that item so \`passes\` becomes \`true\` in the requirements file on this branch.
|
|
476
|
+
Create a GitHub PR with an extensive summary of what you tried and did in the PR description.
|
|
477
|
+
When finished, return the URL for the PR. Don't return a preamble or anything else - only return the URL for the PR.`;
|
|
478
|
+
};
|
|
479
|
+
var formatThread = (thread, index) => {
|
|
480
|
+
const lastComment = thread.comments[thread.comments.length - 1];
|
|
481
|
+
const replyInfo = lastComment ? ` (reply to comment ID: ${lastComment.id})` : "";
|
|
482
|
+
const header = thread.line != null ? `### Thread ${index + 1}: \`${thread.path}\` (line ${thread.line})${replyInfo}` : `### Thread ${index + 1}: \`${thread.path}\`${replyInfo}`;
|
|
483
|
+
const comments = thread.comments.map((c, idx) => `${idx}. **${c.author}:** ${c.body}`).join("\n\n");
|
|
484
|
+
return `${header}
|
|
485
|
+
|
|
486
|
+
${comments}`;
|
|
487
|
+
};
|
|
488
|
+
var buildReactionPrompt = (prLink, threads, pretext = "") => {
|
|
489
|
+
const parsed = parsePrLink(prLink);
|
|
490
|
+
const threadSections = threads.map(formatThread).join("\n\n---\n\n");
|
|
491
|
+
const repoSlug = parsed ? `${parsed.owner}/${parsed.repo}` : "{owner}/{repo}";
|
|
492
|
+
const prNumber = parsed ? parsed.number : "{pull_number}";
|
|
493
|
+
const pretextBlock = pretext ? `${pretext}
|
|
494
|
+
|
|
495
|
+
` : "";
|
|
496
|
+
return `${pretextBlock}You have review comments to address on PR ${prLink}.
|
|
497
|
+
|
|
498
|
+
## Actionable review threads
|
|
499
|
+
|
|
500
|
+
${threadSections}
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
For each thread above:
|
|
505
|
+
1. Determine whether the reviewer is **asking a question** or **requesting a code change**.
|
|
506
|
+
2. If it's a question or request for information: reply with an explanation only \u2014 do NOT change any code.
|
|
507
|
+
3. If it's an actionable request: make the necessary code changes, commit them, and push your updates to the PR branch.
|
|
508
|
+
4. In both cases, reply **directly in each review thread** using the comment ID shown in the thread header. Run this exact command for each thread:
|
|
509
|
+
\`\`\`
|
|
510
|
+
gh api repos/${repoSlug}/pulls/${prNumber}/comments/{comment_id}/replies -f body="your reply"
|
|
511
|
+
\`\`\`
|
|
512
|
+
Replace \`{comment_id}\` with the ID from the thread header. Do NOT leave a general PR comment \u2014 you MUST reply to each thread individually using the command above.
|
|
513
|
+
|
|
514
|
+
When you are done with all threads, return "DONE".`;
|
|
515
|
+
};
|
|
516
|
+
var MERGE_CONFLICT_PRETEXT = "IMPORTANT: The PR branch has merge conflicts with the base branch. Before addressing any review comments, resolve all merge conflicts first. Pull the latest main branch, merge it into the PR branch, resolve conflicts, and push.";
|
|
517
|
+
var buildConflictResolutionPrompt = (prLink, pretext = "") => {
|
|
518
|
+
const pretextBlock = pretext ? `${pretext}
|
|
519
|
+
|
|
520
|
+
` : "";
|
|
521
|
+
return `${pretextBlock}The PR branch for ${prLink} has merge conflicts with the base branch. Please resolve them:
|
|
522
|
+
|
|
523
|
+
1. Pull the latest main branch and merge it into the PR branch.
|
|
524
|
+
2. Resolve all merge conflicts.
|
|
525
|
+
3. Commit the merge resolution and push to the PR branch.
|
|
526
|
+
|
|
527
|
+
When you are done, return "DONE".`;
|
|
528
|
+
};
|
|
529
|
+
var executeConflictResolution = (commandTemplate, prLink, pretext = "") => {
|
|
530
|
+
const prompt = buildConflictResolutionPrompt(prLink, pretext);
|
|
531
|
+
logger().debug("Conflict resolution agent prompt:\n" + prompt);
|
|
532
|
+
return runAgent(commandTemplate, prompt);
|
|
533
|
+
};
|
|
534
|
+
var executeCommentReaction = (commandTemplate, prLink, threads, pretext = "") => {
|
|
535
|
+
const prompt = buildReactionPrompt(prLink, threads, pretext);
|
|
536
|
+
logger().debug("Reaction agent prompt:\n" + prompt);
|
|
537
|
+
return runAgent(commandTemplate, prompt);
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
// src/state.ts
|
|
541
|
+
import { readFileSync, writeFileSync, renameSync, mkdirSync } from "node:fs";
|
|
542
|
+
import { existsSync } from "node:fs";
|
|
543
|
+
import { dirname, join } from "node:path";
|
|
544
|
+
import { randomUUID } from "node:crypto";
|
|
545
|
+
var readCurrentPrLink = (statePath) => {
|
|
546
|
+
if (!existsSync(statePath)) {
|
|
547
|
+
return null;
|
|
548
|
+
}
|
|
549
|
+
const content = readFileSync(statePath, "utf-8").trim();
|
|
550
|
+
if (!content) {
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
const state = JSON.parse(content);
|
|
554
|
+
return state.currentPrLink ?? null;
|
|
555
|
+
};
|
|
556
|
+
var writeStateFile = (statePath, state) => {
|
|
557
|
+
const dir = dirname(statePath);
|
|
558
|
+
mkdirSync(dir, { recursive: true });
|
|
559
|
+
const tempPath = join(dir, `.state-${randomUUID()}.tmp`);
|
|
560
|
+
writeFileSync(tempPath, JSON.stringify(state), "utf-8");
|
|
561
|
+
renameSync(tempPath, statePath);
|
|
562
|
+
};
|
|
563
|
+
var writeCurrentPrLink = (statePath, prLink) => writeStateFile(statePath, { currentPrLink: prLink });
|
|
564
|
+
var clearCurrentPrLink = (statePath) => writeStateFile(statePath, { currentPrLink: null });
|
|
565
|
+
|
|
566
|
+
// src/config.ts
|
|
567
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "node:fs";
|
|
568
|
+
|
|
569
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/core.js
|
|
570
|
+
var NEVER = Object.freeze({
|
|
571
|
+
status: "aborted"
|
|
572
|
+
});
|
|
573
|
+
// @__NO_SIDE_EFFECTS__
|
|
574
|
+
function $constructor(name, initializer2, params) {
|
|
575
|
+
function init(inst, def) {
|
|
576
|
+
if (!inst._zod) {
|
|
577
|
+
Object.defineProperty(inst, "_zod", {
|
|
578
|
+
value: {
|
|
579
|
+
def,
|
|
580
|
+
constr: _,
|
|
581
|
+
traits: /* @__PURE__ */ new Set()
|
|
582
|
+
},
|
|
583
|
+
enumerable: false
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
if (inst._zod.traits.has(name)) {
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
inst._zod.traits.add(name);
|
|
590
|
+
initializer2(inst, def);
|
|
591
|
+
const proto = _.prototype;
|
|
592
|
+
const keys = Object.keys(proto);
|
|
593
|
+
for (let i = 0; i < keys.length; i++) {
|
|
594
|
+
const k = keys[i];
|
|
595
|
+
if (!(k in inst)) {
|
|
596
|
+
inst[k] = proto[k].bind(inst);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
const Parent = params?.Parent ?? Object;
|
|
601
|
+
class Definition extends Parent {
|
|
602
|
+
}
|
|
603
|
+
Object.defineProperty(Definition, "name", { value: name });
|
|
604
|
+
function _(def) {
|
|
605
|
+
var _a2;
|
|
606
|
+
const inst = params?.Parent ? new Definition() : this;
|
|
607
|
+
init(inst, def);
|
|
608
|
+
(_a2 = inst._zod).deferred ?? (_a2.deferred = []);
|
|
609
|
+
for (const fn of inst._zod.deferred) {
|
|
610
|
+
fn();
|
|
611
|
+
}
|
|
612
|
+
return inst;
|
|
613
|
+
}
|
|
614
|
+
Object.defineProperty(_, "init", { value: init });
|
|
615
|
+
Object.defineProperty(_, Symbol.hasInstance, {
|
|
616
|
+
value: (inst) => {
|
|
617
|
+
if (params?.Parent && inst instanceof params.Parent)
|
|
618
|
+
return true;
|
|
619
|
+
return inst?._zod?.traits?.has(name);
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
Object.defineProperty(_, "name", { value: name });
|
|
623
|
+
return _;
|
|
624
|
+
}
|
|
625
|
+
var $ZodAsyncError = class extends Error {
|
|
626
|
+
constructor() {
|
|
627
|
+
super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
var globalConfig = {};
|
|
631
|
+
function config(newConfig) {
|
|
632
|
+
if (newConfig)
|
|
633
|
+
Object.assign(globalConfig, newConfig);
|
|
634
|
+
return globalConfig;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/util.js
|
|
638
|
+
function getEnumValues(entries) {
|
|
639
|
+
const numericValues = Object.values(entries).filter((v) => typeof v === "number");
|
|
640
|
+
const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
|
|
641
|
+
return values;
|
|
642
|
+
}
|
|
643
|
+
function jsonStringifyReplacer(_, value) {
|
|
644
|
+
if (typeof value === "bigint")
|
|
645
|
+
return value.toString();
|
|
646
|
+
return value;
|
|
647
|
+
}
|
|
648
|
+
function cached(getter) {
|
|
649
|
+
const set = false;
|
|
650
|
+
return {
|
|
651
|
+
get value() {
|
|
652
|
+
if (!set) {
|
|
653
|
+
const value = getter();
|
|
654
|
+
Object.defineProperty(this, "value", { value });
|
|
655
|
+
return value;
|
|
656
|
+
}
|
|
657
|
+
throw new Error("cached value already set");
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
function cleanRegex(source) {
|
|
662
|
+
const start = source.startsWith("^") ? 1 : 0;
|
|
663
|
+
const end = source.endsWith("$") ? source.length - 1 : source.length;
|
|
664
|
+
return source.slice(start, end);
|
|
665
|
+
}
|
|
666
|
+
var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
|
|
667
|
+
function defineLazy(object2, key, getter) {
|
|
668
|
+
let value = void 0;
|
|
669
|
+
Object.defineProperty(object2, key, {
|
|
670
|
+
get() {
|
|
671
|
+
if (value === EVALUATING) {
|
|
672
|
+
return void 0;
|
|
673
|
+
}
|
|
674
|
+
if (value === void 0) {
|
|
675
|
+
value = EVALUATING;
|
|
676
|
+
value = getter();
|
|
677
|
+
}
|
|
678
|
+
return value;
|
|
679
|
+
},
|
|
680
|
+
set(v) {
|
|
681
|
+
Object.defineProperty(object2, key, {
|
|
682
|
+
value: v
|
|
683
|
+
// configurable: true,
|
|
684
|
+
});
|
|
685
|
+
},
|
|
686
|
+
configurable: true
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
var captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => {
|
|
690
|
+
};
|
|
691
|
+
function isObject(data) {
|
|
692
|
+
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
693
|
+
}
|
|
694
|
+
var allowsEval = cached(() => {
|
|
695
|
+
if (typeof navigator !== "undefined" && navigator?.userAgent?.includes("Cloudflare")) {
|
|
696
|
+
return false;
|
|
697
|
+
}
|
|
698
|
+
try {
|
|
699
|
+
const F = Function;
|
|
700
|
+
new F("");
|
|
701
|
+
return true;
|
|
702
|
+
} catch (_) {
|
|
703
|
+
return false;
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
var propertyKeyTypes = /* @__PURE__ */ new Set(["string", "number", "symbol"]);
|
|
707
|
+
function escapeRegex(str) {
|
|
708
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
709
|
+
}
|
|
710
|
+
function clone(inst, def, params) {
|
|
711
|
+
const cl = new inst._zod.constr(def ?? inst._zod.def);
|
|
712
|
+
if (!def || params?.parent)
|
|
713
|
+
cl._zod.parent = inst;
|
|
714
|
+
return cl;
|
|
715
|
+
}
|
|
716
|
+
function normalizeParams(_params) {
|
|
717
|
+
const params = _params;
|
|
718
|
+
if (!params)
|
|
719
|
+
return {};
|
|
720
|
+
if (typeof params === "string")
|
|
721
|
+
return { error: () => params };
|
|
722
|
+
if (params?.message !== void 0) {
|
|
723
|
+
if (params?.error !== void 0)
|
|
724
|
+
throw new Error("Cannot specify both `message` and `error` params");
|
|
725
|
+
params.error = params.message;
|
|
726
|
+
}
|
|
727
|
+
delete params.message;
|
|
728
|
+
if (typeof params.error === "string")
|
|
729
|
+
return { ...params, error: () => params.error };
|
|
730
|
+
return params;
|
|
731
|
+
}
|
|
732
|
+
function optionalKeys(shape) {
|
|
733
|
+
return Object.keys(shape).filter((k) => {
|
|
734
|
+
return shape[k]._zod.optin === "optional" && shape[k]._zod.optout === "optional";
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
var NUMBER_FORMAT_RANGES = {
|
|
738
|
+
safeint: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],
|
|
739
|
+
int32: [-2147483648, 2147483647],
|
|
740
|
+
uint32: [0, 4294967295],
|
|
741
|
+
float32: [-34028234663852886e22, 34028234663852886e22],
|
|
742
|
+
float64: [-Number.MAX_VALUE, Number.MAX_VALUE]
|
|
743
|
+
};
|
|
744
|
+
function aborted(x, startIndex = 0) {
|
|
745
|
+
if (x.aborted === true)
|
|
746
|
+
return true;
|
|
747
|
+
for (let i = startIndex; i < x.issues.length; i++) {
|
|
748
|
+
if (x.issues[i]?.continue !== true) {
|
|
749
|
+
return true;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
function prefixIssues(path, issues) {
|
|
755
|
+
return issues.map((iss) => {
|
|
756
|
+
var _a2;
|
|
757
|
+
(_a2 = iss).path ?? (_a2.path = []);
|
|
758
|
+
iss.path.unshift(path);
|
|
759
|
+
return iss;
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
function unwrapMessage(message) {
|
|
763
|
+
return typeof message === "string" ? message : message?.message;
|
|
764
|
+
}
|
|
765
|
+
function finalizeIssue(iss, ctx, config2) {
|
|
766
|
+
const full = { ...iss, path: iss.path ?? [] };
|
|
767
|
+
if (!iss.message) {
|
|
768
|
+
const message = unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config2.customError?.(iss)) ?? unwrapMessage(config2.localeError?.(iss)) ?? "Invalid input";
|
|
769
|
+
full.message = message;
|
|
770
|
+
}
|
|
771
|
+
delete full.inst;
|
|
772
|
+
delete full.continue;
|
|
773
|
+
if (!ctx?.reportInput) {
|
|
774
|
+
delete full.input;
|
|
775
|
+
}
|
|
776
|
+
return full;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/errors.js
|
|
780
|
+
var initializer = (inst, def) => {
|
|
781
|
+
inst.name = "$ZodError";
|
|
782
|
+
Object.defineProperty(inst, "_zod", {
|
|
783
|
+
value: inst._zod,
|
|
784
|
+
enumerable: false
|
|
785
|
+
});
|
|
786
|
+
Object.defineProperty(inst, "issues", {
|
|
787
|
+
value: def,
|
|
788
|
+
enumerable: false
|
|
789
|
+
});
|
|
790
|
+
inst.message = JSON.stringify(def, jsonStringifyReplacer, 2);
|
|
791
|
+
Object.defineProperty(inst, "toString", {
|
|
792
|
+
value: () => inst.message,
|
|
793
|
+
enumerable: false
|
|
794
|
+
});
|
|
795
|
+
};
|
|
796
|
+
var $ZodError = $constructor("$ZodError", initializer);
|
|
797
|
+
var $ZodRealError = $constructor("$ZodError", initializer, { Parent: Error });
|
|
798
|
+
|
|
799
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/parse.js
|
|
800
|
+
var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
801
|
+
const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
|
|
802
|
+
const result = schema._zod.run({ value, issues: [] }, ctx);
|
|
803
|
+
if (result instanceof Promise) {
|
|
804
|
+
throw new $ZodAsyncError();
|
|
805
|
+
}
|
|
806
|
+
if (result.issues.length) {
|
|
807
|
+
const e = new (_params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
808
|
+
captureStackTrace(e, _params?.callee);
|
|
809
|
+
throw e;
|
|
810
|
+
}
|
|
811
|
+
return result.value;
|
|
812
|
+
};
|
|
813
|
+
var parse2 = /* @__PURE__ */ _parse($ZodRealError);
|
|
814
|
+
var _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
815
|
+
const ctx = _ctx ? Object.assign(_ctx, { async: true }) : { async: true };
|
|
816
|
+
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
817
|
+
if (result instanceof Promise)
|
|
818
|
+
result = await result;
|
|
819
|
+
if (result.issues.length) {
|
|
820
|
+
const e = new (params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
821
|
+
captureStackTrace(e, params?.callee);
|
|
822
|
+
throw e;
|
|
823
|
+
}
|
|
824
|
+
return result.value;
|
|
825
|
+
};
|
|
826
|
+
var parseAsync = /* @__PURE__ */ _parseAsync($ZodRealError);
|
|
827
|
+
var _safeParse = (_Err) => (schema, value, _ctx) => {
|
|
828
|
+
const ctx = _ctx ? { ..._ctx, async: false } : { async: false };
|
|
829
|
+
const result = schema._zod.run({ value, issues: [] }, ctx);
|
|
830
|
+
if (result instanceof Promise) {
|
|
831
|
+
throw new $ZodAsyncError();
|
|
832
|
+
}
|
|
833
|
+
return result.issues.length ? {
|
|
834
|
+
success: false,
|
|
835
|
+
error: new (_Err ?? $ZodError)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
836
|
+
} : { success: true, data: result.value };
|
|
837
|
+
};
|
|
838
|
+
var safeParse = /* @__PURE__ */ _safeParse($ZodRealError);
|
|
839
|
+
var _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
|
840
|
+
const ctx = _ctx ? Object.assign(_ctx, { async: true }) : { async: true };
|
|
841
|
+
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
842
|
+
if (result instanceof Promise)
|
|
843
|
+
result = await result;
|
|
844
|
+
return result.issues.length ? {
|
|
845
|
+
success: false,
|
|
846
|
+
error: new _Err(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
847
|
+
} : { success: true, data: result.value };
|
|
848
|
+
};
|
|
849
|
+
var safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
|
|
850
|
+
|
|
851
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/regexes.js
|
|
852
|
+
var dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
|
|
853
|
+
var date = /* @__PURE__ */ new RegExp(`^${dateSource}$`);
|
|
854
|
+
var string = (params) => {
|
|
855
|
+
const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
|
|
856
|
+
return new RegExp(`^${regex}$`);
|
|
857
|
+
};
|
|
858
|
+
var number = /^-?\d+(?:\.\d+)?$/;
|
|
859
|
+
var boolean = /^(?:true|false)$/i;
|
|
860
|
+
|
|
861
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/checks.js
|
|
862
|
+
var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
|
|
863
|
+
var _a2;
|
|
864
|
+
inst._zod ?? (inst._zod = {});
|
|
865
|
+
inst._zod.def = def;
|
|
866
|
+
(_a2 = inst._zod).onattach ?? (_a2.onattach = []);
|
|
867
|
+
});
|
|
868
|
+
var numericOriginMap = {
|
|
869
|
+
number: "number",
|
|
870
|
+
bigint: "bigint",
|
|
871
|
+
object: "date"
|
|
872
|
+
};
|
|
873
|
+
var $ZodCheckGreaterThan = /* @__PURE__ */ $constructor("$ZodCheckGreaterThan", (inst, def) => {
|
|
874
|
+
$ZodCheck.init(inst, def);
|
|
875
|
+
const origin = numericOriginMap[typeof def.value];
|
|
876
|
+
inst._zod.onattach.push((inst2) => {
|
|
877
|
+
const bag = inst2._zod.bag;
|
|
878
|
+
const curr = (def.inclusive ? bag.minimum : bag.exclusiveMinimum) ?? Number.NEGATIVE_INFINITY;
|
|
879
|
+
if (def.value > curr) {
|
|
880
|
+
if (def.inclusive)
|
|
881
|
+
bag.minimum = def.value;
|
|
882
|
+
else
|
|
883
|
+
bag.exclusiveMinimum = def.value;
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
inst._zod.check = (payload) => {
|
|
887
|
+
if (def.inclusive ? payload.value >= def.value : payload.value > def.value) {
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
payload.issues.push({
|
|
891
|
+
origin,
|
|
892
|
+
code: "too_small",
|
|
893
|
+
minimum: typeof def.value === "object" ? def.value.getTime() : def.value,
|
|
894
|
+
input: payload.value,
|
|
895
|
+
inclusive: def.inclusive,
|
|
896
|
+
inst,
|
|
897
|
+
continue: !def.abort
|
|
898
|
+
});
|
|
899
|
+
};
|
|
900
|
+
});
|
|
901
|
+
|
|
902
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/versions.js
|
|
903
|
+
var version = {
|
|
904
|
+
major: 4,
|
|
905
|
+
minor: 3,
|
|
906
|
+
patch: 6
|
|
907
|
+
};
|
|
908
|
+
|
|
909
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/schemas.js
|
|
910
|
+
var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
911
|
+
var _a2;
|
|
912
|
+
inst ?? (inst = {});
|
|
913
|
+
inst._zod.def = def;
|
|
914
|
+
inst._zod.bag = inst._zod.bag || {};
|
|
915
|
+
inst._zod.version = version;
|
|
916
|
+
const checks = [...inst._zod.def.checks ?? []];
|
|
917
|
+
if (inst._zod.traits.has("$ZodCheck")) {
|
|
918
|
+
checks.unshift(inst);
|
|
919
|
+
}
|
|
920
|
+
for (const ch of checks) {
|
|
921
|
+
for (const fn of ch._zod.onattach) {
|
|
922
|
+
fn(inst);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
if (checks.length === 0) {
|
|
926
|
+
(_a2 = inst._zod).deferred ?? (_a2.deferred = []);
|
|
927
|
+
inst._zod.deferred?.push(() => {
|
|
928
|
+
inst._zod.run = inst._zod.parse;
|
|
929
|
+
});
|
|
930
|
+
} else {
|
|
931
|
+
const runChecks = (payload, checks2, ctx) => {
|
|
932
|
+
let isAborted = aborted(payload);
|
|
933
|
+
let asyncResult;
|
|
934
|
+
for (const ch of checks2) {
|
|
935
|
+
if (ch._zod.def.when) {
|
|
936
|
+
const shouldRun = ch._zod.def.when(payload);
|
|
937
|
+
if (!shouldRun)
|
|
938
|
+
continue;
|
|
939
|
+
} else if (isAborted) {
|
|
940
|
+
continue;
|
|
941
|
+
}
|
|
942
|
+
const currLen = payload.issues.length;
|
|
943
|
+
const _ = ch._zod.check(payload);
|
|
944
|
+
if (_ instanceof Promise && ctx?.async === false) {
|
|
945
|
+
throw new $ZodAsyncError();
|
|
946
|
+
}
|
|
947
|
+
if (asyncResult || _ instanceof Promise) {
|
|
948
|
+
asyncResult = (asyncResult ?? Promise.resolve()).then(async () => {
|
|
949
|
+
await _;
|
|
950
|
+
const nextLen = payload.issues.length;
|
|
951
|
+
if (nextLen === currLen)
|
|
952
|
+
return;
|
|
953
|
+
if (!isAborted)
|
|
954
|
+
isAborted = aborted(payload, currLen);
|
|
955
|
+
});
|
|
956
|
+
} else {
|
|
957
|
+
const nextLen = payload.issues.length;
|
|
958
|
+
if (nextLen === currLen)
|
|
959
|
+
continue;
|
|
960
|
+
if (!isAborted)
|
|
961
|
+
isAborted = aborted(payload, currLen);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
if (asyncResult) {
|
|
965
|
+
return asyncResult.then(() => {
|
|
966
|
+
return payload;
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
return payload;
|
|
970
|
+
};
|
|
971
|
+
const handleCanaryResult = (canary, payload, ctx) => {
|
|
972
|
+
if (aborted(canary)) {
|
|
973
|
+
canary.aborted = true;
|
|
974
|
+
return canary;
|
|
975
|
+
}
|
|
976
|
+
const checkResult = runChecks(payload, checks, ctx);
|
|
977
|
+
if (checkResult instanceof Promise) {
|
|
978
|
+
if (ctx.async === false)
|
|
979
|
+
throw new $ZodAsyncError();
|
|
980
|
+
return checkResult.then((checkResult2) => inst._zod.parse(checkResult2, ctx));
|
|
981
|
+
}
|
|
982
|
+
return inst._zod.parse(checkResult, ctx);
|
|
983
|
+
};
|
|
984
|
+
inst._zod.run = (payload, ctx) => {
|
|
985
|
+
if (ctx.skipChecks) {
|
|
986
|
+
return inst._zod.parse(payload, ctx);
|
|
987
|
+
}
|
|
988
|
+
if (ctx.direction === "backward") {
|
|
989
|
+
const canary = inst._zod.parse({ value: payload.value, issues: [] }, { ...ctx, skipChecks: true });
|
|
990
|
+
if (canary instanceof Promise) {
|
|
991
|
+
return canary.then((canary2) => {
|
|
992
|
+
return handleCanaryResult(canary2, payload, ctx);
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
return handleCanaryResult(canary, payload, ctx);
|
|
996
|
+
}
|
|
997
|
+
const result = inst._zod.parse(payload, ctx);
|
|
998
|
+
if (result instanceof Promise) {
|
|
999
|
+
if (ctx.async === false)
|
|
1000
|
+
throw new $ZodAsyncError();
|
|
1001
|
+
return result.then((result2) => runChecks(result2, checks, ctx));
|
|
1002
|
+
}
|
|
1003
|
+
return runChecks(result, checks, ctx);
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
1006
|
+
defineLazy(inst, "~standard", () => ({
|
|
1007
|
+
validate: (value) => {
|
|
1008
|
+
try {
|
|
1009
|
+
const r = safeParse(inst, value);
|
|
1010
|
+
return r.success ? { value: r.data } : { issues: r.error?.issues };
|
|
1011
|
+
} catch (_) {
|
|
1012
|
+
return safeParseAsync(inst, value).then((r) => r.success ? { value: r.data } : { issues: r.error?.issues });
|
|
1013
|
+
}
|
|
1014
|
+
},
|
|
1015
|
+
vendor: "zod",
|
|
1016
|
+
version: 1
|
|
1017
|
+
}));
|
|
1018
|
+
});
|
|
1019
|
+
var $ZodString = /* @__PURE__ */ $constructor("$ZodString", (inst, def) => {
|
|
1020
|
+
$ZodType.init(inst, def);
|
|
1021
|
+
inst._zod.pattern = [...inst?._zod.bag?.patterns ?? []].pop() ?? string(inst._zod.bag);
|
|
1022
|
+
inst._zod.parse = (payload, _) => {
|
|
1023
|
+
if (def.coerce)
|
|
1024
|
+
try {
|
|
1025
|
+
payload.value = String(payload.value);
|
|
1026
|
+
} catch (_2) {
|
|
1027
|
+
}
|
|
1028
|
+
if (typeof payload.value === "string")
|
|
1029
|
+
return payload;
|
|
1030
|
+
payload.issues.push({
|
|
1031
|
+
expected: "string",
|
|
1032
|
+
code: "invalid_type",
|
|
1033
|
+
input: payload.value,
|
|
1034
|
+
inst
|
|
1035
|
+
});
|
|
1036
|
+
return payload;
|
|
1037
|
+
};
|
|
1038
|
+
});
|
|
1039
|
+
var $ZodNumber = /* @__PURE__ */ $constructor("$ZodNumber", (inst, def) => {
|
|
1040
|
+
$ZodType.init(inst, def);
|
|
1041
|
+
inst._zod.pattern = inst._zod.bag.pattern ?? number;
|
|
1042
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
1043
|
+
if (def.coerce)
|
|
1044
|
+
try {
|
|
1045
|
+
payload.value = Number(payload.value);
|
|
1046
|
+
} catch (_) {
|
|
1047
|
+
}
|
|
1048
|
+
const input = payload.value;
|
|
1049
|
+
if (typeof input === "number" && !Number.isNaN(input) && Number.isFinite(input)) {
|
|
1050
|
+
return payload;
|
|
1051
|
+
}
|
|
1052
|
+
const received = typeof input === "number" ? Number.isNaN(input) ? "NaN" : !Number.isFinite(input) ? "Infinity" : void 0 : void 0;
|
|
1053
|
+
payload.issues.push({
|
|
1054
|
+
expected: "number",
|
|
1055
|
+
code: "invalid_type",
|
|
1056
|
+
input,
|
|
1057
|
+
inst,
|
|
1058
|
+
...received ? { received } : {}
|
|
1059
|
+
});
|
|
1060
|
+
return payload;
|
|
1061
|
+
};
|
|
1062
|
+
});
|
|
1063
|
+
var $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
|
|
1064
|
+
$ZodType.init(inst, def);
|
|
1065
|
+
inst._zod.pattern = boolean;
|
|
1066
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
1067
|
+
if (def.coerce)
|
|
1068
|
+
try {
|
|
1069
|
+
payload.value = Boolean(payload.value);
|
|
1070
|
+
} catch (_) {
|
|
1071
|
+
}
|
|
1072
|
+
const input = payload.value;
|
|
1073
|
+
if (typeof input === "boolean")
|
|
1074
|
+
return payload;
|
|
1075
|
+
payload.issues.push({
|
|
1076
|
+
expected: "boolean",
|
|
1077
|
+
code: "invalid_type",
|
|
1078
|
+
input,
|
|
1079
|
+
inst
|
|
1080
|
+
});
|
|
1081
|
+
return payload;
|
|
1082
|
+
};
|
|
1083
|
+
});
|
|
1084
|
+
function handleArrayResult(result, final, index) {
|
|
1085
|
+
if (result.issues.length) {
|
|
1086
|
+
final.issues.push(...prefixIssues(index, result.issues));
|
|
1087
|
+
}
|
|
1088
|
+
final.value[index] = result.value;
|
|
1089
|
+
}
|
|
1090
|
+
var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
1091
|
+
$ZodType.init(inst, def);
|
|
1092
|
+
inst._zod.parse = (payload, ctx) => {
|
|
1093
|
+
const input = payload.value;
|
|
1094
|
+
if (!Array.isArray(input)) {
|
|
1095
|
+
payload.issues.push({
|
|
1096
|
+
expected: "array",
|
|
1097
|
+
code: "invalid_type",
|
|
1098
|
+
input,
|
|
1099
|
+
inst
|
|
1100
|
+
});
|
|
1101
|
+
return payload;
|
|
1102
|
+
}
|
|
1103
|
+
payload.value = Array(input.length);
|
|
1104
|
+
const proms = [];
|
|
1105
|
+
for (let i = 0; i < input.length; i++) {
|
|
1106
|
+
const item = input[i];
|
|
1107
|
+
const result = def.element._zod.run({
|
|
1108
|
+
value: item,
|
|
1109
|
+
issues: []
|
|
1110
|
+
}, ctx);
|
|
1111
|
+
if (result instanceof Promise) {
|
|
1112
|
+
proms.push(result.then((result2) => handleArrayResult(result2, payload, i)));
|
|
1113
|
+
} else {
|
|
1114
|
+
handleArrayResult(result, payload, i);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
if (proms.length) {
|
|
1118
|
+
return Promise.all(proms).then(() => payload);
|
|
1119
|
+
}
|
|
1120
|
+
return payload;
|
|
1121
|
+
};
|
|
1122
|
+
});
|
|
1123
|
+
function handlePropertyResult(result, final, key, input, isOptionalOut) {
|
|
1124
|
+
if (result.issues.length) {
|
|
1125
|
+
if (isOptionalOut && !(key in input)) {
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
final.issues.push(...prefixIssues(key, result.issues));
|
|
1129
|
+
}
|
|
1130
|
+
if (result.value === void 0) {
|
|
1131
|
+
if (key in input) {
|
|
1132
|
+
final.value[key] = void 0;
|
|
1133
|
+
}
|
|
1134
|
+
} else {
|
|
1135
|
+
final.value[key] = result.value;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
function normalizeDef(def) {
|
|
1139
|
+
const keys = Object.keys(def.shape);
|
|
1140
|
+
for (const k of keys) {
|
|
1141
|
+
if (!def.shape?.[k]?._zod?.traits?.has("$ZodType")) {
|
|
1142
|
+
throw new Error(`Invalid element at key "${k}": expected a Zod schema`);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
const okeys = optionalKeys(def.shape);
|
|
1146
|
+
return {
|
|
1147
|
+
...def,
|
|
1148
|
+
keys,
|
|
1149
|
+
keySet: new Set(keys),
|
|
1150
|
+
numKeys: keys.length,
|
|
1151
|
+
optionalKeys: new Set(okeys)
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
function handleCatchall(proms, input, payload, ctx, def, inst) {
|
|
1155
|
+
const unrecognized = [];
|
|
1156
|
+
const keySet = def.keySet;
|
|
1157
|
+
const _catchall = def.catchall._zod;
|
|
1158
|
+
const t = _catchall.def.type;
|
|
1159
|
+
const isOptionalOut = _catchall.optout === "optional";
|
|
1160
|
+
for (const key in input) {
|
|
1161
|
+
if (keySet.has(key))
|
|
1162
|
+
continue;
|
|
1163
|
+
if (t === "never") {
|
|
1164
|
+
unrecognized.push(key);
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
const r = _catchall.run({ value: input[key], issues: [] }, ctx);
|
|
1168
|
+
if (r instanceof Promise) {
|
|
1169
|
+
proms.push(r.then((r2) => handlePropertyResult(r2, payload, key, input, isOptionalOut)));
|
|
1170
|
+
} else {
|
|
1171
|
+
handlePropertyResult(r, payload, key, input, isOptionalOut);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
if (unrecognized.length) {
|
|
1175
|
+
payload.issues.push({
|
|
1176
|
+
code: "unrecognized_keys",
|
|
1177
|
+
keys: unrecognized,
|
|
1178
|
+
input,
|
|
1179
|
+
inst
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
if (!proms.length)
|
|
1183
|
+
return payload;
|
|
1184
|
+
return Promise.all(proms).then(() => {
|
|
1185
|
+
return payload;
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
1189
|
+
$ZodType.init(inst, def);
|
|
1190
|
+
const desc = Object.getOwnPropertyDescriptor(def, "shape");
|
|
1191
|
+
if (!desc?.get) {
|
|
1192
|
+
const sh = def.shape;
|
|
1193
|
+
Object.defineProperty(def, "shape", {
|
|
1194
|
+
get: () => {
|
|
1195
|
+
const newSh = { ...sh };
|
|
1196
|
+
Object.defineProperty(def, "shape", {
|
|
1197
|
+
value: newSh
|
|
1198
|
+
});
|
|
1199
|
+
return newSh;
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
const _normalized = cached(() => normalizeDef(def));
|
|
1204
|
+
defineLazy(inst._zod, "propValues", () => {
|
|
1205
|
+
const shape = def.shape;
|
|
1206
|
+
const propValues = {};
|
|
1207
|
+
for (const key in shape) {
|
|
1208
|
+
const field = shape[key]._zod;
|
|
1209
|
+
if (field.values) {
|
|
1210
|
+
propValues[key] ?? (propValues[key] = /* @__PURE__ */ new Set());
|
|
1211
|
+
for (const v of field.values)
|
|
1212
|
+
propValues[key].add(v);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
return propValues;
|
|
1216
|
+
});
|
|
1217
|
+
const isObject2 = isObject;
|
|
1218
|
+
const catchall = def.catchall;
|
|
1219
|
+
let value;
|
|
1220
|
+
inst._zod.parse = (payload, ctx) => {
|
|
1221
|
+
value ?? (value = _normalized.value);
|
|
1222
|
+
const input = payload.value;
|
|
1223
|
+
if (!isObject2(input)) {
|
|
1224
|
+
payload.issues.push({
|
|
1225
|
+
expected: "object",
|
|
1226
|
+
code: "invalid_type",
|
|
1227
|
+
input,
|
|
1228
|
+
inst
|
|
1229
|
+
});
|
|
1230
|
+
return payload;
|
|
1231
|
+
}
|
|
1232
|
+
payload.value = {};
|
|
1233
|
+
const proms = [];
|
|
1234
|
+
const shape = value.shape;
|
|
1235
|
+
for (const key of value.keys) {
|
|
1236
|
+
const el = shape[key];
|
|
1237
|
+
const isOptionalOut = el._zod.optout === "optional";
|
|
1238
|
+
const r = el._zod.run({ value: input[key], issues: [] }, ctx);
|
|
1239
|
+
if (r instanceof Promise) {
|
|
1240
|
+
proms.push(r.then((r2) => handlePropertyResult(r2, payload, key, input, isOptionalOut)));
|
|
1241
|
+
} else {
|
|
1242
|
+
handlePropertyResult(r, payload, key, input, isOptionalOut);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
if (!catchall) {
|
|
1246
|
+
return proms.length ? Promise.all(proms).then(() => payload) : payload;
|
|
1247
|
+
}
|
|
1248
|
+
return handleCatchall(proms, input, payload, ctx, _normalized.value, inst);
|
|
1249
|
+
};
|
|
1250
|
+
});
|
|
1251
|
+
var $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
1252
|
+
$ZodType.init(inst, def);
|
|
1253
|
+
const values = getEnumValues(def.entries);
|
|
1254
|
+
const valuesSet = new Set(values);
|
|
1255
|
+
inst._zod.values = valuesSet;
|
|
1256
|
+
inst._zod.pattern = new RegExp(`^(${values.filter((k) => propertyKeyTypes.has(typeof k)).map((o) => typeof o === "string" ? escapeRegex(o) : o.toString()).join("|")})$`);
|
|
1257
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
1258
|
+
const input = payload.value;
|
|
1259
|
+
if (valuesSet.has(input)) {
|
|
1260
|
+
return payload;
|
|
1261
|
+
}
|
|
1262
|
+
payload.issues.push({
|
|
1263
|
+
code: "invalid_value",
|
|
1264
|
+
values,
|
|
1265
|
+
input,
|
|
1266
|
+
inst
|
|
1267
|
+
});
|
|
1268
|
+
return payload;
|
|
1269
|
+
};
|
|
1270
|
+
});
|
|
1271
|
+
function handleOptionalResult(result, input) {
|
|
1272
|
+
if (result.issues.length && input === void 0) {
|
|
1273
|
+
return { issues: [], value: void 0 };
|
|
1274
|
+
}
|
|
1275
|
+
return result;
|
|
1276
|
+
}
|
|
1277
|
+
var $ZodOptional = /* @__PURE__ */ $constructor("$ZodOptional", (inst, def) => {
|
|
1278
|
+
$ZodType.init(inst, def);
|
|
1279
|
+
inst._zod.optin = "optional";
|
|
1280
|
+
inst._zod.optout = "optional";
|
|
1281
|
+
defineLazy(inst._zod, "values", () => {
|
|
1282
|
+
return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, void 0]) : void 0;
|
|
1283
|
+
});
|
|
1284
|
+
defineLazy(inst._zod, "pattern", () => {
|
|
1285
|
+
const pattern = def.innerType._zod.pattern;
|
|
1286
|
+
return pattern ? new RegExp(`^(${cleanRegex(pattern.source)})?$`) : void 0;
|
|
1287
|
+
});
|
|
1288
|
+
inst._zod.parse = (payload, ctx) => {
|
|
1289
|
+
if (def.innerType._zod.optin === "optional") {
|
|
1290
|
+
const result = def.innerType._zod.run(payload, ctx);
|
|
1291
|
+
if (result instanceof Promise)
|
|
1292
|
+
return result.then((r) => handleOptionalResult(r, payload.value));
|
|
1293
|
+
return handleOptionalResult(result, payload.value);
|
|
1294
|
+
}
|
|
1295
|
+
if (payload.value === void 0) {
|
|
1296
|
+
return payload;
|
|
1297
|
+
}
|
|
1298
|
+
return def.innerType._zod.run(payload, ctx);
|
|
1299
|
+
};
|
|
1300
|
+
});
|
|
1301
|
+
|
|
1302
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/registries.js
|
|
1303
|
+
var _a;
|
|
1304
|
+
var $ZodRegistry = class {
|
|
1305
|
+
constructor() {
|
|
1306
|
+
this._map = /* @__PURE__ */ new WeakMap();
|
|
1307
|
+
this._idmap = /* @__PURE__ */ new Map();
|
|
1308
|
+
}
|
|
1309
|
+
add(schema, ..._meta) {
|
|
1310
|
+
const meta2 = _meta[0];
|
|
1311
|
+
this._map.set(schema, meta2);
|
|
1312
|
+
if (meta2 && typeof meta2 === "object" && "id" in meta2) {
|
|
1313
|
+
this._idmap.set(meta2.id, schema);
|
|
1314
|
+
}
|
|
1315
|
+
return this;
|
|
1316
|
+
}
|
|
1317
|
+
clear() {
|
|
1318
|
+
this._map = /* @__PURE__ */ new WeakMap();
|
|
1319
|
+
this._idmap = /* @__PURE__ */ new Map();
|
|
1320
|
+
return this;
|
|
1321
|
+
}
|
|
1322
|
+
remove(schema) {
|
|
1323
|
+
const meta2 = this._map.get(schema);
|
|
1324
|
+
if (meta2 && typeof meta2 === "object" && "id" in meta2) {
|
|
1325
|
+
this._idmap.delete(meta2.id);
|
|
1326
|
+
}
|
|
1327
|
+
this._map.delete(schema);
|
|
1328
|
+
return this;
|
|
1329
|
+
}
|
|
1330
|
+
get(schema) {
|
|
1331
|
+
const p = schema._zod.parent;
|
|
1332
|
+
if (p) {
|
|
1333
|
+
const pm = { ...this.get(p) ?? {} };
|
|
1334
|
+
delete pm.id;
|
|
1335
|
+
const f = { ...pm, ...this._map.get(schema) };
|
|
1336
|
+
return Object.keys(f).length ? f : void 0;
|
|
1337
|
+
}
|
|
1338
|
+
return this._map.get(schema);
|
|
1339
|
+
}
|
|
1340
|
+
has(schema) {
|
|
1341
|
+
return this._map.has(schema);
|
|
1342
|
+
}
|
|
1343
|
+
};
|
|
1344
|
+
function registry() {
|
|
1345
|
+
return new $ZodRegistry();
|
|
1346
|
+
}
|
|
1347
|
+
(_a = globalThis).__zod_globalRegistry ?? (_a.__zod_globalRegistry = registry());
|
|
1348
|
+
var globalRegistry = globalThis.__zod_globalRegistry;
|
|
1349
|
+
|
|
1350
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/api.js
|
|
1351
|
+
// @__NO_SIDE_EFFECTS__
|
|
1352
|
+
function _string(Class, params) {
|
|
1353
|
+
return new Class({
|
|
1354
|
+
type: "string",
|
|
1355
|
+
...normalizeParams(params)
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
// @__NO_SIDE_EFFECTS__
|
|
1359
|
+
function _number(Class, params) {
|
|
1360
|
+
return new Class({
|
|
1361
|
+
type: "number",
|
|
1362
|
+
checks: [],
|
|
1363
|
+
...normalizeParams(params)
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1366
|
+
// @__NO_SIDE_EFFECTS__
|
|
1367
|
+
function _boolean(Class, params) {
|
|
1368
|
+
return new Class({
|
|
1369
|
+
type: "boolean",
|
|
1370
|
+
...normalizeParams(params)
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
// @__NO_SIDE_EFFECTS__
|
|
1374
|
+
function _gt(value, params) {
|
|
1375
|
+
return new $ZodCheckGreaterThan({
|
|
1376
|
+
check: "greater_than",
|
|
1377
|
+
...normalizeParams(params),
|
|
1378
|
+
value,
|
|
1379
|
+
inclusive: false
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
// @__NO_SIDE_EFFECTS__
|
|
1383
|
+
function _positive(params) {
|
|
1384
|
+
return /* @__PURE__ */ _gt(0, params);
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/mini/schemas.js
|
|
1388
|
+
var ZodMiniType = /* @__PURE__ */ $constructor("ZodMiniType", (inst, def) => {
|
|
1389
|
+
if (!inst._zod)
|
|
1390
|
+
throw new Error("Uninitialized schema in ZodMiniType.");
|
|
1391
|
+
$ZodType.init(inst, def);
|
|
1392
|
+
inst.def = def;
|
|
1393
|
+
inst.type = def.type;
|
|
1394
|
+
inst.parse = (data, params) => parse2(inst, data, params, { callee: inst.parse });
|
|
1395
|
+
inst.safeParse = (data, params) => safeParse(inst, data, params);
|
|
1396
|
+
inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
|
|
1397
|
+
inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
|
|
1398
|
+
inst.check = (...checks) => {
|
|
1399
|
+
return inst.clone({
|
|
1400
|
+
...def,
|
|
1401
|
+
checks: [
|
|
1402
|
+
...def.checks ?? [],
|
|
1403
|
+
...checks.map((ch) => typeof ch === "function" ? { _zod: { check: ch, def: { check: "custom" }, onattach: [] } } : ch)
|
|
1404
|
+
]
|
|
1405
|
+
}, { parent: true });
|
|
1406
|
+
};
|
|
1407
|
+
inst.with = inst.check;
|
|
1408
|
+
inst.clone = (_def, params) => clone(inst, _def, params);
|
|
1409
|
+
inst.brand = () => inst;
|
|
1410
|
+
inst.register = ((reg, meta2) => {
|
|
1411
|
+
reg.add(inst, meta2);
|
|
1412
|
+
return inst;
|
|
1413
|
+
});
|
|
1414
|
+
inst.apply = (fn) => fn(inst);
|
|
1415
|
+
});
|
|
1416
|
+
var ZodMiniString = /* @__PURE__ */ $constructor("ZodMiniString", (inst, def) => {
|
|
1417
|
+
$ZodString.init(inst, def);
|
|
1418
|
+
ZodMiniType.init(inst, def);
|
|
1419
|
+
});
|
|
1420
|
+
// @__NO_SIDE_EFFECTS__
|
|
1421
|
+
function string2(params) {
|
|
1422
|
+
return _string(ZodMiniString, params);
|
|
1423
|
+
}
|
|
1424
|
+
var ZodMiniNumber = /* @__PURE__ */ $constructor("ZodMiniNumber", (inst, def) => {
|
|
1425
|
+
$ZodNumber.init(inst, def);
|
|
1426
|
+
ZodMiniType.init(inst, def);
|
|
1427
|
+
});
|
|
1428
|
+
// @__NO_SIDE_EFFECTS__
|
|
1429
|
+
function number2(params) {
|
|
1430
|
+
return _number(ZodMiniNumber, params);
|
|
1431
|
+
}
|
|
1432
|
+
var ZodMiniBoolean = /* @__PURE__ */ $constructor("ZodMiniBoolean", (inst, def) => {
|
|
1433
|
+
$ZodBoolean.init(inst, def);
|
|
1434
|
+
ZodMiniType.init(inst, def);
|
|
1435
|
+
});
|
|
1436
|
+
// @__NO_SIDE_EFFECTS__
|
|
1437
|
+
function boolean2(params) {
|
|
1438
|
+
return _boolean(ZodMiniBoolean, params);
|
|
1439
|
+
}
|
|
1440
|
+
var ZodMiniArray = /* @__PURE__ */ $constructor("ZodMiniArray", (inst, def) => {
|
|
1441
|
+
$ZodArray.init(inst, def);
|
|
1442
|
+
ZodMiniType.init(inst, def);
|
|
1443
|
+
});
|
|
1444
|
+
// @__NO_SIDE_EFFECTS__
|
|
1445
|
+
function array(element, params) {
|
|
1446
|
+
return new ZodMiniArray({
|
|
1447
|
+
type: "array",
|
|
1448
|
+
element,
|
|
1449
|
+
...normalizeParams(params)
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
var ZodMiniObject = /* @__PURE__ */ $constructor("ZodMiniObject", (inst, def) => {
|
|
1453
|
+
$ZodObject.init(inst, def);
|
|
1454
|
+
ZodMiniType.init(inst, def);
|
|
1455
|
+
defineLazy(inst, "shape", () => def.shape);
|
|
1456
|
+
});
|
|
1457
|
+
// @__NO_SIDE_EFFECTS__
|
|
1458
|
+
function object(shape, params) {
|
|
1459
|
+
const def = {
|
|
1460
|
+
type: "object",
|
|
1461
|
+
shape: shape ?? {},
|
|
1462
|
+
...normalizeParams(params)
|
|
1463
|
+
};
|
|
1464
|
+
return new ZodMiniObject(def);
|
|
1465
|
+
}
|
|
1466
|
+
var ZodMiniEnum = /* @__PURE__ */ $constructor("ZodMiniEnum", (inst, def) => {
|
|
1467
|
+
$ZodEnum.init(inst, def);
|
|
1468
|
+
ZodMiniType.init(inst, def);
|
|
1469
|
+
inst.options = Object.values(def.entries);
|
|
1470
|
+
});
|
|
1471
|
+
// @__NO_SIDE_EFFECTS__
|
|
1472
|
+
function _enum(values, params) {
|
|
1473
|
+
const entries = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
|
|
1474
|
+
return new ZodMiniEnum({
|
|
1475
|
+
type: "enum",
|
|
1476
|
+
entries,
|
|
1477
|
+
...normalizeParams(params)
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
var ZodMiniOptional = /* @__PURE__ */ $constructor("ZodMiniOptional", (inst, def) => {
|
|
1481
|
+
$ZodOptional.init(inst, def);
|
|
1482
|
+
ZodMiniType.init(inst, def);
|
|
1483
|
+
});
|
|
1484
|
+
// @__NO_SIDE_EFFECTS__
|
|
1485
|
+
function optional(innerType) {
|
|
1486
|
+
return new ZodMiniOptional({
|
|
1487
|
+
type: "optional",
|
|
1488
|
+
innerType
|
|
1489
|
+
});
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
// src/config.ts
|
|
1493
|
+
var MERGE_CONFLICT_RESOLUTION_VALUES = ["never", "withThreads", "always"];
|
|
1494
|
+
var configSchema = object({
|
|
1495
|
+
statePath: optional(string2()),
|
|
1496
|
+
logLevel: optional(_enum(["error", "warn", "info", "debug"])),
|
|
1497
|
+
pollIntervalMinutes: optional(number2().check(_positive())),
|
|
1498
|
+
pretext: optional(string2()),
|
|
1499
|
+
allowlist: optional(array(string2())),
|
|
1500
|
+
requireMention: optional(boolean2()),
|
|
1501
|
+
mergeConflictResolution: optional(_enum(MERGE_CONFLICT_RESOLUTION_VALUES))
|
|
1502
|
+
});
|
|
1503
|
+
var DEFAULT_CONFIG_PATH = "./.remote-ralph/config.json";
|
|
1504
|
+
var DEFAULT_CONFIG = {
|
|
1505
|
+
statePath: "./.remote-ralph/state.json",
|
|
1506
|
+
logLevel: "info",
|
|
1507
|
+
pollIntervalMinutes: 5,
|
|
1508
|
+
pretext: "",
|
|
1509
|
+
allowlist: [],
|
|
1510
|
+
requireMention: false,
|
|
1511
|
+
mergeConflictResolution: "withThreads"
|
|
1512
|
+
};
|
|
1513
|
+
var resolveConfig = (configPath) => {
|
|
1514
|
+
if (!existsSync2(configPath)) {
|
|
1515
|
+
return { ...DEFAULT_CONFIG };
|
|
1516
|
+
}
|
|
1517
|
+
let raw;
|
|
1518
|
+
try {
|
|
1519
|
+
raw = JSON.parse(readFileSync2(configPath, "utf-8"));
|
|
1520
|
+
} catch {
|
|
1521
|
+
console.error(`Error: config file at '${configPath}' is not valid JSON`);
|
|
1522
|
+
process.exit(1);
|
|
1523
|
+
}
|
|
1524
|
+
if (typeof raw === "object" && raw !== null) {
|
|
1525
|
+
const knownKeys = new Set(Object.keys(configSchema.shape));
|
|
1526
|
+
for (const key of Object.keys(raw)) {
|
|
1527
|
+
if (!knownKeys.has(key)) {
|
|
1528
|
+
console.warn(`Warning: unrecognized config key '${key}' in '${configPath}'`);
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
const result = configSchema.safeParse(raw);
|
|
1533
|
+
if (!result.success) {
|
|
1534
|
+
console.error(`Error: invalid config file at '${configPath}': ${result.error.message}`);
|
|
1535
|
+
process.exit(1);
|
|
1536
|
+
}
|
|
1537
|
+
return {
|
|
1538
|
+
statePath: result.data.statePath ?? DEFAULT_CONFIG.statePath,
|
|
1539
|
+
logLevel: result.data.logLevel ?? DEFAULT_CONFIG.logLevel,
|
|
1540
|
+
pollIntervalMinutes: result.data.pollIntervalMinutes ?? DEFAULT_CONFIG.pollIntervalMinutes,
|
|
1541
|
+
pretext: result.data.pretext ?? DEFAULT_CONFIG.pretext,
|
|
1542
|
+
allowlist: result.data.allowlist ?? DEFAULT_CONFIG.allowlist,
|
|
1543
|
+
requireMention: result.data.requireMention ?? DEFAULT_CONFIG.requireMention,
|
|
1544
|
+
mergeConflictResolution: result.data.mergeConflictResolution ?? DEFAULT_CONFIG.mergeConflictResolution
|
|
1545
|
+
};
|
|
1546
|
+
};
|
|
1547
|
+
|
|
1548
|
+
// src/index.ts
|
|
1549
|
+
var LOG_LEVELS = ["error", "warn", "info", "debug"];
|
|
1550
|
+
var MAX_CONSECUTIVE_POLL_FAILURES = 3;
|
|
1551
|
+
var getArg = (args, paramName) => {
|
|
1552
|
+
const index = args.indexOf(paramName);
|
|
1553
|
+
if (index === -1 || index === args.length - 1) {
|
|
1554
|
+
return void 0;
|
|
1555
|
+
}
|
|
1556
|
+
return args[index + 1];
|
|
1557
|
+
};
|
|
1558
|
+
var logHelpMessage = () => {
|
|
1559
|
+
console.log(`
|
|
1560
|
+
remote-ralph - 24/7 autonomous implementation loop
|
|
1561
|
+
|
|
1562
|
+
Usage:
|
|
1563
|
+
remote-ralph --requirements-path <path> --command <template> [options]
|
|
1564
|
+
|
|
1565
|
+
Required:
|
|
1566
|
+
--requirements-path <path> Path to requirements JSON file
|
|
1567
|
+
--command <template> Command template with ${PROMPT_PLACEHOLDER} placeholder
|
|
1568
|
+
|
|
1569
|
+
Optional:
|
|
1570
|
+
--config-path <path> Path to config file (default: ./.remote-ralph/config.json)
|
|
1571
|
+
--state-path <path> Path to state file (default: ./.remote-ralph/state.json)
|
|
1572
|
+
--log-level <level> Log level: error, warn, info, debug (default: info)
|
|
1573
|
+
-h, --help Show this help message
|
|
1574
|
+
`);
|
|
1575
|
+
};
|
|
1576
|
+
var parseArgs = (argv) => {
|
|
1577
|
+
const args = argv.slice(2);
|
|
1578
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
1579
|
+
logHelpMessage();
|
|
1580
|
+
process.exit(0);
|
|
1581
|
+
}
|
|
1582
|
+
const requirementsPath = getArg(args, "--requirements-path");
|
|
1583
|
+
if (!requirementsPath) {
|
|
1584
|
+
console.error("Error: --requirements-path is required");
|
|
1585
|
+
process.exit(1);
|
|
1586
|
+
}
|
|
1587
|
+
const command = getArg(args, "--command");
|
|
1588
|
+
if (!command) {
|
|
1589
|
+
console.error("Error: --command is required");
|
|
1590
|
+
process.exit(1);
|
|
1591
|
+
}
|
|
1592
|
+
if (command && !command.includes(PROMPT_PLACEHOLDER)) {
|
|
1593
|
+
console.error(`Error: --command must contain ${PROMPT_PLACEHOLDER} placeholder`);
|
|
1594
|
+
process.exit(1);
|
|
1595
|
+
}
|
|
1596
|
+
const configPath = getArg(args, "--config-path") ?? DEFAULT_CONFIG_PATH;
|
|
1597
|
+
const config2 = resolveConfig(configPath);
|
|
1598
|
+
const statePathArg = getArg(args, "--state-path");
|
|
1599
|
+
const statePath = statePathArg ?? config2.statePath;
|
|
1600
|
+
const logLevelRaw = getArg(args, "--log-level");
|
|
1601
|
+
const logLevelArg = logLevelRaw?.toLowerCase();
|
|
1602
|
+
const isLogLevel = (value) => LOG_LEVELS.some((l) => l === value);
|
|
1603
|
+
const configLogLevel = config2.logLevel;
|
|
1604
|
+
let logLevel = configLogLevel;
|
|
1605
|
+
if (logLevelArg !== void 0) {
|
|
1606
|
+
if (!isLogLevel(logLevelArg)) {
|
|
1607
|
+
console.error(`Error: invalid --log-level '${logLevelArg}'. Must be one of: ${LOG_LEVELS.join(", ")}`);
|
|
1608
|
+
process.exit(1);
|
|
1609
|
+
}
|
|
1610
|
+
logLevel = logLevelArg;
|
|
1611
|
+
}
|
|
1612
|
+
const pollIntervalMs = config2.pollIntervalMinutes * 60 * 1e3;
|
|
1613
|
+
return { requirementsPath, statePath, logLevel, command, pollIntervalMs, config: config2 };
|
|
1614
|
+
};
|
|
1615
|
+
var validateGitRepo = (cwd = process.cwd()) => {
|
|
1616
|
+
if (!existsSync3(resolve(cwd, ".git"))) {
|
|
1617
|
+
console.error("Error: not a git repository (no .git in current directory)");
|
|
1618
|
+
process.exit(1);
|
|
1619
|
+
}
|
|
1620
|
+
};
|
|
1621
|
+
var validateRequirementsPath = (requirementsPath) => {
|
|
1622
|
+
if (!existsSync3(requirementsPath)) {
|
|
1623
|
+
console.error(`Error: requirements file not found at '${requirementsPath}'`);
|
|
1624
|
+
process.exit(1);
|
|
1625
|
+
}
|
|
1626
|
+
};
|
|
1627
|
+
var createPr = (config2) => {
|
|
1628
|
+
logger().info("No current PR found, starting implementation...");
|
|
1629
|
+
const prompt = buildImplementPrompt(config2.requirementsPath, config2.config.pretext);
|
|
1630
|
+
const result = runAgent(config2.command, prompt);
|
|
1631
|
+
logger().debug("Agent response: " + JSON.stringify(result, null, " "));
|
|
1632
|
+
const prLink = extractPrLink(result.stdout);
|
|
1633
|
+
if (prLink) {
|
|
1634
|
+
writeCurrentPrLink(config2.statePath, prLink);
|
|
1635
|
+
logger().info("PR created:", prLink);
|
|
1636
|
+
return prLink;
|
|
1637
|
+
}
|
|
1638
|
+
logger().error("Failed to extract PR link from agent output");
|
|
1639
|
+
return null;
|
|
1640
|
+
};
|
|
1641
|
+
var reactToThreads = ({ threads, prLink, command, pretext }) => {
|
|
1642
|
+
if (!threads.length) {
|
|
1643
|
+
logger().debug("No actionable threads found");
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
logger().info(`Found ${threads.length} actionable thread(s), invoking agent...`);
|
|
1647
|
+
const result = executeCommentReaction(command, prLink, threads, pretext);
|
|
1648
|
+
logger().debug("Agent response:\n" + JSON.stringify(result, null, " "));
|
|
1649
|
+
logger().info("Finished reacting to threads");
|
|
1650
|
+
};
|
|
1651
|
+
var main = async () => {
|
|
1652
|
+
const config2 = parseArgs(process.argv);
|
|
1653
|
+
validateGitRepo();
|
|
1654
|
+
validateRequirementsPath(config2.requirementsPath);
|
|
1655
|
+
initLogger(config2.logLevel);
|
|
1656
|
+
logger().info("requirements-path:", config2.requirementsPath);
|
|
1657
|
+
logger().info("state-path:", config2.statePath);
|
|
1658
|
+
logger().info("log-level:", config2.logLevel);
|
|
1659
|
+
logger().info("command:", config2.command);
|
|
1660
|
+
logger().info("poll-interval-minutes:", config2.pollIntervalMs / 6e4);
|
|
1661
|
+
while (true) {
|
|
1662
|
+
const existingPrLink = readCurrentPrLink(config2.statePath);
|
|
1663
|
+
if (!existingPrLink) {
|
|
1664
|
+
resetToMain();
|
|
1665
|
+
}
|
|
1666
|
+
const prLink = existingPrLink ?? createPr(config2);
|
|
1667
|
+
if (!prLink) {
|
|
1668
|
+
logger().info("No PR link available, all items may be done");
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1671
|
+
const agentUsername = fetchPrAuthor(prLink);
|
|
1672
|
+
let consecutiveFailures = 0;
|
|
1673
|
+
while (true) {
|
|
1674
|
+
try {
|
|
1675
|
+
if (!isPrOpen(prLink)) break;
|
|
1676
|
+
const mergeConflictMode = config2.config.mergeConflictResolution;
|
|
1677
|
+
let hasConflicts = false;
|
|
1678
|
+
try {
|
|
1679
|
+
hasConflicts = hasMergeConflicts(prLink);
|
|
1680
|
+
} catch (e) {
|
|
1681
|
+
logger().warn(`Failed to check merge conflicts: ${e instanceof Error ? e.message : e}`);
|
|
1682
|
+
}
|
|
1683
|
+
const threads = fetchActionableThreads({
|
|
1684
|
+
prLink,
|
|
1685
|
+
agentUsername,
|
|
1686
|
+
allowlist: config2.config.allowlist ?? DEFAULT_CONFIG.allowlist,
|
|
1687
|
+
requireMention: config2.config.requireMention ?? DEFAULT_CONFIG.requireMention
|
|
1688
|
+
});
|
|
1689
|
+
if (hasConflicts && mergeConflictMode === "always" && threads.length === 0) {
|
|
1690
|
+
logger().info("Merge conflicts detected, invoking agent for conflict resolution...");
|
|
1691
|
+
try {
|
|
1692
|
+
const result = executeConflictResolution(config2.command, prLink, config2.config.pretext);
|
|
1693
|
+
logger().debug("Conflict resolution agent response:\n" + JSON.stringify(result, null, " "));
|
|
1694
|
+
logger().info("Finished conflict resolution attempt");
|
|
1695
|
+
} catch (e) {
|
|
1696
|
+
logger().warn(`Conflict resolution failed: ${e instanceof Error ? e.message : e}`);
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
const reactionPretext = hasConflicts && mergeConflictMode !== "never" && threads.length > 0 ? config2.config.pretext ? `${config2.config.pretext}
|
|
1700
|
+
|
|
1701
|
+
${MERGE_CONFLICT_PRETEXT}` : MERGE_CONFLICT_PRETEXT : config2.config.pretext;
|
|
1702
|
+
reactToThreads({
|
|
1703
|
+
threads,
|
|
1704
|
+
prLink,
|
|
1705
|
+
command: config2.command,
|
|
1706
|
+
pretext: reactionPretext
|
|
1707
|
+
});
|
|
1708
|
+
consecutiveFailures = 0;
|
|
1709
|
+
} catch (error) {
|
|
1710
|
+
consecutiveFailures++;
|
|
1711
|
+
logger().warn(`Failed to fetch PR data (${consecutiveFailures}/${MAX_CONSECUTIVE_POLL_FAILURES}): ${error instanceof Error ? error.message : error}`);
|
|
1712
|
+
if (consecutiveFailures >= MAX_CONSECUTIVE_POLL_FAILURES) {
|
|
1713
|
+
logger().error(`Exiting: ${MAX_CONSECUTIVE_POLL_FAILURES} consecutive poll failures`);
|
|
1714
|
+
return;
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
await sleep(config2.pollIntervalMs);
|
|
1718
|
+
}
|
|
1719
|
+
logger().info("PR is no longer open (merged or closed)");
|
|
1720
|
+
clearCurrentPrLink(config2.statePath);
|
|
1721
|
+
}
|
|
1722
|
+
};
|
|
1723
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
1724
|
+
main();
|
|
1725
|
+
}
|
|
1726
|
+
export {
|
|
1727
|
+
MAX_CONSECUTIVE_POLL_FAILURES,
|
|
1728
|
+
main,
|
|
1729
|
+
parseArgs,
|
|
1730
|
+
validateGitRepo,
|
|
1731
|
+
validateRequirementsPath
|
|
1732
|
+
};
|