Skip to content

Commit 7effb56

Browse files
committed
improvements
1 parent 33b32ac commit 7effb56

9 files changed

Lines changed: 1093 additions & 175 deletions

File tree

README.md

Lines changed: 68 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88

99
AgentPipe is a CLI and TUI application that orchestrates conversations between multiple AI agents. It allows different AI CLI tools (like Claude, Gemini, Qwen) to communicate with each other in a shared "room", creating dynamic multi-agent conversations.
1010

11+
## Screenshots
12+
13+
### Enhanced TUI Interface
14+
![AgentPipe TUI](screenshots/tui/tui1.png)
15+
*Enhanced TUI with multi-panel layout: agent list with status indicators, conversation view with metrics, statistics panel showing turns and total cost, configuration panel, and user input area*
16+
1117
## Features
1218

1319
- **Multi-Agent Conversations**: Connect multiple AI agents in a single conversation
@@ -19,9 +25,13 @@ AgentPipe is a CLI and TUI application that orchestrates conversations between m
1925
- **Enhanced TUI Interface**:
2026
- Beautiful panelized layout with agent list, conversation view, and user input
2127
- Color-coded agent messages with custom badges
28+
- Real-time agent activity indicators (green/grey dots)
2229
- Real-time metrics display (duration, tokens, cost)
2330
- Modal system for agent details
2431
- User participation in conversations
32+
- Topic panel showing initial prompt
33+
- Statistics panel with turn/agent counters
34+
- Configuration panel showing active settings
2535
- **Chat Logging**: Automatic conversation logging to `~/.agentpipe/chats/`
2636
- **Response Metrics**: Track response time, token usage, and estimated costs
2737
- **Health Checks**: Automatic agent health verification before conversations
@@ -30,14 +40,20 @@ AgentPipe is a CLI and TUI application that orchestrates conversations between m
3040

3141
## What's New 🎉
3242

33-
### Latest Features
34-
- **Enhanced TUI Interface**: Beautiful panelized layout with agent list, conversation view, and user participation
35-
- **Response Metrics**: Real-time tracking of response duration, token usage, and estimated costs
36-
- **Chat Logging**: Automatic conversation logging with timestamped files in `~/.agentpipe/chats/`
37-
- **Codex Support**: Added support for OpenAI's Codex CLI tool
38-
- **Improved Health Checks**: More robust agent health verification with better timeout handling
39-
- **Colored Output**: Beautiful color-coded agent messages with custom badges
40-
- **User Participation**: Join conversations directly through the enhanced TUI
43+
### Latest Features (v0.0.7)
44+
- **Enhanced TUI Interface**:
45+
- Beautiful multi-panel layout with dedicated sections for agents, chat, stats, and config
46+
- Real-time agent activity indicators showing when agents are thinking/responding
47+
- Consolidated message headers (only shown when speaker changes)
48+
- Proper multi-paragraph message handling
49+
- Topic panel displaying the initial conversation prompt
50+
- Statistics showing current/max turns, connected/configured agents, and total cost
51+
- Configuration panel showing all active settings including config file path
52+
- **Response Metrics**: Real-time tracking with inline display in chat (X.Xs, XXX tokens, $X.XXXX)
53+
- **Improved Message Formatting**: Better handling of multi-line agent responses
54+
- **Chat Logging**: Dual output support - logs to file while displaying in TUI
55+
- **Configuration Honoring**: TUI mode now properly respects all config settings
56+
- **User Participation**: Seamless integration allowing users to join agent conversations
4157

4258
## Installation
4359

@@ -149,8 +165,9 @@ orchestrator:
149165

