import { InMemoryModelsStore, type Model } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { AuthStorage } from "../src/core/auth-storage.ts"; import { ModelRuntime } from "../src/core/model-runtime.ts"; function model(id: string): Model<"openai-completions"> { return { id, name: id, api: "openai-completions", provider: "extension-oauth", baseUrl: "https://example.test/v1", reasoning: false, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1000, maxTokens: 100, }; } describe("extension provider model lifecycle", () => { it("publishes refreshModels results without forcing ModelsStore persistence", async () => { const modelsStore = new InMemoryModelsStore(); const runtime = await ModelRuntime.create({ credentials: AuthStorage.inMemory(), modelsStore, modelsPath: null, allowModelNetwork: false, }); runtime.registerProvider("extension-dynamic", { baseUrl: "http://localhost:8080/v1", apiKey: "local", api: "openai-completions", refreshModels: async () => [ { ...model("live"), provider: "extension-dynamic", baseUrl: "http://localhost:8080/v1", }, ], }); await runtime.refresh({ allowNetwork: false }); expect(runtime.getModel("extension-dynamic", "live")).toBeDefined(); expect(await modelsStore.read("extension-dynamic")).toBeUndefined(); }); it("applies legacy OAuth modifyModels after async credential initialization", async () => { const runtime = await ModelRuntime.create({ credentials: AuthStorage.inMemory({ "extension-oauth": { type: "oauth", access: "access", refresh: "refresh", expires: Date.now() + 60_000, }, }), modelsStore: new InMemoryModelsStore(), modelsPath: null, allowModelNetwork: false, }); runtime.registerProvider("extension-oauth", { baseUrl: "https://example.test/v1", api: "openai-completions", models: [model("base")], oauth: { name: "Extension OAuth", login: async () => { throw new Error("not used"); }, refreshToken: async (credential) => credential, getApiKey: (credential) => credential.access, modifyModels: (models, credential) => credential.access === "access" ? [...models, model("credential-model")] : models, }, }); await runtime.refresh({ allowNetwork: false }); expect(runtime.getModel("extension-oauth", "base")).toBeDefined(); expect(runtime.getModel("extension-oauth", "credential-model")).toBeDefined(); await runtime.logout("extension-oauth"); expect(runtime.getModel("extension-oauth", "credential-model")).toBeUndefined(); }); });