Download packages/cli/src/commands/gemma/platform.ts from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 8.16 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/commands/gemma/platform.ts
- Command line
-
hf download hf://SaylorTwift/gemini-cli/packages/cli/src/commands/gemma/platform.ts
-
curl -L -o platform.ts https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/commands/gemma/platform.ts
8.16 kB
| /** | |
| * @license | |
| * Copyright 2026 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import { loadSettings, SettingScope } from '../../config/settings.js'; | |
| import fs from 'node:fs'; | |
| import path from 'node:path'; | |
| import { execFileSync } from 'node:child_process'; | |
| import { | |
| PLATFORM_BINARY_MAP, | |
| LITERT_RELEASE_BASE_URL, | |
| LITERT_RELEASE_VERSION, | |
| getLiteRtBinDir, | |
| GEMMA_MODEL_NAME, | |
| HEALTH_CHECK_TIMEOUT_MS, | |
| LITERT_API_VERSION, | |
| getPidFilePath, | |
| } from './constants.js'; | |
| export interface PlatformInfo { | |
| key: string; | |
| binaryName: string; | |
| } | |
| export interface GemmaConfigStatus { | |
| settingsEnabled: boolean; | |
| configuredPort: number; | |
| configuredBinaryPath?: string; | |
| } | |
| export interface LiteRtServerProcessInfo { | |
| pid: number; | |
| binaryPath?: string; | |
| port?: number; | |
| } | |
| function getUserConfiguredBinaryPath( | |
| workspaceDir = process.cwd(), | |
| ): string | undefined { | |
| try { | |
| const userGemmaSettings = loadSettings(workspaceDir).forScope( | |
| SettingScope.User, | |
| ).settings.experimental?.gemmaModelRouter; | |
| return userGemmaSettings?.binaryPath?.trim() || undefined; | |
| } catch { | |
| return undefined; | |
| } | |
| } | |
| function parsePortFromHost( | |
| host: string | undefined, | |
| fallbackPort: number, | |
| ): number { | |
| if (!host) { | |
| return fallbackPort; | |
| } | |
| try { | |
| const url = new URL(host); | |
| const port = Number(url.port); | |
| return Number.isFinite(port) && port > 0 ? port : fallbackPort; | |
| } catch { | |
| const match = host.match(/:(\d+)/); | |
| if (!match) { | |
| return fallbackPort; | |
| } | |
| const port = parseInt(match[1], 10); | |
| return Number.isFinite(port) && port > 0 ? port : fallbackPort; | |
| } | |
| } | |
| export function resolveGemmaConfig(fallbackPort: number): GemmaConfigStatus { | |
| let settingsEnabled = false; | |
| let configuredPort = fallbackPort; | |
| const configuredBinaryPath = getUserConfiguredBinaryPath(); | |
| try { | |
| const settings = loadSettings(process.cwd()); | |
| const gemmaSettings = settings.merged.experimental?.gemmaModelRouter; | |
| settingsEnabled = gemmaSettings?.enabled === true; | |
| configuredPort = parsePortFromHost( | |
| gemmaSettings?.classifier?.host, | |
| fallbackPort, | |
| ); | |
| } catch { | |
| // ignore — settings may fail to load outside a workspace | |
| } | |
| return { settingsEnabled, configuredPort, configuredBinaryPath }; | |
| } | |
| export function detectPlatform(): PlatformInfo | null { | |
| const key = `${process.platform}-${process.arch}`; | |
| const binaryName = PLATFORM_BINARY_MAP[key]; | |
| if (!binaryName) { | |
| return null; | |
| } | |
| return { key, binaryName }; | |
| } | |
| export function getBinaryPath(binaryName?: string): string | null { | |
| const configuredBinaryPath = getUserConfiguredBinaryPath(); | |
| if (configuredBinaryPath) { | |
| return configuredBinaryPath; | |
| } | |
| const name = binaryName ?? detectPlatform()?.binaryName; | |
| if (!name) return null; | |
| return path.join(getLiteRtBinDir(), name); | |
| } | |
| export function getBinaryDownloadUrl(binaryName: string): string { | |
| return `${LITERT_RELEASE_BASE_URL}/${LITERT_RELEASE_VERSION}/${binaryName}`; | |
| } | |
| export function isBinaryInstalled(binaryPath = getBinaryPath()): boolean { | |
| if (!binaryPath) return false; | |
| return fs.existsSync(binaryPath); | |
| } | |
| export function isModelDownloaded(binaryPath: string): boolean { | |
| try { | |
| const output = execFileSync(binaryPath, ['list'], { | |
| encoding: 'utf-8', | |
| timeout: 10000, | |
| }); | |
| return output.includes(GEMMA_MODEL_NAME); | |
| } catch { | |
| return false; | |
| } | |
| } | |
| export async function isServerRunning(port: number): Promise<boolean> { | |
| try { | |
| const controller = new AbortController(); | |
| const timeout = setTimeout( | |
| () => controller.abort(), | |
| HEALTH_CHECK_TIMEOUT_MS, | |
| ); | |
| const response = await fetch( | |
| `http://localhost:${port}/${LITERT_API_VERSION}/models/${GEMMA_MODEL_NAME}:generateContent`, | |
| { method: 'POST', signal: controller.signal }, | |
| ); | |
| clearTimeout(timeout); | |
| // A 400 (bad request) confirms the route exists — the server recognises | |
| // the model endpoint. Only a 404 means "wrong server / wrong model". | |
| return response.status !== 404; | |
| } catch { | |
| return false; | |
| } | |
| } | |
| function isLiteRtServerProcessInfo( | |
| value: unknown, | |
| ): value is LiteRtServerProcessInfo { | |
| if (!value || typeof value !== 'object') { | |
| return false; | |
| } | |
| const isPositiveInteger = (candidate: unknown): candidate is number => | |
| typeof candidate === 'number' && | |
| Number.isInteger(candidate) && | |
| candidate > 0; | |
| const isNonEmptyString = (candidate: unknown): candidate is string => | |
| typeof candidate === 'string' && candidate.length > 0; | |
| const pid: unknown = Object.getOwnPropertyDescriptor(value, 'pid')?.value; | |
| if (!isPositiveInteger(pid)) { | |
| return false; | |
| } | |
| const binaryPath: unknown = Object.getOwnPropertyDescriptor( | |
| value, | |
| 'binaryPath', | |
| )?.value; | |
| if (binaryPath !== undefined && !isNonEmptyString(binaryPath)) { | |
| return false; | |
| } | |
| const port: unknown = Object.getOwnPropertyDescriptor(value, 'port')?.value; | |
| if (port !== undefined && !isPositiveInteger(port)) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| export function readServerProcessInfo(): LiteRtServerProcessInfo | null { | |
| const pidPath = getPidFilePath(); | |
| try { | |
| const content = fs.readFileSync(pidPath, 'utf-8').trim(); | |
| if (!content) { | |
| return null; | |
| } | |
| if (/^\d+$/.test(content)) { | |
| return { pid: parseInt(content, 10) }; | |
| } | |
| const parsed = JSON.parse(content) as unknown; | |
| return isLiteRtServerProcessInfo(parsed) ? parsed : null; | |
| } catch { | |
| return null; | |
| } | |
| } | |
| export function writeServerProcessInfo( | |
| processInfo: LiteRtServerProcessInfo, | |
| ): void { | |
| fs.writeFileSync(getPidFilePath(), JSON.stringify(processInfo), 'utf-8'); | |
| } | |
| export function readServerPid(): number | null { | |
| return readServerProcessInfo()?.pid ?? null; | |
| } | |
| function normalizeProcessValue(value: string): string { | |
| const normalized = value.replace(/\0/g, ' ').trim(); | |
| if (process.platform === 'win32') { | |
| return normalized.replace(/\\/g, '/').replace(/\s+/g, ' ').toLowerCase(); | |
| } | |
| return normalized.replace(/\s+/g, ' '); | |
| } | |
| function readProcessCommandLine(pid: number): string | null { | |
| try { | |
| if (process.platform === 'linux') { | |
| const output = fs.readFileSync(`/proc/${pid}/cmdline`, 'utf-8'); | |
| return output.trim() ? output : null; | |
| } | |
| if (process.platform === 'win32') { | |
| const output = execFileSync( | |
| 'powershell.exe', | |
| [ | |
| '-NoProfile', | |
| '-Command', | |
| `(Get-CimInstance Win32_Process -Filter "ProcessId = ${pid}").CommandLine`, | |
| ], | |
| { | |
| encoding: 'utf-8', | |
| timeout: 5000, | |
| }, | |
| ); | |
| return output.trim() || null; | |
| } | |
| const output = execFileSync('ps', ['-p', String(pid), '-o', 'command='], { | |
| encoding: 'utf-8', | |
| timeout: 5000, | |
| }); | |
| return output.trim() || null; | |
| } catch { | |
| return null; | |
| } | |
| } | |
| export function isExpectedLiteRtServerCommand( | |
| commandLine: string, | |
| options: { | |
| binaryPath?: string | null; | |
| port?: number; | |
| }, | |
| ): boolean { | |
| const normalizedCommandLine = normalizeProcessValue(commandLine); | |
| if (!normalizedCommandLine) { | |
| return false; | |
| } | |
| if (!/(^|\s|")serve(\s|$)/.test(normalizedCommandLine)) { | |
| return false; | |
| } | |
| if ( | |
| options.port !== undefined && | |
| !normalizedCommandLine.includes(`--port=${options.port}`) | |
| ) { | |
| return false; | |
| } | |
| if (!options.binaryPath) { | |
| return true; | |
| } | |
| const normalizedBinaryPath = normalizeProcessValue(options.binaryPath); | |
| const normalizedBinaryName = normalizeProcessValue( | |
| path.basename(options.binaryPath), | |
| ); | |
| return ( | |
| normalizedCommandLine.includes(normalizedBinaryPath) || | |
| normalizedCommandLine.includes(normalizedBinaryName) | |
| ); | |
| } | |
| export function isExpectedLiteRtServerProcess( | |
| pid: number, | |
| options: { | |
| binaryPath?: string | null; | |
| port?: number; | |
| }, | |
| ): boolean { | |
| const commandLine = readProcessCommandLine(pid); | |
| if (!commandLine) { | |
| return false; | |
| } | |
| return isExpectedLiteRtServerCommand(commandLine, options); | |
| } | |
| export function isProcessRunning(pid: number): boolean { | |
| try { | |
| process.kill(pid, 0); | |
| return true; | |
| } catch { | |
| return false; | |
| } | |
| } | |