agents-relay 1.0.20 → 1.0.21

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
@@ -424,7 +424,8 @@ async function runJobCommand(action, args) {
424
424
  console.log(JSON.stringify({ repository: repo, pr: result.pr.number, job: result.job.id, executionMode: result.job.executionMode, state: result.job.state, task: start ? arg(args, '--task-id', 'initial') : undefined }, null, 2));
425
425
  }
426
426
  export function runtimePlanner(args) { const plannerCommand = arg([...args], '--planner-command'); const modelRuntime = arg([...args], '--codex', 'codex'); return plannerCommand ? new CommandObjectivePlanner(plannerCommand) : new AgentObjectivePlanner(modelRuntime); }
427
- export function runtime(store, args, bus) { const emit = (event) => { process.stderr.write(`${JSON.stringify(event)}\n`); }; const modelRuntime = arg(args, '--codex', 'codex'); const policy = chatGptTabClosePolicy(args); const planner = runtimePlanner(args); return new Reconciler(store, { owner: arg(args, '--owner', `cli-${process.pid}`), maxConcurrent: Number(arg(args, '--concurrency', '4')), leaseMs: Number(arg(args, '--lease-ms', '300000')), adapters: [new CodexAdapter(modelRuntime), new ChatGptAdapter({ tabClosePolicy: policy })], continuations: [new CodexThreadContinuation(modelRuntime), new CommandContinuation(), new WebhookContinuation()], planner, eventBus: bus, emit, chatgptTabClosePolicy: policy }); }
427
+ export function runtimeReviewer() { return { adapter: 'chatgpt', routing: { provider: 'chatgpt', model: 'account-defaults', decidedBy: 'fixed-chatgpt-reviewer', decidedAt: new Date().toISOString() }, startAckTimeoutMs: 120000 }; }
428
+ export function runtime(store, args, bus) { const emit = (event) => { process.stderr.write(`${JSON.stringify(event)}\n`); }; const modelRuntime = arg(args, '--codex', 'codex'); const policy = chatGptTabClosePolicy(args); const planner = runtimePlanner(args); return new Reconciler(store, { owner: arg(args, '--owner', `cli-${process.pid}`), maxConcurrent: Number(arg(args, '--concurrency', '4')), leaseMs: Number(arg(args, '--lease-ms', '300000')), adapters: [new CodexAdapter(modelRuntime), new ChatGptAdapter({ tabClosePolicy: policy })], continuations: [new CodexThreadContinuation(modelRuntime), new CommandContinuation(), new WebhookContinuation()], planner, reviewer: runtimeReviewer(), eventBus: bus, emit, chatgptTabClosePolicy: policy }); }
428
429
  export async function createService(args) {
429
430
  const loaded = await storeFor(args);
430
431
  const upstream = eventBus(args);
@@ -183,7 +183,7 @@ export class Reconciler {
183
183
  return;
184
184
  const id = `final-review-${headSha.slice(0, 12)}`;
185
185
  const now = new Date().toISOString();
186
- 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').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 verify the deterministic pre-review gates have passed, then 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 and do not merge.`, 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 };
186
+ 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').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 and do not merge.`, 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 };
187
187
  await this.store.appendTask(task);
188
188
  job.review = { outcome: 'pending', headSha, taskId: id, evidence: null, updatedAt: now };
189
189
  job.state = 'RUNNING';
@@ -306,7 +306,7 @@ export class Reconciler {
306
306
  const controller = new AbortController();
307
307
  let execution;
308
308
  const workerTask = { ...task, input: workerInput };
309
- const startAckSetup = task.adapter === 'chatgpt' ? await this.startAck(job.id, task.id, Date.now()) : null;
309
+ const startAckSetup = task.adapter === 'chatgpt' ? await this.startAck(job.id, task.id, Date.now(), task.agentName === 'reviewer' ? this.options.reviewer?.startAckTimeoutMs : undefined) : null;
310
310
  const closePolicy = task.chatgptTabClosePolicy ?? this.options.chatgptTabClosePolicy ?? adapter.tabClosePolicy ?? 'after-start';
311
311
  const terminalWait = task.adapter === 'chatgpt' && closePolicy === 'after-terminal'
312
312
  ? this.terminalWait(task.id, durableExecutionId, startedAt - 1)
@@ -338,7 +338,7 @@ export class Reconciler {
338
338
  ? this.failLaunch(job.id, task.id, durableExecutionId, error.message, 'delivery')
339
339
  : this.runtimeSettled(job.id, task.id, durableExecutionId, null, error instanceof Error ? error.message : String(error))), job.id, task.id, 'worker runtime completion');
340
340
  }
341
- async startAck(jobId, taskId, launchBarrier) {
341
+ async startAck(jobId, taskId, launchBarrier, timeoutMs = this.options.startAckTimeoutMs ?? 60000) {
342
342
  if (!this.options.eventBus)
343
343
  throw new Error('Worker start acknowledgement requires an event bus');
344
344
  let resolveAck;
@@ -367,7 +367,7 @@ export class Reconciler {
367
367
  settled = true;
368
368
  void unsubscribe();
369
369
  rejectAck(new StartAckTimeout(`Task ${taskId} worker_start_timeout: no worker task.started start-ack`));
370
- }, this.options.startAckTimeoutMs ?? 60000);
370
+ }, timeoutMs);
371
371
  let stopped = false;
