Archived
relay issue-62-authstorage: leg 2 status/log (slice 1 done)
This commit is contained in:
@@ -87,3 +87,85 @@ onward once `sessiond.ts` changes land).
|
||||
|
||||
**Handoff:** spawning leg 2 (slice 1).
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Leg 2 — slice 1: `authService.ts` core migration (commit `e37148c`)
|
||||
|
||||
**What I did:** migrated `src/server/sessions/authService.ts` off the removed
|
||||
`AuthStorage` / `ModelRegistry.create` surface onto the async `ModelRuntime`
|
||||
API, and propagated the async construction into the session daemon.
|
||||
|
||||
- `authService.ts`:
|
||||
- Imports `ModelRuntime` from `@earendil-works/pi-coding-agent` and
|
||||
`AuthInteraction` (type) from `@earendil-works/pi-ai`. Dropped
|
||||
`AuthStorage` / `ModelRegistry`.
|
||||
- `createModelRegistryForAgentDir` → `createModelRuntimeForAgentDir(agentDir)`
|
||||
returning `ModelRuntime.create({ authPath: <dir>/auth.json, modelsPath:
|
||||
<dir>/models.json })`.
|
||||
- Construction is now async: private constructor + static
|
||||
`AuthService.create({ agentDir? | runtime? | authFlows? })`. `runtime` dep
|
||||
replaces the old `modelRegistry` dep; no-agentDir fallback is
|
||||
`ModelRuntime.create({})`.
|
||||
- Public field `readonly runtime: ModelRuntime` replaces `modelRegistry`.
|
||||
- `saveApiKey` → `runtime.login(providerId, "api_key", interaction)` where
|
||||
`interaction` is a non-interactive `AuthInteraction` (`prompt: async () =>
|
||||
key`, `notify: () => {}`). Verified against pi-ai `envApiKeyAuth().login`,
|
||||
which calls `interaction.prompt({ type: "secret" })` and persists the
|
||||
returned `{ type:"api_key", key }` through `credentials.modify` inside
|
||||
`Models.login`. This is the credential-persistence path the assessment
|
||||
(§5.1) called for.
|
||||
- `logoutProvider` → `await runtime.logout(providerId)`.
|
||||
- `refreshAuthState` → `await runtime.refresh()` (no more `authStorage.reload()`
|
||||
— the file store is re-read by the runtime). Now async.
|
||||
- `authProviders` and `requireOAuthLoginProvider` became async, awaiting
|
||||
`runtime.refresh()` and the now-async `getLogin/LogoutProviderOptions`.
|
||||
- `startOAuthLogin` passes `runtime: this.runtime` into
|
||||
`OAuthLoginFlowService.start` (slice 3 will consume it via `runtime.login`).
|
||||
- `sessiond.ts`: `createRuntime()` is now `async`; `new AuthService(...)` →
|
||||
`await AuthService.create({ agentDir })`; `PiSessionService` now receives
|
||||
`modelRuntime: auth.runtime` instead of `modelRegistry: auth.modelRegistry`.
|
||||
- `sessiond/sessionDaemonStartup.ts`: `createRuntime` may now return
|
||||
`Runtime | Promise<Runtime>` and `runSessionDaemonStartup` `await`s it. The
|
||||
existing sync test doubles still satisfy the widened type.
|
||||
|
||||
**Decisions:**
|
||||
- **saveApiKey via `runtime.login("api_key", …)`** rather than reaching for a
|
||||
raw `CredentialStore.modify`: the pi-ai `CredentialStore` is not exposed off
|
||||
`ModelRuntime` publicly, and the provider's own api-key `login` is the
|
||||
intended persistence entry point (it writes through `credentials.modify`).
|
||||
Feeding the key back through a non-interactive `AuthInteraction.prompt` keeps
|
||||
us on the supported public surface. This matches assessment §5.1's
|
||||
"credential persistence via the pi-ai CredentialStore.modify path" without
|
||||
depending on unexported internals.
|
||||
- Kept `AuthService` construction async via a static factory (private ctor)
|
||||
rather than an `init()` method — cleaner async boundary, single valid
|
||||
construction path (code-quality-architecture skill).
|
||||
- Did NOT touch `authProviderOptions.ts`, `oauthLoginFlowService.ts`,
|
||||
`piSessionService.ts`, or any test/support files — strictly slice 1 scope.
|
||||
The async call sites I introduced (`await getLoginProviderOptions(...)`,
|
||||
`runtime:` in `authFlows.start`, `modelRuntime:` in PiSessionService deps)
|
||||
deliberately point at the interfaces slices 2–4 will expose.
|
||||
|
||||
**Typecheck state:** `npx tsc --noEmit` = 31 errors (was 24 at slice 0). The
|
||||
increase is expected and honest: the migrated authService now calls
|
||||
runtime-based interfaces that slices 2/3/4 have not migrated yet. All remaining
|
||||
`authService.ts` / `sessiond.ts` errors are cross-slice (authProviderOptions
|
||||
shape → slice 2; OAuthLoginFlowService.start `runtime` param → slice 3;
|
||||
`PiSessionServiceDependencies.modelRuntime` → slice 4). Test/support files
|
||||
(slice 5) still import the removed `AuthStorage`.
|
||||
|
||||
**Artifacts changed:** `src/server/sessions/authService.ts`,
|
||||
`src/server/sessiond.ts`, `src/server/sessiond/sessionDaemonStartup.ts`
|
||||
(commit `e37148c`); `relays/issue-62-authstorage/{status,log}.md`.
|
||||
|
||||
**Status update:** last completed leg 2, next leg 3 = charter slice 2
|
||||
(`authProviderOptions.ts` migration).
|
||||
|
||||
**Blockers:** none. **Sessiond restart now ACTIVE-pending** — slice 1 changed
|
||||
`sessiond.ts` and the daemon auth construction path; the human must manually
|
||||
restart the sessiond service once the migration lands (noted in status.md).
|
||||
Also: human confirmed `/tmp` is usable again, so the `TMPDIR` install
|
||||
workaround is no longer required (status.md updated).
|
||||
|
||||
**Handoff:** spawning leg 3 (slice 2).
|
||||
|
||||
@@ -1,44 +1,69 @@
|
||||
# Relay status — issue-62-authstorage
|
||||
|
||||
## Current position
|
||||
Bootstrap (slice 0) complete and committed (`0fa9d0e`). Deps are installed in the
|
||||
worktree at **0.80.10** (all three `@earendil-works/*`), `package.json` ranges
|
||||
corrected, and the new export surface is confirmed resolvable
|
||||
(`ModelRuntime`, `readStoredCredential` present; `AuthStorage` gone; pi-ai
|
||||
`InMemoryCredentialStore` present). `npx tsc --noEmit` now reports **24 errors**,
|
||||
all in `src/server/sessions/` at the expected migration sites (no crash — the
|
||||
removed `AuthStorage` import and `ModelRegistry.create/inMemory` calls). The
|
||||
migration itself has not started.
|
||||
Slice 1 (`authService.ts` core migration) complete and committed (`e37148c`).
|
||||
`authService.ts` now uses the async `ModelRuntime` API: `AuthService.create({
|
||||
agentDir | runtime })` factory wraps `ModelRuntime.create({ authPath,
|
||||
modelsPath })`; `createModelRuntimeForAgentDir` replaces
|
||||
`createModelRegistryForAgentDir`. `saveApiKey` → `runtime.login(id, "api_key",
|
||||
nonInteractive)`, `logoutProvider` → `runtime.logout`, `refreshAuthState` →
|
||||
`await runtime.refresh()`. `authProviders` / `requireOAuthLoginProvider` are now
|
||||
async. `startOAuthLogin` passes `runtime` into `OAuthLoginFlowService.start`.
|
||||
`sessiond.ts` uses async `createRuntime`, `AuthService.create`, and passes
|
||||
`modelRuntime: auth.runtime` to `PiSessionService`; `sessionDaemonStartup` now
|
||||
awaits `createRuntime`.
|
||||
|
||||
`npx tsc --noEmit` reports **31 errors** (up from 24 — expected: the migrated
|
||||
authService now calls the runtime-based interfaces that slices 2–4 haven't
|
||||
exposed yet). Slice-1 files are internally consistent; every remaining error
|
||||
in `authService.ts` / `sessiond.ts` is a **cross-slice** dependency:
|
||||
- `authService.ts`: `getLoginProviderOptions/getLogoutProviderOptions` still
|
||||
take the old `AuthProviderModelRegistry` shape (fixed in slice 2);
|
||||
`OAuthLoginFlowService.start` still expects `authStorage` not `runtime`
|
||||
(fixed in slice 3).
|
||||
- `sessiond.ts`: `PiSessionServiceDependencies` still expects `modelRegistry`
|
||||
not `modelRuntime` (fixed in slice 4).
|
||||
Remaining errors otherwise live in slices 2/3/4 files and all test/support
|
||||
files (slice 5).
|
||||
|
||||
## Leg tracking
|
||||
- **Last completed leg:** 1 (slice 0 Bootstrap — deps + range correction).
|
||||
- **Next leg to run:** 2.
|
||||
- **Last completed leg:** 2 (slice 1 — authService.ts core migration + sessiond
|
||||
async construction).
|
||||
- **Next leg to run:** 3.
|
||||
|
||||
## Next task
|
||||
Run **charter slice 1 (`authService.ts` core migration)** as leg 2:
|
||||
- Move `authService.ts` to `ModelRuntime` (async construction via
|
||||
`ModelRuntime.create({ authPath, modelsPath })`), migrate
|
||||
`saveApiKey` / `logoutProvider` / `refreshAuthState` / credential access off
|
||||
the removed `authStorage`/`ModelRegistry.create` surface (see assessment §5.1
|
||||
for the concrete mapping).
|
||||
- Propagate the now-async construction to `src/server/sessiond.ts`.
|
||||
- **Sessiond path:** this slice touches session-daemon code → note in
|
||||
status/handoff that a manual sessiond restart will be needed once landed.
|
||||
- Slice 1 depends only on slice 0 (done). The tree will still not fully
|
||||
typecheck after this leg (slices 2–4 remain); that is expected — leave an
|
||||
honest status.
|
||||
Run **charter slice 2 (`authProviderOptions.ts` migration)** as leg 3:
|
||||
- Rederive login/logout provider options from `runtime.getProviders()`
|
||||
(`{ id, name, auth: { apiKey?, oauth? } }`) + `runtime.listCredentials()`
|
||||
(`{ providerId, type }[]`) / `runtime.getProviderAuthStatus(id)` instead of
|
||||
`authStorage.getOAuthProviders()/list()/get()` + `getAll()` +
|
||||
`getProviderDisplayName()`.
|
||||
- The functions are already **called as async** from `authService.ts`
|
||||
(`await getLoginProviderOptions(this.runtime, authType)` etc.) — make them
|
||||
async and change their parameter type from `AuthProviderModelRegistry` to a
|
||||
runtime-shaped interface (e.g. `AuthProviderRuntime` = `Pick<ModelRuntime,
|
||||
"getProviders" | "listCredentials" | "getProviderAuthStatus">` or a
|
||||
structural equivalent). Update the structural interface + `authProviderOptions.test.ts`
|
||||
test double accordingly.
|
||||
- See assessment §5.2 / §3.3 for the new API shapes. Provider display names come
|
||||
from `Provider.name`; OAuth-capable providers are those with `auth.oauth`,
|
||||
api-key providers those with `auth.apiKey` (respect the existing
|
||||
`OAUTH_ONLY_PROVIDERS` / `isApiKeyLoginProvider` logic).
|
||||
|
||||
If slice 1 is already done when you arrive, apply the charter's task-selection
|
||||
policy: pick the lowest-numbered incomplete slice (2 → 6).
|
||||
If slice 2 is already done when you arrive, apply the charter's task-selection
|
||||
policy: pick the lowest-numbered incomplete slice (3 → 6). Slices 3 and 4
|
||||
unblock the remaining `authService.ts` / `sessiond.ts` cross-slice errors.
|
||||
|
||||
### Build/tooling note (important for every leg)
|
||||
Installs and any native rebuild must set `TMPDIR` to a path inside the worktree,
|
||||
e.g. `TMPDIR="$PWD/.tmp-build" npm install` (remove the dir after). `/tmp` is a
|
||||
5.8G tmpfs at ~81% and node-gyp's `node-pty` build fails there with "Disk quota
|
||||
exceeded". `.tmp-build` is scratch — do not commit it. The pre-commit hook runs
|
||||
a whole-project typecheck; while the migration is incomplete, commit relay work
|
||||
with `git commit --no-verify` (the charter permits legs that aren't verify-green).
|
||||
Node: v24.18.0.
|
||||
**Update (leg 2):** the human reports `/tmp` is now fully usable again, so the
|
||||
previous `TMPDIR` workaround is no longer required — plain `npm install` should
|
||||
work. (If a disk-quota error resurfaces, fall back to
|
||||
`TMPDIR="$PWD/.tmp-build" npm install` and remove `.tmp-build` after; it is
|
||||
scratch, do not commit it.) node_modules is already installed at 0.80.10, so a
|
||||
fresh install is only needed if node_modules is cleared. The pre-commit hook
|
||||
runs a whole-project typecheck; while the migration is incomplete, commit relay
|
||||
work with `git commit --no-verify` (the charter permits legs that aren't
|
||||
verify-green). Node: v24.18.0.
|
||||
|
||||
## Relevant context for the next runner
|
||||
- **Plan of record:** `ASSESSMENT-issue-62.md` (root) — read once. §5 has the
|
||||
@@ -65,10 +90,12 @@ charter's Handover section.
|
||||
|
||||
## Blockers / intervention state
|
||||
None. Known constraints:
|
||||
- **Sessiond restart pending** once slices touching `sessiond.ts` / session
|
||||
runtime land (starts with slice 1/leg 2) — the human must manually restart the
|
||||
sessiond service; keep this note current when it applies.
|
||||
- `/tmp` disk-quota issue is real — see the Build/tooling note above; always set
|
||||
`TMPDIR` into the worktree for installs/native rebuilds.
|
||||
- **Sessiond restart pending (ACTIVE):** slice 1 (leg 2, commit `e37148c`)
|
||||
changed `sessiond.ts` + the session-daemon auth construction path. Per
|
||||
AGENTS.md the human must **manually restart the sessiond service** for these
|
||||
changes to take effect once the migration lands. Keep this note until the
|
||||
human confirms the restart.
|
||||
- `/tmp` disk-quota issue is resolved (human confirmed usable) — see the
|
||||
Build/tooling note above.
|
||||
- node_modules is installed (gitignored) at 0.80.10; a fresh `npm install` is
|
||||
only needed if node_modules is cleared.
|
||||
|
||||
Reference in New Issue
Block a user