agents-relay 2.0.40 → 2.0.42

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/adapters.js CHANGED
@@ -120,7 +120,7 @@ export class CodexAdapter {
120
120
  return execution;
121
121
  }
122
122
  }
123
- export const CHATGPT_BROWSER_WORKSPACE = 'agents-replay';
123
+ export const CHATGPT_BROWSER_WORKSPACE = 'Relay';
124
124
  export const CHATGPT_BROWSER_WORKSPACE_POOL_SIZE = 6;
125
125
  export function chatGptTabClosePolicy(value, fallback = 'after-start') {
126
126
  const policy = value || fallback;
@@ -99,6 +99,29 @@ export class Reconciler extends ReconcilerReviewBase {
99
99
  await this.store.mergePullRequest(headSha);
100
100
  }, context => `effect.mergePullRequest:${context.jobId}:${String(context.data?.headSha ?? 'missing')}`));
101
101
  }
102
+ async dispatchExecutableTasks(jobId) {
103
+ await this.routeExecutableTasks(await this.store.load(jobId));
104
+ const scheduled = schedule(await this.store.load(jobId));
105
+ for (const task of scheduled.tasks.filter(item => item.state === 'SUCCEEDED' && (item.continuation || scheduled.continuation) && !item.continuationDeliveredAt)) {
106
+ this.detach(this.deliverContinuation(scheduled, task), scheduled.id, task.id, 'continuation');
107
+ }
108
+ const capacity = Math.max(0, (this.options.maxConcurrent ?? 4) - this.live.size - this.plannerLive.size);
109
+ const dispatchable = scheduled.tasks
110
+ .filter(task => task.state === 'QUEUED'
111
+ && task.executionId === null
112
+ && task.kind !== 'planner'
113
+ && task.adapter !== 'orchestrator'
114
+ && dependencyReady(task, new Map(scheduled.tasks.map(item => [item.id, item]))))
115
+ .sort((a, b) => compareTaskPriority(a, b, scheduled.priority ?? 'P2'))
116
+ .slice(0, capacity);
117
+ for (const task of dispatchable) {
118
+ await transitionTaskEvent(task, 'dispatch', { dispatchable: true }, async (actionId) => {
119
+ const outcomes = await this.workflowEffects.execute([actionId], { jobId: scheduled.id, taskId: task.id, transitionKey: `dispatch:${task.attempt}`, data: { attempt: task.attempt } });
120
+ await this.applyTaskEffectOutcomes(scheduled, task, outcomes);
121
+ }, async () => { await this.store.saveTask(task); });
122
+ }
123
+ return schedule(await this.store.load(jobId));
124
+ }
102
125
  async reconcile(jobId) {
103
126
  if (this.reconciling)
104
127
  return this.store.load(jobId);
@@ -161,31 +184,14 @@ export class Reconciler extends ReconcilerReviewBase {
161
184
  }
162
185
  if (scheduled.state !== previousState || scheduled.updatedAt !== job.updatedAt)
163
186
  await this.store.saveJob(scheduled);
164
- if (prState === 'OPEN') {
165
- await this.routeExecutableTasks(await this.store.load(jobId));
166
- scheduled = schedule(await this.store.load(jobId));
167
- for (const task of scheduled.tasks.filter(item => item.state === 'SUCCEEDED' && (item.continuation || scheduled.continuation) && !item.continuationDeliveredAt))
168
- this.detach(this.deliverContinuation(scheduled, task), scheduled.id, task.id, 'continuation');
169
- const capacity = Math.max(0, (this.options.maxConcurrent ?? 4) - this.live.size - this.plannerLive.size);
170
- const dispatchable = scheduled.tasks
171
- .filter(task => task.state === 'QUEUED'
172
- && task.executionId === null
173
- && task.kind !== 'planner'
174
- && task.adapter !== 'orchestrator'
175
- && dependencyReady(task, new Map(scheduled.tasks.map(item => [item.id, item]))))
176
- .sort((a, b) => compareTaskPriority(a, b, scheduled.priority ?? 'P2'))
177
- .slice(0, capacity);
178
- for (const task of dispatchable) {
179
- await transitionTaskEvent(task, 'dispatch', { dispatchable: true }, async (actionId) => {
180
- const outcomes = await this.workflowEffects.execute([actionId], { jobId: scheduled.id, taskId: task.id, transitionKey: `dispatch:${task.attempt}`, data: { attempt: task.attempt } });
181
- await this.applyTaskEffectOutcomes(scheduled, task, outcomes);
182
- }, async () => { await this.store.saveTask(task); });
183
- }
184
- }
187
+ if (prState === 'OPEN')
188
+ scheduled = await this.dispatchExecutableTasks(jobId);
185
189
  const finalState = schedule(await this.store.load(jobId));
186
190
  if (finalState.updatedAt !== scheduled.updatedAt)
187
191
  await this.store.saveJob(finalState);
188
192
  await this.ensureFinalReview(finalState, prState, headSha);
193
+ if (prState === 'OPEN')
194
+ await this.dispatchExecutableTasks(jobId);
189
195
  await dispatchJobReconcile(finalState, { prState, headSha, mergeCapable: Boolean(this.store.mergePullRequest) }, async (actionId) => {
190
196
  const outcomes = await this.workflowEffects.execute([actionId], { jobId: finalState.id, transitionKey: `reconcile:${headSha ?? 'no-head'}`, data: { headSha } });
191
197
  await this.applyJobEffectOutcomes(finalState, outcomes);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-relay",
3
- "version": "2.0.40",
3
+ "version": "2.0.42",
4
4
  "description": "Durable async agent jobs coordinated through GitHub pull requests",
5
5
  "type": "module",
6
6
  "bin": {