Repository navigation
Adopt Pi 1.4.0: durable task recovery, reports, and request identity - #108
Merged
Merged
Conversation
Raise pi-durable, chord, and pi-codemode to 1.4.0, and the Pi peers to ^1.4.0, from npm; nothing probes for or works around 1.3. pi-durable 1.4.0 requires a checkpoint policy on every document definition. The agents, graphs, and message log documents live as long as the session and change in small steps, so each stores a complete base after 64 deltas: replay stays bounded and storage may reclaim older records, without rewriting every agent at each change. Before, they never checkpointed. TaskRuntime.sleep() is gone. A settling graph node rechecks on a phase timer instead, since the phase keeps running and watching anyway. Stopping agents also aborts their sleeping tasks, such as generation retry backoffs, which now sleep between phases.
Messages from other agents and the user's attach-view input now carry an input entry kind (pi-agents.message with the sender, pi-agents.user) instead of relying on the [from <name>] and [user] markers. The model still reads the markers; the attach view and Esc restoration read the entry, including the results entries of spawned groups. A plain pi.user input is the parent's: inputs stored by earlier versions aren't parsed for markers.
agent_status, agent_send, and agent_spawn declare structured output schemas, so an agent's codemode scripts get data instead of text: the reachable agents with their state, model, and job; a send's recipient, mode, and what its interrupt did; and a spawned group with its agents' IDs and full names. The model-facing text and the receipts stay as they were; refusals stay error results, which reject in scripts. agent_wait stays model-only.
pi-durable keeps the newest compaction failure in pi.live until a compaction produces a summary. Agent infos carry it, and the panel line, /agents, the attach view, and the parent's agent_status show it, without changing the agent's state.
A running codemode call draws the nested calls it owns from pi.live.nestedTools; a finished one draws the calls its result's details list. The script output drops its header and, when the call lines show, the failure text's list of calls, so nothing shows twice.
Pi resolves compaction.modelOverrides only for a given model, so agents got the harness-wide values alone. The harness settings now carry the overrides as pi-durable's compaction.modelOverrides, which applies them for the model each compaction acts for. The harness also reads its settings through pi-durable's settings function instead of copying them once at open, so the getters run at each use as documented.
pi-durable parks a task that crashes cut off restartLimit times in a row, and its task graph tells why a live task can't run. The service follows the task graph: an agent or graph whose tasks are parked or blocked shows as stalled while it stays working, and service.retry() runs parked tasks again, of the agent or the graph's agents and of everything they spawned. /agents retries with r, the attach view and agent_status say why the agent doesn't progress, and the models get no retry tool, since a crash loop needs the user's judgment.
pi-durable's onReport now passes ReportInfo: the task, its conversation, the extension, or the host callback a report is about. The host turns it into plain data, and the service words it with the agent or graph it belongs to. Reports during open wait until the service knows the agents, and a failed session reports only through the storage recovery.
pi-durable 1.4.0 attributes every harness request to Pi unless told otherwise, and agents borrow the parent's model runtime, which lacks the identity Pi adds per request. The harness now gets Pi's identity: a detailed User-Agent with Pi's version, and Pi's attribution only while install telemetry is on, with PI_TELEMETRY overriding the setting as in Pi. It covers generation, compaction, and codemode scripts' model calls, and is read when the harness opens, like the other settings.
mavam
force-pushed
the
topic/durable-task-recovery
branch
from
October 22, 2026 05:39
964aef4 to
350a98e
Compare
mavam
marked this pull request as ready for review
October 22, 2026 05:43
The attach pane handled only wheel events, so clicks never reached the transcript and cards expanded only with Ctrl+O. The pane now maps a click's row through the window it last drew, past the separator and the clipped start, to the transcript container, which hands it to the card there as Pi's containers do. Tool cards toggle through Pi's ToolExecutionComponent; clicks on the status, editor, or separator pass on, and a click on the newer-lines note follows new output. Click-to-expand for cards now lives in one place, expandableCard, which both Pi's transcript result cards and the attach view's message cards use: a click toggles the card, and a change of the global expansion (Ctrl+O) sets it again.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔍 Problem
pi-agents doesn't use durable state and APIs that pi-durable provides, and it doesn't build against Pi 1.4.0:
[from …]/[user]text.onReportnow says what failed, but we drop that information.checkpointWhenis now required on every document, andTaskRuntime.sleep()is gone.🛠️ Solution
^1.4.0. There are no version probes or 1.3 paths.sleep(): a settling graph node rechecks onruntime.setTimer()within its running phase. Stopping agents also aborts theirsleepingtasks, such as retry backoffs.HarnessOptions.identity: a detailedUser-Agentwith Pi'sVERSION, andPI_ATTRIBUTIONonly while install telemetry is on.PI_TELEMETRY(1/true/yes) overridesgetEnableInstallTelemetry(). The identity covers generation, compaction, and codemodemodels.*calls. Like the other settings, it's read when the harness opens.pi-agents.userandpi-agents.message(with the sender). The model still reads the markers. The attach view and Esc restoration read the entry, including thepi-agents.resultsentries of spawned groups. A plainpi.userinput is the parent's, so markers are never parsed.agent_status,agent_send, andagent_spawndeclare output schemas. Refusals stay error results, which reject in scripts.agent_waitstays model-only.live.compactionFailureshows as a warning until a compaction succeeds. The agent's state doesn't change.live.nestedToolswhile the script runs, and fromdetails.callsonce it's done.compaction.modelOverridesis forwarded, and settings pass through pi-durable's settings function.stalledwhile the agent staysworking./agentsretries withr, covering the agent or the graph's agents and everything they spawned. Models see the stall but get no retry tool.expandableCard, used by Pi's transcript result cards and the attach view's message cards; tool cards use Pi'sToolExecutionComponent.ReportInfobecomes plain data. Notices name the agent or graph and what failed.Deliberately unchanged:
afterFailedRun: stayskeep.HarnessOptions.telemetryhas no sink to forward to.💬 Review
Rebased onto
main(v0.37.0). Recursive spawning (#115) replaceddelegate_graph, so the structured-output commit now targetsagent_spawn/agent_status/agent_send. Stalls and retries followagent_spawnownership recursively.No backward compatibility, deliberately:
Validation:
bun run checkpasses on every commit against the npm 1.4.0 packages from a cleanbun install(252 tests at the tip). The lockfile is regenerated, with no local paths or tarballs.node_modules/@earendil-works/pi-coding-agent/dist/bundle/cli.js) in a throwawayHOME, using a scripted faux provider, with no paid calls. The parent ranagent_spawnandagent_wait, and a child's codemode script gotagent_statusas data. WithPI_TELEMETRY=0, the child's requests carriedattribution: null. WithPI_TELEMETRY=1, they carriedPI_ATTRIBUTION, both withversion: "1.4.0".rretry, the attach view's codemode calls, compaction warnings), a real provider's headers, and compaction requests in a live session. Automated tests cover the logic.Where to look:
src/agents/records.ts: the checkpoint policy.src/agents/graphs.ts:nextChange.src/host/harness-setup.ts:harnessIdentity.src/agents/stalls.tsand its wiring, plusProjection.below(), the retry scope.