feat(coding-agent): replace model registry with model runtime

Move provider auth and OAuth flows onto pi-ai Models, compose models.json and extension overlays through ModelRuntime, and retain ModelRegistry as an extension compatibility facade.
This commit is contained in:
Mario Zechner
2026-07-14 17:48:45 +02:00
parent 6731a0ba9e
commit 9993c96907
133 changed files with 5103 additions and 4340 deletions
@@ -7,19 +7,20 @@ function createSettingsManager(warnings: { anthropicExtraUsage?: boolean } = {})
};
}
function createModelRuntime(credential: { type: "oauth" } | undefined, apiKey?: string) {
return {
checkAuth: vi.fn().mockResolvedValue(credential),
getAuth: vi.fn().mockResolvedValue(apiKey ? { auth: { apiKey } } : undefined),
};
}
describe("InteractiveMode.maybeWarnAboutAnthropicSubscriptionAuth", () => {
test("warns once when Anthropic subscription auth is detected", async () => {
const modelRuntime = createModelRuntime(undefined, "sk-ant-oat01-test");
const fakeThis: any = {
anthropicSubscriptionWarningShown: false,
settingsManager: createSettingsManager(),
session: {
modelRegistry: {
authStorage: {
get: vi.fn().mockReturnValue(undefined),
},
getApiKeyForProvider: vi.fn().mockResolvedValue("sk-ant-oat01-test"),
},
},
session: { modelRuntime },
showWarning: vi.fn(),
};
@@ -31,21 +32,15 @@ describe("InteractiveMode.maybeWarnAboutAnthropicSubscriptionAuth", () => {
});
expect(fakeThis.showWarning).toHaveBeenCalledTimes(1);
expect(fakeThis.session.modelRegistry.getApiKeyForProvider).toHaveBeenCalledTimes(1);
expect(modelRuntime.getAuth).toHaveBeenCalledTimes(1);
});
test("warns when Anthropic OAuth is stored even if token refresh lookup would fail", async () => {
const modelRuntime = createModelRuntime({ type: "oauth" });
const fakeThis: any = {
anthropicSubscriptionWarningShown: false,
settingsManager: createSettingsManager(),
session: {
modelRegistry: {
authStorage: {
get: vi.fn().mockReturnValue({ type: "oauth" }),
},
getApiKeyForProvider: vi.fn().mockResolvedValue(undefined),
},
},
session: { modelRuntime },
showWarning: vi.fn(),
};
@@ -54,21 +49,15 @@ describe("InteractiveMode.maybeWarnAboutAnthropicSubscriptionAuth", () => {
});
expect(fakeThis.showWarning).toHaveBeenCalledTimes(1);
expect(fakeThis.session.modelRegistry.getApiKeyForProvider).not.toHaveBeenCalled();
expect(modelRuntime.getAuth).not.toHaveBeenCalled();
});
test("does not warn for non-Anthropic models", async () => {
const modelRuntime = createModelRuntime(undefined);
const fakeThis: any = {
anthropicSubscriptionWarningShown: false,
settingsManager: createSettingsManager(),
session: {
modelRegistry: {
authStorage: {
get: vi.fn(),
},
getApiKeyForProvider: vi.fn(),
},
},
session: { modelRuntime },
showWarning: vi.fn(),
};
@@ -77,21 +66,15 @@ describe("InteractiveMode.maybeWarnAboutAnthropicSubscriptionAuth", () => {
});
expect(fakeThis.showWarning).not.toHaveBeenCalled();
expect(fakeThis.session.modelRegistry.getApiKeyForProvider).not.toHaveBeenCalled();
expect(modelRuntime.getAuth).not.toHaveBeenCalled();
});
test("does not warn when Anthropic extra usage warning is disabled", async () => {
const modelRuntime = createModelRuntime(undefined);
const fakeThis: any = {
anthropicSubscriptionWarningShown: false,
settingsManager: createSettingsManager({ anthropicExtraUsage: false }),
session: {
modelRegistry: {
authStorage: {
get: vi.fn(),
},
getApiKeyForProvider: vi.fn(),
},
},
session: { modelRuntime },
showWarning: vi.fn(),
};
@@ -100,7 +83,7 @@ describe("InteractiveMode.maybeWarnAboutAnthropicSubscriptionAuth", () => {
});
expect(fakeThis.showWarning).not.toHaveBeenCalled();
expect(fakeThis.session.modelRegistry.authStorage.get).not.toHaveBeenCalled();
expect(fakeThis.session.modelRegistry.getApiKeyForProvider).not.toHaveBeenCalled();
expect(modelRuntime.checkAuth).not.toHaveBeenCalled();
expect(modelRuntime.getAuth).not.toHaveBeenCalled();
});
});