Archived
docs(issue-62): add relay plan for AuthStorage->ModelRuntime migration
This commit is contained in:
@@ -0,0 +1,127 @@
|
|||||||
|
# Relay charter — issue-62-authstorage
|
||||||
|
|
||||||
|
## Relay identity
|
||||||
|
- **Name:** `issue-62-authstorage`
|
||||||
|
- **Root path:** `relays/issue-62-authstorage/` (in the repo, on branch
|
||||||
|
`fix/issue-62-authstorage`, worktree `/srv/dev/pi-web-issue-62`)
|
||||||
|
- **Packet files:** `charter.md`, `status.md`, `log.md` (this directory).
|
||||||
|
|
||||||
|
## Background (read once, do not re-derive)
|
||||||
|
The full technical assessment lives at the worktree root:
|
||||||
|
`ASSESSMENT-issue-62.md`. Read it once at the start of your leg for the API
|
||||||
|
migration details; do not re-investigate the SDK from scratch. Short version:
|
||||||
|
Pi `@earendil-works/pi-coding-agent` 0.80.8 removed the `AuthStorage` export and
|
||||||
|
replaced the auth/model plumbing with an async `ModelRuntime` + pi-ai
|
||||||
|
`CredentialStore` model. Pi Web imports `AuthStorage` statically and crashes at
|
||||||
|
module load with any Pi 0.80.8+. The agreed fix is a **clean migration to the
|
||||||
|
new `ModelRuntime` API** (no dual-version shim) plus dependency-range
|
||||||
|
correction, tests, and a changeset. Rationale and the per-file migration shape
|
||||||
|
are in `ASSESSMENT-issue-62.md` §5.
|
||||||
|
|
||||||
|
## Goal / finish line
|
||||||
|
Pi Web builds, typechecks, lints, and passes its full test suite against Pi
|
||||||
|
`@earendil-works/pi-coding-agent` **0.80.8+** (target the installed 0.80.8/0.80.10
|
||||||
|
line), with:
|
||||||
|
1. No remaining import or use of the removed `AuthStorage` export (and no
|
||||||
|
reliance on `ModelRegistry.create(authStorage)` / `.inMemory(authStorage)` /
|
||||||
|
`modelRegistry.authStorage`).
|
||||||
|
2. Auth, OAuth login, API-key save/logout, provider enumeration, and the
|
||||||
|
Anthropic subscription warning all working through the new `ModelRuntime` /
|
||||||
|
`readStoredCredential` / pi-ai `CredentialStore` APIs.
|
||||||
|
3. `package.json` peerDependencies and devDependencies for the three
|
||||||
|
`@earendil-works/*` packages corrected so npm cannot resolve an unsupported
|
||||||
|
release (target range `>=0.80.8 <0.81`; devDeps on a matching `^0.80.8`).
|
||||||
|
4. A `.changeset/*.md` fragment describing the user-visible fix (no direct
|
||||||
|
`CHANGELOG.md` edit).
|
||||||
|
5. `npm run verify` (typecheck + lint + knip + test) passing.
|
||||||
|
|
||||||
|
Finish line reached = all of the above true and committed on the branch. **Do
|
||||||
|
not open a PR** (out of scope for this relay).
|
||||||
|
|
||||||
|
## Sizing — one leg
|
||||||
|
One leg = **one coherent slice** from the plan below that leaves the tree in a
|
||||||
|
committed, describable state. Prefer the pre-broken-out slices in `status.md`.
|
||||||
|
A leg does not have to leave `npm run verify` fully green (the migration is
|
||||||
|
interdependent), but it MUST:
|
||||||
|
- leave a clear, honest `status.md` describing what compiles/what doesn't yet,
|
||||||
|
- commit its work with a clear message,
|
||||||
|
- not expand scope beyond its slice ("just a bit more" is the main failure mode
|
||||||
|
here — the auth surfaces are interconnected; resist rewriting everything in
|
||||||
|
one leg).
|
||||||
|
|
||||||
|
If a slice turns out bigger than expected, split it and hand off mid-plan with
|
||||||
|
an updated `status.md` — that is expected and fine.
|
||||||
|
|
||||||
|
## Suggested slice breakdown (task selection default)
|
||||||
|
Follow `status.md`'s named next task. If none is named, pick the lowest-numbered
|
||||||
|
incomplete slice here:
|
||||||
|
|
||||||
|
0. **Bootstrap:** `npm install` in the worktree pinning the three `@earendil-works/*`
|
||||||
|
packages to 0.80.8+ (e.g. `npm i -D @earendil-works/[email protected]
|
||||||
|
@earendil-works/[email protected] @earendil-works/[email protected]`), and
|
||||||
|
correct the peerDependencies range to `>=0.80.8 <0.81`. Confirm the crash
|
||||||
|
reproduces / the new exports resolve. Commit. (Install in the worktree, NOT
|
||||||
|
`/tmp` — `/tmp` has a disk quota problem, see assessment §8.)
|
||||||
|
1. **`authService.ts` core migration:** move to `ModelRuntime` (async
|
||||||
|
construction via `ModelRuntime.create({ authPath, modelsPath })`), migrate
|
||||||
|
saveApiKey/logout/refresh/credential access. Propagate async construction to
|
||||||
|
`sessiond.ts`. (Session-daemon path — see restart note.)
|
||||||
|
2. **`authProviderOptions.ts` migration:** rederive login/logout provider
|
||||||
|
options from `runtime.getProviders()` + `listCredentials()` /
|
||||||
|
`getProviderAuthStatus()`; update its structural interface + test double.
|
||||||
|
3. **`oauthLoginFlowService.ts` migration:** reimplement against pi-ai
|
||||||
|
`AuthInteraction` (`prompt`/`notify`) instead of `OAuthLoginCallbacks`; wire
|
||||||
|
`runtime.login(providerId, "oauth", interaction)`. (Riskiest slice — verify
|
||||||
|
prompt/select/device-code/auth_url mapping.)
|
||||||
|
4. **`piSessionService.ts` migration:** pass `modelRuntime` to
|
||||||
|
`createAgentSessionServices`; update `PiAgentSession` type; switch
|
||||||
|
`anthropicSubscriptionWarning` to `readStoredCredential`.
|
||||||
|
5. **Tests + testSupport:** migrate all test doubles to `InMemoryCredentialStore`
|
||||||
|
+ `ModelRuntime.create`; get `npm run verify` green. Follow the testing-guide
|
||||||
|
skill.
|
||||||
|
6. **Changeset + final verify + cleanup:** add `.changeset/*.md`; run full
|
||||||
|
`npm run verify`; remove scratch (`ASSESSMENT` stays, `/srv/dev/pi-inspect`
|
||||||
|
is outside the repo). Confirm goal, hand off to a final confirmation/stop.
|
||||||
|
|
||||||
|
Slices may merge or split. 1–4 depend on 0. Slice 5 finalizes; slice 6 closes.
|
||||||
|
|
||||||
|
## Handover
|
||||||
|
When handing off, `spawn_session` **once** with a prompt whose first line is:
|
||||||
|
`Relay "issue-62-authstorage" leg <N> begins now.` followed by the standard
|
||||||
|
Relay handoff body pointing at:
|
||||||
|
- `relays/issue-62-authstorage/charter.md`
|
||||||
|
- `relays/issue-62-authstorage/status.md`
|
||||||
|
|
||||||
|
Tell the next runner not to read `log.md` end-to-end. Make all work durable
|
||||||
|
(update `status.md`, append `log.md`, commit) **before** spawning.
|
||||||
|
|
||||||
|
## Intervention signal — stop and get the human when:
|
||||||
|
- The new SDK API does not actually provide an operation the migration needs
|
||||||
|
(e.g. no viable credential persistence path for API-key save), i.e. the
|
||||||
|
assessment's assumed mapping is wrong.
|
||||||
|
- A slice would require changing the charter's goal or the agreed "clean
|
||||||
|
migration, no shim" decision.
|
||||||
|
- `npm install` / registry access fails and cannot be resolved in-leg.
|
||||||
|
- Charter churn: if you find yourself needing to edit this charter to proceed,
|
||||||
|
stop and involve the human instead.
|
||||||
|
To raise it: set a clear `## BLOCKED` section at the top of `status.md`, append a
|
||||||
|
`log.md` entry explaining the blocker and what decision is needed, do **not**
|
||||||
|
spawn the next leg, and end your run.
|
||||||
|
|
||||||
|
## Reading discipline
|
||||||
|
Read, in order: this `charter.md`, then `status.md`, then `ASSESSMENT-issue-62.md`
|
||||||
|
(once), then only the specific `src/server/sessions/*` files your slice touches.
|
||||||
|
Do **not** read `log.md` end-to-end — only targeted entries if `status.md` points
|
||||||
|
you there. Do not re-extract SDK tarballs unless the assessment is contradicted
|
||||||
|
by reality.
|
||||||
|
|
||||||
|
## Standing constraints (project conventions)
|
||||||
|
- Session-daemon changes (`sessiond.ts`, session runtime / auth construction
|
||||||
|
loaded by the daemon) require the human to **manually restart the sessiond
|
||||||
|
service** to take effect. Call this out in `status.md`/handoff whenever a leg
|
||||||
|
changes that path so the human knows a restart is pending.
|
||||||
|
- Follow the skills: `code-quality-architecture` (DI, async boundaries,
|
||||||
|
testable seams), `testing-guide` (test layers, no over-mocking), and
|
||||||
|
`changeset-changelog` (changeset not CHANGELOG edit).
|
||||||
|
- Keep changes scoped to the fix; do not opportunistically refactor unrelated
|
||||||
|
code.
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Relay log — issue-62-authstorage
|
||||||
|
|
||||||
|
Append-only. One concise entry per leg. Do not read end-to-end for orientation;
|
||||||
|
use `status.md`. Targeted lookups only.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Leg 0 — Planning (assessment + relay packet)
|
||||||
|
|
||||||
|
**Did:**
|
||||||
|
- Read issue #62 and confirmed the crash: static `import { AuthStorage }` fails
|
||||||
|
at ESM load with Pi 0.80.8+.
|
||||||
|
- Investigated all `AuthStorage`/`ModelRegistry` usage in `src/` (3 production
|
||||||
|
files + 5 test/support files under `src/server/sessions/`; other
|
||||||
|
pi-coding-agent imports unaffected).
|
||||||
|
- Downloaded and diffed real npm tarballs (pi-coding-agent 0.80.7/0.80.8/0.80.10
|
||||||
|
and pi-ai 0.80.7/0.80.8) into `/srv/dev/pi-inspect` (scratch, outside repo) to
|
||||||
|
establish the exact new export surface: `AuthStorage` and its backends removed
|
||||||
|
from exports; new `ModelRuntime` (async) + `readStoredCredential`; changed
|
||||||
|
`ModelRegistry` (constructed from a runtime, `refresh()` now async, no
|
||||||
|
`authStorage`); pi-ai `CredentialStore`/`InMemoryCredentialStore`/
|
||||||
|
`AuthInteraction` model. Confirmed 0.80.8 and 0.80.10 `.d.ts` are identical
|
||||||
|
for the affected files (stable target).
|
||||||
|
- Wrote `ASSESSMENT-issue-62.md` (root).
|
||||||
|
|
||||||
|
**Decisions:**
|
||||||
|
- **Clean migration to `ModelRuntime`, no dual-version compat shim.** Rationale:
|
||||||
|
sync→async, credential-store contract change, OAuth callback contract change,
|
||||||
|
and session-services option change span both surfaces with no small clean
|
||||||
|
adapter; 0.80.0–0.80.7 is already broken/superseded (`latest` = 0.80.10).
|
||||||
|
- **Dep range fix:** peerDeps `>=0.80.0 <1` → `>=0.80.8 <0.81` for all three
|
||||||
|
`@earendil-works/*` packages; upper bound `<0.81` because this line ships
|
||||||
|
breaking changes within `0.80.x`.
|
||||||
|
- Relay packet placed under `relays/issue-62-authstorage/` (committed; not in
|
||||||
|
`package.json` `files`, so not published; `.pi-web/` is gitignored so not used).
|
||||||
|
|
||||||
|
**Artifacts changed:** `ASSESSMENT-issue-62.md`;
|
||||||
|
`relays/issue-62-authstorage/{charter,status,log}.md`.
|
||||||
|
|
||||||
|
**Status update:** last completed leg 0, next leg 1 = charter slice 0
|
||||||
|
(Bootstrap: install Pi 0.80.8+, correct dep ranges).
|
||||||
|
|
||||||
|
**Blockers:** none. Noted `/tmp` disk-quota issue (install in worktree) and the
|
||||||
|
pending sessiond restart for later daemon-path slices.
|
||||||
|
|
||||||
|
**Handoff:** Planning only — NOT auto-spawning the first implementation leg.
|
||||||
|
Assessment + relay plan are laid out ready to be kicked off by the user.
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Relay status — issue-62-authstorage
|
||||||
|
|
||||||
|
## Current position
|
||||||
|
Relay planned and packet created. Assessment complete and committed
|
||||||
|
(`ASSESSMENT-issue-62.md`). No fix work has started. The worktree has **no
|
||||||
|
`node_modules` installed yet** — the first implementation leg must install deps
|
||||||
|
(pinned to Pi 0.80.8+) before anything typechecks.
|
||||||
|
|
||||||
|
## Leg tracking
|
||||||
|
- **Last completed leg:** 0 (planning — this packet + assessment).
|
||||||
|
- **Next leg to run:** 1.
|
||||||
|
|
||||||
|
## Next task
|
||||||
|
Run **charter slice 0 (Bootstrap)** as leg 1:
|
||||||
|
1. In the worktree (`/srv/dev/pi-web-issue-62`), install deps pinning the three
|
||||||
|
`@earendil-works/*` packages to 0.80.8+ (0.80.8 or current 0.80.10):
|
||||||
|
`@earendil-works/pi-coding-agent`, `@earendil-works/pi-ai`,
|
||||||
|
`@earendil-works/pi-agent-core`. Install in the worktree, **not `/tmp`**
|
||||||
|
(`/tmp` has a disk-quota problem; see assessment §8).
|
||||||
|
2. Correct `package.json`: peerDependencies for the three packages
|
||||||
|
`>=0.80.0 <1` → `>=0.80.8 <0.81`; devDependencies `^0.80.6` → `^0.80.8`.
|
||||||
|
3. Confirm the new export surface resolves (`readStoredCredential`,
|
||||||
|
`ModelRuntime` present; `AuthStorage` gone) — e.g. a quick node/tsx check or
|
||||||
|
just observe the typecheck errors now point at the migration sites.
|
||||||
|
4. Commit (e.g. `chore(deps): require pi 0.80.8+ and correct dep ranges (issue #62)`).
|
||||||
|
5. Update this `status.md` + append `log.md`, then hand off to leg 2 (charter
|
||||||
|
slice 1: `authService.ts` core migration).
|
||||||
|
|
||||||
|
If slice 0 is already done when you arrive, apply the charter's task-selection
|
||||||
|
policy: pick the lowest-numbered incomplete slice (1 → 6).
|
||||||
|
|
||||||
|
## Relevant context for the next runner
|
||||||
|
- **Plan of record:** `ASSESSMENT-issue-62.md` (root) — read once. §5 has the
|
||||||
|
per-file migration shape; §3 has the exact new API shapes; §6 the dep ranges.
|
||||||
|
- **Files to change** (all under `src/server/sessions/` unless noted):
|
||||||
|
`authService.ts`, `authProviderOptions.ts`, `oauthLoginFlowService.ts`,
|
||||||
|
`piSessionService.ts`, plus `src/server/sessiond.ts` (async auth
|
||||||
|
construction), and the test/support files listed in assessment §2.
|
||||||
|
- **New API cheat-sheet:** `ModelRuntime.create({ authPath, modelsPath,
|
||||||
|
credentials? }): Promise<ModelRuntime>`; credential persistence via the
|
||||||
|
pi-ai `CredentialStore.modify` path; `runtime.login(providerId, type,
|
||||||
|
AuthInteraction)`; `runtime.logout`; `runtime.getProviders()` /
|
||||||
|
`listCredentials()` / `getProviderAuthStatus()`; `readStoredCredential(
|
||||||
|
providerId, authPath?)` for the sync anthropic warning; pi-ai
|
||||||
|
`InMemoryCredentialStore` for tests.
|
||||||
|
- **Decision already made:** clean migration, **no dual-version compat shim**
|
||||||
|
(assessment §4/§5). Do not reopen this without the intervention signal.
|
||||||
|
|
||||||
|
## Progress documentation expectations
|
||||||
|
Every leg: update this `status.md` (current position, leg tracking, next task,
|
||||||
|
context, blockers), append a concise `log.md` entry, make work durable, and
|
||||||
|
commit before handing off. Hand off with `spawn_session` **once** per the
|
||||||
|
charter's Handover section.
|
||||||
|
|
||||||
|
## Blockers / intervention state
|
||||||
|
None currently. Known constraints:
|
||||||
|
- **Sessiond restart pending** once slices touching `sessiond.ts` / session
|
||||||
|
runtime land — the human must manually restart the sessiond service; note it
|
||||||
|
here when it applies.
|
||||||
|
- `/tmp` disk-quota issue observed during assessment — do dependency installs in
|
||||||
|
the worktree.
|
||||||
Reference in New Issue
Block a user