agents-relay 2.0.29 → 2.0.31

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.
@@ -73,8 +73,15 @@ export async function relayControlJob(args, jobId) {
73
73
  if (!Number.isInteger(port) || port <= 0 || port > 65535)
74
74
  throw new Error('--port must be an integer between 1 and 65535');
75
75
  let response;
76
+ const params = new URLSearchParams({ id: jobId });
77
+ const repo = arg(args, '--repo');
78
+ const pr = Number(arg(args, '--pr'));
79
+ if (repo)
80
+ params.set('repo', repo);
81
+ if (Number.isInteger(pr) && pr > 0)
82
+ params.set('pr', String(pr));
76
83
  try {
77
- response = await fetch(`http://${host}:${port}/api/job?id=${encodeURIComponent(jobId)}`);
84
+ response = await fetch(`http://${host}:${port}/api/job?${params.toString()}`);
78
85
  }
79
86
  catch (error) {
80
87
  throw new Error(`Agents Relay service unavailable at ${host}:${port}: ${error instanceof Error ? error.message : String(error)}`);
package/dist/dashboard.js CHANGED
@@ -110,11 +110,11 @@ export function serveDashboard(store, port = 8787, bus, refreshMs = 300000, jobI
110
110
  }
111
111
  }
112
112
  };
113
- const snapshot = async (requestedJobId = jobId, forceRefresh = false) => {
113
+ const snapshot = async (requestedJobId = jobId, forceRefresh = false, target) => {
114
114
  await subscribeDiscovered();
115
115
  if (overviewProvider) {
116
116
  if (forceRefresh && requestedJobId && resolvedExactJobProvider) {
117
- const exact = await resolvedExactJobProvider(requestedJobId);
117
+ const exact = await resolvedExactJobProvider(requestedJobId, target);
118
118
  if (exact)
119
119
  return { id: exact.id, json: JSON.stringify(exact) };
120
120
  }
@@ -371,8 +371,12 @@ export function serveDashboard(store, port = 8787, bus, refreshMs = 300000, jobI
371
371
  }
372
372
  if (new URL(req.url ?? '/', 'http://127.0.0.1').pathname === '/api/job') {
373
373
  try {
374
- const requestedJobId = new URL(req.url ?? '/', 'http://127.0.0.1').searchParams.get('id') ?? undefined;
375
- const body = (await snapshot(requestedJobId, true)).json;
374
+ const url = new URL(req.url ?? '/', 'http://127.0.0.1');
375
+ const requestedJobId = url.searchParams.get('id') ?? undefined;
376
+ const repository = url.searchParams.get('repo') ?? undefined;
377
+ const parsedPr = Number(url.searchParams.get('pr'));
378
+ const prNumber = Number.isInteger(parsedPr) && parsedPr > 0 ? parsedPr : undefined;
379
+ const body = (await snapshot(requestedJobId, true, { repository, prNumber })).json;
376
380
  if (!res.headersSent)
377
381
  res.writeHead(200, { 'content-type': 'application/json' });
378
382
  if (!res.writableEnded)
package/dist/relayd.js CHANGED
@@ -320,10 +320,17 @@ export async function runDaemon(argv) {
320
320
  cachedOverviews = dashboardManagedJobs(cachedOverviews);
321
321
  }
322
322
  } : undefined;
323
- const exactJob = async (jobId) => {
324
- const cached = cachedOverviews.find(item => item.job.id === jobId);
323
+ const exactJob = async (jobId, target) => {
324
+ let cached = cachedOverviews.find(item => item.job.id === jobId);
325
+ if (!cached && target?.repository && target.prNumber && repositories.includes(target.repository)) {
326
+ cached = (await refreshPullRequest(target.repository, target.prNumber, 'control.job-lookup', { force: true })).find(item => item.job.id === jobId);
327
+ }
325
328
  if (!cached)
326
329
  return null;
330
+ if (target?.repository && cached.job.repository !== target.repository)
331
+ return null;
332
+ if (target?.prNumber && cached.job.prNumber !== target.prNumber)
333
+ return null;
327
334
  const cachedJob = () => ({ ...cached.job, githubState: cached.githubState, runtimeStatus: deriveJobRuntimeStatus(cached.job, cached.githubState), mergedAt: cached.mergedAt, closedAt: cached.closedAt, draft: cached.draft, publication: cached.publication });
328
335
  if (client.rateLimitStatus().limited)
329
336
  return cachedJob();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-relay",
3
- "version": "2.0.29",
3
+ "version": "2.0.31",
4
4
  "description": "Durable async agent jobs coordinated through GitHub pull requests",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,6 +6,25 @@ Before `job create`, the orchestrator converts the relevant discussion into a st
6
6
 
7
7
  This contract defines orchestrator-owned exception workflows that sit above normal Agents Relay task/job execution.
8
8
 
9
+ ## Normal managed Job start workflow
10
+
11
+ For a normal managed Job, `job create` or `job adopt` establishes durable Job/PR state only. Unless the user explicitly requested **create-only / no execution**, the orchestrator must immediately start the Job by invoking the first-class Planner command for that exact Job:
12
+
13
+ ```text
14
+ job create|adopt
15
+ -> agents-relay plan --repo <owner/repo> --pr <number> --id <job_id>
16
+ -> durable plan-N
17
+ -> Planner next_tasks
18
+ -> Relay materializes Tasks
19
+ -> normal routing, execution, and reconciliation
20
+ ```
21
+
22
+ The initial decomposition for a normal managed Job belongs to that durable Planner round. The orchestrator must not hand-author the initial child Task batch as a substitute for `agents-relay plan`, and it must not leave a newly created executable Job with zero Plans and zero Tasks. If the Planner command fails, the Job is blocked at startup and the orchestrator must report the failure rather than silently inventing Tasks.
23
+
24
+ This rule applies regardless of whether the Job uses `fixed` or `autonomous` execution mode; execution mode does not replace the required initial Planner invocation. Later replanning continues to follow Relay's normal Planner/reconciliation rules.
25
+
26
+ The explicit exception is the P0/self-job workflow below: a self job is synchronous orchestrator-owned execution, so it creates orchestrator-owned Tasks directly and terminalizes them in the same turn instead of invoking the normal initial Planner round.
27
+
9
28
  ## P0 / self job workflow
10
29
 
11
30
  A **P0 job** (alias: **self job**) is executed directly by the current active orchestrator thread: