Skip to content

feat: add Pi agent support - #75

Merged
wesm merged 8 commits into
kenn-io:mainfrom
carze:feat/pi-support
Mar 8, 2026
Merged

feat: add Pi agent support#75
wesm merged 8 commits into
kenn-io:mainfrom
carze:feat/pi-support

Conversation

@carze

@carze carze commented Feb 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add Pi as a supported agent with JSONL session parsing, file discovery, sync, and frontend display
  • Parse Pi session files: user messages, assistant messages with thinking blocks and tool calls, tool results
  • Emit thinking and tool-use markers inline in Content (matching Claude/Amp pattern) so export, FTS, and block ordering work correctly
  • Validate Pi session headers during both bulk discovery and watcher-driven sync

Backend (Go)

  • Pi JSONL parser with V1/V2 session support and branchedFrom parent linking
  • File discovery (DiscoverPiSessions, FindPiSourceFile) registered in the agent registry with IDPrefix: "pi:", following the Amp pattern
  • Lowercase Pi tool names (read, write, edit, bash, find, str_replace, run_command, read_file) mapped to standard display format
  • formatPiToolUse bridges Pi's arguments field to the shared formatToolUse logic
  • IsPiSessionFile header validation in both bulk discovery and watcher sync
  • normalizePiIntent rewrites Pi's agent__intent/_i fields to description
  • Export support for Pi sessions

Frontend (Svelte/TS)

  • Pi agent badge with teal accent
  • Tool call display for Pi's lowercase tool aliases and edit format (edits[] array variants)
  • Content parser support for Pi tool patterns
  • agent__intent and _i filtered from displayed tool parameters

Addresses #68

@roborev-ci

roborev-ci Bot commented Feb 28, 2026

Copy link
Copy Markdown

roborev: Combined Review (a2b0931)

Verdict: Implements backend parsing, discovery, and frontend support for the Pi agent, but introduces a few medium-severity
bugs related to parsing errors, frontend filtering, and file discovery.

Medium

Silent partial parses on read errors
File: [internal/parser/pi.go:79]
ParsePiSession uses lineReader.next() in a loop but never checks lr.Err() after
the loop. next() returns false for both EOF and I/O error, so mid-file read failures can be treated as successful parses with truncated data.
Suggested fix: after the read loop, add if err := lr.Err(); err != nil { return nil, nil, ... } (same pattern used by other parsers).

Over-broad frontend filtering drops valid user messages
File: [frontend/src/lib/components/content/MessageList.svelte:38]
isPiToolResult is implemented as role === "user" && content. trim() === "", then filtered globally. This can hide legitimate empty user messages (for non-text blocks, etc.), not just Pi tool-result placeholders.
Suggested fix: remove this heuristic or filter by an explicit backend signal (e.g., persisted tool-result-only marker), not empty-
content alone.

Pi session discovery can miss valid files
File: [internal/sync/discovery.go:852]
isPiSessionFile uses bufio.Scanner with max token size fixed at 8 KiB (s.Buffer(..., 8192 )), and checks only the first scanned line. Valid sessions with long headers (or leading blank line) are skipped during discovery even though parser logic can handle much larger lines and skips empty lines.
Suggested fix: align discovery with parser behavior (use shared line-reader logic or much larger max token + skip blank
lines + check s.Err()).


Synthesized from 4 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Feb 28, 2026

Copy link
Copy Markdown

roborev: Combined Review (4151fdf)

Code review complete: 2 medium-severity issues identified regarding
session discovery limits and synchronization efficiency.

Medium

1. Pi discovery can silently skip valid sessions with large headers

  • Files: internal/sync/discovery.go:854, internal/parser/pi.go:30, internal/parser/claude.go:24
  • Details: isPiSessionFile() uses bufio.Scanner capped at 1<<20 (1 MiB), while parsing uses newLineReader(..., maxLineSize) where maxLineSize is 64 MiB. Headers between 1 MiB and
    64 MiB will parse fine but never be discovered in SyncAll.
  • Suggested Fix: Use the same line-reader path in discovery (or at least maxLineSize), and check scanner.Err() explicitly. Add a test with a header >1 MiB.

2.
Pi sessions are always reparsed on every sync cycle

  • Files: internal/sync/engine.go:1159, internal/sync/engine.go:1077
  • Details: processPi() has no unchanged-file fast path (shouldSkipBy Path/shouldSkipFile), unlike other agents. On periodic sync this reparses all Pi files even when unchanged, which is a scalability/perf regression as Pi history grows.
  • Suggested Fix: Add an mtime/size-based skip check (like Gemini/Codex) before parsing, and optionally file hash
    persistence parity.