150166
logging:
151167
enabled: true # Enable chat logging
152-
path: ~/.agentpipe/chats # Custom log path (optional)
153-
show_metrics: true # Display response metrics
168+
chat_log_dir: ~/.agentpipe/chats # Custom log path (optional)
169+
show_metrics: true # Display response metrics in TUI
170+
log_format: text # Log format (text or json)
154171
```
155172
156173
### Conversation Modes
@@ -173,8 +190,7 @@ Start a conversation between agents.
173190
- `--timeout`: Response timeout in seconds (default: 30)
174191
- `--delay`: Delay between responses in seconds (default: 1)
175192
- `-p, --prompt`: Initial conversation prompt
176-
- `-t, --tui`: Use TUI interface
177-
- `--enhanced-tui`: Use enhanced TUI with panels and user input
193+
- `-t, --tui`: Use enhanced TUI interface with panels and user input
178194
- `--log-path`: Custom path for chat logs (default: ~/.agentpipe/chats)
179195
- `--no-log`: Disable chat logging
180196
- `--show-metrics`: Display response metrics (duration, tokens, cost)
@@ -229,25 +245,54 @@ agentpipe run \
229245
-p "How can we make education more engaging?"
230246
```
231247

232-
## TUI Controls
248+
## TUI Interface
249+
250+
The enhanced TUI provides a rich, interactive experience for managing multi-agent conversations:
233251

234-
### Basic TUI (`--tui`)
235-
- `Ctrl+C` or `Esc`: Quit
236-
- `Ctrl+S`: Start conversation
237-
- `Ctrl+P`: Pause/Resume
238-
- `↑↓`: Scroll through messages
252+
### Layout
253+
The TUI is divided into multiple panels:
254+
- **Agents Panel** (Left): Shows all connected agents with real-time status indicators
255+
- **Chat Panel** (Center): Displays the conversation with color-coded messages
256+
- **Topic Panel** (Top Right): Shows the initial conversation prompt
257+
- **Statistics Panel** (Right): Displays turn count, agent statistics, and total conversation cost
258+
- **Configuration Panel** (Right): Shows active settings and config file path
259+
- **User Input Panel** (Bottom): Allows you to participate in the conversation
239260

240-
### Enhanced TUI (`--enhanced-tui`)
241-
- `Tab`: Switch between panels
261+
### Visual Features
262+
- **Agent Status Indicators**: Green dot (🟢) for active/responding, grey dot (⚫) for idle
263+
- **Color-Coded Messages**: Each agent gets a unique color for easy tracking
264+
- **Consolidated Headers**: Message headers only appear when the speaker changes
265+
- **Metrics Display**: Response time (seconds), token count, and cost shown inline when enabled
266+
- **Multi-Paragraph Support**: Properly formatted multi-line agent responses
267+
268+
### Controls
269+
- `Tab`: Switch between panels (Agents, Chat, User Input)
242270
- `↑↓`: Navigate in active panel
243-
- `Enter`: Select agent or send message
244-
- `i`: Show agent info modal
245-
- `u`: Toggle user input panel
271+
- `Enter`: Send message when in User Input panel
272+
- `i`: Show agent info modal (when in Agents panel)
246273
- `Ctrl+C` or `q`: Quit
247274
- `PageUp/PageDown`: Scroll conversation
275+
- Active agent indicators: 🟢 (responding) / ⚫ (idle)
248276

249277
## Development
250278

279+
### Building from Source
280+
281+
```bash
282+
# Clone the repository
283+
git clone https://github.com/kevinelliott/agentpipe.git
284+
cd agentpipe
285+
286+
# Build the binary
287+
go build -o agentpipe .
288+
289+
# Or build with version information
290+
VERSION=v0.0.7 make build
291+
292+
# Run tests
293+
go test ./...
294+
```
295+
251296
### Project Structure
252297

