diff --git a/.mise.toml b/.mise.toml index e4a1848..0b617da 100644 --- a/.mise.toml +++ b/.mise.toml @@ -1,3 +1,4 @@ [tools] -node = "24.15.0" +node = "26.1.0" +bun= "1.3.14" pnpm = "10.33.3" diff --git a/AGENTS.md b/AGENTS.md index 1075dee..dfc31a4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,12 +32,21 @@ Default implementation work should go into the Clack implementation. Do not work - Keep beau Ink UI components focused on rendering and input handling. - Keep backend/API request logic out of presentation components; expose it through query or mutation hooks. +## Workspace Layout + +This is a pnpm workspace. All packages live under `packages/`. + +- `packages/braintrust-wizard/` — the main wizard CLI (Clack + beau variants). +- `packages/bt-wizard-harness/` — the pi-coding-agent harness scaffold. + +Root-level scripts (`pnpm build`, `pnpm lint`, etc.) delegate to the packages via `--filter` or `-r`. + ## Implementation Notes -- Source files live under `src/`. -- Tests live under `test/`. -- The default CLI entrypoint is `src/cli.ts`; Rolldown emits `dist/cli.js`. -- The beau CLI entrypoint is `src/beau/cli.tsx`; Rolldown emits `dist/cli.beau.js`. -- Shared wizard copy lives in `src/wizard-copy.ts`; keep both variants using it. -- `src/query-client.ts` owns QueryClient creation and should remain the central place for query defaults. +- Wizard source files live under `packages/braintrust-wizard/src/`. +- Wizard tests live under `packages/braintrust-wizard/test/`. +- The default CLI entrypoint is `packages/braintrust-wizard/src/cli.ts`; Rolldown emits `packages/braintrust-wizard/dist/cli.js`. +- The beau CLI entrypoint is `packages/braintrust-wizard/src/beau/cli.tsx`; Rolldown emits `packages/braintrust-wizard/dist/cli.beau.js`. +- Shared wizard copy lives in `packages/braintrust-wizard/src/wizard-copy.ts`; keep both variants using it. +- `packages/braintrust-wizard/src/query-client.ts` owns QueryClient creation and should remain the central place for query defaults. - Do not add SEA packaging yet; the current build targets are JavaScript bundles. diff --git a/package.json b/package.json index 6805d1b..d99b846 100644 --- a/package.json +++ b/package.json @@ -1,45 +1,23 @@ { - "name": "braintrust-wizard", + "name": "crank", "version": "0.0.0", "private": true, - "description": "CLI wizard to get your project set up with Braintrust", + "description": "Braintrust wizard monorepo", "license": "MIT", "type": "module", - "bin": { - "braintrust-wizard": "./dist/cli.js" - }, "packageManager": "pnpm@10.33.3", "scripts": { - "start": "pnpm build && node dist/cli.js", - "build": "rolldown -c", - "start:beau": "pnpm build:beau && node dist/cli.beau.js", - "build:beau": "rolldown -c rolldown.beau.config.mjs", - "typings": "tsc --noEmit", - "test": "vitest run", - "lint": "eslint .", + "start": "pnpm --filter braintrust-wizard start", + "build": "pnpm --filter braintrust-wizard build", + "start:beau": "pnpm --filter braintrust-wizard start:beau", + "build:beau": "pnpm --filter braintrust-wizard build:beau", + "typings": "pnpm -r run typings", + "test": "pnpm -r run test", + "lint": "pnpm -r run lint", "format": "prettier --write .", "format:check": "prettier --check ." }, - "dependencies": { - "@clack/prompts": "1.3.0", - "@tanstack/react-query": "5.100.9", - "ink": "7.0.2", - "react": "19.2.5", - "react-devtools-core": "7.0.1" - }, "devDependencies": { - "@eslint/js": "10.0.1", - "@types/node": "24.12.2", - "@types/react": "19.2.14", - "eslint": "10.3.0", - "eslint-config-prettier": "10.1.8", - "eslint-plugin-react": "7.37.5", - "eslint-plugin-react-hooks": "7.1.1", - "globals": "17.6.0", - "prettier": "3.8.3", - "rolldown": "1.0.0-rc.18", - "typescript": "6.0.3", - "typescript-eslint": "8.59.2", - "vitest": "4.1.5" + "prettier": "3.8.3" } } diff --git a/eslint.config.mjs b/packages/braintrust-wizard/eslint.config.mjs similarity index 100% rename from eslint.config.mjs rename to packages/braintrust-wizard/eslint.config.mjs diff --git a/packages/braintrust-wizard/package.json b/packages/braintrust-wizard/package.json new file mode 100644 index 0000000..91a0601 --- /dev/null +++ b/packages/braintrust-wizard/package.json @@ -0,0 +1,51 @@ +{ + "name": "braintrust-wizard", + "version": "0.0.0", + "private": true, + "description": "CLI wizard to get your project set up with Braintrust", + "license": "MIT", + "type": "module", + "bin": { + "braintrust-wizard": "./dist/cli.js" + }, + "scripts": { + "start": "pnpm build && node dist/cli.js", + "build": "rolldown -c", + "start:beau": "pnpm build:beau && node dist/cli.beau.js", + "build:beau": "rolldown -c rolldown.beau.config.mjs", + "typings": "tsc --noEmit", + "test": "vitest run", + "lint": "eslint .", + "format": "prettier --write .", + "format:check": "prettier --check ." + }, + "dependencies": { + "@braintrust/bt-wizard-harness": "workspace:*", + "@inquirer/search": "4.1.8", + "@clack/prompts": "1.3.0", + "@tanstack/react-query": "5.100.9", + "ignore": "^7.0.5", + "ink": "7.0.2", + "open": "^11.0.0", + "react": "19.2.5", + "react-devtools-core": "7.0.1", + "yargs": "^18.0.0" + }, + "devDependencies": { + "@braintrust/proxy": "0.0.9", + "@eslint/js": "10.0.1", + "@types/node": "24.12.2", + "@types/react": "19.2.14", + "@types/yargs": "^17.0.35", + "eslint": "10.3.0", + "eslint-config-prettier": "10.1.8", + "eslint-plugin-react": "7.37.5", + "eslint-plugin-react-hooks": "7.1.1", + "globals": "17.6.0", + "prettier": "3.8.3", + "rolldown": "1.0.0-rc.18", + "typescript": "6.0.3", + "typescript-eslint": "8.59.2", + "vitest": "4.1.5" + } +} diff --git a/rolldown.beau.config.mjs b/packages/braintrust-wizard/rolldown.beau.config.mjs similarity index 100% rename from rolldown.beau.config.mjs rename to packages/braintrust-wizard/rolldown.beau.config.mjs diff --git a/packages/braintrust-wizard/rolldown.config.mjs b/packages/braintrust-wizard/rolldown.config.mjs new file mode 100644 index 0000000..224bbb1 --- /dev/null +++ b/packages/braintrust-wizard/rolldown.config.mjs @@ -0,0 +1,27 @@ +import { defineConfig } from "rolldown"; + +export default defineConfig([ + { + input: "src/cli.ts", + output: { + banner: "#!/usr/bin/env node", + codeSplitting: false, + file: "dist/cli.mjs", + format: "esm", + sourcemap: true, + }, + platform: "node", + external: [/^node:/], + }, + { + input: "src/crank-telemetry.ts", + output: { + codeSplitting: false, + file: "dist/crank-telemetry.mjs", + format: "esm", + sourcemap: true, + }, + platform: "node", + external: [/^node:/], + }, +]); diff --git a/packages/braintrust-wizard/src/auth.ts b/packages/braintrust-wizard/src/auth.ts new file mode 100644 index 0000000..f017e21 --- /dev/null +++ b/packages/braintrust-wizard/src/auth.ts @@ -0,0 +1,228 @@ +export type WizardSigninCreateResponse = { + readonly id: string; + readonly poll_token: string; + readonly login_path: string; + readonly login_url: string; + readonly expires_at: string; +}; + +export type WizardSigninOrgInfo = { + readonly id: string; + readonly name: string; + readonly api_url?: string | null; + readonly proxy_url?: string | null; + readonly realtime_url?: string | null; + readonly is_universal_api?: boolean | null; + readonly git_metadata?: unknown; +}; + +export type WizardSigninProject = { + readonly id: string; + readonly name: string; + readonly org_id: string; + readonly description?: string | null; +}; + +export type WizardSigninCompleteResult = { + readonly apiKey: string; + readonly orgInfo: WizardSigninOrgInfo; + readonly project: WizardSigninProject; +}; + +export type WizardSigninEvents = { + readonly onLoginUrl: (info: { + readonly loginUrl: string; + readonly expiresAt: string; + }) => void; + readonly onTryOpenBrowser: (url: string) => Promise; +}; + +const POLL_INTERVAL_MS = 2000; +const SLOW_DOWN_INCREMENT_MS = 1000; +const MAX_POLL_INTERVAL_MS = 30_000; +const POLL_HARD_TIMEOUT_MS = 3 * 60 * 1000; +const CREATE_REQUEST_TIMEOUT_MS = 15_000; +const POLL_REQUEST_TIMEOUT_MS = 30_000; + +/** + * Browser-mediated wizard sign-in. + * + * Endpoints (added by the braintrust-wizard-login-flow PR): + * POST {appUrl}/api/cli/wizard-signin/create + * GET {appUrl}/api/cli/wizard-signin/poll?id=... + * (Authorization: Bearer ) + * + * The poll response is one of: + * { status: "pending", expires_at } + * { status: "expired" } + * { status: "claimed" } + * { status: "complete", api_key, org_info, project } + */ +export class WizardSigninAuthClient { + constructor( + private readonly appUrl: string, + private readonly clientName: string = "crank", + ) {} + + async createSession(): Promise { + const res = await fetch(`${this.appUrl}/api/cli/wizard-signin/create`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify({ client_name: this.clientName }), + signal: AbortSignal.timeout(CREATE_REQUEST_TIMEOUT_MS), + }); + if (!res.ok) { + throw new Error( + `Wizard sign-in create failed: ${res.status} ${await res.text()}`, + ); + } + return (await res.json()) as WizardSigninCreateResponse; + } + + async pollSession(args: { + readonly id: string; + readonly pollToken: string; + readonly sleep?: (ms: number) => Promise; + }): Promise { + const sleep = args.sleep ?? defaultSleep; + let interval = POLL_INTERVAL_MS; + const deadline = Date.now() + POLL_HARD_TIMEOUT_MS; + while (Date.now() < deadline) { + await sleep(interval); + const url = `${this.appUrl}/api/cli/wizard-signin/poll?id=${encodeURIComponent(args.id)}`; + const res = await fetch(url, { + method: "GET", + headers: { + Authorization: `Bearer ${args.pollToken}`, + Accept: "application/json", + }, + signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS), + }); + if (res.status === 429) { + interval = Math.min( + interval + SLOW_DOWN_INCREMENT_MS, + MAX_POLL_INTERVAL_MS, + ); + res.body?.cancel(); + continue; + } + const json = (await res.json().catch(() => ({}))) as Record< + string, + unknown + >; + if (!res.ok) { + throw new Error( + `Wizard sign-in poll failed: ${res.status} ${JSON.stringify(json)}`, + ); + } + const status = json["status"]; + switch (status) { + case "pending": + continue; + case "expired": + throw new Error("Wizard sign-in session expired before approval."); + case "claimed": + throw new Error( + "Wizard sign-in session was already claimed by another client.", + ); + case "complete": + return parseCompleteResponse(json); + default: + throw new Error( + `Unexpected wizard sign-in status: ${JSON.stringify(json)}`, + ); + } + } + throw new Error("Wizard sign-in session timed out."); + } + + async login(events: WizardSigninEvents): Promise { + const session = await this.createSession(); + events.onLoginUrl({ + loginUrl: session.login_url, + expiresAt: session.expires_at, + }); + await events.onTryOpenBrowser(session.login_url); + return this.pollSession({ + id: session.id, + pollToken: session.poll_token, + }); + } +} + +function parseCompleteResponse( + json: Record, +): WizardSigninCompleteResult { + const apiKey = json["api_key"]; + if (typeof apiKey !== "string" || apiKey.length === 0) { + throw new Error("Wizard sign-in completed without an api_key"); + } + const orgInfo = parseOrgInfo(json["org_info"]); + const project = parseProject(json["project"]); + return { apiKey, orgInfo, project }; +} + +function parseOrgInfo(value: unknown): WizardSigninOrgInfo { + if (!isObject(value)) { + throw new Error("Wizard sign-in completed without org_info"); + } + const id = value["id"]; + const name = value["name"]; + if (typeof id !== "string" || typeof name !== "string") { + throw new Error("Wizard sign-in org_info missing id/name"); + } + return { + id, + name, + api_url: optionalString(value["api_url"]), + proxy_url: optionalString(value["proxy_url"]), + realtime_url: optionalString(value["realtime_url"]), + is_universal_api: + typeof value["is_universal_api"] === "boolean" + ? value["is_universal_api"] + : null, + git_metadata: value["git_metadata"], + }; +} + +function parseProject(value: unknown): WizardSigninProject { + if (!isObject(value)) { + throw new Error("Wizard sign-in completed without project"); + } + const id = value["id"]; + const name = value["name"]; + const orgId = value["org_id"]; + if ( + typeof id !== "string" || + typeof name !== "string" || + typeof orgId !== "string" + ) { + throw new Error("Wizard sign-in project missing id/name/org_id"); + } + return { + id, + name, + org_id: orgId, + description: optionalString(value["description"]), + }; +} + +function optionalString(value: unknown): string | null { + if (typeof value === "string") { + return value; + } + return null; +} + +function isObject(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function defaultSleep(ms: number): Promise { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} diff --git a/src/beau/App.tsx b/packages/braintrust-wizard/src/beau/App.tsx similarity index 100% rename from src/beau/App.tsx rename to packages/braintrust-wizard/src/beau/App.tsx diff --git a/src/beau/AppRoot.tsx b/packages/braintrust-wizard/src/beau/AppRoot.tsx similarity index 100% rename from src/beau/AppRoot.tsx rename to packages/braintrust-wizard/src/beau/AppRoot.tsx diff --git a/src/beau/SignalStrips.tsx b/packages/braintrust-wizard/src/beau/SignalStrips.tsx similarity index 100% rename from src/beau/SignalStrips.tsx rename to packages/braintrust-wizard/src/beau/SignalStrips.tsx diff --git a/src/beau/brand-colors.ts b/packages/braintrust-wizard/src/beau/brand-colors.ts similarity index 100% rename from src/beau/brand-colors.ts rename to packages/braintrust-wizard/src/beau/brand-colors.ts diff --git a/src/beau/brand-logo.tsx b/packages/braintrust-wizard/src/beau/brand-logo.tsx similarity index 100% rename from src/beau/brand-logo.tsx rename to packages/braintrust-wizard/src/beau/brand-logo.tsx diff --git a/src/beau/cli.tsx b/packages/braintrust-wizard/src/beau/cli.tsx similarity index 100% rename from src/beau/cli.tsx rename to packages/braintrust-wizard/src/beau/cli.tsx diff --git a/src/beau/tui-state.tsx b/packages/braintrust-wizard/src/beau/tui-state.tsx similarity index 100% rename from src/beau/tui-state.tsx rename to packages/braintrust-wizard/src/beau/tui-state.tsx diff --git a/packages/braintrust-wizard/src/braintrust-api.ts b/packages/braintrust-wizard/src/braintrust-api.ts new file mode 100644 index 0000000..93c6398 --- /dev/null +++ b/packages/braintrust-wizard/src/braintrust-api.ts @@ -0,0 +1,218 @@ +export type Org = { + readonly id: string; + readonly name: string; + readonly api_url?: string | null; + readonly proxy_url?: string | null; +}; + +export type Project = { + readonly id: string; + readonly name: string; + readonly org_id: string; +}; + +export type ApiKey = { + readonly id: string; + readonly name: string; + readonly preview_name?: string; +}; + +export type ApiKeyWithSecret = ApiKey & { + readonly key: string; +}; + +export type CurrentUser = { + readonly id: string; + readonly given_name?: string | null; + readonly family_name?: string | null; + readonly email?: string | null; +}; + +export type DataPlane = "us" | "eu"; + +const DATA_PLANE_API_URLS: Record = { + us: "https://api.braintrust.dev", + eu: "https://api.eu.braintrust.dev", +}; + +export function dataPlaneApiUrl(plane: DataPlane): string { + return DATA_PLANE_API_URLS[plane]; +} + +export class BraintrustApiClient { + constructor( + private readonly apiUrl: string, + private readonly token: string, + ) {} + + private async request( + method: string, + path: string, + body?: unknown, + ): Promise<{ data: T; headers: Headers }> { + const res = await fetch(`${this.apiUrl}${path}`, { + method, + headers: { + Authorization: `Bearer ${this.token}`, + Accept: "application/json", + ...(body !== undefined ? { "Content-Type": "application/json" } : {}), + }, + ...(body !== undefined ? { body: JSON.stringify(body) } : {}), + }); + if (!res.ok) { + const text = await res.text().catch(() => ""); + throw new BraintrustApiError(res.status, method, path, text); + } + const data = (await res.json()) as T; + return { data, headers: res.headers }; + } + + async listOrgs(): Promise { + const { data } = await this.request<{ objects: Org[] }>( + "GET", + "/v1/organization?limit=200", + ); + return data.objects; + } + + async createOrg(args: { + readonly orgName: string; + readonly dataPlane: DataPlane; + }): Promise<{ readonly id: string; readonly existed: boolean }> { + const apiUrl = dataPlaneApiUrl(args.dataPlane); + const { data, headers } = await this.request( + "POST", + "/v1/organization", + { org_name: args.orgName, api_url: apiUrl }, + ); + const id = typeof data === "string" ? data : (data as { id: string }).id; + return { id, existed: headers.get("x-bt-found-existing") === "true" }; + } + + async listProjects(orgId: string): Promise { + const { data } = await this.request<{ objects: Project[] }>( + "GET", + `/v1/project?org_id=${encodeURIComponent(orgId)}&limit=500`, + ); + return data.objects; + } + + async createProject(args: { + readonly orgId: string; + readonly name: string; + }): Promise { + const { data } = await this.request("POST", "/v1/project", { + org_id: args.orgId, + name: args.name, + }); + return data; + } + + async listApiKeyNames(orgId: string): Promise { + const { data } = await this.request<{ objects: ApiKey[] }>( + "GET", + `/v1/api_key?org_id=${encodeURIComponent(orgId)}&limit=500`, + ); + return data.objects.map((k) => k.name); + } + + async createApiKey(args: { + readonly orgId: string; + readonly name: string; + }): Promise { + const { data } = await this.request( + "POST", + "/v1/api_key", + { org_id: args.orgId, name: args.name }, + ); + return data; + } + + async currentUser(): Promise { + const { data } = await this.request("GET", "/v1/user/me"); + return data; + } + + /** + * Like {@link currentUser}, but retries on 401 to ride out the brief + * Clerk-webhook race where a freshly-signed-up user's `bt_auth_id` hasn't + * landed in `publicMetadata` yet. See app/api/actions/util.ts:62 in the + * braintrust monorepo for the same race. + * + * Only 401s are retried; other failures throw immediately. + */ + async currentUserAwaitingProvisioning(args?: { + readonly delaysMs?: readonly number[]; + readonly sleep?: (ms: number) => Promise; + }): Promise { + const delays = args?.delaysMs ?? PROVISIONING_RETRY_DELAYS_MS; + const sleep = args?.sleep ?? defaultSleep; + let lastError: unknown; + for (let attempt = 0; attempt <= delays.length; attempt += 1) { + try { + return await this.currentUser(); + } catch (e) { + lastError = e; + if (!(e instanceof BraintrustApiError) || e.status !== 401) { + throw e; + } + if (attempt === delays.length) { + throw new Error( + "Your Braintrust account is still being provisioned. Please try `bt-wizard` again in a moment.", + { cause: e }, + ); + } + await sleep(delays[attempt]!); + } + } + throw lastError instanceof Error + ? lastError + : new Error("currentUserAwaitingProvisioning: unreachable"); + } +} + +const PROVISIONING_RETRY_DELAYS_MS: readonly number[] = [ + 1000, 1500, 2000, 3000, 4000, +]; + +function defaultSleep(ms: number): Promise { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} + +export class BraintrustApiError extends Error { + constructor( + readonly status: number, + readonly method: string, + readonly path: string, + readonly responseBody: string, + ) { + super(`${method} ${path} → ${status}: ${responseBody.slice(0, 200)}`); + this.name = "BraintrustApiError"; + } +} + +export function buildApiKeyName(args: { + readonly userHandle: string; + readonly existingNames: readonly string[]; +}): string { + const base = `${args.userHandle}-created-by-bt-wizard`; + for (let n = 0; n < 10000; n += 1) { + const candidate = `${base}${n}`; + if (!args.existingNames.includes(candidate)) { + return candidate; + } + } + throw new Error("Could not find a unique API key name"); +} + +export function userHandle(user: CurrentUser): string { + if (user.email && user.email.length > 0) { + return user.email.split("@")[0]?.toLowerCase() ?? user.id; + } + if (user.given_name) { + return user.given_name.toLowerCase().replace(/[^a-z0-9-]/g, "-"); + } + return user.id; +} diff --git a/packages/braintrust-wizard/src/browser.ts b/packages/braintrust-wizard/src/browser.ts new file mode 100644 index 0000000..c484e73 --- /dev/null +++ b/packages/braintrust-wizard/src/browser.ts @@ -0,0 +1,10 @@ +import open from "open"; + +export async function openBrowser(url: string): Promise { + try { + await open(url); + return true; + } catch { + return false; + } +} diff --git a/packages/braintrust-wizard/src/clack-wizard.ts b/packages/braintrust-wizard/src/clack-wizard.ts new file mode 100644 index 0000000..1bcf468 --- /dev/null +++ b/packages/braintrust-wizard/src/clack-wizard.ts @@ -0,0 +1,320 @@ +import { cwd as processCwd } from "node:process"; + +import { WizardSigninAuthClient } from "./auth"; +import { openBrowser } from "./browser"; +import { buildLogsPermalink, buildCleanupMessage } from "./cleanup"; +import { findGitRoot, isGitRepo, writeEnvBraintrust } from "./git"; +import { detectLanguages, type DetectedLanguage } from "./language-detect"; +import { + allocateResultFile, + buildHarnessCommand, + ensureBtOnPath, + runHarness, + writePromptToTemp, +} from "./instrument"; +import type { WizardOptions } from "./options"; +import { renderPrompt } from "./prompt"; +import { LLM_PROVIDERS, type LlmProvider, type CredentialField } from "./providers"; +import { + setTelemetryLanguage, + setTelemetryProvider, + notifyPiRunning, + markTelemetrySigint, +} from "./telemetry"; +import { + DOCS_URL, + NOT_GIT_REPO_WARNING, + PROVIDER_KEY_QUESTION, + PROVIDER_QUESTION, + RUN_HARNESS_QUESTION, + WIZARD_CANCEL_MESSAGE, + WIZARD_TITLE, + promptSavedNote, + gitignoreNote, + wizardLoginPrompt, +} from "./wizard-copy"; + +type SelectOption = { + readonly label: string; + readonly value: T; + readonly hint?: string; +}; + +export type ClackWizardPrompts = { + readonly cancel: (message: string) => void; + readonly confirm: (options: { + readonly initialValue?: boolean; + readonly message: string; + }) => Promise; + readonly intro: (message: string) => void; + readonly isCancel: (value: unknown) => value is symbol; + readonly note: (message: string, title?: string) => void; + readonly outro: (message: string) => void; + readonly password: (options: { + readonly message: string; + }) => Promise; + readonly select: (options: { + readonly message: string; + readonly options: ReadonlyArray>; + }) => Promise; + readonly text: (options: { + readonly message: string; + readonly placeholder?: string; + }) => Promise; + readonly log: { + readonly warn: (message: string) => void; + readonly info: (message: string) => void; + readonly error: (message: string) => void; + readonly success: (message: string) => void; + }; +}; + +export type WizardDeps = { + readonly cwd: string; + readonly env: NodeJS.ProcessEnv; + readonly options: WizardOptions; + readonly prompts: ClackWizardPrompts; + readonly authClient: WizardSigninAuthClient; + readonly openBrowser: (url: string) => Promise; +}; + +export class WizardCancelledError extends Error { + constructor() { + super(WIZARD_CANCEL_MESSAGE); + this.name = "WizardCancelledError"; + } +} + +function unwrap(prompts: ClackWizardPrompts, value: T | symbol): T { + if (prompts.isCancel(value)) { + prompts.cancel(WIZARD_CANCEL_MESSAGE); + throw new WizardCancelledError(); + } + return value as T; +} + +export type WizardResult = { + readonly orgName: string; + readonly projectName: string; + readonly braintrustApiKey: string; +}; + +export async function runClackWizard(deps: WizardDeps): Promise { + const { prompts } = deps; + prompts.intro(WIZARD_TITLE); + + if (!(await isGitRepo(deps.cwd))) { + prompts.log.warn(NOT_GIT_REPO_WARNING); + } + + const session = await deps.authClient.login({ + onLoginUrl: ({ loginUrl }) => { + prompts.note(wizardLoginPrompt({ loginUrl }), "Login"); + }, + onTryOpenBrowser: (url) => deps.openBrowser(url), + }); + + const provider = await selectProvider(deps); + const providerCredentials = provider.custom + ? undefined + : await collectCredentials(prompts, provider); + + const gitRoot = await findGitRoot(deps.cwd); + if (gitRoot) { + const result = await writeEnvBraintrust(gitRoot, session.apiKey); + prompts.log.success(`Wrote ${result.envFilePath}`); + prompts.log.info( + gitignoreNote({ + added: result.addedToGitignore, + alreadyCovered: result.alreadyCovered, + }), + ); + } else { + prompts.log.info( + `BRAINTRUST_API_KEY=${session.apiKey}\nNot in a git repo — set this in your environment manually.`, + ); + } + + const canInstrument = !provider.custom && providerCredentials !== undefined; + const languages = detectLanguages(deps.cwd); + setTelemetryLanguage(languages.length === 1 ? languages[0]! : "unknown"); + setTelemetryProvider(provider.id); + + let tracePermalink: string | undefined; + let resumeCommand: string | undefined; + if (canInstrument) { + const runIt = unwrap( + prompts, + await prompts.confirm({ + initialValue: true, + message: RUN_HARNESS_QUESTION, + }), + ); + if (runIt) { + const result = await runInstrumentation(deps, { + org: session.orgInfo.name, + project: session.project.name, + apiKey: session.apiKey, + providerCredentials, + languages, + }); + tracePermalink = result.tracePermalink; + resumeCommand = result.resumeCommand; + } else { + const { path } = writePromptToTemp( + renderPrompt({ languages, interactive: false }), + ); + prompts.note(promptSavedNote(path), "Prompt saved"); + } + } else { + const { path } = writePromptToTemp( + renderPrompt({ languages, interactive: false }), + ); + prompts.note(promptSavedNote(path), "Prompt saved"); + } + + prompts.outro( + buildCleanupMessage({ + docsUrl: DOCS_URL, + tracePermalink, + resumeCommand, + }), + ); + + return { + orgName: session.orgInfo.name, + projectName: session.project.name, + braintrustApiKey: session.apiKey, + }; +} + +async function collectCredentials( + prompts: ClackWizardPrompts, + provider: LlmProvider, +): Promise | undefined> { + const fields: readonly CredentialField[] = provider.credentials ?? [ + { envVar: provider.envVar!, label: provider.label, secret: true }, + ]; + const result: Record = {}; + for (const field of fields) { + const raw = unwrap( + prompts, + field.secret !== false + ? await prompts.password({ + message: PROVIDER_KEY_QUESTION(field.label), + }) + : await prompts.text({ message: PROVIDER_KEY_QUESTION(field.label) }), + ); + if (raw.length > 0) { + result[field.envVar] = raw; + } + } + if (Object.keys(result).length === 0) { + prompts.log.warn("No credentials entered; skipping instrumentation."); + return undefined; + } + return result; +} + +async function selectProvider(deps: WizardDeps): Promise { + const { prompts } = deps; + const value = unwrap( + prompts, + await prompts.select({ + message: PROVIDER_QUESTION, + options: LLM_PROVIDERS.map((p) => ({ label: p.label, value: p })), + }), + ); + return value; +} + +type InstrumentationResult = { + readonly tracePermalink: string | undefined; + readonly resumeCommand: string | undefined; +}; + +async function runInstrumentation( + deps: WizardDeps, + args: { + readonly org: string; + readonly project: string; + readonly apiKey: string; + readonly providerCredentials?: Readonly>; + readonly languages: readonly DetectedLanguage[]; + }, +): Promise { + const { prompts } = deps; + const installResult = await ensureBtOnPath(); + switch (installResult.status) { + case "already-installed": + break; + case "installed": + prompts.log.success("Installed `bt`."); + break; + case "skipped": + prompts.log.warn(`Skipping \`bt\` install: ${installResult.reason}`); + break; + case "failed": + prompts.log.error(`Couldn't install \`bt\`: ${installResult.reason}`); + break; + } + + const resultFilePath = allocateResultFile(); + const promptText = renderPrompt({ + languages: args.languages, + interactive: true, + resultFilePath, + }); + notifyPiRunning(true); + const harnessResult = await runHarness({ + prompt: promptText, + cwd: deps.cwd, + braintrustApiKey: args.apiKey, + resultFilePath, + providerCredentials: args.providerCredentials, + languages: args.languages, + }); + notifyPiRunning(false); + if (harnessResult.status === "completed" && harnessResult.exitCode !== 0) { + markTelemetrySigint(); + } + + if (harnessResult.status === "harness-not-found") { + const { path } = writePromptToTemp(promptText); + prompts.log.warn( + `Harness not found. Wrote prompt to ${path}; run a coding agent against it manually.`, + ); + return { tracePermalink: undefined, resumeCommand: undefined }; + } + if (harnessResult.exitCode !== 0) { + prompts.log.warn(`Harness exited with code ${harnessResult.exitCode}.`); + } + return { + tracePermalink: harnessResult.tracePermalink, + resumeCommand: buildHarnessCommand(harnessResult.promptFilePath), + }; +} + +export type DefaultDepsArgs = { + readonly options: WizardOptions; + readonly prompts: ClackWizardPrompts; + readonly cwd?: string; + readonly env?: NodeJS.ProcessEnv; +}; + +export function buildDefaultDeps(args: DefaultDepsArgs): WizardDeps { + const cwd = args.cwd ?? processCwd(); + const env = args.env ?? process.env; + const authClient = new WizardSigninAuthClient(args.options.appUrl); + return { + cwd, + env, + options: args.options, + prompts: args.prompts, + authClient, + openBrowser, + }; +} + +// Exported for permalink construction in callers that get a span back. +export { buildLogsPermalink }; diff --git a/packages/braintrust-wizard/src/cleanup.ts b/packages/braintrust-wizard/src/cleanup.ts new file mode 100644 index 0000000..02ced12 --- /dev/null +++ b/packages/braintrust-wizard/src/cleanup.ts @@ -0,0 +1,45 @@ +/** + * URL formats from /workspace/bt-main/skills/sdk-install/braintrust-url-formats.md. + * `appUrl` here is the *base* (e.g. https://www.braintrust.dev) — the docs reference + * `BRAINTRUST_APP_URL` which for the SaaS app is `https://www.braintrust.dev/app`. + */ +export type TraceLocation = { + readonly org: string; + readonly project: string; + readonly rootSpanId: string; + readonly spanId?: string; +}; + +export function buildLogsPermalink( + appUrl: string, + trace: TraceLocation, +): string { + const base = `${appUrl}/${encodeURIComponent(trace.org)}/p/${encodeURIComponent(trace.project)}/logs`; + const params = new URLSearchParams({ r: trace.rootSpanId }); + if (trace.spanId) { + params.set("s", trace.spanId); + } + return `${base}?${params.toString()}`; +} + +export type CleanupContext = { + readonly docsUrl: string; + readonly tracePermalink: string | undefined; + readonly resumeCommand?: string; +}; + +export function buildCleanupMessage(ctx: CleanupContext): string { + const lines = [ + "Setup complete.", + "", + "For production runs, set the BRAINTRUST_API_KEY environment variable.", + `Docs: ${ctx.docsUrl}`, + ]; + if (ctx.resumeCommand) { + lines.push("", "To resume the coding agent:", ` ${ctx.resumeCommand}`); + } + if (ctx.tracePermalink) { + lines.push(`Trace: ${ctx.tracePermalink}`); + } + return lines.join("\n"); +} diff --git a/packages/braintrust-wizard/src/cli.ts b/packages/braintrust-wizard/src/cli.ts new file mode 100644 index 0000000..5ffcbfb --- /dev/null +++ b/packages/braintrust-wizard/src/cli.ts @@ -0,0 +1,61 @@ +import { spawnSync } from "node:child_process"; + +import * as prompts from "@clack/prompts"; + +import { + buildDefaultDeps, + runClackWizard, + WizardCancelledError, +} from "./clack-wizard"; +import { parseArgs } from "./options"; +import { + startTelemetry, + finishTelemetry, + markTelemetrySigint, +} from "./telemetry"; + +const options = await parseArgs(process.argv.slice(2), process.env); + +// `NODE_EXTRA_CA_CERTS` is read once at Node startup, so we can't apply it +// in-process. If --ca-cert (or BRAINTRUST_CA_CERT / SSL_CERT_FILE) was set +// and the env var isn't already pointing at the same file, re-exec with it +// applied. The guard env var prevents an infinite re-exec loop. +const REEXEC_GUARD = "BT_WIZARD_REEXECED_FOR_CA"; +if ( + options.caCertPath && + process.env[REEXEC_GUARD] !== "1" && + process.env["NODE_EXTRA_CA_CERTS"] !== options.caCertPath +) { + const result = spawnSync(process.execPath, process.argv.slice(1), { + stdio: "inherit", + env: { + ...process.env, + NODE_EXTRA_CA_CERTS: options.caCertPath, + [REEXEC_GUARD]: "1", + }, + }); + process.exit(result.status ?? 1); +} + +startTelemetry(process.env); + +const deps = buildDefaultDeps({ + options, + prompts: prompts as unknown as Parameters< + typeof buildDefaultDeps + >[0]["prompts"], +}); + +try { + await runClackWizard(deps); + finishTelemetry(); +} catch (error) { + if (error instanceof WizardCancelledError) { + markTelemetrySigint(); + finishTelemetry(); + process.exit(0); + } + finishTelemetry(); + process.stderr.write(`${(error as Error).message}\n`); + process.exit(1); +} diff --git a/packages/braintrust-wizard/src/crank-telemetry.ts b/packages/braintrust-wizard/src/crank-telemetry.ts new file mode 100644 index 0000000..3c24ee9 --- /dev/null +++ b/packages/braintrust-wizard/src/crank-telemetry.ts @@ -0,0 +1,83 @@ +/** + * crank-telemetry — spawned by crank at startup as a detached background + * process. Reads JSON-line updates from stdin (language, provider, + * stop-reason), waits until stdin closes (crank exited) or 15 minutes, + * then POSTs the payload once. + */ + +import * as readline from "node:readline"; + +const TELEMETRY_URL = + process.env["CRANK_TELEMETRY_URL"] ?? + "https://www.braintrust.dev/app/cli-telemetry"; +const REQUEST_TIMEOUT_MS = 5_000; +const MAX_WAIT_MS = 15 * 60 * 1_000; +const VERSION = "dev"; + +type Update = { + language?: string; + provider?: string; + stopReason?: string; +}; + +const state = { + start: Math.floor(Date.now() / 1_000), + language: undefined as string | undefined, + provider: undefined as string | undefined, + stopReason: "SIGINT", +}; + +const rl = readline.createInterface({ input: process.stdin }); + +rl.on("line", (line) => { + try { + const update: Update = JSON.parse(line); + if (update.language) state.language = update.language; + if (update.provider) state.provider = update.provider; + if (update.stopReason) state.stopReason = update.stopReason; + } catch { + // ignore malformed lines + } +}); + +async function send(): Promise { + const payload: Record = { + start: state.start, + end: Math.floor(Date.now() / 1_000), + "stop-reason": state.stopReason, + }; + if (state.language !== undefined) payload["language"] = state.language; + if (state.provider !== undefined) payload["provider"] = state.provider; + const body = JSON.stringify(payload); + const headers = { + "Content-Type": "application/json", + "User-Agent": `crank/${VERSION}`, + }; + for (let attempt = 0; attempt < 2; attempt++) { + try { + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS); + await fetch(TELEMETRY_URL, { + method: "POST", + headers, + body, + signal: controller.signal, + }); + clearTimeout(timer); + return; + } catch { + // retry once then give up + } + } +} + +const timeout = setTimeout(() => { + rl.close(); +}, MAX_WAIT_MS); +timeout.unref(); + +rl.once("close", async () => { + clearTimeout(timeout); + await send(); + process.exit(0); +}); diff --git a/packages/braintrust-wizard/src/git.ts b/packages/braintrust-wizard/src/git.ts new file mode 100644 index 0000000..211d809 --- /dev/null +++ b/packages/braintrust-wizard/src/git.ts @@ -0,0 +1,77 @@ +import { access, readFile, writeFile } from "node:fs/promises"; +import { dirname, join, resolve } from "node:path"; +import ignore from "ignore"; + +async function pathExists(p: string): Promise { + return access(p).then( + () => true, + () => false, + ); +} + +export async function findGitRoot( + startDir: string, +): Promise { + let dir = resolve(startDir); + while (true) { + if (await pathExists(join(dir, ".git"))) { + return dir; + } + const parent = dirname(dir); + if (parent === dir) { + return undefined; + } + dir = parent; + } +} + +export async function isGitRepo(cwd: string): Promise { + return (await findGitRoot(cwd)) !== undefined; +} + +const ENV_FILENAME = ".env.braintrust"; + +export type EnvFileWriteResult = { + readonly envFilePath: string; + readonly gitignorePath: string; + readonly addedToGitignore: boolean; + readonly alreadyCovered: boolean; +}; + +export async function writeEnvBraintrust( + gitRoot: string, + apiKey: string, +): Promise { + const envFilePath = join(gitRoot, ENV_FILENAME); + await writeFile(envFilePath, `BRAINTRUST_API_KEY=${apiKey}\n`, { + mode: 0o600, + }); + + const gitignorePath = join(gitRoot, ".gitignore"); + const existing = (await pathExists(gitignorePath)) + ? await readFile(gitignorePath, "utf8") + : ""; + + const alreadyCovered = gitignoreCovers(existing, ENV_FILENAME); + if (alreadyCovered) { + return { + envFilePath, + gitignorePath, + addedToGitignore: false, + alreadyCovered: true, + }; + } + + const sep = existing.length === 0 || existing.endsWith("\n") ? "" : "\n"; + await writeFile(gitignorePath, `${existing}${sep}${ENV_FILENAME}\n`); + return { + envFilePath, + gitignorePath, + addedToGitignore: true, + alreadyCovered: false, + }; +} + +export function gitignoreCovers(content: string, filename: string): boolean { + return ignore().add(content).ignores(filename); +} diff --git a/packages/braintrust-wizard/src/instrument.ts b/packages/braintrust-wizard/src/instrument.ts new file mode 100644 index 0000000..c82bafa --- /dev/null +++ b/packages/braintrust-wizard/src/instrument.ts @@ -0,0 +1,191 @@ +import { spawn } from "node:child_process"; +import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; +import { createRequire } from "node:module"; +import { tmpdir, platform } from "node:os"; +import { join } from "node:path"; + +import type { DetectedLanguage } from "./language-detect"; + +const HARNESS_PACKAGE_BIN = + "@braintrust/bt-wizard-harness/bin/bt-wizard-harness.mjs"; + +function resolveHarnessPath(): + | { readonly ok: true; readonly path: string } + | { readonly ok: false; readonly reason: string } { + try { + const require = createRequire(import.meta.url); + return { ok: true, path: require.resolve(HARNESS_PACKAGE_BIN) }; + } catch (err) { + return { + ok: false, + reason: err instanceof Error ? err.message : String(err), + }; + } +} + +/** + * Build the shell command a user can copy-paste to re-run the harness against + * a saved prompt file. Returns undefined if the harness binary cannot be + * resolved. + */ +export function buildHarnessCommand( + promptFilePath: string, +): string | undefined { + const resolved = resolveHarnessPath(); + if (!resolved.ok) { + return undefined; + } + return `node ${JSON.stringify(resolved.path)} --prompt-file ${JSON.stringify(promptFilePath)}`; +} + +export type InstallBtResult = + | { readonly status: "already-installed" } + | { readonly status: "installed" } + | { readonly status: "skipped"; readonly reason: string } + | { readonly status: "failed"; readonly reason: string }; + +const BT_INSTALL_URL = "https://bt.dev/cli/install.sh"; + +export async function ensureBtOnPath(): Promise { + if (await commandExists("bt")) { + return { status: "already-installed" }; + } + const plat = platform(); + if (plat === "win32") { + return { + status: "skipped", + reason: "Windows install of `bt` is not yet supported.", + }; + } + if (plat !== "darwin" && plat !== "linux") { + return { + status: "skipped", + reason: `Automatic install of \`bt\` not supported on ${plat}.`, + }; + } + return runShellPipeInstall(); +} + +function commandExists(cmd: string): Promise { + return new Promise((resolve) => { + const which = spawn("sh", ["-c", `command -v ${cmd}`], { + stdio: "ignore", + }); + which.on("error", () => resolve(false)); + which.on("close", (code) => resolve(code === 0)); + }); +} + +function runShellPipeInstall(): Promise { + return new Promise((resolve) => { + const child = spawn("sh", ["-c", `curl -fsSL ${BT_INSTALL_URL} | bash`], { + stdio: "inherit", + }); + child.on("error", (err) => + resolve({ status: "failed", reason: err.message }), + ); + child.on("close", (code) => { + if (code === 0) { + resolve({ status: "installed" }); + } else { + resolve({ + status: "failed", + reason: `installer exited with code ${code}`, + }); + } + }); + }); +} + +export type WritePromptToTempResult = { + readonly path: string; +}; + +export function writePromptToTemp(prompt: string): WritePromptToTempResult { + const dir = mkdtempSync(join(tmpdir(), "bt-wizard-")); + const path = join(dir, "instrument-prompt.md"); + writeFileSync(path, prompt); + return { path }; +} + +export type RunHarnessResult = + | { + readonly status: "completed"; + readonly exitCode: number; + readonly signal: NodeJS.Signals | null; + readonly tracePermalink: string | undefined; + readonly promptFilePath: string; + } + | { + readonly status: "harness-not-found"; + readonly checked: readonly string[]; + }; + +/** + * Allocate a fresh result-file path that the harness will write the trace + * permalink to. The path is also injected into the agent prompt via + * {@link renderPrompt}'s `resultFilePath` and exposed to the harness via + * `BT_WIZARD_RESULT_FILE` (path-guard whitelists it). + */ +export function allocateResultFile(): string { + const dir = mkdtempSync(join(tmpdir(), "bt-wizard-")); + return join(dir, "result.txt"); +} + +function readResultFile(path: string): string | undefined { + try { + const raw = readFileSync(path, "utf8").trim(); + return raw.length > 0 ? raw : undefined; + } catch { + return undefined; + } +} + +export async function runHarness(args: { + readonly prompt: string; + readonly cwd: string; + readonly braintrustApiKey: string; + readonly resultFilePath: string; + readonly providerCredentials?: Readonly>; + readonly languages?: readonly DetectedLanguage[]; +}): Promise { + const resolved = resolveHarnessPath(); + if (!resolved.ok) { + return { status: "harness-not-found", checked: [resolved.reason] }; + } + const promptFile = writePromptToTemp(args.prompt).path; + // Touch the result file so the agent knows the path is writable and so + // a missing file vs. an empty file are distinguishable. + writeFileSync(args.resultFilePath, ""); + return new Promise((resolve) => { + const child = spawn("node", [resolved.path, "--prompt-file", promptFile], { + cwd: args.cwd, + env: { + ...process.env, + BRAINTRUST_API_KEY: args.braintrustApiKey, + BT_WIZARD_RESULT_FILE: args.resultFilePath, + BT_WIZARD_LANGUAGES: (args.languages ?? []).join(","), + ...args.providerCredentials, + }, + stdio: "inherit", + }); + child.on("error", () => + resolve({ + status: "completed", + exitCode: 1, + signal: null, + tracePermalink: readResultFile(args.resultFilePath), + promptFilePath: promptFile, + }), + ); + child.on("close", (code, signal) => + resolve({ + status: "completed", + exitCode: code ?? 1, + signal, + tracePermalink: readResultFile(args.resultFilePath), + promptFilePath: promptFile, + }), + ); + }); +} diff --git a/packages/braintrust-wizard/src/language-detect.ts b/packages/braintrust-wizard/src/language-detect.ts new file mode 100644 index 0000000..e87cb2e --- /dev/null +++ b/packages/braintrust-wizard/src/language-detect.ts @@ -0,0 +1,91 @@ +import { existsSync, readdirSync, statSync } from "node:fs"; +import { join } from "node:path"; + +export type DetectedLanguage = + | "python" + | "typescript" + | "go" + | "java" + | "ruby" + | "csharp"; + +const FILENAME_INDICATORS: ReadonlyArray = + [ + ["pyproject.toml", "python"], + ["setup.py", "python"], + ["requirements.txt", "python"], + ["package.json", "typescript"], + ["tsconfig.json", "typescript"], + ["go.mod", "go"], + ["pom.xml", "java"], + ["build.gradle", "java"], + ["build.gradle.kts", "java"], + ["Gemfile", "ruby"], + ]; + +const EXTENSION_INDICATORS: ReadonlyArray = + [ + [".csproj", "csharp"], + [".sln", "csharp"], + [".gemspec", "ruby"], + ]; + +/** + * Detect candidate languages by scanning the directory; mirrors bt-main's + * detect_languages_from_dir. Scans cwd first; recurses into immediate + * subdirectories only if nothing matched at the top level. + */ +export function detectLanguages(dir: string): readonly DetectedLanguage[] { + const found = new Set(); + scan(dir, found); + if (found.size === 0) { + if (!existsSync(dir)) { + return []; + } + for (const entry of readdirSync(dir)) { + const child = join(dir, entry); + let isDir: boolean; + try { + isDir = statSync(child).isDirectory(); + } catch { + continue; + } + if (isDir) { + scan(child, found); + } + } + } + return [...found].sort(); +} + +function scan(dir: string, found: Set): void { + let entries: string[]; + try { + entries = readdirSync(dir); + } catch { + return; + } + for (const name of entries) { + const path = join(dir, name); + let isFile: boolean; + try { + isFile = statSync(path).isFile(); + } catch { + continue; + } + if (!isFile) { + continue; + } + const lower = name.toLowerCase(); + for (const [indicator, lang] of FILENAME_INDICATORS) { + if (lower === indicator.toLowerCase()) { + found.add(lang); + } + } + for (const [ext, lang] of EXTENSION_INDICATORS) { + if (lower.endsWith(ext.toLowerCase())) { + found.add(lang); + } + } + } +} diff --git a/packages/braintrust-wizard/src/options.ts b/packages/braintrust-wizard/src/options.ts new file mode 100644 index 0000000..dc30909 --- /dev/null +++ b/packages/braintrust-wizard/src/options.ts @@ -0,0 +1,55 @@ +import yargs from "yargs/yargs"; + +export type WizardOptions = { + readonly apiUrl: string; + readonly appUrl: string; + readonly caCertPath: string | undefined; +}; + +const DEFAULT_API_URL = "https://api.braintrust.dev"; +const DEFAULT_APP_URL = "https://www.braintrust.dev"; + +function buildParser(env: NodeJS.ProcessEnv) { + return yargs([]) + .scriptName("bt-wizard") + .usage("$0 [options]") + .option("api-url", { + type: "string", + description: "Override API URL", + default: env["BRAINTRUST_API_URL"] ?? DEFAULT_API_URL, + }) + .option("app-url", { + type: "string", + description: "Override app URL", + default: env["BRAINTRUST_APP_URL"] ?? DEFAULT_APP_URL, + }) + .option("ca-cert", { + type: "string", + description: "Path to PEM CA bundle", + default: env["BRAINTRUST_CA_CERT"] ?? env["SSL_CERT_FILE"], + }) + .epilog( + "Environment:\n CRANK_ENABLE_TELEMETRY=false Disable anonymous usage telemetry", + ) + .help() + .alias("h", "help") + .strict(); +} + +export async function parseArgs( + argv: readonly string[], + env: NodeJS.ProcessEnv, +): Promise { + const parser = buildParser(env); + const parsed = await parser.parseAsync([...argv]); + + return { + apiUrl: stripTrailingSlash(parsed["api-url"] as string), + appUrl: stripTrailingSlash(parsed["app-url"] as string), + caCertPath: (parsed["ca-cert"] as string | undefined) || undefined, + }; +} + +function stripTrailingSlash(url: string): string { + return url.replace(/\/+$/, ""); +} diff --git a/packages/braintrust-wizard/src/prompt.ts b/packages/braintrust-wizard/src/prompt.ts new file mode 100644 index 0000000..8741351 --- /dev/null +++ b/packages/braintrust-wizard/src/prompt.ts @@ -0,0 +1,211 @@ +import type { DetectedLanguage } from "./language-detect"; + +/* + * spark agent prompt + * Adapt the link to the docs given depending on the language to instrument + * Instructs the agent to say INSTRUMENTATION_(IN)COMPLETE after it has completed the task. + * The harness catches these words and close the agent. + * This is non deterministic but knowing instrumentation is done is non deterministic too, I didn't think of a better solution. + */ +const TEMPLATE = `# Braintrust SDK Installation (Agent Instructions) + +## Hard Rules + +{RUN_MODE_CONTEXT} + +- **Only add Braintrust code.** Do not refactor or modify unrelated code. +- **One language, one service per install run.** If the repo has more than one candidate, ask the user which one to instrument before starting. Do not instrument multiple languages or services in the same run. +- **If the language is unclear, ask the user.** Do not guess. See Step 2. +- **Install the latest Braintrust SDK.** Do not hard-pin the Braintrust SDK version unless the user asks for it -- use the package manager's normal install (which may produce an exact or a ranged version, whichever is idiomatic for that ecosystem). Build-time dependencies (e.g. Orchestrion for Go) must still be pinned to an exact version -- see the language-specific resource. +- **Set the project name in code.** Do NOT configure project name via env vars. +- **App must run without Braintrust.** If \`BRAINTRUST_API_KEY\` is missing at runtime, do not crash. +- **Do not guess APIs.** Use official documentation/examples only. +- **Do not add eval code** unless explicitly requested. +- **Do not add manual flush/shutdown logic** unless the app is a short-lived script, serverless function, Lambda, or CLI that exits immediately after LLM calls -- in which case a single \`flush()\` (or language equivalent) right before exit is correct, since otherwise traces get dropped. Do not add flush/shutdown for long-running processes (servers, daemons, workers). +- **If SDK is already installed/configured, do not duplicate work.** +- **Do not create setup-only files or directories in the repo.** Do not write \`.bt/setup/\`, \`.bt/skills/docs/\`, agent skill directories, or setup task files unless explicitly asked by the user. + +--- + +## Execution Requirements + +Before writing any code: + +1. Create a **checklist** from the steps below. +2. Execute each step in order. +3. Do not skip steps. + +--- + +## Steps + +{LANGUAGE_CONTEXT} + +--- + +{INSTALL_SDK_CONTEXT} + +--- + +### 4. Verify Installation (MANDATORY) + +- If the SDK relies on build-time or launch-time auto-instrumentation, make sure the project's normal build/run path now uses it. A one-off verification command is not sufficient. +- Run the application. +- Confirm at least one log/trace is emitted to Braintrust. +- Confirm no runtime errors. +- Confirm the app still runs if \`BRAINTRUST_API_KEY\` is unset. + +If you do not know how to run the app, ask the user and wait for the response before proceeding. + +--- + +### 5. Final Summary + +Summarize: + +- What SDK version was installed +- Where code was modified +- What logs/traces were emitted +- The Braintrust permalink (required) + +If instrumentation succeeded, output the following sentinel on its own line exactly as written: + +INSTRUMENTATION_COMPLETE + +If instrumentation failed or could not be completed, output instead: + +INSTRUMENTATION_INCOMPLETE + +{RESULT_FILE_CONTEXT}{WORKFLOW_CONTEXT} +`; + +const LANGUAGE_DISPLAY: Record = { + python: "Python", + typescript: "TypeScript", + go: "Go", + java: "Java", + ruby: "Ruby", + csharp: "C#", +}; + +const SDK_INSTALL_DOCS_BASE = + "https://www.braintrust.dev/docs/instrument/trace-llm-calls"; + +const INSTALL_SDK_REQUIREMENTS = `- Install the latest Braintrust SDK via the language's package manager. Do not hard-pin the SDK version unless the user asks. Build-time dependencies called out by the language-specific resource (e.g. Orchestrion for Go) must still be pinned to an exact version. +- Modify only dependency files, a minimal application entry point (e.g., main/bootstrap), and any existing build/run scripts or checked-in env/config that must change to keep auto-instrumentation active in normal use. Auto-instrument the app (except for Java and C# which don't support auto-instrumentation). +- Do not change unrelated code.`; + +const DETECT_LANGUAGE_BLOCK = `### 2. Detect Language + +**Instrument exactly one language/service per install run.** Do not install Braintrust for multiple languages or multiple services in the same run, even if the repo contains more than one. If more than one candidate exists, stop and ask the user which single service to instrument before doing anything else. + +Determine the project language using concrete signals: + +- \`package.json\` -> TypeScript +- \`requirements.txt\`, \`setup.py\` or \`pyproject.toml\` -> Python +- \`pom.xml\` or \`build.gradle\` -> Java +- \`go.mod\` -> Go +- \`Gemfile\` -> Ruby +- \`.csproj\` -> C# + +**If exactly one of these matches at the repo root and there is no ambiguity, proceed with that language.** + +In every other case, **stop and ask the user** before continuing. Do not guess, do not pick the "most likely" language, and do not instrument more than one.`; + +export type RenderPromptOptions = { + readonly languages: readonly DetectedLanguage[]; + readonly interactive: boolean; + /** + * If set, a path the agent must write the trace permalink to (single line, + * just the URL) right before exiting. The wizard reads this file after the + * harness exits and surfaces the permalink in its cleanup message. + */ + readonly resultFilePath?: string; +}; + +export function renderPrompt(opts: RenderPromptOptions): string { + const runMode = opts.interactive + ? "- **Interactive mode:** You can ask the user questions through the chat interface.\n" + : "- **Non-interactive mode:** You cannot ask the user questions. If a step requires user input (e.g., ambiguous language in a polyglot repo, unknown run command), abort with a clear explanation of what is needed.\n"; + + let languageContext: string; + let installSdkContext: string; + + if (opts.languages.length === 0) { + languageContext = DETECT_LANGUAGE_BLOCK; + const rows = (Object.keys(LANGUAGE_DISPLAY) as DetectedLanguage[]) + .map( + (lang) => + `| ${LANGUAGE_DISPLAY[lang]} | \`${SDK_INSTALL_DOCS_BASE}#${lang}\` |`, + ) + .join("\n"); + installSdkContext = `### 3. Install SDK (Language-Specific) + +Read the install guide for the detected language from the canonical docs: + +| Language | Doc URL | +| -------- | ------- | +${rows} + +Requirements: + +${INSTALL_SDK_REQUIREMENTS}`; + } else if (opts.languages.length === 1) { + const lang = opts.languages[0]!; + languageContext = `### 2. Language + +The target language has been specified: **${LANGUAGE_DISPLAY[lang]}**.`; + installSdkContext = `### 3. Install SDK + +Read the install guide from the canonical docs: \`${SDK_INSTALL_DOCS_BASE}#${lang}\` + +Requirements: + +${INSTALL_SDK_REQUIREMENTS}`; + } else { + const list = opts.languages + .map((l) => `**${LANGUAGE_DISPLAY[l]}**`) + .join(", "); + languageContext = `### 2. Language + +Candidate languages detected: ${list}. Pick exactly one with the user before proceeding.`; + const rows = opts.languages + .map( + (l) => `| ${LANGUAGE_DISPLAY[l]} | \`${SDK_INSTALL_DOCS_BASE}#${l}\` |`, + ) + .join("\n"); + installSdkContext = `### 3. Install SDK + +Read the install guide for the chosen language from the canonical docs: + +| Language | Doc URL | +| -------- | ------- | +${rows} + +Requirements: + +${INSTALL_SDK_REQUIREMENTS}`; + } + + const resultFileContext = opts.resultFilePath + ? `## Reporting the Trace Permalink (REQUIRED) + +When you have obtained the Braintrust trace permalink in the Final Summary step, write it as plain text (just the URL, no surrounding text, single line) to this exact file path before finishing: + +\`${opts.resultFilePath}\` + +Use the \`write\` tool. The wizard reads this file after you exit and surfaces the permalink to the user. If you cannot produce a permalink, leave the file empty. + +` + : ""; + + const workflowContext = `## Latest Braintrust Setup Docs + +Use the canonical Braintrust docs at https://www.braintrust.dev/docs as the source of truth for SDK setup behavior. Prefer local \`bt\` CLI commands over direct API calls when verifying state.`; + + return TEMPLATE.replace("{RUN_MODE_CONTEXT}", runMode) + .replace("{LANGUAGE_CONTEXT}", languageContext) + .replace("{INSTALL_SDK_CONTEXT}", installSdkContext) + .replace("{RESULT_FILE_CONTEXT}", resultFileContext) + .replace("{WORKFLOW_CONTEXT}", workflowContext); +} diff --git a/packages/braintrust-wizard/src/providers.ts b/packages/braintrust-wizard/src/providers.ts new file mode 100644 index 0000000..5cde186 --- /dev/null +++ b/packages/braintrust-wizard/src/providers.ts @@ -0,0 +1,91 @@ +/** + * LLM providers shown in the wizard. + * + * Single-key providers (most): set `envVar` — one API key is collected and + * passed to the harness as that env var. The list of single-key providers + * mirrors `AISecretTypes` from `@braintrust/proxy/schema`; drift is enforced + * by `test/providers.test.ts`. + * + * Multi-credential providers (Bedrock, Vertex, Azure): set `credentials` with + * one entry per env var. Each field is prompted individually; all are passed + * to the harness. + * + * If `custom: true`, no credentials are requested and instrumentation is + * skipped. + */ +export type CredentialField = { + readonly envVar: string; + readonly label: string; + readonly secret?: boolean; +}; + +type LlmProviderBase = { readonly id: string; readonly label: string }; + +export type LlmProvider = + | (LlmProviderBase & { + readonly envVar: string; + readonly credentials?: never; + readonly custom?: never; + }) + | (LlmProviderBase & { + readonly credentials: readonly CredentialField[]; + readonly envVar?: never; + readonly custom?: never; + }) + | (LlmProviderBase & { + readonly custom: true; + readonly envVar?: never; + readonly credentials?: never; + }); + +export const LLM_PROVIDERS: readonly LlmProvider[] = [ + { id: "openai", label: "OpenAI", envVar: "OPENAI_API_KEY" }, + { id: "anthropic", label: "Anthropic", envVar: "ANTHROPIC_API_KEY" }, + { id: "gemini", label: "Gemini", envVar: "GEMINI_API_KEY" }, + { id: "mistral", label: "Mistral", envVar: "MISTRAL_API_KEY" }, + { id: "together", label: "Together.ai", envVar: "TOGETHER_API_KEY" }, + { id: "fireworks", label: "Fireworks", envVar: "FIREWORKS_API_KEY" }, + { id: "perplexity", label: "Perplexity", envVar: "PERPLEXITY_API_KEY" }, + { id: "xai", label: "xAI", envVar: "XAI_API_KEY" }, + { id: "groq", label: "Groq", envVar: "GROQ_API_KEY" }, + { id: "lepton", label: "Lepton", envVar: "LEPTON_API_KEY" }, + { id: "cerebras", label: "Cerebras", envVar: "CEREBRAS_API_KEY" }, + { id: "replicate", label: "Replicate", envVar: "REPLICATE_API_KEY" }, + { id: "baseten", label: "Baseten", envVar: "BASETEN_API_KEY" }, + { + id: "bedrock", + label: "AWS Bedrock", + credentials: [ + { envVar: "AWS_ACCESS_KEY_ID", label: "Access Key ID" }, + { + envVar: "AWS_SECRET_ACCESS_KEY", + label: "Secret Access Key", + secret: true, + }, + { envVar: "AWS_REGION", label: "Region" }, + ], + }, + { + id: "vertex", + label: "Google Vertex AI", + credentials: [ + { envVar: "GOOGLE_CLOUD_PROJECT", label: "Project ID" }, + { envVar: "GOOGLE_CLOUD_LOCATION", label: "Location (e.g. us-central1)" }, + { + envVar: "GOOGLE_APPLICATION_CREDENTIALS", + label: "Path to service account JSON", + secret: false, + }, + ], + }, + { + id: "azure", + label: "Azure OpenAI", + credentials: [ + { envVar: "AZURE_OPENAI_API_KEY", label: "API Key", secret: true }, + { envVar: "AZURE_OPENAI_ENDPOINT", label: "Endpoint URL" }, + { envVar: "AZURE_OPENAI_DEPLOYMENT", label: "Deployment name" }, + ], + }, + { id: "custom", label: "Custom (self-hosted, skip API key)", custom: true }, +]; diff --git a/src/query-client.ts b/packages/braintrust-wizard/src/query-client.ts similarity index 100% rename from src/query-client.ts rename to packages/braintrust-wizard/src/query-client.ts diff --git a/packages/braintrust-wizard/src/telemetry.ts b/packages/braintrust-wizard/src/telemetry.ts new file mode 100644 index 0000000..ba1fc71 --- /dev/null +++ b/packages/braintrust-wizard/src/telemetry.ts @@ -0,0 +1,95 @@ +import { spawn } from "node:child_process"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +import type { DetectedLanguage } from "./language-detect"; + +type TelemetryChild = { + write: (update: Record) => void; + finish: () => void; + setPiRunning: (running: boolean) => void; + markSigint: () => void; +}; + +let child: TelemetryChild | null = null; + +function telemetryBin(): string { + const dir = dirname(fileURLToPath(import.meta.url)); + return join(dir, "crank-telemetry.mjs"); +} + +export function startTelemetry(env: NodeJS.ProcessEnv): void { + const flag = env["CRANK_ENABLE_TELEMETRY"]; + if (flag !== undefined && flag.toUpperCase() === "FALSE") return; + + const spawnEnv: NodeJS.ProcessEnv = { ...env }; + if (env["CRANK_TELEMETRY_URL"]) { + spawnEnv["CRANK_TELEMETRY_URL"] = env["CRANK_TELEMETRY_URL"]; + } + + const proc = spawn(process.execPath, [telemetryBin()], { + detached: true, + stdio: ["pipe", "ignore", "ignore"], + env: spawnEnv, + }); + proc.unref(); + + let finished = false; + let sigintReceived = false; + let piRunning = false; + + process.on("SIGINT", () => { + if (piRunning) return; + sigintReceived = true; + child?.finish(); + process.exit(1); + }); + + child = { + write(update) { + if (finished) return; + try { + proc.stdin?.write(JSON.stringify(update) + "\n"); + } catch { + // ignore write errors + } + }, + finish() { + if (finished) return; + finished = true; + if (sigintReceived) { + proc.stdin?.end(); + } else { + proc.stdin?.end(JSON.stringify({ stopReason: "finished" }) + "\n"); + } + }, + setPiRunning(running: boolean) { + piRunning = running; + }, + markSigint() { + sigintReceived = true; + }, + }; +} + +export function setTelemetryLanguage( + language: DetectedLanguage | "unknown", +): void { + child?.write({ language }); +} + +export function setTelemetryProvider(provider: string): void { + child?.write({ provider }); +} + +export function finishTelemetry(): void { + child?.finish(); +} + +export function notifyPiRunning(running: boolean): void { + child?.setPiRunning(running); +} + +export function markTelemetrySigint(): void { + child?.markSigint(); +} diff --git a/packages/braintrust-wizard/src/wizard-copy.ts b/packages/braintrust-wizard/src/wizard-copy.ts new file mode 100644 index 0000000..be7d2a1 --- /dev/null +++ b/packages/braintrust-wizard/src/wizard-copy.ts @@ -0,0 +1,62 @@ +export const WIZARD_TITLE = "Braintrust Setup"; + +export const WIZARD_DESCRIPTION = + "Welcome to the Braintrust setup wizard. This wizard will guide you through setting up braintrust in your project."; + +export const ACCOUNT_QUESTION = "Do you already have a Braintrust account?"; + +// Legacy copy used by the beau (Ink) variant. The Clack wizard uses +// browser-mediated wizard sign-in and doesn't need this prompt. +export const LOGIN_BROWSER_PROMPT = + "For the rest of the flow, we require you to be logged in, do you want to open the browser?"; + +export function loginPlaceholderOutro(openBrowser: boolean): string { + if (openBrowser) { + return "Browser login is not wired up yet, so no browser was opened."; + } + return "Browser login skipped. Setup flow stops here for now."; +} + +export const NOT_GIT_REPO_WARNING = + "Heads up: this folder is not a git repository. The wizard may edit files; consider running it inside a checked-in repo."; + +export const DOCS_URL = "https://www.braintrust.dev/docs"; + +export const WIZARD_CANCEL_MESSAGE = "Wizard cancelled."; + +export const PROVIDER_QUESTION = "Which LLM provider are you using?"; + +export const PROVIDER_KEY_QUESTION = (label: string): string => + `Enter your ${label} API key:`; + +export const RUN_HARNESS_QUESTION = + "Run the bt-wizard coding agent harness now to instrument this repo?"; + +export const HARNESS_NOT_FOUND = (checked: readonly string[]): string => + `Couldn't find the bt-wizard harness. Looked in:\n ${checked.join("\n ")}`; + +export function gitignoreNote(args: { + readonly added: boolean; + readonly alreadyCovered: boolean; +}): string { + if (args.added) { + return "Added .env.braintrust to .gitignore."; + } + if (args.alreadyCovered) { + return ".gitignore already covers .env.braintrust."; + } + return ".gitignore unchanged."; +} + +export function wizardLoginPrompt(args: { readonly loginUrl: string }): string { + return [ + "Open this URL in your browser to finish signing in:", + ` ${args.loginUrl}`, + "", + "Pick the org and project you want to use; the wizard will resume here.", + ].join("\n"); +} + +export function promptSavedNote(path: string): string { + return `Wrote the agent prompt to: ${path}\nYou can run a coding agent against it manually.`; +} diff --git a/test/beau-app.test.tsx b/packages/braintrust-wizard/test/beau-app.test.tsx similarity index 99% rename from test/beau-app.test.tsx rename to packages/braintrust-wizard/test/beau-app.test.tsx index 81b9c61..65f47f0 100644 --- a/test/beau-app.test.tsx +++ b/packages/braintrust-wizard/test/beau-app.test.tsx @@ -9,8 +9,8 @@ import { AppRoot } from "../src/beau/AppRoot"; import { ACCOUNT_QUESTION } from "../src/wizard-copy"; const STRIP_PATTERN = /[▌▐]/; -const LOGO_PATTERN = /[▀▄]/; -const LOGO_BODY_SPLIT_PATTERN = /[█▀▄]{3,} +[█▀▄]{3,}/; +const LOGO_PATTERN = /[▟▜▘▝▖▗▙▛█]/; +const LOGO_BODY_SPLIT_PATTERN = /[█]{3,}[▌▐]+[█]{3,}/; const MIN_STRIP_MARKS_PER_LINE = 8; const LOGIN_BROWSER_PROMPT_START = "For the rest of the flow"; const LOGIN_BROWSER_PROMPT_END = "open the browser?"; diff --git a/packages/braintrust-wizard/test/braintrust-api.test.ts b/packages/braintrust-wizard/test/braintrust-api.test.ts new file mode 100644 index 0000000..d59e60e --- /dev/null +++ b/packages/braintrust-wizard/test/braintrust-api.test.ts @@ -0,0 +1,93 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import { BraintrustApiClient, BraintrustApiError } from "../src/braintrust-api"; + +describe("currentUserAwaitingProvisioning", () => { + const originalFetch = globalThis.fetch; + beforeEach(() => { + // No-op; tests stub fetch per-case. + }); + afterEach(() => { + globalThis.fetch = originalFetch; + }); + + it("returns the user on first success", async () => { + const fetchMock = vi.fn().mockResolvedValue( + new Response(JSON.stringify({ id: "u1", email: "a@b.com" }), { + status: 200, + headers: { "Content-Type": "application/json" }, + }), + ); + globalThis.fetch = fetchMock as unknown as typeof fetch; + const api = new BraintrustApiClient("https://api.example", "tok"); + + const sleeps: number[] = []; + const user = await api.currentUserAwaitingProvisioning({ + sleep: async (ms) => { + sleeps.push(ms); + }, + }); + + expect(user.id).toBe("u1"); + expect(fetchMock).toHaveBeenCalledTimes(1); + expect(sleeps).toEqual([]); + }); + + it("retries on 401 and succeeds after a few attempts", async () => { + const responses = [ + new Response("nope", { status: 401 }), + new Response("nope", { status: 401 }), + new Response(JSON.stringify({ id: "u1" }), { + status: 200, + headers: { "Content-Type": "application/json" }, + }), + ]; + const fetchMock = vi.fn().mockImplementation(() => responses.shift()!); + globalThis.fetch = fetchMock as unknown as typeof fetch; + + const api = new BraintrustApiClient("https://api.example", "tok"); + const sleeps: number[] = []; + const user = await api.currentUserAwaitingProvisioning({ + delaysMs: [10, 20, 30, 40, 50], + sleep: async (ms) => { + sleeps.push(ms); + }, + }); + + expect(user.id).toBe("u1"); + expect(fetchMock).toHaveBeenCalledTimes(3); + expect(sleeps).toEqual([10, 20]); + }); + + it("gives up after exhausting retries on persistent 401", async () => { + const fetchMock = vi + .fn() + .mockResolvedValue(new Response("nope", { status: 401 })); + globalThis.fetch = fetchMock as unknown as typeof fetch; + + const api = new BraintrustApiClient("https://api.example", "tok"); + await expect( + api.currentUserAwaitingProvisioning({ + delaysMs: [1, 2, 3], + sleep: async () => {}, + }), + ).rejects.toThrow(/still being provisioned/); + expect(fetchMock).toHaveBeenCalledTimes(4); + }); + + it("does not retry on non-401 errors", async () => { + const fetchMock = vi + .fn() + .mockResolvedValue(new Response("boom", { status: 500 })); + globalThis.fetch = fetchMock as unknown as typeof fetch; + + const api = new BraintrustApiClient("https://api.example", "tok"); + await expect( + api.currentUserAwaitingProvisioning({ + delaysMs: [1, 2, 3], + sleep: async () => {}, + }), + ).rejects.toBeInstanceOf(BraintrustApiError); + expect(fetchMock).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/braintrust-wizard/test/clack-wizard.test.ts b/packages/braintrust-wizard/test/clack-wizard.test.ts new file mode 100644 index 0000000..9cbc0ab --- /dev/null +++ b/packages/braintrust-wizard/test/clack-wizard.test.ts @@ -0,0 +1,188 @@ +import { mkdtempSync, mkdirSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; + +import { describe, expect, it } from "vitest"; + +import { + type WizardSigninAuthClient, + type WizardSigninCompleteResult, + type WizardSigninEvents, +} from "../src/auth"; +import { + type ClackWizardPrompts, + runClackWizard, + WizardCancelledError, + type WizardDeps, +} from "../src/clack-wizard"; +import { WIZARD_TITLE, WIZARD_CANCEL_MESSAGE } from "../src/wizard-copy"; + +const CANCEL = Symbol("cancel"); + +type ConfirmAnswer = boolean | typeof CANCEL; +type SelectAnswer = T | typeof CANCEL; +type TextAnswer = string | typeof CANCEL; + +type FakePromptInputs = { + readonly confirms?: ConfirmAnswer[]; + readonly selects?: ReadonlyArray; + readonly texts?: TextAnswer[]; + readonly passwords?: TextAnswer[]; +}; + +function createPrompts(inputs: FakePromptInputs) { + const events: string[] = []; + const confirms = [...(inputs.confirms ?? [])]; + const selects = [...(inputs.selects ?? [])]; + const texts = [...(inputs.texts ?? [])]; + const passwords = [...(inputs.passwords ?? [])]; + + const prompts: ClackWizardPrompts = { + cancel(message) { + events.push(`cancel:${message}`); + }, + async confirm(options) { + const next = confirms.shift(); + events.push(`confirm:${options.message}`); + if (next === undefined) { + throw new Error(`No confirm answer for: ${options.message}`); + } + return next; + }, + intro(message) { + events.push(`intro:${message}`); + }, + isCancel(value): value is symbol { + return value === CANCEL; + }, + note(message, title) { + events.push(`note:${title ?? ""}`); + void message; + }, + outro(message) { + events.push(`outro:${message.split("\n")[0]}`); + }, + async password(options) { + const next = passwords.shift(); + events.push(`password:${options.message}`); + if (next === undefined) { + throw new Error(`No password answer for: ${options.message}`); + } + return next as string | symbol; + }, + async select(options) { + const next = selects.shift(); + events.push(`select:${options.message}`); + if (next === undefined) { + throw new Error(`No select answer for: ${options.message}`); + } + return next as SelectAnswer as symbol; + }, + async text(options) { + const next = texts.shift(); + events.push(`text:${options.message}`); + if (next === undefined) { + throw new Error(`No text answer for: ${options.message}`); + } + return next as string | symbol; + }, + log: { + warn: (m) => events.push(`warn:${m}`), + info: (m) => events.push(`info:${m}`), + error: (m) => events.push(`error:${m}`), + success: (m) => events.push(`success:${m}`), + }, + }; + + return { prompts, events }; +} + +const DEFAULT_LOGIN_RESULT: WizardSigninCompleteResult = { + apiKey: "bt-secret-key", + orgInfo: { + id: "o1", + name: "acme", + api_url: "https://api.test", + proxy_url: null, + realtime_url: null, + is_universal_api: null, + git_metadata: null, + }, + project: { + id: "p1", + name: "demo", + org_id: "o1", + description: null, + }, +}; + +function buildDeps(args: { + readonly prompts: ClackWizardPrompts; + readonly authClient?: WizardSigninAuthClient; + readonly cwd?: string; +}): WizardDeps { + const cwd = args.cwd ?? mkdtempSync(join(tmpdir(), "bt-wizard-test-")); + const stubAuth = + args.authClient ?? + ({ + login: async (events: WizardSigninEvents) => { + events.onLoginUrl({ + loginUrl: "https://app.test/app/cli-login/test-session", + expiresAt: "2099-01-01T00:00:00.000Z", + }); + await events.onTryOpenBrowser( + "https://app.test/app/cli-login/test-session", + ); + return DEFAULT_LOGIN_RESULT; + }, + } as unknown as WizardSigninAuthClient); + + return { + cwd, + env: {}, + options: { + apiUrl: "https://api.test", + appUrl: "https://app.test", + caCertPath: undefined, + }, + prompts: args.prompts, + authClient: stubAuth, + openBrowser: async () => true, + }; +} + +describe("runClackWizard", () => { + it("walks through happy path with no harness run", async () => { + const customProvider = { id: "custom", label: "Custom", custom: true }; + const { prompts, events } = createPrompts({ + selects: [customProvider], + }); + const deps = buildDeps({ prompts }); + + const result = await runClackWizard(deps); + + expect(result.orgName).toBe("acme"); + expect(result.projectName).toBe("demo"); + expect(result.braintrustApiKey).toBe("bt-secret-key"); + expect(events[0]).toBe(`intro:${WIZARD_TITLE}`); + expect(events).toContain("note:Login"); + }); + + it("cancels cleanly when the user aborts the provider select", async () => { + const { prompts, events } = createPrompts({ selects: [CANCEL] }); + const deps = buildDeps({ prompts }); + + await expect(runClackWizard(deps)).rejects.toThrow(WizardCancelledError); + expect(events).toContain(`cancel:${WIZARD_CANCEL_MESSAGE}`); + }); + + it("warns when not in a git repo", async () => { + const dir = mkdtempSync(join(tmpdir(), "bt-wizard-nogit-")); + mkdirSync(join(dir, "child"), { recursive: true }); + const { prompts, events } = createPrompts({ selects: [CANCEL] }); + const deps = buildDeps({ prompts, cwd: join(dir, "child") }); + + await expect(runClackWizard(deps)).rejects.toThrow(WizardCancelledError); + expect(events.some((e) => e.startsWith("warn:Heads up"))).toBe(true); + }); +}); diff --git a/packages/braintrust-wizard/test/providers.test.ts b/packages/braintrust-wizard/test/providers.test.ts new file mode 100644 index 0000000..c330a79 --- /dev/null +++ b/packages/braintrust-wizard/test/providers.test.ts @@ -0,0 +1,65 @@ +import { AISecretTypes } from "@braintrust/proxy/schema"; +import { describe, expect, it } from "vitest"; + +import { LLM_PROVIDERS } from "../src/providers"; + +// Provider IDs that the wizard offers but that aren't in the currently +// published `@braintrust/proxy@0.0.9` schema yet. Remove from this set +// once the corresponding proxy release ships. +const KNOWN_AHEAD: ReadonlySet = new Set(["baseten"]); + +// Multi-credential providers use several env vars instead of a single API key +// and are intentionally absent from AISecretTypes. +const MULTI_CREDENTIAL: ReadonlySet = new Set( + LLM_PROVIDERS.filter((p) => p.credentials !== undefined).map((p) => p.id), +); + +function envVarToProviderId(envVar: string): string { + return envVar.toLowerCase().replace(/_api_key$/, ""); +} + +describe("LLM_PROVIDERS sync with @braintrust/proxy/schema", () => { + it("matches AISecretTypes (plus the custom entry, KNOWN_AHEAD, and MULTI_CREDENTIAL)", () => { + const fromSchema = new Set( + Object.keys(AISecretTypes).map(envVarToProviderId), + ); + const fromWizard = new Set( + LLM_PROVIDERS.filter((p) => !p.custom).map((p) => p.id), + ); + + const missingFromWizard = [...fromSchema].filter( + (id) => !fromWizard.has(id), + ); + const extraInWizard = [...fromWizard].filter( + (id) => + !fromSchema.has(id) && + !KNOWN_AHEAD.has(id) && + !MULTI_CREDENTIAL.has(id), + ); + + expect(missingFromWizard).toEqual([]); + expect(extraInWizard).toEqual([]); + }); + + it("includes the custom self-hosted entry", () => { + expect(LLM_PROVIDERS.some((p) => p.custom === true)).toBe(true); + }); + + it("uses each AISecretTypes env var verbatim for single-key providers", () => { + const envVars = new Set(Object.keys(AISecretTypes)); + for (const provider of LLM_PROVIDERS) { + if (provider.custom) continue; + if (KNOWN_AHEAD.has(provider.id)) continue; + if (MULTI_CREDENTIAL.has(provider.id)) continue; + expect(envVars.has(provider.envVar!)).toBe(true); + } + }); + + it("multi-credential providers each have at least one credential field", () => { + for (const provider of LLM_PROVIDERS.filter( + (p) => p.credentials !== undefined, + )) { + expect(provider.credentials!.length).toBeGreaterThan(0); + } + }); +}); diff --git a/tsconfig.json b/packages/braintrust-wizard/tsconfig.json similarity index 100% rename from tsconfig.json rename to packages/braintrust-wizard/tsconfig.json diff --git a/vitest.config.ts b/packages/braintrust-wizard/vitest.config.ts similarity index 100% rename from vitest.config.ts rename to packages/braintrust-wizard/vitest.config.ts diff --git a/packages/bt-wizard-harness/bin/bt-wizard-harness.mjs b/packages/bt-wizard-harness/bin/bt-wizard-harness.mjs new file mode 100755 index 0000000..de69330 --- /dev/null +++ b/packages/bt-wizard-harness/bin/bt-wizard-harness.mjs @@ -0,0 +1,219 @@ +#!/usr/bin/env node +/** + * Thin launcher for the bt-wizard pi harness. + * + * Usage: bt-wizard-harness --prompt-file [extra pi args...] + * + * Runs pi inside a PTY so it gets a real terminal: correct window size, + * ANSI colours, cursor control, and automatic resize on SIGWINCH. + * We intercept the PTY output to scan for "summary" (case-insensitive); + * when detected we kill pi and exit so the wizard can run its cleanup phase. + * + * Tools loaded (--no-builtin-tools baseline): + * read,write,edit,grep,find,ls built-in file ops + * path-guard restrict writes to cwd / .env.braintrust + * bt-tool bt CLI + * curl-tool GET/HEAD only HTTP + * git-tool safe git subcommands + * package-manager-tool language-gated pkg/fmt/lint/test + * request-command-tool user-approved one-off commands + */ + +import { existsSync, readFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import pty from "node-pty"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const pkgDir = resolve(__dirname, ".."); + +// --------------------------------------------------------------------------- +// Arg parsing +// --------------------------------------------------------------------------- + +const argv = process.argv.slice(2); +let promptFile; +const passthrough = []; +for (let i = 0; i < argv.length; i += 1) { + const a = argv[i]; + if (a === "--prompt-file") { + promptFile = argv[i + 1]; + i += 1; + } else if (a === "-h" || a === "--help") { + process.stdout.write( + "Usage: bt-wizard-harness --prompt-file [extra pi args...]\n", + ); + process.exit(0); + } else { + passthrough.push(a); + } +} + +if (!promptFile) { + process.stderr.write("error: --prompt-file is required\n"); + process.exit(2); +} +if (!existsSync(promptFile)) { + process.stderr.write(`error: prompt file not found: ${promptFile}\n`); + process.exit(2); +} + +const promptText = readFileSync(promptFile, "utf8"); + +// Resolve pi's actual JS entry point so node-pty can spawn `node ` +// directly. The .bin/pi shim is a POSIX shell script that node-pty cannot +// exec via posix_spawnp, so we must bypass it. +function resolvePiJs() { + const shimCandidates = [ + resolve(pkgDir, "node_modules", ".bin", "pi"), + resolve(pkgDir, "..", "..", "node_modules", ".bin", "pi"), + ]; + for (const shim of shimCandidates) { + if (!existsSync(shim)) continue; + // The shim contains: exec node "$basedir/../../../../path/to/cli.js" "$@" + // $basedir is the directory containing the shim file. + const shimDir = dirname(shim); + const content = readFileSync(shim, "utf8"); + const m = content.match(/exec\s+\S*node\S*\s+"([^"]+\.js)"/); + if (!m) continue; + // Replace the literal "$basedir" token with the shim's directory. + const jsPath = resolve(m[1].replace("$basedir", shimDir)); + if (existsSync(jsPath)) return jsPath; + } + return null; +} + +const piJs = resolvePiJs(); +// spawn args: if we found the JS file, use `node `; else fall back to +// spawning the `pi` executable directly (works if installed globally as a +// real binary rather than a pnpm shim). +const [spawnBin, spawnArgs] = piJs ? [process.execPath, [piJs]] : ["pi", []]; + +const piArgs = [ + "--no-session", + "--no-builtin-tools", + "-t", + "read,write,edit,grep,find,ls,bt,pkg,curl,git,request_command", + "-e", + resolve(pkgDir, "extensions/path-guard.ts"), + "-e", + resolve(pkgDir, "extensions/bt-tool.ts"), + "-e", + resolve(pkgDir, "extensions/curl-tool.ts"), + "-e", + resolve(pkgDir, "extensions/git-tool.ts"), + "-e", + resolve(pkgDir, "extensions/package-manager-tool.ts"), + "-e", + resolve(pkgDir, "extensions/request-command-tool.ts"), + "--append-system-prompt", + promptText, + "Begin the Braintrust SDK instrumentation.", + ...passthrough, +]; + +// --------------------------------------------------------------------------- +// PTY spawn — pi sees a real terminal on all three fds +// --------------------------------------------------------------------------- + +const cols = process.stdout.columns ?? 80; +const rows = process.stdout.rows ?? 24; + +const piProc = pty.spawn(spawnBin, [...spawnArgs, ...piArgs], { + name: process.env.TERM ?? "xterm-256color", + cols, + rows, + cwd: process.cwd(), + env: process.env, +}); + +// --------------------------------------------------------------------------- +// Summary detection +// --------------------------------------------------------------------------- + +// Scan a sliding window so "summary" split across chunks is still caught. +const SENTINEL_COMPLETE = "INSTRUMENTATION_COMPLETE"; +const SENTINEL_INCOMPLETE = "INSTRUMENTATION_INCOMPLETE"; +const WINDOW = SENTINEL_INCOMPLETE.length - 1; // longest sentinel + +let tail = ""; +let summaryDetected = false; +let shutdownTimer = null; +// While the user is typing, pause scanning so echoed keystrokes don't trigger +// shutdown. The timer is reset on every keystroke and expires 150 ms after the +// last one — well before any agent response could arrive. +let userTypingTimer = null; + +function scheduleShutdown() { + // (Re-)arm a timer: kill pi after 1 s of PTY silence, i.e. when the agent + // has finished outputting and is waiting for the user to type. + clearTimeout(shutdownTimer); + shutdownTimer = setTimeout(() => { + try { + piProc.kill("SIGTERM"); + } catch { + // already gone + } + }, 1000); +} + +piProc.onData((data) => { + process.stdout.write(data); + + if (userTypingTimer) return; + + if (summaryDetected) { + // Agent is still outputting after the summary word — keep pushing the + // shutdown deadline until output goes quiet. + scheduleShutdown(); + return; + } + + const text = tail + data; + if (text.includes(SENTINEL_COMPLETE) || text.includes(SENTINEL_INCOMPLETE)) { + summaryDetected = true; + scheduleShutdown(); + } else { + tail = text.length > WINDOW ? text.slice(-WINDOW) : text; + } +}); + +piProc.onExit(() => { + process.stdin.setRawMode?.(false); + process.exit(summaryDetected ? 0 : 130); +}); + +// --------------------------------------------------------------------------- +// Forward stdin and resize events +// --------------------------------------------------------------------------- + +if (process.stdin.isTTY) { + process.stdin.setRawMode(true); +} +process.stdin.resume(); +process.stdin.on("data", (data) => { + clearTimeout(userTypingTimer); + userTypingTimer = setTimeout(() => { + userTypingTimer = null; + tail = ""; // discard any echoed chars that landed in the window + }, 150); + piProc.write(typeof data === "string" ? data : data.toString("binary")); +}); + +process.on("SIGWINCH", () => { + piProc.resize(process.stdout.columns ?? 80, process.stdout.rows ?? 24); +}); + +// --------------------------------------------------------------------------- +// Signal forwarding +// --------------------------------------------------------------------------- + +process.on("SIGINT", () => { + // In raw mode, Ctrl-C is forwarded as a data byte (\x03) via stdin.on("data") + // above, so we only need this as a fallback for non-TTY contexts. + try { + piProc.kill("SIGINT"); + } catch { + // already gone + } +}); diff --git a/packages/bt-wizard-harness/eslint.config.mjs b/packages/bt-wizard-harness/eslint.config.mjs new file mode 100644 index 0000000..933b2ab --- /dev/null +++ b/packages/bt-wizard-harness/eslint.config.mjs @@ -0,0 +1,21 @@ +import js from "@eslint/js"; +import prettier from "eslint-config-prettier"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + +export default tseslint.config( + { + ignores: ["dist/**", "coverage/**", "node_modules/**"], + }, + js.configs.recommended, + ...tseslint.configs.recommended, + { + files: ["**/*.{js,mjs,ts}"], + languageOptions: { + ecmaVersion: "latest", + globals: globals.node, + sourceType: "module", + }, + }, + prettier, +); diff --git a/packages/bt-wizard-harness/extensions/bt-tool.ts b/packages/bt-wizard-harness/extensions/bt-tool.ts new file mode 100644 index 0000000..a74a7e9 --- /dev/null +++ b/packages/bt-wizard-harness/extensions/bt-tool.ts @@ -0,0 +1,152 @@ +/** + * `bt` CLI extension. + * + * The bt-wizard harness disables `bash`, but the agent still needs to invoke + * the Braintrust `bt` CLI. We expose `bt` as a first-class tool so + * the model can call it with a structured argv and stdin instead of a raw + * shell line. + * + * Argv is an array of strings — no shell metacharacter interpretation. stdin + * is optional plain text. The tool spawns the `bt` binary directly with + * `shell: false`. + */ + +import { spawn } from "node:child_process"; +import { Type } from "typebox"; + +import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; + +const BT_PARAMS = Type.Object({ + args: Type.Array(Type.String(), { + description: + "Argv passed to the bt CLI (no shell expansion). Example: ['status','--json'].", + }), + stdin: Type.Optional( + Type.String({ + description: "Optional text written to bt's stdin.", + }), + ), + timeout_ms: Type.Optional( + Type.Integer({ + description: "Hard timeout in milliseconds (default 60000).", + minimum: 1000, + maximum: 600000, + }), + ), +}); + +type BtParams = { + args: string[]; + stdin?: string; + timeout_ms?: number; +}; + +const DEFAULT_TIMEOUT_MS = 60_000; +const MAX_OUTPUT_BYTES = 1_000_000; + +function runBt(params: BtParams): Promise<{ + exitCode: number; + stdout: string; + stderr: string; + timedOut: boolean; +}> { + return new Promise((resolve) => { + const child = spawn("bt", params.args, { + stdio: ["pipe", "pipe", "pipe"], + shell: false, + }); + + let stdoutBytes = 0; + let stderrBytes = 0; + const stdoutChunks: string[] = []; + const stderrChunks: string[] = []; + let timedOut = false; + + const timer = setTimeout(() => { + timedOut = true; + child.kill("SIGTERM"); + setTimeout(() => child.kill("SIGKILL"), 1000).unref(); + }, params.timeout_ms ?? DEFAULT_TIMEOUT_MS); + + child.stdout.setEncoding("utf8"); + child.stderr.setEncoding("utf8"); + child.stdout.on("data", (d: string) => { + stdoutBytes += Buffer.byteLength(d); + if (stdoutBytes < MAX_OUTPUT_BYTES) { + stdoutChunks.push(d); + } + }); + child.stderr.on("data", (d: string) => { + stderrBytes += Buffer.byteLength(d); + if (stderrBytes < MAX_OUTPUT_BYTES) { + stderrChunks.push(d); + } + }); + + child.on("error", (err) => { + clearTimeout(timer); + resolve({ + exitCode: 127, + stdout: "", + stderr: `Failed to spawn bt: ${err.message}`, + timedOut: false, + }); + }); + + child.on("close", (code) => { + clearTimeout(timer); + resolve({ + exitCode: code ?? -1, + stdout: stdoutChunks.join(""), + stderr: stderrChunks.join(""), + timedOut, + }); + }); + + if (params.stdin && params.stdin.length > 0) { + child.stdin.write(params.stdin); + } + child.stdin.end(); + }); +} + +export default function btTool(pi: ExtensionAPI) { + pi.registerTool({ + name: "bt", + label: "bt CLI", + description: + "Run the Braintrust `bt` CLI with a structured argv. Use for `bt status`, `bt sql`, etc.", + promptSnippet: + "Invoke `bt` for Braintrust CLI operations (status, queries, project info). bash/python are not available.", + promptGuidelines: [ + "Pass argv as an array — do not embed shell quoting.", + "Prefer `bt status --json` to inspect the active org/project.", + "Use `bt sql --json` for BTQL queries to verify traces; include a timestamp filter.", + ], + parameters: BT_PARAMS, + async execute(_toolCallId, params) { + const result = await runBt(params as BtParams); + const summary = result.timedOut + ? `bt timed out (exit ${result.exitCode})` + : `bt exited ${result.exitCode}`; + return { + content: [ + { + type: "text", + text: [ + summary, + "--- stdout ---", + result.stdout, + "--- stderr ---", + result.stderr, + ].join("\n"), + }, + ], + details: { + exitCode: result.exitCode, + timedOut: result.timedOut, + }, + }; + }, + }); +} diff --git a/packages/bt-wizard-harness/extensions/curl-tool.ts b/packages/bt-wizard-harness/extensions/curl-tool.ts new file mode 100644 index 0000000..e722571 --- /dev/null +++ b/packages/bt-wizard-harness/extensions/curl-tool.ts @@ -0,0 +1,182 @@ +/** + * `curl` extension. + * + * Read-only HTTP fetcher. GET and HEAD are permitted; POST/PUT/DELETE and + * other stateful methods are blocked. Redirects are followed. Used by the + * agent to read external documentation (e.g. https://www.braintrust.dev/docs, + * library README pages, package indexes). + * + * No URL allow/block list — the agent may need to consult arbitrary + * library docs. Path-guard still constrains the file system. + */ + +import { Type } from "typebox"; + +import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; + +const CURL_PARAMS = Type.Object({ + url: Type.String({ description: "Absolute http(s) URL." }), + method: Type.Optional( + Type.Union([Type.Literal("GET"), Type.Literal("HEAD")], { + description: + "HTTP method. Defaults to GET. Only GET and HEAD are allowed.", + }), + ), + headers: Type.Optional( + Type.Record(Type.String(), Type.String(), { + description: "Extra request headers (e.g. Accept).", + }), + ), + timeout_ms: Type.Optional( + Type.Integer({ + description: "Hard timeout in milliseconds (default 30000).", + minimum: 1000, + maximum: 300000, + }), + ), +}); + +type CurlParams = { + url: string; + method?: "GET" | "HEAD"; + headers?: Record; + timeout_ms?: number; +}; + +const DEFAULT_TIMEOUT_MS = 30_000; +const MAX_BODY_BYTES = 1_000; + +const ALLOWED_METHODS = new Set(["GET", "HEAD"]); + +function isHttpUrl(raw: string): boolean { + try { + const u = new URL(raw); + return u.protocol === "http:" || u.protocol === "https:"; + } catch { + return false; + } +} + +async function runCurl(params: CurlParams): Promise<{ + status: number; + statusText: string; + url: string; + headers: Record; + body: string; + truncated: boolean; +}> { + const method = params.method ?? "GET"; + if (!ALLOWED_METHODS.has(method)) { + throw new Error(`Method ${method} is not permitted (GET/HEAD only).`); + } + if (!isHttpUrl(params.url)) { + throw new Error(`URL must be http(s): ${params.url}`); + } + + const controller = new AbortController(); + const timer = setTimeout( + () => controller.abort(), + params.timeout_ms ?? DEFAULT_TIMEOUT_MS, + ); + try { + const res = await fetch(params.url, { + method, + headers: params.headers, + redirect: "follow", + signal: controller.signal, + }); + + const headers: Record = {}; + res.headers.forEach((v, k) => { + headers[k] = v; + }); + + let body = ""; + let truncated = false; + if (method !== "HEAD") { + const reader = res.body?.getReader(); + if (reader) { + const decoder = new TextDecoder("utf-8", { fatal: false }); + let bytes = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + if (bytes + value.byteLength > MAX_BODY_BYTES) { + body += decoder.decode(value.subarray(0, MAX_BODY_BYTES - bytes), { + stream: false, + }); + truncated = true; + try { + await reader.cancel(); + } catch { + /* ignore */ + } + break; + } + bytes += value.byteLength; + body += decoder.decode(value, { stream: true }); + } + if (!truncated) { + body += decoder.decode(); + } + } + } + + return { + status: res.status, + statusText: res.statusText, + url: res.url, + headers, + body, + truncated, + }; + } finally { + clearTimeout(timer); + } +} + +export default function curlTool(pi: ExtensionAPI) { + pi.registerTool({ + name: "curl", + label: "curl (GET/HEAD)", + description: + "Fetch a URL via HTTP GET or HEAD. Follows redirects. No POST/PUT/DELETE. Use to read docs, READMEs, package indexes.", + promptSnippet: + "Use `curl` to fetch documentation pages or other read-only HTTP resources. POST and stateful methods are not available — anything stateful must go through `bt`.", + promptGuidelines: [ + "Only GET and HEAD are permitted; the tool errors otherwise.", + "Pass full absolute URLs.", + "Prefer https://www.braintrust.dev/docs/... for Braintrust-specific guidance.", + "Bodies above 1 MB are truncated; the response indicates truncation.", + ], + parameters: CURL_PARAMS, + async execute(_toolCallId, params) { + try { + const result = await runCurl(params as CurlParams); + const truncatedNote = result.truncated ? "\n[truncated]" : ""; + const text = [ + `${result.status} ${result.statusText} (${result.url})`, + result.body + truncatedNote, + ].join("\n"); + return { + content: [{ type: "text", text }], + details: { + status: result.status, + url: result.url, + truncated: result.truncated, + }, + }; + } catch (err) { + return { + content: [ + { + type: "text", + text: `curl failed: ${(err as Error).message}`, + }, + ], + details: { error: (err as Error).message }, + }; + } + }, + }); +} diff --git a/packages/bt-wizard-harness/extensions/git-tool.ts b/packages/bt-wizard-harness/extensions/git-tool.ts new file mode 100644 index 0000000..c0a5d7d --- /dev/null +++ b/packages/bt-wizard-harness/extensions/git-tool.ts @@ -0,0 +1,262 @@ +/** + * `git` extension. + * + * Exposes a structured `git` tool. An allowlist of safe subcommands is + * enforced; destructive remote and force operations are blocked. + * + * Allowed: read-only queries (status, log, diff, show, blame, grep, ls-files, + * ls-tree, rev-parse, describe, branch, tag, shortlog) plus staging and + * committing (add, commit) and file-level restore (checkout, restore). + * + * Blocked: push, pull, fetch, clone, remote, reset --hard, clean -f, and + * any subcommand not in the allowlist. + */ + +import { spawn } from "node:child_process"; +import { Type } from "typebox"; + +import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; + +const ALLOWED_SUBCOMMANDS = new Set([ + // read-only + "status", + "log", + "diff", + "show", + "blame", + "grep", + "ls-files", + "ls-tree", + "ls-remote", + "rev-parse", + "rev-list", + "describe", + "branch", + "tag", + "shortlog", + "stash", + "format-patch", + // staging / committing + "add", + "commit", + // file-level restore (must be used with a path, not to switch branches) + "checkout", + "restore", + // submodule inspection + "submodule", +]); + +// argv elements that make otherwise-safe subcommands dangerous +const BLOCKED_FLAGS = new Set([ + "--force", + "-f", + "--hard", + "--delete", + "-D", + "--mirror", + "--all", +]); + +// Subcommand-specific blocks regardless of flags +const BLOCKED_SUBCOMMANDS = new Set([ + "push", + "pull", + "fetch", + "clone", + "remote", + "clean", + "rebase", + "merge", + "cherry-pick", + "revert", + "bisect", + "reflog", + "gc", + "fsck", + "filter-branch", + "am", + "apply", +]); + +const GIT_PARAMS = Type.Object({ + args: Type.Array(Type.String(), { + description: + "Argv passed to git (no shell expansion). Example: ['status', '--short'].", + }), + stdin: Type.Optional( + Type.String({ + description: "Optional text written to git's stdin.", + }), + ), + timeout_ms: Type.Optional( + Type.Integer({ + description: "Hard timeout in milliseconds (default 30000).", + minimum: 1000, + maximum: 120000, + }), + ), +}); + +type GitParams = { + args: string[]; + stdin?: string; + timeout_ms?: number; +}; + +const DEFAULT_TIMEOUT_MS = 30_000; +const MAX_OUTPUT_BYTES = 500_000; + +function runGit( + params: GitParams, + cwd: string, +): Promise<{ + exitCode: number; + stdout: string; + stderr: string; + timedOut: boolean; +}> { + return new Promise((resolve) => { + const child = spawn("git", params.args, { + cwd, + stdio: ["pipe", "pipe", "pipe"], + shell: false, + }); + + let stdoutBytes = 0; + let stderrBytes = 0; + const stdoutChunks: string[] = []; + const stderrChunks: string[] = []; + let timedOut = false; + + const timer = setTimeout(() => { + timedOut = true; + child.kill("SIGTERM"); + setTimeout(() => child.kill("SIGKILL"), 1000).unref(); + }, params.timeout_ms ?? DEFAULT_TIMEOUT_MS); + + child.stdout.setEncoding("utf8"); + child.stderr.setEncoding("utf8"); + child.stdout.on("data", (d: string) => { + stdoutBytes += Buffer.byteLength(d); + if (stdoutBytes < MAX_OUTPUT_BYTES) stdoutChunks.push(d); + }); + child.stderr.on("data", (d: string) => { + stderrBytes += Buffer.byteLength(d); + if (stderrBytes < MAX_OUTPUT_BYTES) stderrChunks.push(d); + }); + + child.on("error", (err) => { + clearTimeout(timer); + resolve({ + exitCode: 127, + stdout: "", + stderr: `Failed to spawn git: ${err.message}`, + timedOut: false, + }); + }); + + child.on("close", (code) => { + clearTimeout(timer); + resolve({ + exitCode: code ?? -1, + stdout: stdoutChunks.join(""), + stderr: stderrChunks.join(""), + timedOut, + }); + }); + + if (params.stdin && params.stdin.length > 0) { + child.stdin.write(params.stdin); + } + child.stdin.end(); + }); +} + +export default function gitTool(pi: ExtensionAPI) { + pi.registerTool({ + name: "git", + label: "git", + description: + "Run safe git commands (read-only queries, add, commit, checkout/restore for files). Push, pull, fetch, remote modifications, and destructive resets are blocked.", + promptSnippet: + "Use `git` for version-control operations: status, log, diff, add, commit. bash/python are not available.", + promptGuidelines: [ + "Pass argv as an array — do not embed shell quoting.", + "Use `git status` and `git diff` to inspect changes before committing.", + "Use `git add ` then `git commit -m '...'` to stage and commit SDK changes.", + "Push, pull, fetch, and destructive resets are blocked.", + ], + parameters: GIT_PARAMS, + async execute(_toolCallId, params) { + const p = params as GitParams; + const subcommand = p.args[0]; + + if (!subcommand) { + return { + content: [{ type: "text", text: "error: no git subcommand given" }], + details: { blocked: true }, + }; + } + + if (BLOCKED_SUBCOMMANDS.has(subcommand)) { + return { + content: [ + { + type: "text", + text: `error: git ${subcommand} is not permitted in the bt-wizard harness.`, + }, + ], + details: { blocked: true, subcommand }, + }; + } + + if (!ALLOWED_SUBCOMMANDS.has(subcommand)) { + return { + content: [ + { + type: "text", + text: `error: git ${subcommand} is not in the allowed list. Use request_command if you need it.`, + }, + ], + details: { blocked: true, subcommand }, + }; + } + + // Block dangerous flags on otherwise-allowed subcommands. + // Exception: `git checkout -f` on a file path is still blocked. + for (const arg of p.args.slice(1)) { + if (BLOCKED_FLAGS.has(arg)) { + return { + content: [ + { + type: "text", + text: `error: flag "${arg}" is not permitted in git ${subcommand}.`, + }, + ], + details: { blocked: true, flag: arg }, + }; + } + } + + const result = await runGit(p, process.cwd()); + const summary = result.timedOut + ? `git timed out (exit ${result.exitCode})` + : `git exited ${result.exitCode}`; + return { + content: [ + { + type: "text", + text: [ + summary, + "--- stdout ---", + result.stdout, + "--- stderr ---", + result.stderr, + ].join("\n"), + }, + ], + details: { exitCode: result.exitCode, timedOut: result.timedOut }, + }; + }, + }); +} diff --git a/packages/bt-wizard-harness/extensions/package-manager-tool.ts b/packages/bt-wizard-harness/extensions/package-manager-tool.ts new file mode 100644 index 0000000..7daba25 --- /dev/null +++ b/packages/bt-wizard-harness/extensions/package-manager-tool.ts @@ -0,0 +1,422 @@ +/** + * Package-manager / formatter / linter / test-runner extension. + * + * Exposes a `pkg` tool so the agent can run language tooling without needing + * bash. The allowed tools are gated by the languages detected by bt-wizard, + * passed in via the `BT_WIZARD_LANGUAGES` environment variable. + * + * If no languages are detected, all known tools are permitted. + * + * Per-language allowlists: + * + * Python + * pkg managers: conda, hatch, mamba, pdm, pip, pipenv, pipx, poetry, rye, uv + * formatters: autopep8, black, isort, ruff, yapf + * linters: flake8, mypy, pylint, pyright, ruff + * test: coverage, nose2, pytest, tox, unittest + * + * JavaScript / TypeScript + * pkg managers: bun, deno, ni, npm, pnpm, yarn + * formatters: biome, dprint, prettier + * linters: biome, eslint, oxlint + * test: ava, jasmine, jest, mocha, vitest + * + * Go + * pkg managers: dep, glide, go + * formatters: gofmt, gofumpt, goimports + * linters: golangci-lint, revive, staticcheck + * test: ginkgo, gomock, testify + * + * C# + * pkg managers: choco, dotnet, nuget, paket + * formatters: csharpier, dotnet + * linters: dotnet + * test: dotnet + * + * Java + * pkg managers: bazel, gradle, ivy, mvn, mill, sbt + * formatters: checkstyle, google-java-format, spotless + * linters: checkstyle, pmd, spotbugs + * test: gradle, mvn, sbt + * + * Ruby + * pkg managers: asdf, bundle, gem, rbenv, rvm + * formatters: rubocop, rufo, standardrb + * linters: brakeman, reek, rubocop, standardrb + * test: cucumber, minitest, rspec, test-unit + */ + +import { spawn } from "node:child_process"; +import { Type } from "typebox"; + +import type { ExtensionAPI, Theme } from "@mariozechner/pi-coding-agent"; +import { Text } from "@mariozechner/pi-tui"; + +type Language = "python" | "typescript" | "go" | "csharp" | "java" | "ruby"; + +const LANGUAGE_TOOLS: Record = { + python: [ + // interpreters + "python", + "python3", + // package managers + "conda", + "hatch", + "mamba", + "pdm", + "pip", + "pipenv", + "pipx", + "poetry", + "rye", + "uv", + // formatters + "autopep8", + "black", + "isort", + "yapf", + // linters + "flake8", + "mypy", + "pylint", + "pyright", + // ruff handles both formatting and linting + "ruff", + // test + "coverage", + "nose2", + "pytest", + "tox", + "unittest", + ], + typescript: [ + // interpreters / runtimes + "node", + "npx", + "ts-node", + "tsx", + // package managers (bun and deno double as runtimes) + "bun", + "deno", + "ni", + "npm", + "pnpm", + "yarn", + // formatters + "dprint", + "prettier", + // linters + "eslint", + "oxlint", + // biome handles formatting + linting + "biome", + // test + "ava", + "jasmine", + "jest", + "mocha", + "vitest", + ], + go: [ + // interpreter/compiler (go run, go build, go test, go mod …) + "dep", + "glide", + "go", + // formatters + "gofmt", + "gofumpt", + "goimports", + // linters + "golangci-lint", + "revive", + "staticcheck", + // test (go test is via "go", others are standalone) + "ginkgo", + "gomock", + "testify", + ], + csharp: [ + // runtime / package managers / build — dotnet covers all of these + "dotnet", + // package managers + "choco", + "nuget", + "paket", + // formatters + linters + "csharpier", + ], + java: [ + // interpreter / compiler + "java", + "javac", + // package managers / build tools + "bazel", + "gradle", + "ivy", + "mvn", + "mill", + "sbt", + // formatters / linters + "checkstyle", + "google-java-format", + "spotless", + "pmd", + "spotbugs", + ], + ruby: [ + // interpreter + "ruby", + // package managers + "asdf", + "bundle", + "gem", + "rbenv", + "rvm", + // formatters + linters (rubocop / standardrb handle both) + "rubocop", + "rufo", + "standardrb", + // linters + "brakeman", + "reek", + // test + "cucumber", + "minitest", + "rspec", + "test-unit", + ], +}; + +// Always allowed regardless of detected language. +const UNIVERSAL_TOOLS: ReadonlySet = new Set(["env"]); + +const ALL_TOOLS: ReadonlySet = new Set([ + ...UNIVERSAL_TOOLS, + ...(Object.values(LANGUAGE_TOOLS) as readonly string[][]).flat(), +]); + +function allowedTools(): ReadonlySet { + const raw = process.env["BT_WIZARD_LANGUAGES"] ?? ""; + const langs = raw + .split(",") + .map((s) => s.trim()) + .filter((s): s is Language => s.length > 0 && s in LANGUAGE_TOOLS); + if (langs.length === 0) { + return ALL_TOOLS; + } + const allowed = new Set([...UNIVERSAL_TOOLS]); + for (const lang of langs) { + for (const tool of LANGUAGE_TOOLS[lang]) { + allowed.add(tool); + } + } + return allowed; +} + +const PKG_PARAMS = Type.Object({ + manager: Type.String({ + description: + "Tool binary name (package manager, formatter, linter, or test runner — e.g. npm, pip, go, pytest, eslint). Must be in the allowed list for the project's language.", + }), + args: Type.Array(Type.String(), { + description: + "Arguments passed to the package manager (no shell expansion). Example: ['install', 'braintrust'].", + }), + timeout_ms: Type.Optional( + Type.Integer({ + description: "Hard timeout in milliseconds (default 120000).", + minimum: 1000, + maximum: 600000, + }), + ), +}); + +type PkgParams = { + manager: string; + args: string[]; + timeout_ms?: number; +}; + +const DEFAULT_TIMEOUT_MS = 120_000; +const MAX_STREAM_BYTES = 500; + +function tailTruncate( + s: string, + maxBytes: number, +): { text: string; truncated: boolean } { + const buf = Buffer.from(s, "utf8"); + if (buf.byteLength <= maxBytes) return { text: s, truncated: false }; + return { text: buf.slice(-maxBytes).toString("utf8"), truncated: true }; +} + +function runPkg( + manager: string, + args: string[], + timeoutMs: number, + cwd: string, +): Promise<{ + exitCode: number; + stdout: string; + stderr: string; + timedOut: boolean; +}> { + return new Promise((resolve) => { + const child = spawn(manager, args, { + cwd, + stdio: ["ignore", "pipe", "pipe"], + shell: false, + }); + + const stdoutChunks: string[] = []; + const stderrChunks: string[] = []; + let timedOut = false; + + const timer = setTimeout(() => { + timedOut = true; + child.kill("SIGTERM"); + setTimeout(() => child.kill("SIGKILL"), 2000).unref(); + }, timeoutMs); + + child.stdout.setEncoding("utf8"); + child.stderr.setEncoding("utf8"); + child.stdout.on("data", (d: string) => { + stdoutChunks.push(d); + }); + child.stderr.on("data", (d: string) => { + stderrChunks.push(d); + }); + + child.on("error", (err) => { + clearTimeout(timer); + resolve({ + exitCode: 127, + stdout: "", + stderr: `Failed to spawn ${manager}: ${err.message}`, + timedOut: false, + }); + }); + + child.on("close", (code) => { + clearTimeout(timer); + resolve({ + exitCode: code ?? -1, + stdout: stdoutChunks.join(""), + stderr: stderrChunks.join(""), + timedOut, + }); + }); + }); +} + +export default function packageManagerTool(pi: ExtensionAPI) { + const allowed = allowedTools(); + const allowedList = [...allowed].sort().join(", "); + + pi.registerTool({ + name: "pkg", + label: "language tooling", + description: `Run language package managers, formatters, linters, and test runners. Allowed tools for this project: ${allowedList}.`, + promptSnippet: + "Use `pkg` to run package managers, formatters, linters, and test runners (npm, pip, pytest, eslint, etc.). bash/python are not available.", + promptGuidelines: [ + `Allowed tools: ${allowedList}.`, + "Pass argv as an array — do not embed shell quoting.", + "Example: manager='npm', args=['install','braintrust']", + "Example: manager='pytest', args=['tests/']", + "The command runs in the current working directory.", + ], + parameters: PKG_PARAMS, + renderShell: "self", + renderCall(args: PkgParams, theme: Theme) { + const cmd = [args.manager, ...args.args].join(" "); + return new Text( + theme.fg("toolTitle", "$ ") + theme.fg("accent", cmd), + 0, + 0, + ); + }, + renderResult(result, _options, theme, context) { + const details = result.details as + | { exitCode?: number; timedOut?: boolean; blocked?: boolean } + | undefined; + const a = context.args as PkgParams; + const cmd = [a.manager, ...a.args].join(" "); + + if (details?.blocked) { + return new Text( + theme.fg("toolTitle", "$ ") + + theme.fg("accent", cmd) + + " → " + + theme.fg("error", "blocked"), + 0, + 0, + ); + } + + const exitCode = details?.exitCode ?? -1; + const timedOut = details?.timedOut ?? false; + const status = timedOut + ? theme.fg("warning", `timed out (exit ${exitCode})`) + : exitCode === 0 + ? theme.fg("success", `exit ${exitCode}`) + : theme.fg("error", `exit ${exitCode}`); + + return new Text( + theme.fg("toolTitle", "$ ") + + theme.fg("accent", cmd) + + " → " + + status, + 0, + 0, + ); + }, + async execute(_toolCallId, params) { + const p = params as PkgParams; + const mgr = p.manager.trim().toLowerCase(); + + if (!allowed.has(mgr)) { + return { + content: [ + { + type: "text", + text: [ + `error: "${mgr}" is not an allowed tool for this project.`, + `Allowed: ${allowedList}.`, + `Use request_command if you need a different tool.`, + ].join("\n"), + }, + ], + details: { blocked: true, manager: mgr }, + }; + } + + const result = await runPkg( + mgr, + p.args, + p.timeout_ms ?? DEFAULT_TIMEOUT_MS, + process.cwd(), + ); + const cmd = [mgr, ...p.args].join(" "); + const summary = result.timedOut + ? `$ ${cmd} → timed out (exit ${result.exitCode})` + : `$ ${cmd} → exit ${result.exitCode}`; + const out = tailTruncate(result.stdout, MAX_STREAM_BYTES); + const err = tailTruncate(result.stderr, MAX_STREAM_BYTES); + const parts: string[] = [summary]; + if (out.text) { + if (out.truncated) parts.push("--- stdout (last 500B) ---"); + else parts.push("--- stdout ---"); + parts.push(out.text); + } + if (err.text) { + if (err.truncated) parts.push("--- stderr (last 500B) ---"); + else parts.push("--- stderr ---"); + parts.push(err.text); + } + return { + content: [{ type: "text", text: parts.join("\n") }], + details: { exitCode: result.exitCode, timedOut: result.timedOut }, + }; + }, + }); +} diff --git a/packages/bt-wizard-harness/extensions/path-guard.ts b/packages/bt-wizard-harness/extensions/path-guard.ts new file mode 100644 index 0000000..5a15fe0 --- /dev/null +++ b/packages/bt-wizard-harness/extensions/path-guard.ts @@ -0,0 +1,133 @@ +/** + * Path-guard extension. + * + * Restricts file-touching tool calls (read/write/edit/grep/find/ls) to: + * - the harness's working directory and its subtree, AND + * - `/.env.braintrust` exactly, AND + * - the path in `BT_WIZARD_RESULT_FILE` (used by the wizard to receive the + * trace permalink), if set. + * + * Anything outside that scope is blocked with a clear reason. This is the + * file-system half of the bt-wizard tool whitelist; bash/python are removed + * by running pi with --no-builtin-tools and an explicit -t allowlist. + */ + +import { spawnSync } from "node:child_process"; +import { resolve, isAbsolute } from "node:path"; +import { existsSync } from "node:fs"; + +import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; + +function gitRoot(cwd: string): string | undefined { + const r = spawnSync("git", ["rev-parse", "--show-toplevel"], { + cwd, + encoding: "utf8", + }); + if (r.status !== 0) { + return undefined; + } + const out = r.stdout.trim(); + return out.length > 0 ? out : undefined; +} + +function isUnderRoot(absPath: string, root: string): boolean { + const rel = absPath.startsWith(root + "/") || absPath === root; + return rel; +} + +const PATH_FIELDS = [ + "path", + "file_path", + "filename", + "directory", + "dir", +] as const; + +function extractPath(input: Record): string | undefined { + for (const f of PATH_FIELDS) { + const v = input[f]; + if (typeof v === "string" && v.length > 0) { + return v; + } + } + return undefined; +} + +// Tools that can mutate the filesystem — strictly scoped to cwd. +const WRITE_TOOLS = new Set(["write", "edit"]); +// Read-only tools — also allowed to access pi's data dir (skills, extensions). +const READ_TOOLS = new Set(["read", "grep", "find", "ls"]); + +export default function pathGuard(pi: ExtensionAPI) { + const cwd = process.cwd(); + const cwdAbs = resolve(cwd); + const root = gitRoot(cwdAbs); + const envBraintrust = root ? resolve(root, ".env.braintrust") : undefined; + const envFile = root ? resolve(root, ".env") : undefined; + const resultFileRaw = process.env["BT_WIZARD_RESULT_FILE"]; + const resultFile = + resultFileRaw && resultFileRaw.length > 0 + ? resolve(resultFileRaw) + : undefined; + + const exceptions = [envBraintrust, resultFile].filter( + (p): p is string => typeof p === "string", + ); + // Paths that must never be touched regardless of cwd. + const blockedPaths = [envFile].filter( + (p): p is string => typeof p === "string", + ); + + // pi stores skills, extensions, and config under ~/.agents/ + const homeDir = process.env["HOME"] ?? process.env["USERPROFILE"] ?? ""; + const piDataDir = homeDir ? resolve(homeDir, ".agents") : undefined; + + pi.on("tool_call", async (event) => { + const isWrite = WRITE_TOOLS.has(event.toolName); + const isRead = READ_TOOLS.has(event.toolName); + if (!isWrite && !isRead) { + return undefined; + } + const raw = extractPath(event.input as Record); + if (!raw) { + return undefined; + } + const abs = isAbsolute(raw) ? resolve(raw) : resolve(cwdAbs, raw); + + if (blockedPaths.includes(abs)) { + return { + block: true, + reason: `Accessing "${raw}" is not allowed; use .env.braintrust instead.`, + }; + } + if (exceptions.includes(abs)) { + return undefined; + } + if (isUnderRoot(abs, cwdAbs)) { + return undefined; + } + // Allow read-only tools to access pi's data directory (skills, extensions). + if (isRead && piDataDir && isUnderRoot(abs, piDataDir)) { + return undefined; + } + return { + block: true, + reason: `Path "${raw}" is outside the bt-wizard scope (cwd subtree${ + exceptions.length > 0 ? ` plus ${exceptions.join(", ")}` : "" + }).`, + }; + }); + + pi.on("session_start", (_event, ctx) => { + if (!ctx.hasUI) { + return; + } + ctx.ui.setToolsExpanded(false); + ctx.ui.notify( + `bt-wizard path-guard active: cwd=${cwdAbs}${ + exceptions.length > 0 ? `, exception=${exceptions.join(", ")}` : "" + }${existsSync(cwdAbs) ? "" : " (cwd missing!)"}`, + "info", + ); + }); +} diff --git a/packages/bt-wizard-harness/extensions/request-command-tool.ts b/packages/bt-wizard-harness/extensions/request-command-tool.ts new file mode 100644 index 0000000..9913f56 --- /dev/null +++ b/packages/bt-wizard-harness/extensions/request-command-tool.ts @@ -0,0 +1,194 @@ +/** + * `request_command` extension. + * + * Lets the agent ask the user to approve a one-off command that is not in the + * default allowed tool list (git, pkg, bt, curl, read/write/edit/grep/find/ls). + * + * Uses ctx.ui.confirm() so it works in both interactive and RPC mode. + * In RPC mode the harness handles the extension_ui_request sub-protocol; + * the tool does not touch stdin directly. + */ + +import { spawn } from "node:child_process"; +import { Type } from "typebox"; + +import type { + ExtensionAPI, + ExtensionContext, +} from "@mariozechner/pi-coding-agent"; + +const REQUEST_PARAMS = Type.Object({ + command: Type.String({ + description: + "The executable or script to run (e.g. 'npx', 'node', 'make').", + }), + args: Type.Array(Type.String(), { + description: "Arguments for the command (no shell expansion).", + }), + reason: Type.String({ + description: "Why this command is needed — shown to the user.", + }), + timeout_ms: Type.Optional( + Type.Integer({ + description: "Hard timeout in milliseconds (default 120000).", + minimum: 1000, + maximum: 600000, + }), + ), +}); + +type RequestParams = { + command: string; + args: string[]; + reason: string; + timeout_ms?: number; +}; + +const DEFAULT_TIMEOUT_MS = 120_000; +const MAX_OUTPUT_BYTES = 1_000_000; + +function runCommand( + command: string, + args: string[], + timeoutMs: number, + cwd: string, +): Promise<{ + exitCode: number; + stdout: string; + stderr: string; + timedOut: boolean; +}> { + return new Promise((resolve) => { + const child = spawn(command, args, { + cwd, + stdio: ["ignore", "pipe", "pipe"], + shell: false, + }); + + let stdoutBytes = 0; + let stderrBytes = 0; + const stdoutChunks: string[] = []; + const stderrChunks: string[] = []; + let timedOut = false; + + const timer = setTimeout(() => { + timedOut = true; + child.kill("SIGTERM"); + setTimeout(() => child.kill("SIGKILL"), 2000).unref(); + }, timeoutMs); + + child.stdout.setEncoding("utf8"); + child.stderr.setEncoding("utf8"); + child.stdout.on("data", (d: string) => { + stdoutBytes += Buffer.byteLength(d); + if (stdoutBytes < MAX_OUTPUT_BYTES) stdoutChunks.push(d); + }); + child.stderr.on("data", (d: string) => { + stderrBytes += Buffer.byteLength(d); + if (stderrBytes < MAX_OUTPUT_BYTES) stderrChunks.push(d); + }); + + child.on("error", (err) => { + clearTimeout(timer); + resolve({ + exitCode: 127, + stdout: "", + stderr: `Failed to spawn ${command}: ${err.message}`, + timedOut: false, + }); + }); + + child.on("close", (code) => { + clearTimeout(timer); + resolve({ + exitCode: code ?? -1, + stdout: stdoutChunks.join(""), + stderr: stderrChunks.join(""), + timedOut, + }); + }); + }); +} + +export default function requestCommandTool(pi: ExtensionAPI) { + pi.registerTool({ + name: "request_command", + label: "Request command approval", + description: + "Ask the user to approve running a command that is not in the default allowed tool list. The command only runs if the user confirms.", + promptSnippet: + "Use `request_command` when you need to run a tool not otherwise available (e.g. npx, node scripts, make). The user must approve each call.", + promptGuidelines: [ + "Use this only when no other allowed tool can accomplish the task.", + "Be specific and concise in the `reason` field.", + "Pass argv as an array — do not embed shell quoting.", + "The user sees the full command and reason before deciding.", + ], + parameters: REQUEST_PARAMS, + async execute( + _toolCallId, + params, + _signal, + _onUpdate, + ctx: ExtensionContext, + ) { + const p = params as RequestParams; + const fullCommand = [p.command, ...p.args].join(" "); + + if (p.command === "sudo" || p.args.includes("sudo")) { + return { + content: [ + { type: "text", text: `Command denied: sudo is not allowed.` }, + ], + details: { approved: false }, + }; + } + + const approved = await ctx.ui.confirm( + "bt-wizard: command approval requested", + `Command: ${fullCommand}\nReason: ${p.reason}`, + ); + + if (!approved) { + return { + content: [ + { + type: "text", + text: `Command denied by user: ${fullCommand}`, + }, + ], + details: { approved: false }, + }; + } + + const result = await runCommand( + p.command, + p.args, + p.timeout_ms ?? DEFAULT_TIMEOUT_MS, + process.cwd(), + ); + const summary = result.timedOut + ? `${p.command} timed out (exit ${result.exitCode})` + : `${p.command} exited ${result.exitCode}`; + return { + content: [ + { + type: "text", + text: [ + summary, + "--- stdout ---", + result.stdout, + "--- stderr ---", + result.stderr, + ].join("\n"), + }, + ], + details: { + approved: true, + exitCode: result.exitCode, + timedOut: result.timedOut, + }, + }; + }, + }); +} diff --git a/packages/bt-wizard-harness/package.json b/packages/bt-wizard-harness/package.json new file mode 100644 index 0000000..0219782 --- /dev/null +++ b/packages/bt-wizard-harness/package.json @@ -0,0 +1,38 @@ +{ + "name": "@braintrust/bt-wizard-harness", + "version": "0.1.0", + "private": true, + "description": "Restricted pi-coding-agent harness for the bt-wizard CLI: write/edit/grep + web search + bt only.", + "type": "module", + "scripts": { + "lint": "eslint .", + "format": "prettier --write .", + "format:check": "prettier --check ." + }, + "dependencies": { + "@earendil-works/pi-coding-agent": "*", + "@earendil-works/pi-tui": "*", + "node-pty": "^1.1.0", + "@sinclair/typebox": "^0.34.49" + }, + "devDependencies": { + "@eslint/js": "10.0.1", + "@types/node": "24.12.2", + "eslint": "10.3.0", + "eslint-config-prettier": "10.1.8", + "globals": "17.6.0", + "prettier": "3.8.3", + "typescript": "6.0.3", + "typescript-eslint": "8.59.2" + }, + "pi": { + "extensions": [ + "./extensions/path-guard.ts", + "./extensions/bt-tool.ts", + "./extensions/curl-tool.ts", + "./extensions/git-tool.ts", + "./extensions/package-manager-tool.ts", + "./extensions/request-command-tool.ts" + ] + } +} diff --git a/packages/bt-wizard-harness/tsconfig.json b/packages/bt-wizard-harness/tsconfig.json new file mode 100644 index 0000000..ded62c8 --- /dev/null +++ b/packages/bt-wizard-harness/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "exactOptionalPropertyTypes": true, + "isolatedModules": true, + "lib": ["ES2024"], + "module": "ESNext", + "moduleDetection": "force", + "moduleResolution": "Bundler", + "noEmit": true, + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noUncheckedIndexedAccess": true, + "skipLibCheck": true, + "strict": true, + "target": "ES2024", + "types": ["node"] + }, + "include": [ + "bin/**/*.ts", + "bin/**/*.mjs", + "extensions/**/*.ts", + "*.config.mjs" + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2c0337d..d230d50 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,44 +7,68 @@ settings: importers: .: + devDependencies: + prettier: + specifier: 3.8.3 + version: 3.8.3 + + packages/braintrust-wizard: dependencies: '@clack/prompts': specifier: 1.3.0 version: 1.3.0 + '@inquirer/search': + specifier: 4.1.8 + version: 4.1.8(@types/node@24.12.2) '@tanstack/react-query': specifier: 5.100.9 version: 5.100.9(react@19.2.5) + ignore: + specifier: ^7.0.5 + version: 7.0.5 ink: specifier: 7.0.2 version: 7.0.2(@types/react@19.2.14)(react-devtools-core@7.0.1)(react@19.2.5) + open: + specifier: ^11.0.0 + version: 11.0.0 react: specifier: 19.2.5 version: 19.2.5 react-devtools-core: specifier: 7.0.1 version: 7.0.1 + yargs: + specifier: ^18.0.0 + version: 18.0.0 devDependencies: + '@braintrust/proxy': + specifier: 0.0.9 + version: 0.0.9(react@19.2.5)(solid-js@1.9.12)(svelte@4.2.20)(vue@3.5.34(typescript@6.0.3))(ws@8.20.0) '@eslint/js': specifier: 10.0.1 - version: 10.0.1(eslint@10.3.0) + version: 10.0.1(eslint@10.3.0(jiti@2.7.0)) '@types/node': specifier: 24.12.2 version: 24.12.2 '@types/react': specifier: 19.2.14 version: 19.2.14 + '@types/yargs': + specifier: ^17.0.35 + version: 17.0.35 eslint: specifier: 10.3.0 - version: 10.3.0 + version: 10.3.0(jiti@2.7.0) eslint-config-prettier: specifier: 10.1.8 - version: 10.1.8(eslint@10.3.0) + version: 10.1.8(eslint@10.3.0(jiti@2.7.0)) eslint-plugin-react: specifier: 7.37.5 - version: 7.37.5(eslint@10.3.0) + version: 7.37.5(eslint@10.3.0(jiti@2.7.0)) eslint-plugin-react-hooks: specifier: 7.1.1 - version: 7.1.1(eslint@10.3.0) + version: 7.1.1(eslint@10.3.0(jiti@2.7.0)) globals: specifier: 17.6.0 version: 17.6.0 @@ -59,10 +83,50 @@ importers: version: 6.0.3 typescript-eslint: specifier: 8.59.2 - version: 8.59.2(eslint@10.3.0)(typescript@6.0.3) + version: 8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: 4.1.5 - version: 4.1.5(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)) + version: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(jiti@2.7.0)(yaml@2.9.0)) + + packages/bt-wizard-harness: + dependencies: + '@earendil-works/pi-coding-agent': + specifier: '*' + version: 0.74.0(ws@8.20.0)(zod@4.4.3) + '@earendil-works/pi-tui': + specifier: '*' + version: 0.74.0 + '@sinclair/typebox': + specifier: ^0.34.49 + version: 0.34.49 + node-pty: + specifier: ^1.1.0 + version: 1.1.0 + devDependencies: + '@eslint/js': + specifier: 10.0.1 + version: 10.0.1(eslint@10.3.0(jiti@2.7.0)) + '@types/node': + specifier: 24.12.2 + version: 24.12.2 + eslint: + specifier: 10.3.0 + version: 10.3.0(jiti@2.7.0) + eslint-config-prettier: + specifier: 10.1.8 + version: 10.1.8(eslint@10.3.0(jiti@2.7.0)) + globals: + specifier: 17.6.0 + version: 17.6.0 + prettier: + specifier: 3.8.3 + version: 3.8.3 + typescript: + specifier: 6.0.3 + version: 6.0.3 + typescript-eslint: + specifier: 8.59.2 + version: 8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) packages: @@ -70,6 +134,180 @@ packages: resolution: {integrity: sha512-p+CMKJ93HFmLkjXKlXiVGlMQEuRb6H0MokBSwUsX+S6BRX8eV5naFZpQJFfJHjRZY0Hmnqy1/r6UWl3x+19zYA==} engines: {node: '>=18'} + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@anthropic-ai/sdk@0.39.0': + resolution: {integrity: sha512-eMyDIPRZbt1CCLErRCi3exlAvNkBtRe+kW5vvJyef93PmNr/clstYgHhtvmkxN82nlKgzyGPCyGxrm0JQ1ZIdg==} + + '@anthropic-ai/sdk@0.91.1': + resolution: {integrity: sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==} + hasBin: true + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@apidevtools/json-schema-ref-parser@11.9.3': + resolution: {integrity: sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==} + engines: {node: '>= 16'} + + '@asteasolutions/zod-to-openapi@6.4.0': + resolution: {integrity: sha512-8cxfF7AHHx2PqnN4Cd8/O8CBu/nVYJP9DpnfVLW3BFb66VJDnqI/CczZnkqMc3SNh6J9GiX7JbJ5T4BSP4HZ2Q==} + peerDependencies: + zod: ^3.20.2 + + '@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.1045.0': + resolution: {integrity: sha512-aPC6gAz9uKRiwfnKB7peTs6yD0FpSzmVnSkx0f2QtJfosFM6J6KtBvR1lMKby050K4C4PAyEScwA5YTsGfTcGA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.974.8': + resolution: {integrity: sha512-njR2qoG6ZuB0kvAS2FyICsFZJ6gmCcf2X/7JcD14sUvGDm26wiZ5BrA6LOiUxKFEF+IVe7kdroxyE00YlkiYsw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.34': + resolution: {integrity: sha512-XT0jtf8Fw9JE6ppsQeoNnZRiG+jqRixMT1v1ZR17G60UvVdsQmTG8nbEyHuEPfMxDXEhfdARaM/XiEhca4lGHQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-http@3.972.36': + resolution: {integrity: sha512-DPoGWfy7J7RKxvbf5kOKIGQkD2ek3dbKgzKIGrnLuvZBz5myU+Im/H6pmc14QcnFbqHMqxvtWSgRDSJW3qXLQg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-ini@3.972.38': + resolution: {integrity: sha512-oDzUBu2MGJFgoar05sPMCwSrhw44ASyccrHzj66vO69OZqi7I6hZZxXfuPLC8OCzW7C+sU+bI73XHij41yekgQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.38': + resolution: {integrity: sha512-g1NosS8qe4OF++G2UFCM5ovSkgipC7YYor5KCWatG0UoMSO5YFj9C8muePlyVmOBV/WTI16Jo3/s1NUo/o1Bww==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-node@3.972.39': + resolution: {integrity: sha512-HEswDQyxUtadoZ/bJsPPENHg7R0Lzym5LuMksJeHvqhCOpP+rtkDLKI4/ZChH4w3cf5kG8n6bZuI8PzajoiqMg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-process@3.972.34': + resolution: {integrity: sha512-T3IFs4EVmVi1dVN5RciFnklCANSzvrQd/VuHY9ThHSQmYkTogjcGkoJEr+oNUPQZnso52183088NqysMPji1/Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-sso@3.972.38': + resolution: {integrity: sha512-5ZxG+t0+3Q3QPh8KEjX6syskhgNf7I0MN7oGioTf6Lm1NTjfP7sIcYGNsthXC2qR8vcD3edNZwCr2ovfSSWuRA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.972.38': + resolution: {integrity: sha512-lYHFF30DGI20jZcYX8cm6Ns0V7f1dDN6g/MBDLTyD/5iw+bXs3yBr2iAiHDkx4RFU5JgsnZvCHYKiRVPRdmOgw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/eventstream-handler-node@3.972.14': + resolution: {integrity: sha512-m4X56gxG76/CKfxNVbOFuYwnAZcHgS6HOH8lgp15HoGHIAVTcZfZrXvcYzJFOMLEJgVn+JHBu6EiNV+xSNXXFg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-eventstream@3.972.10': + resolution: {integrity: sha512-QUqLs7Af1II9X4fCRAu+EGHG3KHyOp4RkuLhRKoA3NuFlh6TL8i+zXBl8w2LUxqm44B/Kom45hgSlwA1SpTsXQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-host-header@3.972.10': + resolution: {integrity: sha512-IJSsIMeVQ8MMCPbuh1AbltkFhLBLXn7aejzfX5YKT/VLDHn++Dcz8886tXckE+wQssyPUhaXrJhdakO2VilRhg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-logger@3.972.10': + resolution: {integrity: sha512-OOuGvvz1Dm20SjZo5oEBePFqxt5nf8AwkNDSyUHvD9/bfNASmstcYxFAHUowy4n6Io7mWUZ04JURZwSBvyQanQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.972.11': + resolution: {integrity: sha512-+zz6f79Kj9V5qFK2P+D8Ehjnw4AhphAlCAsPjUqEcInA9umtSSKMrHbSagEeOIsDNuvVrH98bjRHcyQukTrhaQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.972.37': + resolution: {integrity: sha512-Km7M+i8DrLArVzrid1gfxeGhYHBd3uxvE77g0s5a52zPSVosxzQBnJ0gwWb6NIp/DOk8gsBMhi7V+cpJG0ndTA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-user-agent@3.972.38': + resolution: {integrity: sha512-iz+B29TXcAZsJpwB+AwG/TTGA5l/VnmMZ2UxtiySOZjI6gCdmviXPwdgzcmuazMy16rXoPY4mYCGe7zdNKfx5A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-websocket@3.972.16': + resolution: {integrity: sha512-86+S9oCyRVGzoMRpQhxkArp7kD2K75GPmaNevd9B6EyNhWoNvnCZZ3WbgN4j7ZT+jvtvBCGZvI2XHsWZJ+BRIg==} + engines: {node: '>= 14.0.0'} + + '@aws-sdk/nested-clients@3.997.6': + resolution: {integrity: sha512-WBDnqatJl+kGObpfmfSxqnXeYTu3Me8wx8WCtvoxX3pfWrrTv8I4WTMSSs7PZqcRcVh8WeUKMgGFjMG+52SR1w==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/region-config-resolver@3.972.13': + resolution: {integrity: sha512-CvJ2ZIjK/jVD/lbOpowBVElJyC1YxLTIJ13yM0AEo0t2v7swOzGjSA6lJGH+DwZXQhcjUjoYwc8bVYCX5MDr1A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.996.25': + resolution: {integrity: sha512-+CMIt3e1VzlklAECmG+DtP1sV8iKq25FuA0OKpnJ4KA0kxUtd7CgClY7/RU6VzJBQwbN4EJ9Ue6plvqx1qGadw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1041.0': + resolution: {integrity: sha512-Th7kPI6YPtvJUcdznooXJMy+9rQWjmEF81LxaJssngBzuysK4a/x+l8kjm1zb7nYsUPbndnBdUnwng/3PLvtGw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1045.0': + resolution: {integrity: sha512-/o4qcty0DmQola0DBniRVeBakYY6ALOvKEFo1AtJpTmMn/cJ+Fk3RWGe5ieT/f/eYbHG9k5E7poKge/E+WGv4Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.973.8': + resolution: {integrity: sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-arn-parser@3.972.3': + resolution: {integrity: sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-endpoints@3.996.8': + resolution: {integrity: sha512-oOZHcRDihk5iEe5V25NVWg45b3qEA8OpHWVdU/XQh8Zj4heVPAJqWvMphQnU7LkufmUo10EpvFPZuQMiFLJK3g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-format-url@3.972.10': + resolution: {integrity: sha512-DEKiHNJVtNxdyTeQspzY+15Po/kHm6sF0Cs4HV9Q2+lplB63+DrvdeiSoOSdWEWAoO2RcY1veoXVDz2tWxWCgQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-locate-window@3.965.5': + resolution: {integrity: sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-user-agent-browser@3.972.10': + resolution: {integrity: sha512-FAzqXvfEssGdSIz8ejatan0bOdx1qefBWKF/gWmVBXIP1HkS7v/wjjaqrAGGKvyihrXTXW00/2/1nTJtxpXz7g==} + + '@aws-sdk/util-user-agent-node@3.973.24': + resolution: {integrity: sha512-ZWwlkjcIp7cEL8ZfTpTAPNkwx25p7xol0xlKoWVVf22+nsjwmLcHYtTPjIV1cSpmB/b6DaK4cb1fSkvCXHgRdw==} + engines: {node: '>=20.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.972.22': + resolution: {integrity: sha512-PMYKKtJd70IsSG0yHrdAbxBr+ZWBKLvzFZfD3/urxgf6hXVMzuU5M+3MJ5G67RpOmLBu1fAUN65SbWuKUCOlAA==} + engines: {node: '>=20.0.0'} + + '@aws/lambda-invoke-store@0.2.4': + resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.29.0': resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} @@ -125,6 +363,10 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + '@babel/template@7.28.6': resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} @@ -137,6 +379,18 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@borewit/text-codec@0.2.2': + resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + + '@braintrust/core@0.0.87': + resolution: {integrity: sha512-yKo+2McKBcluVUq+5qoYI7QfGvqZ7c0ftTOmnRSToBR2RqGyHkClnnQZ3+M8Guuk9NEKJu92UMTTaR9AonIvvA==} + + '@braintrust/proxy@0.0.9': + resolution: {integrity: sha512-MIYznqHlb6eduHLg7tJHYUFcku4Wj1rLfyrCf+Uuel8vYowitOdCl8G6nR/NJl/g0xPGCtUOBkZQcJFJkQ2y0g==} + + '@breezystack/lamejs@1.2.7': + resolution: {integrity: sha512-6wc7ck65ctA75Hq7FYHTtTvGnYs6msgdxiSUICQ+A01nVOWg6rqouZB8IdyteRlfpYYiFovkf67dIeOgWIUzTA==} + '@clack/core@1.3.0': resolution: {integrity: sha512-xJPHpAmEQUBrXSLx0gF+q5K/IyihXpsHZcha+jB+tyahsKRK3Dxo4D0coZDewHo12NhiuzC3dTtMPbm53GEAAA==} engines: {node: '>= 20.12.0'} @@ -145,6 +399,24 @@ packages: resolution: {integrity: sha512-GgcWwRCs/xPtaqlMy8qRhPnZf9vlWcWZNHAitnVQ3yk7JmSralSiq5q07yaffYE8SogtDm7zFeKccx1QNVARpw==} engines: {node: '>= 20.12.0'} + '@earendil-works/pi-agent-core@0.74.0': + resolution: {integrity: sha512-6GMR7/wwjEJ1EsXLWEz03QOWin4AMrJ/AZoMpgm5DJ6GHsF6q6GOhQbj5Zip4dow3vo/TmBAVqM+vmGfrjGAFQ==} + engines: {node: '>=20.0.0'} + + '@earendil-works/pi-ai@0.74.0': + resolution: {integrity: sha512-7M7qcrZY/KEkH4wFkX3eqzvmKru4O88wezNKoN0KD2m4aAOmp9tdW2xCmUgSTSWlKB7b2Xw9QtAgrzHtg6t6iw==} + engines: {node: '>=20.0.0'} + hasBin: true + + '@earendil-works/pi-coding-agent@0.74.0': + resolution: {integrity: sha512-Q5GikbB5vRBrsrrf/uvet53rPSQ1sn5I5mO+l7sIobdXYpS04/X2oOc2UHFm90fNdkl3yU+ANTZL0zOtHbnqRw==} + engines: {node: '>=20.6.0'} + hasBin: true + + '@earendil-works/pi-tui@0.74.0': + resolution: {integrity: sha512-1aIfXZp7D/z+1VlZX8BZcs6pgO8rjmil7kwyhctNDsWvce3Yfl8GVgu4eq+I0Mjhr8Cj+ipBiv9CLIzdoyCOIQ==} + engines: {node: '>=20.0.0'} + '@emnapi/core@1.10.0': resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} @@ -193,6 +465,19 @@ packages: resolution: {integrity: sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@google/genai@0.13.0': + resolution: {integrity: sha512-eaEncWt875H7046T04mOpxpHJUM+jLIljEf+5QctRyOeChylE/nhpwm1bZWTRWoOu/t46R9r+PmgsJFhTpE7tQ==} + engines: {node: '>=18.0.0'} + + '@google/genai@1.52.0': + resolution: {integrity: sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.25.2 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + '@humanfs/core@0.19.2': resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} engines: {node: '>=18.18.0'} @@ -213,6 +498,41 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@inquirer/ansi@2.0.5': + resolution: {integrity: sha512-doc2sWgJpbFQ64UflSVd17ibMGDuxO1yKgOgLMwavzESnXjFWJqUeG8saYosqKpHp4kWiM5x1nXvEjbpx90gzw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + + '@inquirer/core@11.1.10': + resolution: {integrity: sha512-a4Q5BXHQAHa9eO202sTaFCHFYVB3x5fauDuThEAdZ9gfn76pSxiKU7wWcEH0N1O0XmQvNfQNU6QXpiRxmYQx+A==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@2.0.5': + resolution: {integrity: sha512-NsSs4kzfm12lNetHwAn3GEuH317IzpwrMCbOuMIVytpjnJ90YYHNwdRgYGuKmVxwuIqSgqk3M5qqQt1cDk0tGQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + + '@inquirer/search@4.1.8': + resolution: {integrity: sha512-fGiHKGD6DyPIYUWxoXnQTeXeyYqSOUrasDMABBmMHUalH/LxkuzY0xVRtimXAt1sUeeyYkVuKQx1bebMuN11Kw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/type@4.0.5': + resolution: {integrity: sha512-aetVUNeKNc/VriqXlw1NRSW0zhMBB0W4bNbWRJgzRl/3d0QNDQFfk0GO5SDdtjMZVg6o8ZKEiadd7SCCzoOn5Q==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -229,18 +549,151 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@jsdevtools/ono@7.1.3': + resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} + + '@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.5': + resolution: {integrity: sha512-D3F+UrU9CR7roJt0zDLp6Oc+4/KlLDIrN4frH+6V90SJNW2KKUec1oCQIPaaDjCqeOsQyX9dyqYbImIQIM45PA==} + engines: {node: '>= 10'} + + '@mistralai/mistralai@2.2.1': + resolution: {integrity: sha512-uKU8CZmL2RzYKmplsU01hii4p3pe4HqJefpWNRWXm1Tcm0Sm4xXfwSLIy4k7ZCPlbETCGcp69E7hZs+WOJ5itQ==} + '@napi-rs/wasm-runtime@1.1.4': resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} peerDependencies: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 + '@nodable/entities@2.1.0': + resolution: {integrity: sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==} + + '@opentelemetry/api@1.9.1': + resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/core@1.30.1': + resolution: {integrity: sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/resources@1.30.1': + resolution: {integrity: sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-metrics@1.30.1': + resolution: {integrity: sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/semantic-conventions@1.28.0': + resolution: {integrity: sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==} + engines: {node: '>=14'} + '@oxc-project/types@0.127.0': resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==} '@oxc-project/types@0.128.0': resolution: {integrity: sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.1': + resolution: {integrity: sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.1': + resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} + '@rolldown/binding-android-arm64@1.0.0-rc.17': resolution: {integrity: sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -437,88 +890,285 @@ packages: '@rolldown/pluginutils@1.0.0-rc.18': resolution: {integrity: sha512-CUY5Mnhe64xQBGZEEXQ5WyZwsc1JU3vAZLIxtrsBt3LO6UOb+C8GunVKqe9sT8NeWb4lqSaoJtp2xo6GxT1MNw==} - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@silvia-odwyer/photon-node@0.3.4': + resolution: {integrity: sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==} - '@tanstack/query-core@5.100.9': - resolution: {integrity: sha512-SJSFw1S8+kQ0+knv/XGfrbocWoAlT7vDKsSImtLx3ZPQmEcR46hkDjLSvynSy25N8Ms4tIEini1FuBd5k7IscQ==} + '@sinclair/typebox@0.34.49': + resolution: {integrity: sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==} - '@tanstack/react-query@5.100.9': - resolution: {integrity: sha512-Oa44XkaI3kCNN6ME0KByU3xT3SEUNOMfZpHxL6+wFoTm+OeUFYHKdeYVe0aOXlRDm/f15sgLwEt2HDorIdW8+A==} - peerDependencies: - react: ^18 || ^19 + '@smithy/config-resolver@4.5.1': + resolution: {integrity: sha512-abXk3LhODsvRHsk0ZS9ztrg/fZatTa9Z/z4pgx65YSLR+rY6kvUG/1IgcDKEUciR8MfdnkT5oPeHJTy/HhzDIQ==} + engines: {node: '>=18.0.0'} - '@tybys/wasm-util@0.10.2': - resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + '@smithy/core@3.24.1': + resolution: {integrity: sha512-3mT7o4qQyUWttYnVK3A0Z/u3Xha3E81tXn32Tz6vjZiUXhBrkEivpw1hBYfh84iFF9CSzkBU9Y1DJ3Q6RQ231g==} + engines: {node: '>=18.0.0'} - '@types/chai@5.2.3': - resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@smithy/credential-provider-imds@4.3.1': + resolution: {integrity: sha512-0S/acwHnqX4WrjXzhdiDRxsG2s9SC0cpPIK9nZ1R6UOHd+j7uL28+4bHu22urbLk2TVw3fkp6na/+fkUt/pLNQ==} + engines: {node: '>=18.0.0'} - '@types/deep-eql@4.0.2': - resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@smithy/eventstream-codec@4.3.1': + resolution: {integrity: sha512-yS8AiJM3Kf7LR+lZyUilUyjdJGksAqxfSC3C9k3d1OCrAvWjpMlsJ+rW9cIslZJM4AtWh2UAqgZUWTtMeMdtDQ==} + engines: {node: '>=18.0.0'} - '@types/esrecurse@4.3.1': - resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + '@smithy/eventstream-serde-browser@4.3.1': + resolution: {integrity: sha512-X7MyI1fu8M84IPKk49kO4kb27Mqp6un9/0o/MsA1ngZ5OxxWKGUxPS3S/AJ9q1cPVTSGmRcbaGNfGUSsflTJkg==} + engines: {node: '>=18.0.0'} - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@smithy/eventstream-serde-config-resolver@4.4.1': + resolution: {integrity: sha512-JZGbSXaBk7JY8VPzsh66ksJ0nTWXbApduFDkA/pEl3aTm2EoAiUZE1Iltp6c+X1bB8kxPQW0mHDfVdYCpWTOzg==} + engines: {node: '>=18.0.0'} - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@smithy/eventstream-serde-node@4.3.1': + resolution: {integrity: sha512-6Cn4xTNVxn9PWTHSbvf8zmcDhQW8lrLE1Xq5CJgmX6wEvdjS2S0KuE79Aiznv/jx51jpFJ98OuWyE+Bt+oG1MQ==} + engines: {node: '>=18.0.0'} - '@types/node@24.12.2': - resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} + '@smithy/fetch-http-handler@5.4.1': + resolution: {integrity: sha512-r7bN6spQ+caZC8AnyvSxkRUb57zt2jhhRw3Z+2Ez8hjq6coIikDBFUUI/+CQ1xx9K6eX1Gx6wUKo4ylU66TIqw==} + engines: {node: '>=18.0.0'} - '@types/react@19.2.14': - resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + '@smithy/hash-node@4.3.1': + resolution: {integrity: sha512-u0/zo11mg7yNneoYgTkH4sXwSmcBpbl49o4UNCtQ7hYsXxynsN25KYHmXzqi7TPk5HQL5klGnpU5koOY0O+9hw==} + engines: {node: '>=18.0.0'} - '@typescript-eslint/eslint-plugin@8.59.2': - resolution: {integrity: sha512-j/bwmkBvHUtPNxzuWe5z6BEk3q54YRyGlBXkSsmfoih7zNrBvl5A9A98anlp/7JbyZcWIJ8KXo/3Tq/DjFLtuQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.59.2 - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' + '@smithy/invalid-dependency@4.3.1': + resolution: {integrity: sha512-cLmwtDoulyZvRepAfyV+3rx5oMvuh51dbE+6En3vGC09j3uVSRt1U4oguNu32ub3soGX0oYtBs8E7S2Q4SxTqg==} + engines: {node: '>=18.0.0'} - '@typescript-eslint/parser@8.59.2': - resolution: {integrity: sha512-plR3pp6D+SSUn1HM7xvSkx12/DhoHInI2YF35KAcVFNZvlC0gtrWqx7Qq1oH2Ssgi0vlFRCTbP+DZc7B9+TtsQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} - '@typescript-eslint/project-service@8.59.2': - resolution: {integrity: sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' + '@smithy/middleware-content-length@4.3.1': + resolution: {integrity: sha512-l4BUIP+wljW/Ar+0/QcGdmElI9lalrywfzNijXMBG34Z510FRzPyrDLx/blNTZOAm0C4Mvx5t/bf760CZo1ajg==} + engines: {node: '>=18.0.0'} - '@typescript-eslint/scope-manager@8.59.2': - resolution: {integrity: sha512-JzfyEpEtOU89CcFSwyNS3mu4MLvLSXqnmX05+aKBDM+TdR5jzcGOEBwxwGNxrEQ7p/z6kK2WyioCGBf2zZBnvg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@smithy/middleware-endpoint@4.5.1': + resolution: {integrity: sha512-qtqu5TS+8Y18ZDkJoiXN5AMW1G4JAg1+xytzpsUvIR5a4EUsgd5HQg12lekEHWpm2TDUmOgg+hBaHK7dvyWdkA==} + engines: {node: '>=18.0.0'} - '@typescript-eslint/tsconfig-utils@8.59.2': - resolution: {integrity: sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' + '@smithy/middleware-retry@4.6.1': + resolution: {integrity: sha512-eTaQhxs0rfUuAkL2MSKrH8DTO7YCeAgrdN0B2/RAeuHmXQ+x52dk5qUBsi/jtcqe5LxItgq5AG5tI6Cp8c0sow==} + engines: {node: '>=18.0.0'} - '@typescript-eslint/type-utils@8.59.2': - resolution: {integrity: sha512-nhqaj1nmTdVVl/BP5omXNRGO38jn5iosis2vbdmupF2txCf8ylWT8lx+JlvMYYVqzGVKtjojUFoQ3JRWK+mfzQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' + '@smithy/middleware-serde@4.3.1': + resolution: {integrity: sha512-t7YtUe076zWVypVmy1rX91oKi2TFJCkpfFpfMhJFpEIRPP0iL9JxjeSyFQ+1bF45JUfDzOzslUJa150WcSrBug==} + engines: {node: '>=18.0.0'} - '@typescript-eslint/types@8.59.2': - resolution: {integrity: sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@smithy/middleware-stack@4.3.1': + resolution: {integrity: sha512-1jKwiKZxCMQNqmp4uVPYA6r+MLGjEtH07gnOUdPgbnjuOIrl/0JY/ICdpQtFgeBsQ/Up01gnSv8GYEL0fb8yvg==} + engines: {node: '>=18.0.0'} - '@typescript-eslint/typescript-estree@8.59.2': - resolution: {integrity: sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' + '@smithy/node-config-provider@4.4.1': + resolution: {integrity: sha512-q7tDJEJXcaSG/8TVpu2f2l9bzxTzDM9geWmltbzsY6Hfh3yiuXXTpLIO8+zwYASPPVFaTJpdKwjSSjdoDoccgw==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.7.1': + resolution: {integrity: sha512-BdEYko85f/ldp68uH8XEyIvo810xFk6eyPH81SRggTOApYHWA+Xu7B2EzLuHbe37WVLaUA7F1fWR3/zBeme2WA==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.3.1': + resolution: {integrity: sha512-3NHoqVBhzpY2b4YBx9AqyKC4C8nnEjl5FyKuxrCjvnjinG0ODj+yg1xX360nNahT6wghYjSw1SooCt3kIdnqIA==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.4.1': + resolution: {integrity: sha512-8irPNCQgYxcSFp1aGcnDNFkTwSA+xPUaFq9V/v1+JXWu8sKr5b3cFmg2kBTkjkvypDmGeNffuNu0x5iqw1NoAw==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.3.1': + resolution: {integrity: sha512-toyi8sXPWDNoVH6yK7sXJ9dm5uxw2tWLCHzPy/t16Fvl62Es4vXQXzlilyNaw+DqFwxSlrFClh0rGLPUF2p9Lg==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.5.1': + resolution: {integrity: sha512-FKoKxVzdFPhyynFI+SPTWrgOP60fZ4l1UwukWYj4eyhpSmEI7MJ6p58hawIIt9bwp+aek9NEm8Zika7E+GEoeg==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.4.1': + resolution: {integrity: sha512-728lZZEWYWubBESrfntNslZQYDKRlJDY4dcDnYbL50+gu35pGPLblu4S0/RH/RDLF6me1M87ECHsHELGL7dA/Q==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.13.1': + resolution: {integrity: sha512-IcznNM8Qd9u1X3oflp12tkzyOB4HbT+sfYWlWiyEysgNzSHoWcHUUsTT4y1jjDjtVuuVVQbYks+g1kVd7u1eGQ==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.14.1': + resolution: {integrity: sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.3.1': + resolution: {integrity: sha512-tuelFlF2PZR/wogFC58NIrPOv+Zna4N1+3kA161/33D1Gbwvl6Nh4WsAsW05ZyPp0O6CMGsdbb0S2b/qVjRMCw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.4.1': + resolution: {integrity: sha512-fTHiwW2xbiRiWzfSk4IGAr3gNZCH4fuRYqt8+IuarsP/YON35576iVdePraZ6yJlFxlCL0eMec3/F7xYqoKzlg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.3.1': + resolution: {integrity: sha512-1scg5t4nV3hV7CZs996/XHb80aDZ5YotH4NcvkW/w/rHj+cSz0aCIzwz8aUNKB4nCDPSHRCbrKoj+TvycYefmw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.3.1': + resolution: {integrity: sha512-VRC8MKVPKrgUYThTA7ughcKMfjW6/X92H0wXGJoda0Apw4O5xbXL0GMLz40DTWlsb5hh2iItk6+XL72uJdxYcw==} + 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-config-provider@4.3.1': + resolution: {integrity: sha512-lw6L5GF5+W19vO6o3fZwRT2cXEG+8b2LH0b9ppjDT6nIxjUgmljEQGninx5XorylwKZZ4XLVABeroJ8oaF9RmQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.4.1': + resolution: {integrity: sha512-1rA7w+LjK1WJClsffC81Z/ZtjFt22QsKhBjUYEnZsGVS2nOTfOENKBzdg4SxhdwFvBCjcbpjscUfXOPwE3UHWQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.3.1': + resolution: {integrity: sha512-1fk1wfQHBenQD5NitVKOFgW0wsISYAFPIXGyStJWAeCtMyRhgHYvtJxBk2rwGWA0L5QX6oM6yeHSLKPFMk59ww==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.5.1': + resolution: {integrity: sha512-yORYzJD5zoGbSDkAACr0dIjDiSEA3X8h8lggDENl1dkKpCG0TQIoItPBqtvuJHzFFjRXumcoH+/09xIuixGyCw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@4.3.1': + resolution: {integrity: sha512-j6dAIaXfj2nsvv/sN9+fi7e/AJxBHgBoIdNjmQjp9jlii72rEniUGQkipnkHMP2XUKHx5q0B1iv0xQEG1AsLBA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-middleware@4.3.1': + resolution: {integrity: sha512-SRRMDcIgVXVhVbxviBaSZbuWuVW3jD08wv4ESV0V2oiw0Mki8TPVQ5IxwD3MvSTPg52QYsRP+JoMw5WdUdeWAg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.4.1': + resolution: {integrity: sha512-qkgWgwn1xw0GoY9Ea/B6FrYSPfHA0zyOtJkokwxZuvucRf2+2lfTut6adi4e4Y7LEAaxsFG7r6i05mtDCxbHKA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.6.1': + resolution: {integrity: sha512-GjZfEft0M0V3n2YM/LGkr5LeLd8gxHUIzW0rUz6VtTtlAq245GxHlJghvoPEjJHKTj255iHFAiA4IsIdK40Ueg==} + 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.3.1': + resolution: {integrity: sha512-FtRrSnriXtOs4+J8/y9SbQ1xmN71hrOsN/YJr5PQQj5nR1l7YNkGS/TEk4gr0WN7gyrUqw8/RFaYVjI18732ZA==} + engines: {node: '>=18.0.0'} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@tanstack/query-core@5.100.9': + resolution: {integrity: sha512-SJSFw1S8+kQ0+knv/XGfrbocWoAlT7vDKsSImtLx3ZPQmEcR46hkDjLSvynSy25N8Ms4tIEini1FuBd5k7IscQ==} + + '@tanstack/react-query@5.100.9': + resolution: {integrity: sha512-Oa44XkaI3kCNN6ME0KByU3xT3SEUNOMfZpHxL6+wFoTm+OeUFYHKdeYVe0aOXlRDm/f15sgLwEt2HDorIdW8+A==} + peerDependencies: + react: ^18 || ^19 + + '@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==} + + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/mime-types@2.1.4': + resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} + + '@types/node-fetch@2.6.13': + resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==} + + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} + + '@types/node@24.12.2': + resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} + + '@types/react@19.2.14': + resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + '@typescript-eslint/eslint-plugin@8.59.2': + resolution: {integrity: sha512-j/bwmkBvHUtPNxzuWe5z6BEk3q54YRyGlBXkSsmfoih7zNrBvl5A9A98anlp/7JbyZcWIJ8KXo/3Tq/DjFLtuQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.59.2 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.59.2': + resolution: {integrity: sha512-plR3pp6D+SSUn1HM7xvSkx12/DhoHInI2YF35KAcVFNZvlC0gtrWqx7Qq1oH2Ssgi0vlFRCTbP+DZc7B9+TtsQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.59.2': + resolution: {integrity: sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/scope-manager@8.59.2': + resolution: {integrity: sha512-JzfyEpEtOU89CcFSwyNS3mu4MLvLSXqnmX05+aKBDM+TdR5jzcGOEBwxwGNxrEQ7p/z6kK2WyioCGBf2zZBnvg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.59.2': + resolution: {integrity: sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/type-utils@8.59.2': + resolution: {integrity: sha512-nhqaj1nmTdVVl/BP5omXNRGO38jn5iosis2vbdmupF2txCf8ylWT8lx+JlvMYYVqzGVKtjojUFoQ3JRWK+mfzQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/types@8.59.2': + resolution: {integrity: sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.59.2': + resolution: {integrity: sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' '@typescript-eslint/utils@8.59.2': resolution: {integrity: sha512-Juw3EinkXqjaffxz6roowvV7GZT/kET5vSKKZT6upl5TXdWkLkYmNPXwDDL2Vkt2DPn0nODIS4egC/0AGxKo/Q==} @@ -560,6 +1210,39 @@ packages: '@vitest/utils@4.1.5': resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==} + '@vue/compiler-core@3.5.34': + resolution: {integrity: sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==} + + '@vue/compiler-dom@3.5.34': + resolution: {integrity: sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==} + + '@vue/compiler-sfc@3.5.34': + resolution: {integrity: sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==} + + '@vue/compiler-ssr@3.5.34': + resolution: {integrity: sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==} + + '@vue/reactivity@3.5.34': + resolution: {integrity: sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==} + + '@vue/runtime-core@3.5.34': + resolution: {integrity: sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==} + + '@vue/runtime-dom@3.5.34': + resolution: {integrity: sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==} + + '@vue/server-renderer@3.5.34': + resolution: {integrity: sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==} + peerDependencies: + vue: 3.5.34 + + '@vue/shared@3.5.34': + resolution: {integrity: sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -570,6 +1253,32 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + ai@2.2.37: + resolution: {integrity: sha512-JIYm5N1muGVqBqWnvkt29FmXhESoO5TcDxw74OE41SsM+uIou6NPDDs0XWb/ABcd1gmp6k5zym64KWMPM2xm0A==} + engines: {node: '>=14.6'} + peerDependencies: + react: ^18.2.0 + solid-js: ^1.7.7 + svelte: ^3.0.0 || ^4.0.0 + vue: ^3.3.4 + peerDependenciesMeta: + react: + optional: true + solid-js: + optional: true + svelte: + optional: true + vue: + optional: true + ajv@6.15.0: resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} @@ -577,14 +1286,32 @@ packages: resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} engines: {node: '>=18'} + 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==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + array-buffer-byte-length@1.0.2: resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} @@ -617,10 +1344,17 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + auto-bind@5.0.1: resolution: {integrity: sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -629,6 +1363,10 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -636,11 +1374,24 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + baseline-browser-mapping@2.10.27: resolution: {integrity: sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA==} engines: {node: '>=6.0.0'} hasBin: true + basic-ftp@5.3.1: + resolution: {integrity: sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==} + 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@1.1.14: resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==} @@ -653,6 +1404,19 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + cache-control-parser@2.2.0: + resolution: {integrity: sha512-Me01OJfiZiyGT42qApiunD9fKiE8WMk9w+zhu1LZlRHuDGW1gvy/IA+GcdJbWXVhZbQkn6NmZKomVaO7BFdl1g==} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -672,6 +1436,10 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + 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} @@ -684,17 +1452,51 @@ packages: resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} engines: {node: ^12.20.0 || ^14.13.1 || >=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 + cli-truncate@6.0.0: resolution: {integrity: sha512-3+YKIUFsohD9MIoOFPFBldjAlnfCmCDcqe6aYGFqlDTRKg80p4wg35L+j83QQ63iOlKRccEkbn8IuM++HsgEjA==} engines: {node: '>=22'} + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@9.0.1: + resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} + engines: {node: '>=20'} + code-excerpt@4.0.0: resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + code-red@1.0.4: + resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} + + 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==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -706,9 +1508,21 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + 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'} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -721,6 +1535,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + date-fns@4.1.0: + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -733,18 +1550,46 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} + engines: {node: '>=0.3.1'} + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -753,9 +1598,25 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + electron-to-chromium@1.5.349: resolution: {integrity: sha512-QsWVGyRuY07Aqb234QytTfwd5d9AJlfNIQ5wIOl1L+PZDzI9d9+Fn0FRale/QYlFxt/bUnB0/nLd1jFPGxGK1A==} + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + environment@1.1.0: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} @@ -810,6 +1671,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + eslint-config-prettier@10.1.8: resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} hasBin: true @@ -854,6 +1720,11 @@ packages: resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esquery@1.7.0: resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} @@ -866,6 +1737,9 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -873,10 +1747,30 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventsource-parser@1.0.0: + resolution: {integrity: sha512-9jgfSCa3dmEme2ES3mPByGXfgZ87VbP97tng1G2nWwWx6bV2nYxm2AWCrbQjXToSe+yYlqaZNtxffR9IeQr95g==} + engines: {node: '>=14.18'} + + eventsource-parser@1.1.2: + resolution: {integrity: sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==} + engines: {node: '>=14.18'} + expect-type@1.3.0: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -895,6 +1789,16 @@ packages: fast-wrap-ansi@0.2.0: resolution: {integrity: sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w==} + fast-xml-builder@1.2.0: + resolution: {integrity: sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==} + + fast-xml-parser@5.7.2: + resolution: {integrity: sha512-P7oW7tLbYnhOLQk/Gv7cZgzgMPP/XN03K02/Jy6Y/NHzyIAIpxuZIM/YqAkfiXFPxA2CTm7NtCijK9EDu09u2w==} + hasBin: true + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -904,10 +1808,18 @@ packages: picomatch: optional: true + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + file-type@21.3.4: + resolution: {integrity: sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==} + engines: {node: '>=20'} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -923,6 +1835,21 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -938,6 +1865,22 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + gaxios@6.7.1: + resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} + engines: {node: '>=14'} + + gaxios@7.1.4: + resolution: {integrity: sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==} + engines: {node: '>=18'} + + gcp-metadata@6.1.1: + resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==} + engines: {node: '>=14'} + + gcp-metadata@8.1.2: + resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} + engines: {node: '>=18'} + generator-function@2.0.1: resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} engines: {node: '>= 0.4'} @@ -946,6 +1889,10 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + 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'} @@ -958,15 +1905,27 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + get-symbol-description@1.1.0: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} + get-uri@6.0.5: + resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} + engines: {node: '>= 14'} + glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - globals@17.6.0: + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} + + globals@17.6.0: resolution: {integrity: sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==} engines: {node: '>=18'} @@ -974,14 +1933,41 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} + google-auth-library@10.6.2: + resolution: {integrity: sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==} + engines: {node: '>=18'} + + google-auth-library@9.15.1: + resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==} + engines: {node: '>=14'} + + google-logging-utils@0.0.2: + resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==} + engines: {node: '>=14'} + + google-logging-utils@1.1.3: + resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==} + engines: {node: '>=14'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -1007,6 +1993,27 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + + hosted-git-info@9.0.3: + resolution: {integrity: sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==} + engines: {node: ^20.17.0 || >=22.9.0} + + 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'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1040,6 +2047,10 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} + ip-address@10.2.0: + resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} + engines: {node: '>= 12'} + is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -1072,6 +2083,11 @@ packages: resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -1080,6 +2096,10 @@ packages: resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-fullwidth-code-point@5.1.0: resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} engines: {node: '>=18'} @@ -1097,6 +2117,15 @@ packages: engines: {node: '>=20'} hasBin: true + is-in-ssh@1.0.0: + resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==} + engines: {node: '>=20'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -1109,6 +2138,9 @@ packages: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} + is-reference@3.0.3: + resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -1121,6 +2153,10 @@ packages: resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} engines: {node: '>= 0.4'} + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + is-string@1.1.1: resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} @@ -1145,6 +2181,10 @@ packages: resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} engines: {node: '>= 0.4'} + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -1155,17 +2195,35 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + jose@5.10.0: + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} hasBin: true + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + json-schema-to-ts@3.1.1: + resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==} + engines: {node: '>=16'} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -1177,13 +2235,26 @@ packages: engines: {node: '>=6'} hasBin: true + jsonwebtoken@9.0.3: + resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} + engines: {node: '>=12', npm: '>=6'} + jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} + 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==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + koffi@2.16.2: + resolution: {integrity: sha512-owU0MRwv6xkrVqCd+33uw6BaYppkTRXbO/rVdJNI2dvZG0gzyRhYwW25eWtc5pauwK8TGh3AbkFONSezdykfSA==} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1262,24 +2333,83 @@ packages: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + + lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + + lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + lru-cache@11.3.6: + resolution: {integrity: sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + marked@15.0.12: + resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==} + engines: {node: '>= 18'} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -1291,21 +2421,65 @@ packages: minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + 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==} + mute-stream@3.0.0: + resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} + engines: {node: ^20.17.0 || >=22.9.0} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nanoid@3.3.12: resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + netmask@2.1.1: + resolution: {integrity: sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==} + engines: {node: '>= 0.4.0'} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + 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-exports-info@1.6.0: resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==} engines: {node: '>= 0.4'} + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + node-pty@1.1.0: + resolution: {integrity: sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg==} + node-releases@2.0.38: resolution: {integrity: sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==} @@ -1340,10 +2514,44 @@ packages: obug@2.1.1: resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + open@11.0.0: + resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==} + engines: {node: '>=20'} + + openai@4.89.0: + resolution: {integrity: sha512-XNI0q2l8/Os6jmojxaID5EhyQjxZgzR2gWcpEjYWK5hGKwE7AcifxEY7UNwFDDHJQXqeiosQ0CJwQN+rvnwdjA==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + + openai@6.26.0: + resolution: {integrity: sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + + openapi3-ts@4.5.0: + resolution: {integrity: sha512-jaL+HgTq2Gj5jRcfdutgRGLosCy/hT8sQf6VOy+P+g36cZOjI1iukdPnijC+4CmeRzg/jEllJUboEic2FhxhtQ==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -1360,6 +2568,30 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + 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'} + + 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==} + patch-console@2.0.0: resolution: {integrity: sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1368,6 +2600,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-expression-matcher@1.5.0: + resolution: {integrity: sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==} + engines: {node: '>=14.0.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -1375,9 +2611,19 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + periscopic@3.1.0: + resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1393,6 +2639,10 @@ packages: resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} engines: {node: ^10 || ^12 || >=14} + powershell-utils@0.1.0: + resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} + engines: {node: '>=20'} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -1405,6 +2655,23 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + + protobufjs@7.5.8: + resolution: {integrity: sha512-dvpCIeLPbXZS/Ete7yLaO7RenOdken2NHKykBXbsaGxZT0UTltcarBciw+A78SRQs9iMAAVpsYA+l8b1hTePIA==} + engines: {node: '>=12.0.0'} + + 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==} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1433,6 +2700,10 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + resolve@2.0.0-next.6: resolution: {integrity: sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==} engines: {node: '>= 0.4'} @@ -1442,6 +2713,14 @@ packages: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + rolldown@1.0.0-rc.17: resolution: {integrity: sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1452,10 +2731,17 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + safe-array-concat@1.1.4: resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} engines: {node: '>=0.4'} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-push-apply@1.0.0: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} @@ -1476,6 +2762,16 @@ packages: engines: {node: '>=10'} hasBin: true + seroval-plugins@1.5.4: + resolution: {integrity: sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + + seroval@1.5.4: + resolution: {integrity: sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==} + engines: {node: '>=10'} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -1522,6 +2818,10 @@ packages: 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'} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -1529,10 +2829,41 @@ packages: resolution: {integrity: sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==} engines: {node: '>=22'} + 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.9: + resolution: {integrity: sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + solid-js@1.9.12: + resolution: {integrity: sha512-QzKaSJq2/iDrWR1As6MHZQ8fQkdOBf8GReYb7L5iKwMGceg7HxDcaOHk0at66tNgn9U2U7dXo8ZZpLIAmGMzgw==} + + solid-swr-store@0.10.7: + resolution: {integrity: sha512-A6d68aJmRP471aWqKKPE2tpgOiR5fH4qXQNfKIec+Vap+MGQm3tvXlT8n0I8UgJSlNAsSAUuw2VTviH2h3Vv5g==} + engines: {node: '>=10'} + peerDependencies: + solid-js: ^1.2 + swr-store: ^0.10 + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sswr@2.0.0: + resolution: {integrity: sha512-mV0kkeBHcjcb0M5NqKtKVg/uTIYNlIIniyDfSGrSfxpEdM9C365jK0z55pl9K0xAkNTJi2OAOVFQpgMPUk+V0w==} + peerDependencies: + svelte: ^4.0.0 + stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -1547,6 +2878,14 @@ packages: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + string-width@8.2.1: resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} engines: {node: '>=20'} @@ -1570,14 +2909,50 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + 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.3.0: + resolution: {integrity: sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==} + + strtok3@10.3.5: + resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} + engines: {node: '>=18'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svelte@4.2.20: + resolution: {integrity: sha512-eeEgGc2DtiUil5ANdtd8vPwt9AgaMdnuUFnPft9F5oMvU/FHu5IHFic+p1dR/UOB7XU2mX2yHW+NcTch4DCh5Q==} + engines: {node: '>=16'} + + swr-store@0.10.6: + resolution: {integrity: sha512-xPjB1hARSiRaNNlUQvWSVrG5SirCjk2TmaUyzzvk69SZQan9hCJqw/5rG9iL7xElHU784GxRPISClq4488/XVw==} + engines: {node: '>=10'} + + swr@2.2.0: + resolution: {integrity: sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 + + swrev@4.0.0: + resolution: {integrity: sha512-LqVcOHSB4cPGgitD1riJ1Hh4vdmITOp+BkmfmXRh4hSF/t7EnS4iD+SOTmq7w5pPm/SiPeto4ADbKS6dHUDWFA==} + + swrv@1.0.4: + resolution: {integrity: sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g==} + peerDependencies: + vue: '>=3.2.26 < 4' + tagged-tag@1.0.0: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} @@ -1586,6 +2961,13 @@ packages: resolution: {integrity: sha512-avMLDQpUI9I5XFrklECw1ZEUPJhqzcwSWsyyI8blhRLT+8N1jLJWLWWYQpB2q2xthq8xDvjZPISVh53T/+CLYQ==} engines: {node: '>=18'} + 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==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -1601,6 +2983,16 @@ packages: resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} + engines: {node: '>=14.16'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + ts-algebra@2.0.0: + resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} + ts-api-utils@2.5.0: resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} @@ -1618,6 +3010,9 @@ packages: resolution: {integrity: sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==} engines: {node: '>=20'} + typebox@1.1.38: + resolution: {integrity: sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -1646,13 +3041,24 @@ packages: engines: {node: '>=14.17'} hasBin: true + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} + unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici@7.25.0: + resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} + engines: {node: '>=20.18.1'} + update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true @@ -1662,6 +3068,20 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + uuid@14.0.0: + resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} + hasBin: true + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + vite@8.0.10: resolution: {integrity: sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1746,6 +3166,28 @@ packages: jsdom: optional: true + vue@3.5.34: + resolution: {integrity: sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -1784,6 +3226,17 @@ packages: resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} engines: {node: '>=20'} + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@7.5.10: resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} engines: {node: '>=8.3.0'} @@ -1808,9 +3261,45 @@ packages: utf-8-validate: optional: true + wsl-utils@0.3.1: + resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} + engines: {node: '>=20'} + + xml-naming@0.1.0: + resolution: {integrity: sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==} + engines: {node: '>=16.0.0'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yargs@18.0.0: + resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -1818,12 +3307,20 @@ packages: yoga-layout@3.2.1: resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + zod-validation-error@4.0.2: resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} engines: {node: '>=18.0.0'} peerDependencies: zod: ^3.25.0 || ^4.0.0 + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.4.3: resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} @@ -1834,47 +3331,502 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 - '@babel/code-frame@7.29.0': + '@ampproject/remapping@2.3.0': dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/compat-data@7.29.3': {} + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 - '@babel/core@7.29.0': + '@anthropic-ai/sdk@0.39.0': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.29.2 - '@babel/parser': 7.29.3 - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 + '@types/node': 18.19.130 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 transitivePeerDependencies: - - supports-color + - encoding - '@babel/generator@7.29.1': + '@anthropic-ai/sdk@0.91.1(zod@4.4.3)': dependencies: - '@babel/parser': 7.29.3 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 + json-schema-to-ts: 3.1.1 + optionalDependencies: + zod: 4.4.3 - '@babel/helper-compilation-targets@7.28.6': + '@apidevtools/json-schema-ref-parser@11.9.3': dependencies: - '@babel/compat-data': 7.29.3 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.2 + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.15 + js-yaml: 4.1.1 + + '@asteasolutions/zod-to-openapi@6.4.0(zod@3.25.76)': + dependencies: + openapi3-ts: 4.5.0 + zod: 3.25.76 + + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.8 + 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.8 + '@aws-sdk/util-locate-window': 3.965.5 + '@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.8 + 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.8 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/client-bedrock-runtime@3.1045.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.8 + '@aws-sdk/credential-provider-node': 3.972.39 + '@aws-sdk/eventstream-handler-node': 3.972.14 + '@aws-sdk/middleware-eventstream': 3.972.10 + '@aws-sdk/middleware-host-header': 3.972.10 + '@aws-sdk/middleware-logger': 3.972.10 + '@aws-sdk/middleware-recursion-detection': 3.972.11 + '@aws-sdk/middleware-user-agent': 3.972.38 + '@aws-sdk/middleware-websocket': 3.972.16 + '@aws-sdk/region-config-resolver': 3.972.13 + '@aws-sdk/token-providers': 3.1045.0 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-endpoints': 3.996.8 + '@aws-sdk/util-user-agent-browser': 3.972.10 + '@aws-sdk/util-user-agent-node': 3.973.24 + '@smithy/config-resolver': 4.5.1 + '@smithy/core': 3.24.1 + '@smithy/eventstream-serde-browser': 4.3.1 + '@smithy/eventstream-serde-config-resolver': 4.4.1 + '@smithy/eventstream-serde-node': 4.3.1 + '@smithy/fetch-http-handler': 5.4.1 + '@smithy/hash-node': 4.3.1 + '@smithy/invalid-dependency': 4.3.1 + '@smithy/middleware-content-length': 4.3.1 + '@smithy/middleware-endpoint': 4.5.1 + '@smithy/middleware-retry': 4.6.1 + '@smithy/middleware-serde': 4.3.1 + '@smithy/middleware-stack': 4.3.1 + '@smithy/node-config-provider': 4.4.1 + '@smithy/node-http-handler': 4.7.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/smithy-client': 4.13.1 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.3.1 + '@smithy/util-base64': 4.4.1 + '@smithy/util-body-length-browser': 4.3.1 + '@smithy/util-body-length-node': 4.3.1 + '@smithy/util-defaults-mode-browser': 4.4.1 + '@smithy/util-defaults-mode-node': 4.3.1 + '@smithy/util-endpoints': 3.5.1 + '@smithy/util-middleware': 4.3.1 + '@smithy/util-retry': 4.4.1 + '@smithy/util-stream': 4.6.1 + '@smithy/util-utf8': 4.3.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.974.8': + dependencies: + '@aws-sdk/types': 3.973.8 + '@aws-sdk/xml-builder': 3.972.22 + '@smithy/core': 3.24.1 + '@smithy/node-config-provider': 4.4.1 + '@smithy/property-provider': 4.3.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/signature-v4': 5.4.1 + '@smithy/smithy-client': 4.13.1 + '@smithy/types': 4.14.1 + '@smithy/util-base64': 4.4.1 + '@smithy/util-middleware': 4.3.1 + '@smithy/util-retry': 4.4.1 + '@smithy/util-utf8': 4.3.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.34': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.3.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.36': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/types': 3.973.8 + '@smithy/fetch-http-handler': 5.4.1 + '@smithy/node-http-handler': 4.7.1 + '@smithy/property-provider': 4.3.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/smithy-client': 4.13.1 + '@smithy/types': 4.14.1 + '@smithy/util-stream': 4.6.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.972.38': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/credential-provider-env': 3.972.34 + '@aws-sdk/credential-provider-http': 3.972.36 + '@aws-sdk/credential-provider-login': 3.972.38 + '@aws-sdk/credential-provider-process': 3.972.34 + '@aws-sdk/credential-provider-sso': 3.972.38 + '@aws-sdk/credential-provider-web-identity': 3.972.38 + '@aws-sdk/nested-clients': 3.997.6 + '@aws-sdk/types': 3.973.8 + '@smithy/credential-provider-imds': 4.3.1 + '@smithy/property-provider': 4.3.1 + '@smithy/shared-ini-file-loader': 4.5.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-login@3.972.38': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/nested-clients': 3.997.6 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.3.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/shared-ini-file-loader': 4.5.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.972.39': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.34 + '@aws-sdk/credential-provider-http': 3.972.36 + '@aws-sdk/credential-provider-ini': 3.972.38 + '@aws-sdk/credential-provider-process': 3.972.34 + '@aws-sdk/credential-provider-sso': 3.972.38 + '@aws-sdk/credential-provider-web-identity': 3.972.38 + '@aws-sdk/types': 3.973.8 + '@smithy/credential-provider-imds': 4.3.1 + '@smithy/property-provider': 4.3.1 + '@smithy/shared-ini-file-loader': 4.5.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.972.34': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.3.1 + '@smithy/shared-ini-file-loader': 4.5.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.972.38': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/nested-clients': 3.997.6 + '@aws-sdk/token-providers': 3.1041.0 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.3.1 + '@smithy/shared-ini-file-loader': 4.5.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.972.38': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/nested-clients': 3.997.6 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.3.1 + '@smithy/shared-ini-file-loader': 4.5.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/eventstream-handler-node@3.972.14': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/eventstream-codec': 4.3.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-eventstream@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/protocol-http': 5.4.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-host-header@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/protocol-http': 5.4.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.972.11': + dependencies: + '@aws-sdk/types': 3.973.8 + '@aws/lambda-invoke-store': 0.2.4 + '@smithy/protocol-http': 5.4.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.972.37': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-arn-parser': 3.972.3 + '@smithy/core': 3.24.1 + '@smithy/node-config-provider': 4.4.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/signature-v4': 5.4.1 + '@smithy/smithy-client': 4.13.1 + '@smithy/types': 4.14.1 + '@smithy/util-config-provider': 4.3.1 + '@smithy/util-middleware': 4.3.1 + '@smithy/util-stream': 4.6.1 + '@smithy/util-utf8': 4.3.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.972.38': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-endpoints': 3.996.8 + '@smithy/core': 3.24.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/types': 4.14.1 + '@smithy/util-retry': 4.4.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-websocket@3.972.16': + dependencies: + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-format-url': 3.972.10 + '@smithy/eventstream-codec': 4.3.1 + '@smithy/eventstream-serde-browser': 4.3.1 + '@smithy/fetch-http-handler': 5.4.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/signature-v4': 5.4.1 + '@smithy/types': 4.14.1 + '@smithy/util-base64': 4.4.1 + '@smithy/util-hex-encoding': 4.3.1 + '@smithy/util-utf8': 4.3.1 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.997.6': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.8 + '@aws-sdk/middleware-host-header': 3.972.10 + '@aws-sdk/middleware-logger': 3.972.10 + '@aws-sdk/middleware-recursion-detection': 3.972.11 + '@aws-sdk/middleware-user-agent': 3.972.38 + '@aws-sdk/region-config-resolver': 3.972.13 + '@aws-sdk/signature-v4-multi-region': 3.996.25 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-endpoints': 3.996.8 + '@aws-sdk/util-user-agent-browser': 3.972.10 + '@aws-sdk/util-user-agent-node': 3.973.24 + '@smithy/config-resolver': 4.5.1 + '@smithy/core': 3.24.1 + '@smithy/fetch-http-handler': 5.4.1 + '@smithy/hash-node': 4.3.1 + '@smithy/invalid-dependency': 4.3.1 + '@smithy/middleware-content-length': 4.3.1 + '@smithy/middleware-endpoint': 4.5.1 + '@smithy/middleware-retry': 4.6.1 + '@smithy/middleware-serde': 4.3.1 + '@smithy/middleware-stack': 4.3.1 + '@smithy/node-config-provider': 4.4.1 + '@smithy/node-http-handler': 4.7.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/smithy-client': 4.13.1 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.3.1 + '@smithy/util-base64': 4.4.1 + '@smithy/util-body-length-browser': 4.3.1 + '@smithy/util-body-length-node': 4.3.1 + '@smithy/util-defaults-mode-browser': 4.4.1 + '@smithy/util-defaults-mode-node': 4.3.1 + '@smithy/util-endpoints': 3.5.1 + '@smithy/util-middleware': 4.3.1 + '@smithy/util-retry': 4.4.1 + '@smithy/util-utf8': 4.3.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.972.13': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/config-resolver': 4.5.1 + '@smithy/node-config-provider': 4.4.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.996.25': + dependencies: + '@aws-sdk/middleware-sdk-s3': 3.972.37 + '@aws-sdk/types': 3.973.8 + '@smithy/protocol-http': 5.4.1 + '@smithy/signature-v4': 5.4.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1041.0': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/nested-clients': 3.997.6 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.3.1 + '@smithy/shared-ini-file-loader': 4.5.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/token-providers@3.1045.0': + dependencies: + '@aws-sdk/core': 3.974.8 + '@aws-sdk/nested-clients': 3.997.6 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.3.1 + '@smithy/shared-ini-file-loader': 4.5.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.973.8': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/util-arn-parser@3.972.3': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.996.8': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.3.1 + '@smithy/util-endpoints': 3.5.1 + tslib: 2.8.1 + + '@aws-sdk/util-format-url@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/querystring-builder': 4.3.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.965.5': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 + bowser: 2.14.1 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.973.24': + dependencies: + '@aws-sdk/middleware-user-agent': 3.972.38 + '@aws-sdk/types': 3.973.8 + '@smithy/node-config-provider': 4.4.1 + '@smithy/types': 4.14.1 + '@smithy/util-config-provider': 4.3.1 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.972.22': + dependencies: + '@nodable/entities': 2.1.0 + '@smithy/types': 4.14.1 + fast-xml-parser: 5.7.2 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.2.4': {} + + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.3': {} + + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.29.2 + '@babel/parser': 7.29.3 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.29.3 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.2 lru-cache: 5.1.1 semver: 6.3.1 @@ -1911,6 +3863,8 @@ snapshots: dependencies: '@babel/types': 7.29.0 + '@babel/runtime@7.29.2': {} + '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 @@ -1934,6 +3888,50 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@borewit/text-codec@0.2.2': {} + + '@braintrust/core@0.0.87': + dependencies: + '@asteasolutions/zod-to-openapi': 6.4.0(zod@3.25.76) + uuid: 9.0.1 + zod: 3.25.76 + + '@braintrust/proxy@0.0.9(react@19.2.5)(solid-js@1.9.12)(svelte@4.2.20)(vue@3.5.34(typescript@6.0.3))(ws@8.20.0)': + dependencies: + '@anthropic-ai/sdk': 0.39.0 + '@apidevtools/json-schema-ref-parser': 11.9.3 + '@aws-sdk/client-bedrock-runtime': 3.1045.0 + '@braintrust/core': 0.0.87 + '@breezystack/lamejs': 1.2.7 + '@google/genai': 0.13.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 1.30.1(@opentelemetry/api@1.9.1) + ai: 2.2.37(react@19.2.5)(solid-js@1.9.12)(svelte@4.2.20)(vue@3.5.34(typescript@6.0.3)) + cache-control-parser: 2.2.0 + content-disposition: 0.5.4 + date-fns: 4.1.0 + eventsource-parser: 1.1.2 + jose: 5.10.0 + jsonwebtoken: 9.0.3 + openai: 4.89.0(ws@8.20.0)(zod@3.25.76) + uuid: 9.0.1 + zod: 3.25.76 + transitivePeerDependencies: + - aws-crt + - bufferutil + - encoding + - react + - solid-js + - supports-color + - svelte + - utf-8-validate + - vue + - ws + + '@breezystack/lamejs@1.2.7': {} + '@clack/core@1.3.0': dependencies: fast-wrap-ansi: 0.2.0 @@ -1946,6 +3944,85 @@ snapshots: fast-wrap-ansi: 0.2.0 sisteransi: 1.0.5 + '@earendil-works/pi-agent-core@0.74.0(ws@8.20.0)(zod@4.4.3)': + dependencies: + '@earendil-works/pi-ai': 0.74.0(ws@8.20.0)(zod@4.4.3) + typebox: 1.1.38 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@earendil-works/pi-ai@0.74.0(ws@8.20.0)(zod@4.4.3)': + dependencies: + '@anthropic-ai/sdk': 0.91.1(zod@4.4.3) + '@aws-sdk/client-bedrock-runtime': 3.1045.0 + '@google/genai': 1.52.0 + '@mistralai/mistralai': 2.2.1 + chalk: 5.6.2 + openai: 6.26.0(ws@8.20.0)(zod@4.4.3) + partial-json: 0.1.7 + proxy-agent: 6.5.0 + typebox: 1.1.38 + undici: 7.25.0 + zod-to-json-schema: 3.25.2(zod@4.4.3) + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@earendil-works/pi-coding-agent@0.74.0(ws@8.20.0)(zod@4.4.3)': + dependencies: + '@earendil-works/pi-agent-core': 0.74.0(ws@8.20.0)(zod@4.4.3) + '@earendil-works/pi-ai': 0.74.0(ws@8.20.0)(zod@4.4.3) + '@earendil-works/pi-tui': 0.74.0 + '@silvia-odwyer/photon-node': 0.3.4 + chalk: 5.6.2 + cli-highlight: 2.1.11 + diff: 8.0.4 + extract-zip: 2.0.1 + file-type: 21.3.4 + glob: 13.0.6 + hosted-git-info: 9.0.3 + ignore: 7.0.5 + jiti: 2.7.0 + marked: 15.0.12 + minimatch: 10.2.5 + proper-lockfile: 4.1.2 + strip-ansi: 7.2.0 + typebox: 1.1.38 + undici: 7.25.0 + uuid: 14.0.0 + yaml: 2.9.0 + optionalDependencies: + '@mariozechner/clipboard': 0.3.5 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@earendil-works/pi-tui@0.74.0': + 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 + optionalDependencies: + koffi: 2.16.2 + '@emnapi/core@1.10.0': dependencies: '@emnapi/wasi-threads': 1.2.1 @@ -1962,9 +4039,9 @@ snapshots: tslib: 2.8.1 optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.3.0)': + '@eslint-community/eslint-utils@4.9.1(eslint@10.3.0(jiti@2.7.0))': dependencies: - eslint: 10.3.0 + eslint: 10.3.0(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -1985,9 +4062,9 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/js@10.0.1(eslint@10.3.0)': + '@eslint/js@10.0.1(eslint@10.3.0(jiti@2.7.0))': optionalDependencies: - eslint: 10.3.0 + eslint: 10.3.0(jiti@2.7.0) '@eslint/object-schema@3.0.5': {} @@ -1996,6 +4073,29 @@ snapshots: '@eslint/core': 1.2.1 levn: 0.4.1 + '@google/genai@0.13.0': + dependencies: + google-auth-library: 9.15.1 + ws: 8.20.0 + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + + '@google/genai@1.52.0': + dependencies: + google-auth-library: 10.6.2 + p-retry: 4.6.2 + protobufjs: 7.5.8 + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + '@humanfs/core@0.19.2': dependencies: '@humanfs/types': 0.15.0 @@ -2012,6 +4112,34 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@inquirer/ansi@2.0.5': {} + + '@inquirer/core@11.1.10(@types/node@24.12.2)': + dependencies: + '@inquirer/ansi': 2.0.5 + '@inquirer/figures': 2.0.5 + '@inquirer/type': 4.0.5(@types/node@24.12.2) + cli-width: 4.1.0 + fast-wrap-ansi: 0.2.0 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + optionalDependencies: + '@types/node': 24.12.2 + + '@inquirer/figures@2.0.5': {} + + '@inquirer/search@4.1.8(@types/node@24.12.2)': + dependencies: + '@inquirer/core': 11.1.10(@types/node@24.12.2) + '@inquirer/figures': 2.0.5 + '@inquirer/type': 4.0.5(@types/node@24.12.2) + optionalDependencies: + '@types/node': 24.12.2 + + '@inquirer/type@4.0.5(@types/node@24.12.2)': + optionalDependencies: + '@types/node': 24.12.2 + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2031,6 +4159,61 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@jsdevtools/ono@7.1.3': {} + + '@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.5': + 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 + optional: true + + '@mistralai/mistralai@2.2.1': + dependencies: + ws: 8.20.0 + zod: 4.4.3 + zod-to-json-schema: 3.25.2(zod@4.4.3) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: '@emnapi/core': 1.10.0 @@ -2038,10 +4221,56 @@ snapshots: '@tybys/wasm-util': 0.10.2 optional: true + '@nodable/entities@2.1.0': {} + + '@opentelemetry/api@1.9.1': {} + + '@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.28.0 + + '@opentelemetry/resources@1.30.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.28.0 + + '@opentelemetry/sdk-metrics@1.30.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/semantic-conventions@1.28.0': {} + '@oxc-project/types@0.127.0': {} '@oxc-project/types@0.128.0': {} + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.5': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.1 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.1': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.1': {} + '@rolldown/binding-android-arm64@1.0.0-rc.17': optional: true @@ -2096,53 +4325,261 @@ snapshots: '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.18': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': - optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.18': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.18': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.18': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.18': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.18': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.18': + optional: true + + '@rolldown/pluginutils@1.0.0-rc.17': {} + + '@rolldown/pluginutils@1.0.0-rc.18': {} + + '@silvia-odwyer/photon-node@0.3.4': {} + + '@sinclair/typebox@0.34.49': {} + + '@smithy/config-resolver@4.5.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/core@3.24.1': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/eventstream-codec@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.4.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.4.1': + dependencies: + '@smithy/core': 3.24.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/hash-node@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.5.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.6.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.4.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.7.1': + dependencies: + '@smithy/core': 3.24.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/property-provider@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/protocol-http@5.4.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/shared-ini-file-loader@4.5.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/signature-v4@5.4.1': + dependencies: + '@smithy/core': 3.24.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/smithy-client@4.13.1': + dependencies: + '@smithy/core': 3.24.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/types@4.14.1': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.18': - optional: true + '@smithy/util-base64@4.4.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': - optional: true + '@smithy/util-body-length-browser@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/binding-linux-x64-musl@1.0.0-rc.18': - optional: true + '@smithy/util-body-length-node@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': - optional: true + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 - '@rolldown/binding-openharmony-arm64@1.0.0-rc.18': - optional: true + '@smithy/util-config-provider@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': + '@smithy/util-defaults-mode-browser@4.4.1': dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) - optional: true + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/binding-wasm32-wasi@1.0.0-rc.18': + '@smithy/util-defaults-mode-node@4.3.1': dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) - optional: true + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': - optional: true + '@smithy/util-endpoints@3.5.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.18': - optional: true + '@smithy/util-hex-encoding@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': - optional: true + '@smithy/util-middleware@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.18': - optional: true + '@smithy/util-retry@4.4.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/pluginutils@1.0.0-rc.17': {} + '@smithy/util-stream@4.6.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 - '@rolldown/pluginutils@1.0.0-rc.18': {} + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 '@standard-schema/spec@1.1.0': {} @@ -2153,6 +4590,17 @@ snapshots: '@tanstack/query-core': 5.100.9 react: 19.2.5 + '@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': {} + '@tybys/wasm-util@0.10.2': dependencies: tslib: 2.8.1 @@ -2171,6 +4619,17 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/mime-types@2.1.4': {} + + '@types/node-fetch@2.6.13': + dependencies: + '@types/node': 24.12.2 + form-data: 4.0.5 + + '@types/node@18.19.130': + dependencies: + undici-types: 5.26.5 + '@types/node@24.12.2': dependencies: undici-types: 7.16.0 @@ -2179,15 +4638,28 @@ snapshots: dependencies: csstype: 3.2.3 - '@typescript-eslint/eslint-plugin@8.59.2(@typescript-eslint/parser@8.59.2(eslint@10.3.0)(typescript@6.0.3))(eslint@10.3.0)(typescript@6.0.3)': + '@types/retry@0.12.0': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 24.12.2 + optional: true + + '@typescript-eslint/eslint-plugin@8.59.2(@typescript-eslint/parser@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.59.2(eslint@10.3.0)(typescript@6.0.3) + '@typescript-eslint/parser': 8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) '@typescript-eslint/scope-manager': 8.59.2 - '@typescript-eslint/type-utils': 8.59.2(eslint@10.3.0)(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.2(eslint@10.3.0)(typescript@6.0.3) + '@typescript-eslint/type-utils': 8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) '@typescript-eslint/visitor-keys': 8.59.2 - eslint: 10.3.0 + eslint: 10.3.0(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -2195,14 +4667,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.59.2(eslint@10.3.0)(typescript@6.0.3)': + '@typescript-eslint/parser@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@typescript-eslint/scope-manager': 8.59.2 '@typescript-eslint/types': 8.59.2 '@typescript-eslint/typescript-estree': 8.59.2(typescript@6.0.3) '@typescript-eslint/visitor-keys': 8.59.2 debug: 4.4.3 - eslint: 10.3.0 + eslint: 10.3.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color @@ -2225,13 +4697,13 @@ snapshots: dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.59.2(eslint@10.3.0)(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@typescript-eslint/types': 8.59.2 '@typescript-eslint/typescript-estree': 8.59.2(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.2(eslint@10.3.0)(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) debug: 4.4.3 - eslint: 10.3.0 + eslint: 10.3.0(jiti@2.7.0) ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: @@ -2254,13 +4726,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.59.2(eslint@10.3.0)(typescript@6.0.3)': + '@typescript-eslint/utils@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.7.0)) '@typescript-eslint/scope-manager': 8.59.2 '@typescript-eslint/types': 8.59.2 '@typescript-eslint/typescript-estree': 8.59.2(typescript@6.0.3) - eslint: 10.3.0 + eslint: 10.3.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color @@ -2279,13 +4751,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.5(vite@8.0.10(@types/node@24.12.2))': + '@vitest/mocker@4.1.5(vite@8.0.10(@types/node@24.12.2)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.5 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.10(@types/node@24.12.2) + vite: 8.0.10(@types/node@24.12.2)(jiti@2.7.0)(yaml@2.9.0) '@vitest/pretty-format@4.1.5': dependencies: @@ -2311,12 +4783,91 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 + '@vue/compiler-core@3.5.34': + dependencies: + '@babel/parser': 7.29.3 + '@vue/shared': 3.5.34 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.34': + dependencies: + '@vue/compiler-core': 3.5.34 + '@vue/shared': 3.5.34 + + '@vue/compiler-sfc@3.5.34': + dependencies: + '@babel/parser': 7.29.3 + '@vue/compiler-core': 3.5.34 + '@vue/compiler-dom': 3.5.34 + '@vue/compiler-ssr': 3.5.34 + '@vue/shared': 3.5.34 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.14 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.34': + dependencies: + '@vue/compiler-dom': 3.5.34 + '@vue/shared': 3.5.34 + + '@vue/reactivity@3.5.34': + dependencies: + '@vue/shared': 3.5.34 + + '@vue/runtime-core@3.5.34': + dependencies: + '@vue/reactivity': 3.5.34 + '@vue/shared': 3.5.34 + + '@vue/runtime-dom@3.5.34': + dependencies: + '@vue/reactivity': 3.5.34 + '@vue/runtime-core': 3.5.34 + '@vue/shared': 3.5.34 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.34(vue@3.5.34(typescript@6.0.3))': + dependencies: + '@vue/compiler-ssr': 3.5.34 + '@vue/shared': 3.5.34 + vue: 3.5.34(typescript@6.0.3) + + '@vue/shared@3.5.34': {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 acorn@8.16.0: {} + agent-base@7.1.4: {} + + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + ai@2.2.37(react@19.2.5)(solid-js@1.9.12)(svelte@4.2.20)(vue@3.5.34(typescript@6.0.3)): + dependencies: + eventsource-parser: 1.0.0 + nanoid: 3.3.6 + solid-swr-store: 0.10.7(solid-js@1.9.12)(swr-store@0.10.6) + sswr: 2.0.0(svelte@4.2.20) + swr: 2.2.0(react@19.2.5) + swr-store: 0.10.6 + swrv: 1.0.4(vue@3.5.34(typescript@6.0.3)) + optionalDependencies: + react: 19.2.5 + solid-js: 1.9.12 + svelte: 4.2.20 + vue: 3.5.34(typescript@6.0.3) + ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 @@ -2328,10 +4879,22 @@ snapshots: dependencies: environment: 1.1.0 + 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: {} + + argparse@2.0.1: {} + + aria-query@5.3.2: {} + array-buffer-byte-length@1.0.2: dependencies: call-bound: 1.0.4 @@ -2391,20 +4954,36 @@ snapshots: assertion-error@2.0.1: {} + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + async-function@1.0.0: {} + asynckit@0.4.0: {} + auto-bind@5.0.1: {} available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 + axobject-query@4.1.0: {} + balanced-match@1.0.2: {} balanced-match@4.0.4: {} + base64-js@1.5.1: {} + baseline-browser-mapping@2.10.27: {} + basic-ftp@5.3.1: {} + + bignumber.js@9.3.1: {} + + bowser@2.14.1: {} + brace-expansion@1.1.14: dependencies: balanced-match: 1.0.2 @@ -2422,6 +5001,16 @@ snapshots: node-releases: 2.0.38 update-browserslist-db: 1.2.3(browserslist@4.28.2) + buffer-crc32@0.2.13: {} + + buffer-equal-constant-time@1.0.1: {} + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + + cache-control-parser@2.2.0: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -2443,6 +5032,11 @@ snapshots: chai@6.2.2: {} + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + chalk@5.6.2: {} cli-boxes@4.0.1: {} @@ -2451,17 +5045,62 @@ snapshots: dependencies: restore-cursor: 4.0.0 + 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 + cli-truncate@6.0.0: dependencies: slice-ansi: 9.0.0 string-width: 8.2.1 + cli-width@4.1.0: {} + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cliui@9.0.1: + dependencies: + string-width: 7.2.0 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 + code-excerpt@4.0.0: dependencies: convert-to-spaces: 2.0.1 + code-red@1.0.4: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@types/estree': 1.0.8 + acorn: 8.16.0 + estree-walker: 3.0.3 + periscopic: 3.1.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + concat-map@0.0.1: {} + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + convert-source-map@2.0.0: {} convert-to-spaces@2.0.1: {} @@ -2472,8 +5111,17 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.1 + csstype@3.2.3: {} + data-uri-to-buffer@4.0.1: {} + + data-uri-to-buffer@6.0.2: {} + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -2492,26 +5140,49 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + date-fns@4.1.0: {} + debug@4.4.3: dependencies: ms: 2.1.3 deep-is@0.1.4: {} + default-browser-id@5.0.1: {} + + default-browser@5.5.0: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + define-data-property@1.1.4: dependencies: es-define-property: 1.0.1 es-errors: 1.3.0 gopd: 1.2.0 + define-lazy-prop@3.0.0: {} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 has-property-descriptors: 1.0.2 object-keys: 1.1.1 + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + + delayed-stream@1.0.0: {} + + dequal@2.0.3: {} + detect-libc@2.1.2: {} + diff@8.0.4: {} + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -2522,8 +5193,22 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + electron-to-chromium@1.5.349: {} + emoji-regex@10.6.0: {} + + emoji-regex@8.0.0: {} + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + entities@7.0.1: {} + environment@1.1.0: {} es-abstract@1.24.2: @@ -2637,22 +5322,30 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.3.0): + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-config-prettier@10.1.8(eslint@10.3.0(jiti@2.7.0)): dependencies: - eslint: 10.3.0 + eslint: 10.3.0(jiti@2.7.0) - eslint-plugin-react-hooks@7.1.1(eslint@10.3.0): + eslint-plugin-react-hooks@7.1.1(eslint@10.3.0(jiti@2.7.0)): dependencies: '@babel/core': 7.29.0 '@babel/parser': 7.29.3 - eslint: 10.3.0 + eslint: 10.3.0(jiti@2.7.0) hermes-parser: 0.25.1 zod: 4.4.3 zod-validation-error: 4.0.2(zod@4.4.3) transitivePeerDependencies: - supports-color - eslint-plugin-react@7.37.5(eslint@10.3.0): + eslint-plugin-react@7.37.5(eslint@10.3.0(jiti@2.7.0)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -2660,7 +5353,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.3.2 - eslint: 10.3.0 + eslint: 10.3.0(jiti@2.7.0) estraverse: 5.3.0 hasown: 2.0.3 jsx-ast-utils: 3.3.5 @@ -2685,9 +5378,9 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.3.0: + eslint@10.3.0(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.23.5 '@eslint/config-helpers': 0.5.5 @@ -2717,6 +5410,8 @@ snapshots: minimatch: 10.2.5 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.7.0 transitivePeerDependencies: - supports-color @@ -2726,6 +5421,8 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.16.0) eslint-visitor-keys: 5.0.1 + esprima@4.0.1: {} + esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -2736,14 +5433,34 @@ snapshots: estraverse@5.3.0: {} + estree-walker@2.0.2: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.8 esutils@2.0.3: {} + event-target-shim@5.0.1: {} + + eventsource-parser@1.0.0: {} + + eventsource-parser@1.1.2: {} + expect-type@1.3.0: {} + extend@3.0.2: {} + + extract-zip@2.0.1: + dependencies: + debug: 4.4.3 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + fast-deep-equal@3.1.3: {} fast-json-stable-stringify@2.1.0: {} @@ -2760,14 +5477,44 @@ snapshots: dependencies: fast-string-width: 3.0.2 + fast-xml-builder@1.2.0: + dependencies: + path-expression-matcher: 1.5.0 + xml-naming: 0.1.0 + + fast-xml-parser@5.7.2: + dependencies: + '@nodable/entities': 2.1.0 + fast-xml-builder: 1.2.0 + path-expression-matcher: 1.5.0 + strnum: 2.3.0 + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: picomatch: 4.0.4 + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 + file-type@21.3.4: + dependencies: + '@tokenizer/inflate': 0.4.1 + strtok3: 10.3.5 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -2784,6 +5531,25 @@ snapshots: dependencies: is-callable: 1.2.7 + form-data-encoder@1.7.2: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.3 + mime-types: 2.1.35 + + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + fsevents@2.3.3: optional: true @@ -2800,10 +5566,48 @@ snapshots: functions-have-names@1.2.3: {} + gaxios@6.7.1: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + is-stream: 2.0.1 + node-fetch: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + gaxios@7.1.4: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + node-fetch: 3.3.2 + transitivePeerDependencies: + - supports-color + + gcp-metadata@6.1.1: + dependencies: + gaxios: 6.7.1 + google-logging-utils: 0.0.2 + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + gcp-metadata@8.1.2: + dependencies: + gaxios: 7.1.4 + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + generator-function@2.0.1: {} gensync@1.0.0-beta.2: {} + get-caller-file@2.0.5: {} + get-east-asian-width@1.5.0: {} get-intrinsic@1.3.0: @@ -2824,27 +5628,84 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-stream@5.2.0: + dependencies: + pump: 3.0.4 + get-symbol-description@1.1.0: dependencies: call-bound: 1.0.4 es-errors: 1.3.0 get-intrinsic: 1.3.0 + get-uri@6.0.5: + dependencies: + basic-ftp: 5.3.1 + data-uri-to-buffer: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 + glob@13.0.6: + dependencies: + minimatch: 10.2.5 + minipass: 7.1.3 + path-scurry: 2.0.2 + globals@17.6.0: {} - globalthis@1.0.4: + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + google-auth-library@10.6.2: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.1.4 + gcp-metadata: 8.1.2 + google-logging-utils: 1.1.3 + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + + google-auth-library@9.15.1: dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.7.1 + gcp-metadata: 6.1.1 + gtoken: 7.1.0 + jws: 4.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + google-logging-utils@0.0.2: {} + + google-logging-utils@1.1.3: {} gopd@1.2.0: {} + graceful-fs@4.2.11: {} + + gtoken@7.1.0: + dependencies: + gaxios: 6.7.1 + jws: 4.0.1 + transitivePeerDependencies: + - encoding + - supports-color + has-bigints@1.1.0: {} + has-flag@4.0.0: {} + has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.1 @@ -2869,6 +5730,32 @@ snapshots: dependencies: hermes-estree: 0.25.1 + highlight.js@10.7.3: {} + + hosted-git-info@9.0.3: + dependencies: + lru-cache: 11.3.6 + + 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 + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + ieee754@1.2.1: {} + ignore@5.3.2: {} ignore@7.0.5: {} @@ -2918,6 +5805,8 @@ snapshots: hasown: 2.0.3 side-channel: 1.1.0 + ip-address@10.2.0: {} + is-array-buffer@3.0.5: dependencies: call-bind: 1.0.9 @@ -2958,12 +5847,16 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-docker@3.0.0: {} + is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: dependencies: call-bound: 1.0.4 + is-fullwidth-code-point@3.0.0: {} + is-fullwidth-code-point@5.1.0: dependencies: get-east-asian-width: 1.5.0 @@ -2982,6 +5875,12 @@ snapshots: is-in-ci@2.0.0: {} + is-in-ssh@1.0.0: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + is-map@2.0.3: {} is-negative-zero@2.0.3: {} @@ -2991,6 +5890,10 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-reference@3.0.3: + dependencies: + '@types/estree': 1.0.8 + is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -3004,6 +5907,8 @@ snapshots: dependencies: call-bound: 1.0.4 + is-stream@2.0.1: {} + is-string@1.1.1: dependencies: call-bound: 1.0.4 @@ -3030,6 +5935,10 @@ snapshots: call-bound: 1.0.4 get-intrinsic: 1.3.0 + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + isarray@2.0.5: {} isexe@2.0.0: {} @@ -3043,18 +5952,48 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 + jiti@2.7.0: {} + + jose@5.10.0: {} + js-tokens@4.0.0: {} + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + jsesc@3.1.0: {} + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + json-buffer@3.0.1: {} + json-schema-to-ts@3.1.1: + dependencies: + '@babel/runtime': 7.29.2 + ts-algebra: 2.0.0 + json-schema-traverse@0.4.1: {} json-stable-stringify-without-jsonify@1.0.1: {} json5@2.2.3: {} + jsonwebtoken@9.0.3: + dependencies: + jws: 4.0.1 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.7.4 + jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.9 @@ -3062,10 +6001,24 @@ snapshots: object.assign: 4.1.7 object.values: 1.2.1 + 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 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 + koffi@2.16.2: + optional: true + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -3120,24 +6073,62 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 + locate-character@3.0.0: {} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 + lodash.includes@4.3.0: {} + + lodash.isboolean@3.0.3: {} + + lodash.isinteger@4.0.4: {} + + lodash.isnumber@3.0.3: {} + + lodash.isplainobject@4.0.6: {} + + lodash.isstring@4.0.1: {} + + lodash.once@4.1.1: {} + + long@5.3.2: {} + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 + lru-cache@11.3.6: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 + lru-cache@7.18.3: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + marked@15.0.12: {} + math-intrinsics@1.1.0: {} + mdn-data@2.0.30: {} + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + mimic-fn@2.1.0: {} minimatch@10.2.5: @@ -3148,12 +6139,30 @@ snapshots: dependencies: brace-expansion: 1.1.14 + minipass@7.1.3: {} + ms@2.1.3: {} + mute-stream@3.0.0: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + nanoid@3.3.12: {} + nanoid@3.3.6: {} + natural-compare@1.4.0: {} + netmask@2.1.1: {} + + node-addon-api@7.1.1: {} + + node-domexception@1.0.0: {} + node-exports-info@1.6.0: dependencies: array.prototype.flatmap: 1.3.3 @@ -3161,6 +6170,20 @@ snapshots: object.entries: 1.1.9 semver: 6.3.1 + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.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 + + node-pty@1.1.0: + dependencies: + node-addon-api: 7.1.1 + node-releases@2.0.38: {} object-assign@4.1.1: {} @@ -3201,10 +6224,47 @@ snapshots: obug@2.1.1: {} + once@1.4.0: + dependencies: + wrappy: 1.0.2 + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 + open@11.0.0: + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-in-ssh: 1.0.0 + is-inside-container: 1.0.0 + powershell-utils: 0.1.0 + wsl-utils: 0.3.1 + + openai@4.89.0(ws@8.20.0)(zod@3.25.76): + dependencies: + '@types/node': 18.19.130 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + optionalDependencies: + ws: 8.20.0 + zod: 3.25.76 + transitivePeerDependencies: + - encoding + + openai@6.26.0(ws@8.20.0)(zod@4.4.3): + optionalDependencies: + ws: 8.20.0 + zod: 4.4.3 + + openapi3-ts@4.5.0: + dependencies: + yaml: 2.9.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -3228,16 +6288,64 @@ snapshots: dependencies: p-limit: 3.1.0 + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + 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.1.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: {} + patch-console@2.0.0: {} path-exists@4.0.0: {} + path-expression-matcher@1.5.0: {} + path-key@3.1.1: {} path-parse@1.0.7: {} + path-scurry@2.0.2: + dependencies: + lru-cache: 11.3.6 + minipass: 7.1.3 + pathe@2.0.3: {} + pend@1.2.0: {} + + periscopic@3.1.0: + dependencies: + '@types/estree': 1.0.8 + estree-walker: 3.0.3 + is-reference: 3.0.3 + picocolors@1.1.1: {} picomatch@4.0.4: {} @@ -3250,6 +6358,8 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + powershell-utils@0.1.0: {} + prelude-ls@1.2.1: {} prettier@3.8.3: {} @@ -3260,6 +6370,47 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 + proper-lockfile@4.1.2: + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + + protobufjs@7.5.8: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.1 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.1 + '@types/node': 24.12.2 + long: 5.3.2 + + 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: {} + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + punycode@2.3.1: {} react-devtools-core@7.0.1: @@ -3299,6 +6450,8 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 + require-directory@2.1.1: {} + resolve@2.0.0-next.6: dependencies: es-errors: 1.3.0 @@ -3313,6 +6466,10 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 + retry@0.12.0: {} + + retry@0.13.1: {} + rolldown@1.0.0-rc.17: dependencies: '@oxc-project/types': 0.127.0 @@ -3355,6 +6512,8 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.18 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.18 + run-applescript@7.1.0: {} + safe-array-concat@1.1.4: dependencies: call-bind: 1.0.9 @@ -3363,6 +6522,8 @@ snapshots: has-symbols: 1.1.0 isarray: 2.0.5 + safe-buffer@5.2.1: {} + safe-push-apply@1.0.0: dependencies: es-errors: 1.3.0 @@ -3380,6 +6541,12 @@ snapshots: semver@7.7.4: {} + seroval-plugins@1.5.4(seroval@1.5.4): + dependencies: + seroval: 1.5.4 + + seroval@1.5.4: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -3442,6 +6609,8 @@ snapshots: signal-exit@3.0.7: {} + signal-exit@4.1.0: {} + sisteransi@1.0.5: {} slice-ansi@9.0.0: @@ -3449,8 +6618,42 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.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.9 + transitivePeerDependencies: + - supports-color + + socks@2.8.9: + dependencies: + ip-address: 10.2.0 + smart-buffer: 4.2.0 + + solid-js@1.9.12: + dependencies: + csstype: 3.2.3 + seroval: 1.5.4 + seroval-plugins: 1.5.4(seroval@1.5.4) + + solid-swr-store@0.10.7(solid-js@1.9.12)(swr-store@0.10.6): + dependencies: + solid-js: 1.9.12 + swr-store: 0.10.6 + source-map-js@1.2.1: {} + source-map@0.6.1: + optional: true + + sswr@2.0.0(svelte@4.2.20): + dependencies: + svelte: 4.2.20 + swrev: 4.0.0 + stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 @@ -3464,6 +6667,18 @@ snapshots: es-errors: 1.3.0 internal-slot: 1.1.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@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + string-width@8.2.1: dependencies: get-east-asian-width: 1.5.0 @@ -3513,16 +6728,70 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + strip-ansi@7.2.0: dependencies: ansi-regex: 6.2.2 + strnum@2.3.0: {} + + strtok3@10.3.5: + dependencies: + '@tokenizer/token': 0.3.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + svelte@4.2.20: + dependencies: + '@ampproject/remapping': 2.3.0 + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + '@types/estree': 1.0.8 + acorn: 8.16.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + code-red: 1.0.4 + css-tree: 2.3.1 + estree-walker: 3.0.3 + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.21 + periscopic: 3.1.0 + + swr-store@0.10.6: + dependencies: + dequal: 2.0.3 + + swr@2.2.0(react@19.2.5): + dependencies: + react: 19.2.5 + use-sync-external-store: 1.6.0(react@19.2.5) + + swrev@4.0.0: {} + + swrv@1.0.4(vue@3.5.34(typescript@6.0.3)): + dependencies: + vue: 3.5.34(typescript@6.0.3) + tagged-tag@1.0.0: {} terminal-size@4.0.1: {} + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + tinybench@2.9.0: {} tinyexec@1.1.2: {} @@ -3534,12 +6803,21 @@ snapshots: tinyrainbow@3.1.0: {} + token-types@6.1.2: + dependencies: + '@borewit/text-codec': 0.2.2 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + + tr46@0.0.3: {} + + ts-algebra@2.0.0: {} + ts-api-utils@2.5.0(typescript@6.0.3): dependencies: typescript: 6.0.3 - tslib@2.8.1: - optional: true + tslib@2.8.1: {} type-check@0.4.0: dependencies: @@ -3549,6 +6827,8 @@ snapshots: dependencies: tagged-tag: 1.0.0 + typebox@1.1.38: {} + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -3582,19 +6862,21 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.59.2(eslint@10.3.0)(typescript@6.0.3): + typescript-eslint@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.59.2(@typescript-eslint/parser@8.59.2(eslint@10.3.0)(typescript@6.0.3))(eslint@10.3.0)(typescript@6.0.3) - '@typescript-eslint/parser': 8.59.2(eslint@10.3.0)(typescript@6.0.3) + '@typescript-eslint/eslint-plugin': 8.59.2(@typescript-eslint/parser@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/parser': 8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) '@typescript-eslint/typescript-estree': 8.59.2(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.2(eslint@10.3.0)(typescript@6.0.3) - eslint: 10.3.0 + '@typescript-eslint/utils': 8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) + eslint: 10.3.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color typescript@6.0.3: {} + uint8array-extras@1.5.0: {} + unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -3602,8 +6884,12 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 + undici-types@5.26.5: {} + undici-types@7.16.0: {} + undici@7.25.0: {} + update-browserslist-db@1.2.3(browserslist@4.28.2): dependencies: browserslist: 4.28.2 @@ -3614,7 +6900,15 @@ snapshots: dependencies: punycode: 2.3.1 - vite@8.0.10(@types/node@24.12.2): + use-sync-external-store@1.6.0(react@19.2.5): + dependencies: + react: 19.2.5 + + uuid@14.0.0: {} + + uuid@9.0.1: {} + + vite@8.0.10(@types/node@24.12.2)(jiti@2.7.0)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 @@ -3624,11 +6918,13 @@ snapshots: optionalDependencies: '@types/node': 24.12.2 fsevents: 2.3.3 + jiti: 2.7.0 + yaml: 2.9.0 - vitest@4.1.5(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)): + vitest@4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(jiti@2.7.0)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.5 - '@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@24.12.2)) + '@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@24.12.2)(jiti@2.7.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.5 '@vitest/runner': 4.1.5 '@vitest/snapshot': 4.1.5 @@ -3645,13 +6941,35 @@ snapshots: tinyexec: 1.1.2 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vite: 8.0.10(@types/node@24.12.2) + vite: 8.0.10(@types/node@24.12.2)(jiti@2.7.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: + '@opentelemetry/api': 1.9.1 '@types/node': 24.12.2 transitivePeerDependencies: - msw + vue@3.5.34(typescript@6.0.3): + dependencies: + '@vue/compiler-dom': 3.5.34 + '@vue/compiler-sfc': 3.5.34 + '@vue/runtime-dom': 3.5.34 + '@vue/server-renderer': 3.5.34(vue@3.5.34(typescript@6.0.3)) + '@vue/shared': 3.5.34 + optionalDependencies: + typescript: 6.0.3 + + web-streams-polyfill@3.3.3: {} + + web-streams-polyfill@4.0.0-beta.3: {} + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -3714,18 +7032,81 @@ snapshots: string-width: 8.2.1 strip-ansi: 7.2.0 + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 + + wrappy@1.0.2: {} + ws@7.5.10: {} ws@8.20.0: {} + wsl-utils@0.3.1: + dependencies: + is-wsl: 3.1.1 + powershell-utils: 0.1.0 + + xml-naming@0.1.0: {} + + y18n@5.0.8: {} + yallist@3.1.1: {} + yaml@2.9.0: {} + + yargs-parser@20.2.9: {} + + yargs-parser@22.0.0: {} + + 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 + + yargs@18.0.0: + dependencies: + cliui: 9.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + string-width: 7.2.0 + y18n: 5.0.8 + yargs-parser: 22.0.0 + + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + yocto-queue@0.1.0: {} yoga-layout@3.2.1: {} + zod-to-json-schema@3.25.2(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod-to-json-schema@3.25.2(zod@4.4.3): + dependencies: + zod: 4.4.3 + zod-validation-error@4.0.2(zod@4.4.3): dependencies: zod: 4.4.3 + zod@3.25.76: {} + zod@4.4.3: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..dee51e9 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - "packages/*" diff --git a/rolldown.config.mjs b/rolldown.config.mjs deleted file mode 100644 index ef8d49b..0000000 --- a/rolldown.config.mjs +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig } from "rolldown"; - -export default defineConfig({ - input: "src/cli.ts", - output: { - banner: "#!/usr/bin/env node", - codeSplitting: false, - file: "dist/cli.js", - format: "esm", - sourcemap: true, - }, - platform: "node", - external: [/^node:/], -}); diff --git a/sea-config.json b/sea-config.json new file mode 100644 index 0000000..44d6b8a --- /dev/null +++ b/sea-config.json @@ -0,0 +1 @@ +{ "main": "dist/cli.mjs", "output": "crank", "mainFormat": "module" } diff --git a/src/clack-wizard.ts b/src/clack-wizard.ts deleted file mode 100644 index ae51bbe..0000000 --- a/src/clack-wizard.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { - ACCOUNT_QUESTION, - LOGIN_BROWSER_PROMPT, - WIZARD_CANCEL_MESSAGE, - WIZARD_TITLE, - loginPlaceholderOutro, -} from "./wizard-copy"; - -type ConfirmOptions = { - readonly initialValue?: boolean; - readonly message: string; -}; - -type PromptResult = T | symbol; - -export type ClackWizardPrompts = { - readonly cancel: (message: string) => void; - readonly confirm: (options: ConfirmOptions) => Promise>; - readonly intro: (message: string) => void; - readonly isCancel: (value: unknown) => value is symbol; - readonly outro: (message: string) => void; -}; - -export type ClackWizardResult = { - readonly hasBraintrustAccount: boolean; - readonly openBrowser: boolean; -}; - -export class WizardCancelledError extends Error { - constructor() { - super(WIZARD_CANCEL_MESSAGE); - this.name = "WizardCancelledError"; - } -} - -async function confirmOrCancel(prompts: ClackWizardPrompts, message: string) { - const value = await prompts.confirm({ - initialValue: true, - message, - }); - - if (prompts.isCancel(value)) { - prompts.cancel(WIZARD_CANCEL_MESSAGE); - throw new WizardCancelledError(); - } - - return value; -} - -export async function runClackWizard( - prompts: ClackWizardPrompts, -): Promise { - prompts.intro(WIZARD_TITLE); - - const hasBraintrustAccount = await confirmOrCancel(prompts, ACCOUNT_QUESTION); - const openBrowser = await confirmOrCancel(prompts, LOGIN_BROWSER_PROMPT); - - prompts.outro(loginPlaceholderOutro(openBrowser)); - - return { - hasBraintrustAccount, - openBrowser, - }; -} diff --git a/src/cli.ts b/src/cli.ts deleted file mode 100644 index 2412909..0000000 --- a/src/cli.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as prompts from "@clack/prompts"; - -import { runClackWizard, WizardCancelledError } from "./clack-wizard"; - -try { - await runClackWizard(prompts); -} catch (error) { - if (error instanceof WizardCancelledError) { - process.exit(0); - } - - throw error; -} diff --git a/src/wizard-copy.ts b/src/wizard-copy.ts deleted file mode 100644 index b54ef3e..0000000 --- a/src/wizard-copy.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const WIZARD_TITLE = "Braintrust Setup"; - -export const WIZARD_DESCRIPTION = - "Welcome to the Braintrust setup wizard. This wizard will guide you through setting up braintrust in your project."; - -export const ACCOUNT_QUESTION = "Do you already have a Braintrust account?"; - -export const LOGIN_BROWSER_PROMPT = - "For the rest of the flow, we require you to be logged in, do you want to open the browser?"; - -export const WIZARD_CANCEL_MESSAGE = "Wizard cancelled."; - -export function loginPlaceholderOutro(openBrowser: boolean) { - if (openBrowser) { - return "Browser login is not wired up yet, so no browser was opened."; - } - - return "Browser login skipped. Setup flow stops here for now."; -} diff --git a/test/clack-wizard.test.ts b/test/clack-wizard.test.ts deleted file mode 100644 index 7b8b2df..0000000 --- a/test/clack-wizard.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import { - runClackWizard, - type ClackWizardPrompts, - WizardCancelledError, -} from "../src/clack-wizard"; -import { - ACCOUNT_QUESTION, - LOGIN_BROWSER_PROMPT, - WIZARD_CANCEL_MESSAGE, - WIZARD_TITLE, - loginPlaceholderOutro, -} from "../src/wizard-copy"; - -const CANCEL = Symbol("cancel"); - -type ConfirmCall = { - readonly initialValue?: boolean; - readonly message: string; -}; - -function createPrompts(answers: Array) { - const confirmCalls: ConfirmCall[] = []; - const events: string[] = []; - - const prompts: ClackWizardPrompts = { - cancel(message) { - events.push(`cancel:${message}`); - }, - async confirm(options) { - confirmCalls.push(options); - - const answer = answers.shift(); - - if (answer === undefined) { - throw new Error("No fake answer was provided."); - } - - return answer; - }, - intro(message) { - events.push(`intro:${message}`); - }, - isCancel(value): value is symbol { - return value === CANCEL; - }, - outro(message) { - events.push(`outro:${message}`); - }, - }; - - return { - confirmCalls, - events, - prompts, - }; -} - -describe("runClackWizard", () => { - it("asks both questions in order", async () => { - const { confirmCalls, events, prompts } = createPrompts([true, true]); - - await expect(runClackWizard(prompts)).resolves.toEqual({ - hasBraintrustAccount: true, - openBrowser: true, - }); - - expect(events).toEqual([ - `intro:${WIZARD_TITLE}`, - `outro:${loginPlaceholderOutro(true)}`, - ]); - expect(confirmCalls).toEqual([ - { initialValue: true, message: ACCOUNT_QUESTION }, - { initialValue: true, message: LOGIN_BROWSER_PROMPT }, - ]); - }); - - it("returns the selected answers and acknowledges the login choice", async () => { - const { confirmCalls, events, prompts } = createPrompts([false, false]); - - await expect(runClackWizard(prompts)).resolves.toEqual({ - hasBraintrustAccount: false, - openBrowser: false, - }); - - expect(confirmCalls).toEqual([ - { initialValue: true, message: ACCOUNT_QUESTION }, - { initialValue: true, message: LOGIN_BROWSER_PROMPT }, - ]); - expect(events).toContain(`outro:${loginPlaceholderOutro(false)}`); - }); - - it("cancels cleanly before completing the flow", async () => { - const { confirmCalls, events, prompts } = createPrompts([CANCEL]); - - await expect(runClackWizard(prompts)).rejects.toThrow(WizardCancelledError); - - expect(confirmCalls).toEqual([ - { initialValue: true, message: ACCOUNT_QUESTION }, - ]); - expect(events).toEqual([ - `intro:${WIZARD_TITLE}`, - `cancel:${WIZARD_CANCEL_MESSAGE}`, - ]); - }); -});