next-issue 2.5.7 → 2.5.9
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/README.md +3 -1
- package/dist/agents.mjs +1 -0
- package/dist/github.mjs +26 -10
- package/dist/protocol.mjs +37 -0
- package/dist/serve.mjs +12 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -249,7 +249,9 @@ Three levels of console output:
|
|
|
249
249
|
level and the extensions from your pi settings, except the `pi-next-issue`
|
|
250
250
|
extension. The implementer and the fixer get the default tools of your pi
|
|
251
251
|
settings, the `grep`, `find` and `ls` tools and the tools of your
|
|
252
|
-
extensions. The reviewer gets all of them except `edit` and `write`.
|
|
252
|
+
extensions. The reviewer gets all of them except `edit` and `write`. The
|
|
253
|
+
agents run with `GIT_OPTIONAL_LOCKS=0`, so a `git status` from an agent or
|
|
254
|
+
an extension does not hold the index lock while the harness commits.
|
|
253
255
|
|
|
254
256
|
## Configuration
|
|
255
257
|
|
package/dist/agents.mjs
CHANGED
|
@@ -17,6 +17,7 @@ export async function runAgent(recorder, request) {
|
|
|
17
17
|
const runtime = request.runtime ?? {};
|
|
18
18
|
const agentDir = runtime.agentDir ?? getAgentDir();
|
|
19
19
|
const started = Date.now();
|
|
20
|
+
process.env.GIT_OPTIONAL_LOCKS = '0';
|
|
20
21
|
log.event('agent.start', { model: request.model, timeoutMs: request.timeoutMs }, 'normal');
|
|
21
22
|
const resourceLoader = new DefaultResourceLoader({
|
|
22
23
|
cwd: request.cwd,
|
package/dist/github.mjs
CHANGED
|
@@ -62,7 +62,7 @@ export async function openIssues(repo, limit, labels) {
|
|
|
62
62
|
ISSUE_FIELDS,
|
|
63
63
|
]);
|
|
64
64
|
const parsed = JSON.parse(raw);
|
|
65
|
-
return parsed.map(toIssue)
|
|
65
|
+
return parsed.map(toIssue);
|
|
66
66
|
}
|
|
67
67
|
export async function viewIssue(repo, issue) {
|
|
68
68
|
const raw = await gh(repo, ['issue', 'view', String(issue), '--json', `${ISSUE_FIELDS},state`]);
|
|
@@ -100,11 +100,25 @@ export function labelArgs(add, remove, current) {
|
|
|
100
100
|
return args;
|
|
101
101
|
}
|
|
102
102
|
export async function setLabel(repo, kind, number, add, remove) {
|
|
103
|
-
await
|
|
103
|
+
await createUnknownLabel(repo, add);
|
|
104
104
|
const current = await labelsOf(repo, kind, number);
|
|
105
|
-
|
|
105
|
+
const args = [kind, 'edit', String(number), ...labelArgs(add, remove, current)];
|
|
106
|
+
try {
|
|
107
|
+
await gh(repo, args);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
KNOWN_LABELS.delete(slug(repo));
|
|
111
|
+
const created = await createUnknownLabel(repo, add);
|
|
112
|
+
if (created === 'known') {
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
if (created instanceof Error) {
|
|
116
|
+
throw created;
|
|
117
|
+
}
|
|
118
|
+
await gh(repo, args);
|
|
119
|
+
}
|
|
106
120
|
}
|
|
107
|
-
async function
|
|
121
|
+
async function createUnknownLabel(repo, label) {
|
|
108
122
|
let known = KNOWN_LABELS.get(slug(repo));
|
|
109
123
|
if (known === undefined) {
|
|
110
124
|
const raw = await gh(repo, ['label', 'list', '--limit', '1000', '--json', 'name']);
|
|
@@ -112,14 +126,16 @@ async function ensureLabel(repo, label) {
|
|
|
112
126
|
KNOWN_LABELS.set(slug(repo), known);
|
|
113
127
|
}
|
|
114
128
|
if (known.has(label)) {
|
|
115
|
-
return;
|
|
129
|
+
return 'known';
|
|
116
130
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
131
|
+
try {
|
|
132
|
+
await ghOnce(repo, ['label', 'create', label]);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
122
136
|
}
|
|
137
|
+
known.add(label);
|
|
138
|
+
return 'created';
|
|
123
139
|
}
|
|
124
140
|
export async function findPr(repo, branch) {
|
|
125
141
|
const raw = await gh(repo, [
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function isNewer(candidate, current) {
|
|
2
|
+
const [leftCore = '', ...leftRest] = candidate.replace(/\+.*$/, '').split('-');
|
|
3
|
+
const [rightCore = '', ...rightRest] = current.replace(/\+.*$/, '').split('-');
|
|
4
|
+
const left = leftCore.split('.').map(Number);
|
|
5
|
+
const right = rightCore.split('.').map(Number);
|
|
6
|
+
for (let index = 0; index < Math.max(left.length, right.length); index += 1) {
|
|
7
|
+
const difference = (left[index] ?? 0) - (right[index] ?? 0);
|
|
8
|
+
if (difference !== 0) {
|
|
9
|
+
return difference > 0;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const leftPrerelease = leftRest.length > 0 ? leftRest.join('-').split('.') : [];
|
|
13
|
+
const rightPrerelease = rightRest.length > 0 ? rightRest.join('-').split('.') : [];
|
|
14
|
+
if (leftPrerelease.length === 0 || rightPrerelease.length === 0) {
|
|
15
|
+
return leftPrerelease.length === 0 && rightPrerelease.length > 0;
|
|
16
|
+
}
|
|
17
|
+
for (let index = 0; index < Math.max(leftPrerelease.length, rightPrerelease.length); index += 1) {
|
|
18
|
+
const leftPart = leftPrerelease[index];
|
|
19
|
+
const rightPart = rightPrerelease[index];
|
|
20
|
+
if (leftPart === undefined || rightPart === undefined) {
|
|
21
|
+
return rightPart === undefined;
|
|
22
|
+
}
|
|
23
|
+
if (leftPart === rightPart) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const leftNumeric = /^\d+$/.test(leftPart);
|
|
27
|
+
const rightNumeric = /^\d+$/.test(rightPart);
|
|
28
|
+
if (leftNumeric && rightNumeric) {
|
|
29
|
+
return Number(leftPart) > Number(rightPart);
|
|
30
|
+
}
|
|
31
|
+
if (leftNumeric || rightNumeric) {
|
|
32
|
+
return rightNumeric;
|
|
33
|
+
}
|
|
34
|
+
return leftPart > rightPart;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
package/dist/serve.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { rmSync } from 'node:fs';
|
|
2
|
-
import {
|
|
2
|
+
import { readFile, rm, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { createServer } from 'node:http';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { getAgentDir } from '@earendil-works/pi-coding-agent';
|
|
@@ -8,6 +8,7 @@ import { parseArgs } from './args.mjs';
|
|
|
8
8
|
import { stopChildren } from './exec.mjs';
|
|
9
9
|
import { message } from './observe.mjs';
|
|
10
10
|
import { applyEvent, startProgress } from './progress.mjs';
|
|
11
|
+
import { isNewer } from './protocol.mjs';
|
|
11
12
|
import { runRepo } from './run.mjs';
|
|
12
13
|
import { packageVersion } from './version.mjs';
|
|
13
14
|
export function socketPaths(agentDir = getAgentDir()) {
|
|
@@ -16,17 +17,6 @@ export function socketPaths(agentDir = getAgentDir()) {
|
|
|
16
17
|
lockPath: join(agentDir, 'next-issue.lock'),
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
|
-
export function isNewer(candidate, current) {
|
|
20
|
-
const left = candidate.split('.').map(Number);
|
|
21
|
-
const right = current.split('.').map(Number);
|
|
22
|
-
for (let index = 0; index < Math.max(left.length, right.length); index += 1) {
|
|
23
|
-
const difference = (left[index] ?? 0) - (right[index] ?? 0);
|
|
24
|
-
if (difference !== 0) {
|
|
25
|
-
return difference > 0;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
20
|
function alive(pid) {
|
|
31
21
|
try {
|
|
32
22
|
process.kill(pid, 0);
|
|
@@ -191,12 +181,17 @@ export async function startWorker(options) {
|
|
|
191
181
|
});
|
|
192
182
|
await new Promise((resolve, reject) => {
|
|
193
183
|
server.once('error', reject);
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
184
|
+
const umask = process.umask(0o177);
|
|
185
|
+
try {
|
|
186
|
+
server.listen(options.socketPath, () => {
|
|
187
|
+
server.off('error', reject);
|
|
188
|
+
resolve();
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
process.umask(umask);
|
|
193
|
+
}
|
|
198
194
|
});
|
|
199
|
-
await chmod(options.socketPath, 0o600);
|
|
200
195
|
return { closed, close };
|
|
201
196
|
}
|
|
202
197
|
export async function serve() {
|