Skip to content

feat: pi agent watcher#2

Merged
Palanikannan1437 merged 7 commits intoAtaraxy-Labs:mainfrom
mbcrocci:main
Apr 8, 2026
Merged

feat: pi agent watcher#2
Palanikannan1437 merged 7 commits intoAtaraxy-Labs:mainfrom
mbcrocci:main

Conversation

@mbcrocci
Copy link
Copy Markdown
Contributor

Adds a new watcher for the pi coding agent.
It reads sessions jsonl transcripts to detect the harness' status.

Copy link
Copy Markdown
Contributor

@Palanikannan1437 Palanikannan1437 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the effort @mbcrocci, overall the structure closely follows our existing JSONL watchers and the code is clean.

I verified against the real Pi data on my machine and caught a few issues, most notably a status flicker bug and a missing seed emit that the other watchers all have now.

Main things to fix:

  1. toolResult role causes idle flicker mid-turn — confirmed with real Pi JSONL data
  2. Missing seed-time emit — Pi agents running at startup won't show in the TUI
  3. decodeProjectDir breaks on hyphenated paths — confirmed with real path /Users/.../mi-pi

See inline comments for details 👇

await this.processFile(filePath);
}
} finally {
if (!this.seeded) this.seeded = true;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the biggest gap vs. the other watchers right now! All of them (codex, claude-code, amp, opencode) emit non-idle sessions after the seed scan completes — that's what populates the TUI sidebar when the server starts up.

Your scan() sets this.seeded = true but never loops through this.sessions to emit them. Compare with the Codex watcher's finally block:

if (!this.seeded) {
  this.seeded = true;
  for (const [threadId, snapshot] of this.sessions) {
    if (snapshot.status === "idle" || !snapshot.projectDir) continue;
    const session = this.ctx?.resolveSession(snapshot.projectDir);
    if (!session) continue;
    this.ctx?.emit({
      agent: "pi",
      session,
      status: snapshot.status,
      ts: Date.now(),
      threadId: snapshot.sessionId ?? threadId,
      ...(snapshot.threadName && { threadName: snapshot.threadName }),
    });
  }
}

Without this, if Pi is mid-task when the server starts, it'll be invisible in the sidebar until the next status change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the codex block almost exactly, but I'm not sure if the issue is fixed.

In my setup, no sessions show up until I initiate the conversion (even if resuming a session). But this happens in Pi, OpenCode and Codex.

Copy link
Copy Markdown
Contributor

@Palanikannan1437 Palanikannan1437 Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no no i meant if the tui was quit and restarted, if say you were running 4 sessions and then quit the sidebar (using q) or updated the version (using tpm update flow), it would seed your data back in for the running sessions on restart, I'll check it though once

Adds a new watcher for the pi coding agent.
It reads sessions jsonl transcripts to detect the harness' status.
@mbcrocci mbcrocci force-pushed the main branch 2 times, most recently from ef527ef to b55489e Compare April 1, 2026 12:24
@mbcrocci
Copy link
Copy Markdown
Contributor Author

mbcrocci commented Apr 1, 2026

Hi, thank you for your thorough review and the project - it's really cool!
I've addressed all the issues and in my testing it provided a much better experience, specially the flickering bug.

There are two pending issues I detected that I'm not sure if they are related to the pi-watcher or my specific tmux setup:
1 - Agent sessions don't appear in the sidebar until I talk in them with pi as well as opencode and codex (I commented this in the related PR comment)
2 - Sometimes (cannot reliably reproduce) agent sessions from my second sessions only appear in my first tmux session

Let me know if there is anything else that needs fixing.

@rs545837
Copy link
Copy Markdown
Member

rs545837 commented Apr 1, 2026

/inspect

Copy link
Copy Markdown

@inspect-review inspect-review bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inspect review

Triage: 37 entities analyzed | 0 critical, 0 high, 3 medium, 34 low
Verdict: standard_review

Findings (3)

  1. [low] Seed scan can crash after stop(): scan()'s finally block uses this.ctx.resolveSession(...) and this.ctx.emit(...) without re-checking this.ctx. stop() sets this.ctx = null, so if stop() is called while scan() is in-flight, finally will throw. Evidence: stop(): this.ctx = null; and scan() finally: const session = this.ctx.resolveSession(snapshot.projectDir); ... this.ctx.emit({ ... }).
  2. [low] Incremental tail parsing can permanently drop entries when the last JSONL line is partially written: processFile() advances snapshot.fileSize to fileStat.size even if applyEntries() skips a truncated JSON line (JSON.parse fails). On the next run, those bytes are no longer re-read, so the entry is lost. Evidence: incremental path sets nextSnapshot = applyEntries(text, { ...prev, fileSize: fileStat.size }); and applyEntries(): try { entry = JSON.parse(rawLine); } catch { continue; } with no buffering/retry of the incomplete last line.
  3. [low] sessions Map key collision across directories: sessions are keyed only by threadId parsed from filename, ignoring the encoded directory. Two different projects with the same session-id suffix will overwrite each other, mixing state and emitting against the wrong session. Evidence: const threadId = parseThreadId(filePath); const prev = this.sessions.get(threadId); ... this.sessions.set(threadId, nextSnapshot); and parseThreadId uses only basename split on '_' (return name.split('_').at(-1) ?? name;).

Reviewed by inspect | Entity-level triage found 0 high-risk changes

@Palanikannan1437 Palanikannan1437 merged commit fe91975 into Ataraxy-Labs:main Apr 8, 2026
@Palanikannan1437
Copy link
Copy Markdown
Contributor

hey @mbcrocci, merged! thanks for the clean work and for sticking with the review — appreciate it. those two issues you mentioned aren't related to the pi watcher, will look into them separately. welcome to the project 🙌

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.

3 participants