From dc9dfb5a7f72e34c1a2a6b93d1890faf0a727a6e Mon Sep 17 00:00:00 2001 From: Sidharth Menon Date: Thu, 8 Oct 2026 18:41:39 -0700 Subject: [PATCH] Add a Diffr extension for Pi (AI-assisted) /diffr docks a review above Pi's chat draft, using Pi's public extension API and native focus. F6 toggles fullscreen. Dragged lines join the draft unsent. The model opens comparisons with a diffr_open tool, acknowledged once a valid comparison starts. Agent-Session: fb96350b-c19e-48f0-b364-31e9ad2b72f4 Agent-Session: a7af3b88-3bb7-48a2-ae20-7626a83628a1 Agent-Session: 01a11ab9-c68e-7c52-916b-e1b0123e302f Agent-Session: 01a11aca-5007-7b80-ad35-c0a0f746a05d Agent-Session: 01a11c34-48e4-7ec1-bb72-2c496acb90dc Agent-Session: 01a11c3d-70b4-7df1-be1a-f0e12840fadf Agent-Session: ec5d2c35-3045-44f3-9c41-ba4378797c8e Agent-Session: 01a11cf1-8ad4-7910-b120-b0d622692a95 Agent-Session: 01a11ded-d896-7251-bf8f-c71bf07fd283 Agent-Session: 01a11e03-81df-7d63-bfa5-953f535444d2 Agent-Session: 01a11e0a-d042-71d2-9bc9-ac7b652487d1 Agent-Session: b5985b3c-e5d2-4bb4-b6ac-7fec168d8328 Agent-Session: cbc75bbf-5438-46f4-b8ed-41beb0e20f0c Claude-Session: https://claude.ai/code/session_01HNbERuYJjvvAjBN19zEDbo Agent-Session: 01a11ecf-aa86-7a81-a5e6-c5dfe72d48eb Agent-Session: 01a11f51-383b-7f63-a323-39195d82ab2e --- .github/workflows/diffr-test.yml | 5 + diffr/packages/pi/USAGE.md | 19 + diffr/packages/pi/bin/diffr-pi.mjs | 6 + diffr/packages/pi/build.ts | 4 + diffr/packages/pi/package.json | 38 + diffr/packages/pi/src/index.test.ts | 140 +++ diffr/packages/pi/src/index.ts | 117 +++ diffr/packages/pi/src/keys.test.ts | 14 + diffr/packages/pi/src/keys.ts | 17 + diffr/packages/pi/src/layout.test.ts | 54 ++ diffr/packages/pi/src/layout.ts | 83 ++ diffr/packages/pi/test/host.ts | 44 + diffr/packages/pi/test/terminal-host.ts | 45 + diffr/packages/pi/tsconfig.json | 4 + diffr/packages/pi/vitest.config.ts | 1 + pnpm-lock.yaml | 1070 ++++++++++++++++++++++- pnpm-workspace.yaml | 3 + 17 files changed, 1631 insertions(+), 33 deletions(-) create mode 100644 diffr/packages/pi/USAGE.md create mode 100755 diffr/packages/pi/bin/diffr-pi.mjs create mode 100644 diffr/packages/pi/build.ts create mode 100644 diffr/packages/pi/package.json create mode 100644 diffr/packages/pi/src/index.test.ts create mode 100644 diffr/packages/pi/src/index.ts create mode 100644 diffr/packages/pi/src/keys.test.ts create mode 100644 diffr/packages/pi/src/keys.ts create mode 100644 diffr/packages/pi/src/layout.test.ts create mode 100644 diffr/packages/pi/src/layout.ts create mode 100644 diffr/packages/pi/test/host.ts create mode 100644 diffr/packages/pi/test/terminal-host.ts create mode 100644 diffr/packages/pi/tsconfig.json create mode 100644 diffr/packages/pi/vitest.config.ts diff --git a/.github/workflows/diffr-test.yml b/.github/workflows/diffr-test.yml index 049ab36f9..ceee5ca69 100644 --- a/.github/workflows/diffr-test.yml +++ b/.github/workflows/diffr-test.yml @@ -301,6 +301,11 @@ jobs: run: | pnpm build git diff --exit-code -- plugin + - working-directory: diffr/packages/pi + run: | + pnpm typecheck + pnpm test + pnpm build - working-directory: diffr/packages/tui run: | pnpm typecheck diff --git a/diffr/packages/pi/USAGE.md b/diffr/packages/pi/USAGE.md new file mode 100644 index 000000000..161b9e880 --- /dev/null +++ b/diffr/packages/pi/USAGE.md @@ -0,0 +1,19 @@ +# Diffr for Pi + +Tested with Pi 0.99.1 and 1.1.0. Use `diffr` on PATH and Pi's fullscreen terminal renderer for mouse input. +From the repository root, run `pnpm install`, then `pnpm --dir diffr/packages/pi build`. +Launch `pi/bin/diffr-pi.mjs` (or `pi --tui-mode fullscreen -e /absolute/path/to/pi/dist/index.js`). + +- `/diffr [arguments]` opens a floating panel at the right. Arguments go directly to Diffr, without a shell. +- The model can call `diffr_open({args: [...]})`. It opens without taking keyboard focus and acknowledges a valid comparison start. Pi registers this tool through its native extension API; no separate MCP process is needed. +- F7 focuses or reopens the panel. Escape returns to chat; a fullscreen overlay hides until F7. +- F6 or the top bar toggles fullscreen. `/diffr-fullscreen` also opens or toggles it. +- Drag source lines, then Enter to append references and contents to the current draft. Nothing is submitted. +- `V` marks a file viewed, `zM` folds scopes, `zR` unfolds them, and `\\` toggles files. +- `q` in the pane or `/diffr-close` closes it. Session changes also close it. + +The panel covers part of the chat; it does not resize the native transcript into a left column. +Pi's public `ctx.ui.custom()` overlay API owns placement and focus. No private layout fields are used. +The panel leaves the bottom quarter of the terminal available for the draft. Fullscreen shows only Diffr. +Viewed marks and folds survive view switches, but reopening starts a new comparison. +`--diffr-bin /path/to/diffr` selects a binary; `--diffr-input /path/to/recording.ndjson` opens a saved comparison. diff --git a/diffr/packages/pi/bin/diffr-pi.mjs b/diffr/packages/pi/bin/diffr-pi.mjs new file mode 100755 index 000000000..380ce8b2c --- /dev/null +++ b/diffr/packages/pi/bin/diffr-pi.mjs @@ -0,0 +1,6 @@ +#!/usr/bin/env node +import { spawn } from "node:child_process"; +import { fileURLToPath } from "node:url"; +const child = spawn("pi", ["--tui-mode", "fullscreen", "-e", fileURLToPath(new URL("../dist/index.js", import.meta.url)), ...process.argv.slice(2)], { stdio: "inherit" }); +child.on("error", error => { console.error(error.message); process.exitCode = 1; }); +child.on("exit", (code, signal) => { process.exitCode = code ?? (signal ? 1 : 0); }); diff --git a/diffr/packages/pi/build.ts b/diffr/packages/pi/build.ts new file mode 100644 index 000000000..59a06a988 --- /dev/null +++ b/diffr/packages/pi/build.ts @@ -0,0 +1,4 @@ +import { build } from "esbuild"; + +await build({ entryPoints: ["src/index.ts"], outdir: "dist", bundle: true, platform: "node", format: "esm", + external: ["@earendil-works/pi-coding-agent", "@earendil-works/pi-tui", "typebox"] }); diff --git a/diffr/packages/pi/package.json b/diffr/packages/pi/package.json new file mode 100644 index 000000000..fbaad2d60 --- /dev/null +++ b/diffr/packages/pi/package.json @@ -0,0 +1,38 @@ +{ + "name": "@diffr/pi", + "version": "0.1.0", + "private": true, + "license": "MIT", + "type": "module", + "pi": { + "extensions": [ + "./dist/index.js" + ] + }, + "bin": { + "diffr-pi": "./bin/diffr-pi.mjs" + }, + "scripts": { + "build": "node build.ts", + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@diffr/consumer": "workspace:*", + "@diffr/viewer": "workspace:*" + }, + "peerDependencies": { + "@earendil-works/pi-coding-agent": ">=0.99.1 <2", + "@earendil-works/pi-tui": ">=0.99.1 <2", + "typebox": "*" + }, + "devDependencies": { + "@earendil-works/pi-coding-agent": "0.99.1", + "@earendil-works/pi-tui": "0.99.1", + "typescript": "5.9.3", + "typebox": "1.3.27", + "@types/node": "24.12.2", + "vitest": "4.1.11", + "esbuild": "0.28.1" + } +} diff --git a/diffr/packages/pi/src/index.test.ts b/diffr/packages/pi/src/index.test.ts new file mode 100644 index 000000000..0e812b869 --- /dev/null +++ b/diffr/packages/pi/src/index.test.ts @@ -0,0 +1,140 @@ +import { expect, test } from "vitest"; +import { stripVTControlCharacters } from "node:util"; +import { fileURLToPath } from "node:url"; +import type { TuiMouseEvent } from "@earendil-works/pi-tui"; +import diffr from "./index"; +import { host } from "../test/host"; +import { terminalHost } from "../test/terminal-host"; + +function harness(h: ReturnType | ReturnType = host()) { + let tool: any; + const events = new Map void>(); + const ctx: any = { mode: "tui", cwd: process.cwd(), ui: h.ui }; + diffr({ registerFlag() {}, registerCommand() {}, registerShortcut() {}, on(name: string, fn: () => void) { events.set(name, fn); }, + registerTool(value: any) { tool = value; }, + getFlag(name: string) { if (name === "diffr-input") return fileURLToPath(new URL("../../consumer/test/fixtures/scopes.ndjson", import.meta.url)); }, + } as any); + return { ctx, events, input: h.input, get component() { return h.widget!; }, get tool() { return tool; }, + get draft() { return h.ui.getEditorText(); }, get submitted() { return h.submitted; } }; +} + +test.each(["unified", "split"] as const)("Pi %s region selection preserves both sides across redraws and appends to an unsent draft", async layout => { + const h = harness(); + const result = await h.tool.execute("call", { args: [] }, undefined, undefined, h.ctx); + expect(result.content[0].text).toContain("1 changed files"); + h.input(" Still writing."); + expect(h.draft).toContain(" Still writing."); + h.input("\x1b[18~"); // F7 focuses the diff. + let lines = h.component.render(360).map(line => stripVTControlCharacters(line)); + if (!lines.some(line => line.includes(`${layout} [s]`))) h.input("s"); + lines = h.component.render(360).map(line => stripVTControlCharacters(line)); + const start = lines.findIndex(line => line.includes("for (const plugin")); + const middle = lines.findIndex(line => line.includes("Number(plugin.lines)")); + const end = lines.findIndex(line => line.includes("plugin.enabled")); + expect(start).toBeGreaterThan(0); + const mouse = (type: TuiMouseEvent["type"], x: number, y: number) => { + h.component.handleMouse!({ type, x, y, screenX: x, screenY: y, width: 360, height: 30, + button: "left", shift: false, alt: false, ctrl: false }); + h.component.render(360); + }; + const left = lines[start]!.indexOf("for (const plugin"); + const right = lines[end]!.lastIndexOf("plugin.enabled"); + const before = h.draft; + mouse("press", left, start); mouse("drag", left, middle); mouse("drag", right, end); mouse("release", right, end); + h.input("\r"); + expect(h.draft).toContain("Keep my draft."); + expect(h.draft).toContain("- plugin.lines = Number(plugin.lines);"); + expect(h.draft).toContain("+ plugin.lines = Number(plugin.shape.lines);"); + expect(h.draft).toContain(" plugin.enabled = true;"); + const forward = h.draft; + h.component.render(360); + mouse("press", right, end); mouse("drag", right, middle); mouse("drag", left, start); mouse("release", left, start); + h.input("\r"); + expect(h.draft.slice(forward.length)).toBe(forward.slice(before.length)); + const draft = h.draft; + h.events.get("session_start")!(); + expect(h.submitted).toBe(0); + expect(h.draft).toBe(draft); +}); + +test("headless tool calls report an unavailable UI instead of claiming success", async () => { + const h = harness(); + h.ctx.mode = "rpc"; + await expect(h.tool.execute("call", {}, undefined, undefined, h.ctx)).rejects.toThrow("interactive terminal"); + expect(h.draft).toBe("Keep my draft."); +}); + +test("docked folding survives height changes and picker cancellation leaves the draft intact", async () => { + const h = harness(); + await h.tool.execute("call", {}, undefined, undefined, h.ctx); + h.input("\x1b[18~"); + const lines = () => h.component.render(180).map(line => stripVTControlCharacters(line)); + expect(lines().some(line => line.includes("plugin.enabled"))).toBe(true); + h.input("z"); h.input("M"); + expect(lines().some(line => line.includes("plugin.enabled"))).toBe(false); + h.input("\x1b[17~"); // F6 expands the same comparison. + expect(lines().some(line => line.includes("plugin.enabled"))).toBe(false); + h.input("z"); h.input("R"); + expect(lines().some(line => line.includes("plugin.enabled"))).toBe(true); + const before = h.draft; + h.input("\x10"); h.input("\x03"); // file picker then cancel + expect(h.draft).toBe(before); + const rendered = lines(); + const row = rendered.findIndex(line => line.includes("▌▾")); + const x = rendered[row]!.indexOf("▌▾") + 1; + h.component.handleMouse!({ type: "press", x, y: row, screenX: x, screenY: row, + width: 180, height: 40, button: "left", shift: false, alt: false, ctrl: false }); + expect(lines().some(line => line.includes("plugin.enabled"))).toBe(false); + h.component.handleMouse!({ type: "press", x, y: row, screenX: x, screenY: row, + width: 180, height: 40, button: "left", shift: false, alt: false, ctrl: false }); + expect(lines().some(line => line.includes("plugin.enabled"))).toBe(true); + expect(h.submitted).toBe(0); + h.events.get("session_start")!(); +}); + + +test("real Pi mouse routing returns typing to the draft and preserves caret clicks after selection", async () => { + const terminal = terminalHost(); + const h = harness(terminal); + try { + await h.tool.execute("call", {}, undefined, undefined, h.ctx); + terminal.tui.renderNow(); + const lines = () => h.component.render(180).map(line => stripVTControlCharacters(line)); + const original = lines(); + const row = original.findIndex(line => line.includes("▾") && line.includes("for (const plugin")); + expect(row).toBeGreaterThan(0); + const caret = original[row]!.indexOf("▾"); + const code = original[row]!.indexOf("for (const plugin"); + const bodyRow = original.findIndex(line => line.includes("Number(plugin.lines)")); + const rail = original[bodyRow]!.lastIndexOf("│"); + terminal.mouse(35, rail + 1, bodyRow); // Motion without a pressed button. + expect(lines()[bodyRow]![rail]).toBe("┃"); + terminal.mouse(35, code + 12, row); + expect(lines()[bodyRow]![rail]).toBe("│"); + terminal.click(code, row); + const editorRow = lines().length + 1; + terminal.click(3, editorRow); + const before = h.draft; + for (const char of "typing") terminal.input(char); + expect(h.draft).not.toBe(before); + expect(h.draft).toContain("typing"); + for (let i = 0; i < 4; i++) { + terminal.click(caret - 1, row); + expect(lines()[row]).toContain("▸"); + terminal.click(caret + 1, row); + expect(lines()[row]).toContain("▾"); + } + terminal.mouse(0, code, row); + terminal.mouse(32, code + 8, row + 1); + terminal.mouse(0, code + 8, row + 1, true); + const selection = lines(); + const bar = selection.findIndex(line => line.includes("Add to chat")); + expect(bar).toBeGreaterThan(0); + terminal.click(selection[bar]!.indexOf("Add to chat"), bar); + expect(h.draft).toContain("diff --git"); + expect(terminal.tui.getFocusedComponent()).toBe(terminal.editor); + terminal.input("after paste"); + expect(h.draft).toContain("after paste"); + expect(h.submitted).toBe(0); + } finally { h.events.get("session_shutdown")!(); terminal.stop(); } +}); diff --git a/diffr/packages/pi/src/index.ts b/diffr/packages/pi/src/index.ts new file mode 100644 index 000000000..39398d2ad --- /dev/null +++ b/diffr/packages/pi/src/index.ts @@ -0,0 +1,117 @@ +import { copyToClipboard, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent"; +import type { Component, TuiMouseEvent, TuiMouseEventResult } from "@earendil-works/pi-tui"; +import { ansiLines } from "@diffr/consumer/ansi"; +import { splitArgs } from "@diffr/consumer/args"; +import { PointerInput } from "@diffr/consumer/pointer"; +import { openComparison, type Comparison } from "@diffr/consumer/process"; +import type { Outcome } from "@diffr/consumer/frame"; +import type { Frame } from "@diffr/consumer/protocol"; +import { fit } from "@diffr/consumer/paint"; +import { Type } from "typebox"; +import { opened, openDescription } from "@diffr/consumer/open-tool"; +import { mountPane } from "./layout"; +import { paneKey } from "./keys"; + +export default function diffr(pi: ExtensionAPI) { + let active: { close(): void; focus(): void; blur(): void; toggle(): void } | undefined; + let generation = 0; + pi.registerFlag("diffr-input", { description: "Open a saved Diffr NDJSON comparison", type: "string" }); + pi.registerFlag("diffr-bin", { description: "Path to the Diffr executable", type: "string" }); + const close = () => { generation++; active?.close(); active = undefined; }; + pi.on("session_shutdown", close); + pi.on("session_start", close); + pi.on("ui_prompt_start", () => active?.blur()); + + async function open(args: string[], ctx: ExtensionContext, full = false, capture = true, signal?: AbortSignal) { + if (ctx.mode !== "tui") throw new Error("Diffr requires Pi’s interactive terminal UI."); + close(); + const id = generation; + let comparison: Comparison | undefined; + try { + comparison = await openComparison({ cwd: ctx.cwd, args, + binary: pi.getFlag("diffr-bin") as string | undefined, input: pi.getFlag("diffr-input") as string | undefined }); + if (id !== generation) { comparison.dispose(); throw new Error("Diffr open was replaced or closed."); } + const current = comparison; + const pointer = new PointerInput(); + let frame: Frame | undefined; + let layout: ReturnType; + let closed = false; + let repaint = () => {}; + const focusChat = () => { + layout.focusChat(); + }; + const outcome = async (value: Outcome) => { + if (value.close) { close(); return; } + if (value.chat) { + // Pi delivers pasteToEditor through handleInput; return to draft input first. + focusChat(); + ctx.ui.pasteToEditor(`\n${value.chat.map(chip => chip.context).join("\n\n")}\n`); + current.pane.chatted(value.chat.map(chip => chip.name)); + } + if (value.copy) { + try { await copyToClipboard(value.copy.text); current.pane.copied(value.copy.what); } + catch (error) { current.pane.copied(value.copy.what, String(error)); } + } + if (!closed) repaint(); + }; + layout = mountPane(ctx.ui, (terminal, expanded, focused) => { + repaint = () => terminal.requestRender(); + const component: Component = { + render(width) { + frame = current.pane.frame({ columns: width, rows: Math.max(3, Math.floor(terminal.terminal.rows * (expanded() ? 0.70 : 0.45)) - 1) }); + const label = ` Diffr · ${focused() ? "review focused · Esc draft" : "draft focused · F7 review"} · F6 ${expanded() ? "shrink" : "expand"} · q close`; + return [fit(label, width).padEnd(width), ...ansiLines(frame)]; + }, + invalidate() {}, + handleInput(data) { + const key = paneKey(data); + if (!key) return; + if (!frame) { repaint(); return; } + void outcome(current.pane.input({ press: key })); + }, + handleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined { + if ((event.type === "press" || event.type === "drag") && event.button !== "left") return; + if (event.y === 0 && event.type === "press") { layout.toggle(); return { handled: true, focus: true }; } + if (!frame) return; + if (event.type === "wheel") { current.pane.scroll(event.wheelDelta ?? 0, event.x); return { handled: true, render: true }; } + const type = event.type === "press" ? "down" : event.type === "release" ? "up" : event.type === "click" ? undefined : event.type; + if (!type) return { handled: true }; + const next = pointer.read(frame, { type, x: event.x, y: event.y - 1, alt: event.alt }); + if (next.hover !== undefined) current.pane.hover(next.hover); + if (next.input) void outcome(current.pane.input(next.input)); + return { handled: true, capture: type === "down", focus: type === "down", render: true }; + }, + }; + return component; + }, full, capture); + layout.onBlur(() => { pointer.reset(); current.pane.blur(); }); + const unsubscribe = current.pane.subscribe(repaint); + active = { focus: () => layout.focus(), blur: focusChat, toggle: () => { layout.toggle(); }, close() { + closed = true; pointer.reset(); unsubscribe(); current.dispose(); layout.dispose(); + } }; + const result = await opened(current, signal); + if (id !== generation) throw new Error("Diffr open was replaced or closed."); + return result; + } catch (error) { + comparison?.dispose(); + if (id === generation) close(); + throw error; + } + } + const command = async (args: string, ctx: ExtensionContext, full = false) => { + try { await open(splitArgs(args), ctx, full); } + catch (error) { ctx.ui.notify(`Diffr: ${error instanceof Error ? error.message : error}`, "error"); } + }; + pi.registerTool({ name: "diffr_open", label: "Open Diffr", description: openDescription, + promptSnippet: "Open a comparison in Diffr for the person to review.", + parameters: Type.Object({ args: Type.Optional(Type.Array(Type.String())) }), + async execute(_id, params, signal, _update, ctx) { + const text = await open(params.args ?? [], ctx, false, false, signal); + return { content: [{ type: "text", text }], details: {} }; + }, + }); + pi.registerCommand("diffr", { description: "Review a comparison above the chat draft", handler: (args, ctx) => command(args, ctx) }); + pi.registerCommand("diffr-fullscreen", { description: "Toggle the expanded docked Diffr view", handler: async (args, ctx) => active && !args ? active.toggle() : command(args, ctx, true) }); + pi.registerCommand("diffr-close", { description: "Close the Diffr pane", handler: async () => close() }); + pi.registerShortcut("f7", { description: "Focus or open Diffr", handler: ctx => active ? active.focus() : command("", ctx) }); +} diff --git a/diffr/packages/pi/src/keys.test.ts b/diffr/packages/pi/src/keys.test.ts new file mode 100644 index 000000000..5d26ca889 --- /dev/null +++ b/diffr/packages/pi/src/keys.test.ts @@ -0,0 +1,14 @@ +import { expect, test } from "vitest"; +import { paneKey } from "./keys"; + +test("Pi terminal sequences preserve Diffr's case-sensitive viewer commands", () => { + expect(paneKey("V")?.key).toBe("V"); + expect(paneKey("\r")?.key).toBe("return"); + expect(paneKey("\x1b")).toEqual({ key: "escape" }); + expect(paneKey("\x10")).toEqual({ key: "p", ctrl: true }); +}); + +test("Kitty releases cannot repeat a pane command", () => { + expect(paneKey("\x1b[17;1:3~")).toBeUndefined(); + expect(paneKey("\x1b[118;2:3u")).toBeUndefined(); +}); diff --git a/diffr/packages/pi/src/keys.ts b/diffr/packages/pi/src/keys.ts new file mode 100644 index 000000000..dab23498d --- /dev/null +++ b/diffr/packages/pi/src/keys.ts @@ -0,0 +1,17 @@ +import { isKeyRelease, parseKey } from "@earendil-works/pi-tui"; +import type { KeyPress } from "@diffr/viewer/viewer"; + +export function paneKey(data: string): KeyPress | undefined { + if (isKeyRelease(data)) return; + const parsed = parseKey(data); + if (!parsed) return; + const parts = parsed.split("+"); + let key = parts.pop()!; + const shift = parts.includes("shift"); + if (/^[^\x00-\x1f\x7f]$/u.test(data)) key = data; + else if (shift && /^[a-z]$/.test(key)) key = key.toUpperCase(); + return { key: key === "enter" ? "return" : key, + ...(parts.includes("ctrl") ? { ctrl: true } : {}), + ...(parts.includes("alt") || parts.includes("meta") ? { meta: true } : {}), + ...(shift ? { shift: true } : {}) }; +} diff --git a/diffr/packages/pi/src/layout.test.ts b/diffr/packages/pi/src/layout.test.ts new file mode 100644 index 000000000..bc6fb602f --- /dev/null +++ b/diffr/packages/pi/src/layout.test.ts @@ -0,0 +1,54 @@ +import { expect, test } from "vitest"; +import { mountPane } from "./layout"; +import { host } from "../test/host"; + +const component = () => ({ render: () => ["DIFF"], invalidate() {} }); + +test("dock open, resize, and close preserve native editor and expanded paste contents", async () => { + const h = host(); + const patch = Array.from({ length: 20 }, (_, i) => `line ${i}`).join("\n"); + h.ui.pasteToEditor(patch); + const before = h.ui.getEditorText(); + expect(h.editor.getText()).toContain("[paste #"); + const editor = h.editor; + const pane = mountPane(h.ui, component, false, false); + expect(h.ui.getEditorText()).toBe(before); + await pane.toggle(); + pane.focusChat(); + h.input(" still typing"); + expect(h.ui.getEditorText()).toContain(" still typing"); + const after = h.ui.getEditorText(); + pane.dispose(); + expect(h.editor).toBe(editor); + expect(h.widget).toBeUndefined(); + expect(h.ui.getEditorText()).toBe(after); + expect(h.submitted).toBe(0); +}); + +test("review keys and picker cancellation stay out of the native draft", () => { + const h = host(); + const keys: string[] = []; + const pane = mountPane(h.ui, () => ({ ...component(), handleInput(data) { keys.push(data); } }), false, false); + h.input("hello"); + pane.focus(); + h.input("j"); h.input("\x10"); h.input("\x03"); + expect(keys).toEqual(["j", "\x10", "\x03"]); + expect(h.ui.getEditorText()).toContain("hello"); + h.input("\x1b"); h.input(" after review"); + expect(h.ui.getEditorText()).toContain("hello after review"); + expect(h.submitted).toBe(0); + pane.dispose(); +}); + +test("another extension's overlay receives input without Diffr interception", () => { + const h = host(); + const keys: string[] = []; + const pane = mountPane(h.ui, () => ({ ...component(), handleInput(data) { keys.push(data); } }), false, true); + h.overlay = true; + h.input("q"); + expect(keys).toEqual([]); + h.overlay = false; + h.input("z"); + expect(keys).toEqual([]); + pane.dispose(); +}); diff --git a/diffr/packages/pi/src/layout.ts b/diffr/packages/pi/src/layout.ts new file mode 100644 index 000000000..b6c95f967 --- /dev/null +++ b/diffr/packages/pi/src/layout.ts @@ -0,0 +1,83 @@ +import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; +import type { Component, Focusable, TUI, TuiAltScreen } from "@earendil-works/pi-tui"; +import { paneKey } from "./keys"; + +/** A public widget reserves space above the native editor and below the transcript. */ +export function mountPane(ui: ExtensionContext["ui"], + create: (tui: TUI, expanded: () => boolean, focused: () => boolean) => Component, + initialExpanded: boolean, capture: boolean) { + let expanded = initialExpanded; + let closed = false; + // Missing from Pi 0.99's TUI interface. + let terminal: TUI & Pick; + let widget: Component & Focusable; + let draft: Component | null; + let blur = () => {}; + const repaint = () => terminal?.requestRender(); + const focused = () => terminal?.getFocusedComponent() === widget; + const focusChat = () => { + // Do not dismiss another extension's dialog when it takes focus. + if (focused()) terminal.setFocus(draft); + repaint(); + }; + const focus = () => { + if (closed || focused() || terminal.hasOverlay()) return; + draft = terminal.getFocusedComponent(); + terminal.setFocus(widget); + repaint(); + }; + ui.setWidget("diffr", tui => { + terminal = tui as typeof terminal; + draft = terminal.getFocusedComponent(); + const component = create(tui, () => expanded, focused); + widget = { + get focused() { return focused(); }, + set focused(value: boolean) { if (!value) blur(); }, + render: width => component.render(width), + invalidate: () => component.invalidate(), + handleInput: data => component.handleInput?.(data), + handleMouse(event) { + if (closed) return; + if (event.type === "press" && event.button === "left") focus(); + // An action can return focus to the draft (Add to chat) or close the pane. + // Do not let the subsequent dispatch result focus the widget again. + const result = component.handleMouse?.(event); + return result ? { ...result, focus: false } : undefined; + }, + } satisfies Component & Focusable; + return widget; + }); + if (capture) focus(); + const removeInput = ui.onTerminalInput(data => { + if (closed || terminal.hasOverlay()) return; + const key = paneKey(data); + if (!key) return; + if (key.key === "f7") { focus(); return { consume: true }; } + if (!focused()) return; + if (key.key === "escape") { focusChat(); return { consume: true }; } + if (key.key === "f6") { expanded = !expanded; repaint(); return { consume: true }; } + const viewerModifier = (key.ctrl && ["p", "n", "c", "g", "d", "u", "f", "b"].includes(key.key)) + || (key.meta && ["p", "b", "l"].includes(key.key)); + if ((key.ctrl || key.meta) && !viewerModifier) focusChat(); + // Pi dispatches ordinary input to its actual focused component. + }); + return { + onBlur(fn: () => void) { blur = fn; }, + focus, + focusChat, + toggle() { + if (closed) return; + expanded = !expanded; + focus(); + repaint(); + }, + dispose() { + if (closed) return; + focusChat(); + closed = true; + removeInput(); + ui.setWidget("diffr", undefined); + repaint(); + }, + }; +} diff --git a/diffr/packages/pi/test/host.ts b/diffr/packages/pi/test/host.ts new file mode 100644 index 000000000..9f7e51640 --- /dev/null +++ b/diffr/packages/pi/test/host.ts @@ -0,0 +1,44 @@ +import { CustomEditor, type ExtensionContext } from "@earendil-works/pi-coding-agent"; +import type { Component, TUI } from "@earendil-works/pi-tui"; + +type InputHandler = Parameters[0]; +export function host(draft = "Keep my draft.") { + const terminal = { columns: 180, rows: 40 }; + let overlay = false; + let focused: Component | null = null; + const tui = { terminal, requestRender() {}, hasOverlay: () => overlay, + getFocusedComponent: () => focused, + setFocus(value: Component | null) { + if (focused && "focused" in focused) (focused as any).focused = false; + focused = value; + if (value && "focused" in value) (value as any).focused = true; + }, + } as unknown as TUI; + const theme = { borderColor: (s: string) => s, selectList: { + selectedPrefix: (s: string) => s, selectedText: (s: string) => s, + description: (s: string) => s, scrollInfo: (s: string) => s, noMatch: (s: string) => s, + } }; + const keys = { matches: () => false } as unknown as ConstructorParameters[2]; + const editor = new CustomEditor(tui, theme, keys); + editor.setText(draft); + tui.setFocus(editor); + let submitted = 0; + editor.onSubmit = () => { submitted++; }; + let widget: Component | undefined; + const handlers = new Set(); + const ui = { + notify() {}, + setWidget(_name: string, factory: ((tui: TUI) => Component) | undefined) { widget = factory?.(tui); }, + onTerminalInput(handler: InputHandler) { handlers.add(handler); return () => { handlers.delete(handler); }; }, + getEditorText: () => editor.getExpandedText(), + setEditorText: (text: string) => editor.setText(text), + pasteToEditor(text: string) { editor.handleInput(`\x1b[200~${text}\x1b[201~`); }, + } as unknown as ExtensionContext["ui"]; + return { ui, terminal, editor, get widget() { return widget; }, + get submitted() { return submitted; }, set overlay(value: boolean) { overlay = value; tui.setFocus(value ? { render: () => [], invalidate() {} } : editor); }, + input(data: string) { + for (const handler of handlers) if (handler(data)?.consume) return; + focused?.handleInput?.(data); + }, + }; +} diff --git a/diffr/packages/pi/test/terminal-host.ts b/diffr/packages/pi/test/terminal-host.ts new file mode 100644 index 000000000..c718dc0df --- /dev/null +++ b/diffr/packages/pi/test/terminal-host.ts @@ -0,0 +1,45 @@ +import { CustomEditor, type ExtensionContext } from "@earendil-works/pi-coding-agent"; +import { Container, TuiAltScreen, type Component, type Terminal } from "@earendil-works/pi-tui"; + +export function terminalHost() { + let receive = (_data: string) => {}; + const terminal: Terminal = { + columns: 180, rows: 40, kittyProtocolActive: false, + start(input) { receive = input; }, stop() {}, async drainInput() {}, write() {}, moveBy() {}, + hideCursor() {}, showCursor() {}, clearLine() {}, clearFromCursor() {}, + clearScreen() {}, setTitle() {}, setProgress() {}, + }; + const tui = new TuiAltScreen(terminal, false, undefined, { copyOnSelect: false }); + const root = new Container(); + const widgets = new Container(); + const theme = { borderColor: (s: string) => s, selectList: { + selectedPrefix: (s: string) => s, selectedText: (s: string) => s, + description: (s: string) => s, scrollInfo: (s: string) => s, noMatch: (s: string) => s, + } }; + const keys = { matches: () => false } as unknown as ConstructorParameters[2]; + const editor = new CustomEditor(tui, theme, keys); + editor.setText("Keep my draft."); + let submitted = 0; + editor.onSubmit = () => { submitted++; }; + root.addChild(widgets); root.addChild(editor); + tui.setLayoutRoot(root); tui.setFocus(editor); tui.start(); + let widget: Component | undefined; + const ui = { + notify() {}, + setWidget(_name: string, factory: ((tui: TuiAltScreen) => Component) | undefined) { + widgets.clear(); widget = factory?.(tui); + if (widget) widgets.addChild(widget); + tui.renderNow(); + }, + onTerminalInput: tui.addInputListener.bind(tui), + getEditorText: () => editor.getExpandedText(), + pasteToEditor(text: string) { editor.handleInput(`\x1b[200~${text}\x1b[201~`); }, + } as unknown as ExtensionContext["ui"]; + const input = (data: string) => { receive(data); tui.renderNow(); }; + const mouse = (button: number, x: number, y: number, release = false) => input(`\x1b[<${button};${x + 1};${y + 1}${release ? "m" : "M"}`); + return { ui, tui, editor, terminal, input, mouse, + click(x: number, y: number) { mouse(0, x, y); mouse(0, x, y, true); }, + get widget() { return widget; }, get submitted() { return submitted; }, + stop() { tui.stop(); }, + }; +} diff --git a/diffr/packages/pi/tsconfig.json b/diffr/packages/pi/tsconfig.json new file mode 100644 index 000000000..7e8ab6378 --- /dev/null +++ b/diffr/packages/pi/tsconfig.json @@ -0,0 +1,4 @@ +{ + "compilerOptions": { "target": "es2023", "module": "esnext", "moduleResolution": "bundler", "strict": true, "skipLibCheck": true, "noEmit": true, "types": ["node"] }, + "include": ["src", "build.ts"] +} diff --git a/diffr/packages/pi/vitest.config.ts b/diffr/packages/pi/vitest.config.ts new file mode 100644 index 000000000..27f7c25aa --- /dev/null +++ b/diffr/packages/pi/vitest.config.ts @@ -0,0 +1 @@ +export { default } from "../viewer/vitest.config"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d500532f8..292abd854 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -87,7 +87,7 @@ importers: version: 5.9.3 vitest: specifier: 4.1.11 - version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) zod: specifier: 4.6.5 version: 4.6.5 @@ -146,7 +146,38 @@ importers: version: 5.9.3 vitest: specifier: 4.1.11 - version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) + + diffr/packages/pi: + dependencies: + '@diffr/consumer': + specifier: workspace:* + version: link:../consumer + '@diffr/viewer': + specifier: workspace:* + version: link:../viewer + devDependencies: + '@earendil-works/pi-coding-agent': + specifier: 0.99.1 + version: 0.99.1(@aws-sdk/credential-provider-node@3.972.84)(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(@smithy/signature-v4@5.7.4)(ws@8.21.3)(zod@4.6.5) + '@earendil-works/pi-tui': + specifier: 0.99.1 + version: 0.99.1 + '@types/node': + specifier: 24.12.2 + version: 24.12.2 + esbuild: + specifier: 0.28.1 + version: 0.28.1 + typebox: + specifier: 1.3.27 + version: 1.3.27 + typescript: + specifier: 5.9.3 + version: 5.9.3 + vitest: + specifier: 4.1.11 + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) diffr/packages/tui: dependencies: @@ -208,7 +239,7 @@ importers: version: 5.9.3 vitest: specifier: 4.1.11 - version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) packages/agent-plugins/pi: {} @@ -241,13 +272,13 @@ importers: version: 6.0.3 vitest: specifier: 4.1.11 - version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) packages/review: dependencies: '@agentclientprotocol/claude-agent-acp': specifier: 0.84.0 - version: 0.84.0(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5)) + version: 0.84.0(@anthropic-ai/sdk@0.124.0(zod@4.6.5))(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5)) '@agentclientprotocol/codex-acp': specifier: 2.0.0 version: 2.0.0 @@ -347,7 +378,7 @@ importers: version: 6.0.3 vitest: specifier: 4.1.11 - version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) packages/review-protocol: dependencies: @@ -369,7 +400,7 @@ importers: version: 0.28.1 vitest: specifier: 4.1.11 - version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) packages/review-share-protocol: dependencies: @@ -379,7 +410,7 @@ importers: devDependencies: vitest: specifier: 4.1.11 - version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) packages/review/app: dependencies: @@ -443,10 +474,10 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: 6.0.1 - version: 6.0.1(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0)) + version: 6.0.1(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0)) '@vitest/browser-playwright': specifier: 4.1.11 - version: 4.1.11(playwright@1.62.1)(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0))(vitest@4.1.11) + version: 4.1.11(playwright@1.62.1)(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.11) hono: specifier: 4.13.5 version: 4.13.5 @@ -464,10 +495,10 @@ importers: version: 2.3.11 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0) + version: 8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0) vitest: specifier: 4.1.11 - version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) packages/trace-core: dependencies: @@ -501,7 +532,7 @@ importers: version: 6.0.3 vitest: specifier: 4.1.11 - version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) packages/trace-protocol: dependencies: @@ -511,7 +542,7 @@ importers: devDependencies: vitest: specifier: 4.1.11 - version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + version: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) packages: @@ -542,6 +573,15 @@ packages: '@modelcontextprotocol/sdk': ^1.29.0 zod: ^4.0.0 + '@anthropic-ai/sdk@0.124.0': + resolution: {integrity: sha512-cN5O8i9UVxHeOQAzj/XjshWXG8KiibJDw9OGpH2Z/eR3n/RBxdoLxDJOcfqAJWvjaMDFfHTBADU04hWRJVkDyA==} + hasBin: true + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + '@asamuzakjp/css-color@5.1.11': resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -557,6 +597,86 @@ packages: '@asamuzakjp/nwsapi@2.3.9': resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@aws-sdk/client-bedrock-runtime@3.1127.0': + resolution: {integrity: sha512-IDl/lrPb90aH+pZFHGNDmgH9nAUQj5PlZH1sJ3w7RikctyjHSnY3oNjZhrLoaBoQn/rNK0zsP6OHEqEhj2tdLA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.978.1': + resolution: {integrity: sha512-LbY9aGsEiznDWmUc30Nwv3aIX/+dbwTx8KfS0yOC3NPYMO+O91e6jkT1azf34FwjOndq8/Q+RcVVZz5xnerwdg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.72': + resolution: {integrity: sha512-xTKO/FWJPozTIXbozVnVGoNBhaGba8TBcx+KyUjRVeOlXE+dUc7GTR1cLvu0uTdIdmemzaFbqqCshXeZA1fZew==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-http@3.972.74': + resolution: {integrity: sha512-u91E/hT8f4d1xy0Jl7VG4nVKJ3lxbrZkoBTeSVoJdWBiSEUMwMS/9+e0H/aJVQV//Lt5wuzP+E69v4aRSsNTmw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-ini@3.973.17': + resolution: {integrity: sha512-ged4KXdBkvIC81bLvNHHuQKdKak/VXhQTR1NWYTTqW0474nlmsxy9O/vlgTIohDDWH3xpBdtVMZRyjb+DnocDA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.79': + resolution: {integrity: sha512-L+Z85anONJd8MaiuraO4wRxATCdEejBZ3K3eymzWI5JPXa9sOS9CkIm72PBKqXKX+Z9p9NGMX5AIMXm0LEflgw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-node@3.972.84': + resolution: {integrity: sha512-oHt854odINVwzwsh+c5x69j0ajm4DbqqqVJ+O1ECsCIZeMDAbzFpXItaqP7UZstJj/ATdTk/KFSH0LaNAgV+kA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-process@3.972.72': + resolution: {integrity: sha512-rLIp2xbMjX/k9/od7APpqq1ZgXXnV0pOL1Th3ZsL8Wu0TRtBsDTVS8iPqcfRFcHakFxPvR04OSTv2ka2qOb/2A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-sso@3.973.16': + resolution: {integrity: sha512-IGihaJfFZYacJJr/odqILCoK7W/mvrZ7cuK7ECn3sAu4vLC6u0V8bS7mCGbdugJ8Aum2tnvqmx0F2MRFp2rn9g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.972.78': + resolution: {integrity: sha512-/y9WvNtlcPBGLR0qc1a+9J/xtYZfVczvLUOuXaVWylzttH7ewsxwHtjmiJSolNrVSDorIxHGHMU61CbonRkmwA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/eventstream-handler-node@3.972.35': + resolution: {integrity: sha512-a8xilRoRaalvSPZdfrs0VY3/BPc0uYhXW56Z/k6nmZ5Vk430LHeowf9APIPq8utM3tMJSNGSSuJMlB9YrPsN+A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-eventstream@3.972.30': + resolution: {integrity: sha512-B6gvZlcnRBNWraKgyEjKsbhv+VjtbyHmpU7hmtTHzXpDSxHPpCJnYLpglEOOsF+SFne20DbZC5IVC1aNr2Pb4A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-websocket@3.972.54': + resolution: {integrity: sha512-bhESdru8u8KosziH8jcVta/NM/dNreeRz2+2aU86si5bfBYOiJ6IiqD+9U4URUcU5WJO3Yw+jO3GLDIHlscXMQ==} + engines: {node: '>= 14.0.0'} + + '@aws-sdk/nested-clients@3.997.46': + resolution: {integrity: sha512-oRxtBcka/JGHGs9l9p9IVajGoTP8vTPmoAzdHGy4Qcy9P5vPnDf6nhIeM/COQNY9k/OahImTRaLkHftoXvfcmQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.996.47': + resolution: {integrity: sha512-Zk08macMvQTHzQJCLJVkOlviVoqwYMrpXv4lmLN7b7sAbiMoOK7Go0NYdR5UeF+MW8LIbRmwrNy9u/5VvX1U5g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1127.0': + resolution: {integrity: sha512-Dv2TMWBshJ+tF6ahs2Sy5bh4Iabsd4GAQqVvE9XZmYmnoaVbpS2QKIKE/HRacc7bTtbjEEvP+laGzHvHlf1CiQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1138.0': + resolution: {integrity: sha512-GpyAr0DD63YOEmYFM6Df+gJuIgC92MMTiBK4FTKfxii5MJ9ge20epR7LyroulscYlG89J+ZB2ivFDPjvfQhzdw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.974.6': + resolution: {integrity: sha512-v/clNZzZnDxGyvpHMOGpJKVXFAExJzUNAAjaWGdcx8QAcXLGwTaOkw33p5SHAi0YAioK32xB3hWwOekRVfmfKg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/xml-builder@3.972.41': + resolution: {integrity: sha512-ctjVSyCMegrWfXlx6VqzSBFI6UqmQ5ZlnfMhdLIiWmhoH8UAQxSCP5N3OpG7X3k4LnS7ou74C4mt20+bfTW2aQ==} + engines: {node: '>=20.0.0'} + + '@aws/lambda-invoke-store@0.3.0': + resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} @@ -634,6 +754,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + '@babel/template@7.29.7': resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} @@ -719,6 +843,40 @@ packages: '@dual-bundle/import-meta-resolve@4.2.1': resolution: {integrity: sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==} + '@earendil-works/chord@0.99.2': + resolution: {integrity: sha512-2dJWiNsOJm/ioBl1fhpJmw0hIjFUhM0CAteEnVkiVG0Kg4LimR7Asq8PfjclEvrbCPsDntzy7rGKhTZObI9TZw==} + engines: {node: '>=22.19.0'} + + '@earendil-works/pi-agent-core@0.99.2': + resolution: {integrity: sha512-VX0QMcg8HKBsv1bYP2NwmutBYa44OrwmtqR6Dq7QC3Ln8X/IlpHhUxB5L1JgnXNUUkTm8Wg/HZhzS797NBDMCQ==} + engines: {node: '>=22.19.0'} + + '@earendil-works/pi-ai@0.99.2': + resolution: {integrity: sha512-9RFOEdY+ZTJ1AI+UuAFs4RM0tF2Tje/R/CEv9gWTJHt0iTu8XHZs64U/EIZxNSllFmec/4HfwsOxYj1qQek9bg==} + engines: {node: '>=22.19.0'} + hasBin: true + + '@earendil-works/pi-codemode@0.99.2': + resolution: {integrity: sha512-PVxNGu4l7LI92MvwUbaY3trjznU1Mlp2OMGwHwCWzLsjG7/lDa8xf6ei+Gws7VCt+Ri1tO+nFVl9KV2EeX7HWg==} + engines: {node: '>=22.19.0'} + + '@earendil-works/pi-coding-agent@0.99.1': + resolution: {integrity: sha512-cWUrTOqA5M73cOYMgsh9PlhDrsBhavd+n5kVY6F7BGbGl1RjqCteVCoeVMVqhngoGACVDyw1tbLjajL8l9jrHg==} + engines: {node: '>=22.19.0'} + hasBin: true + + '@earendil-works/pi-mcp@0.99.2': + resolution: {integrity: sha512-ISk6OIsiUzmULF+sUilLnENGKo9/gVDxZG2CTEq8f4dbp70AXOr/hMiwOjtcrlX6xBd4UMUsIz4EPTOlU6U+HA==} + engines: {node: '>=22.19.0'} + + '@earendil-works/pi-telemetry@0.99.2': + resolution: {integrity: sha512-WThYU4XM6jjjzH4FzLdreN7QAPS9SDdokL0W0Ldheg1ssCIJkfpK7PgebFm7/PoQub7OiXx+SRF6B/oF7z7lXA==} + engines: {node: '>=22.19.0'} + + '@earendil-works/pi-tui@0.99.1': + resolution: {integrity: sha512-gZp0Guat96Fr1AuC/xqVz5B2lulZakp/PxD1lXx3lSgBdjiqmwYhJbcQ0HRrGAfy0WtMGn9b05RJr5qJf7oIuw==} + engines: {node: '>=22.19.0'} + '@emnapi/core@1.10.0': resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} @@ -896,6 +1054,15 @@ packages: '@noble/hashes': optional: true + '@google/genai@2.21.0': + resolution: {integrity: sha512-+PDtco2/Z0ONdzCGekCoCT+O1VJS9xJQNN4XzQpXG/t3El/SWWMkCWlFRO1KmivOHPa4Q0VjUYu1HBKCZ/v33Q==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.25.2 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + '@hono/node-server@2.0.12': resolution: {integrity: sha512-eWpQYr67tqJLeaSUl0Q+TquuYfUdTibpOJlUMV2FfUP7+KqCC5TufnwnlXL6mobZBJbGAYRd7ZvEBDCbLInjhg==} engines: {node: '>=20'} @@ -1281,6 +1448,33 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@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.1': + resolution: {integrity: sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==} + + '@protobufjs/fetch@1.1.1': + resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@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.2': + resolution: {integrity: sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==} + '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} @@ -1475,9 +1669,39 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + '@silvia-odwyer/photon-node@0.3.4': + resolution: {integrity: sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==} + + '@smithy/core@3.35.1': + resolution: {integrity: sha512-i4YPS4B6ts7bjn7UwLnGjiZdprOvHvgGobFZsYK3GIY3E5hIqtj0rReU69BcTpGp+fvtraSNXeG1l+jtJvF55w==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.5.2': + resolution: {integrity: sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.8.0': + resolution: {integrity: sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.12.1': + resolution: {integrity: sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.7.4': + resolution: {integrity: sha512-tHy0K0VtqNd5Y7Y41h0a0Lhh0L1GzC08dTWg0F7vRJWFtTENg7IZikf3wQkanYIRdb7ngoIPMTmqgUi401fEeQ==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.19.0': + resolution: {integrity: sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==} + engines: {node: '>=18.0.0'} + '@speed-highlight/core@1.2.15': resolution: {integrity: sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==} + '@stablelib/base64@1.0.1': + resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==} + '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -1572,6 +1796,9 @@ packages: '@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/retry@0.12.5': resolution: {integrity: sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==} @@ -1931,6 +2158,14 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + agent-base@9.0.0: + resolution: {integrity: sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==} + engines: {node: '>= 20'} + ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} @@ -1953,6 +2188,13 @@ packages: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + baseline-browser-mapping@2.11.25: resolution: {integrity: sha512-gMmEShwwq7FJqMwvfRwvCl00v4kN+KOfJqXn+f4nrufak5gNHJOksd/60Dvjuz7sI8Y5WiSFBa8FEYr+zoyqCw==} engines: {node: '>=6.0.0'} @@ -1961,15 +2203,28 @@ packages: bidi-js@1.1.0: resolution: {integrity: sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==} + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + body-parser@2.3.0: resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} engines: {node: '>=18'} + bowser@2.14.1: + resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} + + brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} + browserslist@4.29.0: resolution: {integrity: sha512-3GSvyjvDI4Dur1Meg2BekJquu5uF+9R9a1+5M1Mde192eZoXbeXjzgOsgqPS2V8D5wrrip0gR5Hf/GhWQ9ZzaA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + bun-ffi-structs@0.3.1: resolution: {integrity: sha512-3gM7PpVWLyrwxWjcilSiGuhWanhZivvo6l0u573NziPH6f/gwk6McbaYgn7oJWov6pKGRTDbrg94W5DcJsKTtQ==} peerDependencies: @@ -2008,6 +2263,10 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + chalk@6.0.0: + resolution: {integrity: sha512-2uNTXIuTTxk7ciZgAU1BQcgnchcG0xXnrs6jzkQfj9SsRa9M2s5zE8WT96hS6KmG4MzWHSrvH43DF1m4XRkrFg==} + engines: {node: '>=22'} + character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} @@ -2108,6 +2367,10 @@ packages: resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} engines: {node: '>=12'} + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + data-urls@7.0.0: resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -2160,6 +2423,10 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} + engines: {node: '>=0.3.1'} + diff@9.0.0: resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==} engines: {node: '>=0.3.1'} @@ -2177,6 +2444,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -2264,6 +2534,9 @@ packages: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + fast-copy@4.0.4: resolution: {integrity: sha512-eVAiWVNPSEGIzDl5yPuLrx8fNMogScXvD9xp1Kzd41FjRIz2I3sSIcxsFeM5EzFfHAfobdvs8ZySffUopljvIA==} @@ -2273,6 +2546,9 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + fast-sha256@1.3.0: + resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==} + fast-uri@3.1.8: resolution: {integrity: sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==} @@ -2285,10 +2561,18 @@ packages: picomatch: optional: true + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + finalhandler@2.1.1: resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} engines: {node: '>= 18.0.0'} + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -2313,6 +2597,14 @@ packages: fuzzysort@4.0.2: resolution: {integrity: sha512-3c7yD6rK1EXIsqpcu1ZVzXJugODWNMzvUij6yTiziaAHrpNS8kzFOI9mJLE8pmG4K9JOaVgzQRgklfOEk8f4Tg==} + gaxios@7.3.1: + resolution: {integrity: sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==} + engines: {node: '>=18'} + + gcp-metadata@8.1.2: + resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} + engines: {node: '>=18'} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -2321,6 +2613,10 @@ packages: resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} engines: {node: '>=18'} + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} + engines: {node: '>=18'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -2342,6 +2638,14 @@ packages: git-url-parse@16.1.0: resolution: {integrity: sha512-cPLz4HuK86wClEW7iDdeAKcCVlWXmrLpb2L+G9goW0Z1dtpNS6BXXSOckUTlJT/LDQViE1QZKstNORzHsLnobw==} + google-auth-library@10.9.1: + resolution: {integrity: sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==} + engines: {node: '>=18'} + + 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'} @@ -2349,6 +2653,10 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + grok-mermaid@0.2.3: + resolution: {integrity: sha512-/4KopAbsjvuRP9MdPtlDjOHUmUVEohOX73JNcsWpzAtFxh+bq5+Dhb6gzvRieLDwIPQIR3/vy8V1NNTuz4Zsmg==} + engines: {node: '>=18'} + has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} @@ -2360,6 +2668,9 @@ packages: help-me@5.0.0: resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + hono@4.13.5: resolution: {integrity: sha512-O6+/eCYRkzzzy0rPWwKLiGBR1nFuUPZynnwjxN1MBA62NNqbT0wQEzQyK2gSO5yDIDB336sXQleAhOHrzlYyKw==} engines: {node: '>=16.9.0'} @@ -2367,6 +2678,10 @@ packages: hookable@6.1.1: resolution: {integrity: sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==} + hosted-git-info@9.0.3: + resolution: {integrity: sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==} + engines: {node: ^20.17.0 || >=22.9.0} + html-encoding-sniffer@6.0.0: resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -2375,10 +2690,26 @@ packages: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} + http-proxy-agent@9.1.0: + resolution: {integrity: sha512-2NxoveTT58mjYT4n3RPTEfCZGLMbidoO8XEieXfpSYxu+PQJ1qpx4ypwH6N+uF9twBPIvRRgvkvW5HUTYWENig==} + engines: {node: '>= 20'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + https-proxy-agent@9.1.0: + resolution: {integrity: sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==} + engines: {node: '>= 20'} + iconv-lite@0.7.3: resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} engines: {node: '>=0.10.0'} + ignore@7.0.8: + resolution: {integrity: sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==} + engines: {node: '>= 4'} + import-without-cache@0.4.0: resolution: {integrity: sha512-NkJQA7oZ4YHQhd2+H3BoRFKF3d/XNsiKpHZCQEMH9pDX27hQQLsTyOocyRgaIVtf8gHX3Nt3LPkR4e5EdtPAGQ==} engines: {node: ^22.18.0 || >=24.0.0} @@ -2427,6 +2758,10 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + jose@6.2.12: resolution: {integrity: sha512-9NiFmJEex0sy2Dk58j2UGBSHgUs2ypF9eZSu4L6vjOX3Dp96Sw1F3uL+H+D1sx02jZZdzUT0HgvCy59CuvXcWw==} @@ -2451,6 +2786,13 @@ packages: engines: {node: '>=6'} hasBin: true + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-schema-to-ts@3.1.1: + resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==} + engines: {node: '>=16'} + json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} @@ -2462,6 +2804,12 @@ packages: engines: {node: '>=6'} hasBin: true + 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==} + katex@0.16.47: resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==} hasBin: true @@ -2547,6 +2895,9 @@ packages: resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -2572,6 +2923,11 @@ packages: engines: {node: '>= 20'} hasBin: true + marked@18.0.11: + resolution: {integrity: sha512-HnslJfsZkRPBDJRHvVtAaWlZHEpSu7u8LgQuJCELjRKuWR+hpq4A7sLq3p8HaI9ypVoXDXxV34CsQJEe1+J5Aw==} + engines: {node: '>= 20'} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -2718,6 +3074,10 @@ packages: resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} engines: {node: '>=18'} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} @@ -2737,6 +3097,15 @@ packages: resolution: {integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==} engines: {node: '>=18'} + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + node-releases@2.0.56: resolution: {integrity: sha512-x0InOIyzgdk+eyaWaRJFH5snEtiImgBgblZ2CyPrLmqqcuMQkEvcDPHbzqbD8eDsSeJbVOjn+crzyzHaM4D+/A==} engines: {node: '>=18'} @@ -2768,6 +3137,30 @@ packages: resolution: {integrity: sha512-++Zlftm0kVLPmzC06t6epuWmcRMDbI4z5P3NNX979WA/k23+NtSOynEGzsVfZwguKw2mi5umVgnBlJQMwRz4Pg==} engines: {node: '>=20'} + openai@7.19.0: + resolution: {integrity: sha512-MX2s3u2L5racTO0CC/SWpCOasJQBCJrqLKXK+l82cAhdeF8mPMBEe/gxMm0ZFa2xpKpOFLRjxv5afYEZbBXmbQ==} + engines: {node: '>=22.0.0'} + peerDependencies: + '@aws-sdk/credential-provider-node': '>=3.972.0 <4' + '@smithy/hash-node': '>=4.3.0 <5' + '@smithy/signature-v4': '>=5.4.0 <6' + undici: 7.29.1 + ws: ^8.21.0 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + '@aws-sdk/credential-provider-node': + optional: true + '@smithy/hash-node': + optional: true + '@smithy/signature-v4': + optional: true + undici: + optional: true + ws: + optional: true + zod: + optional: true + oxfmt@0.48.0: resolution: {integrity: sha512-AVaLh+7XeGx+R1zfFV+f6VV61nT2MWVJXVUDhbTm5LBWGyNt64xAyh3NYYyjeY2WykNt9AvqSQLPHcbWquYF9g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2783,6 +3176,10 @@ packages: oxlint-tsgolint: optional: true + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + parse-path@7.1.0: resolution: {integrity: sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==} @@ -2797,6 +3194,9 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} + partial-json@0.1.7: + resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2872,6 +3272,10 @@ packages: proper-lockfile@4.1.2: resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + protobufjs@7.6.6: + resolution: {integrity: sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==} + engines: {node: '>=12.0.0'} + protocols@2.0.2: resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==} @@ -2879,6 +3283,15 @@ packages: resolution: {integrity: sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==} engines: {node: '>= 0.10'} + proxy-agent-negotiate@1.1.0: + resolution: {integrity: sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ==} + engines: {node: '>= 20'} + peerDependencies: + kerberos: ^2.0.0 + peerDependenciesMeta: + kerberos: + optional: true + pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} @@ -2896,6 +3309,9 @@ packages: quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + quickjs-wasi@3.6.2: + resolution: {integrity: sha512-FCqGtGOrMgzUiIrMNMA2YnsOxCNwo31dzqXvclXUC6xeT35NJLKXQJsvbeCTjvoFAwZgEAPg8U6+KAPDGXn8Mg==} + range-parser@1.3.0: resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==} engines: {node: '>= 0.6'} @@ -2944,6 +3360,10 @@ packages: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + rolldown-plugin-dts@0.27.14: resolution: {integrity: sha512-ZvuDDwoIpRK9RPxDXratCpklFO9QZZWndf/sd0VBFb4LEj0jj07UcHK9OCh7V4XiFz2Z89ziyBC2K6tJiDjrbw==} engines: {node: ^22.18.0 || >=24.11.0} @@ -2981,6 +3401,9 @@ packages: resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} engines: {node: '>=18'} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-stable-stringify@2.5.0: resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} engines: {node: '>=10'} @@ -3083,6 +3506,9 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + standardwebhooks@1.1.1: + resolution: {integrity: sha512-bCbX9ZEyFkWPsRz7Bl3NuQUJohmwGSev/yhr7vhaGPlc4AfIrspIRa6cPTBuI1ItmrTDJ4d/S2hCsfe4+vQGnQ==} + statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} @@ -3166,6 +3592,9 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true + ts-algebra@2.0.0: + resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} + tsdown@0.22.14: resolution: {integrity: sha512-ule7Y+fsAN2iZbLDoo7C4KYljFJNJJ+fLshyn+9gozeTspVersWHxwdGB+Dm2hzA38s6muFnUTl0jK3vJm9ifQ==} engines: {node: ^22.18.0 || >=24.11.0} @@ -3212,6 +3641,9 @@ packages: resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} engines: {node: '>= 18'} + typebox@1.3.27: + resolution: {integrity: sha512-zu+jc1pcy4UiNThxikUr36f0Rybk9PEeCg/NE6adeWr/SKsdNO4EzZHYRDlv2YCVAfj3Odq3dESSo/jNyoBXzA==} + typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -3370,6 +3802,10 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + web-tree-sitter@0.25.10: resolution: {integrity: sha512-Y09sF44/13XvgVKgO2cNDw5rGk6s26MgoZPXLESvMXeefBf7i6/73eFurre0IsTW6E14Y0ArIzhUMmjoc7xyzA==} peerDependencies: @@ -3444,6 +3880,11 @@ packages: 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 + yuku-ast@0.8.4: resolution: {integrity: sha512-s7EWfWIQkaGmsGnyr/BU0jli9YTN5TvrKIsSmALyRD9elumDQInuhv0BrVObENKVCxr9W3Ikmnx5u02KvfuUmw==} @@ -3510,10 +3951,10 @@ ignoredOptionalDependencies: snapshots: - '@agentclientprotocol/claude-agent-acp@0.84.0(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))': + '@agentclientprotocol/claude-agent-acp@0.84.0(@anthropic-ai/sdk@0.124.0(zod@4.6.5))(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))': dependencies: '@agentclientprotocol/sdk': 1.5.1(zod@4.6.5) - '@anthropic-ai/claude-agent-sdk': 0.3.284(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(zod@4.6.5) + '@anthropic-ai/claude-agent-sdk': 0.3.284(@anthropic-ai/sdk@0.124.0(zod@4.6.5))(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(zod@4.6.5) diff: 9.0.0 zod: 4.6.5 transitivePeerDependencies: @@ -3537,11 +3978,19 @@ snapshots: dependencies: zod: 4.6.5 - '@anthropic-ai/claude-agent-sdk@0.3.284(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(zod@4.6.5)': + '@anthropic-ai/claude-agent-sdk@0.3.284(@anthropic-ai/sdk@0.124.0(zod@4.6.5))(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(zod@4.6.5)': dependencies: + '@anthropic-ai/sdk': 0.124.0(zod@4.6.5) '@modelcontextprotocol/sdk': 1.31.0(zod@4.6.5) zod: 4.6.5 + '@anthropic-ai/sdk@0.124.0(zod@4.6.5)': + dependencies: + json-schema-to-ts: 3.1.1 + standardwebhooks: 1.1.1 + optionalDependencies: + zod: 4.6.5 + '@asamuzakjp/css-color@5.1.11': dependencies: '@asamuzakjp/generational-cache': 1.0.1 @@ -3562,6 +4011,188 @@ snapshots: '@asamuzakjp/nwsapi@2.3.9': {} + '@aws-sdk/client-bedrock-runtime@3.1127.0': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/credential-provider-node': 3.972.84 + '@aws-sdk/eventstream-handler-node': 3.972.35 + '@aws-sdk/middleware-eventstream': 3.972.30 + '@aws-sdk/middleware-websocket': 3.972.54 + '@aws-sdk/token-providers': 3.1127.0 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/core@3.978.1': + dependencies: + '@aws-sdk/types': 3.974.6 + '@aws-sdk/xml-builder': 3.972.41 + '@aws/lambda-invoke-store': 0.3.0 + '@smithy/core': 3.35.1 + '@smithy/signature-v4': 5.7.4 + '@smithy/types': 4.19.0 + bowser: 2.14.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.72': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.74': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.973.17': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/credential-provider-env': 3.972.72 + '@aws-sdk/credential-provider-http': 3.972.74 + '@aws-sdk/credential-provider-login': 3.972.79 + '@aws-sdk/credential-provider-process': 3.972.72 + '@aws-sdk/credential-provider-sso': 3.973.16 + '@aws-sdk/credential-provider-web-identity': 3.972.78 + '@aws-sdk/nested-clients': 3.997.46 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/credential-provider-imds': 4.5.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-login@3.972.79': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/nested-clients': 3.997.46 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-node@3.972.84': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.72 + '@aws-sdk/credential-provider-http': 3.972.74 + '@aws-sdk/credential-provider-ini': 3.973.17 + '@aws-sdk/credential-provider-process': 3.972.72 + '@aws-sdk/credential-provider-sso': 3.973.16 + '@aws-sdk/credential-provider-web-identity': 3.972.78 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/credential-provider-imds': 4.5.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-process@3.972.72': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.973.16': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/nested-clients': 3.997.46 + '@aws-sdk/token-providers': 3.1138.0 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-web-identity@3.972.78': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/nested-clients': 3.997.46 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/eventstream-handler-node@3.972.35': + dependencies: + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-eventstream@3.972.30': + dependencies: + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-websocket@3.972.54': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/signature-v4': 5.7.4 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.997.46': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/signature-v4-multi-region': 3.996.47 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.996.47': + dependencies: + '@aws-sdk/types': 3.974.6 + '@smithy/signature-v4': 5.7.4 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1127.0': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/nested-clients': 3.997.46 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1138.0': + dependencies: + '@aws-sdk/core': 3.978.1 + '@aws-sdk/nested-clients': 3.997.46 + '@aws-sdk/types': 3.974.6 + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/types@3.974.6': + dependencies: + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.972.41': + dependencies: + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.3.0': {} + '@babel/code-frame@7.29.7': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -3656,6 +4287,8 @@ snapshots: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 + '@babel/runtime@7.29.7': {} + '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 @@ -3726,6 +4359,108 @@ snapshots: '@dual-bundle/import-meta-resolve@4.2.1': {} + '@earendil-works/chord@0.99.2': + dependencies: + esbuild: 0.28.1 + + '@earendil-works/pi-agent-core@0.99.2(@aws-sdk/credential-provider-node@3.972.84)(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(@smithy/signature-v4@5.7.4)(undici@7.29.1)(ws@8.21.3)(zod@4.6.5)': + dependencies: + '@earendil-works/chord': 0.99.2 + '@earendil-works/pi-ai': 0.99.2(@aws-sdk/credential-provider-node@3.972.84)(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(@smithy/signature-v4@5.7.4)(undici@7.29.1)(ws@8.21.3)(zod@4.6.5) + '@earendil-works/pi-telemetry': 0.99.2 + diff: 8.0.4 + ignore: 7.0.8 + typebox: 1.3.27 + yaml: 2.9.0 + transitivePeerDependencies: + - '@aws-sdk/credential-provider-node' + - '@modelcontextprotocol/sdk' + - '@smithy/hash-node' + - '@smithy/signature-v4' + - bufferutil + - kerberos + - supports-color + - undici + - utf-8-validate + - ws + - zod + + '@earendil-works/pi-ai@0.99.2(@aws-sdk/credential-provider-node@3.972.84)(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(@smithy/signature-v4@5.7.4)(undici@7.29.1)(ws@8.21.3)(zod@4.6.5)': + dependencies: + '@anthropic-ai/sdk': 0.124.0(zod@4.6.5) + '@aws-sdk/client-bedrock-runtime': 3.1127.0 + '@earendil-works/pi-telemetry': 0.99.2 + '@google/genai': 2.21.0(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5)) + '@smithy/node-http-handler': 4.12.1 + http-proxy-agent: 9.1.0 + https-proxy-agent: 9.1.0 + openai: 7.19.0(@aws-sdk/credential-provider-node@3.972.84)(@smithy/signature-v4@5.7.4)(undici@7.29.1)(ws@8.21.3)(zod@4.6.5) + partial-json: 0.1.7 + typebox: 1.3.27 + transitivePeerDependencies: + - '@aws-sdk/credential-provider-node' + - '@modelcontextprotocol/sdk' + - '@smithy/hash-node' + - '@smithy/signature-v4' + - bufferutil + - kerberos + - supports-color + - undici + - utf-8-validate + - ws + - zod + + '@earendil-works/pi-codemode@0.99.2': + dependencies: + quickjs-wasi: 3.6.2 + + '@earendil-works/pi-coding-agent@0.99.1(@aws-sdk/credential-provider-node@3.972.84)(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(@smithy/signature-v4@5.7.4)(ws@8.21.3)(zod@4.6.5)': + dependencies: + '@earendil-works/chord': 0.99.2 + '@earendil-works/pi-agent-core': 0.99.2(@aws-sdk/credential-provider-node@3.972.84)(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(@smithy/signature-v4@5.7.4)(undici@7.29.1)(ws@8.21.3)(zod@4.6.5) + '@earendil-works/pi-ai': 0.99.2(@aws-sdk/credential-provider-node@3.972.84)(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))(@smithy/signature-v4@5.7.4)(undici@7.29.1)(ws@8.21.3)(zod@4.6.5) + '@earendil-works/pi-codemode': 0.99.2 + '@earendil-works/pi-mcp': 0.99.2 + '@earendil-works/pi-tui': 0.99.1 + '@silvia-odwyer/photon-node': 0.3.4 + chalk: 6.0.0 + cross-spawn: 7.0.6 + diff: 8.0.4 + grok-mermaid: 0.2.3 + highlight.js: 10.7.3 + hosted-git-info: 9.0.3 + ignore: 7.0.8 + jiti: 2.7.0 + minimatch: 10.2.6 + proper-lockfile: 4.1.2 + quickjs-wasi: 3.6.2 + semver: 7.8.5 + typebox: 1.3.27 + undici: 7.29.1 + yaml: 2.9.0 + transitivePeerDependencies: + - '@aws-sdk/credential-provider-node' + - '@modelcontextprotocol/sdk' + - '@smithy/hash-node' + - '@smithy/signature-v4' + - bufferutil + - kerberos + - supports-color + - utf-8-validate + - ws + - zod + + '@earendil-works/pi-mcp@0.99.2': + dependencies: + cross-spawn: 7.0.6 + + '@earendil-works/pi-telemetry@0.99.2': {} + + '@earendil-works/pi-tui@0.99.1': + dependencies: + get-east-asian-width: 1.6.0 + marked: 18.0.11 + '@emnapi/core@1.10.0': dependencies: '@emnapi/wasi-threads': 1.2.1 @@ -3826,6 +4561,19 @@ snapshots: '@exodus/bytes@1.15.1': {} + '@google/genai@2.21.0(@modelcontextprotocol/sdk@1.31.0(zod@4.6.5))': + dependencies: + google-auth-library: 10.9.1 + p-retry: 4.6.2 + protobufjs: 7.6.6 + ws: 8.21.3 + optionalDependencies: + '@modelcontextprotocol/sdk': 1.31.0(zod@4.6.5) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + '@hono/node-server@2.0.12(hono@4.13.5)': dependencies: hono: 4.13.5 @@ -4081,6 +4829,26 @@ snapshots: '@polka/url@1.0.0-next.29': {} + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.5': {} + + '@protobufjs/eventemitter@1.1.1': {} + + '@protobufjs/fetch@1.1.1': + dependencies: + '@protobufjs/aspromise': 1.1.2 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.2': {} + '@quansync/fs@1.0.0': dependencies: quansync: 1.0.0 @@ -4180,8 +4948,45 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} + '@silvia-odwyer/photon-node@0.3.4': {} + + '@smithy/core@3.35.1': + dependencies: + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.5.2': + dependencies: + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.8.0': + dependencies: + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.12.1': + dependencies: + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.7.4': + dependencies: + '@smithy/core': 3.35.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/types@4.19.0': + dependencies: + tslib: 2.8.1 + '@speed-highlight/core@1.2.15': {} + '@stablelib/base64@1.0.1': {} + '@standard-schema/spec@1.1.0': {} '@stylexjs/babel-plugin@0.19.1': @@ -4304,6 +5109,8 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/retry@0.12.0': {} + '@types/retry@0.12.5': {} '@types/semver@7.7.1': {} @@ -4370,34 +5177,34 @@ snapshots: '@typescript/typescript-win32-x64@7.0.2': optional: true - '@vitejs/plugin-react@6.0.1(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0))': + '@vitejs/plugin-react@6.0.1(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.7 - vite: 8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0) + vite: 8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0) - '@vitest/browser-playwright@4.1.11(playwright@1.62.1)(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0))(vitest@4.1.11)': + '@vitest/browser-playwright@4.1.11(playwright@1.62.1)(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.11)': dependencies: - '@vitest/browser': 4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0))(vitest@4.1.11) - '@vitest/mocker': 4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0)) + '@vitest/browser': 4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/mocker': 4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0)) playwright: 1.62.1 tinyrainbow: 3.1.1 - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/browser@4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0))(vitest@4.1.11)': + '@vitest/browser@4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.11)': dependencies: '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0)) + '@vitest/mocker': 4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0)) '@vitest/utils': 4.1.11 magic-string: 0.30.21 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.1.1 - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0) ws: 8.21.3 transitivePeerDependencies: - bufferutil @@ -4414,13 +5221,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.1 - '@vitest/mocker@4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0))': + '@vitest/mocker@4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.11 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0) + vite: 8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0) '@vitest/pretty-format@4.1.11': dependencies: @@ -4550,6 +5357,10 @@ snapshots: acorn@8.18.0: {} + agent-base@7.1.4: {} + + agent-base@9.0.0: {} + ajv-formats@3.0.1: dependencies: ajv: 8.20.0 @@ -4569,12 +5380,18 @@ snapshots: atomic-sleep@1.0.0: {} + balanced-match@4.0.4: {} + + base64-js@1.5.1: {} + baseline-browser-mapping@2.11.25: {} bidi-js@1.1.0: dependencies: require-from-string: 2.0.2 + bignumber.js@9.3.1: {} + body-parser@2.3.0: dependencies: bytes: 3.1.2 @@ -4589,6 +5406,12 @@ snapshots: transitivePeerDependencies: - supports-color + bowser@2.14.1: {} + + brace-expansion@5.0.12: + dependencies: + balanced-match: 4.0.4 + browserslist@4.29.0: dependencies: baseline-browser-mapping: 2.11.25 @@ -4597,6 +5420,8 @@ snapshots: node-releases: 2.0.56 update-browserslist-db: 1.3.3(browserslist@4.29.0) + buffer-equal-constant-time@1.0.1: {} + bun-ffi-structs@0.3.1(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -4629,6 +5454,8 @@ snapshots: chai@6.2.2: {} + chalk@6.0.0: {} + character-entities@2.0.2: {} classcat@5.0.5: {} @@ -4709,6 +5536,8 @@ snapshots: d3-selection: 3.0.0 d3-transition: 3.0.1(d3-selection@3.0.0) + data-uri-to-buffer@4.0.1: {} + data-urls@7.0.0: dependencies: whatwg-mimetype: 5.0.0 @@ -4749,6 +5578,8 @@ snapshots: dependencies: dequal: 2.0.3 + diff@8.0.4: {} + diff@9.0.0: {} dts-resolver@3.0.0: {} @@ -4759,6 +5590,10 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + ee-first@1.1.1: {} electron-to-chromium@1.5.434: {} @@ -4877,18 +5712,27 @@ snapshots: transitivePeerDependencies: - supports-color + extend@3.0.2: {} + fast-copy@4.0.4: {} fast-deep-equal@3.1.3: {} fast-safe-stringify@2.1.1: {} + fast-sha256@1.3.0: {} + fast-uri@3.1.8: {} fdir@6.5.0(picomatch@4.0.7): optionalDependencies: picomatch: 4.0.7 + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + finalhandler@2.1.1: dependencies: debug: 4.4.3 @@ -4900,6 +5744,10 @@ snapshots: transitivePeerDependencies: - supports-color + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + forwarded@0.2.0: {} fresh@2.0.0: {} @@ -4914,10 +5762,28 @@ snapshots: fuzzysort@4.0.2: {} + gaxios@7.3.1: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + node-fetch: 3.3.2 + transitivePeerDependencies: + - supports-color + + gcp-metadata@8.1.2: + dependencies: + gaxios: 7.3.1 + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + gensync@1.0.0-beta.2: {} get-east-asian-width@1.4.0: {} + get-east-asian-width@1.6.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -4953,10 +5819,25 @@ snapshots: dependencies: git-up: 8.1.1 + google-auth-library@10.9.1: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.3.1 + gcp-metadata: 8.1.2 + google-logging-utils: 1.1.3 + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + + google-logging-utils@1.1.3: {} + gopd@1.2.0: {} graceful-fs@4.2.11: {} + grok-mermaid@0.2.3: {} + has-symbols@1.1.0: {} hasown@2.0.4: @@ -4965,10 +5846,16 @@ snapshots: help-me@5.0.0: {} + highlight.js@10.7.3: {} + hono@4.13.5: {} hookable@6.1.1: {} + hosted-git-info@9.0.3: + dependencies: + lru-cache: 11.5.2 + html-encoding-sniffer@6.0.0: dependencies: '@exodus/bytes': 1.15.1 @@ -4983,10 +5870,37 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 + http-proxy-agent@9.1.0: + dependencies: + agent-base: 9.0.0 + debug: 4.4.3 + proxy-agent-negotiate: 1.1.0 + transitivePeerDependencies: + - kerberos + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@9.1.0: + dependencies: + agent-base: 9.0.0 + debug: 4.4.3 + proxy-agent-negotiate: 1.1.0 + transitivePeerDependencies: + - kerberos + - supports-color + iconv-lite@0.7.3: dependencies: safer-buffer: 2.1.2 + ignore@7.0.8: {} + import-without-cache@0.4.0: {} inherits@2.0.4: {} @@ -5021,6 +5935,8 @@ snapshots: isexe@2.0.0: {} + jiti@2.7.0: {} + jose@6.2.12: {} joycon@3.1.1: {} @@ -5055,12 +5971,32 @@ snapshots: jsesc@3.1.0: {} + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + + json-schema-to-ts@3.1.1: + dependencies: + '@babel/runtime': 7.29.7 + ts-algebra: 2.0.0 + json-schema-traverse@1.0.0: {} json-schema-typed@8.0.2: {} json5@2.2.3: {} + 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 + katex@0.16.47: dependencies: commander: 8.3.0 @@ -5120,6 +6056,8 @@ snapshots: lightningcss-win32-arm64-msvc: 1.33.0 lightningcss-win32-x64-msvc: 1.33.0 + long@5.3.2: {} + longest-streak@3.1.0: {} loose-envify@1.4.0: @@ -5140,6 +6078,8 @@ snapshots: marked@17.0.1: {} + marked@18.0.11: {} + math-intrinsics@1.1.0: {} mdast-util-find-and-replace@3.0.2: @@ -5469,6 +6409,10 @@ snapshots: dependencies: mime-db: 1.54.0 + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.12 + minimist@1.2.8: {} mrmime@2.0.1: {} @@ -5481,6 +6425,14 @@ snapshots: dependencies: content-type: 2.1.0 + node-domexception@1.0.0: {} + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + node-releases@2.0.56: {} object-assign@4.1.1: {} @@ -5508,6 +6460,14 @@ snapshots: powershell-utils: 0.2.1 wsl-utils: 1.0.0 + openai@7.19.0(@aws-sdk/credential-provider-node@3.972.84)(@smithy/signature-v4@5.7.4)(undici@7.29.1)(ws@8.21.3)(zod@4.6.5): + optionalDependencies: + '@aws-sdk/credential-provider-node': 3.972.84 + '@smithy/signature-v4': 5.7.4 + undici: 7.29.1 + ws: 8.21.3 + zod: 4.6.5 + oxfmt@0.48.0: dependencies: tinypool: 2.2.0 @@ -5554,6 +6514,11 @@ snapshots: '@oxlint/binding-win32-ia32-msvc': 1.63.0 '@oxlint/binding-win32-x64-msvc': 1.63.0 + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + parse-path@7.1.0: dependencies: protocols: 2.0.2 @@ -5569,6 +6534,8 @@ snapshots: parseurl@1.3.3: {} + partial-json@0.1.7: {} + path-key@3.1.1: {} path-to-regexp@8.4.2: {} @@ -5653,6 +6620,20 @@ snapshots: retry: 0.12.0 signal-exit: 3.0.7 + protobufjs@7.6.6: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.1 + '@protobufjs/fetch': 1.1.1 + '@protobufjs/float': 1.0.2 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.2 + '@types/node': 24.12.2 + long: 5.3.2 + protocols@2.0.2: {} proxy-addr@2.0.8: @@ -5660,6 +6641,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-agent-negotiate@1.1.0: {} + pump@3.0.4: dependencies: end-of-stream: 1.4.5 @@ -5676,6 +6659,8 @@ snapshots: quick-format-unescaped@4.0.4: {} + quickjs-wasi@3.6.2: {} + range-parser@1.3.0: {} raw-body@3.0.2: @@ -5717,6 +6702,8 @@ snapshots: retry@0.12.0: {} + retry@0.13.1: {} + rolldown-plugin-dts@0.27.14(rolldown@1.2.3)(typescript@6.0.3): dependencies: dts-resolver: 3.0.0 @@ -5784,6 +6771,8 @@ snapshots: run-applescript@7.1.0: {} + safe-buffer@5.2.1: {} + safe-stable-stringify@2.5.0: {} safer-buffer@2.1.2: {} @@ -5895,6 +6884,11 @@ snapshots: stackback@0.0.2: {} + standardwebhooks@1.1.1: + dependencies: + '@stablelib/base64': 1.0.1 + fast-sha256: 1.3.0 + statuses@2.0.2: {} std-env@4.2.0: {} @@ -5961,6 +6955,8 @@ snapshots: tree-kill@1.2.2: {} + ts-algebra@2.0.0: {} + tsdown@0.22.14(tsx@4.21.0)(typescript@6.0.3): dependencies: ansis: 4.3.1 @@ -6002,6 +6998,8 @@ snapshots: media-typer: 1.1.1 mime-types: 3.0.2 + typebox@1.3.27: {} + typescript@5.9.3: {} typescript@6.0.3: {} @@ -6085,7 +7083,7 @@ snapshots: verkit@0.3.2: {} - vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0): + vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0): dependencies: lightningcss: 1.33.0 picomatch: 4.0.7 @@ -6096,12 +7094,14 @@ snapshots: '@types/node': 24.12.2 esbuild: 0.28.1 fsevents: 2.3.3 + jiti: 2.7.0 tsx: 4.21.0 + yaml: 2.9.0 - vitest@4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jsdom@29.1.1)(tsx@4.21.0): + vitest@4.1.11(@types/node@24.12.2)(@vitest/browser-playwright@4.1.11)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(tsx@4.21.0)(yaml@2.9.0): dependencies: '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0)) + '@vitest/mocker': 4.1.11(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.11 '@vitest/runner': 4.1.11 '@vitest/snapshot': 4.1.11 @@ -6118,11 +7118,11 @@ snapshots: tinyexec: 1.3.1 tinyglobby: 0.2.17 tinyrainbow: 3.1.1 - vite: 8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0) + vite: 8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 24.12.2 - '@vitest/browser-playwright': 4.1.11(playwright@1.62.1)(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.21.0))(vitest@4.1.11) + '@vitest/browser-playwright': 4.1.11(playwright@1.62.1)(vite@8.0.16(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.11) jsdom: 29.1.1 transitivePeerDependencies: - '@vitejs/devtools' @@ -6144,6 +7144,8 @@ snapshots: dependencies: xml-name-validator: 5.0.0 + web-streams-polyfill@3.3.3: {} + web-tree-sitter@0.25.10: {} webidl-conversions@8.0.1: {} @@ -6186,6 +7188,8 @@ snapshots: yallist@3.1.1: {} + yaml@2.9.0: {} + yuku-ast@0.8.4: dependencies: '@yuku-toolchain/types': 0.8.4 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 237f65856..d210fcc1a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -6,6 +6,7 @@ packages: - "diffr/packages/viewer" - "diffr/packages/consumer" - "diffr/packages/claude-code" + - "diffr/packages/pi" - "diffr/packages/tui" - "apps/*" @@ -63,3 +64,5 @@ ignoredOptionalDependencies: allowBuilds: esbuild: true + "@google/genai": false + protobufjs: false