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"