From 01b2bf75d10e5edeb228e015bbe72a472d482ddb Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 9 May 2026 04:12:54 +0100 Subject: [PATCH] refactor: remove unused pi auth json bridge --- docs/pi.md | 1 - src/agents/pi-auth-json.test.ts | 254 -------------------------------- src/agents/pi-auth-json.ts | 83 ----------- 3 files changed, 338 deletions(-) delete mode 100644 src/agents/pi-auth-json.test.ts delete mode 100644 src/agents/pi-auth-json.ts diff --git a/docs/pi.md b/docs/pi.md index 75f5225b477..12a72e898c7 100644 --- a/docs/pi.md +++ b/docs/pi.md @@ -542,7 +542,6 @@ Areas for potential rework: Pi integration coverage spans these suites: - `src/agents/pi-*.test.ts` -- `src/agents/pi-auth-json.test.ts` - `src/agents/pi-embedded-*.test.ts` - `src/agents/pi-embedded-helpers*.test.ts` - `src/agents/pi-embedded-runner*.test.ts` diff --git a/src/agents/pi-auth-json.test.ts b/src/agents/pi-auth-json.test.ts deleted file mode 100644 index 1dfa700ea8d..00000000000 --- a/src/agents/pi-auth-json.test.ts +++ /dev/null @@ -1,254 +0,0 @@ -import fs from "node:fs/promises"; -import os from "node:os"; -import path from "node:path"; -import { describe, expect, it, vi } from "vitest"; -import { saveAuthProfileStore } from "./auth-profiles/store.js"; -import { ensurePiAuthJsonFromAuthProfiles } from "./pi-auth-json.js"; - -vi.mock("./auth-profiles/external-auth.js", () => ({ - overlayExternalAuthProfiles: (store: T) => store, - shouldPersistExternalAuthProfile: () => true, -})); - -type AuthProfileStore = Parameters[0]; - -async function createAgentDir() { - return fs.mkdtemp(path.join(os.tmpdir(), "openclaw-agent-")); -} - -function writeProfiles(agentDir: string, profiles: AuthProfileStore["profiles"]) { - saveAuthProfileStore( - { - version: 1, - profiles, - }, - agentDir, - ); -} - -async function readAuthJson(agentDir: string) { - const authPath = path.join(agentDir, "auth.json"); - return JSON.parse(await fs.readFile(authPath, "utf8")) as Record; -} - -function requireAuthEntry( - auth: Record, - provider: string, -): Record { - const entry = auth[provider]; - if (!entry || typeof entry !== "object") { - throw new Error(`expected auth entry ${provider}`); - } - return entry as Record; -} - -function expectApiKeyAuth(auth: Record, provider: string, key: string): void { - const entry = requireAuthEntry(auth, provider); - expect(entry.type).toBe("api_key"); - expect(entry.key).toBe(key); -} - -function expectOAuthAuth( - auth: Record, - provider: string, - access: string, - refresh?: string, -): void { - const entry = requireAuthEntry(auth, provider); - expect(entry.type).toBe("oauth"); - expect(entry.access).toBe(access); - if (refresh !== undefined) { - expect(entry.refresh).toBe(refresh); - } -} - -describe("ensurePiAuthJsonFromAuthProfiles", () => { - it("writes openai-codex oauth credentials into auth.json for pi-coding-agent discovery", async () => { - const agentDir = await createAgentDir(); - - writeProfiles(agentDir, { - "openai-codex:default": { - type: "oauth", - provider: "openai-codex", - access: "access-token", - refresh: "refresh-token", - expires: Date.now() + 60_000, - }, - }); - - const first = await ensurePiAuthJsonFromAuthProfiles(agentDir); - expect(first.wrote).toBe(true); - - const auth = await readAuthJson(agentDir); - expectOAuthAuth(auth, "openai-codex", "access-token", "refresh-token"); - - const second = await ensurePiAuthJsonFromAuthProfiles(agentDir); - expect(second.wrote).toBe(false); - }); - - it("writes api_key credentials into auth.json", async () => { - const agentDir = await createAgentDir(); - - writeProfiles(agentDir, { - "openrouter:default": { - type: "api_key", - provider: "openrouter", - key: "sk-or-v1-test-key", - }, - }); - - const result = await ensurePiAuthJsonFromAuthProfiles(agentDir); - expect(result.wrote).toBe(true); - - const auth = await readAuthJson(agentDir); - expectApiKeyAuth(auth, "openrouter", "sk-or-v1-test-key"); - }); - - it("writes token credentials as api_key into auth.json", async () => { - const agentDir = await createAgentDir(); - - writeProfiles(agentDir, { - "anthropic:default": { - type: "token", - provider: "anthropic", - token: "sk-ant-test-token", - }, - }); - - const result = await ensurePiAuthJsonFromAuthProfiles(agentDir); - expect(result.wrote).toBe(true); - - const auth = await readAuthJson(agentDir); - expectApiKeyAuth(auth, "anthropic", "sk-ant-test-token"); - }); - - it("syncs multiple providers at once", async () => { - const agentDir = await createAgentDir(); - - writeProfiles(agentDir, { - "openrouter:default": { - type: "api_key", - provider: "openrouter", - key: "sk-or-key", - }, - "anthropic:default": { - type: "token", - provider: "anthropic", - token: "sk-ant-token", - }, - "openai-codex:default": { - type: "oauth", - provider: "openai-codex", - access: "access", - refresh: "refresh", - expires: Date.now() + 60_000, - }, - }); - - const result = await ensurePiAuthJsonFromAuthProfiles(agentDir); - expect(result.wrote).toBe(true); - - const auth = await readAuthJson(agentDir); - - expectApiKeyAuth(auth, "openrouter", "sk-or-key"); - expectApiKeyAuth(auth, "anthropic", "sk-ant-token"); - expectOAuthAuth(auth, "openai-codex", "access"); - }); - - it("skips profiles with empty keys", async () => { - const agentDir = await createAgentDir(); - - writeProfiles(agentDir, { - "openrouter:default": { - type: "api_key", - provider: "openrouter", - key: "", - }, - }); - - const result = await ensurePiAuthJsonFromAuthProfiles(agentDir); - expect(result.wrote).toBe(false); - }); - - it("skips expired token credentials", async () => { - const agentDir = await createAgentDir(); - - writeProfiles(agentDir, { - "anthropic:default": { - type: "token", - provider: "anthropic", - token: "sk-ant-expired", - expires: Date.now() - 60_000, - }, - }); - - const result = await ensurePiAuthJsonFromAuthProfiles(agentDir); - expect(result.wrote).toBe(false); - }); - - it("normalizes provider ids when writing auth.json keys", async () => { - const agentDir = await createAgentDir(); - - writeProfiles(agentDir, { - "z.ai:default": { - type: "api_key", - provider: "z.ai", - key: "sk-zai", - }, - }); - - const result = await ensurePiAuthJsonFromAuthProfiles(agentDir); - expect(result.wrote).toBe(true); - - const auth = await readAuthJson(agentDir); - expectApiKeyAuth(auth, "zai", "sk-zai"); - expect(auth["z.ai"]).toBeUndefined(); - }); - - it("preserves existing auth.json entries not in auth-profiles", async () => { - const agentDir = await createAgentDir(); - const authPath = path.join(agentDir, "auth.json"); - - await fs.mkdir(agentDir, { recursive: true }); - await fs.writeFile( - authPath, - JSON.stringify({ "legacy-provider": { type: "api_key", key: "legacy-key" } }), - ); - - writeProfiles(agentDir, { - "openrouter:default": { - type: "api_key", - provider: "openrouter", - key: "new-key", - }, - }); - - await ensurePiAuthJsonFromAuthProfiles(agentDir); - - const auth = await readAuthJson(agentDir); - expectApiKeyAuth(auth, "legacy-provider", "legacy-key"); - expectApiKeyAuth(auth, "openrouter", "new-key"); - }); - - it("treats malformed existing provider entries as stale and replaces them", async () => { - const agentDir = await createAgentDir(); - const authPath = path.join(agentDir, "auth.json"); - - await fs.mkdir(agentDir, { recursive: true }); - await fs.writeFile(authPath, JSON.stringify({ openrouter: { type: "api_key", key: 123 } })); - - writeProfiles(agentDir, { - "openrouter:default": { - type: "api_key", - provider: "openrouter", - key: "new-key", - }, - }); - - const result = await ensurePiAuthJsonFromAuthProfiles(agentDir); - expect(result.wrote).toBe(true); - - const auth = await readAuthJson(agentDir); - expectApiKeyAuth(auth, "openrouter", "new-key"); - }); -}); diff --git a/src/agents/pi-auth-json.ts b/src/agents/pi-auth-json.ts deleted file mode 100644 index 16f9a1fb082..00000000000 --- a/src/agents/pi-auth-json.ts +++ /dev/null @@ -1,83 +0,0 @@ -import path from "node:path"; -import { z } from "zod"; -import { privateFileStore } from "../infra/private-file-store.js"; -import { safeParseWithSchema } from "../utils/zod-parse.js"; -import { ensureAuthProfileStore } from "./auth-profiles/store.js"; -import { - piCredentialsEqual, - resolvePiCredentialMapFromStore, - type PiCredential, -} from "./pi-auth-credentials.js"; - -type AuthJsonShape = Record; - -const PiCredentialSchema: z.ZodType = z.discriminatedUnion("type", [ - z.object({ - type: z.literal("api_key"), - key: z.string(), - }), - z.object({ - type: z.literal("oauth"), - access: z.string(), - refresh: z.string(), - expires: z.number(), - }), -]); - -const AuthJsonShapeSchema = z.record(z.string(), z.unknown()); - -async function readAuthJson(rootDir: string, filePath: string): Promise { - try { - const parsed = await privateFileStore(rootDir).readJsonIfExists( - path.relative(rootDir, filePath), - ); - return safeParseWithSchema(AuthJsonShapeSchema, parsed) ?? {}; - } catch { - return {}; - } -} - -/** - * pi-coding-agent's ModelRegistry/AuthStorage expects credentials in auth.json. - * - * OpenClaw stores credentials in auth-profiles.json instead. This helper - * bridges all credentials into agentDir/auth.json so pi-coding-agent can - * (a) consider providers authenticated and (b) include built-in models in its - * registry/catalog output. - * - * Syncs all credential types: api_key, token (as api_key), and oauth. - * - * @deprecated Runtime auth now comes from OpenClaw auth-profiles snapshots. - */ -export async function ensurePiAuthJsonFromAuthProfiles(agentDir: string): Promise<{ - wrote: boolean; - authPath: string; -}> { - const store = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false }); - const authPath = path.join(agentDir, "auth.json"); - const providerCredentials = resolvePiCredentialMapFromStore(store); - if (Object.keys(providerCredentials).length === 0) { - return { wrote: false, authPath }; - } - - const existing = await readAuthJson(agentDir, authPath); - let changed = false; - - for (const [provider, cred] of Object.entries(providerCredentials)) { - const current = safeParseWithSchema(PiCredentialSchema, existing[provider]) ?? undefined; - if (!piCredentialsEqual(current, cred)) { - existing[provider] = cred; - changed = true; - } - } - - if (!changed) { - return { wrote: false, authPath }; - } - - await privateFileStore(agentDir).writeJson(path.basename(authPath), existing, { - trailingNewline: true, - }); - - return { wrote: true, authPath }; -}