mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
fix(coding-agent): resolve branch model selection with one catalog lookup
getBranchSelection looked up the model catalog once per assistant message, which made prompt submission scale with session length. Walk the branch backward instead: only the last model_change can hold against later responses, so at most that model needs a lookup. closes #10198
This commit is contained in:
parent
37c9d0d200
commit
a0660b174e
3 changed files with 87 additions and 13 deletions
|
|
@ -14,7 +14,7 @@ import { AuthStorage } from "../src/core/auth-storage.ts";
|
|||
import { ModelRuntime } from "../src/core/model-runtime.ts";
|
||||
import { createAgentSession } from "../src/core/sdk.ts";
|
||||
import { SessionManager } from "../src/core/session-manager.ts";
|
||||
import type { ModelRouteRequest, VirtualModelDefinition } from "../src/core/virtual-models.ts";
|
||||
import { getBranchSelection, type ModelRouteRequest, type VirtualModelDefinition } from "../src/core/virtual-models.ts";
|
||||
import { createTestResourceLoader } from "./utilities.ts";
|
||||
|
||||
async function createRuntime(requests: ModelRouteRequest[] = []) {
|
||||
|
|
@ -51,6 +51,68 @@ function assistantFrom(model: Model<string>, text: string): AssistantMessage {
|
|||
return { ...fauxAssistantMessage(text), api: model.api, provider: model.provider, model: model.id };
|
||||
}
|
||||
|
||||
describe("getBranchSelection", () => {
|
||||
function select(build: (sessionManager: SessionManager) => void, runtime: ModelRuntime) {
|
||||
const sessionManager = SessionManager.inMemory();
|
||||
build(sessionManager);
|
||||
const lookups: string[] = [];
|
||||
const selection = getBranchSelection(sessionManager.getBranch(), (provider, modelId) => {
|
||||
lookups.push(`${provider}/${modelId}`);
|
||||
return runtime.getModel(provider, modelId);
|
||||
});
|
||||
return { selection, lookups };
|
||||
}
|
||||
|
||||
// #10198: the selection must not cost one catalog lookup per assistant message.
|
||||
it("looks up only the last model_change", async () => {
|
||||
const { runtime, virtual } = await createRuntime();
|
||||
const small = runtime.getModel("faux", "small")!;
|
||||
const large = runtime.getModel("faux", "large")!;
|
||||
|
||||
const physical = select((sessionManager) => {
|
||||
sessionManager.appendModelChange(small.provider, small.id);
|
||||
for (let i = 0; i < 100; i++) sessionManager.appendMessage(assistantFrom(large, "ok"));
|
||||
}, runtime);
|
||||
expect(physical.selection).toEqual({ provider: "faux", modelId: "large" });
|
||||
expect(physical.lookups).toEqual(["faux/small"]);
|
||||
|
||||
const routed = select((sessionManager) => {
|
||||
sessionManager.appendModelChange(small.provider, small.id);
|
||||
sessionManager.appendMessage(assistantFrom(small, "ok"));
|
||||
sessionManager.appendModelChange(virtual.provider, virtual.id);
|
||||
for (let i = 0; i < 100; i++) sessionManager.appendMessage(assistantFrom(large, "ok"));
|
||||
}, runtime);
|
||||
expect(routed.selection).toEqual({ provider: "router", modelId: "auto" });
|
||||
expect(routed.lookups).toEqual(["router/auto"]);
|
||||
});
|
||||
|
||||
it("uses the last model_change without responses after it", async () => {
|
||||
const { runtime, virtual } = await createRuntime();
|
||||
const small = runtime.getModel("faux", "small")!;
|
||||
const { selection, lookups } = select((sessionManager) => {
|
||||
sessionManager.appendModelChange(virtual.provider, virtual.id);
|
||||
sessionManager.appendMessage(assistantFrom(small, "ok"));
|
||||
sessionManager.appendModelChange(small.provider, small.id);
|
||||
}, runtime);
|
||||
expect(selection).toEqual({ provider: "faux", modelId: "small" });
|
||||
expect(lookups).toEqual([]);
|
||||
});
|
||||
|
||||
it("uses the latest physical response without a model_change", async () => {
|
||||
const { runtime, virtual } = await createRuntime();
|
||||
const small = runtime.getModel("faux", "small")!;
|
||||
const large = runtime.getModel("faux", "large")!;
|
||||
const { selection, lookups } = select((sessionManager) => {
|
||||
sessionManager.appendMessage(assistantFrom(small, "ok"));
|
||||
sessionManager.appendMessage(assistantFrom(large, "ok"));
|
||||
// Failed routing leaves the virtual model on its message.
|
||||
sessionManager.appendMessage({ ...assistantFrom(virtual, ""), stopReason: "error" });
|
||||
}, runtime);
|
||||
expect(selection).toEqual({ provider: "faux", modelId: "large" });
|
||||
expect(lookups).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("ModelRuntime virtual models", () => {
|
||||
it("lists a virtual model and routes it to a physical model with a clamped thinking level", async () => {
|
||||
const requests: ModelRouteRequest[] = [];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue