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
+26 -9
View File
@@ -1,3 +1,4 @@
import { createModelRegistry, getModelRuntime } from "./model-runtime-test-utils.ts";
/**
* Test harness for AgentSession runtime testing.
*
@@ -28,7 +29,6 @@ import type {
import { createAssistantMessageEventStream } from "@earendil-works/pi-ai";
import { AgentSession, type AgentSessionEvent } from "../src/core/agent-session.ts";
import { AuthStorage } from "../src/core/auth-storage.ts";
import { ModelRegistry } from "../src/core/model-registry.ts";
import { SessionManager } from "../src/core/session-manager.ts";
import type { Settings } from "../src/core/settings-manager.ts";
import { SettingsManager } from "../src/core/settings-manager.ts";
@@ -361,11 +361,11 @@ function createTempDir(): string {
return tempDir;
}
function createHarnessWithResourceLoader(
async function createHarnessWithResourceLoader(
options: HarnessOptions,
resourceLoader: ResourceLoader,
tempDir: string,
): Harness {
): Promise<Harness> {
const baseModel = options.model ?? fauxModel;
const model: Model<any> = options.contextWindow ? { ...baseModel, contextWindow: options.contextWindow } : baseModel;
@@ -389,15 +389,32 @@ function createHarnessWithResourceLoader(
}
const authStorage = AuthStorage.create(join(tempDir, "auth.json"));
authStorage.setRuntimeApiKey(model.provider, "faux-key");
const modelRegistry = ModelRegistry.create(authStorage, tempDir);
await authStorage.modify(model.provider, async () => ({ type: "api_key", key: "faux-key" }));
const modelRegistry = await createModelRegistry(authStorage, tempDir);
modelRegistry.registerProvider(model.provider, {
baseUrl: model.baseUrl,
api: model.api,
models: [
{
id: model.id,
name: model.name,
api: model.api,
reasoning: model.reasoning,
input: model.input,
cost: model.cost,
contextWindow: model.contextWindow,
maxTokens: model.maxTokens,
baseUrl: model.baseUrl,
},
],
});
const session = new AgentSession({
agent,
sessionManager,
settingsManager,
cwd: tempDir,
modelRegistry,
modelRuntime: getModelRuntime(modelRegistry),
resourceLoader,
baseToolsOverride: options.baseToolsOverride,
});
@@ -429,18 +446,18 @@ function createHarnessWithResourceLoader(
};
}
export function createHarness(options: HarnessOptions = {}): Harness {
export async function createHarness(options: HarnessOptions = {}): Promise<Harness> {
if (options.extensionFactories?.length) {
throw new Error("createHarness does not support extensionFactories. Use createHarnessWithExtensions().");
}
const tempDir = createTempDir();
return createHarnessWithResourceLoader(options, options.resourceLoader ?? createTestResourceLoader(), tempDir);
return await createHarnessWithResourceLoader(options, options.resourceLoader ?? createTestResourceLoader(), tempDir);
}
export async function createHarnessWithExtensions(options: HarnessOptions = {}): Promise<Harness> {
const tempDir = createTempDir();
const extensionsResult = await createTestExtensionsResult(options.extensionFactories ?? [], tempDir);
const resourceLoader = options.resourceLoader ?? createTestResourceLoader({ extensionsResult });
return createHarnessWithResourceLoader(options, resourceLoader, tempDir);
return await createHarnessWithResourceLoader(options, resourceLoader, tempDir);
}