agent-relay-runner 0.31.1 → 0.32.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay-runner",
3
- "version": "0.31.1",
3
+ "version": "0.32.1",
4
4
  "description": "Unified provider lifecycle runner for Agent Relay",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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.31.1",
4
+ "version": "0.32.1",
5
5
  "agentRelayContracts": {
6
6
  "providerPluginProtocol": 1
7
7
  }
@@ -44,9 +44,16 @@ relay_post_session_turn() {
44
44
  local last_assistant_message="${2:-}"
45
45
  local port="${AGENT_RELAY_RUNNER_PORT:-}"
46
46
  [ -z "$port" ] && return 0
47
- [ -z "$transcript_path" ] && return 0
48
- local body="{\"transcriptPath\":\"$(relay_json_escape "$transcript_path")\""
49
- [ -n "$last_assistant_message" ] && body="${body},\"lastAssistantMessage\":${last_assistant_message}"
47
+ # transcript_path is the primary capture source, but the Stop payload can omit it
48
+ # (known CC edge case). last_assistant_message is the fallback for exactly that —
49
+ # POST with whichever we have; only bail when both are missing.
50
+ [ -z "$transcript_path" ] && [ -z "$last_assistant_message" ] && return 0
51
+ local body="{"
52
+ [ -n "$transcript_path" ] && body="${body}\"transcriptPath\":\"$(relay_json_escape "$transcript_path")\""
53
+ if [ -n "$last_assistant_message" ]; then
54
+ [ "$body" != "{" ] && body="${body},"
55
+ body="${body}\"lastAssistantMessage\":${last_assistant_message}"
56
+ fi
50
57
  body="${body}}"
51
58
  curl -fsS -X POST "http://127.0.0.1:${port}/session-turn" \
52
59
  -H 'Content-Type: application/json' \
@@ -352,8 +352,13 @@ async function handleSessionTurn(req: Request, options: ControlServerOptions): P
352
352
  if (!options.onSessionTurn) return Response.json({ ok: false, reason: "session capture unavailable" });
353
353
  const body = await req.json().catch(() => null);
354
354
  const transcriptPath = isRecord(body) && typeof body.transcriptPath === "string" ? body.transcriptPath : "";
355
- if (!transcriptPath) return Response.json({ ok: false, reason: "transcriptPath required" }, { status: 400 });
356
355
  const lastAssistantMessage = isRecord(body) ? body.lastAssistantMessage : undefined;
356
+ // transcriptPath is the primary source, but it can be absent (known CC Stop edge case).
357
+ // lastAssistantMessage is the fallback for exactly that — accept either; reject only when
358
+ // both are missing so the turn still reaches the dashboard chat (#264).
359
+ if (!transcriptPath && lastAssistantMessage === undefined) {
360
+ return Response.json({ ok: false, reason: "transcriptPath or lastAssistantMessage required" }, { status: 400 });
361
+ }
357
362
  // Awaited on purpose: the Stop hook posts this synchronously before its
358
363
  // reply-obligation check, so the captured turn must be persisted (and the
359
364
  // obligation cleared) before this response returns.