agents-relay 1.0.62 → 1.0.63

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/markers.js CHANGED
@@ -20,9 +20,22 @@ export function parseMarker(body, label) {
20
20
  }
21
21
  return null;
22
22
  }
23
+ const JOB_OBJECTIVE_END = '<!-- agents-relay:objective:end -->';
24
+ const TASK_INPUT_END = '<!-- agents-relay:task-input:end -->';
25
+ function contentBeforeDelimiter(body, heading, end) {
26
+ const startAt = body.indexOf(heading);
27
+ if (startAt < 0)
28
+ return undefined;
29
+ const contentStart = startAt + heading.length;
30
+ const endAt = body.indexOf(`\n${end}`, contentStart);
31
+ if (endAt < 0)
32
+ return undefined;
33
+ return body.slice(contentStart, endAt);
34
+ }
23
35
  export function renderJobComment(job) {
24
36
  const objective = job.objective?.trim() || '_No objective recorded._';
25
- return `${marker(JOB_MARKER, { ...job, tasks: undefined })}
37
+ const { objective: _objective, tasks: _tasks, ...metadata } = job;
38
+ return `${marker(JOB_MARKER, metadata)}
26
39
  # Agents Relay job: ${job.title}
27
40
 
28
41
  - **State:** ${job.state}
@@ -30,15 +43,13 @@ export function renderJobComment(job) {
30
43
 
31
44
  ## Objective
32
45
 
33
- ${objective}`;
46
+ ${objective}
47
+ ${JOB_OBJECTIVE_END}`;
34
48
  }
35
49
  export function renderTaskComment(task) {
36
- const result = task.result?.summary?.trim() ? `
37
-
38
- ### Result
39
-
40
- ${task.result.summary.trim()}` : '';
41
- return `${marker(TASK_MARKER, task)}
50
+ const result = task.result?.summary?.trim() ? `\n\n### Result\n\n${task.result.summary.trim()}` : '';
51
+ const { input: _input, ...metadata } = task;
52
+ return `${marker(TASK_MARKER, metadata)}
42
53
  ## Task: ${task.id}
43
54
 
44
55
  - **State:** ${task.state}
@@ -46,23 +57,40 @@ ${task.result.summary.trim()}` : '';
46
57
 
47
58
  ### Work
48
59
 
49
- ${task.input}${result}`;
60
+ ${task.input}
61
+ ${TASK_INPUT_END}${result}`;
62
+ }
63
+ function markdownSection(body, heading) {
64
+ const start = body.indexOf(heading);
65
+ if (start < 0)
66
+ return undefined;
67
+ return body.slice(start + heading.length).trim();
50
68
  }
51
69
  export function parseJob(body) {
52
70
  const job = parseMarker(body, JOB_MARKER);
53
71
  if (!job)
54
72
  return null;
55
- if (job.executionMode === undefined)
56
- return { ...job, executionMode: 'fixed' };
57
- if (job.executionMode !== 'fixed' && job.executionMode !== 'autonomous')
73
+ const objective = job.objective ?? contentBeforeDelimiter(body, '\n## Objective\n\n', JOB_OBJECTIVE_END) ?? markdownSection(body, '\n## Objective\n');
74
+ const parsed = { ...job, objective };
75
+ if (parsed.executionMode === undefined)
76
+ return { ...parsed, executionMode: 'fixed' };
77
+ if (parsed.executionMode !== 'fixed' && parsed.executionMode !== 'autonomous')
58
78
  return null;
59
- return job;
79
+ return parsed;
60
80
  }
61
81
  export function parseTask(body) {
62
82
  const task = parseMarker(body, TASK_MARKER);
63
83
  if (!task)
64
84
  return null;
65
- return { ...task, kind: task.kind === 'planner' ? 'planner' : 'work' };
85
+ let input = task.input ?? contentBeforeDelimiter(body, '\n### Work\n\n', TASK_INPUT_END);
86
+ if (input === undefined) {
87
+ const work = markdownSection(body, '\n### Work\n');
88
+ const suffix = task.result?.summary?.trim() ? `\n\n### Result\n\n${task.result.summary.trim()}`.trim() : undefined;
89
+ input = work && suffix && work.endsWith(suffix) ? work.slice(0, -suffix.length).trimEnd() : work;
90
+ }
91
+ if (input === undefined)
92
+ return null;
93
+ return { ...task, input, kind: task.kind === 'planner' ? 'planner' : 'work' };
66
94
  }
67
95
  export function renderAgentComment(agent) { return `${marker(AGENT_MARKER, agent)}\n## Registered agent ${agent.name}\nRole: ${agent.role}\nAvailability: ${agent.availability}`; }
68
96
  export function parseAgent(body) { return parseMarker(body, AGENT_MARKER); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-relay",
3
- "version": "1.0.62",
3
+ "version": "1.0.63",
4
4
  "description": "Durable async agent jobs coordinated through GitHub pull requests",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,6 +6,8 @@ This contract is the shared protocol for every component that creates, schedules
6
6
 
7
7
  Job objectives and Task inputs are **Markdown** and are durable execution context, not short labels. When the work has a workflow, state model, architecture, dependency graph, or relationship that is clearer visually, put a Mermaid block first and follow it with Markdown details. Otherwise use structured Markdown text directly.
8
8
 
9
+ The trusted machine-readable Job/Task marker stores lifecycle and execution metadata only. Do **not** duplicate the Job objective or Task input inside the JSON marker; those long-form Markdown bodies remain the human-readable durable content rendered by the Job/Task comment (and, for a Job objective, the PR body). Readers reconstruct `objective` / `input` from that visible Markdown while remaining backward-compatible with legacy markers that embedded them.
10
+
9
11
  For long-form content, use files instead of shell-quoted arguments:
10
12
 
11
13
  - Job create/update: `--objective-file PATH` (or `--objective-file -` for stdin) is preferred. `--objective` is for short/simple content only. They are mutually exclusive.