agents-relay 1.0.25 → 1.0.27
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/cli.js +7 -4
- package/dist/reconciler.js +14 -1
- package/dist/store.js +11 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -61,7 +61,7 @@ Example:
|
|
|
61
61
|
'job create': `Create or reuse an open PR and persist one durable job marker.
|
|
62
62
|
|
|
63
63
|
Required: --repo OWNER/REPO, --id JOB_ID, and --head BRANCH.
|
|
64
|
-
Common: --base BRANCH (default: main), --title TEXT, --body TEXT, --mode fixed|autonomous.
|
|
64
|
+
Common: --base BRANCH (default: main), --title TEXT, --body TEXT, --mode fixed|autonomous, --no-auto-merge.
|
|
65
65
|
With --start, also require --adapter codex|chatgpt, --model MODEL, --output task-pr|file,
|
|
66
66
|
and --input TEXT. The initial task ID defaults to 'initial'; use --task-id to override it.
|
|
67
67
|
|
|
@@ -70,7 +70,7 @@ Example:
|
|
|
70
70
|
'job adopt': `Adopt an existing PR as a durable job.
|
|
71
71
|
|
|
72
72
|
Required: --repo OWNER/REPO, --pr NUMBER, and --id JOB_ID.
|
|
73
|
-
Common: --title TEXT, --objective TEXT, --mode fixed|autonomous.
|
|
73
|
+
Common: --title TEXT, --objective TEXT, --mode fixed|autonomous, --no-auto-merge.
|
|
74
74
|
|
|
75
75
|
Example:
|
|
76
76
|
npx agents-relay job adopt --repo OWNER/REPO --pr 12 --id job-12 --title "Objective"`,
|
|
@@ -247,7 +247,7 @@ export async function ensureManagedGitHubJob(client, repositoryName, trustedAuth
|
|
|
247
247
|
if (!(error instanceof Error) || !error.message.includes('has no durable'))
|
|
248
248
|
throw error;
|
|
249
249
|
const now = new Date().toISOString();
|
|
250
|
-
job = { id: options.id, title: options.title || pr.title || 'Agents Relay job', objective: options.objective || pr.body || undefined, description: pr.body || undefined, priority: options.priority ?? 'P2', executionMode: options.executionMode ?? 'fixed', prNumber: pr.number, repository: repositoryName, state: 'OPEN', continuation: options.continuation ?? null, createdAt: now, updatedAt: now, tasks: [] };
|
|
250
|
+
job = { id: options.id, title: options.title || pr.title || 'Agents Relay job', objective: options.objective || pr.body || undefined, description: pr.body || undefined, priority: options.priority ?? 'P2', executionMode: options.executionMode ?? 'fixed', autoMerge: options.autoMerge ?? true, prNumber: pr.number, repository: repositoryName, state: 'OPEN', continuation: options.continuation ?? null, createdAt: now, updatedAt: now, tasks: [] };
|
|
251
251
|
}
|
|
252
252
|
if (!job.description && pr.body)
|
|
253
253
|
job.description = pr.body;
|
|
@@ -255,6 +255,8 @@ export async function ensureManagedGitHubJob(client, repositoryName, trustedAuth
|
|
|
255
255
|
job.objective = options.objective;
|
|
256
256
|
if (options.executionMode)
|
|
257
257
|
job.executionMode = options.executionMode;
|
|
258
|
+
if (options.autoMerge !== undefined)
|
|
259
|
+
job.autoMerge = options.autoMerge;
|
|
258
260
|
if (options.priority)
|
|
259
261
|
job.priority = options.priority;
|
|
260
262
|
else if (!job.priority)
|
|
@@ -405,6 +407,7 @@ async function runJobCommand(action, args) {
|
|
|
405
407
|
objective: arg(args, '--objective') || undefined,
|
|
406
408
|
priority: priority(args),
|
|
407
409
|
executionMode: requestedExecutionMode(args),
|
|
410
|
+
autoMerge: !hasArg(args, '--no-auto-merge'),
|
|
408
411
|
continuation: continuation(args),
|
|
409
412
|
prNumber,
|
|
410
413
|
head: arg(args, '--head') || undefined,
|
|
@@ -518,7 +521,7 @@ async function main() {
|
|
|
518
521
|
}
|
|
519
522
|
if (command === 'init') {
|
|
520
523
|
const now = new Date().toISOString();
|
|
521
|
-
const job = { id: arg(args, '--id', randomUUID()), title: arg(args, '--title', 'Agents Relay job'), objective: arg(args, '--objective') || undefined, priority: priority(args), executionMode: executionMode(args), prNumber: Number(arg(args, '--pr', '0')), repository: arg(args, '--repo'), state: 'OPEN', continuation: continuation(args), createdAt: now, updatedAt: now, tasks: [] };
|
|
524
|
+
const job = { id: arg(args, '--id', randomUUID()), title: arg(args, '--title', 'Agents Relay job'), objective: arg(args, '--objective') || undefined, priority: priority(args), executionMode: executionMode(args), autoMerge: !hasArg(args, '--no-auto-merge'), prNumber: Number(arg(args, '--pr', '0')), repository: arg(args, '--repo'), state: 'OPEN', continuation: continuation(args), createdAt: now, updatedAt: now, tasks: [] };
|
|
522
525
|
let store;
|
|
523
526
|
let file = null;
|
|
524
527
|
if (arg(args, '--repo') && arg(args, '--pr'))
|
package/dist/reconciler.js
CHANGED
|
@@ -203,7 +203,7 @@ export class Reconciler {
|
|
|
203
203
|
return;
|
|
204
204
|
const id = `final-review-${headSha.slice(0, 12)}`;
|
|
205
205
|
const now = new Date().toISOString();
|
|
206
|
-
const task = { jobId: job.id, id, kind: 'work', priority: job.priority, projectName: job.title, agentName: 'reviewer', parentTaskId: null, dependencies: job.tasks.filter(item => item.agentName !== 'reviewer' && !this.isSupersededTask(item)).map(item => item.id), capabilities: ['review'], adapter: this.options.reviewer?.adapter ?? 'codex', input: `Review PR #${job.prNumber} at head SHA ${headSha}. Objective: ${job.objective ?? job.description ?? job.title}. First publish task.started as the worker start acknowledgement with data.worker_owned=true, then verify the deterministic pre-review gates have passed and inspect the completed work. Emit review.started, then exactly one of review.approved, review.changes_required, or review.blocked with data.review.headSha set to ${headSha}. Do not modify code
|
|
206
|
+
const task = { jobId: job.id, id, kind: 'work', priority: job.priority, projectName: job.title, agentName: 'reviewer', parentTaskId: null, dependencies: job.tasks.filter(item => item.agentName !== 'reviewer' && !this.isSupersededTask(item)).map(item => item.id), capabilities: ['review'], adapter: this.options.reviewer?.adapter ?? 'codex', input: `Review PR #${job.prNumber} at head SHA ${headSha}. Objective: ${job.objective ?? job.description ?? job.title}. First publish task.started as the worker start acknowledgement with data.worker_owned=true, then verify the deterministic pre-review gates have passed and inspect the completed work. Emit review.started, then exactly one of review.approved, review.changes_required, or review.blocked with data.review.headSha set to ${headSha}. Do not modify code. When auto-merge is enabled, Relay will merge this exact reviewed head after review.approved.`, output: { kind: 'task_pr' }, routing: this.options.reviewer?.routing, continuation: null, continuationDeliveredAt: null, reviewHeadSha: headSha, state: 'QUEUED', attempt: 0, maxAttempts: this.options.reviewer?.maxAttempts ?? 2, leaseOwner: null, leaseExpiresAt: null, executionId: null, threadId: null, result: null, plannerResult: null, error: null, timeoutMs: this.options.reviewer?.timeoutMs ?? 300000, createdAt: now, updatedAt: now };
|
|
207
207
|
await this.store.appendTask(task);
|
|
208
208
|
job.review = { outcome: 'pending', headSha, taskId: id, evidence: null, updatedAt: now };
|
|
209
209
|
job.state = 'RUNNING';
|
|
@@ -235,8 +235,21 @@ export class Reconciler {
|
|
|
235
235
|
return;
|
|
236
236
|
const evidence = { summary: event.message || `Review ${outcome}`, data: { ...(event.data ?? {}), review: reviewData ?? { headSha }, headSha, outcome } };
|
|
237
237
|
job.review = { outcome, headSha, taskId: task.id, evidence, updatedAt: event.timestamp || new Date().toISOString() };
|
|
238
|
+
if (outcome !== 'started') {
|
|
239
|
+
task.state = 'SUCCEEDED';
|
|
240
|
+
task.result = evidence;
|
|
241
|
+
task.error = null;
|
|
242
|
+
task.leaseOwner = null;
|
|
243
|
+
task.leaseExpiresAt = null;
|
|
244
|
+
task.updatedAt = job.review.updatedAt;
|
|
245
|
+
await this.store.saveTask(task);
|
|
246
|
+
}
|
|
238
247
|
job.updatedAt = job.review.updatedAt;
|
|
239
248
|
await this.store.saveJob(job);
|
|
249
|
+
if (outcome === 'approved' && job.autoMerge !== false && this.store.mergePullRequest) {
|
|
250
|
+
await this.store.mergePullRequest(headSha);
|
|
251
|
+
await this.emit(eventFor(job.id, task.id, task.parentTaskId, 'review.merged', 'succeeded', 'Reviewer-approved PR #' + job.prNumber + ' merged', 'user', { headSha, autoMerge: true }, { agent: 'reviewer', component: 'agents-relay' }));
|
|
252
|
+
}
|
|
240
253
|
}
|
|
241
254
|
async recoverLostExecutions(job, now) {
|
|
242
255
|
for (const task of job.tasks.filter(item => item.state === 'RUNNING')) {
|
package/dist/store.js
CHANGED
|
@@ -461,6 +461,17 @@ export class GitHubStore {
|
|
|
461
461
|
return 'MERGED';
|
|
462
462
|
return String(pr.state ?? '').toUpperCase() === 'CLOSED' ? 'CLOSED' : 'OPEN';
|
|
463
463
|
}
|
|
464
|
+
async mergePullRequest(expectedHeadSha) {
|
|
465
|
+
const payload = { merge_method: 'squash' };
|
|
466
|
+
if (expectedHeadSha)
|
|
467
|
+
payload.sha = expectedHeadSha;
|
|
468
|
+
const result = await this.client.request('repos/' + this.repository + '/pulls/' + this.prNumber + '/merge', {
|
|
469
|
+
method: 'PUT',
|
|
470
|
+
body: JSON.stringify(payload),
|
|
471
|
+
});
|
|
472
|
+
if (result.merged !== true)
|
|
473
|
+
throw new Error(typeof result.message === 'string' ? result.message : 'Pull request #' + this.prNumber + ' was not merged');
|
|
474
|
+
}
|
|
464
475
|
async headSha() {
|
|
465
476
|
const { owner, name } = this.repoParts();
|
|
466
477
|
const data = await this.graphql('query($owner:String!,$name:String!,$number:Int!){repository(owner:$owner,name:$name){pullRequest(number:$number){headRefOid}}}', { owner, name, number: this.prNumber });
|