From 953d9845ca539073ca8c6d0c19b15dc9f710db7d Mon Sep 17 00:00:00 2001 From: arkon Date: Sun, 25 Jan 2026 17:51:59 +0100 Subject: [PATCH] fix: subagent description extraction for JSONL format The JSONL files have message.content as a direct string, not an array of content blocks. Now handles both formats correctly. Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 2 +- package.json | 2 +- src/subagent-watcher.ts | 17 +++++++++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 6f73f368..04c3e8aa 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,7 +17,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Claudeman is a Claude Code session manager with a web interface and autonomous Ralph Loop. It spawns Claude CLI processes via PTY, streams output in real-time via SSE, and supports scheduled/timed runs. -**Version**: 0.1354 +**Version**: 0.1355 **Tech Stack**: TypeScript (ES2022/NodeNext, strict mode), Node.js, Fastify, Server-Sent Events, node-pty diff --git a/package.json b/package.json index 3a167908..be8ccccc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claudeman", - "version": "0.1354", + "version": "0.1355", "description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence", "type": "module", "main": "dist/index.js", diff --git a/src/subagent-watcher.ts b/src/subagent-watcher.ts index d6cec25f..fe4ba8b1 100644 --- a/src/subagent-watcher.ts +++ b/src/subagent-watcher.ts @@ -504,11 +504,20 @@ export class SubagentWatcher extends EventEmitter { // Try each line until we find a user message with text for (const line of lines.slice(0, 5)) { try { - const entry = JSON.parse(line) as SubagentTranscriptEntry; + const entry = JSON.parse(line); if (entry.type === 'user' && entry.message?.content) { - const firstContent = entry.message.content[0]; - if (firstContent?.type === 'text' && firstContent.text) { - const text = firstContent.text.trim(); + // Handle both formats: content can be a string or an array of content blocks + let text: string | undefined; + if (typeof entry.message.content === 'string') { + text = entry.message.content.trim(); + } else if (Array.isArray(entry.message.content)) { + const firstContent = entry.message.content[0]; + if (firstContent?.type === 'text' && firstContent.text) { + text = firstContent.text.trim(); + } + } + + if (text) { // Extract a useful title: first line, first sentence, or first 80 chars // Split on newline first const firstLine = text.split('\n')[0].trim();