253298
```

cmd/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Claude, Gemini, and Qwen, allowing them to communicate in a shared "room".`,
2424
Run: func(cmd *cobra.Command, args []string) {
2525
if showVersion {
2626
fmt.Println(version.GetVersionString())
27-
27+
2828
// Quick update check
2929
if hasUpdate, latestVersion, err := version.CheckForUpdate(); err == nil && hasUpdate {
3030
fmt.Printf("\n📦 Update available: %s (current: %s)\n", latestVersion, version.GetShortVersion())

cmd/run.go

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,24 @@ func parseAgentSpec(spec string, index int) (agent.AgentConfig, error) {
151151
}
152152

153153
func startConversation(cmd *cobra.Command, cfg *config.Config) error {
154+
ctx, cancel := context.WithCancel(context.Background())
155+
defer cancel()
156+
157+
sigChan := make(chan os.Signal, 1)
158+
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
159+
go func() {
160+
<-sigChan
161+
fmt.Println("\n\nInterrupted. Shutting down...")
162+
cancel()
163+
}()
164+
165+
if useTUI {
166+
// Use enhanced TUI - agent initialization will happen inside TUI
167+
skipHealthCheck, _ := cmd.Flags().GetBool("skip-health-check")
168+
return tui.RunEnhanced(ctx, cfg, nil, skipHealthCheck, healthCheckTimeout, configPath)
169+
}
170+
171+
// Non-TUI mode: initialize agents here
154172
agentsList := make([]agent.Agent, 0)
155173

156174
verbose := viper.GetBool("verbose")
@@ -219,22 +237,6 @@ func startConversation(cmd *cobra.Command, cfg *config.Config) error {
219237

220238
fmt.Printf("✅ All %d agents initialized successfully\n\n", len(agentsList))
221239

222-
ctx, cancel := context.WithCancel(context.Background())
223-
defer cancel()
224-
225-
sigChan := make(chan os.Signal, 1)
226-
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
227-
go func() {
228-
<-sigChan
229-
fmt.Println("\n\nInterrupted. Shutting down...")
230-
cancel()
231-
}()
232-
233-
if useTUI {
234-
// Use enhanced TUI
235-
return tui.RunEnhanced(ctx, cfg, agentsList)
236-
}
237-
238240
orchConfig := orchestrator.OrchestratorConfig{
239241
Mode: orchestrator.ConversationMode(cfg.Orchestrator.Mode),
240242
TurnTimeout: cfg.Orchestrator.TurnTimeout,

cmd/version.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func runVersion(cmd *cobra.Command, args []string) {
3030
if checkUpdate {
3131
fmt.Println("\n🔍 Checking for updates...")
3232
hasUpdate, latestVersion, err := version.CheckForUpdate()
33-
33+
3434
if err != nil {
3535
// Only show error if it's not a silent failure
3636
if err.Error() != "" {
@@ -52,4 +52,4 @@ func runVersion(cmd *cobra.Command, args []string) {
5252
fmt.Printf(" ℹ️ Update check unavailable at this time\n")
5353
}
5454
}
55-
}
55+
}

examples/debate.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,8 @@ orchestrator:
3030
max_turns: 9
3131
turn_timeout: 45s
3232
response_delay: 3s
33-
initial_prompt: "Should humanity pursue artificial general intelligence (AGI) at all costs?"
33+
initial_prompt: "Should humanity pursue artificial general intelligence (AGI) at all costs?"
34+
35+
logging:
36+
enabled: true
37+
show_metrics: true # Set to true to display response metrics

internal/version/version.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ var (
1212
// Version is the current version of agentpipe
1313
// This will be set at build time using -ldflags
1414
Version = "dev"
15-
15+
1616
// CommitHash is the git commit hash
1717
CommitHash = "unknown"
18-
18+
1919
// BuildDate is the build date
2020
BuildDate = "unknown"
2121
)
@@ -69,7 +69,7 @@ func CheckForUpdate() (bool, string, error) {
6969
if len(parts) == 0 {
7070
return false, "", fmt.Errorf("invalid redirect URL")
7171
}
72-
72+
7373
latestTag := parts[len(parts)-1]
7474
latestVersion := strings.TrimPrefix(latestTag, "v")
7575
currentVersion := strings.TrimPrefix(Version, "v")
@@ -179,4 +179,4 @@ func GetVersionString() string {
179179
// GetShortVersion returns just the version number
180180
func GetShortVersion() string {
181181
return Version
182-
}
182+
}

pkg/orchestrator/orchestrator.go

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,12 @@ func (o *Orchestrator) AddAgent(a agent.Agent) {
7171
}
7272
o.messages = append(o.messages, announcement)
7373

74-
// Log using the logger if available, otherwise use writer
74+
// Log using the logger if available
7575
if o.logger != nil {
7676
o.logger.LogMessage(announcement)
77-
} else if o.writer != nil {
77+
}
78+
// Always write to writer if available (for TUI)
79+
if o.writer != nil {
7880
fmt.Fprintf(o.writer, "\n[System] %s\n", announcement.Content)
7981
}
8082
}
@@ -99,7 +101,9 @@ func (o *Orchestrator) Start(ctx context.Context) error {
99101
// Log using the logger if available
100102
if o.logger != nil {
101103
o.logger.LogMessage(initialMsg)
102-
} else if o.writer != nil {
104+
}
105+
// Always write to writer if available (for TUI)
106+
if o.writer != nil {
103107
fmt.Fprintf(o.writer, "\n[System] %s\n", initialMsg.Content)
104108
}
105109
}
@@ -131,7 +135,8 @@ func (o *Orchestrator) runRoundRobin(ctx context.Context) error {
131135
endMsg := "Maximum turns reached. Conversation ended."
132136
if o.logger != nil {
133137
o.logger.LogSystem(endMsg)
134-
} else if o.writer != nil {
138+
}
139+
if o.writer != nil {
135140
fmt.Fprintln(o.writer, "\n[System] "+endMsg)
136141
}
137142
break
@@ -143,7 +148,8 @@ func (o *Orchestrator) runRoundRobin(ctx context.Context) error {
143148
if o.logger != nil {
144149
o.logger.LogError(currentAgent.GetName(), err)
145150
o.logger.LogSystem("Continuing conversation with remaining agents...")
146-
} else if o.writer != nil {
151+
}
152+
if o.writer != nil {
147153
fmt.Fprintf(o.writer, "\n[Error] Agent %s failed: %v\n", currentAgent.GetName(), err)
148154
fmt.Fprintf(o.writer, "[Info] Continuing conversation with remaining agents...\n")
149155
}
@@ -175,7 +181,8 @@ func (o *Orchestrator) runReactive(ctx context.Context) error {
175181
endMsg := "Maximum turns reached. Conversation ended."
176182
if o.logger != nil {
177183
o.logger.LogSystem(endMsg)
178-
} else if o.writer != nil {
184+
}
185+
if o.writer != nil {
179186
fmt.Fprintln(o.writer, "\n[System] "+endMsg)
180187
}
181188
break
@@ -216,7 +223,8 @@ func (o *Orchestrator) runFreeForm(ctx context.Context) error {
216223
endMsg := "Maximum turns reached. Conversation ended."
217224
if o.logger != nil {
218225
o.logger.LogSystem(endMsg)
219-
} else if o.writer != nil {
226+
}
227+
if o.writer != nil {
220228
fmt.Fprintln(o.writer, "\n[System] "+endMsg)
221229
}
222230
break
@@ -296,8 +304,20 @@ func (o *Orchestrator) getAgentResponse(ctx context.Context, a agent.Agent) erro
296304
// Display the response
297305
if o.logger != nil {
298306
o.logger.LogMessage(msg)
299-
} else if o.writer != nil {
300-
fmt.Fprintf(o.writer, "\n[%s] %s\n", a.GetName(), response)
307+
}
308+
// Always write to writer if available (for TUI)
309+
if o.writer != nil {
310+
// Include metrics in a special format if available
311+
if msg.Metrics != nil {
312+
fmt.Fprintf(o.writer, "\n[%s|%dms|%dt|%.4f] %s\n",
313+
a.GetName(),
314+
msg.Metrics.Duration.Milliseconds(),
315+
msg.Metrics.TotalTokens,
316+
msg.Metrics.Cost,
317+
response)
318+
} else {
319+
fmt.Fprintf(o.writer, "\n[%s] %s\n", a.GetName(), response)
320+
}
301321
}
302322

303323
return nil

0 commit comments

Comments
 (0)