diff --git a/extensions/kortex-cli/icon.png b/extensions/kortex-cli/icon.png new file mode 100644 index 000000000..0cad7b063 Binary files /dev/null and b/extensions/kortex-cli/icon.png differ diff --git a/extensions/kortex-cli/package.json b/extensions/kortex-cli/package.json new file mode 100644 index 000000000..1b17c3820 --- /dev/null +++ b/extensions/kortex-cli/package.json @@ -0,0 +1,33 @@ +{ + "name": "kortex-cli", + "displayName": "Kortex CLI", + "description": "Kortex CLI integration", + "version": "0.0.1-next", + "icon": "icon.png", + "publisher": "kortex", + "license": "Apache-2.0", + "engines": { + "kortex": "^0.0.1" + }, + "main": "./dist/extension.js", + "contributes": { + "configuration": {} + }, + "scripts": { + "build": "vite build && node scripts/build.js", + "test": "vitest run --coverage --passWithNoTests", + "test:watch": "vitest watch --coverage --passWithNoTests", + "watch": "vite build --watch" + }, + "dependencies": { + "@octokit/rest": "^21.1.0", + "unzipper": "^0.11.6" + }, + "devDependencies": { + "@kortex-app/api": "workspace:*", + "@types/unzipper": "^0.10.11", + "mkdirp": "^3.0.1", + "vite": "^7.0.6", + "vitest": "^4.0.10" + } +} diff --git a/extensions/kortex-cli/scripts/build.js b/extensions/kortex-cli/scripts/build.js new file mode 100644 index 000000000..f49867d05 --- /dev/null +++ b/extensions/kortex-cli/scripts/build.js @@ -0,0 +1,46 @@ +#!/usr/bin/env node +/********************************************************************** + * Copyright (C) 2026 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +const AdmZip = require('adm-zip'); +const path = require('path'); +const packageJson = require('../package.json'); +const fs = require('fs'); +const { mkdirp } = require('mkdirp'); + +const destFile = path.resolve(__dirname, `../${packageJson.name}.cdix`); +const builtinDirectory = path.resolve(__dirname, '../builtin'); +const unzippedDirectory = path.resolve(builtinDirectory, `${packageJson.name}.cdix`); +// remove the .cdix file before zipping +if (fs.existsSync(destFile)) { + fs.rmSync(destFile); +} +// remove the builtin folder before zipping +if (fs.existsSync(builtinDirectory)) { + fs.rmSync(builtinDirectory, { recursive: true, force: true }); +} + +const zip = new AdmZip(); +zip.addLocalFolder(path.resolve(__dirname, '../')); +zip.writeZip(destFile); + +// create unzipped built-in +mkdirp(unzippedDirectory).then(() => { + const unzip = new AdmZip(destFile); + unzip.extractAllTo(unzippedDirectory); +}); diff --git a/extensions/kortex-cli/src/extension.ts b/extensions/kortex-cli/src/extension.ts new file mode 100644 index 000000000..f08ac0ae9 --- /dev/null +++ b/extensions/kortex-cli/src/extension.ts @@ -0,0 +1,43 @@ +/********************************************************************** + * Copyright (C) 2026 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import type { ExtensionContext } from '@kortex-app/api'; +import { cli, env, process as processAPI, window } from '@kortex-app/api'; +import type { OctokitOptions } from '@octokit/core'; +import { Octokit } from '@octokit/rest'; + +import { KortexCLI } from './kortex-cli'; +import { KortexCliDownloader } from './kortex-cli-downloader'; + +export async function activate(extensionContext: ExtensionContext): Promise { + const octokitOptions: OctokitOptions = {}; + if (process.env.GITHUB_TOKEN) { + octokitOptions.auth = process.env.GITHUB_TOKEN; + } + const octokit = new Octokit(octokitOptions); + + const downloader = new KortexCliDownloader(extensionContext, octokit, env, window); + await downloader.init(); + extensionContext.subscriptions.push(downloader); + + const kortexCLI = new KortexCLI(cli, processAPI, downloader, env); + await kortexCLI.init(); + extensionContext.subscriptions.push(kortexCLI); +} + +export function deactivate(): void {} diff --git a/extensions/kortex-cli/src/kortex-cli-downloader.ts b/extensions/kortex-cli/src/kortex-cli-downloader.ts new file mode 100644 index 000000000..b12cfd507 --- /dev/null +++ b/extensions/kortex-cli/src/kortex-cli-downloader.ts @@ -0,0 +1,235 @@ +/********************************************************************** + * Copyright (C) 2026 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import { exec } from 'node:child_process'; +import { existsSync } from 'node:fs'; +import { chmod, mkdir, rm, unlink, writeFile } from 'node:fs/promises'; +import { arch } from 'node:os'; +import { join } from 'node:path'; + +import type { + CliTool, + Disposable, + env as EnvAPI, + ExtensionContext, + QuickPickItem, + window as WindowAPI, +} from '@kortex-app/api'; +import type { components as OctokitComponents } from '@octokit/openapi-types'; +import type { Octokit } from '@octokit/rest'; +import { Open } from 'unzipper'; + +const GITHUB_ORG = 'kortex-hub'; +const GITHUB_REPO = 'kortex-cli'; + +export interface ReleaseArtifactMetadata extends QuickPickItem { + tag: string; + id: number; +} + +export class KortexCliDownloader implements Disposable { + #installDirectory: string; + + constructor( + private readonly extensionContext: ExtensionContext, + private readonly octokit: Octokit, + private readonly envAPI: typeof EnvAPI, + private readonly windowAPI: typeof WindowAPI, + ) { + this.#installDirectory = join(this.extensionContext.storagePath, 'kortex-cli-package'); + } + + async init(): Promise { + if (!existsSync(this.#installDirectory)) { + await mkdir(this.#installDirectory, { recursive: true }); + } + } + + dispose(): void {} + + extractTarGz(filePath: string, outDir: string): Promise { + return new Promise((resolve, reject) => { + // eslint-disable-next-line sonarjs/os-command + exec(`tar -xzf "${filePath}" -C "${outDir}"`, err => { + if (err) reject(err); + else resolve(); + }); + }); + } + + async install(release: ReleaseArtifactMetadata): Promise { + const destFile = await this.download(release); + + if (destFile.endsWith('.zip')) { + const directory = await Open.file(destFile); + await directory.extract({ path: this.#installDirectory }); + } else if (destFile.endsWith('.tar.gz') && (this.envAPI.isMac || this.envAPI.isLinux)) { + await this.extractTarGz(destFile, this.#installDirectory); + } else { + throw new Error(`Unsupported archive format: ${destFile}`); + } + + await unlink(destFile); + + const executablePath = this.getKortexExecutablePath(); + if (!existsSync(executablePath)) { + throw new Error(`Kortex CLI executable was not found after extraction: ${executablePath}`); + } + if (!this.envAPI.isWindows) { + await chmod(executablePath, 0o755); + } + + return executablePath; + } + + async uninstall(): Promise { + if (existsSync(this.#installDirectory)) { + await rm(this.#installDirectory, { recursive: true }); + } + } + + getKortexExecutablePath(): string { + const executable = this.envAPI.isWindows ? 'kortex-cli.exe' : 'kortex-cli'; + return join(this.#installDirectory, executable); + } + + async selectVersion(cliInfo?: CliTool): Promise { + let releasesMetadata = await this.grabLatestReleasesMetadata(); + + if (releasesMetadata.length === 0) throw new Error('cannot grab kortex-cli releases'); + + if (cliInfo) { + releasesMetadata = releasesMetadata.filter(release => release.tag.slice(1) !== cliInfo.version); + } + + const selectedRelease = await this.windowAPI.showQuickPick(releasesMetadata, { + placeHolder: 'Select Kortex CLI version to download', + }); + + if (!selectedRelease) { + throw new Error('No version selected'); + } + return selectedRelease; + } + + async grabLatestReleasesMetadata(): Promise { + const lastReleases = await this.octokit.repos.listReleases({ + owner: GITHUB_ORG, + repo: GITHUB_REPO, + per_page: 10, + }); + + return lastReleases.data + .filter(release => !release.prerelease) + .map(release => ({ + label: release.name ?? release.tag_name, + tag: release.tag_name, + id: release.id, + })) + .slice(0, 5); + } + + async getLatestVersionAsset(): Promise { + const latestReleases = await this.grabLatestReleasesMetadata(); + return latestReleases[0]; + } + + async getReleaseAssetId(releaseId: number): Promise { + const architecture = arch(); + let assetName: string; + + if (this.envAPI.isWindows) { + switch (architecture) { + case 'x64': + assetName = 'windows_amd64.zip'; + break; + case 'arm64': + assetName = 'windows_arm64.zip'; + break; + default: + throw new Error(`Unsupported architecture for Windows: ${architecture}`); + } + } else if (this.envAPI.isMac) { + switch (architecture) { + case 'arm64': + assetName = 'darwin_arm64.tar.gz'; + break; + case 'x64': + assetName = 'darwin_amd64.tar.gz'; + break; + default: + throw new Error(`Unsupported architecture for macOS: ${architecture}`); + } + } else if (this.envAPI.isLinux) { + switch (architecture) { + case 'arm64': + assetName = 'linux_arm64.tar.gz'; + break; + case 'x64': + assetName = 'linux_amd64.tar.gz'; + break; + default: + throw new Error(`Unsupported architecture for Linux: ${architecture}`); + } + } else { + throw new Error('Unsupported platform'); + } + + const listOfAssets = await this.octokit.repos.listReleaseAssets({ + owner: GITHUB_ORG, + repo: GITHUB_REPO, + release_id: releaseId, + per_page: 60, + }); + + const asset = listOfAssets.data.find(a => a.name.endsWith(assetName)); + if (!asset) { + throw new Error( + `No asset found for ${architecture} on ${this.envAPI.isWindows ? 'Windows' : this.envAPI.isMac ? 'macOS' : 'Linux'}`, + ); + } + + return asset; + } + + async download(release: ReleaseArtifactMetadata): Promise { + const asset = await this.getReleaseAssetId(release.id); + + const storageData = this.extensionContext.storagePath; + if (!existsSync(storageData)) { + await mkdir(storageData, { recursive: true }); + } + + const destination = join(storageData, asset.name); + await this.downloadReleaseAsset(asset.id, destination); + return destination; + } + + protected async downloadReleaseAsset(assetId: number, destination: string): Promise { + const asset = await this.octokit.repos.getReleaseAsset({ + owner: GITHUB_ORG, + repo: GITHUB_REPO, + asset_id: assetId, + headers: { + accept: 'application/octet-stream', + }, + }); + + await writeFile(destination, Buffer.from(asset.data as unknown as ArrayBuffer)); + } +} diff --git a/extensions/kortex-cli/src/kortex-cli.ts b/extensions/kortex-cli/src/kortex-cli.ts new file mode 100644 index 000000000..99b971633 --- /dev/null +++ b/extensions/kortex-cli/src/kortex-cli.ts @@ -0,0 +1,128 @@ +/********************************************************************** + * Copyright (C) 2026 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import { existsSync } from 'node:fs'; + +import type { + cli as CliAPI, + CliTool, + CliToolInstallationSource, + Disposable, + env as EnvAPI, + process as ProcessAPI, +} from '@kortex-app/api'; + +import type { KortexCliDownloader, ReleaseArtifactMetadata } from './kortex-cli-downloader'; +import { whereBinary } from './utils/system'; + +export const KORTEX_CLI_NAME = 'kortex-cli'; + +export class KortexCLI implements Disposable { + private cli: CliTool | undefined = undefined; + + constructor( + private readonly cliAPI: typeof CliAPI, + private readonly processAPI: typeof ProcessAPI, + private readonly downloader: KortexCliDownloader, + private readonly envAPI: typeof EnvAPI, + ) {} + + protected async findKortexVersion(): Promise< + { path: string; version: string; installationSource: CliToolInstallationSource } | undefined + > { + // Check extension storage first + try { + const path = this.downloader.getKortexExecutablePath(); + if (existsSync(path)) { + const { stdout } = await this.processAPI.exec(path, ['version']); + return { + path, + version: this.parseVersion(stdout), + installationSource: 'extension', + }; + } + } catch (err: unknown) { + console.warn(err); + } + + // Check system PATH + const executable = this.envAPI.isWindows ? 'kortex-cli.exe' : 'kortex-cli'; + try { + const { stdout } = await this.processAPI.exec(executable, ['version']); + const location = await whereBinary(this.envAPI, this.processAPI, executable); + return { + path: location, + version: this.parseVersion(stdout), + installationSource: 'external', + }; + } catch (err: unknown) { + return undefined; + } + } + + // Parse version from "kortex-cli version X.Y.Z" output + protected parseVersion(stdout: string): string { + const parts = stdout.trim().split(' '); + return parts[parts.length - 1]; + } + + async init(): Promise { + const info = await this.findKortexVersion(); + + this.cli = this.cliAPI.createCliTool({ + name: KORTEX_CLI_NAME, + displayName: 'Kortex CLI', + markdownDescription: 'CLI for managing Kortex workspaces', + images: {}, + version: info?.version, + path: info?.path, + installationSource: info?.installationSource, + }); + + if (!this.cli.version) { + let artifact: ReleaseArtifactMetadata | undefined; + + this.cli.registerInstaller({ + selectVersion: async () => { + const release = await this.downloader.selectVersion(this.cli); + artifact = release; + return release.tag.replace('v', '').trim(); + }, + doInstall: async () => { + if (!artifact) throw new Error('No version selected'); + const installPath = await this.downloader.install(artifact); + this.cli?.updateVersion({ + version: artifact.tag.replace('v', '').trim(), + path: installPath, + }); + }, + doUninstall: async () => { + await this.downloader.uninstall(); + this.cli?.updateVersion({ + version: undefined, + path: undefined, + }); + }, + }); + } + } + + dispose(): void { + this.cli?.dispose(); + } +} diff --git a/extensions/kortex-cli/src/utils/system.ts b/extensions/kortex-cli/src/utils/system.ts new file mode 100644 index 000000000..b54994e64 --- /dev/null +++ b/extensions/kortex-cli/src/utils/system.ts @@ -0,0 +1,43 @@ +/********************************************************************** + * Copyright (C) 2026 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import type { env as EnvAPI, process as ProcessAPI } from '@kortex-app/api'; + +export async function whereBinary( + envAPI: typeof EnvAPI, + processAPI: typeof ProcessAPI, + executable: string, +): Promise { + if (envAPI.isLinux || envAPI.isMac) { + try { + const { stdout: fullPath } = await processAPI.exec('which', [executable]); + return fullPath; + } catch (err) { + console.warn('Error getting full path', err); + } + } else if (envAPI.isWindows) { + try { + const { stdout: fullPath } = await processAPI.exec('where.exe', [executable]); + return fullPath.replace(/(\r\n|\n|\r)/gm, ''); + } catch (err) { + console.warn('Error getting full path', err); + } + } + + throw new Error(`binary ${executable} not found.`); +} diff --git a/extensions/kortex-cli/tsconfig.json b/extensions/kortex-cli/tsconfig.json new file mode 100644 index 000000000..32944f54e --- /dev/null +++ b/extensions/kortex-cli/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "strict": true, + "module": "esnext", + "lib": ["ES2024"], + "sourceMap": true, + "rootDir": "src", + "outDir": "dist", + "target": "esnext", + "moduleResolution": "node", + "skipLibCheck": true, + "types": ["node"], + "esModuleInterop": true + }, + "include": ["src"] +} diff --git a/extensions/kortex-cli/vite.config.js b/extensions/kortex-cli/vite.config.js new file mode 100644 index 000000000..55f50ac57 --- /dev/null +++ b/extensions/kortex-cli/vite.config.js @@ -0,0 +1,67 @@ +/********************************************************************** + * Copyright (C) 2026 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import { join } from 'path'; +import { builtinModules } from 'module'; + +const PACKAGE_ROOT = __dirname; + +/** + * @type {import('vite').UserConfig} + * @see https://vitejs.dev/config/ + */ +const config = { + mode: process.env.MODE, + root: PACKAGE_ROOT, + envDir: process.cwd(), + resolve: { + alias: { + '/@/': join(PACKAGE_ROOT, 'src') + '/', + }, + }, + build: { + sourcemap: 'inline', + target: 'esnext', + outDir: 'dist', + assetsDir: '.', + minify: process.env.MODE === 'production' ? 'esbuild' : false, + lib: { + entry: 'src/extension.ts', + formats: ['cjs'], + }, + rollupOptions: { + external: ['@kortex-app/api', ...builtinModules.flatMap(p => [p, `node:${p}`])], + output: { + entryFileNames: '[name].js', + }, + }, + emptyOutDir: true, + reportCompressedSize: false, + }, + test: { + globals: true, + environment: 'node', + include: ['src/**/*.{test,spec}.?(c|m)[jt]s?(x)'], + globalSetup: [join(PACKAGE_ROOT, '..', '..', '__mocks__', 'vitest-generate-api-global-setup.ts')], + alias: { + '@kortex-app/api': join(PACKAGE_ROOT, '..', '..', '__mocks__/@kortex-app/api.js'), + }, + }, +}; + +export default config; diff --git a/package.json b/package.json index 1d5350646..b0632e54a 100644 --- a/package.json +++ b/package.json @@ -15,11 +15,12 @@ "scripts": { "build": "pnpm run build:main && pnpm run build:preload && pnpm run build:preload-webview && npm run build:preload:types && pnpm run build:renderer && pnpm run build:extensions", "build:main": "cd ./packages/main && vite build", - "build:extensions": "pnpm run build:extensions:container && pnpm run build:extensions:docling && pnpm run build:extensions:gemini && pnpm run build:extensions:goose && pnpm run build:extensions:mcp-registries && pnpm run build:extensions:milvus && pnpm run build:extensions:ollama && pnpm run build:extensions:openai-compatible && pnpm run build:extensions:openshift-ai && pnpm run build:extensions:ramalama", + "build:extensions": "pnpm run build:extensions:container && pnpm run build:extensions:docling && pnpm run build:extensions:gemini && pnpm run build:extensions:goose && pnpm run build:extensions:kortex-cli && pnpm run build:extensions:mcp-registries && pnpm run build:extensions:milvus && pnpm run build:extensions:ollama && pnpm run build:extensions:openai-compatible && pnpm run build:extensions:openshift-ai && pnpm run build:extensions:ramalama", "build:extensions:container": "cd ./extensions/container/packages/extension && pnpm run build", "build:extensions:docling": "cd ./extensions/docling && pnpm run build", "build:extensions:gemini": "cd ./extensions/gemini && pnpm run build", "build:extensions:goose": "cd ./extensions/goose && pnpm run build", + "build:extensions:kortex-cli": "cd ./extensions/kortex-cli && pnpm run build", "build:extensions:mcp-registries": "cd ./extensions/mcp-registries && pnpm run build", "build:extensions:milvus": "cd ./extensions/milvus && pnpm run build", "build:extensions:ollama": "cd ./extensions/ollama && pnpm run build", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a9e2d38a8..9241f1908 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -510,6 +510,31 @@ importers: specifier: ^4.0.10 version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.31.1)(msw@2.12.10(@types/node@24.12.2)(typescript@5.9.3))(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.2) + extensions/kortex-cli: + dependencies: + '@octokit/rest': + specifier: ^21.1.0 + version: 21.1.1 + unzipper: + specifier: ^0.11.6 + version: 0.11.6 + devDependencies: + '@kortex-app/api': + specifier: workspace:* + version: link:../../packages/extension-api + '@types/unzipper': + specifier: ^0.10.11 + version: 0.10.11 + mkdirp: + specifier: ^3.0.1 + version: 3.0.1 + vite: + specifier: ^7.0.6 + version: 7.3.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.2) + vitest: + specifier: ^4.0.10 + version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.31.1)(msw@2.12.10(@types/node@24.12.2)(typescript@5.9.3))(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.2) + extensions/mcp-registries: devDependencies: '@kortex-app/api': @@ -911,12 +936,6 @@ packages: '@adobe/css-tools@4.4.3': resolution: {integrity: sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA==} - '@ai-sdk/gateway@3.0.85': - resolution: {integrity: sha512-oPvs3bYnxndBY/O0gFSFuc5aA/QKCJbk/CaJaRnKgA/ZPH17jeVvEtiUBE6/N8hWhK7XgX53NFI7F3CGmDfm1g==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/gateway@3.0.87': resolution: {integrity: sha512-knLx/VY0u5KAZGgrTorWCTbEnwK3oCCdm8yjxVQm3s14erqVo60SP08dsFWm+xNULPTusftQGVD/l0/hx5QOHg==} engines: {node: '>=18'} @@ -953,12 +972,6 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@4.0.21': - resolution: {integrity: sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@4.0.22': resolution: {integrity: sha512-B2OTFcRw/Pdka9ZTjpXv6T6qZ6RruRuLokyb8HwW+aoW9ndJ3YasA3/mVswyJw7VMBF8ofXgqvcrCt9KYvFifg==} engines: {node: '>=18'} @@ -2856,12 +2869,6 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ai@6.0.143: - resolution: {integrity: sha512-wVDb7StQ1EPQ9GDAOmi1AsuAXQRSii+zZT2sFK+MCisH4vV7XNEAdzXL+sKsUAFhhq+EtVFWWlB4mCk4hcoIMw==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - ai@6.0.145: resolution: {integrity: sha512-RbMiFsPZxE4uf5Hhs8rscp5bIwvjQOrqS5dQGWNVRHGM947QZgkKX7Ih5hto8MK/7xkbtneoOZruZ8oSLO828A==} engines: {node: '>=18'} @@ -7818,13 +7825,6 @@ snapshots: '@adobe/css-tools@4.4.3': {} - '@ai-sdk/gateway@3.0.85(zod@4.3.6)': - dependencies: - '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.21(zod@4.3.6) - '@vercel/oidc': 3.1.0 - zod: 4.3.6 - '@ai-sdk/gateway@3.0.87(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 @@ -7865,13 +7865,6 @@ snapshots: eventsource-parser: 3.0.6 zod: 4.3.6 - '@ai-sdk/provider-utils@4.0.21(zod@4.3.6)': - dependencies: - '@ai-sdk/provider': 3.0.8 - '@standard-schema/spec': 1.1.0 - eventsource-parser: 3.0.6 - zod: 4.3.6 - '@ai-sdk/provider-utils@4.0.22(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 @@ -8175,8 +8168,8 @@ snapshots: make-fetch-happen: 10.2.1 nopt: 6.0.0 proc-log: 2.0.1 - semver: 7.7.3 - tar: 7.5.10 + semver: 7.7.4 + tar: 7.5.13 which: 2.0.2 transitivePeerDependencies: - bluebird @@ -8806,7 +8799,7 @@ snapshots: '@npmcli/fs@2.1.2': dependencies: '@gar/promisify': 1.1.3 - semver: 7.7.3 + semver: 7.7.4 '@npmcli/fs@4.0.0': dependencies: @@ -9980,14 +9973,6 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ai@6.0.143(zod@4.3.6): - dependencies: - '@ai-sdk/gateway': 3.0.85(zod@4.3.6) - '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.21(zod@4.3.6) - '@opentelemetry/api': 1.9.0 - zod: 4.3.6 - ai@6.0.145(zod@4.3.6): dependencies: '@ai-sdk/gateway': 3.0.87(zod@4.3.6) @@ -10597,7 +10582,7 @@ snapshots: promise-inflight: 1.0.1 rimraf: 3.0.2 ssri: 9.0.1 - tar: 7.5.10 + tar: 7.5.13 unique-filename: 2.0.1 transitivePeerDependencies: - bluebird