372
372
  const stop = async () => { if (stopped)
373
373
  return; stopped = true; if (timer)
package/dist/relayd.js CHANGED
@@ -11,7 +11,7 @@ import { RepositoryWorkerPool, aggregateManagedGitHubJobs } from './pool.js';
11
11
  import { Reconciler } from './reconciler.js';
12
12
  import { dashboardManagedJobs, GitHubStore, InMemoryStore, loadManagedGitHubPullRequestGraphql } from './store.js';
13
13
  import { githubAuthContext } from './github-auth.js';
14
- import { isEntrypoint, runtimePlanner, startService, SERVICE_DEFAULTS } from './cli.js';
14
+ import { isEntrypoint, runtimePlanner, runtimeReviewer, startService, SERVICE_DEFAULTS } from './cli.js';
15
15
  import { codexAndZaiUsageRegistry } from './usage.js';
16
16
  import { defaultWorkspaceRoot, discoverWorkspaceRepositories } from './workspace.js';
17
17
  export const daemonHelp = `Agents Relay daemon runs the dashboard and worker pool.
@@ -64,7 +64,7 @@ export async function runDaemon(argv) {
64
64
  const trusted = auth.trustedAuthors;
65
65
  const concurrency = Number(value(argv, '--concurrency', '4'));
66
66
  const bus = value(argv, '--events') === 'nats' ? new NatsEventBus(value(argv, '--nats-url', 'nats://127.0.0.1:4222'), value(argv, '--subject-prefix', 'neo.events.job')) : undefined;
67
- const makeReconciler = (store, maxConcurrent) => new Reconciler(store, { owner: `relayd-${process.pid}`, maxConcurrent, leaseMs: Number(value(argv, '--lease-ms', '300000')), adapters: [new CodexAdapter(value(argv, '--codex', 'codex')), new ChatGptAdapter()], continuations: [new CodexThreadContinuation(value(argv, '--codex', 'codex')), new CommandContinuation(), new WebhookContinuation()], planner: runtimePlanner(argv), eventBus: bus });
67
+ const makeReconciler = (store, maxConcurrent) => new Reconciler(store, { owner: `relayd-${process.pid}`, maxConcurrent, leaseMs: Number(value(argv, '--lease-ms', '300000')), adapters: [new CodexAdapter(value(argv, '--codex', 'codex')), new ChatGptAdapter()], continuations: [new CodexThreadContinuation(value(argv, '--codex', 'codex')), new CommandContinuation(), new WebhookContinuation()], planner: runtimePlanner(argv), eventBus: bus, reviewer: runtimeReviewer() });
68
68
  const repositories = normalized.repository
69
69
  ? [normalized.repository]
70
70
  : (await discoverWorkspaceRepositories(normalized.workspaceRoot ?? defaultWorkspaceRoot())).map(item => item.repository);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-relay",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "description": "Durable async agent jobs coordinated through GitHub pull requests",
5
5
  "type": "module",
6
6
  "bin": {