diff --git a/src/llama_stack_ui/app/chat-playground/page.test.tsx b/src/llama_stack_ui/app/chat-playground/page.test.tsx
index d9025e523..1d68e1456 100644
--- a/src/llama_stack_ui/app/chat-playground/page.test.tsx
+++ b/src/llama_stack_ui/app/chat-playground/page.test.tsx
@@ -34,6 +34,11 @@ const mockClient = {
vectorDBs: {
list: jest.fn(),
},
+ toolRuntime: {
+ ragTool: {
+ insert: jest.fn(),
+ },
+ },
};
jest.mock("@/hooks/use-auth-client", () => ({
@@ -133,12 +138,16 @@ const mockAgents = [
const mockModels = [
{
- identifier: "test-model-1",
- model_type: "llm",
+ id: "test-model-1",
+ custom_metadata: {
+ model_type: "llm",
+ },
},
{
- identifier: "test-model-2",
- model_type: "llm",
+ id: "test-model-2",
+ custom_metadata: {
+ model_type: "llm",
+ },
},
];
@@ -419,12 +428,16 @@ describe("ChatPlaygroundPage", () => {
render();
});
- await waitFor(() => {
- expect(mockClient.agents.session.create).toHaveBeenCalledWith(
- "agent_123",
- { session_name: "Default Session" }
- );
- });
+ // Wait for models to load and be filtered, then session should be created
+ await waitFor(
+ () => {
+ expect(mockClient.agents.session.create).toHaveBeenCalledWith(
+ "agent_123",
+ { session_name: "Default Session" }
+ );
+ },
+ { timeout: 3000 }
+ );
});
test("switches agent when different agent is selected", async () => {
@@ -605,14 +618,35 @@ describe("ChatPlaygroundPage", () => {
onload: null,
onerror: null,
};
- global.FileReader = jest.fn(() => mockFileReader);
+ global.FileReader = jest.fn(
+ () => mockFileReader
+ ) as unknown as typeof FileReader;
+ (
+ global.FileReader as unknown as {
+ EMPTY: number;
+ LOADING: number;
+ DONE: number;
+ }
+ ).EMPTY = 0;
+ (
+ global.FileReader as unknown as {
+ EMPTY: number;
+ LOADING: number;
+ DONE: number;
+ }
+ ).LOADING = 1;
+ (
+ global.FileReader as unknown as {
+ EMPTY: number;
+ LOADING: number;
+ DONE: number;
+ }
+ ).DONE = 2;
mockRAGTool = {
insert: jest.fn().mockResolvedValue({}),
};
- mockClient.toolRuntime = {
- ragTool: mockRAGTool,
- };
+ mockClient.toolRuntime.ragTool = mockRAGTool;
});
afterEach(() => {
@@ -762,7 +796,9 @@ describe("ChatPlaygroundPage", () => {
reader.readAsDataURL(pdfFile);
setTimeout(() => {
- reader.onerror?.(new ProgressEvent("error"));
+ reader.onerror?.(
+ new ProgressEvent("error") as ProgressEvent
+ );
}, 0);
});
diff --git a/src/llama_stack_ui/app/chat-playground/page.tsx b/src/llama_stack_ui/app/chat-playground/page.tsx
index 0417f7083..8e691740b 100644
--- a/src/llama_stack_ui/app/chat-playground/page.tsx
+++ b/src/llama_stack_ui/app/chat-playground/page.tsx
@@ -19,6 +19,15 @@ import { VectorDBCreator } from "@/components/chat-playground/vector-db-creator"
import { useAuthClient } from "@/hooks/use-auth-client";
import type { Model } from "llama-stack-client/resources/models";
import type { TurnCreateParams } from "llama-stack-client/resources/agents/turn";
+
+// Extended Model type to include properties from API response
+type ModelWithMetadata = Model & {
+ id: string;
+ custom_metadata?: {
+ model_type?: string;
+ [key: string]: unknown;
+ };
+};
import {
SessionUtils,
type ChatSession,
@@ -680,9 +689,12 @@ export default function ChatPlaygroundPage() {
setModels(modelList);
// set default LLM model for chat
- const llmModels = modelList.filter(model => model.model_type === "llm");
+ const llmModels = modelList.filter(
+ (model): model is ModelWithMetadata =>
+ (model as ModelWithMetadata).custom_metadata?.model_type === "llm"
+ );
if (llmModels.length > 0) {
- handleModelChange(llmModels[0].identifier);
+ handleModelChange(llmModels[0].id);
}
} catch (err) {
console.error("Error fetching models:", err);
@@ -1444,13 +1456,14 @@ export default function ChatPlaygroundPage() {
{models
- .filter(model => model.model_type === "llm")
+ .filter(
+ (model): model is ModelWithMetadata =>
+ (model as ModelWithMetadata).custom_metadata
+ ?.model_type === "llm"
+ )
.map(model => (
-
- {model.identifier}
+
+ {model.id}
))}
@@ -1663,13 +1676,14 @@ export default function ChatPlaygroundPage() {
{models
- .filter(model => model.model_type === "llm")
+ .filter(
+ (model): model is ModelWithMetadata =>
+ (model as ModelWithMetadata).custom_metadata
+ ?.model_type === "llm"
+ )
.map(model => (
-
- {model.identifier}
+
+ {model.id}
))}
diff --git a/src/llama_stack_ui/package-lock.json b/src/llama_stack_ui/package-lock.json
index 16a3dd09f..9650ccb36 100644
--- a/src/llama_stack_ui/package-lock.json
+++ b/src/llama_stack_ui/package-lock.json
@@ -133,7 +133,6 @@
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3",
@@ -753,7 +752,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18"
},
@@ -777,7 +775,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18"
}
@@ -3881,7 +3878,6 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz",
"integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"undici-types": "~7.16.0"
}
@@ -3901,7 +3897,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz",
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"csstype": "^3.0.2"
}
@@ -3912,7 +3907,6 @@
"integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"peerDependencies": {
"@types/react": "^19.2.0"
}
@@ -4000,7 +3994,6 @@
"integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.40.0",
"@typescript-eslint/types": "8.40.0",
@@ -4536,7 +4529,6 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -5085,7 +5077,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.9",
"caniuse-lite": "^1.0.30001746",
@@ -6153,7 +6144,6 @@
"integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -6243,7 +6233,6 @@
"integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
@@ -6345,7 +6334,6 @@
"integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.8",
@@ -9236,7 +9224,6 @@
"integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"cssstyle": "^4.2.1",
"data-urls": "^5.0.0",
@@ -11652,7 +11639,6 @@
"resolved": "https://registry.npmjs.org/preact/-/preact-10.26.9.tgz",
"integrity": "sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA==",
"license": "MIT",
- "peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
@@ -11692,7 +11678,6 @@
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -11826,7 +11811,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -11836,7 +11820,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -13146,7 +13129,6 @@
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -13252,7 +13234,6 @@
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@@ -13440,7 +13421,6 @@
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"dev": true,
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"