Synthesized from 4 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Feb 28, 2026

Copy link
Copy Markdown

roborev: Combined Review (bcadf32)

Summary Verdict: All agents agree the code is clean and no issues were found.


Synthesized from 4 reviews (agents: codex, gemini | types: default, security)

@carze
carze force-pushed the feat/pi-support branch from bcadf32 to 7ae6985 Compare March 1, 2026 06:12
@roborev-ci

roborev-ci Bot commented Mar 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (7ae6985)

Summary Verdict: The PR successfully implements Pi agent support, but introduces a rendering bug for task tool calls that requires a fix.

Medium

Lowercase task tool calls can render as empty tool blocks after switching fallback/meta dispatch to category

  • Evidence:

    • task is normalized to Task (taxonomy.go:55).
    • Tool blocks now pass toolCall.category || toolCall.tool_name into metadata/fallback helpers (ToolBlock.svelte:99, [ToolBlock.svelte:115](/tmp/agentsview-review-7
      ae6985/frontend/src/lib/components/content/ToolBlock.svelte:115)).
    • generateFallbackContent("Task", ...) returns null ([tool-params.ts:116](/tmp/agentsview-review-7ae698
      5/frontend/src/lib/utils/tool-params.ts:116)).
    • taskPrompt only triggers for exact tool_name === "Task" ([ToolBlock.svelte:121](/tmp/agentsview-review-7ae6985/frontend
      /src/lib/components/content/ToolBlock.svelte:121)).
    • Structured non-bash/read tool segments are created with empty content ([content-parser.ts:417](/tmp/agentsview-review-7ae6985/frontend/src/lib
      /utils/content-parser.ts:417), content-parser.ts:421).
  • Impact: Tool calls like
    tool_name: "task", category: "Task" can show a header with no prompt, body, or metadata.

  • Suggested Fix: Use tool_name for Task-specific rendering (or normalize both "Task"/"task" in Task handlers) and avoid routing task through the
    generateFallbackContent("Task") -> null path.


Synthesized from 4 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (547b75e)

Summary Verdict: The implementation is generally solid with no security regressions found, but there is one medium-severity issue regarding inflated user message counts
in Pi sessions.

Medium

  • UserMessageCount is inflated for Pi sessions
    • Files: internal/parser/pi.go:137, internal/parser/pi.go:153, internal/parser/pi.go:19 7
    • Description: model_change and compaction entries are turned into RoleUser messages with non-empty content, and later counted as user messages via m.Role == RoleUser && m.Content != "". This overcounts actual user prompts and can skew stats
      /filters.
    • Suggested Fix: Track the real user-message count during the parse loop only for entryType=="message" && role=="user", or explicitly exclude synthetic events from the count.

Synthesized from 4 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (d0545e7)

Verdict: All agents agree the code is clean. No medium, high, or critical severity issues were found.


Synthesized from 4 reviews (agents: codex, gemini | types: default, security)

Note: gemini review skipped (agent quota exhausted)

@roborev-ci

roborev-ci Bot commented Mar 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (5a2ae16)

Verdict: One Medium issue found; no High or Critical findings.

Medium

  1. UserMessageCount can undercount valid Pi user messages
    File: internal/parser/pi.go:111
    userCount is only incremented when msg.Content != "", which can miss valid user turns that contain non-text/structured payloads. Count all successfully parsed role=="user" messages, while keeping synthetic-entry exclusions (model_change/compaction) as-is.

Synthesized from 4 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (527c29f)

Verdict: PR is largely clean, with one Medium functional issue to address before merge.

Medium

  1. Pi Task metadata rendering misses lowercase task tool calls
    File: frontend/src/lib/components/content/ToolBlock.svelte:38
    taskPrompt and subagentSessionId were updated to use category, but taskMeta still gates on tool_name === "Task". For Pi/OpenCode events like tool_name: "task" with category: "Task", Task metadata tags will not render.
    Suggested fix: Use the same isTask predicate for taskMeta that is already used elsewhere in this file.

No Critical or High findings were reported.


Synthesized from 4 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (6438f17)

Verdict: 1 Medium issue found; no High/Critical concerns identified.

