Skip to content

feat: add debug trace viewer (picoclaw-tracer)#2945

Open
aruntcet2010 wants to merge 13 commits into
sipeed:mainfrom
aruntcet2010:feat/tracer
Open

feat: add debug trace viewer (picoclaw-tracer)#2945
aruntcet2010 wants to merge 13 commits into
sipeed:mainfrom
aruntcet2010:feat/tracer

Conversation

@aruntcet2010
Copy link
Copy Markdown

Summary

Adds picoclaw-tracer, a standalone web UI that reads the gateway JSON-Lines log and renders per-turn LLM traces in real time — system prompt, full messages array, available tools, tool executions, and response metadata for every LLM call within a turn.

  • Fully separate binary at cmd/tracer — no CGO, no libolm, no picoclaw core imports. Build with go build ./cmd/tracer.
  • Passive consumer — only reads ~/.picoclaw/logs/gateway.log from disk. Does not talk to the gateway, share state, or affect the picoclaw process in any way. Crashing/removing the tracer has zero impact on picoclaw.
  • Zero changes to picoclaw core (cmd/picoclaw/, pkg/) — verifiable with git diff main..feat/tracer -- cmd/picoclaw/ pkg/ returning empty.
  • Embedded frontend via go:embed behind a build tag, so a single binary serves the UI. Dev mode reads from disk for hot reload.

What it shows

For each turn:

  • Metadata (time, channel, sender, status, duration, iterations)
  • Tool executions (with duration, byte counts, error status)
  • One collapsible card per LLM call (iteration) containing the exact messages array sent to the LLM: [0] SYSTEM, [1] USER, [2] ASSISTANT, [3] TOOL, ... — captured per-call so you can see when system prompt or tool list changes mid-turn
  • Per-call Available Tools, nested inside each LLM call

Threads are grouped by chat_id and chat threads can be browsed in a three-pane layout (threads → turns → detail).

Architecture

tracer/                      # library (stdlib only)
  tracer.go                  # Run(port, logPath, frontendDir) entry
  parser.go                  # JSON-Lines gateway log → []*Turn
  server.go                  # HTTP API (/api/traces, /api/health)
  types.go                   # Turn, LLMCall, Message, Tool, ToolExec
  frontend_dev.go            # disk-served UI (build tag !embed)
  frontend_embed.go          # embedded UI (build tag embed)
  frontend/                  # React + Vite + TypeScript SPA

cmd/tracer/main.go           # standalone binary

Running

# Run picoclaw with debug logging so per-LLM-call messages get captured
picoclaw gateway --debug --no-truncate

# In another terminal, build and run the tracer
go build -tags embed -o picoclaw-tracer ./cmd/tracer
./picoclaw-tracer --port 7331
# → open http://localhost:7331

See tracer/README.md for details on dev mode and the Makefile targets.

Test plan

  • go build ./tracer/... ./cmd/tracer/... succeeds without CGO
  • Run ./picoclaw-tracer against a populated ~/.picoclaw/logs/gateway.log and confirm:
    • Threads list groups turns by chat_id
    • Single-iteration turns show 1 LLM call with full messages array
    • Multi-iteration turns (tool use) show N LLM calls, each with its own messages + tools
    • System prompt is visible per-call at index [0]
    • Available Tools (collapsed) is per-call so changes between iterations are visible
    • Gateway restart (turn_id reuse) doesn't crash the parser or duplicate turns
  • git diff main..feat/tracer -- cmd/picoclaw/ pkg/ is empty (picoclaw core untouched)

🤖 Generated with Claude Code

Arun Thulasidharan and others added 13 commits May 26, 2026 07:03
Adds a trace viewer tool under tracer/ for inspecting PicoClaw gateway
activity in real time. Parses ~/.picoclaw/logs/gateway.log (JSON Lines)
and serves a React UI showing per-thread turns, LLM calls, system
prompts, messages, available tools, and tool executions.

Backend: Go HTTP server (no extra runtime dependencies)
Frontend: React + TypeScript + Vite, dark-themed

Usage:
  cd tracer && make build-frontend && go run .
  Open http://localhost:7331

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Moves tracer logic from package main into the tracer package so it can
be imported by the CLI. Adds a cobra subcommand so the trace viewer
starts with:

  picoclaw tracer

Flags: --port (default 7331), --log, --frontend-dir

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds cmd/tracer as a self-contained binary entry point with no CGO or
heavy picoclaw dependencies. Build and run independently:

  go build ./cmd/tracer
  go run ./cmd/tracer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When the gateway restarts, turn IDs (e.g. main-turn-2) get reused. The
parser would then index into a freshly-created empty LLMCalls slice
using stale indices from llmIdx, causing a panic.

Purge stale llmIdx entries on agent.turn.start when the turn_id already
exists, and add bounds checks on the indexing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each tool in Available Tools is now clickable to show the full
description and JSON-schema-like parameter definition.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rn label

Fix turn list duplication when the gateway restarts with reused turn IDs:
only append to the display order on first sighting of a turn_id.

Turn list now shows the user message that started the turn as the label,
with the raw turn_id shown smaller below it as a secondary identifier.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each LLM call now shows only the messages that were added by this call,
not the full conversation history. First call shows just the latest user
message; subsequent calls show only the new tool calls/results.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
picoclaw turn IDs skip odd numbers (placeholder turns), which is
confusing. Drop them entirely and rely on the user-message label and
timestamp instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each turn now shows a single flat Conversation section with all messages
in chronological order (user, assistant tool calls, tool results, final
assistant). System prompt and available tools are collapsed sections
shown once per turn instead of repeated per iteration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each LLM call now renders as a collapsible card showing the full
messages array as-sent (system + history + new), with the call's
own Available Tools nested inside. Headers show msg count, tools
count, response chars, and tool calls at a glance.

Also fixes flex layout: minHeight: 0 on the scrollable container
and flexShrink: 0 on each LLM card so the parent's overflowY: auto
actually triggers instead of squishing cards on top of each other.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Drop `picoclaw tracer` subcommand and its wrapper file so the main
  picoclaw binary doesn't link the tracer package. Users run the
  standalone `picoclaw-tracer` binary from cmd/tracer instead.
- Delete LLMCallCard.tsx (replaced by inline rendering in TurnDetail).
- Stop tracking tsconfig.tsbuildinfo; add it to tracer/.gitignore.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Arun Thulasidharan seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants