From cc43b56c9a95fe0c8cb53c405e782ac29c92dbb4 Mon Sep 17 00:00:00 2001 From: "Thomas G. Lopes" Date: Tue, 3 Mar 2026 17:32:47 +0000 Subject: [PATCH] lsp tool --- pi/files/agent/extensions/lsp/.gitignore | 1 + pi/files/agent/extensions/lsp/lsp-core.ts | 1082 ++++++++ pi/files/agent/extensions/lsp/lsp-tool.ts | 394 +++ pi/files/agent/extensions/lsp/lsp.ts | 586 ++++ pi/files/agent/extensions/lsp/package.json | 23 + pi/files/agent/extensions/lsp/pnpm-lock.yaml | 2499 ++++++++++++++++++ pi/files/agent/extensions/lsp/tsconfig.json | 13 + 7 files changed, 4598 insertions(+) create mode 100644 pi/files/agent/extensions/lsp/.gitignore create mode 100644 pi/files/agent/extensions/lsp/lsp-core.ts create mode 100644 pi/files/agent/extensions/lsp/lsp-tool.ts create mode 100644 pi/files/agent/extensions/lsp/lsp.ts create mode 100644 pi/files/agent/extensions/lsp/package.json create mode 100644 pi/files/agent/extensions/lsp/pnpm-lock.yaml create mode 100644 pi/files/agent/extensions/lsp/tsconfig.json diff --git a/pi/files/agent/extensions/lsp/.gitignore b/pi/files/agent/extensions/lsp/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/pi/files/agent/extensions/lsp/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/pi/files/agent/extensions/lsp/lsp-core.ts b/pi/files/agent/extensions/lsp/lsp-core.ts new file mode 100644 index 0000000..9d18f5d --- /dev/null +++ b/pi/files/agent/extensions/lsp/lsp-core.ts @@ -0,0 +1,1082 @@ +/** + * LSP Core - Language Server Protocol client management + */ +import { spawn, type ChildProcessWithoutNullStreams } from "node:child_process"; +import * as path from "node:path"; +import * as fs from "node:fs"; +import { pathToFileURL, fileURLToPath } from "node:url"; +import { + createMessageConnection, + StreamMessageReader, + StreamMessageWriter, + type MessageConnection, + InitializeRequest, + InitializedNotification, + DidOpenTextDocumentNotification, + DidChangeTextDocumentNotification, + DidCloseTextDocumentNotification, + DidSaveTextDocumentNotification, + PublishDiagnosticsNotification, + DocumentDiagnosticRequest, + WorkspaceDiagnosticRequest, + DefinitionRequest, + ReferencesRequest, + HoverRequest, + SignatureHelpRequest, + DocumentSymbolRequest, + RenameRequest, + CodeActionRequest, +} from "vscode-languageserver-protocol/node.js"; +import { + type Diagnostic, + type Location, + type LocationLink, + type DocumentSymbol, + type SymbolInformation, + type Hover, + type SignatureHelp, + type WorkspaceEdit, + type CodeAction, + type Command, + DiagnosticSeverity, + CodeActionKind, + DocumentDiagnosticReportKind, +} from "vscode-languageserver-protocol"; + +// Config +const INIT_TIMEOUT_MS = 30000; +const MAX_OPEN_FILES = 30; +const IDLE_TIMEOUT_MS = 60_000; +const CLEANUP_INTERVAL_MS = 30_000; + +export const LANGUAGE_IDS: Record = { + ".dart": "dart", + ".ts": "typescript", + ".tsx": "typescriptreact", + ".js": "javascript", + ".jsx": "javascriptreact", + ".mjs": "javascript", + ".cjs": "javascript", + ".mts": "typescript", + ".cts": "typescript", + ".vue": "vue", + ".svelte": "svelte", + ".astro": "astro", + ".py": "python", + ".pyi": "python", + ".go": "go", + ".rs": "rust", +}; + +// Types +interface LSPServerConfig { + id: string; + extensions: string[]; + findRoot: (file: string, cwd: string) => string | undefined; + spawn: (root: string) => Promise<{ process: ChildProcessWithoutNullStreams; initOptions?: Record } | undefined>; +} + +interface OpenFile { + version: number; + lastAccess: number; +} + +interface LSPClient { + connection: MessageConnection; + process: ChildProcessWithoutNullStreams; + diagnostics: Map; + openFiles: Map; + listeners: Map void>>; + stderr: string[]; + capabilities?: unknown; + root: string; + closed: boolean; +} + +export interface FileDiagnosticItem { + file: string; + diagnostics: Diagnostic[]; + status: "ok" | "timeout" | "error" | "unsupported"; + error?: string; +} + +export interface FileDiagnosticsResult { + items: FileDiagnosticItem[]; +} + +// Utilities +const SEARCH_PATHS = [ + ...(process.env.PATH?.split(path.delimiter) || []), + "/usr/local/bin", + "/opt/homebrew/bin", + `${process.env.HOME}/.pub-cache/bin`, + `${process.env.HOME}/fvm/default/bin`, + `${process.env.HOME}/go/bin`, + `${process.env.HOME}/.cargo/bin`, +]; + +function which(cmd: string): string | undefined { + const ext = process.platform === "win32" ? ".exe" : ""; + for (const dir of SEARCH_PATHS) { + const full = path.join(dir, cmd + ext); + try { + if (fs.existsSync(full) && fs.statSync(full).isFile()) return full; + } catch {} + } +} + +function normalizeFsPath(p: string): string { + try { + return fs.realpathSync(p); + } catch { + return p; + } +} + +function findNearestFile(startDir: string, targets: string[], stopDir: string): string | undefined { + let current = path.resolve(startDir); + const stop = path.resolve(stopDir); + while (current.length >= stop.length) { + for (const t of targets) { + const candidate = path.join(current, t); + if (fs.existsSync(candidate)) return candidate; + } + const parent = path.dirname(current); + if (parent === current) break; + current = parent; + } +} + +function findRoot(file: string, cwd: string, markers: string[]): string | undefined { + const found = findNearestFile(path.dirname(file), markers, cwd); + return found ? path.dirname(found) : undefined; +} + +function timeout(promise: Promise, ms: number, name: string): Promise { + return new Promise((resolve, reject) => { + const timer = setTimeout(() => reject(new Error(`${name} timed out`)), ms); + promise.then( + (r) => { + clearTimeout(timer); + resolve(r); + }, + (e) => { + clearTimeout(timer); + reject(e); + } + ); + }); +} + +function simpleSpawn(bin: string, args: string[] = ["--stdio"]) { + return async (root: string) => { + const cmd = which(bin); + if (!cmd) return undefined; + return { process: spawn(cmd, args, { cwd: root, stdio: ["pipe", "pipe", "pipe"] }) }; + }; +} + +async function spawnChecked(cmd: string, args: string[], cwd: string): Promise { + try { + const child = spawn(cmd, args, { cwd, stdio: ["pipe", "pipe", "pipe"] }); + + return await new Promise((resolve) => { + let settled = false; + + const cleanup = () => { + child.removeListener("exit", onExit); + child.removeListener("error", onError); + }; + + let timer: NodeJS.Timeout | null = null; + + const finish = (value: ChildProcessWithoutNullStreams | undefined) => { + if (settled) return; + settled = true; + if (timer) clearTimeout(timer); + cleanup(); + resolve(value); + }; + + const onExit = () => finish(undefined); + const onError = () => finish(undefined); + + child.once("exit", onExit); + child.once("error", onError); + + timer = setTimeout(() => finish(child), 200); + (timer as NodeJS.Timeout & { unref?: () => void }).unref?.(); + }); + } catch { + return undefined; + } +} + +async function spawnWithFallback(cmd: string, argsVariants: string[][], cwd: string): Promise { + for (const args of argsVariants) { + const child = await spawnChecked(cmd, args, cwd); + if (child) return child; + } + return undefined; +} + +// Server Configs +export const LSP_SERVERS: LSPServerConfig[] = [ + { + id: "dart", + extensions: [".dart"], + findRoot: (f, cwd) => findRoot(f, cwd, ["pubspec.yaml", "analysis_options.yaml"]), + spawn: async (root) => { + let dart = which("dart"); + const pubspec = path.join(root, "pubspec.yaml"); + if (fs.existsSync(pubspec)) { + try { + const content = fs.readFileSync(pubspec, "utf-8"); + if (content.includes("flutter:") || content.includes("sdk: flutter")) { + const flutter = which("flutter"); + if (flutter) { + const dir = path.dirname(fs.realpathSync(flutter)); + for (const p of ["cache/dart-sdk/bin/dart", "../cache/dart-sdk/bin/dart"]) { + const c = path.join(dir, p); + if (fs.existsSync(c)) { + dart = c; + break; + } + } + } + } + } catch {} + } + if (!dart) return undefined; + return { process: spawn(dart, ["language-server", "--protocol=lsp"], { cwd: root, stdio: ["pipe", "pipe", "pipe"] }) }; + }, + }, + { + id: "typescript", + extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"], + findRoot: (f, cwd) => { + // Skip if this is a Deno project + if (findNearestFile(path.dirname(f), ["deno.json", "deno.jsonc"], cwd)) return undefined; + return findRoot(f, cwd, ["package.json", "tsconfig.json", "jsconfig.json"]); + }, + spawn: async (root) => { + // Prefer tsgo (TypeScript Go) - much faster + const tsgo = which("tsgo"); + if (tsgo) { + const proc = await spawnChecked(tsgo, ["--lsp", "--stdio"], root); + if (proc) return { process: proc }; + } + + // Fall back to typescript-language-server + const local = path.join(root, "node_modules/.bin/typescript-language-server"); + const cmd = fs.existsSync(local) ? local : which("typescript-language-server"); + if (!cmd) return undefined; + return { process: spawn(cmd, ["--stdio"], { cwd: root, stdio: ["pipe", "pipe", "pipe"] }) }; + }, + }, + { + id: "vue", + extensions: [".vue"], + findRoot: (f, cwd) => findRoot(f, cwd, ["package.json", "vite.config.ts", "vite.config.js"]), + spawn: simpleSpawn("vue-language-server"), + }, + { + id: "svelte", + extensions: [".svelte"], + findRoot: (f, cwd) => findRoot(f, cwd, ["package.json", "svelte.config.js"]), + spawn: simpleSpawn("svelteserver"), + }, + { + id: "pyright", + extensions: [".py", ".pyi"], + findRoot: (f, cwd) => findRoot(f, cwd, ["pyproject.toml", "setup.py", "requirements.txt", "pyrightconfig.json"]), + spawn: simpleSpawn("pyright-langserver"), + }, + { + id: "gopls", + extensions: [".go"], + findRoot: (f, cwd) => findRoot(f, cwd, ["go.work"]) || findRoot(f, cwd, ["go.mod"]), + spawn: simpleSpawn("gopls", []), + }, + { + id: "rust-analyzer", + extensions: [".rs"], + findRoot: (f, cwd) => findRoot(f, cwd, ["Cargo.toml"]), + spawn: simpleSpawn("rust-analyzer", []), + }, +]; + +// Singleton Manager +let sharedManager: LSPManager | null = null; +let managerCwd: string | null = null; + +export function getOrCreateManager(cwd: string): LSPManager { + if (!sharedManager || managerCwd !== cwd) { + sharedManager?.shutdown().catch(() => {}); + sharedManager = new LSPManager(cwd); + managerCwd = cwd; + } + return sharedManager; +} + +export function getManager(): LSPManager | null { + return sharedManager; +} + +export async function shutdownManager(): Promise { + const manager = sharedManager; + if (!manager) return; + + sharedManager = null; + managerCwd = null; + + await manager.shutdown(); +} + +// LSP Manager +export class LSPManager { + private clients = new Map(); + private spawning = new Map>(); + private broken = new Set(); + private cwd: string; + private cleanupTimer: NodeJS.Timeout | null = null; + + constructor(cwd: string) { + this.cwd = cwd; + this.cleanupTimer = setInterval(() => this.cleanupIdleFiles(), CLEANUP_INTERVAL_MS); + this.cleanupTimer.unref(); + } + + private cleanupIdleFiles() { + const now = Date.now(); + for (const client of this.clients.values()) { + for (const [fp, state] of client.openFiles) { + if (now - state.lastAccess > IDLE_TIMEOUT_MS) this.closeFile(client, fp); + } + } + } + + private closeFile(client: LSPClient, absPath: string) { + if (!client.openFiles.has(absPath)) return; + client.openFiles.delete(absPath); + if (client.closed) return; + try { + void client.connection + .sendNotification(DidCloseTextDocumentNotification.type, { + textDocument: { uri: pathToFileURL(absPath).href }, + }) + .catch(() => {}); + } catch {} + } + + private evictLRU(client: LSPClient) { + if (client.openFiles.size <= MAX_OPEN_FILES) return; + let oldest: { path: string; time: number } | null = null; + for (const [fp, s] of client.openFiles) { + if (!oldest || s.lastAccess < oldest.time) oldest = { path: fp, time: s.lastAccess }; + } + if (oldest) this.closeFile(client, oldest.path); + } + + private key(id: string, root: string) { + return `${id}:${root}`; + } + + private async initClient(config: LSPServerConfig, root: string): Promise { + const k = this.key(config.id, root); + try { + const handle = await config.spawn(root); + if (!handle) { + this.broken.add(k); + return undefined; + } + + const reader = new StreamMessageReader(handle.process.stdout!); + const writer = new StreamMessageWriter(handle.process.stdin!); + const conn = createMessageConnection(reader, writer); + + handle.process.stdin?.on("error", () => {}); + handle.process.stdout?.on("error", () => {}); + + const stderr: string[] = []; + const MAX_STDERR_LINES = 200; + handle.process.stderr?.on("data", (chunk: Buffer) => { + try { + const text = chunk.toString("utf-8"); + for (const line of text.split(/\r?\n/)) { + if (!line.trim()) continue; + stderr.push(line); + if (stderr.length > MAX_STDERR_LINES) stderr.splice(0, stderr.length - MAX_STDERR_LINES); + } + } catch {} + }); + handle.process.stderr?.on("error", () => {}); + + const client: LSPClient = { + connection: conn, + process: handle.process, + diagnostics: new Map(), + openFiles: new Map(), + listeners: new Map(), + stderr, + root, + closed: false, + }; + + conn.onNotification("textDocument/publishDiagnostics", (params: { uri: string; diagnostics: Diagnostic[] }) => { + const fpRaw = decodeURIComponent(new URL(params.uri).pathname); + const fp = normalizeFsPath(fpRaw); + + client.diagnostics.set(fp, params.diagnostics); + + const listeners1 = client.listeners.get(fp); + const listeners2 = fp !== fpRaw ? client.listeners.get(fpRaw) : undefined; + + listeners1?.slice().forEach((fn) => { + try { + fn(); + } catch {} + }); + listeners2?.slice().forEach((fn) => { + try { + fn(); + } catch {} + }); + }); + + conn.onError(() => {}); + conn.onClose(() => { + client.closed = true; + this.clients.delete(k); + }); + + conn.onRequest("workspace/configuration", () => [handle.initOptions ?? {}]); + conn.onRequest("window/workDoneProgress/create", () => null); + conn.onRequest("client/registerCapability", () => {}); + conn.onRequest("client/unregisterCapability", () => {}); + conn.onRequest("workspace/workspaceFolders", () => [{ name: "workspace", uri: pathToFileURL(root).href }]); + + handle.process.on("exit", () => { + client.closed = true; + this.clients.delete(k); + }); + handle.process.on("error", () => { + client.closed = true; + this.clients.delete(k); + this.broken.add(k); + }); + + conn.listen(); + + const initResult = await timeout( + conn.sendRequest(InitializeRequest.method, { + rootUri: pathToFileURL(root).href, + rootPath: root, + processId: process.pid, + workspaceFolders: [{ name: "workspace", uri: pathToFileURL(root).href }], + initializationOptions: handle.initOptions ?? {}, + capabilities: { + window: { workDoneProgress: true }, + workspace: { configuration: true }, + textDocument: { + synchronization: { didSave: true, didOpen: true, didChange: true, didClose: true }, + publishDiagnostics: { versionSupport: true }, + diagnostic: { dynamicRegistration: false, relatedDocumentSupport: false }, + }, + }, + }), + INIT_TIMEOUT_MS, + `${config.id} init` + ); + + client.capabilities = (initResult as { capabilities?: unknown })?.capabilities; + + conn.sendNotification(InitializedNotification.type, {}); + if (handle.initOptions) { + conn.sendNotification("workspace/didChangeConfiguration", { settings: handle.initOptions }); + } + return client; + } catch { + this.broken.add(k); + return undefined; + } + } + + async getClientsForFile(filePath: string): Promise { + const ext = path.extname(filePath); + const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(this.cwd, filePath); + const clients: LSPClient[] = []; + + for (const config of LSP_SERVERS) { + if (!config.extensions.includes(ext)) continue; + const root = config.findRoot(absPath, this.cwd); + if (!root) continue; + const k = this.key(config.id, root); + if (this.broken.has(k)) continue; + + const existing = this.clients.get(k); + if (existing) { + clients.push(existing); + continue; + } + + if (!this.spawning.has(k)) { + const p = this.initClient(config, root); + this.spawning.set(k, p); + p.finally(() => this.spawning.delete(k)); + } + const client = await this.spawning.get(k); + if (client) { + this.clients.set(k, client); + clients.push(client); + } + } + return clients; + } + + private resolve(fp: string) { + const abs = path.isAbsolute(fp) ? fp : path.resolve(this.cwd, fp); + return normalizeFsPath(abs); + } + + private langId(fp: string) { + return LANGUAGE_IDS[path.extname(fp)] || "plaintext"; + } + + private readFile(fp: string): string | null { + try { + return fs.readFileSync(fp, "utf-8"); + } catch { + return null; + } + } + + private explainNoLsp(absPath: string): string { + const ext = path.extname(absPath); + return `No LSP for ${ext}`; + } + + private toPos(line: number, col: number) { + return { line: Math.max(0, line - 1), character: Math.max(0, col - 1) }; + } + + private normalizeLocs(result: Location | Location[] | LocationLink[] | null | undefined): Location[] { + if (!result) return []; + const items = Array.isArray(result) ? result : [result]; + if (!items.length) return []; + if ("uri" in items[0] && "range" in items[0]) return items as Location[]; + return (items as LocationLink[]).map((l) => ({ uri: l.targetUri, range: l.targetSelectionRange ?? l.targetRange })); + } + + private normalizeSymbols(result: DocumentSymbol[] | SymbolInformation[] | null | undefined): DocumentSymbol[] { + if (!result?.length) return []; + const first = result[0]; + if ("location" in first) { + return (result as SymbolInformation[]).map((s) => ({ + name: s.name, + kind: s.kind, + range: s.location.range, + selectionRange: s.location.range, + detail: s.containerName, + tags: s.tags, + deprecated: s.deprecated, + children: [], + })); + } + return result as DocumentSymbol[]; + } + + private async openOrUpdate(clients: LSPClient[], absPath: string, uri: string, langId: string, content: string, evict = true) { + const now = Date.now(); + for (const client of clients) { + if (client.closed) continue; + const state = client.openFiles.get(absPath); + try { + if (state) { + const v = state.version + 1; + client.openFiles.set(absPath, { version: v, lastAccess: now }); + void client.connection + .sendNotification(DidChangeTextDocumentNotification.type, { + textDocument: { uri, version: v }, + contentChanges: [{ text: content }], + }) + .catch(() => {}); + } else { + client.openFiles.set(absPath, { version: 1, lastAccess: now }); + void client.connection + .sendNotification(DidOpenTextDocumentNotification.type, { + textDocument: { uri, languageId: langId, version: 0, text: content }, + }) + .catch(() => {}); + void client.connection + .sendNotification(DidChangeTextDocumentNotification.type, { + textDocument: { uri, version: 1 }, + contentChanges: [{ text: content }], + }) + .catch(() => {}); + if (evict) this.evictLRU(client); + } + void client.connection + .sendNotification(DidSaveTextDocumentNotification.type, { + textDocument: { uri }, + text: content, + }) + .catch(() => {}); + } catch {} + } + } + + private async loadFile(filePath: string) { + const absPath = this.resolve(filePath); + const clients = await this.getClientsForFile(absPath); + if (!clients.length) return null; + const content = this.readFile(absPath); + if (content === null) return null; + return { clients, absPath, uri: pathToFileURL(absPath).href, langId: this.langId(absPath), content }; + } + + private waitForDiagnostics(client: LSPClient, absPath: string, timeoutMs: number, isNew: boolean): Promise { + return new Promise((resolve) => { + if (client.closed) return resolve(false); + + let resolved = false; + let settleTimer: NodeJS.Timeout | null = null; + let listener: () => void = () => {}; + + const cleanupListener = () => { + const listeners = client.listeners.get(absPath); + if (!listeners) return; + const idx = listeners.indexOf(listener); + if (idx !== -1) listeners.splice(idx, 1); + if (listeners.length === 0) client.listeners.delete(absPath); + }; + + const finish = (value: boolean) => { + if (resolved) return; + resolved = true; + if (settleTimer) clearTimeout(settleTimer); + clearTimeout(timer); + cleanupListener(); + resolve(value); + }; + + listener = () => { + if (resolved) return; + + const current = client.diagnostics.get(absPath); + if (current && current.length > 0) return finish(true); + + if (!isNew) return finish(true); + + if (settleTimer) clearTimeout(settleTimer); + settleTimer = setTimeout(() => finish(true), 2500); + (settleTimer as NodeJS.Timeout & { unref?: () => void }).unref?.(); + }; + + const timer = setTimeout(() => finish(false), timeoutMs); + (timer as NodeJS.Timeout & { unref?: () => void }).unref?.(); + + const listeners = client.listeners.get(absPath) || []; + listeners.push(listener); + client.listeners.set(absPath, listeners); + }); + } + + private async pullDiagnostics(client: LSPClient, absPath: string, uri: string): Promise<{ diagnostics: Diagnostic[]; responded: boolean }> { + if (client.closed) return { diagnostics: [], responded: false }; + + if (!client.capabilities || !(client.capabilities as { diagnosticProvider?: unknown }).diagnosticProvider) { + return { diagnostics: [], responded: false }; + } + + try { + const res = (await client.connection.sendRequest(DocumentDiagnosticRequest.method, { + textDocument: { uri }, + })) as { kind?: string; items?: Diagnostic[] }; + + if (res?.kind === DocumentDiagnosticReportKind.Full) { + return { diagnostics: Array.isArray(res.items) ? res.items : [], responded: true }; + } + if (res?.kind === DocumentDiagnosticReportKind.Unchanged) { + return { diagnostics: client.diagnostics.get(absPath) || [], responded: true }; + } + if (Array.isArray(res?.items)) { + return { diagnostics: res.items, responded: true }; + } + return { diagnostics: [], responded: true }; + } catch {} + + try { + const res = (await client.connection.sendRequest(WorkspaceDiagnosticRequest.method, { + previousResultIds: [], + })) as { items?: Array<{ uri?: string; kind?: string; items?: Diagnostic[] }> }; + + const items = res?.items || []; + const match = items.find((it) => it?.uri === uri); + if (match?.kind === DocumentDiagnosticReportKind.Full) { + return { diagnostics: Array.isArray(match.items) ? match.items : [], responded: true }; + } + if (Array.isArray(match?.items)) { + return { diagnostics: match.items, responded: true }; + } + return { diagnostics: [], responded: true }; + } catch { + return { diagnostics: [], responded: false }; + } + } + + async touchFileAndWait(filePath: string, timeoutMs: number): Promise<{ diagnostics: Diagnostic[]; receivedResponse: boolean; unsupported?: boolean; error?: string }> { + const absPath = this.resolve(filePath); + + if (!fs.existsSync(absPath)) { + return { diagnostics: [], receivedResponse: false, unsupported: true, error: "File not found" }; + } + + const clients = await this.getClientsForFile(absPath); + if (!clients.length) { + return { diagnostics: [], receivedResponse: false, unsupported: true, error: this.explainNoLsp(absPath) }; + } + + const content = this.readFile(absPath); + if (content === null) { + return { diagnostics: [], receivedResponse: false, unsupported: true, error: "Could not read file" }; + } + + const uri = pathToFileURL(absPath).href; + const langId = this.langId(absPath); + const isNew = clients.some((c) => !c.openFiles.has(absPath)); + + const waits = clients.map((c) => this.waitForDiagnostics(c, absPath, timeoutMs, isNew)); + await this.openOrUpdate(clients, absPath, uri, langId, content); + const results = await Promise.all(waits); + + let responded = results.some((r) => r); + const diags: Diagnostic[] = []; + for (const c of clients) { + const d = c.diagnostics.get(absPath); + if (d) diags.push(...d); + } + if (!responded && clients.some((c) => c.diagnostics.has(absPath))) responded = true; + + if (!responded || diags.length === 0) { + const pulled = await Promise.all(clients.map((c) => this.pullDiagnostics(c, absPath, uri))); + for (let i = 0; i < clients.length; i++) { + const r = pulled[i]; + if (r.responded) responded = true; + if (r.diagnostics.length) { + clients[i].diagnostics.set(absPath, r.diagnostics); + diags.push(...r.diagnostics); + } + } + } + + return { diagnostics: diags, receivedResponse: responded }; + } + + async getDiagnosticsForFiles(files: string[], timeoutMs: number): Promise { + const unique = [...new Set(files.map((f) => this.resolve(f)))]; + const results: FileDiagnosticItem[] = []; + const toClose: Map = new Map(); + + for (const absPath of unique) { + if (!fs.existsSync(absPath)) { + results.push({ file: absPath, diagnostics: [], status: "error", error: "File not found" }); + continue; + } + + let clients: LSPClient[]; + try { + clients = await this.getClientsForFile(absPath); + } catch (e) { + results.push({ file: absPath, diagnostics: [], status: "error", error: String(e) }); + continue; + } + + if (!clients.length) { + results.push({ file: absPath, diagnostics: [], status: "unsupported", error: this.explainNoLsp(absPath) }); + continue; + } + + const content = this.readFile(absPath); + if (!content) { + results.push({ file: absPath, diagnostics: [], status: "error", error: "Could not read file" }); + continue; + } + + const uri = pathToFileURL(absPath).href; + const langId = this.langId(absPath); + const isNew = clients.some((c) => !c.openFiles.has(absPath)); + + for (const c of clients) { + if (!c.openFiles.has(absPath)) { + if (!toClose.has(c)) toClose.set(c, []); + toClose.get(c)!.push(absPath); + } + } + + const waits = clients.map((c) => this.waitForDiagnostics(c, absPath, timeoutMs, isNew)); + await this.openOrUpdate(clients, absPath, uri, langId, content, false); + const waitResults = await Promise.all(waits); + + const diags: Diagnostic[] = []; + for (const c of clients) { + const d = c.diagnostics.get(absPath); + if (d) diags.push(...d); + } + + let responded = waitResults.some((r) => r) || diags.length > 0; + + if (!responded || diags.length === 0) { + const pulled = await Promise.all(clients.map((c) => this.pullDiagnostics(c, absPath, uri))); + for (let i = 0; i < clients.length; i++) { + const r = pulled[i]; + if (r.responded) responded = true; + if (r.diagnostics.length) { + clients[i].diagnostics.set(absPath, r.diagnostics); + diags.push(...r.diagnostics); + } + } + } + + if (!responded && !diags.length) { + results.push({ file: absPath, diagnostics: [], status: "timeout", error: "LSP did not respond" }); + } else { + results.push({ file: absPath, diagnostics: diags, status: "ok" }); + } + } + + for (const [c, fps] of toClose) { + for (const fp of fps) this.closeFile(c, fp); + } + for (const c of this.clients.values()) { + while (c.openFiles.size > MAX_OPEN_FILES) this.evictLRU(c); + } + + return { items: results }; + } + + async getDefinition(fp: string, line: number, col: number): Promise { + const l = await this.loadFile(fp); + if (!l) return []; + await this.openOrUpdate(l.clients, l.absPath, l.uri, l.langId, l.content); + const pos = this.toPos(line, col); + const results = await Promise.all( + l.clients.map(async (c) => { + if (c.closed) return []; + try { + return this.normalizeLocs(await c.connection.sendRequest(DefinitionRequest.type, { textDocument: { uri: l.uri }, position: pos })); + } catch { + return []; + } + }) + ); + return results.flat(); + } + + async getReferences(fp: string, line: number, col: number): Promise { + const l = await this.loadFile(fp); + if (!l) return []; + await this.openOrUpdate(l.clients, l.absPath, l.uri, l.langId, l.content); + const pos = this.toPos(line, col); + const results = await Promise.all( + l.clients.map(async (c) => { + if (c.closed) return []; + try { + return this.normalizeLocs(await c.connection.sendRequest(ReferencesRequest.type, { textDocument: { uri: l.uri }, position: pos, context: { includeDeclaration: true } })); + } catch { + return []; + } + }) + ); + return results.flat(); + } + + async getHover(fp: string, line: number, col: number): Promise { + const l = await this.loadFile(fp); + if (!l) return null; + await this.openOrUpdate(l.clients, l.absPath, l.uri, l.langId, l.content); + const pos = this.toPos(line, col); + for (const c of l.clients) { + if (c.closed) continue; + try { + const r = await c.connection.sendRequest(HoverRequest.type, { textDocument: { uri: l.uri }, position: pos }); + if (r) return r; + } catch {} + } + return null; + } + + async getSignatureHelp(fp: string, line: number, col: number): Promise { + const l = await this.loadFile(fp); + if (!l) return null; + await this.openOrUpdate(l.clients, l.absPath, l.uri, l.langId, l.content); + const pos = this.toPos(line, col); + for (const c of l.clients) { + if (c.closed) continue; + try { + const r = await c.connection.sendRequest(SignatureHelpRequest.type, { textDocument: { uri: l.uri }, position: pos }); + if (r) return r; + } catch {} + } + return null; + } + + async getDocumentSymbols(fp: string): Promise { + const l = await this.loadFile(fp); + if (!l) return []; + await this.openOrUpdate(l.clients, l.absPath, l.uri, l.langId, l.content); + const results = await Promise.all( + l.clients.map(async (c) => { + if (c.closed) return []; + try { + return this.normalizeSymbols(await c.connection.sendRequest(DocumentSymbolRequest.type, { textDocument: { uri: l.uri } })); + } catch { + return []; + } + }) + ); + return results.flat(); + } + + async rename(fp: string, line: number, col: number, newName: string): Promise { + const l = await this.loadFile(fp); + if (!l) return null; + await this.openOrUpdate(l.clients, l.absPath, l.uri, l.langId, l.content); + const pos = this.toPos(line, col); + for (const c of l.clients) { + if (c.closed) continue; + try { + const r = await c.connection.sendRequest(RenameRequest.type, { + textDocument: { uri: l.uri }, + position: pos, + newName, + }); + if (r) return r; + } catch {} + } + return null; + } + + async getCodeActions(fp: string, startLine: number, startCol: number, endLine?: number, endCol?: number): Promise<(CodeAction | Command)[]> { + const l = await this.loadFile(fp); + if (!l) return []; + await this.openOrUpdate(l.clients, l.absPath, l.uri, l.langId, l.content); + + const start = this.toPos(startLine, startCol); + const end = this.toPos(endLine ?? startLine, endCol ?? startCol); + const range = { start, end }; + + const diagnostics: Diagnostic[] = []; + for (const c of l.clients) { + const fileDiags = c.diagnostics.get(l.absPath) || []; + for (const d of fileDiags) { + if (this.rangesOverlap(d.range, range)) diagnostics.push(d); + } + } + + const results = await Promise.all( + l.clients.map(async (c) => { + if (c.closed) return []; + try { + const r = await c.connection.sendRequest(CodeActionRequest.type, { + textDocument: { uri: l.uri }, + range, + context: { diagnostics, only: [CodeActionKind.QuickFix, CodeActionKind.Refactor, CodeActionKind.Source] }, + }); + return r || []; + } catch { + return []; + } + }) + ); + return results.flat(); + } + + private rangesOverlap( + a: { start: { line: number; character: number }; end: { line: number; character: number } }, + b: { start: { line: number; character: number }; end: { line: number; character: number } } + ): boolean { + if (a.end.line < b.start.line || b.end.line < a.start.line) return false; + if (a.end.line === b.start.line && a.end.character < b.start.character) return false; + if (b.end.line === a.start.line && b.end.character < a.start.character) return false; + return true; + } + + async shutdown() { + if (this.cleanupTimer) { + clearInterval(this.cleanupTimer); + this.cleanupTimer = null; + } + const clients = Array.from(this.clients.values()); + this.clients.clear(); + for (const c of clients) { + const wasClosed = c.closed; + c.closed = true; + if (!wasClosed) { + try { + await Promise.race([c.connection.sendRequest("shutdown"), new Promise((r) => setTimeout(r, 1000))]); + } catch {} + try { + void c.connection.sendNotification("exit").catch(() => {}); + } catch {} + } + try { + c.connection.end(); + } catch {} + try { + c.process.kill(); + } catch {} + } + } +} + +// Diagnostic Formatting +export { DiagnosticSeverity }; +export type SeverityFilter = "all" | "error" | "warning" | "info" | "hint"; + +export function formatDiagnostic(d: Diagnostic): string { + const sev = ["", "ERROR", "WARN", "INFO", "HINT"][d.severity || 1]; + return `${sev} [${d.range.start.line + 1}:${d.range.start.character + 1}] ${d.message}`; +} + +export function filterDiagnosticsBySeverity(diags: Diagnostic[], filter: SeverityFilter): Diagnostic[] { + if (filter === "all") return diags; + const max = { error: 1, warning: 2, info: 3, hint: 4 }[filter]; + return diags.filter((d) => (d.severity || 1) <= max); +} + +// URI utilities +export function uriToPath(uri: string): string { + if (uri.startsWith("file://")) + try { + return fileURLToPath(uri); + } catch {} + return uri; +} + +// Symbol search +export function findSymbolPosition(symbols: DocumentSymbol[], query: string): { line: number; character: number } | null { + const q = query.toLowerCase(); + let exact: { line: number; character: number } | null = null; + let partial: { line: number; character: number } | null = null; + + const visit = (items: DocumentSymbol[]) => { + for (const sym of items) { + const name = String(sym?.name ?? "").toLowerCase(); + const pos = sym?.selectionRange?.start ?? sym?.range?.start; + if (pos && typeof pos.line === "number" && typeof pos.character === "number") { + if (!exact && name === q) exact = pos; + if (!partial && name.includes(q)) partial = pos; + } + if (sym?.children?.length) visit(sym.children); + } + }; + visit(symbols); + return exact ?? partial; +} + +export async function resolvePosition(manager: LSPManager, file: string, query: string): Promise<{ line: number; column: number } | null> { + const symbols = await manager.getDocumentSymbols(file); + const pos = findSymbolPosition(symbols, query); + return pos ? { line: pos.line + 1, column: pos.character + 1 } : null; +} diff --git a/pi/files/agent/extensions/lsp/lsp-tool.ts b/pi/files/agent/extensions/lsp/lsp-tool.ts new file mode 100644 index 0000000..73753c5 --- /dev/null +++ b/pi/files/agent/extensions/lsp/lsp-tool.ts @@ -0,0 +1,394 @@ +/** + * LSP Tool Extension + * + * Provides Language Server Protocol tool for: + * - definitions, references, hover, signature help + * - document symbols, diagnostics, workspace diagnostics + * - rename, code actions + * + * Supported languages: + * - Dart/Flutter (dart language-server) + * - TypeScript/JavaScript (tsgo --lsp or typescript-language-server) + * - Vue (vue-language-server) + * - Svelte (svelteserver) + * - Python (pyright-langserver) + * - Go (gopls) + * - Rust (rust-analyzer) + */ + +import * as path from "node:path"; +import { Type, type Static } from "@sinclair/typebox"; +import { StringEnum } from "@mariozechner/pi-ai"; +import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; +import { Text } from "@mariozechner/pi-tui"; +import type { SignatureHelp, WorkspaceEdit, CodeAction, Command } from "vscode-languageserver-protocol"; +import { getOrCreateManager, shutdownManager, formatDiagnostic, filterDiagnosticsBySeverity, uriToPath, resolvePosition, type SeverityFilter } from "./lsp-core.js"; + +const PREVIEW_LINES = 10; +const DIAGNOSTICS_WAIT_MS_DEFAULT = 3000; + +function diagnosticsWaitMsForFile(filePath: string): number { + const ext = path.extname(filePath).toLowerCase(); + if (ext === ".rs") return 20000; + return DIAGNOSTICS_WAIT_MS_DEFAULT; +} + +const ACTIONS = ["definition", "references", "hover", "symbols", "diagnostics", "workspace-diagnostics", "signature", "rename", "codeAction", "restart"] as const; +const SEVERITY_FILTERS = ["all", "error", "warning", "info", "hint"] as const; + +const LspParams = Type.Object({ + action: StringEnum(ACTIONS), + file: Type.Optional(Type.String({ description: "File path (required for most actions)" })), + files: Type.Optional(Type.Array(Type.String(), { description: "File paths for workspace-diagnostics" })), + line: Type.Optional(Type.Number({ description: "Line (1-indexed). Required for position-based actions unless query provided." })), + column: Type.Optional(Type.Number({ description: "Column (1-indexed). Required for position-based actions unless query provided." })), + endLine: Type.Optional(Type.Number({ description: "End line for range-based actions (codeAction)" })), + endColumn: Type.Optional(Type.Number({ description: "End column for range-based actions (codeAction)" })), + query: Type.Optional(Type.String({ description: "Symbol name filter (for symbols) or to resolve position (for definition/references/hover/signature)" })), + newName: Type.Optional(Type.String({ description: "New name for rename action" })), + severity: Type.Optional(StringEnum(SEVERITY_FILTERS, { description: 'Filter diagnostics: "all"|"error"|"warning"|"info"|"hint"' })), +}); + +type LspParamsType = Static; + +function abortable(promise: Promise, signal?: AbortSignal): Promise { + if (!signal) return promise; + if (signal.aborted) return Promise.reject(new Error("aborted")); + + return new Promise((resolve, reject) => { + const onAbort = () => { + cleanup(); + reject(new Error("aborted")); + }; + + const cleanup = () => { + signal.removeEventListener("abort", onAbort); + }; + + signal.addEventListener("abort", onAbort, { once: true }); + + promise.then( + (value) => { + cleanup(); + resolve(value); + }, + (err) => { + cleanup(); + reject(err); + } + ); + }); +} + +function isAbortedError(e: unknown): boolean { + return e instanceof Error && e.message === "aborted"; +} + +function cancelledToolResult() { + return { + content: [{ type: "text" as const, text: "Cancelled" }], + details: { cancelled: true }, + }; +} + +type ExecuteArgs = { + signal: AbortSignal | undefined; + onUpdate: ((update: { content: Array<{ type: "text"; text: string }>; details?: Record }) => void) | undefined; + ctx: { cwd: string }; +}; + +function isAbortSignalLike(value: unknown): value is AbortSignal { + return !!value && typeof value === "object" && "aborted" in value && typeof (value as Record).aborted === "boolean" && typeof (value as Record).addEventListener === "function"; +} + +function isContextLike(value: unknown): value is { cwd: string } { + return !!value && typeof value === "object" && typeof (value as { cwd: unknown }).cwd === "string"; +} + +function normalizeExecuteArgs(onUpdateArg: unknown, ctxArg: unknown, signalArg: unknown): ExecuteArgs { + // Runtime >= 0.51: (signal, onUpdate, ctx) + if (isContextLike(signalArg)) { + return { + signal: isAbortSignalLike(onUpdateArg) ? onUpdateArg : undefined, + onUpdate: typeof ctxArg === "function" ? (ctxArg as ExecuteArgs["onUpdate"]) : undefined, + ctx: signalArg, + }; + } + + // Runtime <= 0.50: (onUpdate, ctx, signal) + if (isContextLike(ctxArg)) { + return { + signal: isAbortSignalLike(signalArg) ? signalArg : undefined, + onUpdate: typeof onUpdateArg === "function" ? (onUpdateArg as ExecuteArgs["onUpdate"]) : undefined, + ctx: ctxArg, + }; + } + + throw new Error("Invalid tool execution context"); +} + +function formatLocation(loc: { uri: string; range?: { start?: { line: number; character: number } } }, cwd?: string): string { + const abs = uriToPath(loc.uri); + const display = cwd && path.isAbsolute(abs) ? path.relative(cwd, abs) : abs; + const { line, character: col } = loc.range?.start ?? {}; + return typeof line === "number" && typeof col === "number" ? `${display}:${line + 1}:${col + 1}` : display; +} + +function formatHover(contents: unknown): string { + if (typeof contents === "string") return contents; + if (Array.isArray(contents)) + return contents + .map((c) => (typeof c === "string" ? c : (c as { value?: string })?.value ?? "")) + .filter(Boolean) + .join("\n\n"); + if (contents && typeof contents === "object" && "value" in contents) return String((contents as { value: unknown }).value); + return ""; +} + +function formatSignature(help: SignatureHelp | null): string { + if (!help?.signatures?.length) return "No signature help available."; + const sig = help.signatures[help.activeSignature ?? 0] ?? help.signatures[0]; + let text = sig.label ?? "Signature"; + if (sig.documentation) text += `\n${typeof sig.documentation === "string" ? sig.documentation : sig.documentation?.value ?? ""}`; + if (sig.parameters?.length) { + const params = sig.parameters + .map((p) => (typeof p.label === "string" ? p.label : Array.isArray(p.label) ? String(p.label[0]) + "-" + String(p.label[1]) : "")) + .filter(Boolean); + if (params.length) text += `\nParameters: ${params.join(", ")}`; + } + return text; +} + +function collectSymbols(symbols: Array<{ name?: string; range?: { start?: { line: number; character: number } }; children?: unknown[] }>, depth = 0, lines: string[] = [], query?: string): string[] { + for (const sym of symbols) { + const name = sym?.name ?? ""; + if (query && !name.toLowerCase().includes(query.toLowerCase())) { + if (sym.children?.length) collectSymbols(sym.children as typeof symbols, depth + 1, lines, query); + continue; + } + const loc = sym?.range?.start ? `${sym.range.start.line + 1}:${sym.range.start.character + 1}` : ""; + lines.push(`${" ".repeat(depth)}${name}${loc ? ` (${loc})` : ""}`); + if (sym.children?.length) collectSymbols(sym.children as typeof symbols, depth + 1, lines, query); + } + return lines; +} + +function formatWorkspaceEdit(edit: WorkspaceEdit, cwd?: string): string { + const lines: string[] = []; + + if (edit.documentChanges?.length) { + for (const change of edit.documentChanges) { + // TextDocumentEdit has textDocument, CreateFile/RenameFile/DeleteFile don't + if ("textDocument" in change && change.textDocument?.uri) { + const fp = uriToPath(change.textDocument.uri); + const display = cwd && path.isAbsolute(fp) ? path.relative(cwd, fp) : fp; + lines.push(`${display}:`); + for (const e of change.edits || []) { + if ("range" in e) { + const loc = `${e.range.start.line + 1}:${e.range.start.character + 1}`; + lines.push(` [${loc}] → "${e.newText}"`); + } + } + } + } + } + + if (edit.changes) { + for (const [uri, edits] of Object.entries(edit.changes)) { + const fp = uriToPath(uri); + const display = cwd && path.isAbsolute(fp) ? path.relative(cwd, fp) : fp; + lines.push(`${display}:`); + for (const e of edits) { + const loc = `${e.range.start.line + 1}:${e.range.start.character + 1}`; + lines.push(` [${loc}] → "${e.newText}"`); + } + } + } + + return lines.length ? lines.join("\n") : "No edits."; +} + +function formatCodeActions(actions: (CodeAction | Command)[]): string[] { + return actions.map((a, i) => { + // CodeAction has title directly; Command also has title + const title = a.title || "Untitled action"; + // Only CodeAction has kind and isPreferred + const kind = "kind" in a && a.kind ? ` (${a.kind})` : ""; + const isPreferred = "isPreferred" in a && a.isPreferred ? " ★" : ""; + return `${i + 1}. ${title}${kind}${isPreferred}`; + }); +} + +export default function (pi: ExtensionAPI) { + pi.registerTool({ + name: "lsp", + label: "LSP", + description: `Query language server for definitions, references, types, symbols, diagnostics, rename, and code actions. + +Actions: definition, references, hover, signature, rename (require file + line/column or query), symbols (file, optional query), diagnostics (file), workspace-diagnostics (files array), codeAction (file + position), restart (no args - restarts all LSP servers). +Use bash to find files: find src -name "*.ts" -type f`, + parameters: LspParams, + + async execute(_toolCallId, params, onUpdateArg, ctxArg, signalArg) { + const { signal, ctx } = normalizeExecuteArgs(onUpdateArg, ctxArg, signalArg); + if (signal?.aborted) return cancelledToolResult(); + const manager = getOrCreateManager(ctx.cwd); + const { action, file, files, line, column, endLine, endColumn, query, newName, severity } = params as LspParamsType; + const sevFilter: SeverityFilter = severity || "all"; + const needsFile = action !== "workspace-diagnostics" && action !== "restart"; + const needsPos = ["definition", "references", "hover", "signature", "rename", "codeAction"].includes(action); + + try { + if (needsFile && !file) throw new Error(`Action "${action}" requires a file path.`); + + let rLine = line, + rCol = column, + fromQuery = false; + if (needsPos && (rLine === undefined || rCol === undefined) && query && file) { + const resolved = await abortable(resolvePosition(manager, file, query), signal); + if (resolved) { + rLine = resolved.line; + rCol = resolved.column; + fromQuery = true; + } + } + if (needsPos && (rLine === undefined || rCol === undefined)) { + throw new Error(`Action "${action}" requires line/column or a query matching a symbol.`); + } + + const qLine = query ? `query: ${query}\n` : ""; + const sevLine = sevFilter !== "all" ? `severity: ${sevFilter}\n` : ""; + const posLine = fromQuery && rLine && rCol ? `resolvedPosition: ${rLine}:${rCol}\n` : ""; + + switch (action) { + case "definition": { + const results = await abortable(manager.getDefinition(file!, rLine!, rCol!), signal); + const locs = results.map((l) => formatLocation(l, ctx?.cwd)); + const payload = locs.length ? locs.join("\n") : fromQuery ? `${file}:${rLine}:${rCol}` : "No definitions found."; + return { content: [{ type: "text", text: `action: definition\n${qLine}${posLine}${payload}` }], details: results }; + } + case "references": { + const results = await abortable(manager.getReferences(file!, rLine!, rCol!), signal); + const locs = results.map((l) => formatLocation(l, ctx?.cwd)); + return { content: [{ type: "text", text: `action: references\n${qLine}${posLine}${locs.length ? locs.join("\n") : "No references found."}` }], details: results }; + } + case "hover": { + const result = await abortable(manager.getHover(file!, rLine!, rCol!), signal); + const payload = result ? formatHover(result.contents) || "No hover information." : "No hover information."; + return { content: [{ type: "text", text: `action: hover\n${qLine}${posLine}${payload}` }], details: result ?? null }; + } + case "symbols": { + const symbols = await abortable(manager.getDocumentSymbols(file!), signal); + const lines = collectSymbols(symbols, 0, [], query); + const payload = lines.length ? lines.join("\n") : query ? `No symbols matching "${query}".` : "No symbols found."; + return { content: [{ type: "text", text: `action: symbols\n${qLine}${payload}` }], details: symbols }; + } + case "diagnostics": { + const result = await abortable(manager.touchFileAndWait(file!, diagnosticsWaitMsForFile(file!)), signal); + const filtered = filterDiagnosticsBySeverity(result.diagnostics, sevFilter); + const payload = result.unsupported + ? `Unsupported: ${result.error || "No LSP for this file."}` + : !result.receivedResponse + ? "Timeout: LSP server did not respond. Try again." + : filtered.length + ? filtered.map(formatDiagnostic).join("\n") + : "No diagnostics."; + return { content: [{ type: "text", text: `action: diagnostics\n${sevLine}${payload}` }], details: { ...result, diagnostics: filtered } }; + } + case "workspace-diagnostics": { + if (!files?.length) throw new Error('Action "workspace-diagnostics" requires a "files" array.'); + const waitMs = Math.max(...files.map(diagnosticsWaitMsForFile)); + const result = await abortable(manager.getDiagnosticsForFiles(files, waitMs), signal); + const out: string[] = []; + let errors = 0, + warnings = 0, + filesWithIssues = 0; + + for (const item of result.items) { + const display = ctx?.cwd && path.isAbsolute(item.file) ? path.relative(ctx.cwd, item.file) : item.file; + if (item.status !== "ok") { + out.push(`${display}: ${item.error || item.status}`); + continue; + } + const filtered = filterDiagnosticsBySeverity(item.diagnostics, sevFilter); + if (filtered.length) { + filesWithIssues++; + out.push(`${display}:`); + for (const d of filtered) { + if (d.severity === 1) errors++; + else if (d.severity === 2) warnings++; + out.push(` ${formatDiagnostic(d)}`); + } + } + } + + const summary = `Analyzed ${result.items.length} file(s): ${errors} error(s), ${warnings} warning(s) in ${filesWithIssues} file(s)`; + return { content: [{ type: "text", text: `action: workspace-diagnostics\n${sevLine}${summary}\n\n${out.length ? out.join("\n") : "No diagnostics."}` }], details: result }; + } + case "signature": { + const result = await abortable(manager.getSignatureHelp(file!, rLine!, rCol!), signal); + return { content: [{ type: "text", text: `action: signature\n${qLine}${posLine}${formatSignature(result)}` }], details: result ?? null }; + } + case "rename": { + if (!newName) throw new Error('Action "rename" requires a "newName" parameter.'); + const result = await abortable(manager.rename(file!, rLine!, rCol!, newName), signal); + if (!result) return { content: [{ type: "text", text: `action: rename\n${qLine}${posLine}No rename available at this position.` }], details: null }; + const edits = formatWorkspaceEdit(result, ctx?.cwd); + return { content: [{ type: "text", text: `action: rename\n${qLine}${posLine}newName: ${newName}\n\n${edits}` }], details: result }; + } + case "codeAction": { + const result = await abortable(manager.getCodeActions(file!, rLine!, rCol!, endLine, endColumn), signal); + const actions = formatCodeActions(result); + return { content: [{ type: "text", text: `action: codeAction\n${qLine}${posLine}${actions.length ? actions.join("\n") : "No code actions available."}` }], details: result }; + } + case "restart": { + await shutdownManager(); + return { content: [{ type: "text", text: "action: restart\nLSP servers restarted. Next query will start fresh servers." }], details: { restarted: true } }; + } + } + } catch (e) { + if (signal?.aborted || isAbortedError(e)) return cancelledToolResult(); + throw e; + } + }, + + renderCall(args, theme) { + const params = args as LspParamsType; + let text = theme.fg("toolTitle", theme.bold("lsp ")) + theme.fg("accent", params.action || "..."); + if (params.file) text += " " + theme.fg("muted", params.file); + else if (params.files?.length) text += " " + theme.fg("muted", `${params.files.length} file(s)`); + if (params.query) text += " " + theme.fg("dim", `query="${params.query}"`); + else if (params.line !== undefined && params.column !== undefined) text += theme.fg("warning", `:${params.line}:${params.column}`); + if (params.severity && params.severity !== "all") text += " " + theme.fg("dim", `[${params.severity}]`); + return new Text(text, 0, 0); + }, + + renderResult(result, options, theme) { + if (options.isPartial) return new Text("", 0, 0); + + const textContent = (result.content?.find((c: { type: string }) => c.type === "text") as { text?: string })?.text || ""; + const lines = textContent.split("\n"); + + let headerEnd = 0; + for (let i = 0; i < lines.length; i++) { + if (/^(action|query|severity|resolvedPosition):/.test(lines[i])) headerEnd = i + 1; + else break; + } + + const header = lines.slice(0, headerEnd); + const content = lines.slice(headerEnd); + const maxLines = options.expanded ? content.length : PREVIEW_LINES; + const display = content.slice(0, maxLines); + const remaining = content.length - maxLines; + + let out = header.map((l: string) => theme.fg("muted", l)).join("\n"); + if (display.length) { + if (out) out += "\n"; + out += display.map((l: string) => theme.fg("toolOutput", l)).join("\n"); + } + if (remaining > 0) out += theme.fg("dim", `\n... (${remaining} more lines)`); + + return new Text(out, 0, 0); + }, + }); +} diff --git a/pi/files/agent/extensions/lsp/lsp.ts b/pi/files/agent/extensions/lsp/lsp.ts new file mode 100644 index 0000000..6098086 --- /dev/null +++ b/pi/files/agent/extensions/lsp/lsp.ts @@ -0,0 +1,586 @@ +/** + * LSP Hook Extension + * + * Provides automatic diagnostics feedback (default: agent end). + * Can run after each write/edit or once per agent response. + * + * Usage: /lsp to configure hook mode + */ + +import * as path from "node:path"; +import * as fs from "node:fs"; +import * as os from "node:os"; +import { type ExtensionAPI, type ExtensionContext } from "@mariozechner/pi-coding-agent"; +import { Text } from "@mariozechner/pi-tui"; +import { type Diagnostic } from "vscode-languageserver-protocol"; +import { LSP_SERVERS, formatDiagnostic, getOrCreateManager, shutdownManager } from "./lsp-core.js"; + +type HookScope = "session" | "global"; +type HookMode = "edit_write" | "agent_end" | "disabled"; + +const DIAGNOSTICS_WAIT_MS_DEFAULT = 3000; + +function diagnosticsWaitMsForFile(filePath: string): number { + const ext = path.extname(filePath).toLowerCase(); + if (ext === ".rs") return 20000; + return DIAGNOSTICS_WAIT_MS_DEFAULT; +} + +const DIAGNOSTICS_PREVIEW_LINES = 10; +const LSP_IDLE_SHUTDOWN_MS = 2 * 60 * 1000; +const DIM = "\x1b[2m", + GREEN = "\x1b[32m", + YELLOW = "\x1b[33m", + RESET = "\x1b[0m"; +const DEFAULT_HOOK_MODE: HookMode = "agent_end"; +const SETTINGS_NAMESPACE = "lsp"; +const LSP_CONFIG_ENTRY = "lsp-hook-config"; + +const WARMUP_MAP: Record = { + "pubspec.yaml": ".dart", + "package.json": ".ts", + "pyproject.toml": ".py", + "go.mod": ".go", + "Cargo.toml": ".rs", +}; + +const MODE_LABELS: Record = { + edit_write: "After each edit/write", + agent_end: "At agent end", + disabled: "Disabled", +}; + +function normalizeHookMode(value: unknown): HookMode | undefined { + if (value === "edit_write" || value === "agent_end" || value === "disabled") return value; + if (value === "turn_end") return "agent_end"; + return undefined; +} + +interface HookConfigEntry { + scope: HookScope; + hookMode?: HookMode; +} + +export default function (pi: ExtensionAPI) { + type LspActivity = "idle" | "loading" | "working"; + + let activeClients: Set = new Set(); + let statusUpdateFn: ((key: string, text: string | undefined) => void) | null = null; + let hookMode: HookMode = DEFAULT_HOOK_MODE; + let hookScope: HookScope = "global"; + let activity: LspActivity = "idle"; + let diagnosticsAbort: AbortController | null = null; + let shuttingDown = false; + let idleShutdownTimer: NodeJS.Timeout | null = null; + + const touchedFiles: Map = new Map(); + const globalSettingsPath = path.join(os.homedir(), ".pi", "agent", "settings.json"); + + function readSettingsFile(filePath: string): Record { + try { + if (!fs.existsSync(filePath)) return {}; + const raw = fs.readFileSync(filePath, "utf-8"); + const parsed = JSON.parse(raw); + return parsed && typeof parsed === "object" ? (parsed as Record) : {}; + } catch { + return {}; + } + } + + function getGlobalHookMode(): HookMode | undefined { + const settings = readSettingsFile(globalSettingsPath); + const lspSettings = settings[SETTINGS_NAMESPACE]; + const hookValue = (lspSettings as { hookMode?: unknown; hookEnabled?: unknown } | undefined)?.hookMode; + const normalized = normalizeHookMode(hookValue); + if (normalized) return normalized; + + const legacyEnabled = (lspSettings as { hookEnabled?: unknown } | undefined)?.hookEnabled; + if (typeof legacyEnabled === "boolean") return legacyEnabled ? "edit_write" : "disabled"; + return undefined; + } + + function setGlobalHookMode(mode: HookMode): boolean { + try { + const settings = readSettingsFile(globalSettingsPath); + const existing = settings[SETTINGS_NAMESPACE]; + const nextNamespace = + existing && typeof existing === "object" ? { ...(existing as Record), hookMode: mode } : { hookMode: mode }; + + settings[SETTINGS_NAMESPACE] = nextNamespace; + fs.mkdirSync(path.dirname(globalSettingsPath), { recursive: true }); + fs.writeFileSync(globalSettingsPath, JSON.stringify(settings, null, 2), "utf-8"); + return true; + } catch { + return false; + } + } + + function getLastHookEntry(ctx: ExtensionContext): HookConfigEntry | undefined { + const branchEntries = ctx.sessionManager.getBranch(); + let latest: HookConfigEntry | undefined; + + for (const entry of branchEntries) { + if (entry.type === "custom" && entry.customType === LSP_CONFIG_ENTRY) { + latest = entry.data as HookConfigEntry | undefined; + } + } + + return latest; + } + + function restoreHookState(ctx: ExtensionContext): void { + const entry = getLastHookEntry(ctx); + if (entry?.scope === "session") { + const normalized = normalizeHookMode(entry.hookMode); + if (normalized) { + hookMode = normalized; + hookScope = "session"; + return; + } + + const legacyEnabled = (entry as { hookEnabled?: unknown }).hookEnabled; + if (typeof legacyEnabled === "boolean") { + hookMode = legacyEnabled ? "edit_write" : "disabled"; + hookScope = "session"; + return; + } + } + + const globalSetting = getGlobalHookMode(); + hookMode = globalSetting ?? DEFAULT_HOOK_MODE; + hookScope = "global"; + } + + function persistHookEntry(entry: HookConfigEntry): void { + pi.appendEntry(LSP_CONFIG_ENTRY, entry); + } + + function labelForMode(mode: HookMode): string { + return MODE_LABELS[mode]; + } + + function messageContentToText(content: unknown): string { + if (typeof content === "string") return content; + if (Array.isArray(content)) { + return content + .map((item) => + item && typeof item === "object" && "type" in item && (item as { type: string }).type === "text" + ? String((item as { text?: string }).text ?? "") + : "" + ) + .filter(Boolean) + .join("\n"); + } + return ""; + } + + function formatDiagnosticsForDisplay(text: string): string { + return text + .replace(/\n?This file has errors, please fix\n/gi, "\n") + .replace(/<\/?file_diagnostics>\n?/gi, "") + .replace(/\n{3,}/g, "\n\n") + .trim(); + } + + function setActivity(next: LspActivity): void { + activity = next; + updateLspStatus(); + } + + function clearIdleShutdownTimer(): void { + if (!idleShutdownTimer) return; + clearTimeout(idleShutdownTimer); + idleShutdownTimer = null; + } + + async function shutdownLspServersForIdle(): Promise { + diagnosticsAbort?.abort(); + diagnosticsAbort = null; + setActivity("idle"); + + await shutdownManager(); + activeClients.clear(); + updateLspStatus(); + } + + function scheduleIdleShutdown(): void { + clearIdleShutdownTimer(); + + idleShutdownTimer = setTimeout(() => { + idleShutdownTimer = null; + if (shuttingDown) return; + void shutdownLspServersForIdle(); + }, LSP_IDLE_SHUTDOWN_MS); + + (idleShutdownTimer as NodeJS.Timeout & { unref?: () => void }).unref?.(); + } + + function updateLspStatus(): void { + if (!statusUpdateFn) return; + + const clients = activeClients.size > 0 ? [...activeClients].join(", ") : ""; + const clientsText = clients ? `${DIM}${clients}${RESET}` : ""; + const activityHint = activity === "idle" ? "" : `${DIM}•${RESET}`; + + if (hookMode === "disabled") { + const text = clientsText ? `${YELLOW}LSP${RESET} ${DIM}(tool)${RESET}: ${clientsText}` : `${YELLOW}LSP${RESET} ${DIM}(tool)${RESET}`; + statusUpdateFn("lsp", text); + return; + } + + let text = `${GREEN}LSP${RESET}`; + if (activityHint) text += ` ${activityHint}`; + if (clientsText) text += ` ${clientsText}`; + statusUpdateFn("lsp", text); + } + + function normalizeFilePath(filePath: string, cwd: string): string { + return path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath); + } + + pi.registerMessageRenderer("lsp-diagnostics", (message, options, theme) => { + const content = formatDiagnosticsForDisplay(messageContentToText(message.content)); + if (!content) return new Text("", 0, 0); + + const expanded = options.expanded === true; + const lines = content.split("\n"); + const maxLines = expanded ? lines.length : DIAGNOSTICS_PREVIEW_LINES; + const display = lines.slice(0, maxLines); + const remaining = lines.length - display.length; + + const styledLines = display.map((line) => { + if (line.startsWith("File: ")) return theme.fg("muted", line); + return theme.fg("toolOutput", line); + }); + + if (!expanded && remaining > 0) { + styledLines.push(theme.fg("dim", `... (${remaining} more lines)`)); + } + + return new Text(styledLines.join("\n"), 0, 0); + }); + + function getServerConfig(filePath: string) { + const ext = path.extname(filePath); + return LSP_SERVERS.find((s) => s.extensions.includes(ext)); + } + + function ensureActiveClientForFile(filePath: string, cwd: string): string | undefined { + const absPath = normalizeFilePath(filePath, cwd); + const cfg = getServerConfig(absPath); + if (!cfg) return undefined; + + if (!activeClients.has(cfg.id)) { + activeClients.add(cfg.id); + updateLspStatus(); + } + + return absPath; + } + + function extractLspFiles(input: Record): string[] { + const files: string[] = []; + + if (typeof input.file === "string") files.push(input.file); + if (Array.isArray(input.files)) { + for (const item of input.files) { + if (typeof item === "string") files.push(item); + } + } + + return files; + } + + function buildDiagnosticsOutput( + filePath: string, + diagnostics: Diagnostic[], + cwd: string, + includeFileHeader: boolean + ): { notification: string; errorCount: number; output: string } { + const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath); + const relativePath = path.relative(cwd, absPath); + const errorCount = diagnostics.filter((e) => e.severity === 1).length; + + const MAX = 5; + const lines = diagnostics.slice(0, MAX).map((e) => { + const sev = e.severity === 1 ? "ERROR" : "WARN"; + return `${sev}[${e.range.start.line + 1}] ${e.message.split("\n")[0]}`; + }); + + let notification = `📋 ${relativePath}\n${lines.join("\n")}`; + if (diagnostics.length > MAX) notification += `\n... +${diagnostics.length - MAX} more`; + + const header = includeFileHeader ? `File: ${relativePath}\n` : ""; + const output = `\n${header}This file has errors, please fix\n\n${diagnostics.map(formatDiagnostic).join("\n")}\n\n`; + + return { notification, errorCount, output }; + } + + async function collectDiagnostics( + filePath: string, + ctx: ExtensionContext, + includeWarnings: boolean, + includeFileHeader: boolean, + notify = true + ): Promise { + const manager = getOrCreateManager(ctx.cwd); + const absPath = ensureActiveClientForFile(filePath, ctx.cwd); + if (!absPath) return undefined; + + try { + const result = await manager.touchFileAndWait(absPath, diagnosticsWaitMsForFile(absPath)); + if (!result.receivedResponse) return undefined; + + const diagnostics = includeWarnings ? result.diagnostics : result.diagnostics.filter((d) => d.severity === 1); + if (!diagnostics.length) return undefined; + + const report = buildDiagnosticsOutput(filePath, diagnostics, ctx.cwd, includeFileHeader); + + if (notify) { + if (ctx.hasUI) ctx.ui.notify(report.notification, report.errorCount > 0 ? "error" : "warning"); + else console.error(report.notification); + } + + return report.output; + } catch { + return undefined; + } + } + + pi.registerCommand("lsp-restart", { + description: "Restart all LSP servers", + handler: async (_args, ctx) => { + await shutdownManager(); + activeClients.clear(); + touchedFiles.clear(); + updateLspStatus(); + ctx.ui.notify("LSP servers restarted", "info"); + }, + }); + + pi.registerCommand("lsp", { + description: "LSP settings (auto diagnostics hook)", + handler: async (_args, ctx) => { + if (!ctx.hasUI) { + ctx.ui.notify("LSP settings require UI", "warning"); + return; + } + + const currentMark = " ✓"; + const modeOptions = (["edit_write", "agent_end", "disabled"] as HookMode[]).map((mode) => ({ + mode, + label: mode === hookMode ? `${labelForMode(mode)}${currentMark}` : labelForMode(mode), + })); + + const modeChoice = await ctx.ui.select( + "LSP auto diagnostics hook mode:", + modeOptions.map((option) => option.label) + ); + if (!modeChoice) return; + + const nextMode = modeOptions.find((option) => option.label === modeChoice)?.mode; + if (!nextMode) return; + + const scopeOptions = [ + { scope: "session" as HookScope, label: "Session only" }, + { scope: "global" as HookScope, label: "Global (all sessions)" }, + ]; + + const scopeChoice = await ctx.ui.select( + "Apply LSP auto diagnostics hook setting to:", + scopeOptions.map((option) => option.label) + ); + if (!scopeChoice) return; + + const scope = scopeOptions.find((option) => option.label === scopeChoice)?.scope; + if (!scope) return; + if (scope === "global") { + const ok = setGlobalHookMode(nextMode); + if (!ok) { + ctx.ui.notify("Failed to update global settings", "error"); + return; + } + } + + hookMode = nextMode; + hookScope = scope; + touchedFiles.clear(); + persistHookEntry({ scope, hookMode: nextMode }); + updateLspStatus(); + ctx.ui.notify(`LSP hook: ${labelForMode(hookMode)} (${hookScope})`, "info"); + }, + }); + + pi.on("session_start", async (_event, ctx) => { + restoreHookState(ctx); + statusUpdateFn = ctx.hasUI && ctx.ui.setStatus ? ctx.ui.setStatus.bind(ctx.ui) : null; + updateLspStatus(); + + if (hookMode === "disabled") return; + + const manager = getOrCreateManager(ctx.cwd); + + for (const [marker, ext] of Object.entries(WARMUP_MAP)) { + if (fs.existsSync(path.join(ctx.cwd, marker))) { + setActivity("loading"); + manager + .getClientsForFile(path.join(ctx.cwd, `dummy${ext}`)) + .then((clients) => { + if (clients.length > 0) { + const cfg = LSP_SERVERS.find((s) => s.extensions.includes(ext)); + if (cfg) activeClients.add(cfg.id); + } + }) + .catch(() => {}) + .finally(() => setActivity("idle")); + break; + } + } + }); + + pi.on("session_switch", async (_event, ctx) => { + restoreHookState(ctx); + updateLspStatus(); + }); + + pi.on("session_tree", async (_event, ctx) => { + restoreHookState(ctx); + updateLspStatus(); + }); + + pi.on("session_fork", async (_event, ctx) => { + restoreHookState(ctx); + updateLspStatus(); + }); + + pi.on("session_shutdown", async () => { + shuttingDown = true; + clearIdleShutdownTimer(); + diagnosticsAbort?.abort(); + diagnosticsAbort = null; + setActivity("idle"); + + await shutdownManager(); + activeClients.clear(); + statusUpdateFn?.("lsp", undefined); + }); + + pi.on("tool_call", async (event, ctx) => { + const input = event.input && typeof event.input === "object" ? (event.input as Record) : {}; + + if (event.toolName === "lsp") { + clearIdleShutdownTimer(); + const files = extractLspFiles(input); + for (const file of files) { + ensureActiveClientForFile(file, ctx.cwd); + } + return; + } + + if (event.toolName !== "read" && event.toolName !== "write" && event.toolName !== "edit") return; + + clearIdleShutdownTimer(); + const filePath = typeof input.path === "string" ? input.path : undefined; + if (!filePath) return; + + const absPath = ensureActiveClientForFile(filePath, ctx.cwd); + if (!absPath) return; + + void getOrCreateManager(ctx.cwd).getClientsForFile(absPath).catch(() => {}); + }); + + pi.on("agent_start", async () => { + clearIdleShutdownTimer(); + diagnosticsAbort?.abort(); + diagnosticsAbort = null; + setActivity("idle"); + touchedFiles.clear(); + }); + + function agentWasAborted(event: { messages?: Array<{ role?: string; stopReason?: string }> }): boolean { + const messages = Array.isArray(event?.messages) ? event.messages : []; + return messages.some((m) => m && typeof m === "object" && m.role === "assistant" && (m.stopReason === "aborted" || m.stopReason === "error")); + } + + pi.on("agent_end", async (event, ctx) => { + try { + if (hookMode !== "agent_end") return; + + if (agentWasAborted(event)) { + touchedFiles.clear(); + return; + } + + if (touchedFiles.size === 0) return; + if (!ctx.isIdle() || ctx.hasPendingMessages()) return; + + const abort = new AbortController(); + diagnosticsAbort?.abort(); + diagnosticsAbort = abort; + + const files = Array.from(touchedFiles.entries()); + touchedFiles.clear(); + + try { + const outputs: string[] = []; + for (const [filePath, includeWarnings] of files) { + if (shuttingDown || abort.signal.aborted) return; + if (!ctx.isIdle() || ctx.hasPendingMessages()) { + abort.abort(); + return; + } + + const output = await collectDiagnostics(filePath, ctx, includeWarnings, true, false); + if (abort.signal.aborted) return; + if (output) outputs.push(output); + } + + if (shuttingDown || abort.signal.aborted) return; + + if (outputs.length) { + pi.sendMessage( + { + customType: "lsp-diagnostics", + content: outputs.join("\n"), + display: true, + }, + { + triggerTurn: true, + deliverAs: "followUp", + } + ); + } + } finally { + if (diagnosticsAbort === abort) diagnosticsAbort = null; + if (!shuttingDown) setActivity("idle"); + } + } finally { + if (!shuttingDown) scheduleIdleShutdown(); + } + }); + + pi.on("tool_result", async (event, ctx) => { + if (event.toolName !== "write" && event.toolName !== "edit") return; + + const filePath = event.input.path as string; + if (!filePath) return; + + const absPath = ensureActiveClientForFile(filePath, ctx.cwd); + if (!absPath) return; + + if (hookMode === "disabled") return; + + if (hookMode === "agent_end") { + const includeWarnings = event.toolName === "write"; + const existing = touchedFiles.get(absPath) ?? false; + touchedFiles.set(absPath, existing || includeWarnings); + return; + } + + const includeWarnings = event.toolName === "write"; + const output = await collectDiagnostics(absPath, ctx, includeWarnings, false); + if (!output) return; + + return { content: [...event.content, { type: "text" as const, text: output }] as Array<{ type: "text"; text: string }> }; + }); +} diff --git a/pi/files/agent/extensions/lsp/package.json b/pi/files/agent/extensions/lsp/package.json new file mode 100644 index 0000000..ebdc75b --- /dev/null +++ b/pi/files/agent/extensions/lsp/package.json @@ -0,0 +1,23 @@ +{ + "name": "lsp", + "version": "1.0.0", + "type": "module", + "pi": { + "extensions": [ + "./lsp.ts", + "./lsp-tool.ts" + ] + }, + "dependencies": { + "@sinclair/typebox": "^0.34.33", + "vscode-languageserver-protocol": "^3.17.5" + }, + "peerDependencies": { + "@mariozechner/pi-ai": "^0.50.0", + "@mariozechner/pi-coding-agent": "^0.50.0", + "@mariozechner/pi-tui": "^0.50.0" + }, + "devDependencies": { + "@types/node": "^25.3.3" + } +} diff --git a/pi/files/agent/extensions/lsp/pnpm-lock.yaml b/pi/files/agent/extensions/lsp/pnpm-lock.yaml new file mode 100644 index 0000000..538c2df --- /dev/null +++ b/pi/files/agent/extensions/lsp/pnpm-lock.yaml @@ -0,0 +1,2499 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@mariozechner/pi-ai': + specifier: ^0.50.0 + version: 0.50.9(ws@8.19.0)(zod@3.25.76) + '@mariozechner/pi-coding-agent': + specifier: ^0.50.0 + version: 0.50.9(ws@8.19.0)(zod@3.25.76) + '@mariozechner/pi-tui': + specifier: ^0.50.0 + version: 0.50.9 + '@sinclair/typebox': + specifier: ^0.34.33 + version: 0.34.48 + vscode-languageserver-protocol: + specifier: ^3.17.5 + version: 3.17.5 + devDependencies: + '@types/node': + specifier: ^25.3.3 + version: 25.3.3 + +packages: + + '@anthropic-ai/sdk@0.71.2': + resolution: {integrity: sha512-TGNDEUuEstk/DKu0/TflXAEt+p+p/WhTlFzEnoosvbaDU2LTjm42igSdlL0VijrKpWejtOKxX0b8A7uc+XiSAQ==} + hasBin: true + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-bedrock-runtime@3.1000.0': + resolution: {integrity: sha512-GA96wgTFB4Z5vhysm+hErbgiEWZ9JqAl09BxARajL7Oanpf0KvdIjxuLp2rD/XqEIks9yG/5Rh9XIAoCUUTZXw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.973.15': + resolution: {integrity: sha512-AlC0oQ1/mdJ8vCIqu524j5RB7M8i8E24bbkZmya1CuiQxkY7SdIZAyw7NDNMGaNINQFq/8oGRMX0HeOfCVsl/A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.13': + resolution: {integrity: sha512-6ljXKIQ22WFKyIs1jbORIkGanySBHaPPTOI4OxACP5WXgbcR0nDYfqNJfXEGwCK7IzHdNbCSFsNKKs0qCexR8Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-http@3.972.15': + resolution: {integrity: sha512-dJuSTreu/T8f24SHDNTjd7eQ4rabr0TzPh2UTCwYexQtzG3nTDKm1e5eIdhiroTMDkPEJeY+WPkA6F9wod/20A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-ini@3.972.13': + resolution: {integrity: sha512-JKSoGb7XeabZLBJptpqoZIFbROUIS65NuQnEHGOpuT9GuuZwag2qciKANiDLFiYk4u8nSrJC9JIOnWKVvPVjeA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.13': + resolution: {integrity: sha512-RtYcrxdnJHKY8MFQGLltCURcjuMjnaQpAxPE6+/QEdDHHItMKZgabRe/KScX737F9vJMQsmJy9EmMOkCnoC1JQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-node@3.972.14': + resolution: {integrity: sha512-WqoC2aliIjQM/L3oFf6j+op/enT2i9Cc4UTxxMEKrJNECkq4/PlKE5BOjSYFcq6G9mz65EFbXJh7zOU4CvjSKQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-process@3.972.13': + resolution: {integrity: sha512-rsRG0LQA4VR+jnDyuqtXi2CePYSmfm5GNL9KxiW8DSe25YwJSr06W8TdUfONAC+rjsTI+aIH2rBGG5FjMeANrw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-sso@3.972.13': + resolution: {integrity: sha512-fr0UU1wx8kNHDhTQBXioc/YviSW8iXuAxHvnH7eQUtn8F8o/FU3uu6EUMvAQgyvn7Ne5QFnC0Cj0BFlwCk+RFw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.972.13': + resolution: {integrity: sha512-a6iFMh1pgUH0TdcouBppLJUfPM7Yd3R9S1xFodPtCRoLqCz2RQFA3qjA8x4112PVYXEd4/pHX2eihapq39w0rA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/eventstream-handler-node@3.972.9': + resolution: {integrity: sha512-mKPiiVssgFDWkAXdEDh8+wpr2pFSX/fBn2onXXnrfIAYbdZhYb4WilKbZ3SJMUnQi+Y48jZMam5J0RrgARluaA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-eventstream@3.972.6': + resolution: {integrity: sha512-mB2+3G/oxRC+y9WRk0KCdradE2rSfxxJpcOSmAm+vDh3ex3WQHVLZ1catNIe1j5NQ+3FLBsNMRPVGkZ43PRpjw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-host-header@3.972.6': + resolution: {integrity: sha512-5XHwjPH1lHB+1q4bfC7T8Z5zZrZXfaLcjSMwTd1HPSPrCmPFMbg3UQ5vgNWcVj0xoX4HWqTGkSf2byrjlnRg5w==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-logger@3.972.6': + resolution: {integrity: sha512-iFnaMFMQdljAPrvsCVKYltPt2j40LQqukAbXvW7v0aL5I+1GO7bZ/W8m12WxW3gwyK5p5u1WlHg8TSAizC5cZw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.972.6': + resolution: {integrity: sha512-dY4v3of5EEMvik6+UDwQ96KfUFDk8m1oZDdkSc5lwi4o7rFrjnv0A+yTV+gu230iybQZnKgDLg/rt2P3H+Vscw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-user-agent@3.972.15': + resolution: {integrity: sha512-ABlFVcIMmuRAwBT+8q5abAxOr7WmaINirDJBnqGY5b5jSDo00UMlg/G4a0xoAgwm6oAECeJcwkvDlxDwKf58fQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-websocket@3.972.10': + resolution: {integrity: sha512-uNqRpbL6djE+XXO4cQ+P8ra37cxNNBP+2IfkVOXu1xFdGMfW+uOTxBQuDPpP43i40PBRBXK5un79l/oYpbzYkA==} + engines: {node: '>= 14.0.0'} + + '@aws-sdk/nested-clients@3.996.3': + resolution: {integrity: sha512-AU5TY1V29xqwg/MxmA2odwysTez+ccFAhmfRJk+QZT5HNv90UTA9qKd1J9THlsQkvmH7HWTEV1lDNxkQO5PzNw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/region-config-resolver@3.972.6': + resolution: {integrity: sha512-Aa5PusHLXAqLTX1UKDvI3pHQJtIsF7Q+3turCHqfz/1F61/zDMWfbTC8evjhrrYVAtz9Vsv3SJ/waSUeu7B6gw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1000.0': + resolution: {integrity: sha512-eOI+8WPtWpLdlYBGs8OCK3k5uIMUHVsNG3AFO4kaRaZcKReJ/2OO6+2O2Dd/3vTzM56kRjSKe7mBOCwa4PdYqg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.999.0': + resolution: {integrity: sha512-cx0hHUlgXULfykx4rdu/ciNAJaa3AL5xz3rieCz7NKJ68MJwlj3664Y8WR5MGgxfyYJBdamnkjNSx5Kekuc0cg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.973.4': + resolution: {integrity: sha512-RW60aH26Bsc016Y9B98hC0Plx6fK5P2v/iQYwMzrSjiDh1qRMUCP6KrXHYEHe3uFvKiOC93Z9zk4BJsUi6Tj1Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-endpoints@3.996.3': + resolution: {integrity: sha512-yWIQSNiCjykLL+ezN5A+DfBb1gfXTytBxm57e64lYmwxDHNmInYHRJYYRAGWG1o77vKEiWaw4ui28e3yb1k5aQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-format-url@3.972.6': + resolution: {integrity: sha512-0YNVNgFyziCejXJx0rzxPiD2rkxTWco4c9wiMF6n37Tb9aQvIF8+t7GyEyIFCwQHZ0VMQaAl+nCZHOYz5I5EKw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-locate-window@3.965.4': + resolution: {integrity: sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-user-agent-browser@3.972.6': + resolution: {integrity: sha512-Fwr/llD6GOrFgQnKaI2glhohdGuBDfHfora6iG9qsBBBR8xv1SdCSwbtf5CWlUdCw5X7g76G/9Hf0Inh0EmoxA==} + + '@aws-sdk/util-user-agent-node@3.973.0': + resolution: {integrity: sha512-A9J2G4Nf236e9GpaC1JnA8wRn6u6GjnOXiTwBLA6NUJhlBTIGfrTy+K1IazmF8y+4OFdW3O5TZlhyspJMqiqjA==} + engines: {node: '>=20.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.972.8': + resolution: {integrity: sha512-Ql8elcUdYCha83Ol7NznBsgN5GVZnv3vUd86fEc6waU6oUdY0T1O9NODkEEOS/Uaogr87avDrUC6DSeM4oXjZg==} + engines: {node: '>=20.0.0'} + + '@aws/lambda-invoke-store@0.2.3': + resolution: {integrity: sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==} + engines: {node: '>=18.0.0'} + + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + + '@borewit/text-codec@0.2.1': + resolution: {integrity: sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==} + + '@google/genai@1.34.0': + resolution: {integrity: sha512-vu53UMPvjmb7PGzlYu6Tzxso8Dfhn+a7eQFaS2uNemVtDZKwzSpJ5+ikqBbXplF7RGB1STcVDqCkPvquiwb2sw==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.24.0 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@isaacs/cliui@9.0.0': + resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==} + engines: {node: '>=18'} + + '@mariozechner/clipboard-darwin-arm64@0.3.2': + resolution: {integrity: sha512-uBf6K7Je1ihsgvmWxA8UCGCeI+nbRVRXoarZdLjl6slz94Zs1tNKFZqx7aCI5O1i3e0B6ja82zZ06BWrl0MCVw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@mariozechner/clipboard-darwin-universal@0.3.2': + resolution: {integrity: sha512-mxSheKTW2U9LsBdXy0SdmdCAE5HqNS9QUmpNHLnfJ+SsbFKALjEZc5oRrVMXxGQSirDvYf5bjmRyT0QYYonnlg==} + engines: {node: '>= 10'} + os: [darwin] + + '@mariozechner/clipboard-darwin-x64@0.3.2': + resolution: {integrity: sha512-U1BcVEoidvwIp95+HJswSW+xr28EQiHR7rZjH6pn8Sja5yO4Yoe3yCN0Zm8Lo72BbSOK/fTSq0je7CJpaPCspg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@mariozechner/clipboard-linux-arm64-gnu@0.3.2': + resolution: {integrity: sha512-BsinwG3yWTIjdgNCxsFlip7LkfwPk+ruw/aFCXHUg/fb5XC/Ksp+YMQ7u0LUtiKzIv/7LMXgZInJQH6gxbAaqQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@mariozechner/clipboard-linux-arm64-musl@0.3.2': + resolution: {integrity: sha512-0/Gi5Xq2V6goXBop19ePoHvXsmJD9SzFlO3S+d6+T2b+BlPcpOu3Oa0wTjl+cZrLAAEzA86aPNBI+VVAFDFPKw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@mariozechner/clipboard-linux-riscv64-gnu@0.3.2': + resolution: {integrity: sha512-2AFFiXB24qf0zOZsxI1GJGb9wQGlOJyN6UwoXqmKS3dpQi/l6ix30IzDDA4c4ZcCcx4D+9HLYXhC1w7Sov8pXA==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@mariozechner/clipboard-linux-x64-gnu@0.3.2': + resolution: {integrity: sha512-v6fVnsn7WMGg73Dab8QMwyFce7tzGfgEixKgzLP8f1GJqkJZi5zO4k4FOHzSgUufgLil63gnxvMpjWkgfeQN7A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@mariozechner/clipboard-linux-x64-musl@0.3.2': + resolution: {integrity: sha512-xVUtnoMQ8v2JVyfJLKKXACA6avdnchdbBkTsZs8BgJQo29qwCp5NIHAUO8gbJ40iaEGToW5RlmVk2M9V0HsHEw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@mariozechner/clipboard-win32-arm64-msvc@0.3.2': + resolution: {integrity: sha512-AEgg95TNi8TGgak2wSXZkXKCvAUTjWoU1Pqb0ON7JHrX78p616XUFNTJohtIon3e0w6k0pYPZeCuqRCza/Tqeg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@mariozechner/clipboard-win32-x64-msvc@0.3.2': + resolution: {integrity: sha512-tGRuYpZwDOD7HBrCpyRuhGnHHSCknELvqwKKUG4JSfSB7JIU7LKRh6zx6fMUOQd8uISK35TjFg5UcNih+vJhFA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@mariozechner/clipboard@0.3.2': + resolution: {integrity: sha512-IHQpksNjo7EAtGuHFU+tbWDp5LarH3HU/8WiB9O70ZEoBPHOg0/6afwSLK0QyNMMmx4Bpi/zl6+DcBXe95nWYA==} + engines: {node: '>= 10'} + + '@mariozechner/jiti@2.6.5': + resolution: {integrity: sha512-faGUlTcXka5l7rv0lP3K3vGW/ejRuOS24RR2aSFWREUQqzjgdsuWNo/IiPqL3kWRGt6Ahl2+qcDAwtdeWeuGUw==} + hasBin: true + + '@mariozechner/pi-agent-core@0.50.9': + resolution: {integrity: sha512-Zsgqs/f2Fxrub1k95vj8kg7M1eTDdS1lP3gTV7h9raBUQzoaPP+9jYGoUL5KKqxsBbt7WgeAQrK3nrev400EHA==} + engines: {node: '>=20.0.0'} + + '@mariozechner/pi-ai@0.50.9': + resolution: {integrity: sha512-a6sLIHLH+wo5zTFoo/0AE/P6GPyJzaXnE86z89t6tINzeSdKMApZZ+B4Cy4U3GpsYfxuZ9gBJlcKbfj+oKP3wg==} + engines: {node: '>=20.0.0'} + hasBin: true + + '@mariozechner/pi-coding-agent@0.50.9': + resolution: {integrity: sha512-XO1fc+UdGbFlOgRx9bVccimJWGquWwvgVlK2Sbr9tjnGNBOBq2G0SvYE6MHhzxIyL0MolqOT8IrMGJFus9tEOg==} + engines: {node: '>=20.0.0'} + hasBin: true + + '@mariozechner/pi-tui@0.50.9': + resolution: {integrity: sha512-suMWoh+XB3JKkwrXfXSwEAsvkrPUn6Zn8JQ1I+1hcNQqH/lY6e8LFRwVBkkvPt/jwoxBh8jGoiTNVh5i7Yod0g==} + engines: {node: '>=20.0.0'} + + '@mistralai/mistralai@1.10.0': + resolution: {integrity: sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@silvia-odwyer/photon-node@0.3.4': + resolution: {integrity: sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==} + + '@sinclair/typebox@0.34.48': + resolution: {integrity: sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==} + + '@smithy/abort-controller@4.2.10': + resolution: {integrity: sha512-qocxM/X4XGATqQtUkbE9SPUB6wekBi+FyJOMbPj0AhvyvFGYEmOlz6VB22iMePCQsFmMIvFSeViDvA7mZJG47g==} + engines: {node: '>=18.0.0'} + + '@smithy/config-resolver@4.4.9': + resolution: {integrity: sha512-ejQvXqlcU30h7liR9fXtj7PIAau1t/sFbJpgWPfiYDs7zd16jpH0IsSXKcba2jF6ChTXvIjACs27kNMc5xxE2Q==} + engines: {node: '>=18.0.0'} + + '@smithy/core@3.23.6': + resolution: {integrity: sha512-4xE+0L2NrsFKpEVFlFELkIHQddBvMbQ41LRIP74dGCXnY1zQ9DgksrBcRBDJT+iOzGy4VEJIeU3hkUK5mn06kg==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.2.10': + resolution: {integrity: sha512-3bsMLJJLTZGZqVGGeBVFfLzuRulVsGTj12BzRKODTHqUABpIr0jMN1vN3+u6r2OfyhAQ2pXaMZWX/swBK5I6PQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-codec@4.2.10': + resolution: {integrity: sha512-A4ynrsFFfSXUHicfTcRehytppFBcY3HQxEGYiyGktPIOye3Ot7fxpiy4VR42WmtGI4Wfo6OXt/c1Ky1nUFxYYQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-browser@4.2.10': + resolution: {integrity: sha512-0xupsu9yj9oDVuQ50YCTS9nuSYhGlrwqdaKQel9y2Fz7LU9fNErVlw9N0o4pm4qqvWEGbSTI4HKc6XJfB30MVw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-config-resolver@4.3.10': + resolution: {integrity: sha512-8kn6sinrduk0yaYHMJDsNuiFpXwQwibR7n/4CDUqn4UgaG+SeBHu5jHGFdU9BLFAM7Q4/gvr9RYxBHz9/jKrhA==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-node@4.2.10': + resolution: {integrity: sha512-uUrxPGgIffnYfvIOUmBM5i+USdEBRTdh7mLPttjphgtooxQ8CtdO1p6K5+Q4BBAZvKlvtJ9jWyrWpBJYzBKsyQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-universal@4.2.10': + resolution: {integrity: sha512-aArqzOEvcs2dK+xQVCgLbpJQGfZihw8SD4ymhkwNTtwKbnrzdhJsFDKuMQnam2kF69WzgJYOU5eJlCx+CA32bw==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.3.11': + resolution: {integrity: sha512-wbTRjOxdFuyEg0CpumjZO0hkUl+fetJFqxNROepuLIoijQh51aMBmzFLfoQdwRjxsuuS2jizzIUTjPWgd8pd7g==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-node@4.2.10': + resolution: {integrity: sha512-1VzIOI5CcsvMDvP3iv1vG/RfLJVVVc67dCRyLSB2Hn9SWCZrDO3zvcIzj3BfEtqRW5kcMg5KAeVf1K3dR6nD3w==} + engines: {node: '>=18.0.0'} + + '@smithy/invalid-dependency@4.2.10': + resolution: {integrity: sha512-vy9KPNSFUU0ajFYk0sDZIYiUlAWGEAhRfehIr5ZkdFrRFTAuXEPUd41USuqHU6vvLX4r6Q9X7MKBco5+Il0Org==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.2.1': + resolution: {integrity: sha512-Yfu664Qbf1B4IYIsYgKoABt010daZjkaCRvdU/sPnZG6TtHOB0md0RjNdLGzxe5UIdn9js4ftPICzmkRa9RJ4Q==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.2.10': + resolution: {integrity: sha512-TQZ9kX5c6XbjhaEBpvhSvMEZ0klBs1CFtOdPFwATZSbC9UeQfKHPLPN9Y+I6wZGMOavlYTOlHEPDrt42PMSH9w==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.4.20': + resolution: {integrity: sha512-9W6Np4ceBP3XCYAGLoMCmn8t2RRVzuD1ndWPLBbv7H9CrwM9Bprf6Up6BM9ZA/3alodg0b7Kf6ftBK9R1N04vw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.4.37': + resolution: {integrity: sha512-/1psZZllBBSQ7+qo5+hhLz7AEPGLx3Z0+e3ramMBEuPK2PfvLK4SrncDB9VegX5mBn+oP/UTDrM6IHrFjvX1ZA==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.2.11': + resolution: {integrity: sha512-STQdONGPwbbC7cusL60s7vOa6He6A9w2jWhoapL0mgVjmR19pr26slV+yoSP76SIssMTX/95e5nOZ6UQv6jolg==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.2.10': + resolution: {integrity: sha512-pmts/WovNcE/tlyHa8z/groPeOtqtEpp61q3W0nW1nDJuMq/x+hWa/OVQBtgU0tBqupeXq0VBOLA4UZwE8I0YA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.3.10': + resolution: {integrity: sha512-UALRbJtVX34AdP2VECKVlnNgidLHA2A7YgcJzwSBg1hzmnO/bZBHl/LDQQyYifzUwp1UOODnl9JJ3KNawpUJ9w==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.4.12': + resolution: {integrity: sha512-zo1+WKJkR9x7ZtMeMDAAsq2PufwiLDmkhcjpWPRRkmeIuOm6nq1qjFICSZbnjBvD09ei8KMo26BWxsu2BUU+5w==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.2.10': + resolution: {integrity: sha512-5jm60P0CU7tom0eNrZ7YrkgBaoLFXzmqB0wVS+4uK8PPGmosSrLNf6rRd50UBvukztawZ7zyA8TxlrKpF5z9jw==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.3.10': + resolution: {integrity: sha512-2NzVWpYY0tRdfeCJLsgrR89KE3NTWT2wGulhNUxYlRmtRmPwLQwKzhrfVaiNlA9ZpJvbW7cjTVChYKgnkqXj1A==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.2.10': + resolution: {integrity: sha512-HeN7kEvuzO2DmAzLukE9UryiUvejD3tMp9a1D1NJETerIfKobBUCLfviP6QEk500166eD2IATaXM59qgUI+YDA==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.2.10': + resolution: {integrity: sha512-4Mh18J26+ao1oX5wXJfWlTT+Q1OpDR8ssiC9PDOuEgVBGloqg18Fw7h5Ct8DyT9NBYwJgtJ2nLjKKFU6RP1G1Q==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.2.10': + resolution: {integrity: sha512-0R/+/Il5y8nB/By90o8hy/bWVYptbIfvoTYad0igYQO5RefhNCDmNzqxaMx7K1t/QWo0d6UynqpqN5cCQt1MCg==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.4.5': + resolution: {integrity: sha512-pHgASxl50rrtOztgQCPmOXFjRW+mCd7ALr/3uXNzRrRoGV5G2+78GOsQ3HlQuBVHCh9o6xqMNvlIKZjWn4Euug==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.3.10': + resolution: {integrity: sha512-Wab3wW8468WqTKIxI+aZe3JYO52/RYT/8sDOdzkUhjnLakLe9qoQqIcfih/qxcF4qWEFoWBszY0mj5uxffaVXA==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.12.0': + resolution: {integrity: sha512-R8bQ9K3lCcXyZmBnQqUZJF4ChZmtWT5NLi6x5kgWx5D+/j0KorXcA0YcFg/X5TOgnTCy1tbKc6z2g2y4amFupQ==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.13.0': + resolution: {integrity: sha512-COuLsZILbbQsdrwKQpkkpyep7lCsByxwj7m0Mg5v66/ZTyenlfBc40/QFQ5chO0YN/PNEH1Bi3fGtfXPnYNeDw==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.2.10': + resolution: {integrity: sha512-uypjF7fCDsRk26u3qHmFI/ePL7bxxB9vKkE+2WKEciHhz+4QtbzWiHRVNRJwU3cKhrYDYQE3b0MRFtqfLYdA4A==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.3.1': + resolution: {integrity: sha512-BKGuawX4Doq/bI/uEmg+Zyc36rJKWuin3py89PquXBIBqmbnJwBBsmKhdHfNEp0+A4TDgLmT/3MSKZ1SxHcR6w==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.2.1': + resolution: {integrity: sha512-SiJeLiozrAoCrgDBUgsVbmqHmMgg/2bA15AzcbcW+zan7SuyAVHN4xTSbq0GlebAIwlcaX32xacnrG488/J/6g==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.2.2': + resolution: {integrity: sha512-4rHqBvxtJEBvsZcFQSPQqXP2b/yy/YlB66KlcEgcH2WNoOKCKB03DSLzXmOsXjbl8dJ4OEYTn31knhdznwk7zw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.2.1': + resolution: {integrity: sha512-/swhmt1qTiVkaejlmMPPDgZhEaWb/HWMGRBheaxwuVkusp/z+ErJyQxO6kaXumOciZSWlmq6Z5mNylCd33X7Ig==} + engines: {node: '>=18.0.0'} + + '@smithy/util-config-provider@4.2.1': + resolution: {integrity: sha512-462id/00U8JWFw6qBuTSWfN5TxOHvDu4WliI97qOIOnuC/g+NDAknTU8eoGXEPlLkRVgWEr03jJBLV4o2FL8+A==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.3.36': + resolution: {integrity: sha512-R0smq7EHQXRVMxkAxtH5akJ/FvgAmNF6bUy/GwY/N20T4GrwjT633NFm0VuRpC+8Bbv8R9A0DoJ9OiZL/M3xew==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.2.39': + resolution: {integrity: sha512-otWuoDm35btJV1L8MyHrPl462B07QCdMTktKc7/yM+Psv6KbED/ziXiHnmr7yPHUjfIwE9S8Max0LO24Mo3ZVg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.3.1': + resolution: {integrity: sha512-xyctc4klmjmieQiF9I1wssBWleRV0RhJ2DpO8+8yzi2LO1Z+4IWOZNGZGNj4+hq9kdo+nyfrRLmQTzc16Op2Vg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@4.2.1': + resolution: {integrity: sha512-c1hHtkgAWmE35/50gmdKajgGAKV3ePJ7t6UtEmpfCWJmQE9BQAQPz0URUVI89eSkcDqCtzqllxzG28IQoZPvwA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-middleware@4.2.10': + resolution: {integrity: sha512-LxaQIWLp4y0r72eA8mwPNQ9va4h5KeLM0I3M/HV9klmFaY2kN766wf5vsTzmaOpNNb7GgXAd9a25P3h8T49PSA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.2.10': + resolution: {integrity: sha512-HrBzistfpyE5uqTwiyLsFHscgnwB0kgv8vySp7q5kZ0Eltn/tjosaSGGDj/jJ9ys7pWzIP/icE2d+7vMKXLv7A==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.5.15': + resolution: {integrity: sha512-OlOKnaqnkU9X+6wEkd7mN+WB7orPbCVDauXOj22Q7VtiTkvy7ZdSsOg4QiNAZMgI4OkvNf+/VLUC3VXkxuWJZw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-uri-escape@4.2.1': + resolution: {integrity: sha512-YmiUDn2eo2IOiWYYvGQkgX5ZkBSiTQu4FlDo5jNPpAxng2t6Sjb6WutnZV9l6VR4eJul1ABmCrnWBC9hKHQa6Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.2.1': + resolution: {integrity: sha512-DSIwNaWtmzrNQHv8g7DBGR9mulSit65KSj5ymGEIAknmIN8IpbZefEep10LaMG/P/xquwbmJ1h9ectz8z6mV6g==} + engines: {node: '>=18.0.0'} + + '@smithy/uuid@1.1.1': + resolution: {integrity: sha512-dSfDCeihDmZlV2oyr0yWPTUfh07suS+R5OB+FZGiv/hHyK3hrFBW5rR1UYjfa57vBsrP9lciFkRPzebaV1Qujw==} + engines: {node: '>=18.0.0'} + + '@tokenizer/inflate@0.4.1': + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} + engines: {node: '>=18'} + + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + + '@types/mime-types@2.1.4': + resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} + + '@types/node@25.3.3': + resolution: {integrity: sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==} + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + basic-ftp@5.2.0: + resolution: {integrity: sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==} + engines: {node: '>=10.0.0'} + + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + + bowser@2.14.1: + resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + brace-expansion@5.0.4: + resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} + engines: {node: 18 || 20 || >=22} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + cli-highlight@2.1.11: + resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + + diff@8.0.3: + resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} + engines: {node: '>=0.3.1'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + + fast-xml-parser@5.3.6: + resolution: {integrity: sha512-QNI3sAvSvaOiaMl8FYU4trnEzCwiRr8XMWgAHzlrWpTSj+QaCSvOf1h82OEP1s4hiAXhnbXSyFWCf4ldZzZRVA==} + hasBin: true + + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + file-type@21.3.0: + resolution: {integrity: sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==} + engines: {node: '>=20'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + + gaxios@7.1.3: + resolution: {integrity: sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==} + engines: {node: '>=18'} + + gcp-metadata@8.1.2: + resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} + engines: {node: '>=18'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + + get-uri@6.0.5: + resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} + engines: {node: '>= 14'} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + google-auth-library@10.6.1: + resolution: {integrity: sha512-5awwuLrzNol+pFDmKJd0dKtZ0fPLAtoA5p7YO4ODsDu6ONJUVqbYwvv8y2ZBO5MBNp9TJXigB19710kYpBPdtA==} + engines: {node: '>=18'} + + google-logging-utils@1.1.3: + resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==} + engines: {node: '>=14'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jackspeak@4.2.3: + resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} + engines: {node: 20 || >=22} + + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-schema-to-ts@3.1.1: + resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==} + engines: {node: '>=16'} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.2.6: + resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==} + engines: {node: 20 || >=22} + + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + + marked@15.0.12: + resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==} + engines: {node: '>= 18'} + hasBin: true + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + engines: {node: 18 || 20 || >=22} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + openai@6.10.0: + resolution: {integrity: sha512-ITxOGo7rO3XRMiKA5l7tQ43iNNu+iXGFAcf2t+aWVzzqRaS0i7m1K2BhxNdaveB+5eENhO0VY1FkiZzhBk4v3A==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + + pac-proxy-agent@7.2.0: + resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parse5-htmlparser2-tree-adapter@6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + + parse5@5.1.1: + resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} + + parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + + partial-json@0.1.7: + resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + + proxy-agent@6.5.0: + resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} + engines: {node: '>= 14'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} + hasBin: true + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@8.0.5: + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} + + socks@2.8.7: + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strnum@2.2.0: + resolution: {integrity: sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==} + + strtok3@10.3.4: + resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==} + engines: {node: '>=18'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} + engines: {node: '>=14.16'} + + ts-algebra@2.0.0: + resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + undici@7.22.0: + resolution: {integrity: sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==} + engines: {node: '>=20.18.1'} + + vscode-jsonrpc@8.2.0: + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} + + vscode-languageserver-protocol@3.17.5: + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} + + vscode-languageserver-types@3.17.5: + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + ws@8.19.0: + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yaml@2.8.2: + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + engines: {node: '>=18'} + + zod-to-json-schema@3.25.1: + resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} + peerDependencies: + zod: ^3.25 || ^4 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + +snapshots: + + '@anthropic-ai/sdk@0.71.2(zod@3.25.76)': + dependencies: + json-schema-to-ts: 3.1.1 + optionalDependencies: + zod: 3.25.76 + + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.4 + tslib: 2.8.1 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.4 + '@aws-sdk/util-locate-window': 3.965.4 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.4 + tslib: 2.8.1 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.8.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.973.4 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/client-bedrock-runtime@3.1000.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.973.15 + '@aws-sdk/credential-provider-node': 3.972.14 + '@aws-sdk/eventstream-handler-node': 3.972.9 + '@aws-sdk/middleware-eventstream': 3.972.6 + '@aws-sdk/middleware-host-header': 3.972.6 + '@aws-sdk/middleware-logger': 3.972.6 + '@aws-sdk/middleware-recursion-detection': 3.972.6 + '@aws-sdk/middleware-user-agent': 3.972.15 + '@aws-sdk/middleware-websocket': 3.972.10 + '@aws-sdk/region-config-resolver': 3.972.6 + '@aws-sdk/token-providers': 3.1000.0 + '@aws-sdk/types': 3.973.4 + '@aws-sdk/util-endpoints': 3.996.3 + '@aws-sdk/util-user-agent-browser': 3.972.6 + '@aws-sdk/util-user-agent-node': 3.973.0 + '@smithy/config-resolver': 4.4.9 + '@smithy/core': 3.23.6 + '@smithy/eventstream-serde-browser': 4.2.10 + '@smithy/eventstream-serde-config-resolver': 4.3.10 + '@smithy/eventstream-serde-node': 4.2.10 + '@smithy/fetch-http-handler': 5.3.11 + '@smithy/hash-node': 4.2.10 + '@smithy/invalid-dependency': 4.2.10 + '@smithy/middleware-content-length': 4.2.10 + '@smithy/middleware-endpoint': 4.4.20 + '@smithy/middleware-retry': 4.4.37 + '@smithy/middleware-serde': 4.2.11 + '@smithy/middleware-stack': 4.2.10 + '@smithy/node-config-provider': 4.3.10 + '@smithy/node-http-handler': 4.4.12 + '@smithy/protocol-http': 5.3.10 + '@smithy/smithy-client': 4.12.0 + '@smithy/types': 4.13.0 + '@smithy/url-parser': 4.2.10 + '@smithy/util-base64': 4.3.1 + '@smithy/util-body-length-browser': 4.2.1 + '@smithy/util-body-length-node': 4.2.2 + '@smithy/util-defaults-mode-browser': 4.3.36 + '@smithy/util-defaults-mode-node': 4.2.39 + '@smithy/util-endpoints': 3.3.1 + '@smithy/util-middleware': 4.2.10 + '@smithy/util-retry': 4.2.10 + '@smithy/util-stream': 4.5.15 + '@smithy/util-utf8': 4.2.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.973.15': + dependencies: + '@aws-sdk/types': 3.973.4 + '@aws-sdk/xml-builder': 3.972.8 + '@smithy/core': 3.23.6 + '@smithy/node-config-provider': 4.3.10 + '@smithy/property-provider': 4.2.10 + '@smithy/protocol-http': 5.3.10 + '@smithy/signature-v4': 5.3.10 + '@smithy/smithy-client': 4.12.0 + '@smithy/types': 4.13.0 + '@smithy/util-base64': 4.3.1 + '@smithy/util-middleware': 4.2.10 + '@smithy/util-utf8': 4.2.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.13': + dependencies: + '@aws-sdk/core': 3.973.15 + '@aws-sdk/types': 3.973.4 + '@smithy/property-provider': 4.2.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.15': + dependencies: + '@aws-sdk/core': 3.973.15 + '@aws-sdk/types': 3.973.4 + '@smithy/fetch-http-handler': 5.3.11 + '@smithy/node-http-handler': 4.4.12 + '@smithy/property-provider': 4.2.10 + '@smithy/protocol-http': 5.3.10 + '@smithy/smithy-client': 4.12.0 + '@smithy/types': 4.13.0 + '@smithy/util-stream': 4.5.15 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.972.13': + dependencies: + '@aws-sdk/core': 3.973.15 + '@aws-sdk/credential-provider-env': 3.972.13 + '@aws-sdk/credential-provider-http': 3.972.15 + '@aws-sdk/credential-provider-login': 3.972.13 + '@aws-sdk/credential-provider-process': 3.972.13 + '@aws-sdk/credential-provider-sso': 3.972.13 + '@aws-sdk/credential-provider-web-identity': 3.972.13 + '@aws-sdk/nested-clients': 3.996.3 + '@aws-sdk/types': 3.973.4 + '@smithy/credential-provider-imds': 4.2.10 + '@smithy/property-provider': 4.2.10 + '@smithy/shared-ini-file-loader': 4.4.5 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-login@3.972.13': + dependencies: + '@aws-sdk/core': 3.973.15 + '@aws-sdk/nested-clients': 3.996.3 + '@aws-sdk/types': 3.973.4 + '@smithy/property-provider': 4.2.10 + '@smithy/protocol-http': 5.3.10 + '@smithy/shared-ini-file-loader': 4.4.5 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.972.14': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.13 + '@aws-sdk/credential-provider-http': 3.972.15 + '@aws-sdk/credential-provider-ini': 3.972.13 + '@aws-sdk/credential-provider-process': 3.972.13 + '@aws-sdk/credential-provider-sso': 3.972.13 + '@aws-sdk/credential-provider-web-identity': 3.972.13 + '@aws-sdk/types': 3.973.4 + '@smithy/credential-provider-imds': 4.2.10 + '@smithy/property-provider': 4.2.10 + '@smithy/shared-ini-file-loader': 4.4.5 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.972.13': + dependencies: + '@aws-sdk/core': 3.973.15 + '@aws-sdk/types': 3.973.4 + '@smithy/property-provider': 4.2.10 + '@smithy/shared-ini-file-loader': 4.4.5 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.972.13': + dependencies: + '@aws-sdk/core': 3.973.15 + '@aws-sdk/nested-clients': 3.996.3 + '@aws-sdk/token-providers': 3.999.0 + '@aws-sdk/types': 3.973.4 + '@smithy/property-provider': 4.2.10 + '@smithy/shared-ini-file-loader': 4.4.5 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.972.13': + dependencies: + '@aws-sdk/core': 3.973.15 + '@aws-sdk/nested-clients': 3.996.3 + '@aws-sdk/types': 3.973.4 + '@smithy/property-provider': 4.2.10 + '@smithy/shared-ini-file-loader': 4.4.5 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/eventstream-handler-node@3.972.9': + dependencies: + '@aws-sdk/types': 3.973.4 + '@smithy/eventstream-codec': 4.2.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-eventstream@3.972.6': + dependencies: + '@aws-sdk/types': 3.973.4 + '@smithy/protocol-http': 5.3.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-host-header@3.972.6': + dependencies: + '@aws-sdk/types': 3.973.4 + '@smithy/protocol-http': 5.3.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.972.6': + dependencies: + '@aws-sdk/types': 3.973.4 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.972.6': + dependencies: + '@aws-sdk/types': 3.973.4 + '@aws/lambda-invoke-store': 0.2.3 + '@smithy/protocol-http': 5.3.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.972.15': + dependencies: + '@aws-sdk/core': 3.973.15 + '@aws-sdk/types': 3.973.4 + '@aws-sdk/util-endpoints': 3.996.3 + '@smithy/core': 3.23.6 + '@smithy/protocol-http': 5.3.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-websocket@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.4 + '@aws-sdk/util-format-url': 3.972.6 + '@smithy/eventstream-codec': 4.2.10 + '@smithy/eventstream-serde-browser': 4.2.10 + '@smithy/fetch-http-handler': 5.3.11 + '@smithy/protocol-http': 5.3.10 + '@smithy/signature-v4': 5.3.10 + '@smithy/types': 4.13.0 + '@smithy/util-base64': 4.3.1 + '@smithy/util-hex-encoding': 4.2.1 + '@smithy/util-utf8': 4.2.1 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.996.3': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.973.15 + '@aws-sdk/middleware-host-header': 3.972.6 + '@aws-sdk/middleware-logger': 3.972.6 + '@aws-sdk/middleware-recursion-detection': 3.972.6 + '@aws-sdk/middleware-user-agent': 3.972.15 + '@aws-sdk/region-config-resolver': 3.972.6 + '@aws-sdk/types': 3.973.4 + '@aws-sdk/util-endpoints': 3.996.3 + '@aws-sdk/util-user-agent-browser': 3.972.6 + '@aws-sdk/util-user-agent-node': 3.973.0 + '@smithy/config-resolver': 4.4.9 + '@smithy/core': 3.23.6 + '@smithy/fetch-http-handler': 5.3.11 + '@smithy/hash-node': 4.2.10 + '@smithy/invalid-dependency': 4.2.10 + '@smithy/middleware-content-length': 4.2.10 + '@smithy/middleware-endpoint': 4.4.20 + '@smithy/middleware-retry': 4.4.37 + '@smithy/middleware-serde': 4.2.11 + '@smithy/middleware-stack': 4.2.10 + '@smithy/node-config-provider': 4.3.10 + '@smithy/node-http-handler': 4.4.12 + '@smithy/protocol-http': 5.3.10 + '@smithy/smithy-client': 4.12.0 + '@smithy/types': 4.13.0 + '@smithy/url-parser': 4.2.10 + '@smithy/util-base64': 4.3.1 + '@smithy/util-body-length-browser': 4.2.1 + '@smithy/util-body-length-node': 4.2.2 + '@smithy/util-defaults-mode-browser': 4.3.36 + '@smithy/util-defaults-mode-node': 4.2.39 + '@smithy/util-endpoints': 3.3.1 + '@smithy/util-middleware': 4.2.10 + '@smithy/util-retry': 4.2.10 + '@smithy/util-utf8': 4.2.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.972.6': + dependencies: + '@aws-sdk/types': 3.973.4 + '@smithy/config-resolver': 4.4.9 + '@smithy/node-config-provider': 4.3.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1000.0': + dependencies: + '@aws-sdk/core': 3.973.15 + '@aws-sdk/nested-clients': 3.996.3 + '@aws-sdk/types': 3.973.4 + '@smithy/property-provider': 4.2.10 + '@smithy/shared-ini-file-loader': 4.4.5 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/token-providers@3.999.0': + dependencies: + '@aws-sdk/core': 3.973.15 + '@aws-sdk/nested-clients': 3.996.3 + '@aws-sdk/types': 3.973.4 + '@smithy/property-provider': 4.2.10 + '@smithy/shared-ini-file-loader': 4.4.5 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.973.4': + dependencies: + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.996.3': + dependencies: + '@aws-sdk/types': 3.973.4 + '@smithy/types': 4.13.0 + '@smithy/url-parser': 4.2.10 + '@smithy/util-endpoints': 3.3.1 + tslib: 2.8.1 + + '@aws-sdk/util-format-url@3.972.6': + dependencies: + '@aws-sdk/types': 3.973.4 + '@smithy/querystring-builder': 4.2.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.965.4': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.972.6': + dependencies: + '@aws-sdk/types': 3.973.4 + '@smithy/types': 4.13.0 + bowser: 2.14.1 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.973.0': + dependencies: + '@aws-sdk/middleware-user-agent': 3.972.15 + '@aws-sdk/types': 3.973.4 + '@smithy/node-config-provider': 4.3.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.972.8': + dependencies: + '@smithy/types': 4.13.0 + fast-xml-parser: 5.3.6 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.2.3': {} + + '@babel/runtime@7.28.6': {} + + '@borewit/text-codec@0.2.1': {} + + '@google/genai@1.34.0': + dependencies: + google-auth-library: 10.6.1 + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@isaacs/cliui@9.0.0': {} + + '@mariozechner/clipboard-darwin-arm64@0.3.2': + optional: true + + '@mariozechner/clipboard-darwin-universal@0.3.2': + optional: true + + '@mariozechner/clipboard-darwin-x64@0.3.2': + optional: true + + '@mariozechner/clipboard-linux-arm64-gnu@0.3.2': + optional: true + + '@mariozechner/clipboard-linux-arm64-musl@0.3.2': + optional: true + + '@mariozechner/clipboard-linux-riscv64-gnu@0.3.2': + optional: true + + '@mariozechner/clipboard-linux-x64-gnu@0.3.2': + optional: true + + '@mariozechner/clipboard-linux-x64-musl@0.3.2': + optional: true + + '@mariozechner/clipboard-win32-arm64-msvc@0.3.2': + optional: true + + '@mariozechner/clipboard-win32-x64-msvc@0.3.2': + optional: true + + '@mariozechner/clipboard@0.3.2': + optionalDependencies: + '@mariozechner/clipboard-darwin-arm64': 0.3.2 + '@mariozechner/clipboard-darwin-universal': 0.3.2 + '@mariozechner/clipboard-darwin-x64': 0.3.2 + '@mariozechner/clipboard-linux-arm64-gnu': 0.3.2 + '@mariozechner/clipboard-linux-arm64-musl': 0.3.2 + '@mariozechner/clipboard-linux-riscv64-gnu': 0.3.2 + '@mariozechner/clipboard-linux-x64-gnu': 0.3.2 + '@mariozechner/clipboard-linux-x64-musl': 0.3.2 + '@mariozechner/clipboard-win32-arm64-msvc': 0.3.2 + '@mariozechner/clipboard-win32-x64-msvc': 0.3.2 + + '@mariozechner/jiti@2.6.5': + dependencies: + std-env: 3.10.0 + yoctocolors: 2.1.2 + + '@mariozechner/pi-agent-core@0.50.9(ws@8.19.0)(zod@3.25.76)': + dependencies: + '@mariozechner/pi-ai': 0.50.9(ws@8.19.0)(zod@3.25.76) + '@mariozechner/pi-tui': 0.50.9 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@mariozechner/pi-ai@0.50.9(ws@8.19.0)(zod@3.25.76)': + dependencies: + '@anthropic-ai/sdk': 0.71.2(zod@3.25.76) + '@aws-sdk/client-bedrock-runtime': 3.1000.0 + '@google/genai': 1.34.0 + '@mistralai/mistralai': 1.10.0 + '@sinclair/typebox': 0.34.48 + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + chalk: 5.6.2 + openai: 6.10.0(ws@8.19.0)(zod@3.25.76) + partial-json: 0.1.7 + proxy-agent: 6.5.0 + undici: 7.22.0 + zod-to-json-schema: 3.25.1(zod@3.25.76) + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@mariozechner/pi-coding-agent@0.50.9(ws@8.19.0)(zod@3.25.76)': + dependencies: + '@mariozechner/clipboard': 0.3.2 + '@mariozechner/jiti': 2.6.5 + '@mariozechner/pi-agent-core': 0.50.9(ws@8.19.0)(zod@3.25.76) + '@mariozechner/pi-ai': 0.50.9(ws@8.19.0)(zod@3.25.76) + '@mariozechner/pi-tui': 0.50.9 + '@silvia-odwyer/photon-node': 0.3.4 + chalk: 5.6.2 + cli-highlight: 2.1.11 + diff: 8.0.3 + file-type: 21.3.0 + glob: 11.1.0 + ignore: 7.0.5 + marked: 15.0.12 + minimatch: 10.2.4 + proper-lockfile: 4.1.2 + yaml: 2.8.2 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@mariozechner/pi-tui@0.50.9': + dependencies: + '@types/mime-types': 2.1.4 + chalk: 5.6.2 + get-east-asian-width: 1.5.0 + marked: 15.0.12 + mime-types: 3.0.2 + + '@mistralai/mistralai@1.10.0': + dependencies: + zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@silvia-odwyer/photon-node@0.3.4': {} + + '@sinclair/typebox@0.34.48': {} + + '@smithy/abort-controller@4.2.10': + dependencies: + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/config-resolver@4.4.9': + dependencies: + '@smithy/node-config-provider': 4.3.10 + '@smithy/types': 4.13.0 + '@smithy/util-config-provider': 4.2.1 + '@smithy/util-endpoints': 3.3.1 + '@smithy/util-middleware': 4.2.10 + tslib: 2.8.1 + + '@smithy/core@3.23.6': + dependencies: + '@smithy/middleware-serde': 4.2.11 + '@smithy/protocol-http': 5.3.10 + '@smithy/types': 4.13.0 + '@smithy/util-base64': 4.3.1 + '@smithy/util-body-length-browser': 4.2.1 + '@smithy/util-middleware': 4.2.10 + '@smithy/util-stream': 4.5.15 + '@smithy/util-utf8': 4.2.1 + '@smithy/uuid': 1.1.1 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.2.10': + dependencies: + '@smithy/node-config-provider': 4.3.10 + '@smithy/property-provider': 4.2.10 + '@smithy/types': 4.13.0 + '@smithy/url-parser': 4.2.10 + tslib: 2.8.1 + + '@smithy/eventstream-codec@4.2.10': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.13.0 + '@smithy/util-hex-encoding': 4.2.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.2.10': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.3.10': + dependencies: + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.2.10': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-universal@4.2.10': + dependencies: + '@smithy/eventstream-codec': 4.2.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.3.11': + dependencies: + '@smithy/protocol-http': 5.3.10 + '@smithy/querystring-builder': 4.2.10 + '@smithy/types': 4.13.0 + '@smithy/util-base64': 4.3.1 + tslib: 2.8.1 + + '@smithy/hash-node@4.2.10': + dependencies: + '@smithy/types': 4.13.0 + '@smithy/util-buffer-from': 4.2.1 + '@smithy/util-utf8': 4.2.1 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.2.10': + dependencies: + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/is-array-buffer@4.2.1': + dependencies: + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.2.10': + dependencies: + '@smithy/protocol-http': 5.3.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.4.20': + dependencies: + '@smithy/core': 3.23.6 + '@smithy/middleware-serde': 4.2.11 + '@smithy/node-config-provider': 4.3.10 + '@smithy/shared-ini-file-loader': 4.4.5 + '@smithy/types': 4.13.0 + '@smithy/url-parser': 4.2.10 + '@smithy/util-middleware': 4.2.10 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.4.37': + dependencies: + '@smithy/node-config-provider': 4.3.10 + '@smithy/protocol-http': 5.3.10 + '@smithy/service-error-classification': 4.2.10 + '@smithy/smithy-client': 4.12.0 + '@smithy/types': 4.13.0 + '@smithy/util-middleware': 4.2.10 + '@smithy/util-retry': 4.2.10 + '@smithy/uuid': 1.1.1 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.2.11': + dependencies: + '@smithy/protocol-http': 5.3.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.2.10': + dependencies: + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.3.10': + dependencies: + '@smithy/property-provider': 4.2.10 + '@smithy/shared-ini-file-loader': 4.4.5 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.4.12': + dependencies: + '@smithy/abort-controller': 4.2.10 + '@smithy/protocol-http': 5.3.10 + '@smithy/querystring-builder': 4.2.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/property-provider@4.2.10': + dependencies: + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/protocol-http@5.3.10': + dependencies: + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.2.10': + dependencies: + '@smithy/types': 4.13.0 + '@smithy/util-uri-escape': 4.2.1 + tslib: 2.8.1 + + '@smithy/querystring-parser@4.2.10': + dependencies: + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/service-error-classification@4.2.10': + dependencies: + '@smithy/types': 4.13.0 + + '@smithy/shared-ini-file-loader@4.4.5': + dependencies: + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.3.10': + dependencies: + '@smithy/is-array-buffer': 4.2.1 + '@smithy/protocol-http': 5.3.10 + '@smithy/types': 4.13.0 + '@smithy/util-hex-encoding': 4.2.1 + '@smithy/util-middleware': 4.2.10 + '@smithy/util-uri-escape': 4.2.1 + '@smithy/util-utf8': 4.2.1 + tslib: 2.8.1 + + '@smithy/smithy-client@4.12.0': + dependencies: + '@smithy/core': 3.23.6 + '@smithy/middleware-endpoint': 4.4.20 + '@smithy/middleware-stack': 4.2.10 + '@smithy/protocol-http': 5.3.10 + '@smithy/types': 4.13.0 + '@smithy/util-stream': 4.5.15 + tslib: 2.8.1 + + '@smithy/types@4.13.0': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.2.10': + dependencies: + '@smithy/querystring-parser': 4.2.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/util-base64@4.3.1': + dependencies: + '@smithy/util-buffer-from': 4.2.1 + '@smithy/util-utf8': 4.2.1 + tslib: 2.8.1 + + '@smithy/util-body-length-browser@4.2.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-body-length-node@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-buffer-from@4.2.1': + dependencies: + '@smithy/is-array-buffer': 4.2.1 + tslib: 2.8.1 + + '@smithy/util-config-provider@4.2.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-defaults-mode-browser@4.3.36': + dependencies: + '@smithy/property-provider': 4.2.10 + '@smithy/smithy-client': 4.12.0 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/util-defaults-mode-node@4.2.39': + dependencies: + '@smithy/config-resolver': 4.4.9 + '@smithy/credential-provider-imds': 4.2.10 + '@smithy/node-config-provider': 4.3.10 + '@smithy/property-provider': 4.2.10 + '@smithy/smithy-client': 4.12.0 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/util-endpoints@3.3.1': + dependencies: + '@smithy/node-config-provider': 4.3.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.2.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-middleware@4.2.10': + dependencies: + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/util-retry@4.2.10': + dependencies: + '@smithy/service-error-classification': 4.2.10 + '@smithy/types': 4.13.0 + tslib: 2.8.1 + + '@smithy/util-stream@4.5.15': + dependencies: + '@smithy/fetch-http-handler': 5.3.11 + '@smithy/node-http-handler': 4.4.12 + '@smithy/types': 4.13.0 + '@smithy/util-base64': 4.3.1 + '@smithy/util-buffer-from': 4.2.1 + '@smithy/util-hex-encoding': 4.2.1 + '@smithy/util-utf8': 4.2.1 + tslib: 2.8.1 + + '@smithy/util-uri-escape@4.2.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.2.1': + dependencies: + '@smithy/util-buffer-from': 4.2.1 + tslib: 2.8.1 + + '@smithy/uuid@1.1.1': + dependencies: + tslib: 2.8.1 + + '@tokenizer/inflate@0.4.1': + dependencies: + debug: 4.4.3 + token-types: 6.1.2 + transitivePeerDependencies: + - supports-color + + '@tokenizer/token@0.3.0': {} + + '@tootallnate/quickjs-emscripten@0.23.0': {} + + '@types/mime-types@2.1.4': {} + + '@types/node@25.3.3': + dependencies: + undici-types: 7.18.2 + + agent-base@7.1.4: {} + + ajv-formats@3.0.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + + any-promise@1.3.0: {} + + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + base64-js@1.5.1: {} + + basic-ftp@5.2.0: {} + + bignumber.js@9.3.1: {} + + bowser@2.14.1: {} + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.4: + dependencies: + balanced-match: 4.0.4 + + buffer-equal-constant-time@1.0.1: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + cli-highlight@2.1.11: + dependencies: + chalk: 4.1.2 + highlight.js: 10.7.3 + mz: 2.7.0 + parse5: 5.1.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + yargs: 16.2.0 + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + data-uri-to-buffer@4.0.1: {} + + data-uri-to-buffer@6.0.2: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + + diff@8.0.3: {} + + eastasianwidth@0.2.0: {} + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + escalade@3.2.0: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + esprima@4.0.1: {} + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + extend@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + fast-uri@3.1.0: {} + + fast-xml-parser@5.3.6: + dependencies: + strnum: 2.2.0 + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + file-type@21.3.0: + dependencies: + '@tokenizer/inflate': 0.4.1 + strtok3: 10.3.4 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + gaxios@7.1.3: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + node-fetch: 3.3.2 + rimraf: 5.0.10 + transitivePeerDependencies: + - supports-color + + gcp-metadata@8.1.2: + dependencies: + gaxios: 7.1.3 + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.5.0: {} + + get-uri@6.0.5: + dependencies: + basic-ftp: 5.2.0 + data-uri-to-buffer: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@11.1.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.2.3 + minimatch: 10.2.4 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.2 + + google-auth-library@10.6.1: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.1.3 + gcp-metadata: 8.1.2 + google-logging-utils: 1.1.3 + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + + google-logging-utils@1.1.3: {} + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + highlight.js@10.7.3: {} + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + ieee754@1.2.1: {} + + ignore@7.0.5: {} + + ip-address@10.1.0: {} + + is-fullwidth-code-point@3.0.0: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jackspeak@4.2.3: + dependencies: + '@isaacs/cliui': 9.0.0 + + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + + json-schema-to-ts@3.1.1: + dependencies: + '@babel/runtime': 7.28.6 + ts-algebra: 2.0.0 + + json-schema-traverse@1.0.0: {} + + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.1: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + + lru-cache@10.4.3: {} + + lru-cache@11.2.6: {} + + lru-cache@7.18.3: {} + + marked@15.0.12: {} + + mime-db@1.54.0: {} + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + minimatch@10.2.4: + dependencies: + brace-expansion: 5.0.4 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.0.2 + + minipass@7.1.3: {} + + ms@2.1.3: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + netmask@2.0.2: {} + + node-domexception@1.0.0: {} + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + object-assign@4.1.1: {} + + openai@6.10.0(ws@8.19.0)(zod@3.25.76): + optionalDependencies: + ws: 8.19.0 + zod: 3.25.76 + + pac-proxy-agent@7.2.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.4 + debug: 4.4.3 + get-uri: 6.0.5 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + + package-json-from-dist@1.0.1: {} + + parse5-htmlparser2-tree-adapter@6.0.1: + dependencies: + parse5: 6.0.1 + + parse5@5.1.1: {} + + parse5@6.0.1: {} + + partial-json@0.1.7: {} + + path-key@3.1.1: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + path-scurry@2.0.2: + dependencies: + lru-cache: 11.2.6 + minipass: 7.1.3 + + proper-lockfile@4.1.2: + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + + proxy-agent@6.5.0: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 7.18.3 + pac-proxy-agent: 7.2.0 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + retry@0.12.0: {} + + rimraf@5.0.10: + dependencies: + glob: 10.5.0 + + safe-buffer@5.2.1: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + smart-buffer@4.2.0: {} + + socks-proxy-agent@8.0.5: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + socks: 2.8.7 + transitivePeerDependencies: + - supports-color + + socks@2.8.7: + dependencies: + ip-address: 10.1.0 + smart-buffer: 4.2.0 + + source-map@0.6.1: + optional: true + + std-env@3.10.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strnum@2.2.0: {} + + strtok3@10.3.4: + dependencies: + '@tokenizer/token': 0.3.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + token-types@6.1.2: + dependencies: + '@borewit/text-codec': 0.2.1 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + + ts-algebra@2.0.0: {} + + tslib@2.8.1: {} + + uint8array-extras@1.5.0: {} + + undici-types@7.18.2: {} + + undici@7.22.0: {} + + vscode-jsonrpc@8.2.0: {} + + vscode-languageserver-protocol@3.17.5: + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + + vscode-languageserver-types@3.17.5: {} + + web-streams-polyfill@3.3.3: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + ws@8.19.0: {} + + y18n@5.0.8: {} + + yaml@2.8.2: {} + + yargs-parser@20.2.9: {} + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yoctocolors@2.1.2: {} + + zod-to-json-schema@3.25.1(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod@3.25.76: {} diff --git a/pi/files/agent/extensions/lsp/tsconfig.json b/pi/files/agent/extensions/lsp/tsconfig.json new file mode 100644 index 0000000..c23ee3a --- /dev/null +++ b/pi/files/agent/extensions/lsp/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "declaration": true, + "types": ["node"] + }, + "include": ["*.ts"] +}