Medium

  1. find preview logic is unreachable in structured-tool fallback (deduplicated across reviews)
    • File/line refs:
      • frontend/src/lib/utils/content-parser.ts (around isReadTool, reported at line ~44)
      • frontend/src/lib/utils/content-parser.ts (inside appended structured-tool branch near the input.pattern comment)
    • Issue: isReadTool() does not include "find", but later logic inside the isReadTool(...) branch attempts to handle Pi find and render its pattern preview. That branch never runs for tool_name === "find".
    • Suggested fix: Add "find" to isReadTool() or switch this check to normalized tool category (tc.category || tc.tool_name) so Pi find is consistently treated as Read.

Synthesized from 4 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (a61fbe6)

Verdict: No Medium, High, or Critical findings; PR is clean at actionable severity.

All reviews were consolidated and deduplicated.
No Medium/High/Critical issues were identified.


Synthesized from 4 reviews (agents: codex, gemini | types: default, security)

@carze carze changed the title Add pi support/pi-derivative support feat: Add pi support/pi-derivative support Mar 2, 2026
@roborev-ci

roborev-ci Bot commented Mar 3, 2026

Copy link
Copy Markdown

roborev: Combined Review (110c786)

Summary Verdict: This PR successfully adds end-to
-end support for the Pi agent, but introduces a few medium-severity issues in message counting, styling configuration, and HTML export logic that should be addressed.

Medium

  • Pi user message count fix is effectively bypassed during DB writes

    • Files: internal/parser/pi.go :139, internal/sync/engine.go:1369, internal/sync/engine.go:1429, internal/sync/engine.go:1498
    • Details: ParsePiSession now excludes synthetic model_ change/compaction from UserMessageCount, but the sync path recomputes UserMessageCount from persisted roles (postFilterCounts). Since those synthetic entries are stored as RoleUser, the DB and user-visible counts still include the synthetic entries.
    • Suggested Fix: Preserve
      parser-provided UserMessageCount for Pi (or add a synthetic flag and exclude synthetic rows from postFilterCounts), and add an integration assertion for Pi session counts after sync.
  • Pi agent color mapping and test expectation are inconsistent

    • Files: frontend/src/lib/ utils/agents.ts:16, frontend/src/lib/utils/agents.test.ts:55
    • Details: The implementation sets the Pi agent color to --accent-green, while the test expects --accent-teal. This indicates either a failing test or an incorrect runtime styling target
      .
    • Suggested Fix: Choose one canonical color and align both the implementation and tests (teal is recommended as it is more distinguishable from Codex’s green).
  • HTML export displays incorrect agent name for new agents

    • Files: internal/server/export.go:521 (
      in generateExportHTML)
    • Details: The agentDisplay variable is hardcoded to default to "Claude", with only an explicit check for "codex". With the addition of Pi agent support, exported sessions for this agent will incorrectly display as "Claude" in the header.
  • Suggested Fix: Update the conditional logic to handle "pi" (and any other agents like "gemini"), using a switch statement or map to set the correct agentDisplay value.


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 4, 2026

Copy link
Copy Markdown

roborev: Combined Review (2f073d9)

Verdict: The PR introduces Pi agent support and related features, with one medium-severity portability issue identified in the test suite.

Medium

  • Non-portable test path breaks on
    Windows

    File: internal/parser/pi_test.go:276
    /dev/fd/<n> is Unix-specific
    . The test lr.Err check does not fire on clean pipe read will fail on Windows, causing cross-platform CI instability.
    Suggested fix: Avoid /dev/fd in this test (use a temp file), or gate this subtest by OS and use a Windows-safe approach.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 4, 2026

Copy link
Copy Markdown

roborev: Combined Review (a73c1fd)

Summary Verdict: All agents agree the code is clean; no medium, high, or critical severity issues were found.


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 4, 2026

Copy link
Copy Markdown

roborev: Combined Review (5a753a7)

Summary: The PR successfully adds end-to-end support for the Pi
agent and frontend improvements, but there is one medium-severity issue regarding a stale unit test expectation.

Medium

  • Stale unit test expectation after Pi color change
    • Files: frontend/src/lib/utils/agents.test.ts:54, frontend/src /lib/utils/agents.ts:16
    • Problem: The test still expects pi to be var(--accent-red) while the implementation changed to var(--accent-indigo). This will fail the unit test suite when run.
    • Suggested fix: Update
      the expected value in agents.test.ts to var(--accent-indigo).

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 4, 2026

Copy link
Copy Markdown

roborev: Combined Review (a1e0354)

