agent-relay-server 0.121.3 → 0.121.4

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/docs/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Agent Relay API",
5
- "version": "0.121.3",
5
+ "version": "0.121.4",
6
6
  "description": "Real-time message bus for inter-agent communication. Agent-first: this spec is designed for machine consumption — agents can self-discover the full API surface via GET /api/spec.",
7
7
  "license": {
8
8
  "name": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay-server",
3
- "version": "0.121.3",
3
+ "version": "0.121.4",
4
4
  "description": "Lightweight HTTP message relay for inter-agent communication across machines",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",
@@ -37,7 +37,7 @@
37
37
  "CONTRIBUTING.md"
38
38
  ],
39
39
  "dependencies": {
40
- "agent-relay-channels-host": "0.121.3",
40
+ "agent-relay-channels-host": "0.121.4",
41
41
  "agent-relay-providers": "0.104.3",
42
42
  "agent-relay-sdk": "0.2.113",
43
43
  "ajv": "^8.20.0"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-relay-runner",
3
3
  "description": "Thin Agent Relay runner bridge for Claude Code",
4
- "version": "0.121.3",
4
+ "version": "0.121.4",
5
5
  "agentRelayContracts": {
6
6
  "providerPluginProtocol": 1
7
7
  }
@@ -354,17 +354,33 @@ function childIsBusy(child: AgentCard): boolean {
354
354
  // verbatim floods the coordinator with a wall of mid-work text (the exact bug #1037 keeps
355
355
  // re-shipping). Idle-gating alone can't help: this is a genuine turn-final at a genuine idle, so
356
356
  // the payload itself must be distilled. Short bodies pass through untouched (concise finals are
357
- // unaffected); a long body is trimmed to its trailing result block(s) a turn's conclusion lives
358
- // at its end with an elision marker so the coordinator knows narration was dropped. The actual
359
- // result is never lost. Pure function of the body → deterministic, so re-promotion (the idle flush)
360
- // yields the identical distilled body + idempotency key and dedups cleanly.
357
+ // unaffected). Pure function of the body deterministic, so re-promotion (the idle flush) yields
358
+ // the identical distilled body + idempotency key and dedups cleanly.
359
+ //
360
+ // #1056 cut on a SEMANTIC result boundary, not a block count. The old heuristic kept the last N
361
+ // `\n\n`-separated blocks by a size budget; that is fragile to how a model CHUNKS its answer. A
362
+ // chatty Claude emitted its `## SUMMARY` result as one block (kept whole), but a chatty Codex
363
+ // paragraph-broke the heading away from its bullets, so the tail-block budget clipped the header +
364
+ // the first bullet — distillation ate the TOP of the result, delivering it mid-sentence. Fix: keep
365
+ // everything from the FIRST markdown heading onward. Workers conclude under a heading (`## SUMMARY`,
366
+ // `## FINAL REPORT`), narration is prose chatter emitted before it — so the result is the trailing
367
+ // region a heading marks the start of, and cutting at the heading drops the leading narration while
368
+ // keeping the WHOLE result, however the model split it. We cut at the FIRST heading (not the last):
369
+ // the result may itself contain sub-headings (`### Details`) or multiple `##` sections, and "last
370
+ // heading" would slice into it — the very clip #1056 is about; "first heading" never can, since it
371
+ // sits at or before the result's start. Fallback (no heading anywhere — rare; workers are told to
372
+ // emit one): there is no reliable boundary, so keep the trailing answer and trim only the leading
373
+ // narration flood by the legacy tail budget, never slicing the block we keep.
361
374
  const REPORT_UP_DISTILL_THRESHOLD = 800;
362
375
  const REPORT_UP_TAIL_MAX = 800;
363
376
  const REPORT_UP_ELISION = "[…mid-work narration trimmed by report-up…]";
377
+ const REPORT_UP_HEADING = /^#{1,6}\s/m;
364
378
 
365
379
  function distillLineageReportBody(body: string): string {
366
380
  const trimmed = body.trim();
367
381
  if (trimmed.length <= REPORT_UP_DISTILL_THRESHOLD) return body;
382
+ const heading = REPORT_UP_HEADING.exec(trimmed);
383
+ if (heading) return heading.index === 0 ? body : `${REPORT_UP_ELISION}\n\n${trimmed.slice(heading.index).trim()}`;
368
384
  const blocks = trimmed.split(/\n{2,}/).map((block) => block.trim()).filter(Boolean);
369
385
  const kept: string[] = [];
370
386
  let size = 0;