feat: unify installation model catalog
This commit is contained in:
@@ -18,25 +18,25 @@ const SCRIPT = path.resolve("../harness/tests/fake_pi/scripts/f1_disambiguation.
|
||||
|
||||
function operationalWorkspace(id = "default") {
|
||||
return {
|
||||
workspace: { schema_version: 3, id, name: id, language: "en" },
|
||||
workspace: { schema_version: 4, id, name: id, language: "en" },
|
||||
dwh: {
|
||||
engine: "postgres", database: "warehouse", schema: "public",
|
||||
supported_transports: ["postgres_direct"],
|
||||
},
|
||||
semantic_index: {
|
||||
vector_store: {
|
||||
engine: "qdrant", collection: id, dimensions: 1024, distance: "cosine",
|
||||
},
|
||||
embedding: {
|
||||
provider: "ollama_internal", model: "qwen3-embedding:0.6b", dimensions: 1024,
|
||||
},
|
||||
},
|
||||
llm_policy: {
|
||||
allowed: ["zai/glm-5.2", "deepseek/deepseek-v4-pro", "local-qwen/qwen3.6-35b-a3b"],
|
||||
},
|
||||
} as const;
|
||||
}
|
||||
|
||||
function sessionCatalog(defaultSession = "zai/glm-5.2", available = [defaultSession]) {
|
||||
return {
|
||||
defaultSession,
|
||||
defaultMetadataGeneration: null,
|
||||
embedding: { id: "ollama/qwen3-embedding:0.6b", dimensions: 1024 },
|
||||
sessionModels: () => [],
|
||||
metadataModels: () => [],
|
||||
hasSession: (id: string) => available.includes(id),
|
||||
} as any;
|
||||
}
|
||||
|
||||
const defaultWorkspaceRegistry = {
|
||||
list: vi.fn(async () => [{
|
||||
id: "default", commit: "e".repeat(40), blob: "f".repeat(40),
|
||||
@@ -495,8 +495,8 @@ test("creates a session from the active immutable workspace revision", async ()
|
||||
workspaceRegistry: {
|
||||
read: vi.fn(async () => ({
|
||||
workspace: {
|
||||
workspace: { schema_version: 2, id: "psd-clinical", name: "PSD", language: "it" },
|
||||
dwh: {}, semantic_index: {}, llm_policy: { allowed: ["zai/glm-5.2"] },
|
||||
workspace: { schema_version: 4, id: "psd-clinical", name: "PSD", language: "it" },
|
||||
dwh: {},
|
||||
},
|
||||
revision: {
|
||||
id: "psd-clinical", commit: "a".repeat(40), blob: "b".repeat(40),
|
||||
@@ -589,22 +589,11 @@ test("rejects an SSH-only workspace before persisting or starting a session", as
|
||||
workspaceRegistry: {
|
||||
acquireSessionRevision: vi.fn(async () => ({
|
||||
workspace: {
|
||||
workspace: { schema_version: 2, id: "ssh-workspace", name: "SSH", language: "en" },
|
||||
workspace: { schema_version: 4, id: "ssh-workspace", name: "SSH", language: "en" },
|
||||
dwh: {
|
||||
engine: "postgres", database: "postgres", schema: "public",
|
||||
supported_transports: ["ssh_tunnel"],
|
||||
},
|
||||
semantic_index: {
|
||||
vector_store: {
|
||||
engine: "pgvector", database: "postgres", schema: "vectors",
|
||||
collection: "documents", dimensions: 768, distance: "cosine",
|
||||
supported_transports: ["ssh_tunnel"],
|
||||
},
|
||||
embedding: {
|
||||
provider: "ollama_compatible", model: "nomic-embed-text", dimensions: 768,
|
||||
},
|
||||
},
|
||||
llm_policy: { allowed: ["zai/glm-5.2"] },
|
||||
},
|
||||
revision: {
|
||||
id: "ssh-workspace", commit: "a".repeat(40), blob: "b".repeat(40),
|
||||
@@ -632,7 +621,7 @@ test("hands a revision lease to retention only after the session manifest is dur
|
||||
const markPersisted = vi.fn(async () => {});
|
||||
const abort = vi.fn(async () => {});
|
||||
const acquireSessionRevision = vi.fn(async () => ({
|
||||
workspace: { llm_policy: { allowed: ["zai/glm-5.2"] } },
|
||||
workspace: operationalWorkspace("leased"),
|
||||
revision: {
|
||||
id: "leased", commit: "a".repeat(40), blob: "b".repeat(40),
|
||||
snapshotPath: `/data/workspace-registry/snapshots/${"a".repeat(40)}/leased.yaml`,
|
||||
@@ -670,7 +659,7 @@ test("creates a session from the configured default workspace revision when work
|
||||
const sessionNew = vi.fn(async () => ({ id: "default-pinned" }));
|
||||
const registry = {
|
||||
read: vi.fn(async (id: string) => ({
|
||||
workspace: { llm_policy: { allowed: ["zai/glm-5.2"] } },
|
||||
workspace: operationalWorkspace(id),
|
||||
revision: {
|
||||
id, commit: "c".repeat(40), blob: "d".repeat(40),
|
||||
snapshotPath: `/data/workspace-registry/snapshots/${"c".repeat(40)}/${id}.yaml`,
|
||||
@@ -758,7 +747,7 @@ test("session lifecycle locates a B session when installation default is A", asy
|
||||
listModels: async () => [{ provider: "zai", id: "glm-5.2", name: "GLM 5.2", reasoning: true }],
|
||||
workspaceRegistry: {
|
||||
read: async (id: string) => ({
|
||||
workspace: { llm_policy: { allowed: ["zai/glm-5.2"] } },
|
||||
workspace: operationalWorkspace(id),
|
||||
revision: { id, commit: "b".repeat(40), blob: "d".repeat(40), snapshotPath: bPath },
|
||||
}),
|
||||
list: async () => [
|
||||
@@ -793,7 +782,7 @@ test("session lifecycle locates a B session when installation default is A", asy
|
||||
expect(runtimeOptions).toEqual(["/runtime/1.yaml", "/runtime/2.yaml"]);
|
||||
});
|
||||
|
||||
test("POST /sessions usa i settings (workspace/provider/model/thinking) e crea+avvia", async () => {
|
||||
test("POST /sessions uses the catalog default with workspace/thinking settings and starts", async () => {
|
||||
const modelKey = path.join(os.tmpdir(), `thoth-model-key-${process.pid}`);
|
||||
writeFileSync(modelKey, "test-model-key", { mode: 0o600 });
|
||||
chmodSync(modelKey, 0o600);
|
||||
@@ -808,7 +797,8 @@ test("POST /sessions usa i settings (workspace/provider/model/thinking) e crea+a
|
||||
sessionNew: async (o: any) => { sessionNewArg = o; return { id: "s1" }; },
|
||||
sessionList: async () => [{ id: "s1" }],
|
||||
} as any,
|
||||
getSettings: () => ({ workspace: "w", provider: "zai", model: "glm-5.2", thinking: "high" }),
|
||||
getSettings: () => ({ workspace: "w", thinking: "high" }),
|
||||
runtimeModelCatalog: sessionCatalog(),
|
||||
listModels: async () => [
|
||||
{ provider: "zai", id: "glm-5.2", name: "GLM 5.2", reasoning: true },
|
||||
],
|
||||
@@ -2565,32 +2555,43 @@ test("POST /sessions proceeds when ollamaEnsure succeeds", async () => {
|
||||
expect(ensureWs).toContain(`/snapshots/${"e".repeat(40)}/psd.yaml`);
|
||||
});
|
||||
|
||||
test("POST /sessions rejects an unavailable saved model before persisting a session", async () => {
|
||||
test("POST /sessions falls back from a stale requested model to the catalog default", async () => {
|
||||
let created = 0;
|
||||
let persisted: any;
|
||||
const runtime = { bridge: { onClientEvent: () => {} } };
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
thtRunner: {
|
||||
sessionNew: async () => { created += 1; return { id: "must-not-exist" }; },
|
||||
sessionNew: async (options: any) => { created += 1; persisted = options; return { id: "fallback" }; },
|
||||
searchPack: async () => {},
|
||||
} as any,
|
||||
readiness: { ensure: async () => ({ ok: true }) } as any,
|
||||
getSettings: () => ({
|
||||
workspace: "psd",
|
||||
provider: "deepseek",
|
||||
model: "deepseek-v4-pro",
|
||||
thinking: "medium",
|
||||
}) as any,
|
||||
getSettings: () => ({ workspace: "psd", thinking: "medium" }) as any,
|
||||
runtimeModelCatalog: sessionCatalog(),
|
||||
listModels: async () => [
|
||||
{ provider: "zai", id: "glm-5.2", name: "GLM 5.2", reasoning: true },
|
||||
],
|
||||
mgr: {
|
||||
teardownForPrincipal: () => [],
|
||||
createFor: () => runtime,
|
||||
get: () => runtime,
|
||||
configure: async () => {},
|
||||
start: () => {},
|
||||
} as any,
|
||||
});
|
||||
|
||||
const res = await app.inject({ method: "POST", url: "/sessions", payload: { question: "q" } });
|
||||
const res = await app.inject({
|
||||
method: "POST",
|
||||
url: "/sessions",
|
||||
payload: { question: "q", provider: "deepseek", model: "deepseek-v4-pro" },
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(503);
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.json()).toEqual({
|
||||
error: "Selected model is unavailable. Check Pi authentication and model settings, then try again.",
|
||||
code: "model_unavailable",
|
||||
id: "fallback",
|
||||
warning: "Configured model deepseek/deepseek-v4-pro is unavailable; using zai/glm-5.2.",
|
||||
});
|
||||
expect(created).toBe(0);
|
||||
expect(persisted).toMatchObject({ provider: "zai", model: "glm-5.2" });
|
||||
expect(created).toBe(1);
|
||||
});
|
||||
|
||||
test("POST /sessions marks a persisted session failed when runtime construction throws", async () => {
|
||||
|
||||
Reference in New Issue
Block a user