Summary Verdict: The changes generally look solid, but there is one medium-severity issue regarding missing type guards that could cause runtime crashes in frontend message rendering.

Medium

  • Malformed edits entries can throw at runtime

    File: tool-params.ts:134
    generateFallbackContent() assumes every params .edits item is an object, then directly reads edit.set_line / edit.replace_lines / etc. If an entry is null or a primitive (format drift, partial data), this throws and can break message rendering.
    Suggested fix: guard each
    entry before property access:

    • if (!edit || typeof edit !== "object") continue;
    • then cast to Record<string, unknown>.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 4, 2026

Copy link
Copy Markdown

roborev: Combined Review (87443ca)

The code changes introduce support for the Pi agent,
but there is a syntax error in the added tests that requires a fix.

Medium

  • Broken test syntax in agents.test.ts
    File: /home/roborev/.roborev/clones/wesm/agentsview/frontend/src/lib/utils /agents.test.ts:54
    The expect(agentColor("pi")).toBe(...) call is missing a closing ); before the next expect(...).
    Suggested fix: close the Pi assertion properly:
    expect(agentColor("pi")).toBe("var

(--accent-indigo)");


---
*Synthesized from 3 reviews (agents: codex, gemini | types: default, security)*

@roborev-ci

roborev-ci Bot commented Mar 4, 2026

Copy link
Copy Markdown

roborev: Combined Review (7f3bda2)

Summary Verdict: The PR successfully adds support for the Pi agent, but there is
a medium-severity issue in the frontend content parser regarding tool call rendering.

Medium

  • File: [content-parser.ts](/home/roborev/.roborev/clones/wesm/agentsview/frontend/src/lib/utils/content-parser.ts:3
  • Problem: enrichSegments() only appends remaining structured toolCalls when hasTextBasedTools === false. If parsing produces even one tool-like text segment (including false positives), leftover structured tool calls are dropped.
  • Why it matters: Tool calls can
    disappear from UI in mixed/edge messages.
  • Suggested fix: Always append remaining toolCalls after the main loop (while tcIdx < toolCalls.length), not only in the !hasTextBasedTools branch. Keep dedupe by advancing tcIdx for matched segments.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 4, 2026

Copy link
Copy Markdown

roborev: Combined Review (734de12)

Verdict: All agents agree the code is clean (no medium, high, or critical severity issues found).


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 5, 2026

Copy link
Copy Markdown

roborev: Combined Review (56b88c0)

Review Summary: The PR successfully introduces Pi agent support, but there are high and medium severity parsing
issues that need to be addressed.

High

  • Missing tool result payload persistence for Pi
    • Files: internal/parser/pi.go:296, internal/sync/engine.go:1920
    • parsePiToolResultMessage sets ContentLength but never sets ParsedToolResult.ContentRaw. Downstream pairing decodes tr.ContentRaw, so Pi tool outputs will pair with an empty result_content.
    • Suggested fix: Populate ContentRaw from the message.content raw JSON
      (and ideally reuse shared toolResultContentLength logic). Add a test that verifies paired tool_calls.result_content is non-empty for Pi.

Medium

  • Assistant string-content variant is silently dropped
    • Files: internal/parser/pi .go:234, internal/parser/pi.go:198
    • User parsing handles both string and array content, but assistant parsing only iterates array-style blocks. If Pi emits assistant content as a plain string (format variation/back-compat), the assistant text is lost
      .
    • Suggested fix: Mirror parsePiUserMessage behavior for assistant/tool-result content shape handling; add tests for assistant/toolResult string payloads.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 5, 2026

Copy link
Copy Markdown

roborev: Combined Review (652d814)

Verdict: The PR looks solid overall, but there is one medium-severity issue regarding missing CSS variables in the export templates.

Medium

Missing --accent-indigo in export CSS
Files: internal/server/export.go:312, internal/server/
export.go:344
, [frontend/src/lib/utils/agents.ts:16](/home/roborev/.roborev
/clones/wesm/agentsview/frontend/src/lib/utils/agents.ts:16), [internal/server/export_test.go:550](/home/roborev/.roborev/clones/wesm/agentsview/internal/server/export_
test.go:550)

pi uses var(--accent-indigo) in the frontend, but the export CSS does not define --accent-indigo, and the parity test does not check it. This can cause incorrect Pi color rendering in exported HTML and lets the regression pass tests.

Suggested
fix:
Add --accent-indigo in both light/dark export themes and include it in TestExportTemplateAccentColors.


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 5, 2026

Copy link
Copy Markdown

roborev: Combined Review (8a2af4c)

Summary: The code changes introduce support for the Pi agent and are generally well-implemented, with one medium-severity issue identified regarding JSON reconstruction
.

Medium

  • Manual JSON reconstruction can emit invalid input_json for valid keys with escaping
    • File: internal/parser/pi.go:329, internal/parser/pi.go:338
    • normalizePiIntent() rebuilds JSON via string concatenation and writes keys as " + k + " without escaping. If a key contains "/\/control chars, output becomes invalid JSON and downstream JSON.parse paths lose metadata/fallback rendering.
    • Suggested fix: parse into map[string ]json.RawMessage, move agent__intent/_i to description, then json.Marshal the map.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 5, 2026

Copy link
Copy Markdown

roborev: Combined Review (a3b9596)

Summary Verdict: The commit range successfully adds end-to-end Pi agent support, but introduces a medium-severity UI regression for structured tool calls.

Findings

Medium

  • Structured Edit-category tool calls can render as blank blocks
    • References: content-
      parser.ts:401
      , [ToolBlock.svelte:121](/home/roborev/.roborev
      /clones/wesm/agentsview/frontend/src/lib/components/content/ToolBlock.svelte:121), [tool-params.ts:117](/home/roborev/.roborev/clones/wesm/agentsview/frontend/src/lib
      /utils/tool-params.ts:117)
    • Why: Leftover tool calls are appended with empty content (except Bash/Read). Then ToolBlock passes category (Edit) into generateFallbackContent, but Edit fallback returns null unless it finds known diff fields. Result: some tool calls show no input details (regression for unmatched/structured-only calls like apply_patch).
    • Suggested fix: In ToolBlock, prefer raw tool_name fallback when category-based fallback returns null, or add explicit fallback
      handling for apply_patch/patch-like payloads.

(Note: Several low-severity code quality and testing gaps were identified but omitted according to review guidelines.)


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 6, 2026

Copy link
Copy Markdown

roborev: Combined Review (4131826)

Summary: The PR successfully adds support for the Pi agent and improves tool rendering, with one medium-severity issue regarding tool metadata lookup that needs addressing.

Medium

  • Category-only metadata lookup drops known tool metadata (regression)
    • ToolBlock.svelte
    • tool-params.ts
    • toolParamMeta now calls extractToolParamMeta (toolCall.category || toolCall.tool_name, ...). For tools like Skill, parser category is "Tool", but extractToolParamMeta only has a Skill branch, so metadata disappears.
    • Suggested fix: Mirror fallbackContent behavior: try category
      first, then fallback to tool_name when category lookup returns null.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 7, 2026

Copy link
Copy Markdown

roborev: Combined Review (b106245)

Summary Verdict: The changes successfully introduce Pi agent support and related frontend/backend updates, with one medium-severity edge case identified in the
parsing logic.

Medium

  • Discovery/parser mismatch on leading whitespace-only lines can cause "discoverable but unparsable" Pi sessions.
    • [discovery.go:896](/home/roborev/.roborev/clones/wesm/agentsview/internal
      /parser/discovery.go:896) skips whitespace-only lines via TrimSpace, but pi.go:34 relies on line Reader.next() and immediately validates JSON; linereader.go:39 only skips truly empty lines.
    • Result: a file
      with leading " " lines can pass isPiSessionFile but fail ParsePiSession.
    • Suggested fix: in ParsePiSession, loop until strings.TrimSpace(line) != "" before header validation (or make blank-line handling consistent centrally). Add a parser test for leading
      whitespace-only lines.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci

roborev-ci Bot commented Mar 7, 2026

Copy link
Copy Markdown

roborev: Combined Review (5ff91e3)

Verdict: The code is clean; no issues of medium severity or higher were found across the reviews.


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

Add parser, frontend rendering, and export support for Pi (Anthropic
internal agent) sessions. Includes session discovery, tool call
enrichment, intent normalization, indigo accent color, and FTS indexing.
@wesm

wesm commented Mar 8, 2026

Copy link
Copy Markdown
Member

I am working on this now, I'll rebase and push fixes and get this merged soon

…r Pi

Emit [Thinking] and tool-use markers inline in Content for Pi assistant
messages, matching the pattern used by Claude and Amp parsers. This
preserves block order, fixes export/FTS for tool-only messages, and
ensures thinking text is indexed.

- Add Pi lowercase tool names (read, write, edit, bash, find,
  str_replace, run_command, read_file) to formatToolUse
- Add formatPiToolUse helper that maps Pi's "arguments" field to
  "input" and delegates to formatToolUse
- Emit [Thinking]/[/Thinking] and tool markers in
  parsePiAssistantMessage preserving block order
- Export IsPiSessionFile and add header validation in watcher-driven
  sync (classifyOnePath) to reject non-Pi .jsonl files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wesm
wesm force-pushed the feat/pi-support branch from 5ff91e3 to 66ba363 Compare March 8, 2026 15:02
@wesm wesm changed the title feat: Add pi support/pi-derivative support feat: add Pi agent support Mar 8, 2026
@roborev-ci

roborev-ci Bot commented Mar 8, 2026

Copy link
Copy Markdown

roborev: Combined Review (66ba363)

Summary Verdict: The PR successfully implements Pi agent support end-to-end, but introduces medium-severity issues with
tool path formatting and session ID backward compatibility that need to be addressed.

Medium

  • Pi tool formatting drops file paths for common payload shapes

    • File: [internal/parser/content.go:190](/home/roborev/.roborev/clones/wesm/
      agentsview/internal/parser/content.go:190)
    • Details: write, edit, str_replace (and read_file) only read input.file_path. In this same change set, frontend handling explicitly supports Pi/OpenCode path /filePath, which means backend-rendered tool markers can become [Write: ] / [Edit: ] for valid Pi events.
    • Suggested fix: For these Pi cases, resolve path as file_path ?? path ?? filePath (where applicable), and add parser tests for
      path-only inputs.
  • Session ID format changed without in-app migration path (Regression Risk)

    • File: [internal/parser/pi.go:177](/home/roborev/.roborev/clones/wesm/agentsview/internal/parser/
      pi.go:177)

    • Details: IDs are now always stored as pi:<id>. Existing DB rows from earlier Pi support (bare IDs) will not be recognized by prefix-based lookups (FindSourceFile/single-session sync flows) unless users manually reset/migrate DB.

    • Suggested fix: Add automatic migration (or backward-compat fallback lookup) for existing agent='pi' rows.


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

wesm and others added 4 commits March 8, 2026 10:09
Pi payloads may use path or filePath instead of file_path. Add
resolveFilePath helper with fallback chain (file_path -> path ->
filePath) and apply it to the read, read_file, write, edit, and
str_replace cases in formatToolUse.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
formatPiToolUse was receiving the raw arguments before intent
normalization, so agent__intent wasn't renamed to description
for the Bash description line. Use the post-normalization argsRaw
instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add regression test confirming that agent__intent is renamed to
description before formatPiToolUse renders the Bash description line.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wesm
wesm merged commit e7e6fc7 into kenn-io:main Mar 8, 2026
5 of 6 checks passed
@wesm

wesm commented Mar 8, 2026

Copy link
Copy Markdown
Member

thanks!

cursor Bot pushed a commit to diazMelgarejo/periscope that referenced this pull request Jun 1, 2026
## Summary

- Add Pi as a supported agent with JSONL session parsing, file
discovery, sync, and frontend display
- Parse Pi session files: user messages, assistant messages with
thinking blocks and tool calls, tool results
- Emit thinking and tool-use markers inline in Content (matching
Claude/Amp pattern) so export, FTS, and block ordering work correctly
- Validate Pi session headers during both bulk discovery and
watcher-driven sync

## Backend (Go)

- Pi JSONL parser with V1/V2 session support and `branchedFrom` parent
linking
- File discovery (`DiscoverPiSessions`, `FindPiSourceFile`) registered
in the agent registry with `IDPrefix: "pi:"`, following the Amp pattern
- Lowercase Pi tool names (`read`, `write`, `edit`, `bash`, `find`,
`str_replace`, `run_command`, `read_file`) mapped to standard display
format
- `formatPiToolUse` bridges Pi's `arguments` field to the shared
`formatToolUse` logic
- `IsPiSessionFile` header validation in both bulk discovery and watcher
sync
- `normalizePiIntent` rewrites Pi's `agent__intent`/`_i` fields to
`description`
- Export support for Pi sessions

## Frontend (Svelte/TS)

- Pi agent badge with teal accent
- Tool call display for Pi's lowercase tool aliases and edit format
(`edits[]` array variants)
- Content parser support for Pi tool patterns
- `agent__intent` and `_i` filtered from displayed tool parameters

Addresses kenn-io#68

---------

Co-authored-by: Wes McKinney <wesmckinn+git@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants