agents-relay 1.0.33 → 1.0.35
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 +12 -9
- package/dist/reconciler.js +10 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -65,7 +65,7 @@ Example:
|
|
|
65
65
|
'job create': `Create or reuse an open PR and persist one durable job marker.
|
|
66
66
|
|
|
67
67
|
Required: --repo OWNER/REPO, --id JOB_ID, and --head BRANCH.
|
|
68
|
-
Common: --base BRANCH (default: main), --title TEXT, --body TEXT, --mode fixed|autonomous, --no-auto-merge.
|
|
68
|
+
Common: --base BRANCH (default: main), --title TEXT, --body TEXT, --mode fixed|autonomous, --no-auto-merge, --no-review.
|
|
69
69
|
With --start, also require --adapter codex|chatgpt, --model MODEL, --output task-pr|file,
|
|
70
70
|
and --input TEXT. The initial task ID defaults to 'initial'; use --task-id to override it.
|
|
71
71
|
|
|
@@ -117,7 +117,7 @@ Example:
|
|
|
117
117
|
submit: `Queue a task for a managed job.
|
|
118
118
|
|
|
119
119
|
Required: --repo OWNER/REPO, --pr NUMBER, --id JOB_ID, and --input TEXT.
|
|
120
|
-
Required for worker tasks: --adapter codex|chatgpt
|
|
120
|
+
Required for worker tasks: --adapter codex|chatgpt|orchestrator and --output task-pr|file. Codex/ChatGPT also require --model MODEL. File output also requires --output-path PATH.\nCommon: --task-id ID, --priority P0|P1|P2|P3, --story-size S|M|L, --max-attempts N. Story size defaults to M. Task producers follow the shared Task / Job Contract; prefer --story-size over raw --timeout. Model-backed execution requires --events nats in the running reconciler/daemon.
|
|
121
121
|
|
|
122
122
|
Example:
|
|
123
123
|
npx agents-relay submit --repo OWNER/REPO --pr 12 --id job-1 --task-id build --adapter codex --provider openai --model gpt-5-6 --output task-pr --input "Run the required tests and report the result through events."`,
|
|
@@ -270,7 +270,7 @@ export async function ensureManagedGitHubJob(client, repositoryName, trustedAuth
|
|
|
270
270
|
if (!(error instanceof Error) || !error.message.includes('has no durable'))
|
|
271
271
|
throw error;
|
|
272
272
|
const now = new Date().toISOString();
|
|
273
|
-
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, initialPlanning: options.initialTasks?.length ? { status: 'pending', decisionId: 'planner-0' } : undefined, createdAt: now, updatedAt: now, tasks: [] };
|
|
273
|
+
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, reviewEnabled: options.reviewEnabled ?? true, prNumber: pr.number, repository: repositoryName, state: 'OPEN', continuation: options.continuation ?? null, initialPlanning: options.initialTasks?.length ? { status: 'pending', decisionId: 'planner-0' } : undefined, createdAt: now, updatedAt: now, tasks: [] };
|
|
274
274
|
}
|
|
275
275
|
if (!job.description && pr.body)
|
|
276
276
|
job.description = pr.body;
|
|
@@ -280,6 +280,8 @@ export async function ensureManagedGitHubJob(client, repositoryName, trustedAuth
|
|
|
280
280
|
job.executionMode = options.executionMode;
|
|
281
281
|
if (options.autoMerge !== undefined)
|
|
282
282
|
job.autoMerge = options.autoMerge;
|
|
283
|
+
if (options.reviewEnabled !== undefined)
|
|
284
|
+
job.reviewEnabled = options.reviewEnabled;
|
|
283
285
|
if (options.priority)
|
|
284
286
|
job.priority = options.priority;
|
|
285
287
|
else if (!job.priority)
|
|
@@ -327,9 +329,9 @@ function workerTaskFromArgs(job, args, now, requireInput = false) {
|
|
|
327
329
|
const outputKind = arg(args, '--output');
|
|
328
330
|
const outputPath = arg(args, '--output-path');
|
|
329
331
|
const input = arg(args, '--input');
|
|
330
|
-
if (!['codex', 'chatgpt'].includes(adapter))
|
|
331
|
-
throw new Error('submit adapter must be codex or
|
|
332
|
-
if (!model)
|
|
332
|
+
if (!['codex', 'chatgpt', 'orchestrator'].includes(adapter))
|
|
333
|
+
throw new Error('submit adapter must be codex, chatgpt, or orchestrator');
|
|
334
|
+
if (adapter !== 'orchestrator' && !model)
|
|
333
335
|
throw new Error('submit requires --model for codex/chatgpt tasks');
|
|
334
336
|
if (requireInput && !input)
|
|
335
337
|
throw new Error('job create --start requires --input');
|
|
@@ -337,10 +339,10 @@ function workerTaskFromArgs(job, args, now, requireInput = false) {
|
|
|
337
339
|
throw new Error('submit requires --output task-pr|file');
|
|
338
340
|
if (outputKind === 'file' && !outputPath)
|
|
339
341
|
throw new Error('--output file requires --output-path');
|
|
340
|
-
const routing = { provider: arg(args, '--provider', 'openai'), model, profile: arg(args, '--profile') || undefined, reasoning: arg(args, '--reasoning') || undefined, cwd: arg(args, '--cwd') || undefined, projectId: arg(args, '--chatgpt-project') || undefined, decidedBy: 'cli', decidedAt: now };
|
|
342
|
+
const routing = adapter === 'orchestrator' ? undefined : { provider: arg(args, '--provider', 'openai'), model, profile: arg(args, '--profile') || undefined, reasoning: arg(args, '--reasoning') || undefined, cwd: arg(args, '--cwd') || undefined, projectId: arg(args, '--chatgpt-project') || undefined, decidedBy: 'cli', decidedAt: now };
|
|
341
343
|
const closePolicy = hasArg(args, '--chatgpt-tab-close-policy') ? chatGptTabClosePolicy(args) : undefined;
|
|
342
344
|
const size = storySize(args);
|
|
343
|
-
const timeoutMs = hasArg(args, '--timeout') ? integerArg(args, '--timeout', taskOverallTimeoutMs(size, routing
|
|
345
|
+
const timeoutMs = adapter === 'orchestrator' ? 0 : hasArg(args, '--timeout') ? integerArg(args, '--timeout', taskOverallTimeoutMs(size, routing?.reasoning)) : taskOverallTimeoutMs(size, routing?.reasoning);
|
|
344
346
|
return {
|
|
345
347
|
jobId: job.id,
|
|
346
348
|
id: arg(args, '--task-id', 'initial'),
|
|
@@ -492,6 +494,7 @@ async function runJobCommand(action, args) {
|
|
|
492
494
|
priority: priority(args),
|
|
493
495
|
executionMode: requestedExecutionMode(args),
|
|
494
496
|
autoMerge: !hasArg(args, '--no-auto-merge'),
|
|
497
|
+
reviewEnabled: !hasArg(args, '--no-review'),
|
|
495
498
|
continuation: continuation(args),
|
|
496
499
|
prNumber,
|
|
497
500
|
head: arg(args, '--head') || undefined,
|
|
@@ -603,7 +606,7 @@ async function main() {
|
|
|
603
606
|
}
|
|
604
607
|
if (command === 'init') {
|
|
605
608
|
const now = new Date().toISOString();
|
|
606
|
-
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: [] };
|
|
609
|
+
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'), reviewEnabled: !hasArg(args, '--no-review'), prNumber: Number(arg(args, '--pr', '0')), repository: arg(args, '--repo'), state: 'OPEN', continuation: continuation(args), createdAt: now, updatedAt: now, tasks: [] };
|
|
607
610
|
let store;
|
|
608
611
|
let file = null;
|
|
609
612
|
if (arg(args, '--repo') && arg(args, '--pr'))
|
package/dist/reconciler.js
CHANGED
|
@@ -160,6 +160,14 @@ export class Reconciler {
|
|
|
160
160
|
for (const task of scheduled.tasks.filter(t => t.state === 'READY').sort((a, b) => compareTaskPriority(a, b, scheduled.priority ?? 'P2')).slice(0, capacity)) {
|
|
161
161
|
if (task.kind === 'planner')
|
|
162
162
|
await this.launchPlanner(scheduled, task);
|
|
163
|
+
else if (task.adapter === 'orchestrator') {
|
|
164
|
+
transitionTask(task, 'RUNNING');
|
|
165
|
+
task.leaseOwner = null;
|
|
166
|
+
task.leaseExpiresAt = null;
|
|
167
|
+
task.executionId = null;
|
|
168
|
+
await this.store.saveTask(task);
|
|
169
|
+
await this.emit(eventFor(scheduled.id, task.id, task.parentTaskId, 'task.orchestrator_assigned', 'running', `Task ${task.id} assigned to orchestrator self`, 'orchestrator', { adapter: 'orchestrator' }, { agent: 'relay', component: 'agents-relay' }));
|
|
170
|
+
}
|
|
163
171
|
else
|
|
164
172
|
await this.launch(scheduled, task);
|
|
165
173
|
}
|
|
@@ -199,7 +207,7 @@ export class Reconciler {
|
|
|
199
207
|
await this.store.saveJob(job);
|
|
200
208
|
}
|
|
201
209
|
async ensureFinalReview(job, prState, headSha) {
|
|
202
|
-
if (prState !== 'OPEN' || job.state !== 'COMPLETED' || !headSha)
|
|
210
|
+
if (job.reviewEnabled === false || prState !== 'OPEN' || job.state !== 'COMPLETED' || !headSha)
|
|
203
211
|
return;
|
|
204
212
|
if (!this.preReviewGatesPass(job))
|
|
205
213
|
return;
|
|
@@ -675,7 +683,7 @@ export class Reconciler {
|
|
|
675
683
|
async applyTerminalEvent(event) {
|
|
676
684
|
const job = await this.store.load(event.job_id);
|
|
677
685
|
const task = job.tasks.find(item => item.id === event.task_id);
|
|
678
|
-
if (!task || !['codex', 'chatgpt'].includes(task.adapter))
|
|
686
|
+
if (!task || !['codex', 'chatgpt', 'orchestrator'].includes(task.adapter))
|
|
679
687
|
return;
|
|
680
688
|
if (task.state === 'FAILED' && this.isRecoverableWatchdogFailure(task) && this.isWorkerOwnedEvent(event)) {
|
|
681
689
|
if (event.timestamp && new Date(event.timestamp).getTime() < new Date(task.updatedAt).getTime())
|