Skip to content

feat(pi-acp): opt-in persistent sessions via PI_SESSION_DIR#1672

Merged
NathanFlurry merged 1 commit into
rivet-dev:mainfrom
khaled-mansour-zid:zid/adapter-session-persistence
Jul 10, 2026
Merged

feat(pi-acp): opt-in persistent sessions via PI_SESSION_DIR#1672
NathanFlurry merged 1 commit into
rivet-dev:mainfrom
khaled-mansour-zid:zid/adapter-session-persistence

Conversation

@khaled-mansour-zid

Copy link
Copy Markdown
Contributor

feat(pi-acp): opt-in persistent sessions via PI_SESSION_DIR

Problem

registry/agent/pi/src/adapter.ts hardcodes SessionManager.inMemory(params.cwd)
for every new session. In-memory means pi never writes the session .jsonl, so the
entire conversation is lost the moment the adapter process restarts (actor
sleep/eviction, crash, redeploy). There is no way for an embedder to get persistent,
resumable sessions short of patching the adapter.

Pi already provides the other half — SessionManager.continueRecent(cwd, sessionDir)
persists the session under sessionDir and resumes the most recent one. It just
isn't reachable from the ACP adapter.

Change

Add resolveSessionManager(SessionManager, cwd, env): if PI_SESSION_DIR is set in
the session env, use continueRecent(cwd, PI_SESSION_DIR); otherwise inMemory(cwd).
Wire the newSession call site to it.

  • Additive & non-breaking — default stays in-memory; behavior only changes when
    the embedder sets PI_SESSION_DIR.
  • Env-driven, matching the accepted SECURE_EXEC_FRAME_TIMEOUT_MS override (feat(runtime-core): env-override the native sidecar frame timeout #1641).
  • TestedresolveSessionManager is exported and unit-tested with a fake
    SessionManager (persist branch, default branch, blank-value guard); the real
    newSession path needs the Pi SDK so the selection logic is tested directly.

Verification

resolveSessionManager logic verified for all three branches; check-types + the
tests/*.test.mjs node:test suite run in CI.

The Pi ACP adapter hardcodes `SessionManager.inMemory(params.cwd)` for every new
session, so nothing is written to disk and the whole conversation is lost when the
adapter process restarts (e.g. an actor sleep/eviction). Pi already ships
`SessionManager.continueRecent(cwd, sessionDir)` — persist + resume the most
recent session — but there's no way for an embedder to select it without patching
the adapter source.

Add `resolveSessionManager()`: when the embedder provides a session directory via
the `PI_SESSION_DIR` env var, use `continueRecent` (persist under that dir and
resume); otherwise keep the current in-memory behavior. Env-driven and additive —
no behavior change unless `PI_SESSION_DIR` is set (same pattern as the
`SECURE_EXEC_FRAME_TIMEOUT_MS` override in rivet-dev#1641). The helper is exported and unit
tested with a fake SessionManager (the real newSession path needs the Pi SDK).

Co-authored-by: Khaled Mansour <[email protected]>

@NathanFlurry NathanFlurry left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Validated the persistence selection and tests. Merging this additive patch; native ACP load and persistent-by-default behavior will follow separately.

@NathanFlurry
NathanFlurry merged commit 8c9206b into rivet-dev:main Jul 10, 2026
4 checks passed
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.

2 participants