Files
takopi/docs/runner/pi/pi-takopi-events.md
T
2026-01-02 17:12:32 +04:00

4.0 KiB

Pi -> Takopi event mapping (spec)

This document specifies how the Pi runner shipped in Takopi v0.5.0 translates Pi CLI --mode json JSONL events into Takopi events. The Pi JSONL stream is AgentSessionEvent from @mariozechner/pi-agent-core.

The goal is to make Pi feel identical to the Codex/Claude runners from the bridge/renderer point of view while preserving Takopi invariants (stable action ids, per-session serialization, single completed event).


1. Input stream contract (Pi CLI)

Pi CLI emits one JSON object per line (JSONL) when invoked with:

pi --print --mode json <prompt>

Notes:

  • --print is required for non-interactive runs.
  • --mode json outputs all agent events (no TUI banners).
  • Pi does not support -- <prompt>; prompts starting with - must be prefixed (Takopi does this automatically).

2. Resume tokens and resume lines

  • Engine id: pi
  • Canonical resume line (embedded in chat):
`pi --session <path>`

The token is the session JSONL file path.

Why not --resume?

  • --resume/-r opens an interactive session picker; it does not accept a session token. Takopi must use --session <path> instead.

3. Session lifecycle + serialization

Takopi requires serialization per session token:

  • For new runs (resume=None), do not acquire a lock until a started event is emitted (Takopi emits this as soon as the first JSON event arrives).
  • Once the session is known, acquire a lock for pi:<session_path> and hold it until the run completes.
  • For resumed runs, acquire the lock immediately on entry.

4. Event translation (Pi JSONL -> Takopi)

Pi emits AgentSessionEvent objects. Only a subset is required for Takopi.

4.1 tool_execution_start

Example:

{"type":"tool_execution_start","toolCallId":"tool_1","toolName":"bash","args":{"command":"ls"}}

Mapping:

  • Emit action with phase="started".
  • action.id = toolCallId.
  • action.kind from tool name (see section 5).
  • action.title derived from tool + args.

4.2 tool_execution_end

Example:

{"type":"tool_execution_end","toolCallId":"tool_1","toolName":"bash","result":{...},"isError":false}

Mapping:

  • Emit action with phase="completed".
  • ok = !isError.
  • Carry result and isError in detail for debugging.

4.3 message_end (assistant)

Pi emits message lifecycle events. For message_end where message.role == "assistant":

  • Store the latest assistant text as the final answer fallback.
  • If stopReason is error or aborted, store errorMessage.
  • Capture usage for completed.usage.

4.4 agent_end

Example:

{"type":"agent_end","messages":[...]} 

Mapping:

  • Emit a single completed event:
    • ok = true unless the last assistant message has stopReason error or aborted.
    • answer = last assistant text (from message_end or agent_end.messages).
    • error = errorMessage if present.
    • resume = ResumeToken(engine="pi", value=session_path).
    • usage = last assistant usage.

4.5 Other events

Ignore unknown events. If a JSONL line is malformed, emit a warning action and continue (default JsonlSubprocessRunner behavior).


5. Tool name -> ActionKind mapping heuristics

Pi tool names are lower-case by default. Suggested mapping:

Tool name ActionKind Title logic
bash command args.command
edit, write file_change args.path
read tool read: <path>
grep tool grep: <pattern>
find tool find: <pattern>
ls tool ls: <path>
(default) tool tool name

For file_change, include detail.changes = [{"path": <path>, "kind": "update"}].


6. Usage mapping

Takopi completed.usage should mirror Pi's assistant usage object without transformation.


7. Suggested Takopi config keys

A minimal TOML config for Pi:

[pi]
cmd = "pi"
model = "..."
provider = "..."
extra_args = []

Use extra_args for any newer Pi CLI flags not explicitly mapped.