This release adds support for Pi 1.4 and makes PiHarness recover more reliably from evictions, crashes and storage errors.
Highlights
- Pi 1.4 support:
agents/harness/pinow runs on Pi 1.4. - Hibernation while Pi's tasks sleep:
PiHarnesspasses Pi'sonWakethrough your harness factory, so a Durable Object sleeps until Pi's next task is due instead of staying in memory. - One wake job per object:
PiHarnesswakes from Pi'swake(), so a task stopped by Pi's restart limit no longer keeps the object awake. - Parked tasks: tasks stopped by Pi's restart limit show as
parkedinpending(), andretry()runs them again. - Recovery: Pi reopens after a storage error instead of failing every call until the object restarts, and the wake job survives failed steps with backoff.
- Fixes: Lifecycle no longer keeps evicted Durable Objects in memory, and it arms a fallback alarm when startup fails. pi-ai now reports cut-off model streams with wording Pi treats as transient, so Pi retries them.
Upgrading
-
Update Pi to
~1.4.0(@earendil-works/pi-durable,pi-ai,pi-agent-core) and install@earendil-works/chordalongside them. Pi 1.4 migrates session storage to a schema Pi 1.3 cannot open, so a deployment cannot roll back past this release. -
Check pi-durable's 1.4.0 changelog for its breaking changes, such as the removal of
TaskRuntime.sleep(), the newsleepingtask status, and the restart limit that parks a crash-looping task after 5 restarts. -
Pass
onWaketoHarness.open, as in the diff below. Without it, the harness still works but logs a warning, and the object stays in memory while Pi's tasks sleep. -
If you create Pi's registry at module scope, move it into your class, as a field or in the factory. Our tool examples showed module scope before this release. Pi keeps every
Harnesssubscribed to its registry until it closes, and an evicted object never closes it, so a module-level registry keeps every evicted object's harness in memory.- const registry = createRegistry(); export class Assistant extends Agent<Env> { + registry = createRegistry(); harness = new PiHarness({ harness: ({ storage, context, onWake }) => - Harness.open(storage, { models, registry }, context) + Harness.open(storage, { models, registry: this.registry, onWake }, context) }); }
-
Keep the harness factory safe to run more than once. It now runs again when Pi reopens after a storage error.
-
Handle the new
parkedstatus if you switch onPiPendingOperation.status.
Existing objects need no migration step. Wake jobs left by earlier releases are handed over to the new wake job on first start.
Minor Changes
-
#2617
cfe9d0fThanks @ben-reitz! - Support Pi 1.4: the Pi peer range is now~1.4.0. Pi 1.4 migrates SQLite session storage to a schema that Pi 1.3 cannot open, so a deployment cannot roll back past this release. See Pi harness. -
#2619
4b535dcThanks @ben-reitz! -PiHarnesshands its factory anonWaketo pass toHarness.open, so the Durable Object can hibernate while Pi's tasks sleep. Add it to your factory:harness: ({ storage, context, onWake }) => Harness.open(storage, { ...options, onWake }, context). Without it the harness still works and logs a warning. See Pi harness. -
#2624
3954859Thanks @ben-reitz! -PiHarnessshows operations stopped by Pi's restart limit asparkedinpending(), andretry()runs them again. See Pi harness.
Patch Changes
-
#2644
f404547Thanks @ben-reitz! - Lifecycle arms a fallback alarm while its job queue holds jobs, before startup runs in an alarm and after a startup that queued jobs throws, so a failed startup cannot leave queued jobs without a wake. See Lifecycle. -
#2653
fc4cd24Thanks @ben-reitz! - Stop Lifecycle startup keeping an evicted Durable Object in memory when a capability's startup leaves a promise pending, asPiHarnessdoes when it opens Pi. See Pi harness. -
#2643
e117121Thanks @ben-reitz! -agents/models/pi-aireports a cut-off or idle model stream with wording pi's retry policy treats as transient, so pi retries the turn instead of failing it. See Models with pi-ai. -
#2617
cfe9d0fThanks @ben-reitz! -agents/harness/pinow uses chord's own context helpers, so install@earendil-works/chordalongside pi-durable and pi-ai. See Pi harness. -
#2648
000fcafThanks @ben-reitz! -PiHarnessopens pi again after a storage error closes it, instead of failing every call until the object restarts. See How recovery works. -
#2618
3e91dedThanks @ben-reitz! -PiHarnesswakes from Pi'swake()with one job per object, so a task parked by Pi's restart limit no longer keeps the Durable Object awake. See Pi harness. -
#2649
91a8f61Thanks @ben-reitz! -PiHarnesskeeps its wake job when a step fails, retrying with a backoff up to 10 minutes, and counts a memory-limit reset during the job's wait against the alarm memory-limit breaker. See How recovery works.