Skip to content

Commit 25b205f

Browse files
Add agent detail command to inspect running agent conversations (#49)
* feat: add agent detail command planning * feat: add agent detail implementation * feat: add agent detail command in cli * fix: lint error
1 parent c0b6f30 commit 25b205f

File tree

13 files changed

+1030
-12
lines changed

13 files changed

+1030
-12
lines changed
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
---
2+
phase: design
3+
title: Agent Detail Command - System Design
4+
description: Technical design for the agent detail CLI command
5+
---
6+
7+
# System Design & Architecture
8+
9+
## Architecture Overview
10+
11+
The `agent detail` command follows the existing adapter pattern. It reuses `AgentManager` for agent discovery and resolution, then adds a conversation-reading layer.
12+
13+
```mermaid
14+
graph TD
15+
CLI["CLI: agent detail --id abc"]
16+
AM["AgentManager"]
17+
CCA["ClaudeCodeAdapter"]
18+
CA["CodexAdapter"]
19+
SR["Session Reader"]
20+
SF["Session JSONL Files"]
21+
22+
CLI -->|resolve agent| AM
23+
AM --> CCA
24+
AM --> CA
25+
CLI -->|read conversation| SR
26+
SR -->|parse JSONL| SF
27+
CCA -->|AgentInfo + sessionFilePath| CLI
28+
CA -->|AgentInfo + sessionFilePath| CLI
29+
```
30+
31+
**Key insight:** The existing adapters already read session files to extract status/summary. For `detail`, we need the full conversation, which requires a second pass that reads and parses all JSONL entries (not just the last few lines).
32+
33+
## Data Models
34+
35+
### AgentDetail (extends AgentInfo conceptually)
36+
37+
```typescript
38+
interface AgentDetail {
39+
sessionId: string;
40+
cwd: string;
41+
startTime: Date;
42+
status: AgentStatus;
43+
type: AgentType;
44+
name: string;
45+
slug?: string;
46+
conversation: ConversationMessage[];
47+
}
48+
49+
interface ConversationMessage {
50+
role: 'user' | 'assistant' | 'system';
51+
content: string;
52+
timestamp?: string;
53+
}
54+
```
55+
56+
### Conversation parsing rules
57+
58+
**Claude Code JSONL:**
59+
- Each line is `{ type, timestamp, message, ... }`
60+
- `type: "user"` → role=user, extract text from `message.content`
61+
- `type: "assistant"` → role=assistant, extract text from `message.content`
62+
- `type: "system"` → role=system
63+
- Skip metadata types: `file-history-snapshot`, `last-prompt`, `progress`, `thinking`
64+
- **Default mode:** Extract only text blocks from `message.content` arrays
65+
- **Verbose mode:** Also include tool_use blocks (name + input summary) and tool_result blocks
66+
67+
**Codex JSONL:**
68+
- First line: `session_meta` → skip (metadata only)
69+
- Subsequent lines have `type`, `timestamp`, and `payload` with `payload.message` (plain string) and `payload.type`
70+
- Map `payload.type` to roles: `user_message` → user, `agent_message` → assistant, others → system
71+
- Default mode: extract `payload.message` strings
72+
- Verbose mode: include additional payload details if present
73+
74+
## API Design
75+
76+
### CLI Interface
77+
78+
```
79+
ai-devkit agent detail --id <name> [--json] [--full] [--tail <n>] [--verbose]
80+
```
81+
82+
**Options:**
83+
- `--id <name>` (required): Agent name (as shown in `agent list` output)
84+
- `--json` (optional): Output as JSON
85+
- `--full` (optional): Show entire conversation history (default: last 20 messages)
86+
- `--tail <n>` (optional): Show last N messages (default: 20)
87+
- `--verbose` (optional): Include tool call/result details in messages
88+
89+
**Default output format (human-readable, text only, last 20 messages):**
90+
```
91+
Agent Detail
92+
────────────────────────────────
93+
Session ID: a6ce7023-6ac4-40b7-a8a5-dde50645bed5
94+
CWD: ~/Code/ai-devkit
95+
Start Time: 2026-03-27 10:30:00
96+
Status: 🟢 run
97+
Type: Claude Code
98+
99+
Conversation (last 20 messages)
100+
────────────────────────────────
101+
[10:30:05] user:
102+
Fix the login bug in auth.ts
103+
104+
[10:30:12] assistant:
105+
I'll look at the auth.ts file...
106+
...
107+
```
108+
109+
**Verbose mode adds tool details:**
110+
```
111+
[10:30:12] assistant:
112+
I'll look at the auth.ts file...
113+
[Tool: Read] auth.ts
114+
[Tool: Edit] auth.ts (lines 15-20)
115+
```
116+
117+
### Internal API
118+
119+
Add `getConversation()` as a **required** method on the `AgentAdapter` interface:
120+
121+
```typescript
122+
interface AgentAdapter {
123+
// existing...
124+
getConversation(sessionFilePath: string, options?: { verbose?: boolean }): ConversationMessage[];
125+
}
126+
```
127+
128+
Each adapter implements its own parsing logic (Claude: structured content blocks, Codex: `payload.message` strings) but all return the same `ConversationMessage[]` output.
129+
130+
## Component Breakdown
131+
132+
1. **CLI command handler** (`packages/cli/src/commands/agent.ts`):
133+
- New `detail` subcommand under the existing `agent` command
134+
- Uses `AgentManager` to list + resolve agent
135+
- Calls conversation reader
136+
- Formats and displays output
137+
138+
2. **Conversation reader** (`packages/agent-manager/src/`):
139+
- New method or utility to parse full conversation from JSONL
140+
- Claude-specific parsing in `ClaudeCodeAdapter`
141+
- Codex-specific parsing in `CodexAdapter`
142+
- Returns `ConversationMessage[]`
143+
144+
3. **AgentInfo extension**:
145+
- Add `sessionFilePath?: string` to `AgentInfo` — already known at detection time, avoids re-discovery
146+
147+
## Design Decisions
148+
149+
| Decision | Choice | Rationale |
150+
|----------|--------|-----------|
151+
| Where to add conversation parsing | Required method on `AgentAdapter` interface | Each adapter has its own JSONL format but unified output |
152+
| How to pass session file path | Add to `AgentInfo` | Already known at detection, avoids re-discovery |
153+
| Output format | Table header + message list | Consistent with `agent list` style |
154+
| Message filtering | Skip progress/thinking/metadata | Show only meaningful conversation turns |
155+
| Default message count | Last 20 | Practical default; `--full`/`--tail` for overrides |
156+
| Tool display | Text-only default, `--verbose` for tools | Keeps output clean; tools are verbose |
157+
| Identifier type | Name only | Consistent, simple; users copy from `agent list` |
158+
| Non-running agents | Not supported | Scoped to running processes only |
159+
160+
## Non-Functional Requirements
161+
162+
- **Performance:** Session files can be large. Read the file once, parse line-by-line. No concern for very large files since we're already reading them in `readSession()`.
163+
- **Reliability:** Graceful handling of corrupted JSONL lines (skip and continue).
164+
- **Compatibility:** Works on macOS and Linux (same as existing commands).
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
phase: implementation
3+
title: Agent Detail Command - Implementation Guide
4+
description: Technical implementation notes for the agent detail command
5+
---
6+
7+
# Implementation Guide
8+
9+
## Development Setup
10+
11+
- Worktree: `.worktrees/feature-agent-detail`
12+
- Branch: `feature-agent-detail`
13+
- Dependencies: already bootstrapped via `npm ci`
14+
15+
## Code Structure
16+
17+
**Files to modify:**
18+
- `packages/agent-manager/src/adapters/AgentAdapter.ts` — add `sessionFilePath` to `AgentInfo`, add `ConversationMessage` type
19+
- `packages/agent-manager/src/adapters/ClaudeCodeAdapter.ts` — populate `sessionFilePath`, add `getConversation()`
20+
- `packages/agent-manager/src/adapters/CodexAdapter.ts` — populate `sessionFilePath`, add `getConversation()`
21+
- `packages/agent-manager/src/index.ts` — export new types
22+
- `packages/cli/src/commands/agent.ts` — add `detail` subcommand
23+
24+
## Implementation Notes
25+
26+
### ConversationMessage type
27+
```typescript
28+
export interface ConversationMessage {
29+
role: 'user' | 'assistant' | 'system';
30+
content: string;
31+
timestamp?: string;
32+
}
33+
```
34+
35+
### Claude conversation parsing
36+
- Read file once, split by newlines
37+
- For each line: parse JSON, check `type` field
38+
- Include `user`, `assistant`, `system` types
39+
- Skip `progress`, `thinking`, `file-history-snapshot`, `last-prompt`
40+
- Extract text content using existing `extractUserMessageText` logic for user messages
41+
- For assistant messages, concatenate text blocks from `message.content` array
42+
43+
### Codex conversation parsing
44+
- Skip `session_meta` first line
45+
- Map event types to roles based on Codex format
46+
47+
### CLI output formatting
48+
- Use `ui.text()` for section headers
49+
- Use chalk for coloring roles
50+
- Truncate very long messages with `--full` flag (future consideration)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
phase: planning
3+
title: Agent Detail Command - Planning
4+
description: Task breakdown and implementation plan for the agent detail command
5+
---
6+
7+
# Project Planning & Task Breakdown
8+
9+
## Milestones
10+
11+
- [x] Milestone 1: Core infrastructure (AgentInfo extension + conversation reader)
12+
- [x] Milestone 2: CLI command implementation
13+
- [x] Milestone 3: Tests and polish
14+
15+
## Task Breakdown
16+
17+
### Phase 1: Core Infrastructure
18+
19+
- [x] Task 1.1: Add `sessionFilePath` field to `AgentInfo` interface in `AgentAdapter.ts`
20+
- [x] Task 1.2: Populate `sessionFilePath` in `ClaudeCodeAdapter.mapSessionToAgent()` and `CodexAdapter`
21+
- [x] Task 1.3: Add `ConversationMessage` type and `getConversation(filePath: string): ConversationMessage[]` method to `ClaudeCodeAdapter`
22+
- [x] Task 1.4: Add `getConversation(filePath: string): ConversationMessage[]` method to `CodexAdapter`
23+
- [x] Task 1.5: Export new types and methods from `@ai-devkit/agent-manager` package index
24+
25+
### Phase 2: CLI Command
26+
27+
- [x] Task 2.1: Add `agent detail` subcommand in `agent.ts` with `--id`, `--json`, `--full`, `--tail`, `--verbose` options
28+
- [x] Task 2.2: Implement agent resolution logic (reuse `resolveAgent` by name + handle ambiguity)
29+
- [x] Task 2.3: Implement human-readable output formatting (metadata header + tail-limited conversation, text-only default)
30+
- [x] Task 2.4: Implement `--verbose` mode (include tool call/result details)
31+
- [x] Task 2.5: Implement JSON output mode
32+
33+
### Phase 3: Testing & Polish
34+
35+
- [x] Task 3.1: Unit tests for `ClaudeCodeAdapter.getConversation()` — 11 tests
36+
- [x] Task 3.2: Unit tests for `CodexAdapter.getConversation()` — 9 tests
37+
- [ ] Task 3.3: Integration test for `agent detail` CLI command (deferred — requires running agents)
38+
- [ ] Task 3.4: Manual testing with real running agents (deferred — requires running agents)
39+
40+
## Dependencies
41+
42+
- Task 1.1 must complete before Task 1.2
43+
- Task 1.3/1.4 can run in parallel
44+
- Task 1.5 depends on 1.1–1.4
45+
- Phase 2 depends on Phase 1 completion
46+
- Phase 3 depends on Phase 2 completion
47+
48+
## Risks & Mitigation
49+
50+
| Risk | Impact | Mitigation |
51+
|------|--------|------------|
52+
| Large session files slow down detail display | Medium | Stream/parse line by line (already done in readSession) |
53+
| Codex JSONL format has undocumented fields | Low | Graceful fallback for unknown entry types |
54+
| Adding field to AgentInfo breaks existing consumers | Low | Field is optional (`sessionFilePath?: string`) |
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
phase: requirements
3+
title: Agent Detail Command
4+
description: CLI command to fetch detailed information about a running agent including session data and conversation history
5+
---
6+
7+
# Requirements & Problem Understanding
8+
9+
## Problem Statement
10+
11+
Users of `ai-devkit` can list running agents via `agent list`, but there is no way to inspect the full details of a specific agent. When debugging, monitoring, or reviewing an agent's work, users need to see:
12+
13+
- The session ID and metadata (cwd, start time)
14+
- Current status
15+
- The full conversation history (all messages)
16+
17+
Currently, users must manually navigate to `~/.claude/projects/` or `~/.codex/sessions/`, find the correct JSONL file, and parse it themselves.
18+
19+
## Goals & Objectives
20+
21+
**Primary goals:**
22+
- Provide a `ai-devkit agent detail --id <identifier>` command that displays comprehensive agent information
23+
- Show session metadata: session ID, cwd, start time, current status
24+
- Show the last N conversation messages by default, with `--full` to show all and `--tail <n>` to control count
25+
- Show text content by default; `--verbose` to include tool call/result details
26+
27+
**Non-goals:**
28+
- Editing or modifying session data
29+
- Real-time streaming/tailing of the conversation
30+
- Exporting conversation to external formats (PDF, HTML, etc.)
31+
- Supporting terminated/non-running agents (only agents visible in `agent list`)
32+
33+
## User Stories & Use Cases
34+
35+
- **As a developer**, I want to run `ai-devkit agent detail --id "abc"` so that I can see what a specific agent has been doing, including its recent conversation.
36+
- **As a team lead**, I want to inspect an agent's session details (start time, status, cwd) to understand its context and current state.
37+
- **As a developer**, I want JSON output (`--json` flag) so I can pipe agent details into other tools for analysis.
38+
- **As a developer**, I want `--verbose` to see tool call details when debugging what an agent actually executed.
39+
- **As a developer**, I want `--full` or `--tail <n>` to control how much conversation history is shown.
40+
41+
**Key workflows:**
42+
1. User runs `agent list` to see all running agents
43+
2. User picks an agent name from the list
44+
3. User runs `agent detail --id <name>` to see details + recent conversation
45+
4. Output shows metadata header + last N conversation messages (text only by default)
46+
47+
**Edge cases:**
48+
- Agent name matches multiple agents → show error with available matches
49+
- Agent name matches no agent → show error with available agents
50+
- Session file is missing or corrupted → graceful error message
51+
- Agent is from Codex (not just Claude) → adapter-agnostic detail fetching
52+
53+
## Success Criteria
54+
55+
- `ai-devkit agent detail --id <name>` resolves the agent by name and displays:
56+
- Session ID
57+
- CWD (working directory)
58+
- Start time
59+
- Current status
60+
- Last 20 conversation messages (text only) by default
61+
- `--full` shows entire conversation history
62+
- `--tail <n>` shows last N messages
63+
- `--verbose` includes tool call/result details in messages
64+
- `--json` flag outputs structured JSON
65+
- Works for both Claude Code and Codex agents
66+
- Only works for running agents (those visible in `agent list`)
67+
- Handles ambiguous/missing names gracefully with helpful messages
68+
- Uses existing `AgentManager.resolveAgent()` for name resolution
69+
70+
## Constraints & Assumptions
71+
72+
- Reuses the existing adapter architecture (`AgentManager`, `ClaudeCodeAdapter`, `CodexAdapter`)
73+
- Session data is read from JSONL files already discovered during agent detection
74+
- The conversation reader needs access to the session file path, which is available via the matched `SessionFile`
75+
- Conversation parsing must handle both Claude and Codex JSONL formats
76+
- Must not break existing `agent list`, `agent open`, or `agent send` commands
77+
78+
## Resolved Questions
79+
80+
- **Identifier type:** Accept agent name only (from `agent list` output), not session IDs or slugs
81+
- **Conversation length:** Show last 20 messages by default; `--full` for all, `--tail <n>` for custom count
82+
- **Tool use display:** Text-only by default; `--verbose` includes tool call/result details
83+
- **Non-running agents:** Not supported — only agents with a running process (visible in `agent list`)

0 commit comments

Comments
 (0)