diff --git a/packages/coding-agent/src/extensibility/legacy-pi-coding-agent-shim.ts b/packages/coding-agent/src/extensibility/legacy-pi-coding-agent-shim.ts index 1c67ea249..95c33a80c 100644 --- a/packages/coding-agent/src/extensibility/legacy-pi-coding-agent-shim.ts +++ b/packages/coding-agent/src/extensibility/legacy-pi-coding-agent-shim.ts @@ -13,7 +13,7 @@ */ import { Database } from "bun:sqlite"; -import * as fs from "node:fs/promises"; +import * as fs from "node:fs"; import * as path from "node:path"; import type { AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core"; import { type AuthCredential, SqliteAuthCredentialStore, type TSchema } from "@oh-my-pi/pi-ai"; @@ -612,16 +612,16 @@ export function createLsToolDefinition(cwd: string, options?: LsToolOptions): To const ops = options?.operations; const exists = ops ? await ops.exists(absolutePath) - : await fs.stat(absolutePath).then( + : await fs.promises.stat(absolutePath).then( () => true, () => false, ); if (!exists) throw new Error(`Path not found: ${absolutePath}`); - const stat = ops ? await ops.stat(absolutePath) : await fs.stat(absolutePath); + const stat = ops ? await ops.stat(absolutePath) : await fs.promises.stat(absolutePath); if (!stat.isDirectory()) { return { content: [{ type: "text", text: rawPath }] }; } - const entries = ops ? await ops.readdir(absolutePath) : await fs.readdir(absolutePath); + const entries = ops ? await ops.readdir(absolutePath) : await fs.promises.readdir(absolutePath); const sorted = [...entries].sort((a, b) => a.localeCompare(b)); const limited = sorted.slice(0, limit); const output = limited.join("\n"); @@ -1106,7 +1106,7 @@ export class DefaultResourceLoader implements ResourceLoader { : path.resolve(this.#state.cwd, resourcePath); const files: string[] = []; try { - const stat = await fs.stat(resolvedPath); + const stat = await fs.promises.stat(resolvedPath); if (stat.isDirectory()) { const glob = new Bun.Glob("**/*.md"); for await (const entry of glob.scan({ cwd: resolvedPath, absolute: false, onlyFiles: true })) { @@ -1301,6 +1301,10 @@ export async function createAgentSession( * call `AuthStorage.create().get()` during module initialization. */ export class AuthStorage { + constructor() { + fs.mkdirSync(path.dirname(getAgentDbPath()), { recursive: true, mode: 0o700 }); + } + static create(): AuthStorage { return new AuthStorage(); } diff --git a/packages/coding-agent/test/issue-5879-legacy-event-stream-factory.test.ts b/packages/coding-agent/test/issue-5879-legacy-event-stream-factory.test.ts index 12cb8f2fe..7880099bb 100644 --- a/packages/coding-agent/test/issue-5879-legacy-event-stream-factory.test.ts +++ b/packages/coding-agent/test/issue-5879-legacy-event-stream-factory.test.ts @@ -1,11 +1,17 @@ import { describe, expect, it } from "bun:test"; import * as path from "node:path"; import { loadExtensions } from "@oh-my-pi/pi-coding-agent/extensibility/extensions/loader"; -import { TempDir } from "@oh-my-pi/pi-utils"; +import { __resetDirsFromEnvForTests, setAgentDir, TempDir } from "@oh-my-pi/pi-utils"; describe("issue #5879: legacy provider compatibility", () => { - it("loads an extension that calls historical stream and auth exports", async () => { + it("creates a fresh agent database while loading historical auth exports", async () => { const projectDir = TempDir.createSync("@issue-5879-"); + const freshAgentDir = projectDir.join("fresh", "agent"); + const originalDirEnv: Record = { + PI_CODING_AGENT_DIR: process.env.PI_CODING_AGENT_DIR, + OMP_PROFILE: process.env.OMP_PROFILE, + PI_PROFILE: process.env.PI_PROFILE, + }; const extensionPath = path.join(projectDir.path(), "pi-provider-like-plugin", "index.ts"); await Bun.write( extensionPath, @@ -22,12 +28,21 @@ describe("issue #5879: legacy provider compatibility", () => { ].join("\n"), ); + setAgentDir(freshAgentDir); + try { const result = await loadExtensions([extensionPath], projectDir.path()); expect(result.errors).toEqual([]); expect(result.extensions).toHaveLength(1); + expect(await Bun.file(path.join(freshAgentDir, "agent.db")).exists()).toBe(true); } finally { + for (const key in originalDirEnv) { + const value = originalDirEnv[key]; + if (value === undefined) delete process.env[key]; + else process.env[key] = value; + } + __resetDirsFromEnvForTests(); projectDir.removeSync(); } });