agents-relay 1.0.34 → 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
@@ -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."`,
@@ -329,9 +329,9 @@ function workerTaskFromArgs(job, args, now, requireInput = false) {
329
329
  const outputKind = arg(args, '--output');
330
330
  const outputPath = arg(args, '--output-path');
331
331
  const input = arg(args, '--input');
332
- if (!['codex', 'chatgpt'].includes(adapter))
333
- throw new Error('submit adapter must be codex or chatgpt');
334
- 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)
335
335
  throw new Error('submit requires --model for codex/chatgpt tasks');
336
336
  if (requireInput && !input)
337
337
  throw new Error('job create --start requires --input');
@@ -339,10 +339,10 @@ function workerTaskFromArgs(job, args, now, requireInput = false) {
339
339
  throw new Error('submit requires --output task-pr|file');
340
340
  if (outputKind === 'file' && !outputPath)
341
341
  throw new Error('--output file requires --output-path');
342
- 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 };
343
343
  const closePolicy = hasArg(args, '--chatgpt-tab-close-policy') ? chatGptTabClosePolicy(args) : undefined;
344
344
  const size = storySize(args);
345
- 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);
346
346
  return {
347
347
  jobId: job.id,
348
348
  id: arg(args, '--task-id', 'initial'),
@@ -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
  }
@@ -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.34",
3
+ "version": "1.0.35",
4
4
  "description": "Durable async agent jobs coordinated through GitHub pull requests",
5
5
  "type": "module",
6
6
  "bin": {