Compare commits
45 Commits
Author | SHA1 | Date |
---|---|---|
|
7b333d6132 | |
|
260e009ee1 | |
|
7078043b31 | |
|
c9904b72ba | |
|
e758c2c7b5 | |
|
fe2803eedc | |
|
edb858b924 | |
|
bbad58e7e7 | |
|
4fe5d75d37 | |
|
e67ebb773d | |
|
0847ffd6fe | |
|
baa3f6fa16 | |
|
8aec87aec3 | |
|
ee838d4337 | |
|
1a65ce7309 | |
|
8ee204265c | |
|
d12fbe7077 | |
|
f2e50a9d96 | |
|
7c56784f17 | |
|
d7bef61a17 | |
|
dfb0d129a2 | |
|
d8b30d9056 | |
|
ec4a50926b | |
|
0f51ac9fb8 | |
|
95d855d5dc | |
|
92cd8d54a6 | |
|
383bc584bd | |
|
b201805cd8 | |
|
3ec5fa9d99 | |
|
26589bf7c0 | |
|
8f87998e72 | |
|
3dff4f9493 | |
|
38b8a27a61 | |
|
7758d94952 | |
|
bba111a748 | |
|
be7ca31004 | |
|
b7f5074429 | |
|
900c4478f6 | |
|
d191cdd38a | |
|
576830d438 | |
|
27d5f6e726 | |
|
16fd59fd1d | |
|
8a9df3c634 | |
|
c640a95eab | |
|
6bab97b462 |
|
@ -26,7 +26,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
|
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
# Runs a single command using the runners shell
|
||||
- name: Compute model size
|
||||
run: ./tools/compute-model-sizes.sh
|
||||
|
|
|
@ -46,20 +46,20 @@ jobs:
|
|||
name: Run E2E tests ${{ github.event_name == 'schedule' && '[nightly]' || '' }}
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
repository: ${{ github.event.inputs.organization }}/${{ github.event.inputs.repositoryName }}
|
||||
ref: ${{ github.event.inputs.branch }}
|
||||
path: ${{ github.event.inputs.repositoryName }}
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
if: github.event_name == 'push' || github.event_name == 'schedule'
|
||||
with:
|
||||
path: podman-desktop-extension-ai-lab
|
||||
|
||||
# Checkout podman desktop
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
repository: containers/podman-desktop
|
||||
ref: main
|
||||
|
|
|
@ -30,7 +30,7 @@ jobs:
|
|||
name: publish
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
repository: meta-llama/llama-stack
|
||||
ref: ${{ github.event.inputs.version }}
|
||||
|
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
matrix:
|
||||
os: [windows-2022, ubuntu-22.04, macos-14]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
|
@ -74,7 +74,7 @@ jobs:
|
|||
env:
|
||||
SKIP_INSTALLATION: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
path: podman-desktop-extension-ai-lab
|
||||
# Set up pnpm
|
||||
|
@ -88,7 +88,7 @@ jobs:
|
|||
with:
|
||||
node-version: 22
|
||||
# Checkout podman desktop
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
repository: containers/podman-desktop
|
||||
ref: main
|
||||
|
|
|
@ -36,7 +36,7 @@ jobs:
|
|||
env:
|
||||
SKIP_INSTALLATION: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
path: podman-desktop-extension-ai-lab
|
||||
# Set up pnpm
|
||||
|
@ -50,7 +50,7 @@ jobs:
|
|||
with:
|
||||
node-version: 22
|
||||
# Checkout podman desktop
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
repository: podman-desktop/podman-desktop
|
||||
ref: main
|
||||
|
|
|
@ -41,7 +41,7 @@ jobs:
|
|||
releaseId: ${{ steps.create_release.outputs.id}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch }}
|
||||
- name: Generate tag utilities
|
||||
|
@ -116,7 +116,7 @@ jobs:
|
|||
needs: [tag]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ needs.tag.outputs.githubTag }}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
update-references:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
- name: Get latest ramalama version
|
||||
id: get_ramalama_version
|
||||
|
|
18
package.json
18
package.json
|
@ -3,7 +3,7 @@
|
|||
"displayName": "ai-lab-monorepo",
|
||||
"description": "ai-lab-monorepo",
|
||||
"publisher": "redhat",
|
||||
"version": "1.8.0-next",
|
||||
"version": "1.9.0-next",
|
||||
"license": "Apache-2.0",
|
||||
"private": true,
|
||||
"engines": {
|
||||
|
@ -46,14 +46,14 @@
|
|||
"devDependencies": {
|
||||
"@commitlint/cli": "^19.8.1",
|
||||
"@commitlint/config-conventional": "^19.8.1",
|
||||
"@eslint/compat": "^1.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
||||
"@typescript-eslint/parser": "^8.39.0",
|
||||
"@eslint/compat": "^1.3.2",
|
||||
"@typescript-eslint/eslint-plugin": "^8.40.0",
|
||||
"@typescript-eslint/parser": "^8.40.0",
|
||||
"@vitest/coverage-v8": "^3.2.3",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"commitlint": "^19.8.1",
|
||||
"concurrently": "^9.1.2",
|
||||
"eslint": "^9.32.0",
|
||||
"eslint": "^9.33.0",
|
||||
"eslint-import-resolver-custom-alias": "^1.3.2",
|
||||
"eslint-import-resolver-typescript": "^4.3.5",
|
||||
"eslint-plugin-etc": "^2.0.3",
|
||||
|
@ -66,14 +66,14 @@
|
|||
"eslint-plugin-unicorn": "^60.0.0",
|
||||
"globals": "^16.1.0",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^16.1.4",
|
||||
"lint-staged": "^16.1.5",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"svelte-check": "^4.3.1",
|
||||
"svelte-eslint-parser": "^1.3.1",
|
||||
"typescript": "5.8.3",
|
||||
"typescript-eslint": "^8.38.0",
|
||||
"vite": "^7.0.6",
|
||||
"typescript": "5.9.2",
|
||||
"typescript-eslint": "^8.40.0",
|
||||
"vite": "^7.1.3",
|
||||
"vitest": "^3.0.5"
|
||||
},
|
||||
"workspaces": {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "ai-lab",
|
||||
"displayName": "Podman AI Lab",
|
||||
"description": "Podman AI Lab lets you work with LLMs locally, exploring AI fundamentals, experimenting with models and prompts, and serving models while maintaining data security and privacy.",
|
||||
"version": "1.8.0-next",
|
||||
"version": "1.9.0-next",
|
||||
"icon": "icon.png",
|
||||
"type": "module",
|
||||
"publisher": "redhat",
|
||||
|
@ -111,15 +111,15 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai-compatible": "^0.2.16",
|
||||
"@huggingface/gguf": "^0.2.0",
|
||||
"@huggingface/hub": "^2.4.0",
|
||||
"@huggingface/gguf": "^0.2.1",
|
||||
"@huggingface/hub": "^2.4.1",
|
||||
"ai": "^4.3.19",
|
||||
"express": "^4.21.2",
|
||||
"express-openapi-validator": "^5.5.8",
|
||||
"isomorphic-git": "^1.32.2",
|
||||
"isomorphic-git": "^1.33.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"mustache": "^4.2.0",
|
||||
"openai": "^5.11.0",
|
||||
"openai": "^5.15.0",
|
||||
"postman-code-generators": "^1.14.1",
|
||||
"postman-collection": "^5.1.0",
|
||||
"semver": "^7.7.2",
|
||||
|
@ -140,7 +140,7 @@
|
|||
"@types/supertest": "^6.0.3",
|
||||
"@types/swagger-ui-dist": "^3.30.5",
|
||||
"@types/swagger-ui-express": "^4.1.8",
|
||||
"openapi-typescript": "^7.8.0",
|
||||
"openapi-typescript": "^7.9.1",
|
||||
"supertest": "^7.1.4",
|
||||
"vitest": "^3.0.5"
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"whispercpp": {
|
||||
"default": "quay.io/ramalama/ramalama-whisper-server@sha256:8986b418c1cd576a214f81dd42c9c7c340debf9b930ac782be08aeacec7feaea"
|
||||
"default": "quay.io/ramalama/ramalama-whisper-server@sha256:010aa34d8734e5e698fb4c5e852e43e5909baa928e3b6e991e1038a1973909ba"
|
||||
},
|
||||
"llamacpp": {
|
||||
"default": "quay.io/ramalama/ramalama-llama-server@sha256:3ca009ed7c1bf97c79f1f8314117dc3f1eced88c8fcfe8b216797bef84b6e440",
|
||||
"cuda": "quay.io/ramalama/cuda-llama-server@sha256:567a284fcf4c210f767e18ae1e5528b0f418889ec4b630996229ab3e49741ee3"
|
||||
"default": "quay.io/ramalama/ramalama-llama-server@sha256:4409a5c964382408f3bc08be1314754edaf2dfec1626f31974e34379bfeec41e",
|
||||
"cuda": "quay.io/ramalama/cuda-llama-server@sha256:5e1a3a2508e4b802c8d8c3ecb97ad1778a1b4288fd114562b51fd411bad91841"
|
||||
},
|
||||
"openvino": {
|
||||
"default": "quay.io/ramalama/openvino@sha256:4142ab5d661bdbcbe3b39e2579caa364680dab561a41958bafc9fd95ba324581"
|
||||
"default": "quay.io/ramalama/openvino@sha256:705f3e0a44dcdc2c7b81c3931e42d5ee19d2502bdb5ebddf3f186932a2658e83"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "frontend-app",
|
||||
"displayName": "UI for AI Lab",
|
||||
"version": "1.8.0-next",
|
||||
"version": "1.9.0-next",
|
||||
"type": "module",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
|
@ -26,24 +26,24 @@
|
|||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "5.1.0",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@tailwindcss/vite": "^4.1.7",
|
||||
"@tailwindcss/vite": "^4.1.12",
|
||||
"@testing-library/dom": "^10.4.1",
|
||||
"@testing-library/jest-dom": "^6.6.4",
|
||||
"@testing-library/jest-dom": "^6.8.0",
|
||||
"@testing-library/svelte": "^5.2.8",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
"@tsconfig/svelte": "^5.0.4",
|
||||
"@tsconfig/svelte": "^5.0.5",
|
||||
"@types/humanize-duration": "^3.27.4",
|
||||
"@typescript-eslint/eslint-plugin": "8.38.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.40.0",
|
||||
"jsdom": "^26.1.0",
|
||||
"monaco-editor": "^0.52.2",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-load-config": "^6.0.1",
|
||||
"svelte": "5.37.2",
|
||||
"svelte": "5.38.2",
|
||||
"svelte-fa": "^4.0.4",
|
||||
"svelte-select": "^5.8.3",
|
||||
"svelte-markdown": "^0.4.1",
|
||||
"svelte-preprocess": "^6.0.3",
|
||||
"tailwindcss": "^4.1.8",
|
||||
"tailwindcss": "^4.1.12",
|
||||
"vitest": "^3.0.5"
|
||||
}
|
||||
}
|
||||
|
|
1757
pnpm-lock.yaml
1757
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ai-lab-tests-playwright",
|
||||
"version": "1.8.0-next",
|
||||
"version": "1.9.0-next",
|
||||
"description": "Podman Desktop AI Lab extension Playwright E2E tests",
|
||||
"scripts": {
|
||||
"test:e2e": "xvfb-maybe --auto-servernum --server-args='-screen 0 1280x960x24' -- npx playwright test src/",
|
||||
|
@ -10,10 +10,10 @@
|
|||
"author": "Red Hat",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.54.2",
|
||||
"@podman-desktop/tests-playwright": "1.20.2",
|
||||
"@playwright/test": "^1.55.0",
|
||||
"@podman-desktop/tests-playwright": "1.21.0",
|
||||
"@types/node": "^22",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript": "^5.9.2",
|
||||
"xvfb-maybe": "^0.2.1"
|
||||
},
|
||||
"type": "module"
|
||||
|
|
|
@ -227,7 +227,7 @@ test.describe.serial(`AI Lab extension installation and verification`, () => {
|
|||
|
||||
// This test is currently failing due to a known issue: https://github.com/containers/podman-desktop-extension-ai-lab/issues/2925
|
||||
test.skip(`Download ${model} via API`, async ({ request }) => {
|
||||
test.setTimeout(300_000);
|
||||
test.setTimeout(610_000);
|
||||
const catalogPage = await aiLabPage.navigationBar.openCatalog();
|
||||
await catalogPage.waitForLoad();
|
||||
console.log(`Downloading ${model}...`);
|
||||
|
@ -241,7 +241,7 @@ test.describe.serial(`AI Lab extension installation and verification`, () => {
|
|||
insecure: false,
|
||||
stream: true,
|
||||
},
|
||||
timeout: 300_000,
|
||||
timeout: 600_000,
|
||||
});
|
||||
|
||||
const body = await response.body();
|
||||
|
@ -297,24 +297,24 @@ test.describe.serial(`AI Lab extension installation and verification`, () => {
|
|||
});
|
||||
|
||||
test(`Download ${modelName} model`, async () => {
|
||||
test.setTimeout(310_000);
|
||||
test.setTimeout(610_000);
|
||||
if (!(await catalogPage.isModelDownloaded(modelName))) {
|
||||
await catalogPage.downloadModel(modelName);
|
||||
}
|
||||
await playExpect
|
||||
// eslint-disable-next-line sonarjs/no-nested-functions
|
||||
.poll(async () => await waitForCatalogModel(modelName), { timeout: 300_000, intervals: [5_000] })
|
||||
.poll(async () => await waitForCatalogModel(modelName), { timeout: 600_000, intervals: [5_000] })
|
||||
.toBeTruthy();
|
||||
});
|
||||
|
||||
test(`Delete ${modelName} model`, async () => {
|
||||
test.skip(isWindows, 'Model deletion is currently very buggy in azure cicd');
|
||||
test.setTimeout(310_000);
|
||||
test.setTimeout(610_000);
|
||||
playExpect(await catalogPage.isModelDownloaded(modelName)).toBeTruthy();
|
||||
await catalogPage.deleteModel(modelName);
|
||||
await playExpect
|
||||
// eslint-disable-next-line sonarjs/no-nested-functions
|
||||
.poll(async () => await waitForCatalogModel(modelName), { timeout: 300_000, intervals: [2_500] })
|
||||
.poll(async () => await waitForCatalogModel(modelName), { timeout: 600_000, intervals: [2_500] })
|
||||
.toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
@ -421,20 +421,17 @@ test.describe.serial(`AI Lab extension installation and verification`, () => {
|
|||
.toBe('RUNNING');
|
||||
});
|
||||
|
||||
test(`Delete model service for ${modelName}`, async () => {
|
||||
test(`Delete model service and model for ${modelName}`, async () => {
|
||||
test.setTimeout(150_000);
|
||||
const modelServicePage = await modelServiceDetailsPage.deleteService();
|
||||
await playExpect(modelServicePage.heading).toBeVisible({ timeout: 120_000 });
|
||||
await cleanupServices();
|
||||
await deleteAllModels();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
[
|
||||
'ibm-granite/granite-3.3-8b-instruct-GGUF',
|
||||
'instructlab/granite-7b-lab-GGUF',
|
||||
'instructlab/merlinite-7b-lab-GGUF',
|
||||
'TheBloke/Mistral-7B-Instruct-v0.2-GGUF',
|
||||
].forEach(modelName => {
|
||||
// Do not use non-instruct models in playground tests.
|
||||
// They break out of guilderails and fail the tests.
|
||||
['ibm-granite/granite-3.3-8b-instruct-GGUF', 'TheBloke/Mistral-7B-Instruct-v0.2-GGUF'].forEach(modelName => {
|
||||
test.describe.serial(`AI Lab playground creation and deletion for ${modelName}`, { tag: '@smoke' }, () => {
|
||||
let catalogPage: AILabCatalogPage;
|
||||
let playgroundsPage: AILabPlaygroundsPage;
|
||||
|
@ -453,7 +450,7 @@ test.describe.serial(`AI Lab extension installation and verification`, () => {
|
|||
});
|
||||
|
||||
test(`Download ${modelName} model if not available`, async () => {
|
||||
test.setTimeout(310_000);
|
||||
test.setTimeout(610_000);
|
||||
if (!(await catalogPage.isModelDownloaded(modelName))) {
|
||||
await catalogPage.downloadModel(modelName);
|
||||
}
|
||||
|
@ -515,7 +512,8 @@ test.describe.serial(`AI Lab extension installation and verification`, () => {
|
|||
|
||||
test.afterAll(`Cleaning up service model`, async () => {
|
||||
test.setTimeout(60_000);
|
||||
await cleanupServiceModels();
|
||||
await cleanupServices();
|
||||
await deleteAllModels();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -640,14 +638,15 @@ test.describe.serial(`AI Lab extension installation and verification`, () => {
|
|||
|
||||
await restartApp(appName);
|
||||
await stopAndDeleteApp(appName);
|
||||
await cleanupServiceModels();
|
||||
await cleanupServices();
|
||||
});
|
||||
|
||||
test.afterAll(`Ensure cleanup of "${appName}" app, related service, and images`, async ({ navigationBar }) => {
|
||||
test.setTimeout(150_000);
|
||||
|
||||
await stopAndDeleteApp(appName);
|
||||
await cleanupServiceModels();
|
||||
await cleanupServices();
|
||||
await deleteAllModels();
|
||||
await deleteUnusedImages(navigationBar);
|
||||
});
|
||||
});
|
||||
|
@ -716,7 +715,7 @@ test.describe.serial(`AI Lab extension installation and verification`, () => {
|
|||
});
|
||||
});
|
||||
|
||||
async function cleanupServiceModels(): Promise<void> {
|
||||
async function cleanupServices(): Promise<void> {
|
||||
try {
|
||||
const modelServicePage = await aiLabPage.navigationBar.openServices();
|
||||
await modelServicePage.waitForLoad();
|
||||
|
@ -727,6 +726,12 @@ async function cleanupServiceModels(): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
async function deleteAllModels(): Promise<void> {
|
||||
const modelCatalogPage = await aiLabPage.navigationBar.openCatalog();
|
||||
await modelCatalogPage.waitForLoad();
|
||||
await modelCatalogPage.deleteAllModels();
|
||||
}
|
||||
|
||||
async function restartApp(appName: string): Promise<void> {
|
||||
const aiRunningAppsPage = await aiLabPage.navigationBar.openRunningApps();
|
||||
const aiApp = await aiRunningAppsPage.getRowForApp(appName);
|
||||
|
|
|
@ -50,6 +50,12 @@ export class AILabCatalogPage extends AILabBasePage {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
async getModelNameByRow(row: Locator): Promise<string> {
|
||||
const modelNameCell = row.getByLabel('Model Name');
|
||||
const modelName = await modelNameCell.textContent();
|
||||
return modelName?.trim() ?? '';
|
||||
}
|
||||
|
||||
async downloadModel(modelName: string): Promise<void> {
|
||||
const modelRow = await this.getModelRowByName(modelName);
|
||||
if (!modelRow) {
|
||||
|
@ -75,16 +81,35 @@ export class AILabCatalogPage extends AILabBasePage {
|
|||
}
|
||||
|
||||
async deleteModel(modelName: string): Promise<void> {
|
||||
if (!modelName || modelName.trim() === '') {
|
||||
console.warn('Model name is empty, skipping deletion.');
|
||||
return;
|
||||
}
|
||||
const modelRow = await this.getModelRowByName(modelName);
|
||||
if (!modelRow) {
|
||||
throw new Error(`Model ${modelName} not found`);
|
||||
}
|
||||
const deleteButton = modelRow.getByRole('button', { name: 'Delete Model' });
|
||||
await playExpect(deleteButton).toBeEnabled();
|
||||
await playExpect.poll(async () => await deleteButton.isEnabled(), { timeout: 10_000 }).toBeTruthy();
|
||||
await deleteButton.focus();
|
||||
await deleteButton.click();
|
||||
await this.page.waitForTimeout(1_000);
|
||||
await handleConfirmationDialog(this.page, podmanAILabExtension.extensionName, true, 'Confirm');
|
||||
await playExpect.poll(async () => await this.isModelDownloaded(modelName), { timeout: 30_000 }).toBeFalsy();
|
||||
}
|
||||
|
||||
async deleteAllModels(): Promise<void> {
|
||||
const modelRows = await this.getAllModelRows();
|
||||
if (modelRows.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const modelRow of modelRows) {
|
||||
const modelName = await this.getModelNameByRow(modelRow);
|
||||
if (await this.isModelDownloaded(modelName)) {
|
||||
await this.deleteModel(modelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async isModelDownloaded(modelName: string): Promise<boolean> {
|
||||
|
|
|
@ -33,7 +33,7 @@ export class AILabStartRecipePage extends AILabBasePage {
|
|||
super(page, webview, 'Start recipe');
|
||||
this.recipeStatus = this.webview.getByRole('status');
|
||||
this.applicationDetailsPanel = this.webview.getByLabel('application details panel');
|
||||
this.startRecipeButton = this.webview.getByRole('button', { name: /Start(\s+([a-z]+\s+)+)recipe/i });
|
||||
this.startRecipeButton = this.webview.getByRole('button', { name: /^Start .+ recipe$/i });
|
||||
this.openAIAppButton = this.applicationDetailsPanel.getByRole('button', { name: 'Open AI App' });
|
||||
this.deleteAIAppButton = this.applicationDetailsPanel.getByRole('button', { name: 'Delete AI App' });
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue