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 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, --model MODEL, and --output task-pr|file. 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.
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 chatgpt');
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.reasoning)) : taskOverallTimeoutMs(size, routing.reasoning);
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'))
@@ -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())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-relay",
3
- "version": "1.0.33",
3
+ "version": "1.0.35",
4
4
  "description": "Durable async agent jobs coordinated through GitHub pull requests",
5
5
  "type": "module",
6
6
  "bin": {