From e494595d52d8ddeae88aa13cbdb3a97bac71902a Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Mon, 13 Jul 2026 17:17:12 +0200 Subject: [PATCH 01/14] chore(lint): add .oxlintrc.json with type-aware rules Formalize the lint configuration that was previously running on oxlint defaults via the --type-aware flag. The config: - Activates type-aware rules (no-floating-promises, no-misused-promises, await-thenable, no-base-to-string, restrict-template-expressions). - Formalizes the repo no-explicit-any policy as a warning. - Disables noisy rules in test files where type strictness is less valuable (unbound-method, no-floating-promises, any). - Keeps correctness category as warnings, not errors, to preserve a green baseline while surfacing 364 items of technical debt for incremental cleanup. --- .oxlintrc.json | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .oxlintrc.json diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 00000000..0f570074 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,42 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "categories": { + "correctness": "warn" + }, + "rules": { + "no-explicit-any": "warn", + "typescript/no-floating-promises": "warn", + "typescript/no-misused-promises": "warn", + "typescript/await-thenable": "warn", + "typescript/no-base-to-string": "warn", + "typescript/restrict-template-expressions": "warn", + "typescript/no-misused-spread": "warn", + "typescript/no-this-alias": "warn", + "no-unused-vars": "warn", + "no-unassigned-vars": "warn", + "no-dupe-keys": "warn", + "no-unused-expressions": "warn", + "no-misleading-character-class": "warn", + "no-control-regex": "warn", + "no-new-array": "off" + }, + "overrides": [ + { + "files": [ + "**/*.test.ts", + "**/*.e2e.test.ts", + "**/*.live.test.ts", + "**/test-helpers/**", + "**/test-utils/**" + ], + "rules": { + "typescript/no-floating-promises": "off", + "typescript/no-misused-promises": "off", + "typescript/unbound-method": "off", + "no-explicit-any": "off", + "typescript/no-base-to-string": "off", + "typescript/restrict-template-expressions": "off" + } + } + ] +} From 010ffea414c534589e37049849799701e71a42e2 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Mon, 13 Jul 2026 17:19:51 +0200 Subject: [PATCH 02/14] docs(security): document dependency supply-chain policy Add a Dependency Supply Chain section to SECURITY.md covering the controls the project already enforces via package.json: - The 48-hour release age floor (minimumReleaseAge: 2880). - The rationale requirement for every pnpm.overrides entry, tied to a CVE or regression. - The hard rule that patchedDependencies must use exact versions. - Lockfile discipline: frozen-lockfile in CI, deps: commits for dependency changes, reviewed transitive bumps. - The onlyBuiltDependencies allowlist limiting native build scripts. This formalizes existing practice as written policy so maintainers and contributors have a single source of truth for dependency trust decisions. --- SECURITY.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/SECURITY.md b/SECURITY.md index 784bdf96..fb315a71 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -123,6 +123,56 @@ docker run --read-only --cap-drop=ALL \ mayros/mayros:latest ``` +## Dependency Supply Chain + +Mayros treats its dependency tree as part of its trust boundary. A malicious or +broken transitive package reaches users the moment it enters the lockfile, so the +project enforces the following controls in `package.json`: + +### Release age floor + +`pnpm.minimumReleaseAge: 2880` (48 hours) gates every resolution. A package +published less than 48 hours ago is not eligible for install, which buffers +against compromised or yanked releases that get quarantined shortly after +publish. + +### Forced security overrides + +The `pnpm.overrides` map forces specific versions of transitive dependencies +known to carry security regressions. Each override exists because a transitive +in the tree resolved to a vulnerable version and the override is the most +durable way to pin the patched floor without waiting for upstreams to bump. + +When adding or changing an override, record why in the commit message: the CVE +or GHSA it addresses (or the regression it prevents). Overrides without a +recorded rationale are rejected in review. + +### Patched dependencies + +Any dependency declared in `pnpm.patchedDependencies` must use an exact version +(no `^` or `~`). This is a hard rule: a range on a patched package lets a future +resolve drift past the patch, silently reverting the fix. + +### Lockfile discipline + +The npm/pnpm lockfile pins the full transitive tree by content hash. Treat the +lockfile as a reviewed artifact, not an auto-generated one: + +- A change to `pnpm-lock.yaml` without a corresponding dependency change in + `package.json` is suspicious and must be explained in the commit. +- Dependabot/Renovate PRs that bump a transitive without a recorded CVE/fix are + held until the change is understood. +- `pnpm install --frozen-lockfile` is the canonical install command in CI; + `pnpm install` (which can mutate the lockfile) is reserved for local + dependency changes that are committed alongside a `deps:` commit. + +### Native build scripts + +`pnpm.onlyBuiltDependencies` enumerates the packages allowed to run native +build scripts (node-gyp, prebuilt binaries). Packages not in this list cannot +execute install scripts, which limits the blast radius of a compromised native +dependency. + ## Security Scanning This project uses `detect-secrets` for automated secret detection in CI/CD. From d26e0218a957e6dfbc71e6e9d6d124984e607214 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Mon, 13 Jul 2026 17:21:29 +0200 Subject: [PATCH 03/14] =?UTF-8?q?docs(security):=20add=20trust=20model=20?= =?UTF-8?q?=E2=80=94=20OS=20isolation=20as=20the=20load-bearing=20boundary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a Trust Model section that states the project's governing security principle: operating-system level isolation is the only load-bearing boundary, and every in-process defense (approval gate, output redaction, scanners, rate limiters, the WASM sandbox) is a heuristic that reduces attack surface but does not contain a determined adversary with in-process code execution. The section classifies real boundaries (separate users, containers, VMs, namespaces, seccomp, Landlock) against in-process defenses, and gives concrete implications for operators running untrusted skills and plugins. This sharpens the existing Plugin Trust Boundary section, which now reads as a specific case of the general model. --- SECURITY.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/SECURITY.md b/SECURITY.md index fb315a71..74786ce3 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -57,6 +57,48 @@ Mayros security guidance assumes: - Anyone who can modify `~/.mayros` state/config (including `mayros.json`) is effectively a trusted operator. - A single Gateway shared by mutually untrusted people is **not a recommended setup**. Use separate gateways (or at minimum separate OS users/hosts) per trust boundary. +## Trust Model + +The single load-bearing security boundary in Mayros is **operating-system level +isolation**. Everything else is a heuristic or a convenience, not a containment +boundary. + +This distinction matters because it is easy to over-trust in-process defenses. +The rule below governs how each layer should be treated: + +### What is and is not a boundary + +- **Real boundaries** — mechanisms the OS or kernel enforces against a + malicious process running inside them: + - Separate OS users, containers, VMs, namespaces, seccomp, Landlock. + - A sandboxed Docker container with `--cap-drop=ALL --read-only`. + - A separate host entirely (the strongest option). +- **In-process defenses** — useful, but **not containment**. A sufficiently + resourced attacker who has code execution inside the process can bypass them: + - The approval gate and interactive permission prompts. + - Output redaction and secret masking (`src/security/output-masking.ts`). + - The static skill scanner and bash command blocklist. + - Rate limiters, query/write caps, and the enrichment timeout. + - The WASM skill sandbox (it narrows the attack surface of untrusted skill + code, but the host process can still be reached via bugs in the runtime). + +Treat the in-process defenses as **defense in depth and attack-surface +reduction**, never as the thing that stops a determined adversary. The thing +that stops a determined adversary is running the untrusted workload under a +real OS boundary. + +### Practical implications + +- For fully untrusted skills, plugins, or tool output, run the Gateway (or the + session) inside a container or separate OS user. Do not rely on the approval + gate alone. +- The default loopback-only bind is a real boundary against remote network + attackers; keep it unless you have a replacement boundary (Tailscale, SSH + tunnel, firewall). +- When reviewing a security finding, classify it by which boundary it crosses. + A bug that lets a plugin read another plugin's memory is contained by the OS + user; a bug that lets a remotely-reached endpoint execute code is not. + ## Plugin Trust Boundary Plugins/extensions are loaded **in-process** with the Gateway and are treated as trusted code. From f2da992691d031f5499a7bb36124ea8062b2f092 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Mon, 13 Jul 2026 17:25:16 +0200 Subject: [PATCH 04/14] ci: enforce lockfile change policy Add a CI step on pull requests that fails when pnpm-lock.yaml changes without a deps-scoped commit or a corresponding manifest change (package.json, pnpm-workspace.yaml). This implements the lockfile discipline documented in SECURITY.md as an automated gate rather than relying on review alone. The check is implemented as scripts/check-lockfile-policy.mjs so it can also run locally (node scripts/check-lockfile-policy.mjs --base ) before pushing. On CI it only runs on pull_request events, where the base ref is well-defined. --- .github/workflows/ci.yml | 6 ++ scripts/check-lockfile-policy.mjs | 134 ++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 scripts/check-lockfile-policy.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a856ab70..8a769815 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,6 +106,8 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: + # Full history so the lockfile policy check can read commit messages. + fetch-depth: 0 submodules: false - name: Setup Node environment @@ -114,6 +116,10 @@ jobs: - name: Check types, lint, and format run: pnpm check + - name: Enforce lockfile change policy + if: github.event_name == 'pull_request' + run: node scripts/check-lockfile-policy.mjs --base "origin/${{ github.base_ref }}" --head "${{ github.event.pull_request.head.sha }}" + build-artifacts: needs: [docs-scope, changed-scope, check] if: needs.docs-scope.outputs.docs_only != 'true' && (github.event_name == 'push' || needs.changed-scope.outputs.run_node == 'true') diff --git a/scripts/check-lockfile-policy.mjs b/scripts/check-lockfile-policy.mjs new file mode 100644 index 00000000..59e95005 --- /dev/null +++ b/scripts/check-lockfile-policy.mjs @@ -0,0 +1,134 @@ +#!/usr/bin/env node +/** + * Lockfile change policy check. + * + * Enforces the dependency supply-chain policy documented in SECURITY.md: + * a change to pnpm-lock.yaml should arrive alongside a dependency change in + * package.json, and the commit carrying it should be scoped as `deps:`. + * + * The check compares the lockfile against a base. On CI it reads the base + * from the GITHUB_BASE_REF / commit range; locally it can be invoked with + * --base to run the same gate before pushing. + * + * Exit codes: + * 0 — policy satisfied (or lockfile unchanged) + * 1 — policy violated (lockfile changed without a deps-scoped commit) + * 2 — unable to determine the range (soft-fail with a warning) + */ +import { execSync } from "node:child_process"; +import process from "node:process"; + +const LOCKFILE = "pnpm-lock.yaml"; +const DEPS_SCOPE = /^deps:/; +const DEPS_FILES = new Set(["package.json", "pnpm-workspace.yaml"]); + +function parseArgs(argv) { + const args = { base: null, head: null }; + for (let i = 2; i < argv.length; i++) { + const a = argv[i]; + if (a === "--base") args.base = argv[++i]; + else if (a === "--head") args.head = argv[++i]; + else if (a === "-h" || a === "--help") { + process.stdout.write( + "Usage: check-lockfile-policy.mjs [--base ] [--head ]\n" + + " Checks that pnpm-lock.yaml changes arrive in deps-scoped commits.\n", + ); + process.exit(0); + } + } + return args; +} + +function run(cmd) { + return execSync(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim(); +} + +function tryRun(cmd) { + try { + return run(cmd); + } catch { + return null; + } +} + +function resolveRange(args) { + const head = args.head || process.env.GITHUB_SHA || "HEAD"; + let base = args.base; + if (!base) { + if (process.env.GITHUB_BASE_REF) { + base = `origin/${process.env.GITHUB_BASE_REF}`; + } else if (process.env.GITHUB_EVENT_BEFORE) { + base = process.env.GITHUB_EVENT_BEFORE; + } else { + // local default: compare against the default branch tip + base = + tryRun("git rev-parse --verify origin/main >/dev/null 2>&1 && echo origin/main") || null; + } + } + return { base, head }; +} + +function changedFiles(base, head) { + const out = tryRun(`git diff --name-only ${base}..${head}`); + if (!out) return null; + return new Set(out.split(/\r?\n/).filter(Boolean)); +} + +function commitSubjects(base, head) { + const out = tryRun(`git log --format=%s ${base}..${head}`); + if (!out) return []; + return out.split(/\r?\n/).filter(Boolean); +} + +function main() { + const args = parseArgs(process.argv); + const { base, head } = resolveRange(args); + + if (!base) { + console.warn("[lockfile-policy] could not determine a base ref; skipping."); + process.exit(2); + } + + // Make sure the base is locally resolvable (CI shallow clones). + const resolvedBase = tryRun(`git rev-parse --verify "${base}^{commit}"`); + if (!resolvedBase) { + const fetched = tryRun(`git fetch --no-tags --depth=1 origin ${base}`); + if (!fetched === false) { + console.warn(`[lockfile-policy] base ref ${base} not resolvable; skipping.`); + process.exit(2); + } + } + + const files = changedFiles(base, head); + if (!files) { + console.warn("[lockfile-policy] could not compute diff; skipping."); + process.exit(2); + } + + if (!files.has(LOCKFILE)) { + console.log(`[lockfile-policy] ${LOCKFILE} unchanged — policy satisfied.`); + process.exit(0); + } + + // Lockfile changed. Require either a deps-scoped commit or a change to a + // recognized dependency manifest in the same range. + const subjects = commitSubjects(base, head); + const hasDepsScope = subjects.some((s) => DEPS_SCOPE.test(s)); + const hasManifestChange = [...files].some((f) => DEPS_FILES.has(f)); + + if (hasDepsScope || hasManifestChange) { + console.log(`[lockfile-policy] ${LOCKFILE} changed with deps-scoped commit — OK.`); + process.exit(0); + } + + console.error( + `[lockfile-policy] ${LOCKFILE} changed but no commit in range is scoped "deps:" ` + + `and no manifest (${[...DEPS_FILES].join(", ")}) changed.\n` + + `Commit subjects in range:\n` + + subjects.map((s) => ` - ${s}`).join("\n") + + '\nEither re-scope the commit to start with "deps:" or explain the lockfile drift.', + ); + process.exit(1); +} + +main(); From f49188b9d4abf1e2133d4dc5a51cb1d4979c8999 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Mon, 13 Jul 2026 17:40:32 +0200 Subject: [PATCH 05/14] refactor: replace all non-test as-any casts with proper types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove every `as any` escape hatch in production code (the 20 occurrences flagged by no-explicit-any once the rule was formalized). Each replacement uses a concrete type: - mattermost/channel.ts: params is already Record, so the casts were unnecessary — access the fields directly with typeof narrowing. - agent-mesh/index.ts: model the on-disk mayros.json and auth-profiles shapes with structural types instead of Record; forward the heterogeneous Mamoru gateway handlers through a typed callable. - feishu/bot.ts: narrow the Lark SDK response with a minimal FeishuUserResponse type; widen the logger signature to unknown[]. - feishu/docx.ts: introduce a FeishuBlock structural type for the document blocks used by sortBlocksByFirstLevel, with a type-guard filter. - mcp-server/index.ts: type registerCli's program as Command and the dashboard respond callback with its structural signature. Also extend the oxlint test override to *.test-helpers.ts so test fixtures are not held to production type strictness. --- .oxlintrc.json | 1 + extensions/agent-mesh/index.ts | 41 +++++++++----- extensions/feishu/src/bot.ts | 15 ++++-- extensions/feishu/src/docx.ts | 11 ++-- extensions/mattermost/src/channel.ts | 12 ++--- extensions/mcp-server/index.ts | 81 +++++++++++++++------------- 6 files changed, 99 insertions(+), 62 deletions(-) diff --git a/.oxlintrc.json b/.oxlintrc.json index 0f570074..cda82e50 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -26,6 +26,7 @@ "**/*.test.ts", "**/*.e2e.test.ts", "**/*.live.test.ts", + "**/*.test-helpers.ts", "**/test-helpers/**", "**/test-utils/**" ], diff --git a/extensions/agent-mesh/index.ts b/extensions/agent-mesh/index.ts index 24ba5bf6..76eb5f12 100644 --- a/extensions/agent-mesh/index.ts +++ b/extensions/agent-mesh/index.ts @@ -2222,7 +2222,12 @@ const agentMeshPlugin = { for (const [name, handler] of Object.entries(methods)) { api.registerGatewayMethod(name, async ({ params, respond }) => { try { - const result = await handler((params ?? {}) as any); + // Handlers in the Mamoru gateway map are heterogeneous (each + // declares its own params shape). The runtime contract is that + // params arrive validated by the gateway dispatcher, so we forward + // the resolved object typed as the handler's first parameter. + const fn = handler as (input: Record) => Promise; + const result = await fn((params ?? {}) as Record); respond(true, result); } catch (err) { respond(false, { error: err instanceof Error ? err.message : String(err) }); @@ -2277,21 +2282,28 @@ const agentMeshPlugin = { const nodeFsP = await import("node:fs/promises"); const home = process.env.HOME ?? ""; - // Update mayros.json with model + ollama auth profile + // Update mayros.json with model + ollama auth profile. The config is + // read from disk and mutated, so we model the shape we touch rather + // than widening to Record. + type MayrosJsonFile = { + agents?: { defaults?: { model?: { primary?: string; [k: string]: unknown } } }; + auth?: { profiles?: Record }; + [k: string]: unknown; + }; const configPath = nodePath.join(home, ".mayros", "mayros.json"); - let cfg: Record = {}; + let cfg: MayrosJsonFile = {}; try { - cfg = JSON.parse(await nodeFsP.readFile(configPath, "utf8")); + cfg = JSON.parse(await nodeFsP.readFile(configPath, "utf8")) as MayrosJsonFile; } catch { /* new */ } - if (!cfg.agents) cfg.agents = {}; - if (!cfg.agents.defaults) cfg.agents.defaults = {}; - if (!cfg.agents.defaults.model) cfg.agents.defaults.model = {}; + cfg.agents ??= {}; + cfg.agents.defaults ??= {}; + cfg.agents.defaults.model ??= {}; cfg.agents.defaults.model.primary = p.model; if (p.provider === "local" && p.model.startsWith("ollama/")) { - if (!cfg.auth) cfg.auth = {}; - if (!cfg.auth.profiles) cfg.auth.profiles = {}; + cfg.auth ??= {}; + cfg.auth.profiles ??= {}; cfg.auth.profiles["ollama"] = { provider: "ollama", mode: "api_key" }; } await nodeFsP.writeFile(configPath, JSON.stringify(cfg, null, 2) + "\n"); @@ -2301,13 +2313,18 @@ const agentMeshPlugin = { const agentDir = nodePath.join(home, ".mayros", "agents", "main", "agent"); await nodeFsP.mkdir(agentDir, { recursive: true }); const storePath = nodePath.join(agentDir, "auth-profiles.json"); - let store: Record = { version: 2, profiles: {} }; + type AuthProfileStore = { + version?: number; + profiles?: Record; + [k: string]: unknown; + }; + let store: AuthProfileStore = { version: 2, profiles: {} }; try { - store = JSON.parse(await nodeFsP.readFile(storePath, "utf8")); + store = JSON.parse(await nodeFsP.readFile(storePath, "utf8")) as AuthProfileStore; } catch { /* new */ } - if (!store.profiles) store.profiles = {}; + store.profiles ??= {}; store.profiles["ollama"] = { provider: "ollama", type: "api_key", key: "ollama-local" }; await nodeFsP.writeFile(storePath, JSON.stringify(store, null, 2)); } diff --git a/extensions/feishu/src/bot.ts b/extensions/feishu/src/bot.ts index 95af28eb..83215694 100644 --- a/extensions/feishu/src/bot.ts +++ b/extensions/feishu/src/bot.ts @@ -86,7 +86,7 @@ type SenderNameResult = { async function resolveFeishuSenderName(params: { account: ResolvedFeishuAccount; senderOpenId: string; - log: (...args: any[]) => void; + log: (...args: unknown[]) => void; }): Promise { const { account, senderOpenId, log } = params; if (!account.configured) return {}; @@ -100,10 +100,19 @@ async function resolveFeishuSenderName(params: { const client = createFeishuClient(account); // contact/v3/users/:user_id?user_id_type=open_id - const res: any = await client.contact.user.get({ + // The Feishu SDK returns an untyped response envelope; narrow the fields + // we actually read instead of widening the whole value to `any`. + type FeishuUser = { + name?: string; + display_name?: string; + nickname?: string; + en_name?: string; + }; + type FeishuUserResponse = { data?: { user?: FeishuUser } }; + const res = (await client.contact.user.get({ path: { user_id: senderOpenId }, params: { user_id_type: "open_id" }, - }); + })) as FeishuUserResponse; const name: string | undefined = res?.data?.user?.name || diff --git a/extensions/feishu/src/docx.ts b/extensions/feishu/src/docx.ts index 52f90dbb..f4f5d048 100644 --- a/extensions/feishu/src/docx.ts +++ b/extensions/feishu/src/docx.ts @@ -93,11 +93,16 @@ async function convertMarkdown(client: Lark.Client, markdown: string) { }; } -function sortBlocksByFirstLevel(blocks: any[], firstLevelIds: string[]): any[] { +/** Minimal structural shape of a Feishu/Lark document block used for sorting. */ +type FeishuBlock = { block_id?: string; [key: string]: unknown }; + +function sortBlocksByFirstLevel(blocks: FeishuBlock[], firstLevelIds: string[]): FeishuBlock[] { if (!firstLevelIds || firstLevelIds.length === 0) return blocks; - const sorted = firstLevelIds.map((id) => blocks.find((b) => b.block_id === id)).filter(Boolean); + const sorted = firstLevelIds + .map((id) => blocks.find((b) => b.block_id === id)) + .filter((b): b is FeishuBlock => Boolean(b)); const sortedIds = new Set(firstLevelIds); - const remaining = blocks.filter((b) => !sortedIds.has(b.block_id)); + const remaining = blocks.filter((b) => !sortedIds.has(b.block_id ?? "")); return [...sorted, ...remaining]; } diff --git a/extensions/mattermost/src/channel.ts b/extensions/mattermost/src/channel.ts index ed979461..37ce4591 100644 --- a/extensions/mattermost/src/channel.ts +++ b/extensions/mattermost/src/channel.ts @@ -67,23 +67,23 @@ const mattermostMessageActions: ChannelMessageActionAdapter = { } const postIdRaw = - typeof (params as any)?.messageId === "string" - ? (params as any).messageId - : typeof (params as any)?.postId === "string" - ? (params as any).postId + typeof params.messageId === "string" + ? params.messageId + : typeof params.postId === "string" + ? params.postId : ""; const postId = postIdRaw.trim(); if (!postId) { throw new Error("Mattermost react requires messageId (post id)"); } - const emojiRaw = typeof (params as any)?.emoji === "string" ? (params as any).emoji : ""; + const emojiRaw = typeof params.emoji === "string" ? params.emoji : ""; const emojiName = emojiRaw.trim().replace(/^:+|:+$/g, ""); if (!emojiName) { throw new Error("Mattermost react requires emoji"); } - const remove = (params as any)?.remove === true; + const remove = params.remove === true; if (remove) { const result = await removeMattermostReaction({ cfg, diff --git a/extensions/mcp-server/index.ts b/extensions/mcp-server/index.ts index 65efa511..299f8016 100644 --- a/extensions/mcp-server/index.ts +++ b/extensions/mcp-server/index.ts @@ -15,6 +15,7 @@ // @ts-expect-error — dist/index.js has no declaration file; types resolved via source paths import type { MayrosPluginApi, MayrosPluginToolContext } from "@apilium/mayros"; +import type { Command } from "commander"; import { mcpServerConfigSchema, type McpServerConfig } from "./config.js"; import { McpServer, type McpServerOptions } from "./server.js"; import type { AdaptableTool } from "./tool-adapter.js"; @@ -142,7 +143,7 @@ const mcpServerPlugin = { // ── Register CLI ──────────────────────────────────────────────── - api.registerCli(({ program }: { program: any }) => { + api.registerCli(({ program }: { program: Command }) => { const serve = program .command("serve") .description("Start MCP server to expose Mayros tools, resources, and prompts"); @@ -303,45 +304,49 @@ const mcpServerPlugin = { // ── Register gateway method (MCP Dashboard) ──────────────────── - api.registerGatewayMethod("mcp.dashboard", async ({ respond }: { respond: any }) => { - // Cortex health check with 3s timeout — always runs - let cortexHealth: { status: "online" | "offline"; latencyMs: number }; - try { - const cortexPort = cfg.cortex?.port ?? 19090; - const cortexUrl = `http://127.0.0.1:${cortexPort}/api/v1/health`; - const start = Date.now(); - const cortexRes = await fetch(cortexUrl, { - signal: AbortSignal.timeout(3000), - }); - const latencyMs = Date.now() - start; - cortexHealth = { - status: cortexRes.ok ? "online" : "offline", - latencyMs, - }; - } catch { - cortexHealth = { status: "offline", latencyMs: 0 }; - } + type DashboardRespond = (ok: boolean, payload?: unknown) => void; + api.registerGatewayMethod( + "mcp.dashboard", + async ({ respond }: { respond: DashboardRespond }) => { + // Cortex health check with 3s timeout — always runs + let cortexHealth: { status: "online" | "offline"; latencyMs: number }; + try { + const cortexPort = cfg.cortex?.port ?? 19090; + const cortexUrl = `http://127.0.0.1:${cortexPort}/api/v1/health`; + const start = Date.now(); + const cortexRes = await fetch(cortexUrl, { + signal: AbortSignal.timeout(3000), + }); + const latencyMs = Date.now() - start; + cortexHealth = { + status: cortexRes.ok ? "online" : "offline", + latencyMs, + }; + } catch { + cortexHealth = { status: "offline", latencyMs: 0 }; + } - if (!server) { - respond(true, { - status: { - running: false, - transport: cfg.transport ?? "http", - toolCount: 0, - initialized: false, - uptimeMs: 0, - sseSessionCount: 0, - }, - metrics: null, - cortexHealth, - }); - return; - } + if (!server) { + respond(true, { + status: { + running: false, + transport: cfg.transport ?? "http", + toolCount: 0, + initialized: false, + uptimeMs: 0, + sseSessionCount: 0, + }, + metrics: null, + cortexHealth, + }); + return; + } - const status = server.status(); - const metrics = server.getMetrics(); - respond(true, { status, metrics, cortexHealth }); - }); + const status = server.status(); + const metrics = server.getMetrics(); + respond(true, { status, metrics, cortexHealth }); + }, + ); // ── Register service lifecycle ────────────────────────────────── From 9212ff3e75c4ea17bc75ef25d0f4ef556ad6c186 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Mon, 13 Jul 2026 17:55:02 +0200 Subject: [PATCH 06/14] feat(agents): prompt cache discipline + system-prompt drift detection Formalize the project's prompt-cache invariant and add a drift signal to the cache trace so cache-breaking changes become visible. AGENTS.md: - Add a Prompt Cache Discipline section stating the governing principle: the system prompt must stay stable across runs that have no reason to change it, slash commands that mutate state invalidate only on the next turn, and hooks must be deterministic. This makes the contract explicit for contributors. cache-trace.ts: - Track the last system digest per session key in a module-level map. - When wrapStreamFn sees a different system digest for the same session on a consecutive call, emit a new cache:system-drift event carrying both the current and previous digests. This turns silent cache invalidations (which multiply token cost) into a diagnosable signal. - Propagate previousSystemDigest through the event pipeline. cache-trace.test.ts: - Unit tests covering first-call (no drift), drift on change, stability across repeated calls, and independent per-session tracking. --- AGENTS.md | 10 +++ src/agents/cache-trace.test.ts | 118 +++++++++++++++++++++++++++++++++ src/agents/cache-trace.ts | 39 ++++++++++- 3 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 src/agents/cache-trace.test.ts diff --git a/AGENTS.md b/AGENTS.md index 7a543e1d..6f603a8f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -79,6 +79,16 @@ - Aim to keep files under ~700 LOC; guideline only (not a hard guardrail). Split/refactor when it improves clarity or testability. - Naming: use **Mayros** for product/app/docs headings; use `mayros` for CLI command, package/binary, paths, and config keys. +## Prompt Cache Discipline + +Per-conversation prompt caching is sacred. A long-lived session reuses a cached prefix on every turn; anything that mutates past context, swaps toolsets, or rebuilds the system prompt with volatile content invalidates that cache and multiplies token cost. The project enforces caching via the `cacheRetention` stream option (handled by the provider layer), and the cost of an invalidation is real and silent. + +- The system prompt is rebuilt on every run. Its content must be **stable across runs that have no reason to change it**. Do not add volatile data (timestamps that tick every second, random IDs, unordered maps) to the system prompt or to context files that feed it. The `Runtime:` line is the sanctioned place for run-scoped info and is designed to change only when the operator changes model, channel, or thinking level. +- Slash commands that mutate prompt-relevant state (`/model`, `/think`, `/reasoning`, `/elevated`, `/fast`, `/new`) are expected to invalidate the cache on the **next** turn by design. That is the only acceptable invalidation. A change that invalidates the cache mid-turn, or on every turn regardless of whether the operator touched anything, is a bug. +- When adding context to the prompt (new sections, hook output, injected memory), prefer **append-only** structure. Reordering existing sections or inserting in the middle invalidates everything after the insertion point. +- Hooks (`before_prompt_build`, `before_agent_start`) that override `systemPrompt` or `prependContext` must be deterministic for a given input. A hook that returns different text on consecutive calls with the same inputs breaks the cache and is a high-priority bug. +- The `diagnostics.cacheTrace` subsystem records a SHA-256 of the system prompt and messages at each pipeline stage. When investigating cache regressions, compare `systemDigest` across consecutive turns of a session where nothing should have changed — a drift there is the signature of a cache-breaking change. + ## Release Channels (Naming) - stable: tagged releases only (e.g. `vYYYY.M.D`), npm dist-tag `latest`. diff --git a/src/agents/cache-trace.test.ts b/src/agents/cache-trace.test.ts new file mode 100644 index 00000000..c6edcaab --- /dev/null +++ b/src/agents/cache-trace.test.ts @@ -0,0 +1,118 @@ +import { describe, expect, it } from "vitest"; +import type { MayrosConfig } from "../config/config.js"; +import { createCacheTrace } from "./cache-trace.js"; + +/** + * cache-trace drift detection unit tests. + * + * These cover the system-prompt drift signal added to wrapStreamFn: when the + * same session sees a different system digest between consecutive stream calls, + * a `cache:system-drift` event is emitted so cache-breaking changes become + * visible instead of silently inflating token cost. + */ + +type TraceLine = { stage: string; systemDigest?: string; previousSystemDigest?: string }; + +function makeTrace(sessionKey: string, lines: TraceLine[]) { + return createCacheTrace({ + cfg: { + diagnostics: { + cacheTrace: { + enabled: true, + includeSystem: true, + }, + }, + } as MayrosConfig, + env: {}, + sessionKey, + writer: { + filePath: "memory", + write: (line: string) => { + const parsed = JSON.parse(line) as TraceLine; + lines.push(parsed); + }, + }, + }); +} + +// Minimal StreamFn stub: returns an empty async iterable and records nothing. +function noopStreamFn() { + return (async function* () { + /* empty */ + })(); +} + +// The wrapper invokes streamFn(model, context, options). Build a minimal model +// stub and a typed context so tsgo accepts the call without constructing a full +// Model (which carries many fields irrelevant to drift detection). +type StreamCallContext = { system?: unknown; messages: unknown[] }; +function callWrapped( + wrapped: ReturnType>["wrapStreamFn"]> | undefined, + system: unknown, +) { + const model = { id: "m", provider: "anthropic" } as unknown as Parameters< + NonNullable + >[0]; + const context = { system, messages: [] } as StreamCallContext as Parameters< + NonNullable + >[1]; + wrapped?.(model, context, {}); +} + +describe("cache-trace drift detection", () => { + it("does not emit a drift event on the first stream call for a session", () => { + const lines: TraceLine[] = []; + const trace = makeTrace("sess-first", lines); + const wrapped = trace?.wrapStreamFn(noopStreamFn as never); + + callWrapped(wrapped, "system-A"); + + const drifts = lines.filter((l) => l.stage === "cache:system-drift"); + expect(drifts).toHaveLength(0); + }); + + it("emits a drift event when the system prompt changes between two calls of the same session", () => { + const lines: TraceLine[] = []; + const trace = makeTrace("sess-drift", lines); + const wrapped = trace?.wrapStreamFn(noopStreamFn as never); + + callWrapped(wrapped, "system-A"); + callWrapped(wrapped, "system-B"); + + const drifts = lines.filter((l) => l.stage === "cache:system-drift"); + expect(drifts).toHaveLength(1); + expect(drifts[0]?.previousSystemDigest).toBeDefined(); + expect(drifts[0]?.systemDigest).toBeDefined(); + expect(drifts[0]?.previousSystemDigest).not.toBe(drifts[0]?.systemDigest); + }); + + it("does not emit a drift event when the system prompt stays stable across calls", () => { + const lines: TraceLine[] = []; + const trace = makeTrace("sess-stable", lines); + const wrapped = trace?.wrapStreamFn(noopStreamFn as never); + + callWrapped(wrapped, "same-system"); + callWrapped(wrapped, "same-system"); + callWrapped(wrapped, "same-system"); + + const drifts = lines.filter((l) => l.stage === "cache:system-drift"); + expect(drifts).toHaveLength(0); + }); + + it("tracks sessions independently", () => { + const linesA: TraceLine[] = []; + const linesB: TraceLine[] = []; + const traceA = makeTrace("sess-a", linesA); + const traceB = makeTrace("sess-b", linesB); + + // Session A and B both start with the same system, then A changes. + callWrapped(traceA?.wrapStreamFn(noopStreamFn as never), "shared-system"); + callWrapped(traceB?.wrapStreamFn(noopStreamFn as never), "shared-system"); + callWrapped(traceA?.wrapStreamFn(noopStreamFn as never), "changed-system"); + + const driftsA = linesA.filter((l) => l.stage === "cache:system-drift"); + const driftsB = linesB.filter((l) => l.stage === "cache:system-drift"); + expect(driftsA).toHaveLength(1); + expect(driftsB).toHaveLength(0); + }); +}); diff --git a/src/agents/cache-trace.ts b/src/agents/cache-trace.ts index cc9a6786..9da1fc3d 100644 --- a/src/agents/cache-trace.ts +++ b/src/agents/cache-trace.ts @@ -15,6 +15,7 @@ export type CacheTraceStage = | "prompt:before" | "prompt:images" | "stream:context" + | "cache:system-drift" | "session:after"; export type CacheTraceEvent = { @@ -38,6 +39,8 @@ export type CacheTraceEvent = { messageFingerprints?: string[]; messagesDigest?: string; systemDigest?: string; + /** Previous system digest for the same session, when a drift is detected. */ + previousSystemDigest?: string; note?: string; error?: string; }; @@ -74,6 +77,14 @@ type CacheTraceWriter = QueuedFileWriter; const writers = new Map(); +/** + * Last system digest seen per session key, so we can detect when the system + * prompt drifts between consecutive turns of the same session. A drift with no + * operator-triggered change (model, thinking, channel) is the signature of a + * cache-breaking bug. Keyed by sessionKey (or sessionId as fallback). + */ +const lastSystemDigestBySession = new Map(); + function resolveCacheTraceConfig(params: CacheTraceInit): CacheTraceConfig { const env = params.env ?? process.env; const config = params.cfg?.diagnostics?.cacheTrace; @@ -222,6 +233,9 @@ export function createCacheTrace(params: CacheTraceInit): CacheTrace | null { if (payload.error) { event.error = payload.error; } + if (payload.previousSystemDigest !== undefined) { + event.previousSystemDigest = payload.previousSystemDigest; + } const line = safeJsonStringify(event); if (!line) { @@ -232,16 +246,37 @@ export function createCacheTrace(params: CacheTraceInit): CacheTrace | null { const wrapStreamFn: CacheTrace["wrapStreamFn"] = (streamFn) => { const wrapped: StreamFn = (model, context, options) => { + const system = (context as { system?: unknown }).system; + const messages = (context as { messages?: AgentMessage[] }).messages ?? []; recordStage("stream:context", { model: { id: model?.id, provider: model?.provider, api: model?.api, }, - system: (context as { system?: unknown }).system, - messages: (context as { messages?: AgentMessage[] }).messages ?? [], + system, + messages, options: (options ?? {}) as Record, }); + + // Detect system-prompt drift across turns of the same session. A + // different digest with no operator-triggered change (model/thinking) + // is the signature of a cache-breaking bug, per the Prompt Cache + // Discipline policy in AGENTS.md. + if (system !== undefined && params.sessionKey) { + const currentDigest = digest(system); + const previous = lastSystemDigestBySession.get(params.sessionKey); + if (previous !== undefined && previous !== currentDigest) { + recordStage("cache:system-drift", { + system, + systemDigest: currentDigest, + previousSystemDigest: previous, + note: "system prompt changed between turns without a session restart; investigate if no operator change triggered this", + }); + } + lastSystemDigestBySession.set(params.sessionKey, currentDigest); + } + return streamFn(model, context, options); }; return wrapped; From 499cd764228cba8526225fe0f9f62bc0e4fe71f6 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Mon, 13 Jul 2026 18:02:58 +0200 Subject: [PATCH 07/14] docs: TUI redesign audit and roadmap Add docs/platforms/tui-redesign.md capturing the current state of the terminal UI, the gaps found during an internal audit, and a prioritized P0/P1/P2 roadmap for the next redesign pass. The audit covers rendering, input, slash commands, themes, vim mode, accessibility, and platform coverage. It documents the architectural constraints (shared terminal UI dependency as rendering floor, mandatory gateway, mutable state, two parallel TUI implementations, two palette systems) that bound the redesign, and calls out two P0 items that block trustworthy feature work: verifying the vim bridge is actually wired, and bringing the accessibility TUI to feature parity. --- docs/platforms/tui-redesign.md | 109 +++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 docs/platforms/tui-redesign.md diff --git a/docs/platforms/tui-redesign.md b/docs/platforms/tui-redesign.md new file mode 100644 index 00000000..edc609c2 --- /dev/null +++ b/docs/platforms/tui-redesign.md @@ -0,0 +1,109 @@ +--- +title: TUI Redesign Roadmap +description: Audit of the current terminal UI and prioritized plan for reaching a polished, best-in-class experience. +--- + +# TUI Redesign Roadmap + +This document captures the current state of the Mayros terminal UI (`mayros code` / `mayros tui`), the gaps identified during an internal audit, and a prioritized roadmap for the next redesign pass. It is a planning artifact; implementation is tracked separately. + +## Current state at a glance + +The TUI is a gateway client: it renders in the terminal and talks to a running `mayros gateway` daemon over WebSocket. The rendering, input, and component layer comes from the shared terminal UI dependency; Mayros adds the slash-command surface, themes, vim mode, mouse scrolling, accessibility fallback, and the gateway chat client. + +| Area | Maturity | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| Rendering and streaming | Mature. Event-driven render loop, full assistant-message re-render on each delta. | +| Slash commands | Mature in count (40+ built-in), uneven in depth. Core session commands are first-class; ecosystem commands are prompt-injection shims. | +| Themes | Mature. Ten palettes with 22 color tokens each, live hot-swap. | +| Vim mode | Basic. Custom implementation; operators partially stubbed, no visual or command-line mode. | +| Accessibility | Split. A linear text-mode TUI exists but is a separate, feature-poor implementation. | +| Platform coverage | Gaps. Clipboard image paste and `/copy` work on macOS and Linux only; Windows and Wayland are unsupported. | +| Architecture | Workable but strained. Two monolithic files (`tui.ts`, `tui-command-handlers.ts`), a mutable god-object state, and two parallel palette systems. | + +## Architectural constraints + +These shape what a redesign can and cannot do without larger upstream work. + +- **The terminal UI dependency is the rendering floor.** Layout capabilities (vertical-stack containers, select-list overlays) bound what Mayros can render. The tightest couplings are a `CustomEditor` that subclasses the shared editor and a `ChatLog` that subclasses the shared container. Refactoring either to composition requires an adapter layer or upstream changes. +- **The gateway is mandatory.** The TUI cannot run without a reachable gateway daemon. There is no in-process fallback, which affects offline use and dev ergonomics. +- **Theme hot-swap relies on singleton mutation.** Active theme objects are mutated in place so existing references stay live. Any snapshotting or caching of theme values would break live switching. +- **Mutable state object.** The TUI threads a single state object through every handler with manual render requests. There is no reactive store, although the signal libraries used elsewhere in the repo are available as a foundation. +- **Two parallel TUI implementations.** The graphical TUI and the accessibility TUI share almost no code. Every new feature currently needs to be implemented twice or skipped in one of them. +- **Two palette systems.** Terminal output (onboarding, prompts, CLI tables) and the TUI use separate palette modules with different accent colors. Visual consistency across the CLI experience requires unifying them. + +## Gaps by category + +### Rendering + +- No inline image rendering despite the shared terminal dependency shipping the capability. Image content blocks currently render as text placeholders. +- The diff renderer hardcodes colors instead of consuming the active theme, so diffs look wrong under light or high-contrast themes. +- Only vertical-stack layout; no split panes or resizable regions beyond the select-list overlay. +- Full assistant-text re-render on every streaming delta; long messages may degrade. + +### Input + +- Vim operator-plus-motion combinations are a simplified stub (non-linewise motions collapse to single-character operations). No visual mode, no command-line mode, no search, no repeat, no registers beyond a single yank buffer. +- The vim bridge does not appear to be wired from the TUI side; motions may silently no-op if the bridge is never connected. This needs verification before any vim work. +- Ctrl+C does not abort the active run; only Escape does. This is surprising and should align with user expectations. +- A cross-session input history store exists in code but is not connected to the main loop. + +### Commands + +- Ecosystem commands (`/team`, `/tasks`, `/workflow`, `/rules`, `/mailbox`, `/sync`, `/trace`, `/kg`, `/plan`) inject a prompt that asks the model to call a tool, rather than being first-class features. Results depend on the model. +- Several commands lack argument autocomplete. +- The theme preset list is duplicated in two files and can drift. +- The README command list is stale relative to the implementation. + +### Themes + +- The terminal palette and the TUI palette are separate modules with different accent colors. +- No user-defined custom themes. +- No colorblind-optimized palettes beyond the existing high-contrast option. +- No explicit `NO_COLOR` or `FORCE_COLOR` handling in the TUI. + +### Accessibility + +- The accessibility TUI is a stripped-down parallel implementation: no slash commands beyond exit, no session switching, no abort, no model selection. It excludes screen-reader users from most functionality. +- No screen-reader announcements in the graphical TUI. +- No monochrome or no-color mode in the graphical TUI. + +### Robustness and platform + +- Clipboard image paste and `/copy` support macOS and Linux (xclip) only. Windows and Wayland are unsupported. +- Several silent `catch` blocks swallow errors without logging. +- Disconnect handling shows hints but does not auto-reconnect with backoff. +- Window resize handling is delegated entirely to the shared terminal dependency and is not verified end-to-end in Mayros. + +## Roadmap + +Priorities are assigned as P0 (correctness or blocker), P1 (high-value polish), and P2 (nice to have). + +### P0 — Correctness and blockers + +1. **Verify the vim bridge is connected.** If the editor bridge is never set from the TUI side, every vim motion that relies on it silently no-ops. Confirm or fix before any further vim work. +2. **Accessibility TUI feature parity.** Either linearize the graphical renderer for screen readers or bring slash commands, session switching, and abort into the accessibility TUI. The current split excludes users from most functionality. + +### P1 — High-value polish + +3. **Inline image rendering.** Use the shared terminal image component to render image content blocks inline instead of text placeholders. +4. **Unify the palettes.** Merge the terminal palette and the TUI palette into one source of truth; make the diff renderer and every component consume the active theme. +5. **Complete vim mode.** Implement real operator-plus-motion semantics and add visual mode, or adopt a proven keymap pattern. +6. **Windows and Wayland clipboard support.** Add the platform-native clipboard commands for `/copy` and image paste. +7. **Make Ctrl+C abort the active run** with a double-press-to-exit fallback, keeping Escape as a secondary abort. +8. **Refresh the README** to reflect the actual theme count and command list. + +### P2 — Nice to have + +9. Terminal color-scheme auto-detection to pick dark or light theme automatically. +10. Wire the cross-session input history store into the main loop, or remove the dead code. +11. User-defined custom themes loaded from a config directory. +12. Argument autocomplete for every command; deduplicate the theme preset list. +13. Colorblind-optimized palettes and a true monochrome mode. +14. Incremental streaming render for long assistant messages. +15. Replace silent error swallowing with structured logging behind a debug flag. +16. Split the two monolithic TUI files to bring them under the file-size guideline. + +## Next steps + +The first implementation pass should focus on the P0 items, since both block a trustworthy feature surface: vim cannot be extended on top of an unwired bridge, and the accessibility TUI cannot ship as the screen-reader path while it lacks core commands. The P1 items are the bulk of the visible polish work and can be sequenced independently once the P0 verifications land. From 1a1143974b26eecbc7c96da417d3ced8a2930972 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Mon, 13 Jul 2026 19:32:07 +0200 Subject: [PATCH 08/14] deps: migrate pi agent suite to @earendil-works scope (#66) The @mariozechner/pi-{agent-core,ai,coding-agent,tui} packages were renamed and deprecated ("use @earendil-works/... going forward"); their last published version (0.73.1) is still affected by 3 open advisories with no fix. Migrate the whole suite to @earendil-works/pi-* ^0.80.2, which carries the fixes. - Repoint all import specifiers @mariozechner/pi-* -> @earendil-works/pi-* across src, extensions, scripts, skills, docs and the mac packaging script. - Bump the 4 root deps to ^0.80.2. - Adapt to the 0.54 -> 0.80 API surface: - pi-ai: legacy helpers (complete/completeSimple/stream/streamSimple/getModel/ getEnvApiKey/streamOpenAIResponses) moved to the `@earendil-works/pi-ai/compat` subpath; OAuth helpers to `@earendil-works/pi-ai/oauth`; deep `/dist/...` imports repointed (types -> root, google-shared -> /api); onPayload callback now (payload, model); ProviderHeaders allows null values; typebox re-exported from pi-ai. - pi-tui: dropped the `Editor` infix (getKeybindings/setKeybindings/ KeybindingsConfig/KeybindingsManager); KeybindingsManager(definitions, userBindings?); namespaced keybinding ids; async 4-arg AutocompleteProvider. - pi-coding-agent: codingTools -> createCodingTools(cwd); Skill.source -> Skill.sourceInfo.source; ModelRegistry.create(...)/getApiKeyForProvider; generateSummary headers param; createAgentSession tools is a name allowlist. - pi-agent-core: agent.replaceMessages/setSystemPrompt -> agent.state.*. - Add pnpm override "@apilium/mayros": "workspace:*" so the bluebubbles plugin resolves its peer to the workspace package instead of pulling the published 0.1.1, which bundled the old vulnerable pi suite. Closes the 3 remaining pi-coding-agent advisories: pnpm audit no longer reports any @mariozechner/pi or pi-coding-agent finding, and @earendil-works has none. Verified: pnpm install, pnpm tsgo (0 errors), pnpm lint (0 errors), oxfmt on changed files. Full test suite not run here (native deps + live keys); needs a CI run and a smoke test of the agent runtime before merge. --- .../Sources/Mayros/ModelCatalogLoader.swift | 2 +- docs/concepts/oauth.md | 2 +- docs/gateway/doctor.md | 2 +- docs/pi.md | 12 +- .../session-management-compaction.md | 2 +- extensions/browser-automation/index.ts | 9 +- extensions/kakeru-bridge/index.ts | 16 +- extensions/matrix/src/tool-actions.ts | 2 +- extensions/osameru-governance/index.ts | 8 +- extensions/voice-call/index.ts | 10 +- package.json | 9 +- pnpm-lock.yaml | 1531 ++++++++--------- scripts/bench-model.ts | 2 +- scripts/package-mac-app.sh | 2 +- skills/coding-agent/SKILL.md | 2 +- src/agents/anthropic-payload-log.ts | 8 +- src/agents/anthropic.setup-token.live.test.ts | 3 +- src/agents/apply-patch.ts | 2 +- src/agents/auth-profiles/oauth.ts | 8 +- src/agents/auth-profiles/store.ts | 2 +- src/agents/auth-profiles/types.ts | 2 +- src/agents/bash-tools.exec-host-gateway.ts | 2 +- src/agents/bash-tools.exec-host-node.ts | 2 +- src/agents/bash-tools.exec-runtime.ts | 2 +- src/agents/bash-tools.exec.ts | 2 +- src/agents/bash-tools.process.ts | 2 +- src/agents/byteplus.live.test.ts | 3 +- src/agents/cache-trace.ts | 2 +- src/agents/chutes-oauth.ts | 2 +- src/agents/cli-credentials.ts | 2 +- src/agents/cli-runner.ts | 2 +- src/agents/cli-runner/helpers.ts | 4 +- src/agents/compaction.e2e.test.ts | 2 +- src/agents/compaction.retry.test.ts | 13 +- ...compaction.tool-result-details.e2e.test.ts | 8 +- src/agents/compaction.ts | 7 +- src/agents/google-gemini-switch.live.test.ts | 2 +- src/agents/minimax.live.test.ts | 3 +- src/agents/model-auth.e2e.test.ts | 2 +- src/agents/model-auth.ts | 3 +- src/agents/model-compat.e2e.test.ts | 2 +- src/agents/model-compat.ts | 2 +- src/agents/model-forward-compat.test.ts | 2 +- src/agents/model-forward-compat.ts | 2 +- src/agents/model-scan.ts | 11 +- src/agents/models.profiles.live.test.ts | 3 +- src/agents/ollama-stream.ts | 6 +- .../openai-responses.reasoning-replay.test.ts | 4 +- ...lpers.formatassistanterrortext.e2e.test.ts | 2 +- ...tant-text-blocks-but-preserves.e2e.test.ts | 2 +- ...mbedded-helpers.validate-turns.e2e.test.ts | 2 +- src/agents/pi-embedded-helpers/bootstrap.ts | 2 +- src/agents/pi-embedded-helpers/errors.ts | 2 +- src/agents/pi-embedded-helpers/images.ts | 2 +- src/agents/pi-embedded-helpers/openai.ts | 2 +- src/agents/pi-embedded-helpers/turns.ts | 2 +- ...pi-embedded-runner-extraparams.e2e.test.ts | 8 +- ...i-embedded-runner-extraparams.live.test.ts | 4 +- ...ner.applygoogleturnorderingfix.e2e.test.ts | 4 +- src/agents/pi-embedded-runner.e2e.test.ts | 9 +- ...unner.google-sanitize-thinking.e2e.test.ts | 4 +- .../pi-embedded-runner.guard.e2e.test.ts | 4 +- ...ner.guard.waitforidle-before-flush.test.ts | 4 +- ...edded-runner.limithistoryturns.e2e.test.ts | 2 +- ...er.openai-tool-id-preservation.e2e.test.ts | 2 +- ...pi-agent.auth-profile-rotation.e2e.test.ts | 2 +- ...r.sanitize-session-history.test-harness.ts | 4 +- ...ed-runner.sanitize-session-history.test.ts | 2 +- ...-embedded-runner.splitsdktools.e2e.test.ts | 2 +- src/agents/pi-embedded-runner/compact.ts | 6 +- src/agents/pi-embedded-runner/extensions.ts | 4 +- ...tra-params.cache-retention-default.test.ts | 2 +- src/agents/pi-embedded-runner/extra-params.ts | 18 +- .../extra-params.zai-tool-stream.test.ts | 8 +- .../pi-embedded-runner/google.e2e.test.ts | 2 +- src/agents/pi-embedded-runner/google.ts | 6 +- src/agents/pi-embedded-runner/history.ts | 2 +- src/agents/pi-embedded-runner/model.ts | 2 +- .../run/attempt.e2e.test.ts | 4 +- src/agents/pi-embedded-runner/run/attempt.ts | 16 +- .../run/compaction-timeout.e2e.test.ts | 2 +- .../run/compaction-timeout.ts | 2 +- src/agents/pi-embedded-runner/run/images.ts | 2 +- src/agents/pi-embedded-runner/run/params.ts | 2 +- .../run/payloads.e2e.test.ts | 2 +- src/agents/pi-embedded-runner/run/payloads.ts | 2 +- src/agents/pi-embedded-runner/run/types.ts | 4 +- ...on-history.tool-result-details.e2e.test.ts | 4 +- .../pi-embedded-runner/system-prompt.ts | 6 +- src/agents/pi-embedded-runner/thinking.ts | 2 +- .../tool-result-context-guard.e2e.test.ts | 2 +- .../tool-result-context-guard.ts | 2 +- .../tool-result-truncation.e2e.test.ts | 2 +- .../tool-result-truncation.ts | 6 +- src/agents/pi-embedded-runner/tool-split.ts | 4 +- src/agents/pi-embedded-runner/utils.ts | 2 +- .../pi-embedded-subscribe.e2e-harness.ts | 2 +- ...-embedded-subscribe.handlers.compaction.ts | 2 +- ...pi-embedded-subscribe.handlers.messages.ts | 2 +- ...cribe.handlers.tools.media.test-helpers.ts | 2 +- ...-embedded-subscribe.handlers.tools.test.ts | 2 +- .../pi-embedded-subscribe.handlers.tools.ts | 2 +- .../pi-embedded-subscribe.handlers.types.ts | 2 +- ...scribe.lifecycle-billing-error.e2e.test.ts | 2 +- ...-embedded-subscribe.reply-tags.e2e.test.ts | 2 +- ...t-duplicate-block-replies-text.e2e.test.ts | 2 +- ...lock-replies-text-end-does-not.e2e.test.ts | 2 +- ...ng-as-separate-message-enabled.e2e.test.ts | 2 +- ...esses-output-without-start-tag.e2e.test.ts | 2 +- ...final-answer-block-replies-are.e2e.test.ts | 2 +- ...ngle-line-fenced-blocks-reopen.e2e.test.ts | 2 +- ...ion.subscribeembeddedpisession.e2e.test.ts | 2 +- ...end-block-replies-message-tool.e2e.test.ts | 2 +- src/agents/pi-embedded-subscribe.ts | 2 +- src/agents/pi-embedded-subscribe.types.ts | 2 +- src/agents/pi-embedded-utils.e2e.test.ts | 2 +- src/agents/pi-embedded-utils.ts | 4 +- .../compaction-safeguard.e2e.test.ts | 2 +- .../pi-extensions/compaction-safeguard.ts | 6 +- .../pi-extensions/context-pruning.e2e.test.ts | 4 +- .../context-pruning/extension.ts | 2 +- .../pi-extensions/context-pruning/pruner.ts | 6 +- src/agents/pi-model-discovery.ts | 6 +- ...nition-adapter.after-tool-call.e2e.test.ts | 2 +- .../pi-tool-definition-adapter.e2e.test.ts | 2 +- src/agents/pi-tool-definition-adapter.ts | 4 +- ...iases-schemas-without-dropping.e2e.test.ts | 2 +- src/agents/pi-tools.policy.e2e.test.ts | 2 +- src/agents/pi-tools.read.ts | 4 +- src/agents/pi-tools.ts | 9 +- src/agents/pi-tools.types.ts | 2 +- .../session-tool-result-guard-wrapper.ts | 4 +- .../session-tool-result-guard.e2e.test.ts | 4 +- ...guard.tool-result-persist-hook.e2e.test.ts | 4 +- src/agents/session-tool-result-guard.ts | 6 +- .../session-transcript-repair.e2e.test.ts | 2 +- src/agents/session-transcript-repair.ts | 2 +- src/agents/skills-status.e2e.test.ts | 7 +- src/agents/skills-status.ts | 4 +- ...ills.resolveskillspromptforrun.e2e.test.ts | 7 +- src/agents/skills/bundled-context.ts | 2 +- src/agents/skills/config.ts | 2 +- src/agents/skills/frontmatter.ts | 2 +- src/agents/skills/types.ts | 2 +- src/agents/skills/workspace.ts | 2 +- src/agents/system-prompt-report.ts | 2 +- .../assistant-message-fixtures.ts | 2 +- src/agents/tool-call-id.e2e.test.ts | 2 +- src/agents/tool-call-id.ts | 2 +- src/agents/tool-images.ts | 4 +- src/agents/tool-summaries.ts | 2 +- src/agents/tools/common.ts | 2 +- src/agents/tools/discord-actions-guild.ts | 2 +- src/agents/tools/discord-actions-messaging.ts | 2 +- .../tools/discord-actions-moderation.ts | 2 +- src/agents/tools/discord-actions-presence.ts | 2 +- src/agents/tools/discord-actions.ts | 2 +- src/agents/tools/image-tool.helpers.ts | 2 +- src/agents/tools/image-tool.ts | 3 +- src/agents/tools/memory-tool.ts | 6 +- src/agents/tools/nodes-tool.ts | 2 +- src/agents/tools/slack-actions.ts | 2 +- src/agents/tools/telegram-actions.ts | 2 +- src/agents/tools/whatsapp-actions.ts | 2 +- src/agents/zai.live.test.ts | 2 +- .../reply/commands-export-session.ts | 7 +- .../reply/commands-system-prompt.ts | 2 +- src/auto-reply/reply/session.ts | 2 +- src/auto-reply/types.ts | 2 +- .../discord/handle-action.guild-admin.ts | 2 +- .../plugins/actions/discord/handle-action.ts | 2 +- src/channels/plugins/message-actions.ts | 2 +- src/channels/plugins/types.core.ts | 2 +- src/cli/skills-cli.e2e.test.ts | 7 +- src/cli/skills-cli.test.ts | 2 +- src/commands/auth-choice.e2e.test.ts | 2 +- src/commands/chutes-oauth.ts | 2 +- src/commands/models/list.list-command.ts | 2 +- src/commands/models/list.registry.ts | 2 +- src/commands/onboard-auth.credentials.ts | 2 +- src/commands/onboard-auth.e2e.test.ts | 2 +- src/commands/openai-codex-oauth.test.ts | 2 +- src/commands/openai-codex-oauth.ts | 4 +- src/config/sessions/transcript.ts | 2 +- src/config/sessions/types.ts | 2 +- .../gateway-models.profiles.live.test.ts | 2 +- .../chat.abort-persistence.test.ts | 2 +- .../chat.inject.parentid.e2e.test.ts | 2 +- src/gateway/server-methods/chat.ts | 2 +- src/gateway/test-helpers.mocks.ts | 19 +- src/infra/outbound/message-action-runner.ts | 2 +- src/infra/outbound/outbound-send-service.ts | 2 +- src/infra/outbound/tool-payload.ts | 2 +- src/media-understanding/providers/image.ts | 4 +- src/plugin-sdk/slack-message-actions.ts | 2 +- src/plugins/types.ts | 2 +- ...unction-call-comes-after-user-turn.test.ts | 6 +- ...eserves-parameters-type-is-missing.test.ts | 4 +- src/providers/google-shared.test-helpers.ts | 2 +- src/providers/qwen-portal-oauth.ts | 2 +- src/security/audit-extra.async.ts | 2 +- src/sessions/input-provenance.ts | 2 +- src/tts/tts-core.ts | 3 +- src/tts/tts.test.ts | 8 +- src/tui/commands.ts | 2 +- src/tui/components/assistant-message.ts | 2 +- src/tui/components/chat-log.ts | 4 +- src/tui/components/custom-editor.ts | 2 +- src/tui/components/filterable-select-list.ts | 10 +- src/tui/components/searchable-select-list.ts | 8 +- src/tui/components/selectors.ts | 7 +- src/tui/components/tool-execution.ts | 2 +- src/tui/components/user-message.ts | 2 +- src/tui/components/welcome-screen.ts | 4 +- src/tui/enriched-autocomplete.test.ts | 40 +- src/tui/enriched-autocomplete.ts | 13 +- src/tui/keybinding-resolver.test.ts | 27 +- src/tui/keybinding-resolver.ts | 17 +- src/tui/theme/theme-factory.ts | 2 +- src/tui/tui-command-handlers.ts | 2 +- src/tui/tui-local-shell.ts | 2 +- src/tui/tui-overlays.test.ts | 2 +- src/tui/tui-overlays.ts | 2 +- src/tui/tui-session-actions.test.ts | 2 +- src/tui/tui-session-actions.ts | 2 +- src/tui/tui.ts | 2 +- 226 files changed, 1152 insertions(+), 1236 deletions(-) diff --git a/apps/macos/Sources/Mayros/ModelCatalogLoader.swift b/apps/macos/Sources/Mayros/ModelCatalogLoader.swift index 0432b328..18bfaf72 100644 --- a/apps/macos/Sources/Mayros/ModelCatalogLoader.swift +++ b/apps/macos/Sources/Mayros/ModelCatalogLoader.swift @@ -114,7 +114,7 @@ enum ModelCatalogLoader { ] for root in roots { let candidate = root - .appendingPathComponent("node_modules/@mariozechner/pi-ai/dist/models.generated.js") + .appendingPathComponent("node_modules/@earendil-works/pi-ai/dist/models.generated.js") if FileManager().isReadableFile(atPath: candidate.path) { return candidate.path } diff --git a/docs/concepts/oauth.md b/docs/concepts/oauth.md index fe11ab4c..da93712e 100644 --- a/docs/concepts/oauth.md +++ b/docs/concepts/oauth.md @@ -71,7 +71,7 @@ mayros models status ## OAuth exchange (how login works) -Mayros’s interactive login flows are implemented in `@mariozechner/pi-ai` and wired into the wizards/commands. +Mayros’s interactive login flows are implemented in `@earendil-works/pi-ai` and wired into the wizards/commands. ### Anthropic (Claude Pro/Max) setup-token diff --git a/docs/gateway/doctor.md b/docs/gateway/doctor.md index 04a4ae45..fae508d7 100644 --- a/docs/gateway/doctor.md +++ b/docs/gateway/doctor.md @@ -129,7 +129,7 @@ Current migrations: ### 2b) OpenCode Zen provider overrides If you’ve added `models.providers.opencode` (or `opencode-zen`) manually, it -overrides the built-in OpenCode Zen catalog from `@mariozechner/pi-ai`. That can +overrides the built-in OpenCode Zen catalog from `@earendil-works/pi-ai`. That can force every model onto a single API or zero out costs. Doctor warns so you can remove the override and restore per-model API routing + costs. diff --git a/docs/pi.md b/docs/pi.md index f5fc0c74..3944e4c4 100644 --- a/docs/pi.md +++ b/docs/pi.md @@ -21,10 +21,10 @@ Mayros uses the pi SDK to embed an AI coding agent into its messaging gateway ar ```json { - "@mariozechner/pi-agent-core": "0.49.3", - "@mariozechner/pi-ai": "0.49.3", - "@mariozechner/pi-coding-agent": "0.49.3", - "@mariozechner/pi-tui": "0.49.3" + "@earendil-works/pi-agent-core": "0.49.3", + "@earendil-works/pi-ai": "0.49.3", + "@earendil-works/pi-coding-agent": "0.49.3", + "@earendil-works/pi-tui": "0.49.3" } ``` @@ -164,7 +164,7 @@ import { DefaultResourceLoader, SessionManager, SettingsManager, -} from "@mariozechner/pi-coding-agent"; +} from "@earendil-works/pi-coding-agent"; const resourceLoader = new DefaultResourceLoader({ cwd: resolvedWorkspace, @@ -504,7 +504,7 @@ Mayros also has a local TUI mode that uses pi-tui components directly: ```typescript // src/tui/tui.ts -import { ... } from "@mariozechner/pi-tui"; +import { ... } from "@earendil-works/pi-tui"; ``` This provides the interactive terminal experience similar to pi's native mode. diff --git a/docs/reference/session-management-compaction.md b/docs/reference/session-management-compaction.md index 8f1c43a3..0080299f 100644 --- a/docs/reference/session-management-compaction.md +++ b/docs/reference/session-management-compaction.md @@ -123,7 +123,7 @@ The store is safe to edit, but the Gateway is the authority: it may rewrite or r ## Transcript structure (`*.jsonl`) -Transcripts are managed by `@mariozechner/pi-coding-agent`’s `SessionManager`. +Transcripts are managed by `@earendil-works/pi-coding-agent`’s `SessionManager`. The file is JSONL: diff --git a/extensions/browser-automation/index.ts b/extensions/browser-automation/index.ts index ce407915..835d50f5 100644 --- a/extensions/browser-automation/index.ts +++ b/extensions/browser-automation/index.ts @@ -46,7 +46,8 @@ const browserAutomationPlugin = { }, required: ["url"], }, - execute: async (_toolCallId: string, args: Record) => { + execute: async (_toolCallId: string, rawArgs: unknown) => { + const args = rawArgs as Record; const { BrowserClient } = await import("./browser-client.js"); const client = new BrowserClient(); await client.connect(); @@ -110,7 +111,8 @@ const browserAutomationPlugin = { }, required: ["selector"], }, - execute: async (_toolCallId: string, args: Record) => { + execute: async (_toolCallId: string, rawArgs: unknown) => { + const args = rawArgs as Record; const { BrowserClient } = await import("./browser-client.js"); const client = new BrowserClient(); await client.connect(); @@ -141,7 +143,8 @@ const browserAutomationPlugin = { }, required: ["expression"], }, - execute: async (_toolCallId: string, args: Record) => { + execute: async (_toolCallId: string, rawArgs: unknown) => { + const args = rawArgs as Record; const { BrowserClient } = await import("./browser-client.js"); const client = new BrowserClient(); await client.connect(); diff --git a/extensions/kakeru-bridge/index.ts b/extensions/kakeru-bridge/index.ts index 379a4980..163d6fc6 100644 --- a/extensions/kakeru-bridge/index.ts +++ b/extensions/kakeru-bridge/index.ts @@ -88,15 +88,13 @@ const kakeruPlugin = { ), timeout: Type.Optional(Type.Number({ description: "Timeout in ms" })), }), - execute: async ( - _toolCallId: string, - params: { + execute: async (_toolCallId: string, rawParams: unknown) => { + const params = rawParams as { platform: string; prompt: string; workDir?: string; timeout?: number; - }, - ) => { + }; const bridge = coordinator.getBridge(params.platform); if (!bridge) { return { @@ -148,12 +146,10 @@ const kakeruPlugin = { }), ), }), - execute: async ( - _toolCallId: string, - params: { + execute: async (_toolCallId: string, rawParams: unknown) => { + const params = rawParams as { tasks: Array<{ platform: string; prompt: string; filePaths?: string[] }>; - }, - ) => { + }; const workDir = ((api.config as Record | undefined)?.workspaceDir as | string diff --git a/extensions/matrix/src/tool-actions.ts b/extensions/matrix/src/tool-actions.ts index cc187e7b..d08f512e 100644 --- a/extensions/matrix/src/tool-actions.ts +++ b/extensions/matrix/src/tool-actions.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import { createActionGate, jsonResult, diff --git a/extensions/osameru-governance/index.ts b/extensions/osameru-governance/index.ts index 1a3de3aa..5f360dd0 100644 --- a/extensions/osameru-governance/index.ts +++ b/extensions/osameru-governance/index.ts @@ -182,15 +182,13 @@ const osameruPlugin = { ), limit: Type.Optional(Type.Number({ description: "Max entries to return" })), }), - execute: async ( - _toolCallId: string, - params: { + execute: async (_toolCallId: string, rawParams: unknown) => { + const params = rawParams as { event?: string; actor?: string; decision?: string; limit?: number; - }, - ) => { + }; const entries = await auditTrail.query(params); return { content: [ diff --git a/extensions/voice-call/index.ts b/extensions/voice-call/index.ts index 645eed5f..f18b30ed 100644 --- a/extensions/voice-call/index.ts +++ b/extensions/voice-call/index.ts @@ -349,7 +349,15 @@ const voiceCallPlugin = { label: "Voice Call", description: "Make phone calls and have voice conversations via the voice-call plugin.", parameters: VoiceCallToolSchema, - async execute(_toolCallId, params) { + async execute(_toolCallId, rawParams) { + const params = rawParams as { + action?: string; + message?: string; + to?: string; + mode?: string; + callId?: string; + sid?: string; + }; const json = (payload: unknown) => ({ content: [{ type: "text" as const, text: JSON.stringify(payload, null, 2) }], details: payload, diff --git a/package.json b/package.json index 031db48a..d4584c93 100644 --- a/package.json +++ b/package.json @@ -164,15 +164,15 @@ "@buape/carbon": "0.0.0-beta-20260216184201", "@clack/prompts": "^1.0.1", "@discordjs/voice": "^0.19.0", + "@earendil-works/pi-agent-core": "^0.80.2", + "@earendil-works/pi-ai": "^0.80.2", + "@earendil-works/pi-coding-agent": "^0.80.2", + "@earendil-works/pi-tui": "^0.80.2", "@grammyjs/runner": "^2.0.3", "@grammyjs/transformer-throttler": "^1.2.1", "@homebridge/ciao": "^1.3.5", "@line/bot-sdk": "^10.6.0", "@lydell/node-pty": "1.2.0-beta.3", - "@mariozechner/pi-agent-core": "0.54.0", - "@mariozechner/pi-ai": "0.54.0", - "@mariozechner/pi-coding-agent": "0.54.0", - "@mariozechner/pi-tui": "0.54.0", "@mozilla/readability": "^0.6.0", "@noble/curves": "^2.0.1", "@sinclair/typebox": "0.34.48", @@ -249,6 +249,7 @@ "pnpm": { "minimumReleaseAge": 2880, "overrides": { + "@apilium/mayros": "workspace:*", "hono": "4.12.7", "@hono/node-server": "1.19.10", "fast-xml-parser": ">=5.5.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 39bc2a0e..d458b3d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,7 @@ settings: excludeLinksFromLockfile: false overrides: + '@apilium/mayros': workspace:* hono: 4.12.7 '@hono/node-server': 1.19.10 fast-xml-parser: '>=5.5.7' @@ -37,13 +38,25 @@ importers: version: 3.1019.0 '@buape/carbon': specifier: 0.0.0-beta-20260216184201 - version: 0.0.0-beta-20260216184201(hono@4.12.7)(opusscript@0.0.8)(opusscript@0.0.8) + version: 0.0.0-beta-20260216184201(hono@4.12.7)(opusscript@0.0.8) '@clack/prompts': specifier: ^1.0.1 version: 1.0.1 '@discordjs/voice': specifier: ^0.19.0 - version: 0.19.0(opusscript@0.0.8)(opusscript@0.0.8) + version: 0.19.0(opusscript@0.0.8) + '@earendil-works/pi-agent-core': + specifier: ^0.80.2 + version: 0.80.2(ws@8.19.0)(zod@4.3.6) + '@earendil-works/pi-ai': + specifier: ^0.80.2 + version: 0.80.2(ws@8.19.0)(zod@4.3.6) + '@earendil-works/pi-coding-agent': + specifier: ^0.80.2 + version: 0.80.2(ws@8.19.0)(zod@4.3.6) + '@earendil-works/pi-tui': + specifier: ^0.80.2 + version: 0.80.2 '@grammyjs/runner': specifier: ^2.0.3 version: 2.0.3(grammy@1.40.0) @@ -59,18 +72,6 @@ importers: '@lydell/node-pty': specifier: 1.2.0-beta.3 version: 1.2.0-beta.3 - '@mariozechner/pi-agent-core': - specifier: 0.54.0 - version: 0.54.0(ws@8.19.0)(zod@4.3.6) - '@mariozechner/pi-ai': - specifier: 0.54.0 - version: 0.54.0(ws@8.19.0)(zod@4.3.6) - '@mariozechner/pi-coding-agent': - specifier: 0.54.0 - version: 0.54.0(ws@8.19.0)(zod@4.3.6) - '@mariozechner/pi-tui': - specifier: 0.54.0 - version: 0.54.0 '@mozilla/readability': specifier: ^0.6.0 version: 0.6.0 @@ -290,8 +291,8 @@ importers: extensions/bluebubbles: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. extensions/ci-plugin: dependencies: @@ -341,8 +342,8 @@ importers: extensions/diagnostics-otel: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. '@opentelemetry/api': specifier: ^1.9.0 version: 1.9.0 @@ -380,8 +381,8 @@ importers: extensions/discord: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. extensions/eruberu: dependencies: @@ -396,8 +397,8 @@ importers: extensions/feishu: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. '@larksuiteoapi/node-sdk': specifier: ^1.59.0 version: 1.59.0 @@ -469,8 +470,8 @@ importers: extensions/irc: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. zod: specifier: ^4.3.6 version: 4.3.6 @@ -510,8 +511,8 @@ importers: extensions/lobster: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. '@sinclair/typebox': specifier: 0.34.48 version: 0.34.48 @@ -525,8 +526,8 @@ importers: extensions/matrix: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. '@matrix-org/matrix-sdk-crypto-nodejs': specifier: ^0.4.0 version: 0.4.0 @@ -610,8 +611,8 @@ importers: extensions/msteams: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. '@microsoft/agents-hosting': specifier: ^1.3.1 version: 1.3.1 @@ -622,8 +623,8 @@ importers: extensions/nextcloud-talk: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. zod: specifier: ^4.3.6 version: 4.3.6 @@ -631,8 +632,8 @@ importers: extensions/nostr: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. nostr-tools: specifier: ^2.23.1 version: 2.23.1(typescript@5.9.3) @@ -759,8 +760,8 @@ importers: extensions/voice-call: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. '@sinclair/typebox': specifier: 0.34.48 version: 0.34.48 @@ -780,8 +781,8 @@ importers: extensions/zalo: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. undici: specifier: '>=7.24.0' version: 7.24.2 @@ -789,8 +790,8 @@ importers: extensions/zalouser: dependencies: '@apilium/mayros': - specifier: '>=0.1.0' - version: 0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3)) + specifier: workspace:* + version: link:../.. '@sinclair/typebox': specifier: 0.34.48 version: 0.34.48 @@ -819,7 +820,7 @@ importers: version: 0.25.12 vitest: specifier: ^3.0.0 - version: 3.2.4(@types/node@25.3.0)(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18))(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + version: 3.2.4(@types/node@25.3.0)(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18))(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) ui: dependencies: @@ -849,17 +850,17 @@ importers: version: 0.21.1(signal-polyfill@0.2.2) vite: specifier: 7.3.1 - version: 7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + version: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) devDependencies: '@vitest/browser-playwright': specifier: 4.0.18 - version: 4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) + version: 4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) playwright: specifier: ^1.58.2 version: 1.58.2 vitest: specifier: 4.0.18 - version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) packages: @@ -868,8 +869,8 @@ packages: peerDependencies: zod: ^3.25.0 || ^4.0.0 - '@anthropic-ai/sdk@0.73.0': - resolution: {integrity: sha512-URURVzhxXGJDGUGFunIOtBlSl7KWvZiAAKY/ttTkZAkXT9bTPqdk2eK0b8qqSxXpikh3QKPnPYpiyX98zf5ebw==} + '@anthropic-ai/sdk@0.91.1': + resolution: {integrity: sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==} hasBin: true peerDependencies: zod: ^3.25.0 || ^4.0.0 @@ -877,14 +878,6 @@ packages: zod: optional: true - '@apilium/mayros@0.1.1': - resolution: {integrity: sha512-mtW1hseokxhgGsx5fvekJ+HeDngsyIV9iPC3Btk0r6hfzG+UGx5gc0vX5+aM0YShk0bC1k3lbYs6GrpeC6Dyng==} - engines: {node: '>=22.12.0'} - hasBin: true - peerDependencies: - '@napi-rs/canvas': ^0.1.89 - node-llama-cpp: 3.15.1 - '@aws-crypto/crc32@5.2.0': resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} engines: {node: '>=16.0.0'} @@ -902,8 +895,8 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-bedrock-runtime@3.997.0': - resolution: {integrity: sha512-yEgCc/HvI7dLeXQLCuc4cnbzwE/NbNpKX8NmSSWTy3jnjiMZwrNKdHMBgPoNvaEb0klHhnTyO+JCHVVCPI/eYw==} + '@aws-sdk/client-bedrock-runtime@3.1048.0': + resolution: {integrity: sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==} engines: {node: '>=20.0.0'} '@aws-sdk/client-bedrock@3.1019.0': @@ -914,44 +907,80 @@ packages: resolution: {integrity: sha512-TNrx7eq6nKNOO62HWPqoBqPLXEkW6nLZQGwjL6lq1jZtigWYbK1NbCnT7mKDzbLMHZfuOECUt3n6CzxjUW9HWQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/core@3.974.23': + resolution: {integrity: sha512-MiWR/uWjxjFXGzrE0Ghc5lWxUxzHsUWFhV+OX7M4cR9SrmrnZs6TXavnCWnzzdwJeFri34xQo81rvGNzK3c4BQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-env@3.972.23': resolution: {integrity: sha512-EamaclJcCEaPHp6wiVknNMM2RlsPMjAHSsYSFLNENBM8Wz92QPc6cOn3dif6vPDQt0Oo4IEghDy3NMDCzY/IvA==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-env@3.972.49': + resolution: {integrity: sha512-liB3yQNHCM9k/gu/w36XHMKPluT7HTlnGUhRbBGSISDQkcr/Sy1zsZabiuvQj8WG5yW573u9RehrBvvnIQ9OEQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-http@3.972.25': resolution: {integrity: sha512-qPymamdPcLp6ugoVocG1y5r69ScNiRzb0hogX25/ij+Wz7c7WnsgjLTaz7+eB5BfRxeyUwuw5hgULMuwOGOpcw==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-http@3.972.51': + resolution: {integrity: sha512-XET0H2oofciJ5lMRWNIvRjAP7Q3wv2XT+JtJJEdhPWUMwe3TvQ9qcxonpu7vXmNngncvFpi4E2It+Tamas/naA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-ini@3.972.26': resolution: {integrity: sha512-xKxEAMuP6GYx2y5GET+d3aGEroax3AgGfwBE65EQAUe090lzyJ/RzxPX9s8v7Z6qAk0XwfQl+LrmH05X7YvTeg==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-ini@3.972.56': + resolution: {integrity: sha512-IAmc61hbgQiHht9U3x0tnRwz0lzdwOwD/i9voRgdJrKamF+JtmrBOsW9GwB7mfFonNWOWL4qARWYrF8veEMe3w==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-login@3.972.26': resolution: {integrity: sha512-EFcM8RM3TUxnZOfMJo++3PnyxFu1fL/huzmn3Vh+8IWRgqZawUD3cRwwOr+/4bE9DpyHaLOWFAjY0lfK5X9ZkQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-login@3.972.55': + resolution: {integrity: sha512-hBBkANo3cDn+h2qxxzER4a+J8JCO9o9Z/YYmU7iky6AcaarX5RRdRcHNC6SLdwY0vAXQygn6soUbDqPn3GghaA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-node@3.972.27': resolution: {integrity: sha512-jXpxSolfFnPVj6GCTtx3xIdWNoDR7hYC/0SbetGZxOC9UnNmipHeX1k6spVstf7eWJrMhXNQEgXC0pD1r5tXIg==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-node@3.972.58': + resolution: {integrity: sha512-OyCLVmSI7pZO8hxwNVX6pXhTVlJqRBTp+ijdEfJSUj0RyjHnF602OfAarOzGq6wkGodeFkYBt8MmJ6A6ycRgWw==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-process@3.972.23': resolution: {integrity: sha512-IL/TFW59++b7MpHserjUblGrdP5UXy5Ekqqx1XQkERXBFJcZr74I7VaSrQT5dxdRMU16xGK4L0RQ5fQG1pMgnA==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-process@3.972.49': + resolution: {integrity: sha512-C8h36lBuC/RnBSsjlO+dn6xZm3KbAl5vpJaVPAfQnMmz2/OISmKOc8XZcqMQgO2ADwBYNRMM6Kf3vz9G/TulMQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-sso@3.972.26': resolution: {integrity: sha512-c6ghvRb6gTlMznWhGxn/bpVCcp0HRaz4DobGVD9kI4vwHq186nU2xN/S7QGkm0lo0H2jQU8+dgpUFLxfTcwCOg==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-sso@3.972.55': + resolution: {integrity: sha512-1FkOz74Ea5QGS9jtIoXp55T/IkSS3spv+nLTT07fRY/+T5xmEOqaYBVIaEmX4zTNvbV6g2lrtlaVKWEoNyJt3w==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-web-identity@3.972.26': resolution: {integrity: sha512-cXcS3+XD3iwhoXkM44AmxjmbcKueoLCINr1e+IceMmCySda5ysNIfiGBGe9qn5EMiQ9Jd7pP0AGFtcd6OV3Lvg==} engines: {node: '>=20.0.0'} - '@aws-sdk/eventstream-handler-node@3.972.7': - resolution: {integrity: sha512-p8k2ZWKJVrR3KIcBbI+/+FcWXdwe3LLgGnixsA7w8lDwWjzSVDHFp6uPeSqBt5PQpRxzak9EheJ1xTmOnHGf4g==} + '@aws-sdk/credential-provider-web-identity@3.972.55': + resolution: {integrity: sha512-g2BoECD1q01kTPByi56+VLVvdWDzMkKIcr77qixpqH0okw2t0U5CoPv+6S8v/D1Y2Wa6QKKtn6XAtDzP+Kfpvg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/eventstream-handler-node@3.972.22': + resolution: {integrity: sha512-tqPJv0dz4+O0hWGm1a6YekcMZyPhDFs/zH73Von7icaVT5n0Jqvm86typ3jRrG+qoUdPhALOnboRLTmnWQTlYQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-eventstream@3.972.4': - resolution: {integrity: sha512-0t+2Dn46cRE9iu5ynUXINBtR0wNHi/Jz3FbrqS5k3dGot2O7Ln1xCqXbJUAtGM5ZAqN77SbnpETAgVWC84DeoA==} + '@aws-sdk/middleware-eventstream@3.972.18': + resolution: {integrity: sha512-OHpk8YoZi3yexPq8aFt1vN1IxA2zLKvsIR5GpWYylX/ve6kQmY7wxHNSFy/D3t2apMZ16rs76Co4dJWcDyIk3A==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-host-header@3.972.8': @@ -970,24 +999,40 @@ packages: resolution: {integrity: sha512-AilFIh4rI/2hKyyGN6XrB0yN96W2o7e7wyrPWCM6QjZM1mcC/pVkW3IWWRvuBWMpVP8Fg+rMpbzeLQ6dTM4gig==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-websocket@3.972.8': - resolution: {integrity: sha512-KPUXz8lRw73Rh12/QkELxiryC9Wi9Ah1xNzFe2Vtbz2/81c2ZA0yM8er+u0iCF/SRMMhDQshLcmRNgn/ueA+gA==} + '@aws-sdk/middleware-websocket@3.972.31': + resolution: {integrity: sha512-ps1rumU1LybSFHaW9dTDgkhCMJLVaedEY78kKSzUDDY+b9974/g6aiaYYA0U9WV0oL4CJCJrVWG+EZ/qr4or7g==} engines: {node: '>= 14.0.0'} '@aws-sdk/nested-clients@3.996.16': resolution: {integrity: sha512-L7Qzoj/qQU1cL5GnYLQP5LbI+wlLCLoINvcykR3htKcQ4tzrPf2DOs72x933BM7oArYj1SKrkb2lGlsJHIic3g==} engines: {node: '>=20.0.0'} + '@aws-sdk/nested-clients@3.997.23': + resolution: {integrity: sha512-gO93ZPsI2bxeFZD42f1/qjDw6FAZkNZcKRO94LIiT03fzOmcJ9e/tunxjVjA1Rl69ClmVJzz8H3G9CdKef10PA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/region-config-resolver@3.972.10': resolution: {integrity: sha512-1dq9ToC6e070QvnVhhbAs3bb5r6cQ10gTVc6cyRV5uvQe7P138TV2uG2i6+Yok4bAkVAcx5AqkTEBUvWEtBlsQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/signature-v4-multi-region@3.996.35': + resolution: {integrity: sha512-6L/VWs+Wch2stHemCGTmUNqKLMzURxQDK5boNG3Jn3kAOp71meDUuS5sbObpEvFxHDq0uWeSLFDNSYsjNt+Dlg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/token-providers@3.1019.0': resolution: {integrity: sha512-OF+2RfRmUKyjzrRWlDcyju3RBsuqcrYDQ8TwrJg8efcOotMzuZN4U9mpVTIdATpmEc4lWNZBMSjPzrGm6JPnAQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.997.0': - resolution: {integrity: sha512-UdG36F7lU9aTqGFRieEyuRUJlgEJBqKeKKekC0esH21DbUSKhPR1kZBah214kYasIaWe1hLJLaqUigoTa5hZAQ==} + '@aws-sdk/token-providers@3.1048.0': + resolution: {integrity: sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1074.0': + resolution: {integrity: sha512-pv80IzgGW4RnXWtft692chZOM9i6PhebVsLCcnaM4dBEPZva2fE6FXAHs76G7Rc7s3yGyX/68G0nZMrUy+Vmpg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.973.13': + resolution: {integrity: sha512-pEHZqRkAlHfnfAU9tK+WpKv/gBNjGJrHMgA3A0iYRGyswBS2t0pfez+lWlwktb3Bqa0ovh7w/QJTFwp3fDxLNg==} engines: {node: '>=20.0.0'} '@aws-sdk/types@3.973.6': @@ -998,10 +1043,6 @@ packages: resolution: {integrity: sha512-Uh93L5sXFNbyR5sEPMzUU8tJ++Ku97EY4udmC01nB8Zu+xfBPwpIwJ6F7snqQeq8h2pf+8SGN5/NoytfKgYPIw==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-format-url@3.972.4': - resolution: {integrity: sha512-rPm9g4WvgTz4ko5kqseIG5Vp5LUAbWBBDalm4ogHLMc0i20ChwQWqwuTUPJSu8zXn43jIM0xO2KZaYQsFJb+ew==} - engines: {node: '>=20.0.0'} - '@aws-sdk/util-locate-window@3.965.4': resolution: {integrity: sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog==} engines: {node: '>=20.0.0'} @@ -1022,6 +1063,10 @@ packages: resolution: {integrity: sha512-iu2pyvaqmeatIJLURLqx9D+4jKAdTH20ntzB6BFwjyN7V960r4jK32mx0Zf7YbtOYAbmbtQfDNuL60ONinyw7A==} engines: {node: '>=20.0.0'} + '@aws-sdk/xml-builder@3.972.31': + resolution: {integrity: sha512-SzE4Pgyl+hDF+BuyuzxUSpwnuUu9lJuO1YGgteG89/4Qv0+2IQiVQqdbPV32IozLvXWQChPQcdkk/sKvb1QHiQ==} + engines: {node: '>=20.0.0'} + '@aws/lambda-invoke-store@0.2.4': resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==} engines: {node: '>=18.0.0'} @@ -1164,6 +1209,24 @@ packages: resolution: {integrity: sha512-UyX6rGEXzVyPzb1yvjHtPfTlnLvB5jX/stAMdiytHhfoydX+98hfympdOwsnTktzr+IRvphxTbdErgYDJkEsvw==} engines: {node: '>=22.12.0'} + '@earendil-works/pi-agent-core@0.80.2': + resolution: {integrity: sha512-BF9WPhixIFjT6Kp3Iz3H6ugkU+4AWotM8py96XE5pIK0arJbQKMWbR+dXSWWDEmR5yc/aFQODnuyowOEzMGO7Q==} + engines: {node: '>=22.19.0'} + + '@earendil-works/pi-ai@0.80.2': + resolution: {integrity: sha512-5GNKfdrRJ4uZ5Zd9iudoXggi/BbUcKnD/xfRHtdR+7q4vWqPvfx8auFuaT+ewGBVI8K4wj87eigFQ/iCSuy9RQ==} + engines: {node: '>=22.19.0'} + hasBin: true + + '@earendil-works/pi-coding-agent@0.80.2': + resolution: {integrity: sha512-m9v7OUit0s9LklWfh61ca/XY5INjUzjtYtNZwy3cNvyjOLk3IpBgghP8aAp0iH35rLaiRwuuWiJ8t88ODMWY+A==} + engines: {node: '>=22.19.0'} + hasBin: true + + '@earendil-works/pi-tui@0.80.2': + resolution: {integrity: sha512-OvOAMIbXiC9OSse17YMiXIsI9AS5XM/ZV8N/k+UzdlRpPILDQYmLElevgGW92kkXR8qHBClIdzhCjuzlBGvphA==} + engines: {node: '>=22.19.0'} + '@emnapi/core@1.8.1': resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} @@ -1485,8 +1548,8 @@ packages: cpu: [x64] os: [win32] - '@google/genai@1.42.0': - resolution: {integrity: sha512-+3nlMTcrQufbQ8IumGkOphxD5Pd5kKyJOzLcnY0/1IuE8upJk5aLmoexZ2BJhBp1zAjRJMEB4a2CJwKI9e2EYw==} + '@google/genai@1.52.0': + resolution: {integrity: sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==} engines: {node: '>=20.0.0'} peerDependencies: '@modelcontextprotocol/sdk': ^1.25.2 @@ -1831,91 +1894,69 @@ packages: '@lydell/node-pty@1.2.0-beta.3': resolution: {integrity: sha512-ngGAItlRhmJXrhspxt8kX13n1dVFqzETOq0m/+gqSkO8NJBvNMwP7FZckMwps2UFySdr4yxCXNGu/bumg5at6A==} - '@mariozechner/clipboard-darwin-arm64@0.3.2': - resolution: {integrity: sha512-uBf6K7Je1ihsgvmWxA8UCGCeI+nbRVRXoarZdLjl6slz94Zs1tNKFZqx7aCI5O1i3e0B6ja82zZ06BWrl0MCVw==} + '@mariozechner/clipboard-darwin-arm64@0.3.9': + resolution: {integrity: sha512-BfgV7vCEWZwJwZJw03r6bP5+tf0iI/ANuQYCxi9RNn7FrWB3yzGuMKCrNLRl6V761vXRdL8+OqZ0wd4TqlsNOQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@mariozechner/clipboard-darwin-universal@0.3.2': - resolution: {integrity: sha512-mxSheKTW2U9LsBdXy0SdmdCAE5HqNS9QUmpNHLnfJ+SsbFKALjEZc5oRrVMXxGQSirDvYf5bjmRyT0QYYonnlg==} + '@mariozechner/clipboard-darwin-universal@0.3.9': + resolution: {integrity: sha512-BGGR4iA9Z2shAjI65eI5xtyb3LYNlDW9X3gxKxDbqtbnREohsrqznov6zpKoIrsRWpzlYVEdKphS7ksJ0/ndSQ==} engines: {node: '>= 10'} os: [darwin] - '@mariozechner/clipboard-darwin-x64@0.3.2': - resolution: {integrity: sha512-U1BcVEoidvwIp95+HJswSW+xr28EQiHR7rZjH6pn8Sja5yO4Yoe3yCN0Zm8Lo72BbSOK/fTSq0je7CJpaPCspg==} + '@mariozechner/clipboard-darwin-x64@0.3.9': + resolution: {integrity: sha512-4kURmCbS6nt8uYhtmWpUcJWyPHfmAr5dTpXD1nO3pIfa+TSQ9DbrGOYCKH+aEFW47XhQ4Vp8ZTszie+wfFvDKg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@mariozechner/clipboard-linux-arm64-gnu@0.3.2': - resolution: {integrity: sha512-BsinwG3yWTIjdgNCxsFlip7LkfwPk+ruw/aFCXHUg/fb5XC/Ksp+YMQ7u0LUtiKzIv/7LMXgZInJQH6gxbAaqQ==} + '@mariozechner/clipboard-linux-arm64-gnu@0.3.9': + resolution: {integrity: sha512-g59OkUGP2DDfCOIKypHeYgv2M55u/cKvXa5dSxFbEJ34XvIQMdcVmpKCkGUro3ZgefXiGVdwguvTMQGpHWzIXw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@mariozechner/clipboard-linux-arm64-musl@0.3.2': - resolution: {integrity: sha512-0/Gi5Xq2V6goXBop19ePoHvXsmJD9SzFlO3S+d6+T2b+BlPcpOu3Oa0wTjl+cZrLAAEzA86aPNBI+VVAFDFPKw==} + '@mariozechner/clipboard-linux-arm64-musl@0.3.9': + resolution: {integrity: sha512-AGuJdgKsmJdm4Pych7kv3sqe591ERRaAHW3xjLooiFzn8J+PxUyof++7YZrB5Y5tpnTO+K18Og3taj2NpluCRQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@mariozechner/clipboard-linux-riscv64-gnu@0.3.2': - resolution: {integrity: sha512-2AFFiXB24qf0zOZsxI1GJGb9wQGlOJyN6UwoXqmKS3dpQi/l6ix30IzDDA4c4ZcCcx4D+9HLYXhC1w7Sov8pXA==} + '@mariozechner/clipboard-linux-riscv64-gnu@0.3.9': + resolution: {integrity: sha512-DXBEAiuMpk7dhS1a9NzNxVAFi1vaKoPu7rQNgY8LIDLGrK3lnIp3nT10DUum+PKVJoJppIP+NAA8IZe4DMNDPw==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] - '@mariozechner/clipboard-linux-x64-gnu@0.3.2': - resolution: {integrity: sha512-v6fVnsn7WMGg73Dab8QMwyFce7tzGfgEixKgzLP8f1GJqkJZi5zO4k4FOHzSgUufgLil63gnxvMpjWkgfeQN7A==} + '@mariozechner/clipboard-linux-x64-gnu@0.3.9': + resolution: {integrity: sha512-WORrMLd6EpElEME7JRKfSaY34nW1P5LbdgK5YNCS1ncG2LqmITsSMEJ8nh2mpvxb3TxqbOOKgY7k9eMJYlW9Mw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@mariozechner/clipboard-linux-x64-musl@0.3.2': - resolution: {integrity: sha512-xVUtnoMQ8v2JVyfJLKKXACA6avdnchdbBkTsZs8BgJQo29qwCp5NIHAUO8gbJ40iaEGToW5RlmVk2M9V0HsHEw==} + '@mariozechner/clipboard-linux-x64-musl@0.3.9': + resolution: {integrity: sha512-/DHn+1DrfL6oRaPPWXaOKvonFFrni666fxd+zFqiQEfvBH0tsHVWjq9iqBk0oDp0qaPA72lIMy5BptxISBEhZQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@mariozechner/clipboard-win32-arm64-msvc@0.3.2': - resolution: {integrity: sha512-AEgg95TNi8TGgak2wSXZkXKCvAUTjWoU1Pqb0ON7JHrX78p616XUFNTJohtIon3e0w6k0pYPZeCuqRCza/Tqeg==} + '@mariozechner/clipboard-win32-arm64-msvc@0.3.9': + resolution: {integrity: sha512-O5FHD3ErkMwMhNzAfu3ggy0ug4z7btZuoQgwwxlzPrwV2bxlD6WDpqBY4NCgICAgZdDKdp+loUEKVAVt8aYnhQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@mariozechner/clipboard-win32-x64-msvc@0.3.2': - resolution: {integrity: sha512-tGRuYpZwDOD7HBrCpyRuhGnHHSCknELvqwKKUG4JSfSB7JIU7LKRh6zx6fMUOQd8uISK35TjFg5UcNih+vJhFA==} + '@mariozechner/clipboard-win32-x64-msvc@0.3.9': + resolution: {integrity: sha512-ihQC3EufqEY81vhXBgVBtK4prL+wc62zJsSvxrgz7K1hsdt6OObz6v9p3Rn1OG3GJksTTKMJF0u/guMISHPhSA==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@mariozechner/clipboard@0.3.2': - resolution: {integrity: sha512-IHQpksNjo7EAtGuHFU+tbWDp5LarH3HU/8WiB9O70ZEoBPHOg0/6afwSLK0QyNMMmx4Bpi/zl6+DcBXe95nWYA==} + '@mariozechner/clipboard@0.3.9': + resolution: {integrity: sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA==} engines: {node: '>= 10'} - '@mariozechner/jiti@2.6.5': - resolution: {integrity: sha512-faGUlTcXka5l7rv0lP3K3vGW/ejRuOS24RR2aSFWREUQqzjgdsuWNo/IiPqL3kWRGt6Ahl2+qcDAwtdeWeuGUw==} - hasBin: true - - '@mariozechner/pi-agent-core@0.54.0': - resolution: {integrity: sha512-LsPoudpOJLj7JjSpjlAdLM5uA2iy8nP+4nA6Si1ASD3tMqXdjHzNaKNloGSODKJO+3O3yhwPMSbuk78CCnZteQ==} - engines: {node: '>=20.0.0'} - - '@mariozechner/pi-ai@0.54.0': - resolution: {integrity: sha512-XHhMIbFFHCa4mbiYdttfhVg6r3VmFD5tAiW4tjnmf33FhLUCRd76bGMQRc4kLWXPKCi/U4nqAErvaGiZUY4B8A==} - engines: {node: '>=20.0.0'} - hasBin: true - - '@mariozechner/pi-coding-agent@0.54.0': - resolution: {integrity: sha512-CO8uLmigLzzep2i5/f05dchyywDYDsqykLxpaMXbwDa/dDzsBRbuWoGQBOAsiGbcCMya6AT5nAggFFo4Aqy/+g==} - engines: {node: '>=20.0.0'} - hasBin: true - - '@mariozechner/pi-tui@0.54.0': - resolution: {integrity: sha512-bvFlUohdxDvKcFeQM2xsd5twCGKWxVaYSlHCFljIW0KqMC4vU+/Ts4A1i9iDnm6Xe/MlueKvC0V09YeC8fLIHA==} - engines: {node: '>=20.0.0'} - '@matrix-org/matrix-sdk-crypto-nodejs@0.4.0': resolution: {integrity: sha512-+qqgpn39XFSbsD0dFjssGO9vHEP7sTyfs8yTpt8vuqWpUpF20QMwpCZi0jpYw7GxjErNTsMshopuo8677DfGEA==} engines: {node: '>= 22'} @@ -1928,8 +1969,13 @@ packages: resolution: {integrity: sha512-570oJr93l1RcCNNaMVpOm+PgQkRgno/F65nH1aCWLIKLnw0o7iPoj+8Z5b7mnLMidg9lldVSCcf0dBxqTGE1/w==} engines: {node: '>=20.0.0'} - '@mistralai/mistralai@1.10.0': - resolution: {integrity: sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg==} + '@mistralai/mistralai@2.2.6': + resolution: {integrity: sha512-W8pX7zHxjJvMIpw8JMxeJEleapXX0Q9NPszdNzqkM3MIEoIGPObdodujj+WHteXEvGfaP/AMwlNyRfEzSY6dQQ==} + peerDependencies: + '@opentelemetry/api': ^1.9.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true '@mozilla/readability@0.6.0': resolution: {integrity: sha512-juG5VWh4qAivzTAeMzvY9xs9HY5rAcr2E4I7tiSSCokRFi7XIZCAu92ZkSTsIj1OPceCifL3cpfteP3pDT9/QQ==} @@ -1941,140 +1987,70 @@ packages: cpu: [arm64] os: [android] - '@napi-rs/canvas-android-arm64@0.1.97': - resolution: {integrity: sha512-V1c/WVw+NzH8vk7ZK/O8/nyBSCQimU8sfMsB/9qeSvdkGKNU7+mxy/bIF0gTgeBFmHpj30S4E9WHMSrxXGQuVQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - '@napi-rs/canvas-darwin-arm64@0.1.95': resolution: {integrity: sha512-F7jT0Syu+B9DGBUBcMk3qCRIxAWiDXmvEjamwbYfbZl7asI1pmXZUnCOoIu49Wt0RNooToYfRDxU9omD6t5Xuw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@napi-rs/canvas-darwin-arm64@0.1.97': - resolution: {integrity: sha512-ok+SCEF4YejcxuJ9Rm+WWunHHpf2HmiPxfz6z1a/NFQECGXtsY7A4B8XocK1LmT1D7P174MzwPF9Wy3AUAwEPw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - '@napi-rs/canvas-darwin-x64@0.1.95': resolution: {integrity: sha512-54eb2Ho15RDjYGXO/harjRznBrAvu+j5nQ85Z4Qd6Qg3slR8/Ja+Yvvy9G4yo7rdX6NR9GPkZeSTf2UcKXwaXw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@napi-rs/canvas-darwin-x64@0.1.97': - resolution: {integrity: sha512-PUP6e6/UGlclUvAQNnuXCcnkpdUou6VYZfQOQxExLp86epOylmiwLkqXIvpFmjoTEDmPmXrI+coL/9EFU1gKPA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.95': resolution: {integrity: sha512-hYaLCSLx5bmbnclzQc3ado3PgZ66blJWzjXp0wJmdwpr/kH+Mwhj6vuytJIomgksyJoCdIqIa4N6aiqBGJtJ5Q==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.97': - resolution: {integrity: sha512-XyXH2L/cic8eTNtbrXCcvqHtMX/nEOxN18+7rMrAM2XtLYC/EB5s0wnO1FsLMWmK+04ZSLN9FBGipo7kpIkcOw==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - '@napi-rs/canvas-linux-arm64-gnu@0.1.95': resolution: {integrity: sha512-J7VipONahKsmScPZsipHVQBqpbZx4favaD8/enWzzlGcjiwycOoymL7f4tNeqdjK0su19bDOUt6mjp9gsPWYlw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@napi-rs/canvas-linux-arm64-gnu@0.1.97': - resolution: {integrity: sha512-Kuq/M3djq0K8ktgz6nPlK7Ne5d4uWeDxPpyKWOjWDK2RIOhHVtLtyLiJw2fuldw7Vn4mhw05EZXCEr4Q76rs9w==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - '@napi-rs/canvas-linux-arm64-musl@0.1.95': resolution: {integrity: sha512-PXy0UT1J/8MPG8UAkWp6Fd51ZtIZINFzIjGH909JjQrtCuJf3X6nanHYdz1A+Wq9o4aoPAw1YEUpFS1lelsVlg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@napi-rs/canvas-linux-arm64-musl@0.1.97': - resolution: {integrity: sha512-kKmSkQVnWeqg7qdsiXvYxKhAFuHz3tkBjW/zyQv5YKUPhotpaVhpBGv5LqCngzyuRV85SXoe+OFj+Tv0a0QXkQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - '@napi-rs/canvas-linux-riscv64-gnu@0.1.95': resolution: {integrity: sha512-2IzCkW2RHRdcgF9W5/plHvYFpc6uikyjMb5SxjqmNxfyDFz9/HB89yhi8YQo0SNqrGRI7yBVDec7Pt+uMyRWsg==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] - '@napi-rs/canvas-linux-riscv64-gnu@0.1.97': - resolution: {integrity: sha512-Jc7I3A51jnEOIAXeLsN/M/+Z28LUeakcsXs07FLq9prXc0eYOtVwsDEv913Gr+06IRo34gJJVgT0TXvmz+N2VA==} - engines: {node: '>= 10'} - cpu: [riscv64] - os: [linux] - '@napi-rs/canvas-linux-x64-gnu@0.1.95': resolution: {integrity: sha512-OV/ol/OtcUr4qDhQg8G7SdViZX8XyQeKpPsVv/j3+7U178FGoU4M+yIocdVo1ih/A8GQ63+LjF4jDoEjaVU8Pw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@napi-rs/canvas-linux-x64-gnu@0.1.97': - resolution: {integrity: sha512-iDUBe7AilfuBSRbSa8/IGX38Mf+iCSBqoVKLSQ5XaY2JLOaqz1TVyPFEyIck7wT6mRQhQt5sN6ogfjIDfi74tg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - '@napi-rs/canvas-linux-x64-musl@0.1.95': resolution: {integrity: sha512-Z5KzqBK/XzPz5+SFHKz7yKqClEQ8pOiEDdgk5SlphBLVNb8JFIJkxhtJKSvnJyHh2rjVgiFmvtJzMF0gNwwKyQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@napi-rs/canvas-linux-x64-musl@0.1.97': - resolution: {integrity: sha512-AKLFd/v0Z5fvgqBDqhvqtAdx+fHMJ5t9JcUNKq4FIZ5WH+iegGm8HPdj00NFlCSnm83Fp3Ln8I2f7uq1aIiWaA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - '@napi-rs/canvas-win32-arm64-msvc@0.1.95': resolution: {integrity: sha512-aj0YbRpe8qVJ4OzMsK7NfNQePgcf9zkGFzNZ9mSuaxXzhpLHmlF2GivNdCdNOg8WzA/NxV6IU4c5XkXadUMLeA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@napi-rs/canvas-win32-arm64-msvc@0.1.97': - resolution: {integrity: sha512-u883Yr6A6fO7Vpsy9YE4FVCIxzzo5sO+7pIUjjoDLjS3vQaNMkVzx5bdIpEL+ob+gU88WDK4VcxYMZ6nmnoX9A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - '@napi-rs/canvas-win32-x64-msvc@0.1.95': resolution: {integrity: sha512-GA8leTTCfdjuHi8reICTIxU0081PhXvl3lzIniLUjeLACx9GubUiyzkwFb+oyeKLS5IAGZFLKnzAf4wm2epRlA==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@napi-rs/canvas-win32-x64-msvc@0.1.97': - resolution: {integrity: sha512-sWtD2EE3fV0IzN+iiQUqr/Q1SwqWhs2O1FKItFlxtdDkikpEj5g7DKQpY3x55H/MAOnL8iomnlk3mcEeGiUMoQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - '@napi-rs/canvas@0.1.95': resolution: {integrity: sha512-lkg23ge+rgyhgUwXmlbkPEhuhHq/hUi/gXKH+4I7vO+lJrbNfEYcQdJLIGjKyXLQzgFiiyDAwh5vAe/tITAE+w==} engines: {node: '>= 10'} - '@napi-rs/canvas@0.1.97': - resolution: {integrity: sha512-8cFniXvrIEnVwuNSRCW9wirRZbHvrD3JVujdS2P5n5xiJZNZMOZcfOvJ1pb66c7jXMKHHglJEDVJGbm8XWFcXQ==} - engines: {node: '>= 10'} - '@napi-rs/wasm-runtime@1.1.1': resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} @@ -2351,6 +2327,10 @@ packages: resolution: {integrity: sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==} engines: {node: '>=14'} + '@opentelemetry/semantic-conventions@1.41.1': + resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==} + engines: {node: '>=14'} + '@oxc-project/types@0.112.0': resolution: {integrity: sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ==} @@ -2631,12 +2611,21 @@ packages: '@protobufjs/codegen@2.0.4': resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} + '@protobufjs/eventemitter@1.1.0': resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + '@protobufjs/eventemitter@1.1.1': + resolution: {integrity: sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==} + '@protobufjs/fetch@1.1.0': resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + '@protobufjs/fetch@1.1.1': + resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==} + '@protobufjs/float@1.0.2': resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} @@ -2652,6 +2641,9 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@protobufjs/utf8@1.1.1': + resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} + '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} @@ -2968,34 +2960,26 @@ packages: resolution: {integrity: sha512-o9VycsYNtgC+Dy3I0yrwCqv9CWicDnke0L7EVOrZtJpjb2t0EjaEofmMrYc0T1Kn3yk32zm6cspxF9u9Bj7e5w==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.2.12': - resolution: {integrity: sha512-cr2lR792vNZcYMriSIj+Um3x9KWrjcu98kn234xA6reOAFMmbRpQMOv8KPgEmLLtx3eldU6c5wALKFqNOhugmg==} - engines: {node: '>=18.0.0'} - - '@smithy/eventstream-codec@4.2.10': - resolution: {integrity: sha512-A4ynrsFFfSXUHicfTcRehytppFBcY3HQxEGYiyGktPIOye3Ot7fxpiy4VR42WmtGI4Wfo6OXt/c1Ky1nUFxYYQ==} - engines: {node: '>=18.0.0'} - - '@smithy/eventstream-serde-browser@4.2.10': - resolution: {integrity: sha512-0xupsu9yj9oDVuQ50YCTS9nuSYhGlrwqdaKQel9y2Fz7LU9fNErVlw9N0o4pm4qqvWEGbSTI4HKc6XJfB30MVw==} - engines: {node: '>=18.0.0'} - - '@smithy/eventstream-serde-config-resolver@4.3.10': - resolution: {integrity: sha512-8kn6sinrduk0yaYHMJDsNuiFpXwQwibR7n/4CDUqn4UgaG+SeBHu5jHGFdU9BLFAM7Q4/gvr9RYxBHz9/jKrhA==} + '@smithy/core@3.26.0': + resolution: {integrity: sha512-mLUktFAn+Pa2agl1J7VgtYNFWCX8/b4GMJSK1hCu4YCvtBfM6F8Os3EP4ry+DFFlXOf3wyvlgXhuUdFoy52D3g==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-node@4.2.10': - resolution: {integrity: sha512-uUrxPGgIffnYfvIOUmBM5i+USdEBRTdh7mLPttjphgtooxQ8CtdO1p6K5+Q4BBAZvKlvtJ9jWyrWpBJYzBKsyQ==} + '@smithy/credential-provider-imds@4.2.12': + resolution: {integrity: sha512-cr2lR792vNZcYMriSIj+Um3x9KWrjcu98kn234xA6reOAFMmbRpQMOv8KPgEmLLtx3eldU6c5wALKFqNOhugmg==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-universal@4.2.10': - resolution: {integrity: sha512-aArqzOEvcs2dK+xQVCgLbpJQGfZihw8SD4ymhkwNTtwKbnrzdhJsFDKuMQnam2kF69WzgJYOU5eJlCx+CA32bw==} + '@smithy/credential-provider-imds@4.4.2': + resolution: {integrity: sha512-18UMDMyrAbDcpmL1gLUA7ww0fRTcdCrSjSJOi2Sbld+tVjwD/pW+OAwjlScFLR7vvBnhZrIPQ7kVuTf1mnJLug==} engines: {node: '>=18.0.0'} '@smithy/fetch-http-handler@5.3.15': resolution: {integrity: sha512-T4jFU5N/yiIfrtrsb9uOQn7RdELdM/7HbyLNr6uO/mpkj1ctiVs7CihVr51w4LyQlXWDpXFn4BElf1WmQvZu/A==} engines: {node: '>=18.0.0'} + '@smithy/fetch-http-handler@5.5.2': + resolution: {integrity: sha512-Ei/UK/QMhq0rKaMqGPlOAkE2yS9DZeYmZdk1RAKc3vp3zxgleZHZyBLlZv8yLsxljX4svCRuMTD6u3LLIcU4Bg==} + engines: {node: '>=18.0.0'} + '@smithy/hash-node@4.2.12': resolution: {integrity: sha512-QhBYbGrbxTkZ43QoTPrK72DoYviDeg6YKDrHTMJbbC+A0sml3kSjzFtXP7BtbyJnXojLfTQldGdUR0RGD8dA3w==} engines: {node: '>=18.0.0'} @@ -3040,6 +3024,14 @@ packages: resolution: {integrity: sha512-Rnq9vQWiR1+/I6NZZMNzJHV6pZYyEHt2ZnuV3MG8z2NNenC4i/8Kzttz7CjZiHSmsN5frhXhg17z3Zqjjhmz1A==} engines: {node: '>=18.0.0'} + '@smithy/node-http-handler@4.7.3': + resolution: {integrity: sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.8.2': + resolution: {integrity: sha512-wfl1uwrAqMH9/pi4kqBo5LBcFwrJLxuDLqL7p7qNcJIFcyZDUc6pzhYk4CYv+DP7fIUpQCZumwNnkhPKS52osQ==} + engines: {node: '>=18.0.0'} + '@smithy/property-provider@4.2.12': resolution: {integrity: sha512-jqve46eYU1v7pZ5BM+fmkbq3DerkSluPr5EhvOcHxygxzD05ByDRppRwRPPpFrsFo5yDtCYLKu+kreHKVrvc7A==} engines: {node: '>=18.0.0'} @@ -3068,6 +3060,10 @@ packages: resolution: {integrity: sha512-B/FBwO3MVOL00DaRSXfXfa/TRXRheagt/q5A2NM13u7q+sHS59EOVGQNfG7DkmVtdQm5m3vOosoKAXSqn/OEgw==} engines: {node: '>=18.0.0'} + '@smithy/signature-v4@5.5.2': + resolution: {integrity: sha512-7xHpmPY4rt0IOmeAA8EfjgEH8isT+587TCdy9H6a7d4OMi5CQ0oEHhWllunvPu4j4Cq0vTFwdxXN/kABWPjdyA==} + engines: {node: '>=18.0.0'} + '@smithy/smithy-client@4.12.7': resolution: {integrity: sha512-q3gqnwml60G44FECaEEsdQMplYhDMZYCtYhMCzadCnRnnHIobZJjegmdoUo6ieLQlPUzvrMdIJUpx6DoPmzANQ==} engines: {node: '>=18.0.0'} @@ -3076,6 +3072,10 @@ packages: resolution: {integrity: sha512-787F3yzE2UiJIQ+wYW1CVg2odHjmaWLGksnKQHUrK/lYZSEcy1msuLVvxaR/sI2/aDe9U+TBuLsXnr3vod1g0g==} engines: {node: '>=18.0.0'} + '@smithy/types@4.15.0': + resolution: {integrity: sha512-Z5TAOxygoFvybJV3igo5SloFflSokHx2hu1eFA+DxDTcn+FtKxUSui+rbTRG1pAafMA888Z3MVvCWUuvCrTXjg==} + engines: {node: '>=18.0.0'} + '@smithy/url-parser@4.2.12': resolution: {integrity: sha512-wOPKPEpso+doCZGIlr+e1lVI6+9VAKfL4kZWFgzVgGWY2hZxshNKod4l2LXS3PRC9otH/JRSjtEHqQ/7eLciRA==} engines: {node: '>=18.0.0'} @@ -3116,10 +3116,6 @@ packages: resolution: {integrity: sha512-VACQVe50j0HZPjpwWcjyT51KUQ4AnsvEaQ2lKHOSL4mNLD0G9BjEniQ+yCt1qqfKfiAHRAts26ud7hBjamrwig==} engines: {node: '>=18.0.0'} - '@smithy/util-hex-encoding@4.2.1': - resolution: {integrity: sha512-c1hHtkgAWmE35/50gmdKajgGAKV3ePJ7t6UtEmpfCWJmQE9BQAQPz0URUVI89eSkcDqCtzqllxzG28IQoZPvwA==} - engines: {node: '>=18.0.0'} - '@smithy/util-hex-encoding@4.2.2': resolution: {integrity: sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==} engines: {node: '>=18.0.0'} @@ -3132,10 +3128,6 @@ packages: resolution: {integrity: sha512-1zopLDUEOwumjcHdJ1mwBHddubYF8GMQvstVCLC54Y46rqoHwlIU+8ZzUeaBcD+WCJHyDGSeZ2ml9YSe9aqcoQ==} engines: {node: '>=18.0.0'} - '@smithy/util-stream@4.5.15': - resolution: {integrity: sha512-OlOKnaqnkU9X+6wEkd7mN+WB7orPbCVDauXOj22Q7VtiTkvy7ZdSsOg4QiNAZMgI4OkvNf+/VLUC3VXkxuWJZw==} - engines: {node: '>=18.0.0'} - '@smithy/util-stream@4.5.20': resolution: {integrity: sha512-4yXLm5n/B5SRBR2p8cZ90Sbv4zL4NKsgxdzCzp/83cXw2KxLEumt5p+GAVyRNZgQOSrzXn9ARpO0lUe8XSlSDw==} engines: {node: '>=18.0.0'} @@ -3173,9 +3165,6 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - '@tootallnate/quickjs-emscripten@0.23.0': - resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - '@twurple/api-call@8.0.3': resolution: {integrity: sha512-/5DBTqFjpYB+qqOkkFzoTWE79a7+I8uLXmBIIIYjGoq/CIPxKcHnlemXlU8cQhTr87PVa3th8zJXGYiNkpRx8w==} @@ -3249,27 +3238,18 @@ packages: '@types/linkify-it@5.0.0': resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} - '@types/long@4.0.2': - resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} - '@types/markdown-it@14.1.2': resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} '@types/mdurl@2.0.0': resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} - '@types/mime-types@2.1.4': - resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} - '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@10.17.60': - resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} - '@types/node@20.19.37': resolution: {integrity: sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==} @@ -3466,10 +3446,6 @@ packages: link-preview-js: optional: true - '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67': - resolution: {tarball: https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67} - version: 2.0.1 - abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -3496,14 +3472,6 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} - ajv-formats@3.0.1: - resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} @@ -3570,10 +3538,6 @@ packages: resolution: {integrity: sha512-trmleAnZ2PxN/loHWVhhx1qeOHSRXq4TDsBBxq3GqeJitfk3+jTQ+v/C1km/KYq9M7wKqCewMh+/NAvVH7m+bw==} engines: {node: '>=20.19.0'} - ast-types@0.13.4: - resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} - engines: {node: '>=4'} - ast-v8-to-istanbul@0.3.11: resolution: {integrity: sha512-Qya9fkoofMjCBNVdWINMjB5KZvkYfaO9/anwkWnjxibpWUxo5iHl2sOdP7/uAqaRuUYuoo8rDwnbaaKVFxoUvw==} @@ -3613,10 +3577,6 @@ packages: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} - basic-ftp@5.2.0: - resolution: {integrity: sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==} - engines: {node: '>=10.0.0'} - bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} @@ -3841,10 +3801,6 @@ packages: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} - data-uri-to-buffer@6.0.2: - resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} - engines: {node: '>= 14'} - debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -3877,10 +3833,6 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - degenerator@5.0.1: - resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} - engines: {node: '>= 14'} - delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -3897,8 +3849,8 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - diff@8.0.3: - resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} engines: {node: '>=0.3.1'} discord-api-types@0.38.37: @@ -4022,27 +3974,9 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - escodegen@2.1.0: - resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} - engines: {node: '>=6.0'} - hasBin: true - - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} @@ -4210,6 +4144,10 @@ packages: resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} 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'} @@ -4221,10 +4159,6 @@ packages: get-tsconfig@4.13.6: resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} - get-uri@6.0.5: - resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} - engines: {node: '>= 14'} - getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} @@ -4303,8 +4237,8 @@ packages: hookified@1.15.1: resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==} - hosted-git-info@9.0.2: - resolution: {integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==} + hosted-git-info@9.0.3: + resolution: {integrity: sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==} engines: {node: ^20.17.0 || >=22.9.0} html-escaper@2.0.2: @@ -4373,10 +4307,6 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - ip-address@10.1.0: - resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} - engines: {node: '>= 12'} - ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -4469,6 +4399,10 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + jose@4.15.9: resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} @@ -4542,12 +4476,13 @@ packages: resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} engines: {node: '>= 8'} - koffi@2.15.1: - resolution: {integrity: sha512-mnc0C0crx/xMSljb5s9QbnLrlFHprioFO1hkXyuSuO/QtbpLDa0l/uM21944UfQunMKmp3/r789DTDxVyyH6aA==} - leac@0.6.0: resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} + libsignal@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/bcea72df9ec34d9d9140ab30619cf479c7c144c7: + resolution: {tarball: https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/bcea72df9ec34d9d9140ab30619cf479c7c144c7} + version: 6.0.0 + lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} @@ -4627,9 +4562,6 @@ packages: resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==} engines: {node: '>=18'} - long@4.0.0: - resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} - long@5.3.2: resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} @@ -4655,10 +4587,6 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - lru-memoizer@2.3.0: resolution: {integrity: sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==} @@ -4676,16 +4604,16 @@ packages: resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} hasBin: true - marked@15.0.12: - resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==} - engines: {node: '>= 18'} - hasBin: true - marked@17.0.3: resolution: {integrity: sha512-jt1v2ObpyOKR8p4XaUJVk3YWRJ5n+i4+rjQopxvV32rSndTJXvIzuUdWWIy/1pFQMkQmvTXawzDNqOH/CUmx6A==} engines: {node: '>= 20'} hasBin: true + marked@18.0.5: + resolution: {integrity: sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==} + engines: {node: '>= 20'} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -4810,10 +4738,6 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} - netmask@2.0.2: - resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} - engines: {node: '>= 0.4.0'} - node-addon-api@8.7.0: resolution: {integrity: sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==} engines: {node: ^18 || ^20 || >= 21} @@ -4913,8 +4837,8 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} - openai@6.10.0: - resolution: {integrity: sha512-ITxOGo7rO3XRMiKA5l7tQ43iNNu+iXGFAcf2t+aWVzzqRaS0i7m1K2BhxNdaveB+5eENhO0VY1FkiZzhBk4v3A==} + openai@6.25.0: + resolution: {integrity: sha512-mEh6VZ2ds2AGGokWARo18aPISI1OhlgdEIC1ewhkZr8pSIT31dec0ecr9Nhxx0JlybyOgoAT1sWeKtwPZzJyww==} hasBin: true peerDependencies: ws: ^8.18.0 @@ -4925,8 +4849,8 @@ packages: zod: optional: true - openai@6.25.0: - resolution: {integrity: sha512-mEh6VZ2ds2AGGokWARo18aPISI1OhlgdEIC1ewhkZr8pSIT31dec0ecr9Nhxx0JlybyOgoAT1sWeKtwPZzJyww==} + openai@6.26.0: + resolution: {integrity: sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==} hasBin: true peerDependencies: ws: ^8.18.0 @@ -4991,14 +4915,6 @@ packages: resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==} engines: {node: '>=20'} - pac-proxy-agent@7.2.0: - resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} - engines: {node: '>= 14'} - - pac-resolver@7.0.1: - resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} - engines: {node: '>= 14'} - package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -5156,14 +5072,14 @@ packages: proper-lockfile@4.1.2: resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} - protobufjs@6.8.8: - resolution: {integrity: sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==} - hasBin: true - protobufjs@7.5.4: resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} engines: {node: '>=12.0.0'} + protobufjs@7.6.4: + resolution: {integrity: sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==} + engines: {node: '>=12.0.0'} + protobufjs@8.0.0: resolution: {integrity: sha512-jx6+sE9h/UryaCZhsJWbJtTEy47yXoGNYI4z8ZaRncM0zBKeRqjO2JEcOUYwrYGb1WLhXM1FfMzW3annvFv0rw==} engines: {node: '>=12.0.0'} @@ -5172,10 +5088,6 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} - proxy-agent@6.5.0: - resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} - engines: {node: '>= 14'} - proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -5355,6 +5267,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.8.0: + resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==} + engines: {node: '>=10'} + hasBin: true + send@0.19.2: resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} engines: {node: '>= 0.8.0'} @@ -5444,18 +5361,6 @@ packages: resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} engines: {node: '>=20'} - smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - - socks-proxy-agent@8.0.5: - resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} - engines: {node: '>= 14'} - - socks@2.8.7: - resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - sonic-boom@4.2.1: resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} @@ -5722,6 +5627,9 @@ packages: resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} engines: {node: '>= 0.6'} + typebox@1.1.38: + resolution: {integrity: sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==} + typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -6022,9 +5930,6 @@ packages: zod@3.25.75: resolution: {integrity: sha512-OhpzAmVzabPOL6C3A3gpAifqr9MqihV/Msx3gor2b2kviCgcb+HM9SEOpMWwwNp9MRunWnhtAKUoo0AHhjyPPg==} - zod@3.25.76: - resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.3.6: resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} @@ -6034,91 +5939,16 @@ snapshots: dependencies: zod: 4.3.6 - '@anthropic-ai/sdk@0.73.0(zod@4.3.6)': + '@anthropic-ai/sdk@0.91.1(zod@4.3.6)': dependencies: json-schema-to-ts: 3.1.1 optionalDependencies: zod: 4.3.6 - '@apilium/mayros@0.1.1(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(hono@4.12.7)(node-llama-cpp@3.17.1(typescript@5.9.3))': - dependencies: - '@agentclientprotocol/sdk': 0.14.1(zod@4.3.6) - '@aws-sdk/client-bedrock': 3.1019.0 - '@buape/carbon': 0.0.0-beta-20260216184201(hono@4.12.7)(opusscript@0.0.8)(opusscript@0.0.8) - '@clack/prompts': 1.0.1 - '@discordjs/opus': opusscript@0.0.8 - '@discordjs/voice': 0.19.0(opusscript@0.0.8)(opusscript@0.0.8) - '@grammyjs/runner': 2.0.3(grammy@1.40.0) - '@grammyjs/transformer-throttler': 1.2.1(grammy@1.40.0) - '@homebridge/ciao': 1.3.5 - '@line/bot-sdk': 10.6.0 - '@lydell/node-pty': 1.2.0-beta.3 - '@mariozechner/pi-agent-core': 0.54.0(ws@8.19.0)(zod@4.3.6) - '@mariozechner/pi-ai': 0.54.0(ws@8.19.0)(zod@4.3.6) - '@mariozechner/pi-coding-agent': 0.54.0(ws@8.19.0)(zod@4.3.6) - '@mariozechner/pi-tui': 0.54.0 - '@mozilla/readability': 0.6.0 - '@napi-rs/canvas': 0.1.97 - '@sinclair/typebox': 0.34.48 - '@slack/bolt': 4.6.0(@types/express@5.0.6) - '@slack/web-api': 7.14.1 - '@whiskeysockets/baileys': 7.0.0-rc.9(sharp@0.34.5) - ajv: 8.18.0 - chalk: 5.6.2 - chokidar: 5.0.0 - cli-highlight: 2.1.11 - commander: 14.0.3 - croner: 10.0.1 - discord-api-types: 0.38.40 - dotenv: 17.3.1 - express: 5.2.1 - file-type: 21.3.2 - grammy: 1.40.0 - https-proxy-agent: 7.0.6 - jiti: 2.6.1 - json5: 2.2.3 - jszip: 3.10.1 - linkedom: 0.18.12 - long: 5.3.2 - markdown-it: 14.1.1 - node-edge-tts: 1.2.10 - node-llama-cpp: 3.17.1(typescript@5.9.3) - opusscript: 0.0.8 - osc-progress: 0.3.0 - pdfjs-dist: 5.4.624 - playwright-core: 1.58.2 - qrcode-terminal: 0.12.0 - quickjs-emscripten: 0.31.0 - semver: 7.7.4 - sharp: 0.34.5 - sqlite-vec: 0.1.7-alpha.2 - tar: 7.5.11 - tslog: 4.10.2 - undici: 7.24.2 - ws: 8.19.0 - yaml: 2.8.3 - zod: 4.3.6 - transitivePeerDependencies: - - '@modelcontextprotocol/sdk' - - '@types/express' - - audio-decode - - aws-crt - - bufferutil - - canvas - - debug - - encoding - - ffmpeg-static - - hono - - jimp - - link-preview-js - - node-opus - - supports-color - - utf-8-validate - '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.13 tslib: 2.8.1 '@aws-crypto/sha256-browser@5.2.0': @@ -6147,57 +5977,22 @@ snapshots: '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-bedrock-runtime@3.997.0': + '@aws-sdk/client-bedrock-runtime@3.1048.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.25 - '@aws-sdk/credential-provider-node': 3.972.27 - '@aws-sdk/eventstream-handler-node': 3.972.7 - '@aws-sdk/middleware-eventstream': 3.972.4 - '@aws-sdk/middleware-host-header': 3.972.8 - '@aws-sdk/middleware-logger': 3.972.8 - '@aws-sdk/middleware-recursion-detection': 3.972.9 - '@aws-sdk/middleware-user-agent': 3.972.26 - '@aws-sdk/middleware-websocket': 3.972.8 - '@aws-sdk/region-config-resolver': 3.972.10 - '@aws-sdk/token-providers': 3.997.0 - '@aws-sdk/types': 3.973.6 - '@aws-sdk/util-endpoints': 3.996.5 - '@aws-sdk/util-user-agent-browser': 3.972.8 - '@aws-sdk/util-user-agent-node': 3.973.12 - '@smithy/config-resolver': 4.4.13 - '@smithy/core': 3.23.12 - '@smithy/eventstream-serde-browser': 4.2.10 - '@smithy/eventstream-serde-config-resolver': 4.3.10 - '@smithy/eventstream-serde-node': 4.2.10 - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/hash-node': 4.2.12 - '@smithy/invalid-dependency': 4.2.12 - '@smithy/middleware-content-length': 4.2.12 - '@smithy/middleware-endpoint': 4.4.27 - '@smithy/middleware-retry': 4.4.44 - '@smithy/middleware-serde': 4.2.15 - '@smithy/middleware-stack': 4.2.12 - '@smithy/node-config-provider': 4.3.12 - '@smithy/node-http-handler': 4.5.0 - '@smithy/protocol-http': 5.3.12 - '@smithy/smithy-client': 4.12.7 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 - '@smithy/util-base64': 4.3.2 - '@smithy/util-body-length-browser': 4.2.2 - '@smithy/util-body-length-node': 4.2.3 - '@smithy/util-defaults-mode-browser': 4.3.43 - '@smithy/util-defaults-mode-node': 4.2.47 - '@smithy/util-endpoints': 3.3.3 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-retry': 4.2.12 - '@smithy/util-stream': 4.5.15 - '@smithy/util-utf8': 4.2.2 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/eventstream-handler-node': 3.972.22 + '@aws-sdk/middleware-eventstream': 3.972.18 + '@aws-sdk/middleware-websocket': 3.972.31 + '@aws-sdk/token-providers': 3.1048.0 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/fetch-http-handler': 5.5.2 + '@smithy/node-http-handler': 4.7.3 + '@smithy/types': 4.15.0 tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt '@aws-sdk/client-bedrock@3.1019.0': dependencies: @@ -6260,6 +6055,17 @@ snapshots: '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 + '@aws-sdk/core@3.974.23': + dependencies: + '@aws-sdk/types': 3.973.13 + '@aws-sdk/xml-builder': 3.972.31 + '@aws/lambda-invoke-store': 0.2.4 + '@smithy/core': 3.26.0 + '@smithy/signature-v4': 5.5.2 + '@smithy/types': 4.15.0 + bowser: 2.14.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-env@3.972.23': dependencies: '@aws-sdk/core': 3.973.25 @@ -6268,6 +6074,14 @@ snapshots: '@smithy/types': 4.13.1 tslib: 2.8.1 + '@aws-sdk/credential-provider-env@3.972.49': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@aws-sdk/credential-provider-http@3.972.25': dependencies: '@aws-sdk/core': 3.973.25 @@ -6281,6 +6095,16 @@ snapshots: '@smithy/util-stream': 4.5.20 tslib: 2.8.1 + '@aws-sdk/credential-provider-http@3.972.51': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/fetch-http-handler': 5.5.2 + '@smithy/node-http-handler': 4.8.2 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@aws-sdk/credential-provider-ini@3.972.26': dependencies: '@aws-sdk/core': 3.973.25 @@ -6300,6 +6124,22 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-ini@3.972.56': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-env': 3.972.49 + '@aws-sdk/credential-provider-http': 3.972.51 + '@aws-sdk/credential-provider-login': 3.972.55 + '@aws-sdk/credential-provider-process': 3.972.49 + '@aws-sdk/credential-provider-sso': 3.972.55 + '@aws-sdk/credential-provider-web-identity': 3.972.55 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/credential-provider-imds': 4.4.2 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@aws-sdk/credential-provider-login@3.972.26': dependencies: '@aws-sdk/core': 3.973.25 @@ -6313,6 +6153,15 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-login@3.972.55': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@aws-sdk/credential-provider-node@3.972.27': dependencies: '@aws-sdk/credential-provider-env': 3.972.23 @@ -6330,6 +6179,20 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-node@3.972.58': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.49 + '@aws-sdk/credential-provider-http': 3.972.51 + '@aws-sdk/credential-provider-ini': 3.972.56 + '@aws-sdk/credential-provider-process': 3.972.49 + '@aws-sdk/credential-provider-sso': 3.972.55 + '@aws-sdk/credential-provider-web-identity': 3.972.55 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/credential-provider-imds': 4.4.2 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@aws-sdk/credential-provider-process@3.972.23': dependencies: '@aws-sdk/core': 3.973.25 @@ -6339,6 +6202,14 @@ snapshots: '@smithy/types': 4.13.1 tslib: 2.8.1 + '@aws-sdk/credential-provider-process@3.972.49': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@aws-sdk/credential-provider-sso@3.972.26': dependencies: '@aws-sdk/core': 3.973.25 @@ -6352,6 +6223,16 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-sso@3.972.55': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/token-providers': 3.1074.0 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@aws-sdk/credential-provider-web-identity@3.972.26': dependencies: '@aws-sdk/core': 3.973.25 @@ -6364,18 +6245,27 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/eventstream-handler-node@3.972.7': + '@aws-sdk/credential-provider-web-identity@3.972.55': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/eventstream-codec': 4.2.10 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/middleware-eventstream@3.972.4': + '@aws-sdk/eventstream-handler-node@3.972.22': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-eventstream@3.972.18': + dependencies: + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 '@aws-sdk/middleware-host-header@3.972.8': @@ -6410,19 +6300,14 @@ snapshots: '@smithy/util-retry': 4.2.12 tslib: 2.8.1 - '@aws-sdk/middleware-websocket@3.972.8': + '@aws-sdk/middleware-websocket@3.972.31': dependencies: - '@aws-sdk/types': 3.973.6 - '@aws-sdk/util-format-url': 3.972.4 - '@smithy/eventstream-codec': 4.2.10 - '@smithy/eventstream-serde-browser': 4.2.10 - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/protocol-http': 5.3.12 - '@smithy/signature-v4': 5.3.12 - '@smithy/types': 4.13.1 - '@smithy/util-base64': 4.3.2 - '@smithy/util-hex-encoding': 4.2.1 - '@smithy/util-utf8': 4.2.2 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/fetch-http-handler': 5.5.2 + '@smithy/signature-v4': 5.5.2 + '@smithy/types': 4.15.0 tslib: 2.8.1 '@aws-sdk/nested-clients@3.996.16': @@ -6468,6 +6353,19 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/nested-clients@3.997.23': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/signature-v4-multi-region': 3.996.35 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/fetch-http-handler': 5.5.2 + '@smithy/node-http-handler': 4.8.2 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@aws-sdk/region-config-resolver@3.972.10': dependencies: '@aws-sdk/types': 3.973.6 @@ -6476,6 +6374,13 @@ snapshots: '@smithy/types': 4.13.1 tslib: 2.8.1 + '@aws-sdk/signature-v4-multi-region@3.996.35': + dependencies: + '@aws-sdk/types': 3.973.13 + '@smithy/signature-v4': 5.5.2 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@aws-sdk/token-providers@3.1019.0': dependencies: '@aws-sdk/core': 3.973.25 @@ -6488,17 +6393,28 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/token-providers@3.997.0': + '@aws-sdk/token-providers@3.1048.0': dependencies: - '@aws-sdk/core': 3.973.25 - '@aws-sdk/nested-clients': 3.996.16 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1074.0': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@aws-sdk/types@3.973.13': + dependencies: + '@smithy/types': 4.15.0 tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt '@aws-sdk/types@3.973.6': dependencies: @@ -6513,13 +6429,6 @@ snapshots: '@smithy/util-endpoints': 3.3.3 tslib: 2.8.1 - '@aws-sdk/util-format-url@3.972.4': - dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/querystring-builder': 4.2.12 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - '@aws-sdk/util-locate-window@3.965.4': dependencies: tslib: 2.8.1 @@ -6546,6 +6455,11 @@ snapshots: fast-xml-parser: 5.5.9 tslib: 2.8.1 + '@aws-sdk/xml-builder@3.972.31': + dependencies: + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@aws/lambda-invoke-store@0.2.4': {} '@azure/abort-controller@2.1.2': @@ -6617,13 +6531,13 @@ snapshots: '@borewit/text-codec@0.2.2': {} - '@buape/carbon@0.0.0-beta-20260216184201(hono@4.12.7)(opusscript@0.0.8)(opusscript@0.0.8)': + '@buape/carbon@0.0.0-beta-20260216184201(hono@4.12.7)(opusscript@0.0.8)': dependencies: '@types/node': 25.3.0 discord-api-types: 0.38.37 optionalDependencies: '@cloudflare/workers-types': 4.20260120.0 - '@discordjs/voice': 0.19.0(opusscript@0.0.8)(opusscript@0.0.8) + '@discordjs/voice': 0.19.0(opusscript@0.0.8) '@hono/node-server': 1.19.10(hono@4.12.7) '@types/bun': 1.3.9 '@types/ws': 8.18.1 @@ -6748,11 +6662,11 @@ snapshots: dependencies: tslib: 2.8.1 - '@discordjs/voice@0.19.0(opusscript@0.0.8)(opusscript@0.0.8)': + '@discordjs/voice@0.19.0(opusscript@0.0.8)': dependencies: '@types/ws': 8.18.1 discord-api-types: 0.38.40 - prism-media: 1.3.5(opusscript@0.0.8)(opusscript@0.0.8) + prism-media: 1.3.5(opusscript@0.0.8) tslib: 2.8.1 ws: 8.19.0 transitivePeerDependencies: @@ -6763,6 +6677,76 @@ snapshots: - opusscript - utf-8-validate + '@earendil-works/pi-agent-core@0.80.2(ws@8.19.0)(zod@4.3.6)': + dependencies: + '@earendil-works/pi-ai': 0.80.2(ws@8.19.0)(zod@4.3.6) + ignore: 7.0.5 + typebox: 1.1.38 + yaml: 2.8.3 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@earendil-works/pi-ai@0.80.2(ws@8.19.0)(zod@4.3.6)': + dependencies: + '@anthropic-ai/sdk': 0.91.1(zod@4.3.6) + '@aws-sdk/client-bedrock-runtime': 3.1048.0 + '@google/genai': 1.52.0 + '@mistralai/mistralai': 2.2.6(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.0 + '@smithy/node-http-handler': 4.7.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + openai: 6.26.0(ws@8.19.0)(zod@4.3.6) + partial-json: 0.1.7 + typebox: 1.1.38 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@earendil-works/pi-coding-agent@0.80.2(ws@8.19.0)(zod@4.3.6)': + dependencies: + '@earendil-works/pi-agent-core': 0.80.2(ws@8.19.0)(zod@4.3.6) + '@earendil-works/pi-ai': 0.80.2(ws@8.19.0)(zod@4.3.6) + '@earendil-works/pi-tui': 0.80.2 + '@silvia-odwyer/photon-node': 0.3.4 + chalk: 5.6.2 + cross-spawn: 7.0.6 + diff: 8.0.4 + glob: 13.0.6 + highlight.js: 10.7.3 + hosted-git-info: 9.0.3 + ignore: 7.0.5 + jiti: 2.7.0 + minimatch: 10.2.3 + proper-lockfile: 4.1.2 + semver: 7.8.0 + typebox: 1.1.38 + undici: 7.24.2 + yaml: 2.8.3 + optionalDependencies: + '@mariozechner/clipboard': 0.3.9 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@earendil-works/pi-tui@0.80.2': + dependencies: + get-east-asian-width: 1.6.0 + marked: 18.0.5 + '@emnapi/core@1.8.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -6935,7 +6919,7 @@ snapshots: '@esbuild/win32-x64@0.27.3': optional: true - '@google/genai@1.42.0': + '@google/genai@1.52.0': dependencies: google-auth-library: 10.6.1 p-retry: 4.6.2 @@ -7249,129 +7233,50 @@ snapshots: '@lydell/node-pty-win32-arm64': 1.2.0-beta.3 '@lydell/node-pty-win32-x64': 1.2.0-beta.3 - '@mariozechner/clipboard-darwin-arm64@0.3.2': + '@mariozechner/clipboard-darwin-arm64@0.3.9': optional: true - '@mariozechner/clipboard-darwin-universal@0.3.2': + '@mariozechner/clipboard-darwin-universal@0.3.9': optional: true - '@mariozechner/clipboard-darwin-x64@0.3.2': + '@mariozechner/clipboard-darwin-x64@0.3.9': optional: true - '@mariozechner/clipboard-linux-arm64-gnu@0.3.2': + '@mariozechner/clipboard-linux-arm64-gnu@0.3.9': optional: true - '@mariozechner/clipboard-linux-arm64-musl@0.3.2': + '@mariozechner/clipboard-linux-arm64-musl@0.3.9': optional: true - '@mariozechner/clipboard-linux-riscv64-gnu@0.3.2': + '@mariozechner/clipboard-linux-riscv64-gnu@0.3.9': optional: true - '@mariozechner/clipboard-linux-x64-gnu@0.3.2': + '@mariozechner/clipboard-linux-x64-gnu@0.3.9': optional: true - '@mariozechner/clipboard-linux-x64-musl@0.3.2': + '@mariozechner/clipboard-linux-x64-musl@0.3.9': optional: true - '@mariozechner/clipboard-win32-arm64-msvc@0.3.2': + '@mariozechner/clipboard-win32-arm64-msvc@0.3.9': optional: true - '@mariozechner/clipboard-win32-x64-msvc@0.3.2': + '@mariozechner/clipboard-win32-x64-msvc@0.3.9': optional: true - '@mariozechner/clipboard@0.3.2': + '@mariozechner/clipboard@0.3.9': optionalDependencies: - '@mariozechner/clipboard-darwin-arm64': 0.3.2 - '@mariozechner/clipboard-darwin-universal': 0.3.2 - '@mariozechner/clipboard-darwin-x64': 0.3.2 - '@mariozechner/clipboard-linux-arm64-gnu': 0.3.2 - '@mariozechner/clipboard-linux-arm64-musl': 0.3.2 - '@mariozechner/clipboard-linux-riscv64-gnu': 0.3.2 - '@mariozechner/clipboard-linux-x64-gnu': 0.3.2 - '@mariozechner/clipboard-linux-x64-musl': 0.3.2 - '@mariozechner/clipboard-win32-arm64-msvc': 0.3.2 - '@mariozechner/clipboard-win32-x64-msvc': 0.3.2 + '@mariozechner/clipboard-darwin-arm64': 0.3.9 + '@mariozechner/clipboard-darwin-universal': 0.3.9 + '@mariozechner/clipboard-darwin-x64': 0.3.9 + '@mariozechner/clipboard-linux-arm64-gnu': 0.3.9 + '@mariozechner/clipboard-linux-arm64-musl': 0.3.9 + '@mariozechner/clipboard-linux-riscv64-gnu': 0.3.9 + '@mariozechner/clipboard-linux-x64-gnu': 0.3.9 + '@mariozechner/clipboard-linux-x64-musl': 0.3.9 + '@mariozechner/clipboard-win32-arm64-msvc': 0.3.9 + '@mariozechner/clipboard-win32-x64-msvc': 0.3.9 optional: true - '@mariozechner/jiti@2.6.5': - dependencies: - std-env: 3.10.0 - yoctocolors: 2.1.2 - - '@mariozechner/pi-agent-core@0.54.0(ws@8.19.0)(zod@4.3.6)': - dependencies: - '@mariozechner/pi-ai': 0.54.0(ws@8.19.0)(zod@4.3.6) - transitivePeerDependencies: - - '@modelcontextprotocol/sdk' - - aws-crt - - bufferutil - - supports-color - - utf-8-validate - - ws - - zod - - '@mariozechner/pi-ai@0.54.0(ws@8.19.0)(zod@4.3.6)': - dependencies: - '@anthropic-ai/sdk': 0.73.0(zod@4.3.6) - '@aws-sdk/client-bedrock-runtime': 3.997.0 - '@google/genai': 1.42.0 - '@mistralai/mistralai': 1.10.0 - '@sinclair/typebox': 0.34.48 - ajv: 8.18.0 - ajv-formats: 3.0.1(ajv@8.18.0) - chalk: 5.6.2 - openai: 6.10.0(ws@8.19.0)(zod@4.3.6) - partial-json: 0.1.7 - proxy-agent: 6.5.0 - undici: 7.24.2 - zod-to-json-schema: 3.25.1(zod@4.3.6) - transitivePeerDependencies: - - '@modelcontextprotocol/sdk' - - aws-crt - - bufferutil - - supports-color - - utf-8-validate - - ws - - zod - - '@mariozechner/pi-coding-agent@0.54.0(ws@8.19.0)(zod@4.3.6)': - dependencies: - '@mariozechner/jiti': 2.6.5 - '@mariozechner/pi-agent-core': 0.54.0(ws@8.19.0)(zod@4.3.6) - '@mariozechner/pi-ai': 0.54.0(ws@8.19.0)(zod@4.3.6) - '@mariozechner/pi-tui': 0.54.0 - '@silvia-odwyer/photon-node': 0.3.4 - chalk: 5.6.2 - cli-highlight: 2.1.11 - diff: 8.0.3 - file-type: 21.3.2 - glob: 13.0.6 - hosted-git-info: 9.0.2 - ignore: 7.0.5 - marked: 15.0.12 - minimatch: 10.2.3 - proper-lockfile: 4.1.2 - yaml: 2.8.3 - optionalDependencies: - '@mariozechner/clipboard': 0.3.2 - transitivePeerDependencies: - - '@modelcontextprotocol/sdk' - - aws-crt - - bufferutil - - supports-color - - utf-8-validate - - ws - - zod - - '@mariozechner/pi-tui@0.54.0': - dependencies: - '@types/mime-types': 2.1.4 - chalk: 5.6.2 - get-east-asian-width: 1.5.0 - koffi: 2.15.1 - marked: 15.0.12 - mime-types: 3.0.2 - '@matrix-org/matrix-sdk-crypto-nodejs@0.4.0': dependencies: https-proxy-agent: 7.0.6 @@ -7401,79 +7306,53 @@ snapshots: - debug - supports-color - '@mistralai/mistralai@1.10.0': + '@mistralai/mistralai@2.2.6(@opentelemetry/api@1.9.0)': dependencies: - zod: 3.25.76 - zod-to-json-schema: 3.25.1(zod@3.25.76) + '@opentelemetry/semantic-conventions': 1.41.1 + ws: 8.19.0 + zod: 4.3.6 + zod-to-json-schema: 3.25.1(zod@4.3.6) + optionalDependencies: + '@opentelemetry/api': 1.9.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate '@mozilla/readability@0.6.0': {} '@napi-rs/canvas-android-arm64@0.1.95': optional: true - '@napi-rs/canvas-android-arm64@0.1.97': - optional: true - '@napi-rs/canvas-darwin-arm64@0.1.95': optional: true - '@napi-rs/canvas-darwin-arm64@0.1.97': - optional: true - '@napi-rs/canvas-darwin-x64@0.1.95': optional: true - '@napi-rs/canvas-darwin-x64@0.1.97': - optional: true - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.95': optional: true - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.97': - optional: true - '@napi-rs/canvas-linux-arm64-gnu@0.1.95': optional: true - '@napi-rs/canvas-linux-arm64-gnu@0.1.97': - optional: true - '@napi-rs/canvas-linux-arm64-musl@0.1.95': optional: true - '@napi-rs/canvas-linux-arm64-musl@0.1.97': - optional: true - '@napi-rs/canvas-linux-riscv64-gnu@0.1.95': optional: true - '@napi-rs/canvas-linux-riscv64-gnu@0.1.97': - optional: true - '@napi-rs/canvas-linux-x64-gnu@0.1.95': optional: true - '@napi-rs/canvas-linux-x64-gnu@0.1.97': - optional: true - '@napi-rs/canvas-linux-x64-musl@0.1.95': optional: true - '@napi-rs/canvas-linux-x64-musl@0.1.97': - optional: true - '@napi-rs/canvas-win32-arm64-msvc@0.1.95': optional: true - '@napi-rs/canvas-win32-arm64-msvc@0.1.97': - optional: true - '@napi-rs/canvas-win32-x64-msvc@0.1.95': optional: true - '@napi-rs/canvas-win32-x64-msvc@0.1.97': - optional: true - '@napi-rs/canvas@0.1.95': optionalDependencies: '@napi-rs/canvas-android-arm64': 0.1.95 @@ -7488,20 +7367,6 @@ snapshots: '@napi-rs/canvas-win32-arm64-msvc': 0.1.95 '@napi-rs/canvas-win32-x64-msvc': 0.1.95 - '@napi-rs/canvas@0.1.97': - optionalDependencies: - '@napi-rs/canvas-android-arm64': 0.1.97 - '@napi-rs/canvas-darwin-arm64': 0.1.97 - '@napi-rs/canvas-darwin-x64': 0.1.97 - '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.97 - '@napi-rs/canvas-linux-arm64-gnu': 0.1.97 - '@napi-rs/canvas-linux-arm64-musl': 0.1.97 - '@napi-rs/canvas-linux-riscv64-gnu': 0.1.97 - '@napi-rs/canvas-linux-x64-gnu': 0.1.97 - '@napi-rs/canvas-linux-x64-musl': 0.1.97 - '@napi-rs/canvas-win32-arm64-msvc': 0.1.97 - '@napi-rs/canvas-win32-x64-msvc': 0.1.97 - '@napi-rs/wasm-runtime@1.1.1': dependencies: '@emnapi/core': 1.8.1 @@ -7806,6 +7671,8 @@ snapshots: '@opentelemetry/semantic-conventions@1.39.0': {} + '@opentelemetry/semantic-conventions@1.41.1': {} + '@oxc-project/types@0.112.0': {} '@oxfmt/binding-android-arm-eabi@0.34.0': @@ -7953,13 +7820,21 @@ snapshots: '@protobufjs/codegen@2.0.4': {} + '@protobufjs/codegen@2.0.5': {} + '@protobufjs/eventemitter@1.1.0': {} + '@protobufjs/eventemitter@1.1.1': {} + '@protobufjs/fetch@1.1.0': dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/inquire': 1.1.0 + '@protobufjs/fetch@1.1.1': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/float@1.0.2': {} '@protobufjs/inquire@1.1.0': {} @@ -7970,6 +7845,8 @@ snapshots: '@protobufjs/utf8@1.1.0': {} + '@protobufjs/utf8@1.1.1': {} + '@quansync/fs@1.0.0': dependencies: quansync: 1.0.0 @@ -8242,42 +8119,24 @@ snapshots: '@smithy/uuid': 1.1.2 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.2.12': - dependencies: - '@smithy/node-config-provider': 4.3.12 - '@smithy/property-provider': 4.2.12 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 - tslib: 2.8.1 - - '@smithy/eventstream-codec@4.2.10': + '@smithy/core@3.26.0': dependencies: '@aws-crypto/crc32': 5.2.0 - '@smithy/types': 4.13.1 - '@smithy/util-hex-encoding': 4.2.2 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@smithy/eventstream-serde-browser@4.2.10': - dependencies: - '@smithy/eventstream-serde-universal': 4.2.10 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/eventstream-serde-config-resolver@4.3.10': - dependencies: - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/eventstream-serde-node@4.2.10': + '@smithy/credential-provider-imds@4.2.12': dependencies: - '@smithy/eventstream-serde-universal': 4.2.10 + '@smithy/node-config-provider': 4.3.12 + '@smithy/property-provider': 4.2.12 '@smithy/types': 4.13.1 + '@smithy/url-parser': 4.2.12 tslib: 2.8.1 - '@smithy/eventstream-serde-universal@4.2.10': + '@smithy/credential-provider-imds@4.4.2': dependencies: - '@smithy/eventstream-codec': 4.2.10 - '@smithy/types': 4.13.1 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 '@smithy/fetch-http-handler@5.3.15': @@ -8288,6 +8147,12 @@ snapshots: '@smithy/util-base64': 4.3.2 tslib: 2.8.1 + '@smithy/fetch-http-handler@5.5.2': + dependencies: + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@smithy/hash-node@4.2.12': dependencies: '@smithy/types': 4.13.1 @@ -8364,6 +8229,18 @@ snapshots: '@smithy/types': 4.13.1 tslib: 2.8.1 + '@smithy/node-http-handler@4.7.3': + dependencies: + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.8.2': + dependencies: + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@smithy/property-provider@4.2.12': dependencies: '@smithy/types': 4.13.1 @@ -8405,6 +8282,12 @@ snapshots: '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 + '@smithy/signature-v4@5.5.2': + dependencies: + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + '@smithy/smithy-client@4.12.7': dependencies: '@smithy/core': 3.23.12 @@ -8419,6 +8302,10 @@ snapshots: dependencies: tslib: 2.8.1 + '@smithy/types@4.15.0': + dependencies: + tslib: 2.8.1 + '@smithy/url-parser@4.2.12': dependencies: '@smithy/querystring-parser': 4.2.12 @@ -8476,10 +8363,6 @@ snapshots: '@smithy/types': 4.13.1 tslib: 2.8.1 - '@smithy/util-hex-encoding@4.2.1': - dependencies: - tslib: 2.8.1 - '@smithy/util-hex-encoding@4.2.2': dependencies: tslib: 2.8.1 @@ -8495,17 +8378,6 @@ snapshots: '@smithy/types': 4.13.1 tslib: 2.8.1 - '@smithy/util-stream@4.5.15': - dependencies: - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/node-http-handler': 4.5.0 - '@smithy/types': 4.13.1 - '@smithy/util-base64': 4.3.2 - '@smithy/util-buffer-from': 4.2.2 - '@smithy/util-hex-encoding': 4.2.1 - '@smithy/util-utf8': 4.2.2 - tslib: 2.8.1 - '@smithy/util-stream@4.5.20': dependencies: '@smithy/fetch-http-handler': 5.3.15 @@ -8552,8 +8424,6 @@ snapshots: '@tokenizer/token@0.3.0': {} - '@tootallnate/quickjs-emscripten@0.23.0': {} - '@twurple/api-call@8.0.3': dependencies: '@d-fischer/shared-utils': 3.6.4 @@ -8677,8 +8547,6 @@ snapshots: '@types/linkify-it@5.0.0': {} - '@types/long@4.0.2': {} - '@types/markdown-it@14.1.2': dependencies: '@types/linkify-it': 5.0.0 @@ -8686,14 +8554,10 @@ snapshots: '@types/mdurl@2.0.0': {} - '@types/mime-types@2.1.4': {} - '@types/mime@1.3.5': {} '@types/ms@2.1.0': {} - '@types/node@10.17.60': {} - '@types/node@20.19.37': dependencies: undici-types: 6.21.0 @@ -8831,6 +8695,20 @@ snapshots: - msw - utf-8-validate - vite + optional: true + + '@vitest/browser-playwright@4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18)': + dependencies: + '@vitest/browser': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3)) + playwright: 1.58.2 + tinyrainbow: 3.0.3 + vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite '@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18)': dependencies: @@ -8848,6 +8726,24 @@ snapshots: - msw - utf-8-validate - vite + optional: true + + '@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18)': + dependencies: + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/utils': 4.0.18 + magic-string: 0.30.21 + pixelmatch: 7.1.0 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.0.3 + vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite '@vitest/coverage-v8@4.0.18(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18))(vitest@4.0.18)': dependencies: @@ -8882,13 +8778,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.0.3 - '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: @@ -8898,6 +8794,14 @@ snapshots: optionalDependencies: vite: 7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@vitest/spy': 4.0.18 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/pretty-format@3.2.4': dependencies: tinyrainbow: 2.0.0 @@ -8951,7 +8855,7 @@ snapshots: '@cacheable/node-cache': 1.7.6 '@hapi/boom': 9.1.4 async-mutex: 0.5.0 - libsignal: '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67' + libsignal: https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/bcea72df9ec34d9d9140ab30619cf479c7c144c7 lru-cache: 11.2.6 music-metadata: 11.12.3 p-queue: 9.1.0 @@ -8964,11 +8868,6 @@ snapshots: - supports-color - utf-8-validate - '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67': - dependencies: - curve25519-js: 0.0.4 - protobufjs: 6.8.8 - abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -8991,10 +8890,6 @@ snapshots: agent-base@7.1.4: {} - ajv-formats@3.0.1(ajv@8.18.0): - optionalDependencies: - ajv: 8.18.0 - ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 @@ -9054,10 +8949,6 @@ snapshots: estree-walker: 3.0.3 pathe: 2.0.3 - ast-types@0.13.4: - dependencies: - tslib: 2.8.1 - ast-v8-to-istanbul@0.3.11: dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -9098,8 +8989,6 @@ snapshots: dependencies: safe-buffer: 5.1.2 - basic-ftp@5.2.0: {} - bcrypt-pbkdf@1.0.2: dependencies: tweetnacl: 0.14.5 @@ -9340,8 +9229,6 @@ snapshots: data-uri-to-buffer@4.0.1: {} - data-uri-to-buffer@6.0.2: {} - debug@2.6.9: dependencies: ms: 2.0.0 @@ -9358,12 +9245,6 @@ snapshots: defu@6.1.4: {} - degenerator@5.0.1: - dependencies: - ast-types: 0.13.4 - escodegen: 2.1.0 - esprima: 4.0.1 - delayed-stream@1.0.0: {} depd@2.0.0: {} @@ -9372,7 +9253,7 @@ snapshots: detect-libc@2.1.2: {} - diff@8.0.3: {} + diff@8.0.4: {} discord-api-types@0.38.37: {} @@ -9520,24 +9401,10 @@ snapshots: escape-string-regexp@4.0.0: {} - escodegen@2.1.0: - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionalDependencies: - source-map: 0.6.1 - - esprima@4.0.1: {} - - estraverse@5.3.0: {} - estree-walker@3.0.3: dependencies: '@types/estree': 1.0.8 - esutils@2.0.3: {} - etag@1.8.1: {} event-target-shim@5.0.1: {} @@ -9767,6 +9634,8 @@ snapshots: get-east-asian-width@1.5.0: {} + get-east-asian-width@1.6.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -9789,14 +9658,6 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 - get-uri@6.0.5: - dependencies: - basic-ftp: 5.2.0 - data-uri-to-buffer: 6.0.2 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - getpass@0.1.7: dependencies: assert-plus: 1.0.0 @@ -9880,7 +9741,7 @@ snapshots: hookified@1.15.1: {} - hosted-git-info@9.0.2: + hosted-git-info@9.0.3: dependencies: lru-cache: 11.2.6 @@ -9967,8 +9828,6 @@ snapshots: ini@1.3.8: {} - ip-address@10.1.0: {} - ipaddr.js@1.9.1: {} ipull@3.9.5: @@ -10067,6 +9926,8 @@ snapshots: jiti@2.6.1: {} + jiti@2.7.0: {} + jose@4.15.9: {} js-tokens@10.0.0: {} @@ -10156,10 +10017,13 @@ snapshots: klona@2.0.6: {} - koffi@2.15.1: {} - leac@0.6.0: {} + libsignal@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/bcea72df9ec34d9d9140ab30619cf479c7c144c7: + dependencies: + curve25519-js: 0.0.4 + protobufjs: 7.6.4 + lie@3.3.0: dependencies: immediate: 3.0.6 @@ -10231,8 +10095,6 @@ snapshots: is-unicode-supported: 2.1.0 yoctocolors: 2.1.2 - long@4.0.0: {} - long@5.3.2: {} loupe@3.2.1: {} @@ -10257,8 +10119,6 @@ snapshots: dependencies: yallist: 4.0.0 - lru-cache@7.18.3: {} - lru-memoizer@2.3.0: dependencies: lodash.clonedeep: 4.5.0 @@ -10287,10 +10147,10 @@ snapshots: punycode.js: 2.3.1 uc.micro: 2.1.0 - marked@15.0.12: {} - marked@17.0.3: {} + marked@18.0.5: {} + math-intrinsics@1.1.0: {} mdurl@2.0.0: {} @@ -10391,8 +10251,6 @@ snapshots: negotiator@1.0.0: {} - netmask@2.0.2: {} - node-addon-api@8.7.0: {} node-api-headers@1.8.0: {} @@ -10518,12 +10376,12 @@ snapshots: dependencies: mimic-function: 5.0.1 - openai@6.10.0(ws@8.19.0)(zod@4.3.6): + openai@6.25.0(ws@8.19.0)(zod@4.3.6): optionalDependencies: ws: 8.19.0 zod: 4.3.6 - openai@6.25.0(ws@8.19.0)(zod@4.3.6): + openai@6.26.0(ws@8.19.0)(zod@4.3.6): optionalDependencies: ws: 8.19.0 zod: 4.3.6 @@ -10622,24 +10480,6 @@ snapshots: p-timeout@7.0.1: {} - pac-proxy-agent@7.2.0: - dependencies: - '@tootallnate/quickjs-emscripten': 0.23.0 - agent-base: 7.1.4 - debug: 4.4.3 - get-uri: 6.0.5 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - pac-resolver: 7.0.1 - socks-proxy-agent: 8.0.5 - transitivePeerDependencies: - - supports-color - - pac-resolver@7.0.1: - dependencies: - degenerator: 5.0.1 - netmask: 2.0.2 - package-json-from-dist@1.0.1: {} pako@1.0.11: {} @@ -10754,9 +10594,8 @@ snapshots: dependencies: parse-ms: 4.0.0 - prism-media@1.3.5(opusscript@0.0.8)(opusscript@0.0.8): + prism-media@1.3.5(opusscript@0.0.8): optionalDependencies: - '@discordjs/opus': opusscript@0.0.8 opusscript: 0.0.8 process-nextick-args@2.0.1: {} @@ -10769,7 +10608,7 @@ snapshots: retry: 0.12.0 signal-exit: 3.0.7 - protobufjs@6.8.8: + protobufjs@7.5.4: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 @@ -10781,22 +10620,20 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/long': 4.0.2 - '@types/node': 10.17.60 - long: 4.0.0 + '@types/node': 25.3.0 + long: 5.3.2 - protobufjs@7.5.4: + protobufjs@7.6.4: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.1 + '@protobufjs/fetch': 1.1.1 '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 + '@protobufjs/utf8': 1.1.1 '@types/node': 25.3.0 long: 5.3.2 @@ -10820,19 +10657,6 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 - proxy-agent@6.5.0: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - lru-cache: 7.18.3 - pac-proxy-agent: 7.2.0 - proxy-from-env: 1.1.0 - socks-proxy-agent: 8.0.5 - transitivePeerDependencies: - - supports-color - proxy-from-env@1.1.0: {} psl@1.15.0: @@ -11052,6 +10876,8 @@ snapshots: semver@7.7.4: {} + semver@7.8.0: {} + send@0.19.2: dependencies: debug: 2.6.9 @@ -11213,21 +11039,6 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 - smart-buffer@4.2.0: {} - - socks-proxy-agent@8.0.5: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - socks: 2.8.7 - transitivePeerDependencies: - - supports-color - - socks@2.8.7: - dependencies: - ip-address: 10.1.0 - smart-buffer: 4.2.0 - sonic-boom@4.2.1: dependencies: atomic-sleep: 1.0.0 @@ -11486,6 +11297,8 @@ snapshots: media-typer: 1.1.0 mime-types: 3.0.2 + typebox@1.1.38: {} + typescript@5.9.3: {} typical@4.0.0: {} @@ -11546,13 +11359,13 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite-node@3.2.4(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3): + vite-node@3.2.4(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - '@types/node' - jiti @@ -11582,11 +11395,26 @@ snapshots: tsx: 4.21.0 yaml: 2.8.3 - vitest@3.2.4(@types/node@25.3.0)(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18))(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3): + vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3): + dependencies: + esbuild: 0.27.3 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.6 + rollup: 4.59.0 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 25.3.0 + fsevents: 2.3.3 + jiti: 2.7.0 + tsx: 4.21.0 + yaml: 2.8.3 + + vitest@3.2.4(@types/node@25.3.0)(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18))(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -11604,8 +11432,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) - vite-node: 3.2.4(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + vite-node: 3.2.4(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.3.0 @@ -11663,6 +11491,45 @@ snapshots: - tsx - yaml + vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3): + dependencies: + '@vitest/expect': 4.0.18 + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/pretty-format': 4.0.18 + '@vitest/runner': 4.0.18 + '@vitest/snapshot': 4.0.18 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 + es-module-lexer: 1.7.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + why-is-node-running: 2.3.0 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + '@types/node': 25.3.0 + '@vitest/browser-playwright': 4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + web-streams-polyfill@3.3.3: {} webidl-conversions@3.0.1: {} @@ -11739,16 +11606,10 @@ snapshots: yoctocolors@2.1.2: {} - zod-to-json-schema@3.25.1(zod@3.25.76): - dependencies: - zod: 3.25.76 - zod-to-json-schema@3.25.1(zod@4.3.6): dependencies: zod: 4.3.6 zod@3.25.75: {} - zod@3.25.76: {} - zod@4.3.6: {} diff --git a/scripts/bench-model.ts b/scripts/bench-model.ts index f1698737..b5d42dd8 100644 --- a/scripts/bench-model.ts +++ b/scripts/bench-model.ts @@ -1,4 +1,4 @@ -import { completeSimple, getModel, type Model } from "@mariozechner/pi-ai"; +import { completeSimple, getModel, type Model } from "@earendil-works/pi-ai"; type Usage = { input?: number; diff --git a/scripts/package-mac-app.sh b/scripts/package-mac-app.sh index fa422c8e..4188048d 100755 --- a/scripts/package-mac-app.sh +++ b/scripts/package-mac-app.sh @@ -208,7 +208,7 @@ rm -rf "$APP_ROOT/Contents/Resources/DeviceModels" cp -R "$ROOT_DIR/apps/macos/Sources/Mayros/Resources/DeviceModels" "$APP_ROOT/Contents/Resources/DeviceModels" echo "📦 Copying model catalog" -MODEL_CATALOG_SRC="$ROOT_DIR/node_modules/@mariozechner/pi-ai/dist/models.generated.js" +MODEL_CATALOG_SRC="$ROOT_DIR/node_modules/@earendil-works/pi-ai/dist/models.generated.js" MODEL_CATALOG_DEST="$APP_ROOT/Contents/Resources/models.generated.js" if [ -f "$MODEL_CATALOG_SRC" ]; then cp "$MODEL_CATALOG_SRC" "$MODEL_CATALOG_DEST" diff --git a/skills/coding-agent/SKILL.md b/skills/coding-agent/SKILL.md index d7894afc..36effceb 100644 --- a/skills/coding-agent/SKILL.md +++ b/skills/coding-agent/SKILL.md @@ -176,7 +176,7 @@ bash pty:true workdir:~/project command:"opencode run 'Your task'" ## Pi Coding Agent ```bash -# Install: npm install -g @mariozechner/pi-coding-agent +# Install: npm install -g @earendil-works/pi-coding-agent bash pty:true workdir:~/project command:"pi 'Your task'" # Non-interactive mode (PTY still recommended) diff --git a/src/agents/anthropic-payload-log.ts b/src/agents/anthropic-payload-log.ts index e663cad1..ff05fcfc 100644 --- a/src/agents/anthropic-payload-log.ts +++ b/src/agents/anthropic-payload-log.ts @@ -1,7 +1,7 @@ import crypto from "node:crypto"; import path from "node:path"; -import type { AgentMessage, StreamFn } from "@mariozechner/pi-agent-core"; -import type { Api, Model } from "@mariozechner/pi-ai"; +import type { AgentMessage, StreamFn } from "@earendil-works/pi-agent-core"; +import type { Api, Model } from "@earendil-works/pi-ai"; import { resolveStateDir } from "../config/paths.js"; import { createSubsystemLogger } from "../logging/subsystem.js"; import { resolveUserPath } from "../utils.js"; @@ -134,7 +134,7 @@ export function createAnthropicPayloadLogger(params: { if (!isAnthropicModel(model)) { return streamFn(model, context, options); } - const nextOnPayload = (payload: unknown) => { + const nextOnPayload: NonNullable["onPayload"] = (payload, payloadModel) => { record({ ...base, ts: new Date().toISOString(), @@ -142,7 +142,7 @@ export function createAnthropicPayloadLogger(params: { payload, payloadDigest: digest(payload), }); - options?.onPayload?.(payload); + return options?.onPayload?.(payload, payloadModel); }; return streamFn(model, context, { ...options, diff --git a/src/agents/anthropic.setup-token.live.test.ts b/src/agents/anthropic.setup-token.live.test.ts index bfd211c0..ee0e046e 100644 --- a/src/agents/anthropic.setup-token.live.test.ts +++ b/src/agents/anthropic.setup-token.live.test.ts @@ -2,7 +2,8 @@ import { randomUUID } from "node:crypto"; import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { type Api, completeSimple, type Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; +import { completeSimple } from "@earendil-works/pi-ai/compat"; import { describe, expect, it } from "vitest"; import { ANTHROPIC_SETUP_TOKEN_PREFIX, diff --git a/src/agents/apply-patch.ts b/src/agents/apply-patch.ts index ef756b37..818df6dc 100644 --- a/src/agents/apply-patch.ts +++ b/src/agents/apply-patch.ts @@ -1,6 +1,6 @@ import fs from "node:fs/promises"; import path from "node:path"; -import type { AgentTool } from "@mariozechner/pi-agent-core"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; import { Type } from "@sinclair/typebox"; import { applyUpdateHunk } from "./apply-patch-update.js"; import { assertSandboxPath, resolveSandboxInputPath } from "./sandbox-paths.js"; diff --git a/src/agents/auth-profiles/oauth.ts b/src/agents/auth-profiles/oauth.ts index 0855e629..a1b9d8e7 100644 --- a/src/agents/auth-profiles/oauth.ts +++ b/src/agents/auth-profiles/oauth.ts @@ -1,9 +1,5 @@ -import { - getOAuthApiKey, - getOAuthProviders, - type OAuthCredentials, - type OAuthProvider, -} from "@mariozechner/pi-ai"; +import type { OAuthCredentials, OAuthProvider } from "@earendil-works/pi-ai"; +import { getOAuthApiKey, getOAuthProviders } from "@earendil-works/pi-ai/oauth"; import type { MayrosConfig } from "../../config/config.js"; import { withFileLock } from "../../infra/file-lock.js"; import { refreshQwenPortalCredentials } from "../../providers/qwen-portal-oauth.js"; diff --git a/src/agents/auth-profiles/store.ts b/src/agents/auth-profiles/store.ts index 4e6b1f91..1c6759d3 100644 --- a/src/agents/auth-profiles/store.ts +++ b/src/agents/auth-profiles/store.ts @@ -1,5 +1,5 @@ import fs from "node:fs"; -import type { OAuthCredentials } from "@mariozechner/pi-ai"; +import type { OAuthCredentials } from "@earendil-works/pi-ai"; import { resolveOAuthPath } from "../../config/paths.js"; import { withFileLock } from "../../infra/file-lock.js"; import { loadJsonFile, saveJsonFile } from "../../infra/json-file.js"; diff --git a/src/agents/auth-profiles/types.ts b/src/agents/auth-profiles/types.ts index c44467d0..9c14a6f8 100644 --- a/src/agents/auth-profiles/types.ts +++ b/src/agents/auth-profiles/types.ts @@ -1,4 +1,4 @@ -import type { OAuthCredentials } from "@mariozechner/pi-ai"; +import type { OAuthCredentials } from "@earendil-works/pi-ai"; import type { MayrosConfig } from "../../config/config.js"; export type ApiKeyCredential = { diff --git a/src/agents/bash-tools.exec-host-gateway.ts b/src/agents/bash-tools.exec-host-gateway.ts index d3cc26c4..ebffc67a 100644 --- a/src/agents/bash-tools.exec-host-gateway.ts +++ b/src/agents/bash-tools.exec-host-gateway.ts @@ -1,5 +1,5 @@ import crypto from "node:crypto"; -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import { addAllowlistEntry, type ExecAsk, diff --git a/src/agents/bash-tools.exec-host-node.ts b/src/agents/bash-tools.exec-host-node.ts index 3cca1bc1..11bcd210 100644 --- a/src/agents/bash-tools.exec-host-node.ts +++ b/src/agents/bash-tools.exec-host-node.ts @@ -1,5 +1,5 @@ import crypto from "node:crypto"; -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import { type ExecApprovalsFile, type ExecAsk, diff --git a/src/agents/bash-tools.exec-runtime.ts b/src/agents/bash-tools.exec-runtime.ts index caa63d0e..e459360e 100644 --- a/src/agents/bash-tools.exec-runtime.ts +++ b/src/agents/bash-tools.exec-runtime.ts @@ -1,5 +1,5 @@ import path from "node:path"; -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import { Type } from "@sinclair/typebox"; import type { ExecAsk, ExecHost, ExecSecurity } from "../infra/exec-approvals.js"; import { requestHeartbeatNow } from "../infra/heartbeat-wake.js"; diff --git a/src/agents/bash-tools.exec.ts b/src/agents/bash-tools.exec.ts index e5b9c5eb..84c23c71 100644 --- a/src/agents/bash-tools.exec.ts +++ b/src/agents/bash-tools.exec.ts @@ -1,6 +1,6 @@ import fs from "node:fs/promises"; import path from "node:path"; -import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core"; import { type ExecHost, maxAsk, minSecurity, resolveSafeBins } from "../infra/exec-approvals.js"; import { getTrustedSafeBinDirs } from "../infra/exec-safe-bin-trust.js"; import { diff --git a/src/agents/bash-tools.process.ts b/src/agents/bash-tools.process.ts index dbdb6f99..1ef1b0ab 100644 --- a/src/agents/bash-tools.process.ts +++ b/src/agents/bash-tools.process.ts @@ -1,4 +1,4 @@ -import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core"; import { Type } from "@sinclair/typebox"; import { formatDurationCompact } from "../infra/format-time/format-duration.ts"; import { getDiagnosticSessionState } from "../logging/diagnostic-session-state.js"; diff --git a/src/agents/byteplus.live.test.ts b/src/agents/byteplus.live.test.ts index 1c1b730a..15546d4f 100644 --- a/src/agents/byteplus.live.test.ts +++ b/src/agents/byteplus.live.test.ts @@ -1,4 +1,5 @@ -import { completeSimple, type Model } from "@mariozechner/pi-ai"; +import type { Model } from "@earendil-works/pi-ai"; +import { completeSimple } from "@earendil-works/pi-ai/compat"; import { describe, expect, it } from "vitest"; import { isTruthyEnvValue } from "../infra/env.js"; import { BYTEPLUS_CODING_BASE_URL, BYTEPLUS_DEFAULT_COST } from "./byteplus-models.js"; diff --git a/src/agents/cache-trace.ts b/src/agents/cache-trace.ts index 9da1fc3d..8e0a2a9d 100644 --- a/src/agents/cache-trace.ts +++ b/src/agents/cache-trace.ts @@ -1,6 +1,6 @@ import crypto from "node:crypto"; import path from "node:path"; -import type { AgentMessage, StreamFn } from "@mariozechner/pi-agent-core"; +import type { AgentMessage, StreamFn } from "@earendil-works/pi-agent-core"; import type { MayrosConfig } from "../config/config.js"; import { resolveStateDir } from "../config/paths.js"; import { resolveUserPath } from "../utils.js"; diff --git a/src/agents/chutes-oauth.ts b/src/agents/chutes-oauth.ts index 02adf10c..a5d7c5d5 100644 --- a/src/agents/chutes-oauth.ts +++ b/src/agents/chutes-oauth.ts @@ -1,5 +1,5 @@ import { createHash, randomBytes } from "node:crypto"; -import type { OAuthCredentials } from "@mariozechner/pi-ai"; +import type { OAuthCredentials } from "@earendil-works/pi-ai"; export const CHUTES_OAUTH_ISSUER = "https://api.chutes.ai"; export const CHUTES_AUTHORIZE_ENDPOINT = `${CHUTES_OAUTH_ISSUER}/idp/authorize`; diff --git a/src/agents/cli-credentials.ts b/src/agents/cli-credentials.ts index 0d6d7c28..529d69d3 100644 --- a/src/agents/cli-credentials.ts +++ b/src/agents/cli-credentials.ts @@ -2,7 +2,7 @@ import { execFileSync, execSync } from "node:child_process"; import { createHash } from "node:crypto"; import fs from "node:fs"; import path from "node:path"; -import type { OAuthCredentials, OAuthProvider } from "@mariozechner/pi-ai"; +import type { OAuthCredentials, OAuthProvider } from "@earendil-works/pi-ai"; import { loadJsonFile, saveJsonFile } from "../infra/json-file.js"; import { createSubsystemLogger } from "../logging/subsystem.js"; import { resolveUserPath } from "../utils.js"; diff --git a/src/agents/cli-runner.ts b/src/agents/cli-runner.ts index b97cc3f1..45d6f37e 100644 --- a/src/agents/cli-runner.ts +++ b/src/agents/cli-runner.ts @@ -1,4 +1,4 @@ -import type { ImageContent } from "@mariozechner/pi-ai"; +import type { ImageContent } from "@earendil-works/pi-ai"; import { resolveHeartbeatPrompt } from "../auto-reply/heartbeat.js"; import type { ThinkLevel } from "../auto-reply/thinking.js"; import type { MayrosConfig } from "../config/config.js"; diff --git a/src/agents/cli-runner/helpers.ts b/src/agents/cli-runner/helpers.ts index 8acb1eb3..544d1ccd 100644 --- a/src/agents/cli-runner/helpers.ts +++ b/src/agents/cli-runner/helpers.ts @@ -2,8 +2,8 @@ import crypto from "node:crypto"; import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import type { AgentTool } from "@mariozechner/pi-agent-core"; -import type { ImageContent } from "@mariozechner/pi-ai"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; +import type { ImageContent } from "@earendil-works/pi-ai"; import type { ThinkLevel } from "../../auto-reply/thinking.js"; import type { MayrosConfig } from "../../config/config.js"; import type { CliBackendConfig } from "../../config/types.js"; diff --git a/src/agents/compaction.e2e.test.ts b/src/agents/compaction.e2e.test.ts index de5f4ec4..5a7f7609 100644 --- a/src/agents/compaction.e2e.test.ts +++ b/src/agents/compaction.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { estimateMessagesTokens, diff --git a/src/agents/compaction.retry.test.ts b/src/agents/compaction.retry.test.ts index 50fe043c..a4e8b83b 100644 --- a/src/agents/compaction.retry.test.ts +++ b/src/agents/compaction.retry.test.ts @@ -1,11 +1,11 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { ExtensionContext } from "@mariozechner/pi-coding-agent"; -import * as piCodingAgent from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; +import * as piCodingAgent from "@earendil-works/pi-coding-agent"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { retryAsync } from "../infra/retry.js"; // Mock the external generateSummary function -vi.mock("@mariozechner/pi-coding-agent", async (importOriginal) => { +vi.mock("@earendil-works/pi-coding-agent", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, @@ -44,6 +44,7 @@ describe("compaction retry integration", () => { testModel, 1000, "test-api-key", + undefined, new AbortController().signal, ), { @@ -71,6 +72,7 @@ describe("compaction retry integration", () => { testModel, 1000, "test-api-key", + undefined, new AbortController().signal, ), { @@ -100,6 +102,7 @@ describe("compaction retry integration", () => { testModel, 1000, "test-api-key", + undefined, new AbortController().signal, ), { @@ -126,6 +129,7 @@ describe("compaction retry integration", () => { testModel, 1000, "test-api-key", + undefined, new AbortController().signal, ), { @@ -156,6 +160,7 @@ describe("compaction retry integration", () => { testModel, 1000, "test-api-key", + undefined, new AbortController().signal, ), { diff --git a/src/agents/compaction.tool-result-details.e2e.test.ts b/src/agents/compaction.tool-result-details.e2e.test.ts index 79c883a7..60dfda77 100644 --- a/src/agents/compaction.tool-result-details.e2e.test.ts +++ b/src/agents/compaction.tool-result-details.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { beforeEach, describe, expect, it, vi } from "vitest"; const piCodingAgentMocks = vi.hoisted(() => ({ @@ -6,9 +6,9 @@ const piCodingAgentMocks = vi.hoisted(() => ({ estimateTokens: vi.fn(() => 1), })); -vi.mock("@mariozechner/pi-coding-agent", async () => { - const actual = await vi.importActual( - "@mariozechner/pi-coding-agent", +vi.mock("@earendil-works/pi-coding-agent", async () => { + const actual = await vi.importActual( + "@earendil-works/pi-coding-agent", ); return { ...actual, diff --git a/src/agents/compaction.ts b/src/agents/compaction.ts index d60d1af2..04546bb3 100644 --- a/src/agents/compaction.ts +++ b/src/agents/compaction.ts @@ -1,6 +1,6 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { ExtensionContext } from "@mariozechner/pi-coding-agent"; -import { estimateTokens, generateSummary } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; +import { estimateTokens, generateSummary } from "@earendil-works/pi-coding-agent"; import { retryAsync } from "../infra/retry.js"; import { DEFAULT_CONTEXT_TOKENS } from "./defaults.js"; import { repairToolUseResultPairing, stripToolResultDetails } from "./session-transcript-repair.js"; @@ -167,6 +167,7 @@ async function summarizeChunks(params: { params.model, params.reserveTokens, params.apiKey, + undefined, params.signal, params.customInstructions, summary, diff --git a/src/agents/google-gemini-switch.live.test.ts b/src/agents/google-gemini-switch.live.test.ts index 7c253b03..ad1f393e 100644 --- a/src/agents/google-gemini-switch.live.test.ts +++ b/src/agents/google-gemini-switch.live.test.ts @@ -1,4 +1,4 @@ -import { completeSimple, getModel } from "@mariozechner/pi-ai"; +import { completeSimple, getModel } from "@earendil-works/pi-ai/compat"; import { Type } from "@sinclair/typebox"; import { describe, expect, it } from "vitest"; import { isTruthyEnvValue } from "../infra/env.js"; diff --git a/src/agents/minimax.live.test.ts b/src/agents/minimax.live.test.ts index ca380f2c..e3b76adb 100644 --- a/src/agents/minimax.live.test.ts +++ b/src/agents/minimax.live.test.ts @@ -1,4 +1,5 @@ -import { completeSimple, type Model } from "@mariozechner/pi-ai"; +import type { Model } from "@earendil-works/pi-ai"; +import { completeSimple } from "@earendil-works/pi-ai/compat"; import { describe, expect, it } from "vitest"; import { isTruthyEnvValue } from "../infra/env.js"; diff --git a/src/agents/model-auth.e2e.test.ts b/src/agents/model-auth.e2e.test.ts index 4c6b4cc6..2d2b8527 100644 --- a/src/agents/model-auth.e2e.test.ts +++ b/src/agents/model-auth.e2e.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import type { Api, Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { captureEnv } from "../test-utils/env.js"; import { ensureAuthProfileStore } from "./auth-profiles.js"; diff --git a/src/agents/model-auth.ts b/src/agents/model-auth.ts index c1c4a510..8eb8ba98 100644 --- a/src/agents/model-auth.ts +++ b/src/agents/model-auth.ts @@ -1,5 +1,6 @@ import path from "node:path"; -import { type Api, getEnvApiKey, type Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; +import { getEnvApiKey } from "@earendil-works/pi-ai/compat"; import { formatCliCommand } from "../cli/command-format.js"; import type { MayrosConfig } from "../config/config.js"; import type { ModelProviderAuthMode, ModelProviderConfig } from "../config/types.js"; diff --git a/src/agents/model-compat.e2e.test.ts b/src/agents/model-compat.e2e.test.ts index 95b4a0eb..2e44f413 100644 --- a/src/agents/model-compat.e2e.test.ts +++ b/src/agents/model-compat.e2e.test.ts @@ -1,4 +1,4 @@ -import type { Api, Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { normalizeModelCompat } from "./model-compat.js"; diff --git a/src/agents/model-compat.ts b/src/agents/model-compat.ts index e7b428e8..6047c7c0 100644 --- a/src/agents/model-compat.ts +++ b/src/agents/model-compat.ts @@ -1,4 +1,4 @@ -import type { Api, Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; function isOpenAiCompletionsModel(model: Model): model is Model<"openai-completions"> { return model.api === "openai-completions"; diff --git a/src/agents/model-forward-compat.test.ts b/src/agents/model-forward-compat.test.ts index b2017213..915caaa4 100644 --- a/src/agents/model-forward-compat.test.ts +++ b/src/agents/model-forward-compat.test.ts @@ -1,4 +1,4 @@ -import type { Api, Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { resolveForwardCompatModel } from "./model-forward-compat.js"; import type { ModelRegistry } from "./pi-model-discovery.js"; diff --git a/src/agents/model-forward-compat.ts b/src/agents/model-forward-compat.ts index 600b52a0..9671e52a 100644 --- a/src/agents/model-forward-compat.ts +++ b/src/agents/model-forward-compat.ts @@ -1,4 +1,4 @@ -import type { Api, Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; import { DEFAULT_CONTEXT_TOKENS } from "./defaults.js"; import { normalizeModelCompat } from "./model-compat.js"; import { normalizeProviderId } from "./model-selection.js"; diff --git a/src/agents/model-scan.ts b/src/agents/model-scan.ts index 3fe131d9..610eb9f9 100644 --- a/src/agents/model-scan.ts +++ b/src/agents/model-scan.ts @@ -1,12 +1,5 @@ -import { - type Context, - complete, - getEnvApiKey, - getModel, - type Model, - type OpenAICompletionsOptions, - type Tool, -} from "@mariozechner/pi-ai"; +import type { Context, Model, OpenAICompletionsOptions, Tool } from "@earendil-works/pi-ai"; +import { complete, getEnvApiKey, getModel } from "@earendil-works/pi-ai/compat"; import { Type } from "@sinclair/typebox"; import { inferParamBFromIdOrName } from "../shared/model-param-b.js"; diff --git a/src/agents/models.profiles.live.test.ts b/src/agents/models.profiles.live.test.ts index cb04fe6c..e4965ebb 100644 --- a/src/agents/models.profiles.live.test.ts +++ b/src/agents/models.profiles.live.test.ts @@ -1,4 +1,5 @@ -import { type Api, completeSimple, type Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; +import { completeSimple } from "@earendil-works/pi-ai/compat"; import { Type } from "@sinclair/typebox"; import { describe, expect, it } from "vitest"; import { loadConfig } from "../config/config.js"; diff --git a/src/agents/ollama-stream.ts b/src/agents/ollama-stream.ts index 39a19769..30059141 100644 --- a/src/agents/ollama-stream.ts +++ b/src/agents/ollama-stream.ts @@ -1,5 +1,5 @@ import { randomUUID } from "node:crypto"; -import type { StreamFn } from "@mariozechner/pi-agent-core"; +import type { StreamFn } from "@earendil-works/pi-agent-core"; import type { AssistantMessage, StopReason, @@ -7,8 +7,8 @@ import type { ToolCall, Tool, Usage, -} from "@mariozechner/pi-ai"; -import { createAssistantMessageEventStream } from "@mariozechner/pi-ai"; +} from "@earendil-works/pi-ai"; +import { createAssistantMessageEventStream } from "@earendil-works/pi-ai"; export const OLLAMA_NATIVE_BASE_URL = "http://127.0.0.1:11434"; diff --git a/src/agents/openai-responses.reasoning-replay.test.ts b/src/agents/openai-responses.reasoning-replay.test.ts index b5ccc50e..41efd555 100644 --- a/src/agents/openai-responses.reasoning-replay.test.ts +++ b/src/agents/openai-responses.reasoning-replay.test.ts @@ -1,5 +1,5 @@ -import type { AssistantMessage, Model, ToolResultMessage } from "@mariozechner/pi-ai"; -import { streamOpenAIResponses } from "@mariozechner/pi-ai"; +import type { AssistantMessage, Model, ToolResultMessage } from "@earendil-works/pi-ai"; +import { streamOpenAIResponses } from "@earendil-works/pi-ai/compat"; import { Type } from "@sinclair/typebox"; import { describe, expect, it } from "vitest"; diff --git a/src/agents/pi-embedded-helpers.formatassistanterrortext.e2e.test.ts b/src/agents/pi-embedded-helpers.formatassistanterrortext.e2e.test.ts index 1087d1b7..16ee72de 100644 --- a/src/agents/pi-embedded-helpers.formatassistanterrortext.e2e.test.ts +++ b/src/agents/pi-embedded-helpers.formatassistanterrortext.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { BILLING_ERROR_USER_MESSAGE, diff --git a/src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.e2e.test.ts b/src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.e2e.test.ts index 878b1199..7e784f95 100644 --- a/src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.e2e.test.ts +++ b/src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { sanitizeGoogleTurnOrdering, diff --git a/src/agents/pi-embedded-helpers.validate-turns.e2e.test.ts b/src/agents/pi-embedded-helpers.validate-turns.e2e.test.ts index ff1f9628..f143ed8c 100644 --- a/src/agents/pi-embedded-helpers.validate-turns.e2e.test.ts +++ b/src/agents/pi-embedded-helpers.validate-turns.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { mergeConsecutiveUserTurns, diff --git a/src/agents/pi-embedded-helpers/bootstrap.ts b/src/agents/pi-embedded-helpers/bootstrap.ts index 3b544435..1220c21f 100644 --- a/src/agents/pi-embedded-helpers/bootstrap.ts +++ b/src/agents/pi-embedded-helpers/bootstrap.ts @@ -1,6 +1,6 @@ import fs from "node:fs/promises"; import path from "node:path"; -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import type { MayrosConfig } from "../../config/config.js"; import { truncateUtf16Safe } from "../../utils.js"; import type { WorkspaceBootstrapFile } from "../workspace.js"; diff --git a/src/agents/pi-embedded-helpers/errors.ts b/src/agents/pi-embedded-helpers/errors.ts index b7644660..d58d1ad9 100644 --- a/src/agents/pi-embedded-helpers/errors.ts +++ b/src/agents/pi-embedded-helpers/errors.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import type { MayrosConfig } from "../../config/config.js"; import { formatSandboxToolPolicyBlockedMessage } from "../sandbox.js"; import { stableStringify } from "../stable-stringify.js"; diff --git a/src/agents/pi-embedded-helpers/images.ts b/src/agents/pi-embedded-helpers/images.ts index c3b4d0a3..2f289115 100644 --- a/src/agents/pi-embedded-helpers/images.ts +++ b/src/agents/pi-embedded-helpers/images.ts @@ -1,4 +1,4 @@ -import type { AgentMessage, AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentMessage, AgentToolResult } from "@earendil-works/pi-agent-core"; import type { ImageSanitizationLimits } from "../image-sanitization.js"; import type { ToolCallIdMode } from "../tool-call-id.js"; import { sanitizeToolCallIdsForCloudCodeAssist } from "../tool-call-id.js"; diff --git a/src/agents/pi-embedded-helpers/openai.ts b/src/agents/pi-embedded-helpers/openai.ts index c6a317aa..ddbf1f2e 100644 --- a/src/agents/pi-embedded-helpers/openai.ts +++ b/src/agents/pi-embedded-helpers/openai.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; type OpenAIThinkingBlock = { type?: unknown; diff --git a/src/agents/pi-embedded-helpers/turns.ts b/src/agents/pi-embedded-helpers/turns.ts index f6dddb20..3a01c801 100644 --- a/src/agents/pi-embedded-helpers/turns.ts +++ b/src/agents/pi-embedded-helpers/turns.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; function validateTurnsWithConsecutiveMerge(params: { messages: AgentMessage[]; diff --git a/src/agents/pi-embedded-runner-extraparams.e2e.test.ts b/src/agents/pi-embedded-runner-extraparams.e2e.test.ts index 57140582..5ab1663b 100644 --- a/src/agents/pi-embedded-runner-extraparams.e2e.test.ts +++ b/src/agents/pi-embedded-runner-extraparams.e2e.test.ts @@ -1,5 +1,5 @@ -import type { StreamFn } from "@mariozechner/pi-agent-core"; -import type { Context, Model, SimpleStreamOptions } from "@mariozechner/pi-ai"; +import type { StreamFn } from "@earendil-works/pi-agent-core"; +import type { Context, Model, SimpleStreamOptions } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { applyExtraParamsToAgent, resolveExtraParams } from "./pi-embedded-runner.js"; @@ -99,7 +99,7 @@ describe("applyExtraParamsToAgent", () => { }) { const payload = { store: false }; const baseStreamFn: StreamFn = (_model, _context, options) => { - options?.onPayload?.(payload); + options?.onPayload?.(payload, _model); return {} as ReturnType; }; const agent = { streamFn: baseStreamFn }; @@ -295,7 +295,7 @@ describe("applyExtraParamsToAgent", () => { it("does not force store=true for Codex responses (Codex requires store=false)", () => { const payload = { store: false }; const baseStreamFn: StreamFn = (_model, _context, options) => { - options?.onPayload?.(payload); + options?.onPayload?.(payload, _model); return {} as ReturnType; }; const agent = { streamFn: baseStreamFn }; diff --git a/src/agents/pi-embedded-runner-extraparams.live.test.ts b/src/agents/pi-embedded-runner-extraparams.live.test.ts index 602d79dd..3af3b122 100644 --- a/src/agents/pi-embedded-runner-extraparams.live.test.ts +++ b/src/agents/pi-embedded-runner-extraparams.live.test.ts @@ -1,5 +1,5 @@ -import type { Model } from "@mariozechner/pi-ai"; -import { getModel, streamSimple } from "@mariozechner/pi-ai"; +import type { Model } from "@earendil-works/pi-ai"; +import { getModel, streamSimple } from "@earendil-works/pi-ai/compat"; import { describe, expect, it } from "vitest"; import type { MayrosConfig } from "../config/config.js"; import { isTruthyEnvValue } from "../infra/env.js"; diff --git a/src/agents/pi-embedded-runner.applygoogleturnorderingfix.e2e.test.ts b/src/agents/pi-embedded-runner.applygoogleturnorderingfix.e2e.test.ts index f4807b7d..7fb80157 100644 --- a/src/agents/pi-embedded-runner.applygoogleturnorderingfix.e2e.test.ts +++ b/src/agents/pi-embedded-runner.applygoogleturnorderingfix.e2e.test.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import { SessionManager } from "@earendil-works/pi-coding-agent"; import { describe, expect, it, vi } from "vitest"; import { applyGoogleTurnOrderingFix } from "./pi-embedded-runner.js"; diff --git a/src/agents/pi-embedded-runner.e2e.test.ts b/src/agents/pi-embedded-runner.e2e.test.ts index 8d92aab5..9896bce0 100644 --- a/src/agents/pi-embedded-runner.e2e.test.ts +++ b/src/agents/pi-embedded-runner.e2e.test.ts @@ -6,8 +6,9 @@ import "./test-helpers/fast-coding-tools.js"; import type { MayrosConfig } from "../config/config.js"; import { ensureMayrosModelsJson } from "./models-config.js"; -vi.mock("@mariozechner/pi-ai", async () => { - const actual = await vi.importActual("@mariozechner/pi-ai"); +vi.mock("@earendil-works/pi-ai", async () => { + const actual = + await vi.importActual("@earendil-works/pi-ai"); const buildAssistantMessage = (model: { api: string; provider: string; id: string }) => ({ role: "assistant" as const, @@ -152,7 +153,7 @@ const testSessionKey = "agent:test:embedded"; const immediateEnqueue = async (task: () => Promise) => task(); const runWithOrphanedSingleUserMessage = async (text: string) => { - const { SessionManager } = await import("@mariozechner/pi-coding-agent"); + const { SessionManager } = await import("@earendil-works/pi-coding-agent"); const sessionFile = nextSessionFile(); const sessionManager = SessionManager.open(sessionFile); sessionManager.appendMessage({ @@ -418,7 +419,7 @@ describe("runEmbeddedPiAgent", () => { "appends new user + assistant after existing transcript entries", { timeout: 90_000 }, async () => { - const { SessionManager } = await import("@mariozechner/pi-coding-agent"); + const { SessionManager } = await import("@earendil-works/pi-coding-agent"); const sessionFile = nextSessionFile(); const sessionManager = SessionManager.open(sessionFile); diff --git a/src/agents/pi-embedded-runner.google-sanitize-thinking.e2e.test.ts b/src/agents/pi-embedded-runner.google-sanitize-thinking.e2e.test.ts index f716ff32..b811f1c9 100644 --- a/src/agents/pi-embedded-runner.google-sanitize-thinking.e2e.test.ts +++ b/src/agents/pi-embedded-runner.google-sanitize-thinking.e2e.test.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import { SessionManager } from "@earendil-works/pi-coding-agent"; import { describe, expect, it } from "vitest"; import { sanitizeSessionHistory } from "./pi-embedded-runner/google.js"; diff --git a/src/agents/pi-embedded-runner.guard.e2e.test.ts b/src/agents/pi-embedded-runner.guard.e2e.test.ts index d93a3520..1b239b4c 100644 --- a/src/agents/pi-embedded-runner.guard.e2e.test.ts +++ b/src/agents/pi-embedded-runner.guard.e2e.test.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import { SessionManager } from "@earendil-works/pi-coding-agent"; import { describe, expect, it } from "vitest"; import { guardSessionManager } from "./session-tool-result-guard-wrapper.js"; import { sanitizeToolUseResultPairing } from "./session-transcript-repair.js"; diff --git a/src/agents/pi-embedded-runner.guard.waitforidle-before-flush.test.ts b/src/agents/pi-embedded-runner.guard.waitforidle-before-flush.test.ts index d0396039..3cbcc91b 100644 --- a/src/agents/pi-embedded-runner.guard.waitforidle-before-flush.test.ts +++ b/src/agents/pi-embedded-runner.guard.waitforidle-before-flush.test.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import { SessionManager } from "@earendil-works/pi-coding-agent"; import { afterEach, describe, expect, it, vi } from "vitest"; import { flushPendingToolResultsAfterIdle } from "./pi-embedded-runner/wait-for-idle-before-flush.js"; import { guardSessionManager } from "./session-tool-result-guard-wrapper.js"; diff --git a/src/agents/pi-embedded-runner.limithistoryturns.e2e.test.ts b/src/agents/pi-embedded-runner.limithistoryturns.e2e.test.ts index e9cbbc5e..f1be64b1 100644 --- a/src/agents/pi-embedded-runner.limithistoryturns.e2e.test.ts +++ b/src/agents/pi-embedded-runner.limithistoryturns.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { limitHistoryTurns } from "./pi-embedded-runner.js"; diff --git a/src/agents/pi-embedded-runner.openai-tool-id-preservation.e2e.test.ts b/src/agents/pi-embedded-runner.openai-tool-id-preservation.e2e.test.ts index 5d3a86ee..cc2fab2b 100644 --- a/src/agents/pi-embedded-runner.openai-tool-id-preservation.e2e.test.ts +++ b/src/agents/pi-embedded-runner.openai-tool-id-preservation.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { makeInMemorySessionManager, diff --git a/src/agents/pi-embedded-runner.run-embedded-pi-agent.auth-profile-rotation.e2e.test.ts b/src/agents/pi-embedded-runner.run-embedded-pi-agent.auth-profile-rotation.e2e.test.ts index 5baa7954..6ad01c93 100644 --- a/src/agents/pi-embedded-runner.run-embedded-pi-agent.auth-profile-rotation.e2e.test.ts +++ b/src/agents/pi-embedded-runner.run-embedded-pi-agent.auth-profile-rotation.e2e.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import type { MayrosConfig } from "../config/config.js"; import type { EmbeddedRunAttemptResult } from "./pi-embedded-runner/run/types.js"; diff --git a/src/agents/pi-embedded-runner.sanitize-session-history.test-harness.ts b/src/agents/pi-embedded-runner.sanitize-session-history.test-harness.ts index bb371798..8990e14d 100644 --- a/src/agents/pi-embedded-runner.sanitize-session-history.test-harness.ts +++ b/src/agents/pi-embedded-runner.sanitize-session-history.test-harness.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { SessionManager } from "@earendil-works/pi-coding-agent"; import { expect, vi } from "vitest"; import * as helpers from "./pi-embedded-helpers.js"; diff --git a/src/agents/pi-embedded-runner.sanitize-session-history.test.ts b/src/agents/pi-embedded-runner.sanitize-session-history.test.ts index 665e9879..e48979ca 100644 --- a/src/agents/pi-embedded-runner.sanitize-session-history.test.ts +++ b/src/agents/pi-embedded-runner.sanitize-session-history.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { beforeEach, describe, expect, it, vi } from "vitest"; import * as helpers from "./pi-embedded-helpers.js"; import { diff --git a/src/agents/pi-embedded-runner.splitsdktools.e2e.test.ts b/src/agents/pi-embedded-runner.splitsdktools.e2e.test.ts index 9a376ebf..4ee6fcd1 100644 --- a/src/agents/pi-embedded-runner.splitsdktools.e2e.test.ts +++ b/src/agents/pi-embedded-runner.splitsdktools.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core"; import { Type } from "@sinclair/typebox"; import { describe, expect, it } from "vitest"; import { splitSdkTools } from "./pi-embedded-runner.js"; diff --git a/src/agents/pi-embedded-runner/compact.ts b/src/agents/pi-embedded-runner/compact.ts index 1c656b92..ceae1117 100644 --- a/src/agents/pi-embedded-runner/compact.ts +++ b/src/agents/pi-embedded-runner/compact.ts @@ -1,13 +1,13 @@ import fs from "node:fs/promises"; import os from "node:os"; -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { createAgentSession, DefaultResourceLoader, estimateTokens, SessionManager, SettingsManager, -} from "@mariozechner/pi-coding-agent"; +} from "@earendil-works/pi-coding-agent"; import { resolveHeartbeatPrompt } from "../../auto-reply/heartbeat.js"; import type { ReasoningLevel, ThinkLevel } from "../../auto-reply/thinking.js"; import { resolveChannelCapabilities } from "../../config/channel-capabilities.js"; @@ -611,7 +611,7 @@ export async function compactEmbeddedPiSessionDirect( ? sanitizeToolUseResultPairing(truncated) : truncated; if (limited.length > 0) { - session.agent.replaceMessages(limited); + session.agent.state.messages = limited; } // Run before_compaction hooks (fire-and-forget). // The session JSONL already contains all messages on disk, so plugins diff --git a/src/agents/pi-embedded-runner/extensions.ts b/src/agents/pi-embedded-runner/extensions.ts index a418bf68..ce4bdb0b 100644 --- a/src/agents/pi-embedded-runner/extensions.ts +++ b/src/agents/pi-embedded-runner/extensions.ts @@ -1,5 +1,5 @@ -import type { Api, Model } from "@mariozechner/pi-ai"; -import type { ExtensionFactory, SessionManager } from "@mariozechner/pi-coding-agent"; +import type { Api, Model } from "@earendil-works/pi-ai"; +import type { ExtensionFactory, SessionManager } from "@earendil-works/pi-coding-agent"; import type { MayrosConfig } from "../../config/config.js"; import { resolveContextWindowInfo } from "../context-window-guard.js"; import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js"; diff --git a/src/agents/pi-embedded-runner/extra-params.cache-retention-default.test.ts b/src/agents/pi-embedded-runner/extra-params.cache-retention-default.test.ts index cd093a86..640f4e29 100644 --- a/src/agents/pi-embedded-runner/extra-params.cache-retention-default.test.ts +++ b/src/agents/pi-embedded-runner/extra-params.cache-retention-default.test.ts @@ -1,4 +1,4 @@ -import type { StreamFn } from "@mariozechner/pi-agent-core"; +import type { StreamFn } from "@earendil-works/pi-agent-core"; import { describe, expect, it, vi } from "vitest"; import { applyExtraParamsToAgent } from "../pi-embedded-runner.js"; diff --git a/src/agents/pi-embedded-runner/extra-params.ts b/src/agents/pi-embedded-runner/extra-params.ts index 5addc333..470effae 100644 --- a/src/agents/pi-embedded-runner/extra-params.ts +++ b/src/agents/pi-embedded-runner/extra-params.ts @@ -1,6 +1,6 @@ -import type { StreamFn } from "@mariozechner/pi-agent-core"; -import type { SimpleStreamOptions } from "@mariozechner/pi-ai"; -import { streamSimple } from "@mariozechner/pi-ai"; +import type { StreamFn } from "@earendil-works/pi-agent-core"; +import type { ProviderHeaders, SimpleStreamOptions } from "@earendil-works/pi-ai"; +import { streamSimple } from "@earendil-works/pi-ai/compat"; import type { MayrosConfig } from "../../config/config.js"; import { log } from "./logger.js"; @@ -152,11 +152,11 @@ function createOpenAIResponsesStoreWrapper(baseStreamFn: StreamFn | undefined): const originalOnPayload = options?.onPayload; return underlying(model, context, { ...options, - onPayload: (payload) => { + onPayload: (payload, payloadModel) => { if (payload && typeof payload === "object") { (payload as { store?: unknown }).store = true; } - originalOnPayload?.(payload); + return originalOnPayload?.(payload, payloadModel); }, }); }; @@ -210,9 +210,9 @@ function resolveAnthropicBetas( } function mergeAnthropicBetaHeader( - headers: Record | undefined, + headers: ProviderHeaders | undefined, betas: string[], -): Record { +): ProviderHeaders { const merged = { ...headers }; const existingKey = Object.keys(merged).find((key) => key.toLowerCase() === "anthropic-beta"); const existing = existingKey ? parseHeaderList(merged[existingKey]) : []; @@ -302,12 +302,12 @@ function createZaiToolStreamWrapper( const originalOnPayload = options?.onPayload; return underlying(model, context, { ...options, - onPayload: (payload) => { + onPayload: (payload, payloadModel) => { if (payload && typeof payload === "object") { // Inject tool_stream: true for Z.AI API (payload as Record).tool_stream = true; } - originalOnPayload?.(payload); + return originalOnPayload?.(payload, payloadModel); }, }); }; diff --git a/src/agents/pi-embedded-runner/extra-params.zai-tool-stream.test.ts b/src/agents/pi-embedded-runner/extra-params.zai-tool-stream.test.ts index 3a757cea..59dd83d5 100644 --- a/src/agents/pi-embedded-runner/extra-params.zai-tool-stream.test.ts +++ b/src/agents/pi-embedded-runner/extra-params.zai-tool-stream.test.ts @@ -1,10 +1,10 @@ -import type { StreamFn } from "@mariozechner/pi-agent-core"; -import type { Context, Model, SimpleStreamOptions } from "@mariozechner/pi-ai"; +import type { StreamFn } from "@earendil-works/pi-agent-core"; +import type { Context, Model, SimpleStreamOptions } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { applyExtraParamsToAgent } from "./extra-params.js"; // Mock streamSimple for testing -vi.mock("@mariozechner/pi-ai", () => ({ +vi.mock("@earendil-works/pi-ai", () => ({ streamSimple: vi.fn(() => ({ push: vi.fn(), result: vi.fn(), @@ -22,7 +22,7 @@ type ToolStreamCase = { function runToolStreamCase(params: ToolStreamCase) { const payload: Record = { model: params.model.id, messages: [] }; const baseStreamFn: StreamFn = (_model, _context, options) => { - options?.onPayload?.(payload); + options?.onPayload?.(payload, _model); return {} as ReturnType; }; const agent = { streamFn: baseStreamFn }; diff --git a/src/agents/pi-embedded-runner/google.e2e.test.ts b/src/agents/pi-embedded-runner/google.e2e.test.ts index f5e331b1..e5d41dc5 100644 --- a/src/agents/pi-embedded-runner/google.e2e.test.ts +++ b/src/agents/pi-embedded-runner/google.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentTool } from "@mariozechner/pi-agent-core"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { sanitizeToolsForGoogle } from "./google.js"; diff --git a/src/agents/pi-embedded-runner/google.ts b/src/agents/pi-embedded-runner/google.ts index 394dddf7..5633f43c 100644 --- a/src/agents/pi-embedded-runner/google.ts +++ b/src/agents/pi-embedded-runner/google.ts @@ -1,7 +1,7 @@ import { EventEmitter } from "node:events"; -import type { AgentMessage, AgentTool } from "@mariozechner/pi-agent-core"; -import type { SessionManager } from "@mariozechner/pi-coding-agent"; -import type { TSchema } from "@sinclair/typebox"; +import type { AgentMessage, AgentTool } from "@earendil-works/pi-agent-core"; +import type { SessionManager } from "@earendil-works/pi-coding-agent"; +import type { TSchema } from "@earendil-works/pi-ai"; import type { MayrosConfig } from "../../config/config.js"; import { registerUnhandledRejectionHandler } from "../../infra/unhandled-rejections.js"; import { diff --git a/src/agents/pi-embedded-runner/history.ts b/src/agents/pi-embedded-runner/history.ts index bf3228f9..2113341e 100644 --- a/src/agents/pi-embedded-runner/history.ts +++ b/src/agents/pi-embedded-runner/history.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import type { MayrosConfig } from "../../config/config.js"; const THREAD_SUFFIX_REGEX = /^(.*)(?::(?:thread|topic):\d+)$/i; diff --git a/src/agents/pi-embedded-runner/model.ts b/src/agents/pi-embedded-runner/model.ts index 7fa32f02..fb08c083 100644 --- a/src/agents/pi-embedded-runner/model.ts +++ b/src/agents/pi-embedded-runner/model.ts @@ -1,4 +1,4 @@ -import type { Api, Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; import type { MayrosConfig } from "../../config/config.js"; import type { ModelDefinitionConfig } from "../../config/types.js"; import { resolveMayrosAgentDir } from "../agent-paths.js"; diff --git a/src/agents/pi-embedded-runner/run/attempt.e2e.test.ts b/src/agents/pi-embedded-runner/run/attempt.e2e.test.ts index ca931138..11a4cb3a 100644 --- a/src/agents/pi-embedded-runner/run/attempt.e2e.test.ts +++ b/src/agents/pi-embedded-runner/run/attempt.e2e.test.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { ImageContent } from "@mariozechner/pi-ai"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { ImageContent } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { injectHistoryImagesIntoMessages } from "./attempt.js"; diff --git a/src/agents/pi-embedded-runner/run/attempt.ts b/src/agents/pi-embedded-runner/run/attempt.ts index ebf3e740..0f36626b 100644 --- a/src/agents/pi-embedded-runner/run/attempt.ts +++ b/src/agents/pi-embedded-runner/run/attempt.ts @@ -1,14 +1,14 @@ import fs from "node:fs/promises"; import os from "node:os"; -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { ImageContent } from "@mariozechner/pi-ai"; -import { streamSimple } from "@mariozechner/pi-ai"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { ImageContent } from "@earendil-works/pi-ai"; +import { streamSimple } from "@earendil-works/pi-ai/compat"; import { createAgentSession, DefaultResourceLoader, SessionManager, SettingsManager, -} from "@mariozechner/pi-coding-agent"; +} from "@earendil-works/pi-coding-agent"; import { resolveHeartbeatPrompt } from "../../../auto-reply/heartbeat.js"; import { resolveChannelCapabilities } from "../../../config/channel-capabilities.js"; import { getMachineDisplayName } from "../../../infra/machine-name.js"; @@ -657,7 +657,7 @@ export async function runEmbeddedAttempt( const ollamaBaseUrl = modelBaseUrl || providerBaseUrl || OLLAMA_NATIVE_BASE_URL; activeSession.agent.streamFn = createOllamaStreamFn(ollamaBaseUrl); } else { - // Force a stable streamFn reference so vitest can reliably mock @mariozechner/pi-ai. + // Force a stable streamFn reference so vitest can reliably mock @earendil-works/pi-ai. activeSession.agent.streamFn = streamSimple; } @@ -737,7 +737,7 @@ export async function runEmbeddedAttempt( : truncated; cacheTrace?.recordStage("session:limited", { messages: limited }); if (limited.length > 0) { - activeSession.agent.replaceMessages(limited); + activeSession.agent.state.messages = limited; } } catch (err) { await flushPendingToolResultsAfterIdle({ @@ -1002,7 +1002,7 @@ export async function runEmbeddedAttempt( const sanitizedOrphan = transcriptPolicy.sanitizeThinkingSignatures ? sanitizeAntigravityThinkingBlocks(sessionContext.messages) : sessionContext.messages; - activeSession.agent.replaceMessages(sanitizedOrphan); + activeSession.agent.state.messages = sanitizedOrphan; log.warn( `Removed orphaned user message to prevent consecutive user turns. ` + `runId=${params.runId} sessionId=${params.sessionId}`, @@ -1037,7 +1037,7 @@ export async function runEmbeddedAttempt( ); if (didMutate) { // Persist message mutations (e.g., injected history images) so we don't re-scan/reload. - activeSession.agent.replaceMessages(activeSession.messages); + activeSession.agent.state.messages = activeSession.messages; } cacheTrace?.recordStage("prompt:images", { diff --git a/src/agents/pi-embedded-runner/run/compaction-timeout.e2e.test.ts b/src/agents/pi-embedded-runner/run/compaction-timeout.e2e.test.ts index 7258a33b..75d20e32 100644 --- a/src/agents/pi-embedded-runner/run/compaction-timeout.e2e.test.ts +++ b/src/agents/pi-embedded-runner/run/compaction-timeout.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { selectCompactionTimeoutSnapshot, diff --git a/src/agents/pi-embedded-runner/run/compaction-timeout.ts b/src/agents/pi-embedded-runner/run/compaction-timeout.ts index 45a94525..1dde57df 100644 --- a/src/agents/pi-embedded-runner/run/compaction-timeout.ts +++ b/src/agents/pi-embedded-runner/run/compaction-timeout.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; export type CompactionTimeoutSignal = { isTimeout: boolean; diff --git a/src/agents/pi-embedded-runner/run/images.ts b/src/agents/pi-embedded-runner/run/images.ts index c11f191e..f486bdd2 100644 --- a/src/agents/pi-embedded-runner/run/images.ts +++ b/src/agents/pi-embedded-runner/run/images.ts @@ -1,6 +1,6 @@ import path from "node:path"; import { fileURLToPath } from "node:url"; -import type { ImageContent } from "@mariozechner/pi-ai"; +import type { ImageContent } from "@earendil-works/pi-ai"; import { resolveUserPath } from "../../../utils.js"; import { loadWebMedia } from "../../../web/media.js"; import type { ImageSanitizationLimits } from "../../image-sanitization.js"; diff --git a/src/agents/pi-embedded-runner/run/params.ts b/src/agents/pi-embedded-runner/run/params.ts index 29e0a244..95c2ff37 100644 --- a/src/agents/pi-embedded-runner/run/params.ts +++ b/src/agents/pi-embedded-runner/run/params.ts @@ -1,4 +1,4 @@ -import type { ImageContent } from "@mariozechner/pi-ai"; +import type { ImageContent } from "@earendil-works/pi-ai"; import type { ReasoningLevel, ThinkLevel, VerboseLevel } from "../../../auto-reply/thinking.js"; import type { AgentStreamParams } from "../../../commands/agent/types.js"; import type { MayrosConfig } from "../../../config/config.js"; diff --git a/src/agents/pi-embedded-runner/run/payloads.e2e.test.ts b/src/agents/pi-embedded-runner/run/payloads.e2e.test.ts index 39767e8f..0c6a3e52 100644 --- a/src/agents/pi-embedded-runner/run/payloads.e2e.test.ts +++ b/src/agents/pi-embedded-runner/run/payloads.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { formatBillingErrorMessage } from "../../pi-embedded-helpers.js"; import { makeAssistantMessageFixture } from "../../test-helpers/assistant-message-fixtures.js"; diff --git a/src/agents/pi-embedded-runner/run/payloads.ts b/src/agents/pi-embedded-runner/run/payloads.ts index 7d65bfc2..849d88e1 100644 --- a/src/agents/pi-embedded-runner/run/payloads.ts +++ b/src/agents/pi-embedded-runner/run/payloads.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { parseReplyDirectives } from "../../../auto-reply/reply/reply-directives.js"; import type { ReasoningLevel, VerboseLevel } from "../../../auto-reply/thinking.js"; import { stripReasoningTagsFromText } from "../../../shared/text/reasoning-tags.js"; diff --git a/src/agents/pi-embedded-runner/run/types.ts b/src/agents/pi-embedded-runner/run/types.ts index f0d12348..f2f69003 100644 --- a/src/agents/pi-embedded-runner/run/types.ts +++ b/src/agents/pi-embedded-runner/run/types.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { Api, AssistantMessage, Model } from "@mariozechner/pi-ai"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { Api, AssistantMessage, Model } from "@earendil-works/pi-ai"; import type { ThinkLevel } from "../../../auto-reply/thinking.js"; import type { SessionSystemPromptReport } from "../../../config/sessions/types.js"; import type { MessagingToolSend } from "../../pi-embedded-messaging.js"; diff --git a/src/agents/pi-embedded-runner/sanitize-session-history.tool-result-details.e2e.test.ts b/src/agents/pi-embedded-runner/sanitize-session-history.tool-result-details.e2e.test.ts index 53c97356..50c63bb5 100644 --- a/src/agents/pi-embedded-runner/sanitize-session-history.tool-result-details.e2e.test.ts +++ b/src/agents/pi-embedded-runner/sanitize-session-history.tool-result-details.e2e.test.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import { SessionManager } from "@earendil-works/pi-coding-agent"; import { describe, expect, it } from "vitest"; import { sanitizeSessionHistory } from "./google.js"; diff --git a/src/agents/pi-embedded-runner/system-prompt.ts b/src/agents/pi-embedded-runner/system-prompt.ts index 67df4493..e9a88054 100644 --- a/src/agents/pi-embedded-runner/system-prompt.ts +++ b/src/agents/pi-embedded-runner/system-prompt.ts @@ -1,5 +1,5 @@ -import type { AgentTool } from "@mariozechner/pi-agent-core"; -import type { AgentSession } from "@mariozechner/pi-coding-agent"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; +import type { AgentSession } from "@earendil-works/pi-coding-agent"; import type { MemoryCitationsMode } from "../../config/types.memory.js"; import type { ResolvedTimeFormat } from "../date-time.js"; import type { EmbeddedContextFile } from "../pi-embedded-helpers.js"; @@ -93,7 +93,7 @@ export function applySystemPromptOverrideToSession( override: string | ((defaultPrompt?: string) => string), ) { const prompt = typeof override === "function" ? override() : override.trim(); - session.agent.setSystemPrompt(prompt); + session.agent.state.systemPrompt = prompt; const mutableSession = session as unknown as { _baseSystemPrompt?: string; _rebuildSystemPrompt?: (toolNames: string[]) => string; diff --git a/src/agents/pi-embedded-runner/thinking.ts b/src/agents/pi-embedded-runner/thinking.ts index 5cd7ba7d..38780b70 100644 --- a/src/agents/pi-embedded-runner/thinking.ts +++ b/src/agents/pi-embedded-runner/thinking.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; type AssistantContentBlock = Extract["content"][number]; diff --git a/src/agents/pi-embedded-runner/tool-result-context-guard.e2e.test.ts b/src/agents/pi-embedded-runner/tool-result-context-guard.e2e.test.ts index 00915be4..9cdfd6c9 100644 --- a/src/agents/pi-embedded-runner/tool-result-context-guard.e2e.test.ts +++ b/src/agents/pi-embedded-runner/tool-result-context-guard.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { CONTEXT_LIMIT_TRUNCATION_NOTICE, diff --git a/src/agents/pi-embedded-runner/tool-result-context-guard.ts b/src/agents/pi-embedded-runner/tool-result-context-guard.ts index 2cc8d1ba..19ed6a69 100644 --- a/src/agents/pi-embedded-runner/tool-result-context-guard.ts +++ b/src/agents/pi-embedded-runner/tool-result-context-guard.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; const CHARS_PER_TOKEN_ESTIMATE = 4; // Keep a conservative input budget to absorb tokenizer variance and provider framing overhead. diff --git a/src/agents/pi-embedded-runner/tool-result-truncation.e2e.test.ts b/src/agents/pi-embedded-runner/tool-result-truncation.e2e.test.ts index 6b7bbcf4..b75020ab 100644 --- a/src/agents/pi-embedded-runner/tool-result-truncation.e2e.test.ts +++ b/src/agents/pi-embedded-runner/tool-result-truncation.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { truncateToolResultText, diff --git a/src/agents/pi-embedded-runner/tool-result-truncation.ts b/src/agents/pi-embedded-runner/tool-result-truncation.ts index 5d54cbf8..811315ec 100644 --- a/src/agents/pi-embedded-runner/tool-result-truncation.ts +++ b/src/agents/pi-embedded-runner/tool-result-truncation.ts @@ -1,6 +1,6 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { TextContent } from "@mariozechner/pi-ai"; -import { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { TextContent } from "@earendil-works/pi-ai"; +import { SessionManager } from "@earendil-works/pi-coding-agent"; import { log } from "./logger.js"; /** diff --git a/src/agents/pi-embedded-runner/tool-split.ts b/src/agents/pi-embedded-runner/tool-split.ts index 26eb0866..9370f07b 100644 --- a/src/agents/pi-embedded-runner/tool-split.ts +++ b/src/agents/pi-embedded-runner/tool-split.ts @@ -1,4 +1,4 @@ -import type { AgentTool } from "@mariozechner/pi-agent-core"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; import { toToolDefinitions } from "../pi-tool-definition-adapter.js"; // We always pass tools via `customTools` so our policy filtering, sandbox integration, @@ -6,7 +6,7 @@ import { toToolDefinitions } from "../pi-tool-definition-adapter.js"; type AnyAgentTool = AgentTool; export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }): { - builtInTools: AnyAgentTool[]; + builtInTools: string[]; customTools: ReturnType; } { const { tools } = options; diff --git a/src/agents/pi-embedded-runner/utils.ts b/src/agents/pi-embedded-runner/utils.ts index 9450998e..c35cb47e 100644 --- a/src/agents/pi-embedded-runner/utils.ts +++ b/src/agents/pi-embedded-runner/utils.ts @@ -1,4 +1,4 @@ -import type { ThinkingLevel } from "@mariozechner/pi-agent-core"; +import type { ThinkingLevel } from "@earendil-works/pi-agent-core"; import type { ReasoningLevel, ThinkLevel } from "../../auto-reply/thinking.js"; export function mapThinkingLevel(level?: ThinkLevel): ThinkingLevel { diff --git a/src/agents/pi-embedded-subscribe.e2e-harness.ts b/src/agents/pi-embedded-subscribe.e2e-harness.ts index 918685a1..25d75cd0 100644 --- a/src/agents/pi-embedded-subscribe.e2e-harness.ts +++ b/src/agents/pi-embedded-subscribe.e2e-harness.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { expect } from "vitest"; import { subscribeEmbeddedPiSession } from "./pi-embedded-subscribe.js"; diff --git a/src/agents/pi-embedded-subscribe.handlers.compaction.ts b/src/agents/pi-embedded-subscribe.handlers.compaction.ts index f28e47d1..018863f8 100644 --- a/src/agents/pi-embedded-subscribe.handlers.compaction.ts +++ b/src/agents/pi-embedded-subscribe.handlers.compaction.ts @@ -1,4 +1,4 @@ -import type { AgentEvent } from "@mariozechner/pi-agent-core"; +import type { AgentEvent } from "@earendil-works/pi-agent-core"; import { emitAgentEvent } from "../infra/agent-events.js"; import { getGlobalHookRunner } from "../plugins/hook-runner-global.js"; import type { EmbeddedPiSubscribeContext } from "./pi-embedded-subscribe.handlers.types.js"; diff --git a/src/agents/pi-embedded-subscribe.handlers.messages.ts b/src/agents/pi-embedded-subscribe.handlers.messages.ts index 845ded9f..2a5a79c3 100644 --- a/src/agents/pi-embedded-subscribe.handlers.messages.ts +++ b/src/agents/pi-embedded-subscribe.handlers.messages.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentEvent, AgentMessage } from "@earendil-works/pi-agent-core"; import { parseReplyDirectives } from "../auto-reply/reply/reply-directives.js"; import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js"; import { emitAgentEvent } from "../infra/agent-events.js"; diff --git a/src/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.ts b/src/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.ts index 378ae575..36816045 100644 --- a/src/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.ts +++ b/src/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.ts @@ -1,4 +1,4 @@ -import type { AgentEvent } from "@mariozechner/pi-agent-core"; +import type { AgentEvent } from "@earendil-works/pi-agent-core"; import type { Mock } from "vitest"; import { handleToolExecutionEnd, diff --git a/src/agents/pi-embedded-subscribe.handlers.tools.test.ts b/src/agents/pi-embedded-subscribe.handlers.tools.test.ts index c03eb00d..d116af50 100644 --- a/src/agents/pi-embedded-subscribe.handlers.tools.test.ts +++ b/src/agents/pi-embedded-subscribe.handlers.tools.test.ts @@ -1,4 +1,4 @@ -import type { AgentEvent } from "@mariozechner/pi-agent-core"; +import type { AgentEvent } from "@earendil-works/pi-agent-core"; import { describe, expect, it, vi } from "vitest"; import type { MessagingToolSend } from "./pi-embedded-messaging.js"; import { diff --git a/src/agents/pi-embedded-subscribe.handlers.tools.ts b/src/agents/pi-embedded-subscribe.handlers.tools.ts index 17d6eabf..61c7ccf0 100644 --- a/src/agents/pi-embedded-subscribe.handlers.tools.ts +++ b/src/agents/pi-embedded-subscribe.handlers.tools.ts @@ -1,4 +1,4 @@ -import type { AgentEvent } from "@mariozechner/pi-agent-core"; +import type { AgentEvent } from "@earendil-works/pi-agent-core"; import { emitAgentEvent } from "../infra/agent-events.js"; import { getGlobalHookRunner } from "../plugins/hook-runner-global.js"; import type { PluginHookAfterToolCallEvent } from "../plugins/types.js"; diff --git a/src/agents/pi-embedded-subscribe.handlers.types.ts b/src/agents/pi-embedded-subscribe.handlers.types.ts index d5c72552..9d9a4eea 100644 --- a/src/agents/pi-embedded-subscribe.handlers.types.ts +++ b/src/agents/pi-embedded-subscribe.handlers.types.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentEvent, AgentMessage } from "@earendil-works/pi-agent-core"; import type { ReplyDirectiveParseResult } from "../auto-reply/reply/reply-directives.js"; import type { ReasoningLevel } from "../auto-reply/thinking.js"; import type { InlineCodeState } from "../markdown/code-spans.js"; diff --git a/src/agents/pi-embedded-subscribe.lifecycle-billing-error.e2e.test.ts b/src/agents/pi-embedded-subscribe.lifecycle-billing-error.e2e.test.ts index 669bb50c..8773645c 100644 --- a/src/agents/pi-embedded-subscribe.lifecycle-billing-error.e2e.test.ts +++ b/src/agents/pi-embedded-subscribe.lifecycle-billing-error.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { createStubSessionHarness } from "./pi-embedded-subscribe.e2e-harness.js"; import { subscribeEmbeddedPiSession } from "./pi-embedded-subscribe.js"; diff --git a/src/agents/pi-embedded-subscribe.reply-tags.e2e.test.ts b/src/agents/pi-embedded-subscribe.reply-tags.e2e.test.ts index a76db602..961ec557 100644 --- a/src/agents/pi-embedded-subscribe.reply-tags.e2e.test.ts +++ b/src/agents/pi-embedded-subscribe.reply-tags.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { createStubSessionHarness, diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-emit-duplicate-block-replies-text.e2e.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-emit-duplicate-block-replies-text.e2e.test.ts index 44f829af..dd778b27 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-emit-duplicate-block-replies-text.e2e.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-emit-duplicate-block-replies-text.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { createStubSessionHarness, diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-block-replies-text-end-does-not.e2e.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-block-replies-text-end-does-not.e2e.test.ts index cb383b04..e5097781 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-block-replies-text-end-does-not.e2e.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-block-replies-text-end-does-not.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { createTextEndBlockReplyHarness, diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-reasoning-as-separate-message-enabled.e2e.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-reasoning-as-separate-message-enabled.e2e.test.ts index 98b4ce09..2da43ccb 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-reasoning-as-separate-message-enabled.e2e.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-reasoning-as-separate-message-enabled.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { THINKING_TAG_CASES, diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.filters-final-suppresses-output-without-start-tag.e2e.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.filters-final-suppresses-output-without-start-tag.e2e.test.ts index 9ccb7860..87fc886e 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.filters-final-suppresses-output-without-start-tag.e2e.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.filters-final-suppresses-output-without-start-tag.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { createStubSessionHarness, diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.keeps-assistanttexts-final-answer-block-replies-are.e2e.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.keeps-assistanttexts-final-answer-block-replies-are.e2e.test.ts index 710b1f28..a902d920 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.keeps-assistanttexts-final-answer-block-replies-are.e2e.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.keeps-assistanttexts-final-answer-block-replies-are.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { createStubSessionHarness, diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.e2e.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.e2e.test.ts index bbc2a019..869f9529 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.e2e.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { createParagraphChunkedBlockReplyHarness, diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.e2e.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.e2e.test.ts index a048ab2d..22f01904 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.e2e.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { THINKING_TAG_CASES, diff --git a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.suppresses-message-end-block-replies-message-tool.e2e.test.ts b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.suppresses-message-end-block-replies-message-tool.e2e.test.ts index 737edc7f..ffd8e672 100644 --- a/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.suppresses-message-end-block-replies-message-tool.e2e.test.ts +++ b/src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.suppresses-message-end-block-replies-message-tool.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it, vi } from "vitest"; import { createStubSessionHarness, diff --git a/src/agents/pi-embedded-subscribe.ts b/src/agents/pi-embedded-subscribe.ts index b3326c39..267a63df 100644 --- a/src/agents/pi-embedded-subscribe.ts +++ b/src/agents/pi-embedded-subscribe.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { parseReplyDirectives } from "../auto-reply/reply/reply-directives.js"; import { createStreamingDirectiveAccumulator } from "../auto-reply/reply/streaming-directives.js"; import { formatToolAggregate } from "../auto-reply/tool-meta.js"; diff --git a/src/agents/pi-embedded-subscribe.types.ts b/src/agents/pi-embedded-subscribe.types.ts index e9b6ebd3..e536832d 100644 --- a/src/agents/pi-embedded-subscribe.types.ts +++ b/src/agents/pi-embedded-subscribe.types.ts @@ -1,4 +1,4 @@ -import type { AgentSession } from "@mariozechner/pi-coding-agent"; +import type { AgentSession } from "@earendil-works/pi-coding-agent"; import type { ReasoningLevel, VerboseLevel } from "../auto-reply/thinking.js"; import type { MayrosConfig } from "../config/types.mayros.js"; import type { HookRunner } from "../plugins/hooks.js"; diff --git a/src/agents/pi-embedded-utils.e2e.test.ts b/src/agents/pi-embedded-utils.e2e.test.ts index ecb8dace..a5c972ba 100644 --- a/src/agents/pi-embedded-utils.e2e.test.ts +++ b/src/agents/pi-embedded-utils.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { extractAssistantText, diff --git a/src/agents/pi-embedded-utils.ts b/src/agents/pi-embedded-utils.ts index 82ad3efc..88e317f1 100644 --- a/src/agents/pi-embedded-utils.ts +++ b/src/agents/pi-embedded-utils.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import { extractTextFromChatContent } from "../shared/chat-content.js"; import { stripReasoningTagsFromText } from "../shared/text/reasoning-tags.js"; import { sanitizeUserFacingText } from "./pi-embedded-helpers.js"; diff --git a/src/agents/pi-extensions/compaction-safeguard.e2e.test.ts b/src/agents/pi-extensions/compaction-safeguard.e2e.test.ts index 3d5fab42..c9f7c12b 100644 --- a/src/agents/pi-extensions/compaction-safeguard.e2e.test.ts +++ b/src/agents/pi-extensions/compaction-safeguard.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { getCompactionSafeguardRuntime, diff --git a/src/agents/pi-extensions/compaction-safeguard.ts b/src/agents/pi-extensions/compaction-safeguard.ts index 12c6627e..b0a7a6b0 100644 --- a/src/agents/pi-extensions/compaction-safeguard.ts +++ b/src/agents/pi-extensions/compaction-safeguard.ts @@ -1,7 +1,7 @@ import fs from "node:fs"; import path from "node:path"; -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { ExtensionAPI, FileOperations } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { ExtensionAPI, FileOperations } from "@earendil-works/pi-coding-agent"; import { extractSections } from "../../auto-reply/reply/post-compaction-context.js"; import { BASE_CHUNK_RATIO, @@ -207,7 +207,7 @@ export default function compactionSafeguardExtension(api: ExtensionAPI): void { }; } - const apiKey = await ctx.modelRegistry.getApiKey(model); + const apiKey = await ctx.modelRegistry.getApiKeyForProvider(model.provider); if (!apiKey) { return { compaction: { diff --git a/src/agents/pi-extensions/context-pruning.e2e.test.ts b/src/agents/pi-extensions/context-pruning.e2e.test.ts index c71591d7..649d113b 100644 --- a/src/agents/pi-extensions/context-pruning.e2e.test.ts +++ b/src/agents/pi-extensions/context-pruning.e2e.test.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; import { describe, expect, it } from "vitest"; import { computeEffectiveSettings, diff --git a/src/agents/pi-extensions/context-pruning/extension.ts b/src/agents/pi-extensions/context-pruning/extension.ts index 2a4063ae..dc86e6ed 100644 --- a/src/agents/pi-extensions/context-pruning/extension.ts +++ b/src/agents/pi-extensions/context-pruning/extension.ts @@ -1,4 +1,4 @@ -import type { ContextEvent, ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent"; +import type { ContextEvent, ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; import { pruneContextMessages } from "./pruner.js"; import { getContextPruningRuntime } from "./runtime.js"; diff --git a/src/agents/pi-extensions/context-pruning/pruner.ts b/src/agents/pi-extensions/context-pruning/pruner.ts index acfa6316..406793e1 100644 --- a/src/agents/pi-extensions/context-pruning/pruner.ts +++ b/src/agents/pi-extensions/context-pruning/pruner.ts @@ -1,6 +1,6 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { ImageContent, TextContent, ToolResultMessage } from "@mariozechner/pi-ai"; -import type { ExtensionContext } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { ImageContent, TextContent, ToolResultMessage } from "@earendil-works/pi-ai"; +import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; import type { EffectiveContextPruningSettings } from "./settings.js"; import { makeToolPrunablePredicate } from "./tools.js"; diff --git a/src/agents/pi-model-discovery.ts b/src/agents/pi-model-discovery.ts index 51ac1aeb..96bdcc88 100644 --- a/src/agents/pi-model-discovery.ts +++ b/src/agents/pi-model-discovery.ts @@ -1,7 +1,7 @@ import path from "node:path"; -import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent"; +import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent"; -export { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent"; +export { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent"; function createAuthStorage(AuthStorageLike: unknown, path: string) { const withFactory = AuthStorageLike as { create?: (path: string) => unknown }; @@ -17,5 +17,5 @@ export function discoverAuthStorage(agentDir: string): AuthStorage { } export function discoverModels(authStorage: AuthStorage, agentDir: string): ModelRegistry { - return new ModelRegistry(authStorage, path.join(agentDir, "models.json")); + return ModelRegistry.create(authStorage, path.join(agentDir, "models.json")); } diff --git a/src/agents/pi-tool-definition-adapter.after-tool-call.e2e.test.ts b/src/agents/pi-tool-definition-adapter.after-tool-call.e2e.test.ts index 5d442fc6..f6f8a374 100644 --- a/src/agents/pi-tool-definition-adapter.after-tool-call.e2e.test.ts +++ b/src/agents/pi-tool-definition-adapter.after-tool-call.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentTool } from "@mariozechner/pi-agent-core"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; import { Type } from "@sinclair/typebox"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { toToolDefinitions } from "./pi-tool-definition-adapter.js"; diff --git a/src/agents/pi-tool-definition-adapter.e2e.test.ts b/src/agents/pi-tool-definition-adapter.e2e.test.ts index 1b11bbf4..161dbe7c 100644 --- a/src/agents/pi-tool-definition-adapter.e2e.test.ts +++ b/src/agents/pi-tool-definition-adapter.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentTool } from "@mariozechner/pi-agent-core"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; import { Type } from "@sinclair/typebox"; import { describe, expect, it } from "vitest"; import { toToolDefinitions } from "./pi-tool-definition-adapter.js"; diff --git a/src/agents/pi-tool-definition-adapter.ts b/src/agents/pi-tool-definition-adapter.ts index f3963600..4e70485e 100644 --- a/src/agents/pi-tool-definition-adapter.ts +++ b/src/agents/pi-tool-definition-adapter.ts @@ -2,8 +2,8 @@ import type { AgentTool, AgentToolResult, AgentToolUpdateCallback, -} from "@mariozechner/pi-agent-core"; -import type { ToolDefinition } from "@mariozechner/pi-coding-agent"; +} from "@earendil-works/pi-agent-core"; +import type { ToolDefinition } from "@earendil-works/pi-coding-agent"; import { logDebug, logError } from "../logger.js"; import { getGlobalHookRunner } from "../plugins/hook-runner-global.js"; import { isPlainObject } from "../utils.js"; diff --git a/src/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping.e2e.test.ts b/src/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping.e2e.test.ts index 68483d73..a57c4395 100644 --- a/src/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping.e2e.test.ts +++ b/src/agents/pi-tools.create-mayros-coding-tools.adds-claude-style-aliases-schemas-without-dropping.e2e.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core"; import { Type } from "@sinclair/typebox"; import { describe, expect, it, vi } from "vitest"; import "./test-helpers/fast-coding-tools.js"; diff --git a/src/agents/pi-tools.policy.e2e.test.ts b/src/agents/pi-tools.policy.e2e.test.ts index b36fb18c..5206e550 100644 --- a/src/agents/pi-tools.policy.e2e.test.ts +++ b/src/agents/pi-tools.policy.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core"; import { Type } from "@sinclair/typebox"; import { describe, expect, it } from "vitest"; import type { MayrosConfig } from "../config/config.js"; diff --git a/src/agents/pi-tools.read.ts b/src/agents/pi-tools.read.ts index 385d25a4..397a3c29 100644 --- a/src/agents/pi-tools.read.ts +++ b/src/agents/pi-tools.read.ts @@ -1,5 +1,5 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; -import { createEditTool, createReadTool, createWriteTool } from "@mariozechner/pi-coding-agent"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; +import { createEditTool, createReadTool, createWriteTool } from "@earendil-works/pi-coding-agent"; import { detectMime } from "../media/mime.js"; import { sniffMimeFromBase64 } from "../media/sniff-mime-from-base64.js"; import type { ImageSanitizationLimits } from "./image-sanitization.js"; diff --git a/src/agents/pi-tools.ts b/src/agents/pi-tools.ts index a6ca4386..1f9659fc 100644 --- a/src/agents/pi-tools.ts +++ b/src/agents/pi-tools.ts @@ -1,10 +1,9 @@ import { - codingTools, + createCodingTools, createEditTool, createReadTool, createWriteTool, - readTool, -} from "@mariozechner/pi-coding-agent"; +} from "@earendil-works/pi-coding-agent"; import type { MayrosConfig } from "../config/config.js"; import type { ToolLoopDetectionConfig } from "../config/types.tools.js"; import { logWarn } from "../logger.js"; @@ -303,8 +302,8 @@ export function createMayrosCodingTools(options?: { } const imageSanitization = resolveImageSanitizationLimits(options?.config); - const base = (codingTools as unknown as AnyAgentTool[]).flatMap((tool) => { - if (tool.name === readTool.name) { + const base = (createCodingTools(workspaceRoot) as unknown as AnyAgentTool[]).flatMap((tool) => { + if (tool.name === "read") { if (sandboxRoot) { const sandboxed = createSandboxedReadTool({ root: sandboxRoot, diff --git a/src/agents/pi-tools.types.ts b/src/agents/pi-tools.types.ts index ad2bd85f..3c8aa6fc 100644 --- a/src/agents/pi-tools.types.ts +++ b/src/agents/pi-tools.types.ts @@ -1,4 +1,4 @@ -import type { AgentTool } from "@mariozechner/pi-agent-core"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; // oxlint-disable-next-line typescript/no-explicit-any export type AnyAgentTool = AgentTool; diff --git a/src/agents/session-tool-result-guard-wrapper.ts b/src/agents/session-tool-result-guard-wrapper.ts index 89668023..7ae8539b 100644 --- a/src/agents/session-tool-result-guard-wrapper.ts +++ b/src/agents/session-tool-result-guard-wrapper.ts @@ -1,4 +1,4 @@ -import type { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { SessionManager } from "@earendil-works/pi-coding-agent"; import { getGlobalHookRunner } from "../plugins/hook-runner-global.js"; import { applyInputProvenanceToUserMessage, @@ -30,7 +30,7 @@ export function guardSessionManager( const hookRunner = getGlobalHookRunner(); const beforeMessageWrite = hookRunner?.hasHooks("before_message_write") - ? (event: { message: import("@mariozechner/pi-agent-core").AgentMessage }) => { + ? (event: { message: import("@earendil-works/pi-agent-core").AgentMessage }) => { return hookRunner.runBeforeMessageWrite(event, { agentId: opts?.agentId, sessionKey: opts?.sessionKey, diff --git a/src/agents/session-tool-result-guard.e2e.test.ts b/src/agents/session-tool-result-guard.e2e.test.ts index 37cf5c96..ce2f69ce 100644 --- a/src/agents/session-tool-result-guard.e2e.test.ts +++ b/src/agents/session-tool-result-guard.e2e.test.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import { SessionManager } from "@earendil-works/pi-coding-agent"; import { describe, expect, it } from "vitest"; import { installSessionToolResultGuard } from "./session-tool-result-guard.js"; diff --git a/src/agents/session-tool-result-guard.tool-result-persist-hook.e2e.test.ts b/src/agents/session-tool-result-guard.tool-result-persist-hook.e2e.test.ts index 7c38e73b..b8f3e289 100644 --- a/src/agents/session-tool-result-guard.tool-result-persist-hook.e2e.test.ts +++ b/src/agents/session-tool-result-guard.tool-result-persist-hook.e2e.test.ts @@ -1,8 +1,8 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import { SessionManager } from "@earendil-works/pi-coding-agent"; import { describe, expect, it, afterEach } from "vitest"; import { initializeGlobalHookRunner, diff --git a/src/agents/session-tool-result-guard.ts b/src/agents/session-tool-result-guard.ts index 0f82cd2d..ba1d16ae 100644 --- a/src/agents/session-tool-result-guard.ts +++ b/src/agents/session-tool-result-guard.ts @@ -1,6 +1,6 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; -import type { TextContent } from "@mariozechner/pi-ai"; -import type { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { TextContent } from "@earendil-works/pi-ai"; +import type { SessionManager } from "@earendil-works/pi-coding-agent"; import type { PluginHookBeforeMessageWriteEvent, PluginHookBeforeMessageWriteResult, diff --git a/src/agents/session-transcript-repair.e2e.test.ts b/src/agents/session-transcript-repair.e2e.test.ts index de988edf..8f0e2715 100644 --- a/src/agents/session-transcript-repair.e2e.test.ts +++ b/src/agents/session-transcript-repair.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { sanitizeToolCallInputs, diff --git a/src/agents/session-transcript-repair.ts b/src/agents/session-transcript-repair.ts index 4741914e..f9e27e1f 100644 --- a/src/agents/session-transcript-repair.ts +++ b/src/agents/session-transcript-repair.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { extractToolCallsFromAssistant, extractToolResultId } from "./tool-call-id.js"; type ToolCallBlock = { diff --git a/src/agents/skills-status.e2e.test.ts b/src/agents/skills-status.e2e.test.ts index 38fa50e8..f4a9e907 100644 --- a/src/agents/skills-status.e2e.test.ts +++ b/src/agents/skills-status.e2e.test.ts @@ -15,7 +15,12 @@ describe("buildWorkspaceSkillStatus", () => { skill: { name: "os-scoped", description: "test", - source: "test", + sourceInfo: { + path: "/tmp/os-scoped", + source: "test", + scope: "project", + origin: "top-level", + }, filePath: "/tmp/os-scoped", baseDir: "/tmp", disableModelInvocation: false, diff --git a/src/agents/skills-status.ts b/src/agents/skills-status.ts index 96dabfa3..0c187630 100644 --- a/src/agents/skills-status.ts +++ b/src/agents/skills-status.ts @@ -189,7 +189,7 @@ function buildSkillStatus( const bundled = bundledNames && bundledNames.size > 0 ? bundledNames.has(entry.skill.name) - : entry.skill.source === "mayros-bundled"; + : entry.skill.sourceInfo.source === "mayros-bundled"; const requirementStatus = evaluateEntryMetadataRequirementsForCurrentPlatform({ always, @@ -207,7 +207,7 @@ function buildSkillStatus( return { name: entry.skill.name, description: entry.skill.description, - source: entry.skill.source, + source: entry.skill.sourceInfo.source, bundled, filePath: entry.skill.filePath, baseDir: entry.skill.baseDir, diff --git a/src/agents/skills.resolveskillspromptforrun.e2e.test.ts b/src/agents/skills.resolveskillspromptforrun.e2e.test.ts index a5c2acfe..3a546231 100644 --- a/src/agents/skills.resolveskillspromptforrun.e2e.test.ts +++ b/src/agents/skills.resolveskillspromptforrun.e2e.test.ts @@ -17,7 +17,12 @@ describe("resolveSkillsPromptForRun", () => { description: "Demo", filePath: "/app/skills/demo-skill/SKILL.md", baseDir: "/app/skills/demo-skill", - source: "mayros-bundled", + sourceInfo: { + path: "/app/skills/demo-skill/SKILL.md", + source: "mayros-bundled", + scope: "project", + origin: "top-level", + }, disableModelInvocation: false, }, frontmatter: {}, diff --git a/src/agents/skills/bundled-context.ts b/src/agents/skills/bundled-context.ts index 06576497..b5f3d4a3 100644 --- a/src/agents/skills/bundled-context.ts +++ b/src/agents/skills/bundled-context.ts @@ -1,4 +1,4 @@ -import { loadSkillsFromDir } from "@mariozechner/pi-coding-agent"; +import { loadSkillsFromDir } from "@earendil-works/pi-coding-agent"; import { createSubsystemLogger } from "../../logging/subsystem.js"; import { resolveBundledSkillsDir, type BundledSkillsResolveOptions } from "./bundled-dir.js"; diff --git a/src/agents/skills/config.ts b/src/agents/skills/config.ts index ebbad246..097506dc 100644 --- a/src/agents/skills/config.ts +++ b/src/agents/skills/config.ts @@ -49,7 +49,7 @@ function normalizeAllowlist(input: unknown): string[] | undefined { const BUNDLED_SOURCES = new Set(["mayros-bundled"]); function isBundledSkill(entry: SkillEntry): boolean { - return BUNDLED_SOURCES.has(entry.skill.source); + return BUNDLED_SOURCES.has(entry.skill.sourceInfo.source); } export function resolveBundledAllowlist(config?: MayrosConfig): string[] | undefined { diff --git a/src/agents/skills/frontmatter.ts b/src/agents/skills/frontmatter.ts index 7575fbb3..abf46fd9 100644 --- a/src/agents/skills/frontmatter.ts +++ b/src/agents/skills/frontmatter.ts @@ -1,4 +1,4 @@ -import type { Skill } from "@mariozechner/pi-coding-agent"; +import type { Skill } from "@earendil-works/pi-coding-agent"; import { parseFrontmatterBlock } from "../../markdown/frontmatter.js"; import { getFrontmatterString, diff --git a/src/agents/skills/types.ts b/src/agents/skills/types.ts index ca93f42e..d2a0ae62 100644 --- a/src/agents/skills/types.ts +++ b/src/agents/skills/types.ts @@ -1,4 +1,4 @@ -import type { Skill } from "@mariozechner/pi-coding-agent"; +import type { Skill } from "@earendil-works/pi-coding-agent"; export type SkillInstallSpec = { id?: string; diff --git a/src/agents/skills/workspace.ts b/src/agents/skills/workspace.ts index 02901c0c..b69ad4f2 100644 --- a/src/agents/skills/workspace.ts +++ b/src/agents/skills/workspace.ts @@ -5,7 +5,7 @@ import { formatSkillsForPrompt, loadSkillsFromDir, type Skill, -} from "@mariozechner/pi-coding-agent"; +} from "@earendil-works/pi-coding-agent"; import type { MayrosConfig } from "../../config/config.js"; import { createSubsystemLogger } from "../../logging/subsystem.js"; import { CONFIG_DIR, resolveUserPath } from "../../utils.js"; diff --git a/src/agents/system-prompt-report.ts b/src/agents/system-prompt-report.ts index 71d77f47..f1077d75 100644 --- a/src/agents/system-prompt-report.ts +++ b/src/agents/system-prompt-report.ts @@ -1,5 +1,5 @@ import path from "node:path"; -import type { AgentTool } from "@mariozechner/pi-agent-core"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; import type { SessionSystemPromptReport } from "../config/sessions/types.js"; import type { EmbeddedContextFile } from "./pi-embedded-helpers.js"; import type { WorkspaceBootstrapFile } from "./workspace.js"; diff --git a/src/agents/test-helpers/assistant-message-fixtures.ts b/src/agents/test-helpers/assistant-message-fixtures.ts index edf26770..ebac953b 100644 --- a/src/agents/test-helpers/assistant-message-fixtures.ts +++ b/src/agents/test-helpers/assistant-message-fixtures.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; const ZERO_USAGE: AssistantMessage["usage"] = { input: 0, diff --git a/src/agents/tool-call-id.e2e.test.ts b/src/agents/tool-call-id.e2e.test.ts index ce4e5dd6..69480307 100644 --- a/src/agents/tool-call-id.e2e.test.ts +++ b/src/agents/tool-call-id.e2e.test.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { describe, expect, it } from "vitest"; import { isValidCloudCodeAssistToolId, diff --git a/src/agents/tool-call-id.ts b/src/agents/tool-call-id.ts index e30236e6..6a39360c 100644 --- a/src/agents/tool-call-id.ts +++ b/src/agents/tool-call-id.ts @@ -1,5 +1,5 @@ import { createHash } from "node:crypto"; -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; export type ToolCallIdMode = "strict" | "strict9"; diff --git a/src/agents/tool-images.ts b/src/agents/tool-images.ts index 0059578e..f4a1f6b7 100644 --- a/src/agents/tool-images.ts +++ b/src/agents/tool-images.ts @@ -1,5 +1,5 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; -import type { ImageContent } from "@mariozechner/pi-ai"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; +import type { ImageContent } from "@earendil-works/pi-ai"; import { createSubsystemLogger } from "../logging/subsystem.js"; import { buildImageResizeSideGrid, diff --git a/src/agents/tool-summaries.ts b/src/agents/tool-summaries.ts index bca325e4..009e6868 100644 --- a/src/agents/tool-summaries.ts +++ b/src/agents/tool-summaries.ts @@ -1,4 +1,4 @@ -import type { AgentTool } from "@mariozechner/pi-agent-core"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; export function buildToolSummaryMap(tools: AgentTool[]): Record { const summaries: Record = {}; diff --git a/src/agents/tools/common.ts b/src/agents/tools/common.ts index 1aea6dd3..25556822 100644 --- a/src/agents/tools/common.ts +++ b/src/agents/tools/common.ts @@ -1,5 +1,5 @@ import fs from "node:fs/promises"; -import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core"; import { detectMime } from "../../media/mime.js"; import type { ImageSanitizationLimits } from "../image-sanitization.js"; import { sanitizeToolResultImages } from "../tool-images.js"; diff --git a/src/agents/tools/discord-actions-guild.ts b/src/agents/tools/discord-actions-guild.ts index 630c6e9a..fc026680 100644 --- a/src/agents/tools/discord-actions-guild.ts +++ b/src/agents/tools/discord-actions-guild.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import type { DiscordActionConfig } from "../../config/config.js"; import { getPresence } from "../../discord/monitor/presence-cache.js"; import { diff --git a/src/agents/tools/discord-actions-messaging.ts b/src/agents/tools/discord-actions-messaging.ts index 144992ac..f73a6be5 100644 --- a/src/agents/tools/discord-actions-messaging.ts +++ b/src/agents/tools/discord-actions-messaging.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import type { DiscordActionConfig } from "../../config/config.js"; import { readDiscordComponentSpec } from "../../discord/components.js"; import { diff --git a/src/agents/tools/discord-actions-moderation.ts b/src/agents/tools/discord-actions-moderation.ts index c2dd5ebc..ba981e43 100644 --- a/src/agents/tools/discord-actions-moderation.ts +++ b/src/agents/tools/discord-actions-moderation.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import type { DiscordActionConfig } from "../../config/config.js"; import { banMemberDiscord, diff --git a/src/agents/tools/discord-actions-presence.ts b/src/agents/tools/discord-actions-presence.ts index 90639aa6..5a0bc2f2 100644 --- a/src/agents/tools/discord-actions-presence.ts +++ b/src/agents/tools/discord-actions-presence.ts @@ -1,5 +1,5 @@ import type { Activity, UpdatePresenceData } from "@buape/carbon/gateway"; -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import type { DiscordActionConfig } from "../../config/config.js"; import { getGateway } from "../../discord/monitor/gateway-registry.js"; import { type ActionGate, jsonResult, readStringParam } from "./common.js"; diff --git a/src/agents/tools/discord-actions.ts b/src/agents/tools/discord-actions.ts index 3b33f91e..109b3767 100644 --- a/src/agents/tools/discord-actions.ts +++ b/src/agents/tools/discord-actions.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import type { MayrosConfig } from "../../config/config.js"; import { createDiscordActionGate } from "../../discord/accounts.js"; import { readStringParam } from "./common.js"; diff --git a/src/agents/tools/image-tool.helpers.ts b/src/agents/tools/image-tool.helpers.ts index 61943a4b..d294dbbc 100644 --- a/src/agents/tools/image-tool.helpers.ts +++ b/src/agents/tools/image-tool.helpers.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; import type { MayrosConfig } from "../../config/config.js"; import { extractAssistantText } from "../pi-embedded-utils.js"; diff --git a/src/agents/tools/image-tool.ts b/src/agents/tools/image-tool.ts index e6b520a7..693bf922 100644 --- a/src/agents/tools/image-tool.ts +++ b/src/agents/tools/image-tool.ts @@ -1,5 +1,6 @@ import path from "node:path"; -import { type Api, type Context, complete, type Model } from "@mariozechner/pi-ai"; +import type { Api, Context, Model } from "@earendil-works/pi-ai"; +import { complete } from "@earendil-works/pi-ai/compat"; import { Type } from "@sinclair/typebox"; import type { MayrosConfig } from "../../config/config.js"; import { resolveUserPath } from "../../utils.js"; diff --git a/src/agents/tools/memory-tool.ts b/src/agents/tools/memory-tool.ts index 2ba91da6..32ee0ac8 100644 --- a/src/agents/tools/memory-tool.ts +++ b/src/agents/tools/memory-tool.ts @@ -52,7 +52,8 @@ export function createMemorySearchTool(options: { description: "Mandatory recall step: semantically search MEMORY.md + memory/*.md (and optional session transcripts) before answering questions about prior work, decisions, dates, people, preferences, or todos; returns top snippets with path + lines. If response has disabled=true, memory retrieval is unavailable and should be surfaced to the user.", parameters: MemorySearchSchema, - execute: async (_toolCallId, params) => { + execute: async (_toolCallId, rawParams) => { + const params = rawParams as Record; const query = readStringParam(params, "query", { required: true }); const maxResults = readNumberParam(params, "maxResults"); const minScore = readNumberParam(params, "minScore"); @@ -113,7 +114,8 @@ export function createMemoryGetTool(options: { description: "Safe snippet read from MEMORY.md or memory/*.md with optional from/lines; use after memory_search to pull only the needed lines and keep context small.", parameters: MemoryGetSchema, - execute: async (_toolCallId, params) => { + execute: async (_toolCallId, rawParams) => { + const params = rawParams as Record; const relPath = readStringParam(params, "path", { required: true }); const from = readNumberParam(params, "from", { integer: true }); const lines = readNumberParam(params, "lines", { integer: true }); diff --git a/src/agents/tools/nodes-tool.ts b/src/agents/tools/nodes-tool.ts index d3d85872..6cf7d6e4 100644 --- a/src/agents/tools/nodes-tool.ts +++ b/src/agents/tools/nodes-tool.ts @@ -1,5 +1,5 @@ import crypto from "node:crypto"; -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import { Type } from "@sinclair/typebox"; import { type CameraFacing, diff --git a/src/agents/tools/slack-actions.ts b/src/agents/tools/slack-actions.ts index e3b08227..bcdb50cf 100644 --- a/src/agents/tools/slack-actions.ts +++ b/src/agents/tools/slack-actions.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import type { MayrosConfig } from "../../config/config.js"; import { resolveSlackAccount } from "../../slack/accounts.js"; import { diff --git a/src/agents/tools/telegram-actions.ts b/src/agents/tools/telegram-actions.ts index f2d5f941..057fd9e9 100644 --- a/src/agents/tools/telegram-actions.ts +++ b/src/agents/tools/telegram-actions.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import type { MayrosConfig } from "../../config/config.js"; import { createTelegramActionGate } from "../../telegram/accounts.js"; import type { TelegramButtonStyle, TelegramInlineButtons } from "../../telegram/button-types.js"; diff --git a/src/agents/tools/whatsapp-actions.ts b/src/agents/tools/whatsapp-actions.ts index 2957d419..cbaf0d8d 100644 --- a/src/agents/tools/whatsapp-actions.ts +++ b/src/agents/tools/whatsapp-actions.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import type { MayrosConfig } from "../../config/config.js"; import { sendReactionWhatsApp } from "../../web/outbound.js"; import { createActionGate, jsonResult, readReactionParams, readStringParam } from "./common.js"; diff --git a/src/agents/zai.live.test.ts b/src/agents/zai.live.test.ts index fbca5a07..428c821d 100644 --- a/src/agents/zai.live.test.ts +++ b/src/agents/zai.live.test.ts @@ -1,4 +1,4 @@ -import { completeSimple, getModel } from "@mariozechner/pi-ai"; +import { completeSimple, getModel } from "@earendil-works/pi-ai/compat"; import { describe, expect, it } from "vitest"; import { isTruthyEnvValue } from "../infra/env.js"; diff --git a/src/auto-reply/reply/commands-export-session.ts b/src/auto-reply/reply/commands-export-session.ts index b05d059d..ead4f437 100644 --- a/src/auto-reply/reply/commands-export-session.ts +++ b/src/auto-reply/reply/commands-export-session.ts @@ -1,8 +1,11 @@ import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; -import type { SessionEntry as PiSessionEntry, SessionHeader } from "@mariozechner/pi-coding-agent"; -import { SessionManager } from "@mariozechner/pi-coding-agent"; +import type { + SessionEntry as PiSessionEntry, + SessionHeader, +} from "@earendil-works/pi-coding-agent"; +import { SessionManager } from "@earendil-works/pi-coding-agent"; import { resolveDefaultSessionStorePath, resolveSessionFilePath, diff --git a/src/auto-reply/reply/commands-system-prompt.ts b/src/auto-reply/reply/commands-system-prompt.ts index a8c4fbe3..159bd4e8 100644 --- a/src/auto-reply/reply/commands-system-prompt.ts +++ b/src/auto-reply/reply/commands-system-prompt.ts @@ -1,4 +1,4 @@ -import type { AgentTool } from "@mariozechner/pi-agent-core"; +import type { AgentTool } from "@earendil-works/pi-agent-core"; import { resolveSessionAgentIds } from "../../agents/agent-scope.js"; import { resolveBootstrapContextForRun } from "../../agents/bootstrap-files.js"; import { resolveDefaultModelForAgent } from "../../agents/model-selection.js"; diff --git a/src/auto-reply/reply/session.ts b/src/auto-reply/reply/session.ts index 01c445f3..2e9def31 100644 --- a/src/auto-reply/reply/session.ts +++ b/src/auto-reply/reply/session.ts @@ -1,7 +1,7 @@ import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; -import { CURRENT_SESSION_VERSION, SessionManager } from "@mariozechner/pi-coding-agent"; +import { CURRENT_SESSION_VERSION, SessionManager } from "@earendil-works/pi-coding-agent"; import { resolveSessionAgentId } from "../../agents/agent-scope.js"; import { normalizeChatType } from "../../channels/chat-type.js"; import type { MayrosConfig } from "../../config/config.js"; diff --git a/src/auto-reply/types.ts b/src/auto-reply/types.ts index 839fac55..34f5ce64 100644 --- a/src/auto-reply/types.ts +++ b/src/auto-reply/types.ts @@ -1,4 +1,4 @@ -import type { ImageContent } from "@mariozechner/pi-ai"; +import type { ImageContent } from "@earendil-works/pi-ai"; import type { TypingController } from "./reply/typing.js"; export type BlockReplyContext = { diff --git a/src/channels/plugins/actions/discord/handle-action.guild-admin.ts b/src/channels/plugins/actions/discord/handle-action.guild-admin.ts index 18c3bfd0..eca79687 100644 --- a/src/channels/plugins/actions/discord/handle-action.guild-admin.ts +++ b/src/channels/plugins/actions/discord/handle-action.guild-admin.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import { parseAvailableTags, readNumberParam, diff --git a/src/channels/plugins/actions/discord/handle-action.ts b/src/channels/plugins/actions/discord/handle-action.ts index a2711dc0..4579ed6d 100644 --- a/src/channels/plugins/actions/discord/handle-action.ts +++ b/src/channels/plugins/actions/discord/handle-action.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import { readNumberParam, readStringArrayParam, diff --git a/src/channels/plugins/message-actions.ts b/src/channels/plugins/message-actions.ts index 86834661..3e360bcd 100644 --- a/src/channels/plugins/message-actions.ts +++ b/src/channels/plugins/message-actions.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import type { MayrosConfig } from "../../config/config.js"; import { getChannelPlugin, listChannelPlugins } from "./index.js"; import type { ChannelMessageActionContext, ChannelMessageActionName } from "./types.js"; diff --git a/src/channels/plugins/types.core.ts b/src/channels/plugins/types.core.ts index f1e163f2..f580de83 100644 --- a/src/channels/plugins/types.core.ts +++ b/src/channels/plugins/types.core.ts @@ -1,4 +1,4 @@ -import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core"; import type { TSchema } from "@sinclair/typebox"; import type { MsgContext } from "../../auto-reply/templating.js"; import type { MayrosConfig } from "../../config/config.js"; diff --git a/src/cli/skills-cli.e2e.test.ts b/src/cli/skills-cli.e2e.test.ts index 345587a0..2f700f45 100644 --- a/src/cli/skills-cli.e2e.test.ts +++ b/src/cli/skills-cli.e2e.test.ts @@ -36,7 +36,12 @@ describe("skills-cli (e2e)", () => { skill: { name: "peekaboo", description: "Capture UI screenshots", - source: "mayros-bundled", + sourceInfo: { + path: path.join(baseDir, "SKILL.md"), + source: "mayros-bundled", + scope: "project", + origin: "top-level", + }, filePath: path.join(baseDir, "SKILL.md"), baseDir, } as SkillEntry["skill"], diff --git a/src/cli/skills-cli.test.ts b/src/cli/skills-cli.test.ts index 5546ed9e..44e4e72c 100644 --- a/src/cli/skills-cli.test.ts +++ b/src/cli/skills-cli.test.ts @@ -4,7 +4,7 @@ import { createEmptyInstallChecks } from "./requirements-test-fixtures.js"; import { formatSkillInfo, formatSkillsCheck, formatSkillsList } from "./skills-cli.format.js"; // Unit tests: don't pay the runtime cost of loading/parsing the real skills loader. -vi.mock("@mariozechner/pi-coding-agent", () => ({ +vi.mock("@earendil-works/pi-coding-agent", () => ({ loadSkillsFromDir: () => ({ skills: [] }), formatSkillsForPrompt: () => "", })); diff --git a/src/commands/auth-choice.e2e.test.ts b/src/commands/auth-choice.e2e.test.ts index 5718187e..aa7fbba8 100644 --- a/src/commands/auth-choice.e2e.test.ts +++ b/src/commands/auth-choice.e2e.test.ts @@ -1,5 +1,5 @@ import fs from "node:fs/promises"; -import type { OAuthCredentials } from "@mariozechner/pi-ai"; +import type { OAuthCredentials } from "@earendil-works/pi-ai"; import { afterEach, describe, expect, it, vi } from "vitest"; import type { WizardPrompter } from "../wizard/prompts.js"; import { applyAuthChoice, resolvePreferredProviderForAuthChoice } from "./auth-choice.js"; diff --git a/src/commands/chutes-oauth.ts b/src/commands/chutes-oauth.ts index cc4d88b2..0e686c74 100644 --- a/src/commands/chutes-oauth.ts +++ b/src/commands/chutes-oauth.ts @@ -1,6 +1,6 @@ import { randomBytes } from "node:crypto"; import { createServer } from "node:http"; -import type { OAuthCredentials } from "@mariozechner/pi-ai"; +import type { OAuthCredentials } from "@earendil-works/pi-ai"; import type { ChutesOAuthAppConfig } from "../agents/chutes-oauth.js"; import { CHUTES_AUTHORIZE_ENDPOINT, diff --git a/src/commands/models/list.list-command.ts b/src/commands/models/list.list-command.ts index dc195985..2b30157f 100644 --- a/src/commands/models/list.list-command.ts +++ b/src/commands/models/list.list-command.ts @@ -1,4 +1,4 @@ -import type { Api, Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; import { resolveForwardCompatModel } from "../../agents/model-forward-compat.js"; import { parseModelRef } from "../../agents/model-selection.js"; import type { ModelRegistry } from "../../agents/pi-model-discovery.js"; diff --git a/src/commands/models/list.registry.ts b/src/commands/models/list.registry.ts index 27d9f29f..aad52655 100644 --- a/src/commands/models/list.registry.ts +++ b/src/commands/models/list.registry.ts @@ -1,4 +1,4 @@ -import type { Api, Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; import { resolveMayrosAgentDir } from "../../agents/agent-paths.js"; import type { AuthProfileStore } from "../../agents/auth-profiles.js"; import { listProfilesForProvider } from "../../agents/auth-profiles.js"; diff --git a/src/commands/onboard-auth.credentials.ts b/src/commands/onboard-auth.credentials.ts index e224ff8f..f00c4e59 100644 --- a/src/commands/onboard-auth.credentials.ts +++ b/src/commands/onboard-auth.credentials.ts @@ -1,6 +1,6 @@ import fs from "node:fs"; import path from "node:path"; -import type { OAuthCredentials } from "@mariozechner/pi-ai"; +import type { OAuthCredentials } from "@earendil-works/pi-ai"; import { resolveMayrosAgentDir } from "../agents/agent-paths.js"; import { upsertAuthProfile } from "../agents/auth-profiles.js"; import { resolveStateDir } from "../config/paths.js"; diff --git a/src/commands/onboard-auth.e2e.test.ts b/src/commands/onboard-auth.e2e.test.ts index 92a59142..0643866c 100644 --- a/src/commands/onboard-auth.e2e.test.ts +++ b/src/commands/onboard-auth.e2e.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import type { OAuthCredentials } from "@mariozechner/pi-ai"; +import type { OAuthCredentials } from "@earendil-works/pi-ai"; import { afterEach, describe, expect, it } from "vitest"; import type { MayrosConfig } from "../config/config.js"; import { diff --git a/src/commands/openai-codex-oauth.test.ts b/src/commands/openai-codex-oauth.test.ts index d68645d9..167e2b80 100644 --- a/src/commands/openai-codex-oauth.test.ts +++ b/src/commands/openai-codex-oauth.test.ts @@ -7,7 +7,7 @@ const mocks = vi.hoisted(() => ({ createVpsAwareOAuthHandlers: vi.fn(), })); -vi.mock("@mariozechner/pi-ai", () => ({ +vi.mock("@earendil-works/pi-ai", () => ({ loginOpenAICodex: mocks.loginOpenAICodex, })); diff --git a/src/commands/openai-codex-oauth.ts b/src/commands/openai-codex-oauth.ts index 7c7e4a68..e0a0f022 100644 --- a/src/commands/openai-codex-oauth.ts +++ b/src/commands/openai-codex-oauth.ts @@ -1,5 +1,5 @@ -import type { OAuthCredentials } from "@mariozechner/pi-ai"; -import { loginOpenAICodex } from "@mariozechner/pi-ai"; +import type { OAuthCredentials } from "@earendil-works/pi-ai"; +import { loginOpenAICodex } from "@earendil-works/pi-ai/oauth"; import type { RuntimeEnv } from "../runtime.js"; import type { WizardPrompter } from "../wizard/prompts.js"; import { createVpsAwareOAuthHandlers } from "./oauth-flow.js"; diff --git a/src/config/sessions/transcript.ts b/src/config/sessions/transcript.ts index 720fd69e..85cc21d1 100644 --- a/src/config/sessions/transcript.ts +++ b/src/config/sessions/transcript.ts @@ -1,6 +1,6 @@ import fs from "node:fs"; import path from "node:path"; -import { CURRENT_SESSION_VERSION, SessionManager } from "@mariozechner/pi-coding-agent"; +import { CURRENT_SESSION_VERSION, SessionManager } from "@earendil-works/pi-coding-agent"; import { emitSessionTranscriptUpdate } from "../../sessions/transcript-events.js"; import { resolveDefaultSessionStorePath } from "./paths.js"; import { resolveAndPersistSessionFile } from "./session-file.js"; diff --git a/src/config/sessions/types.ts b/src/config/sessions/types.ts index 10d1d3bc..1e2093ca 100644 --- a/src/config/sessions/types.ts +++ b/src/config/sessions/types.ts @@ -1,5 +1,5 @@ import crypto from "node:crypto"; -import type { Skill } from "@mariozechner/pi-coding-agent"; +import type { Skill } from "@earendil-works/pi-coding-agent"; import type { ChatType } from "../../channels/chat-type.js"; import type { ChannelId } from "../../channels/plugins/types.js"; import type { DeliveryContext } from "../../utils/delivery-context.js"; diff --git a/src/gateway/gateway-models.profiles.live.test.ts b/src/gateway/gateway-models.profiles.live.test.ts index 214a63ba..d23af5d9 100644 --- a/src/gateway/gateway-models.profiles.live.test.ts +++ b/src/gateway/gateway-models.profiles.live.test.ts @@ -3,7 +3,7 @@ import fs from "node:fs/promises"; import { createServer } from "node:net"; import os from "node:os"; import path from "node:path"; -import type { Api, Model } from "@mariozechner/pi-ai"; +import type { Api, Model } from "@earendil-works/pi-ai"; import { describe, it } from "vitest"; import { resolveMayrosAgentDir } from "../agents/agent-paths.js"; import { resolveAgentWorkspaceDir } from "../agents/agent-scope.js"; diff --git a/src/gateway/server-methods/chat.abort-persistence.test.ts b/src/gateway/server-methods/chat.abort-persistence.test.ts index 5453fdbd..a81aa1c4 100644 --- a/src/gateway/server-methods/chat.abort-persistence.test.ts +++ b/src/gateway/server-methods/chat.abort-persistence.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { CURRENT_SESSION_VERSION } from "@mariozechner/pi-coding-agent"; +import { CURRENT_SESSION_VERSION } from "@earendil-works/pi-coding-agent"; import { afterEach, describe, expect, it, vi } from "vitest"; type TranscriptLine = { diff --git a/src/gateway/server-methods/chat.inject.parentid.e2e.test.ts b/src/gateway/server-methods/chat.inject.parentid.e2e.test.ts index 60fbec4c..9c21afb3 100644 --- a/src/gateway/server-methods/chat.inject.parentid.e2e.test.ts +++ b/src/gateway/server-methods/chat.inject.parentid.e2e.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; -import { CURRENT_SESSION_VERSION } from "@mariozechner/pi-coding-agent"; +import { CURRENT_SESSION_VERSION } from "@earendil-works/pi-coding-agent"; import { describe, expect, it, vi } from "vitest"; import type { GatewayRequestContext } from "./types.js"; diff --git a/src/gateway/server-methods/chat.ts b/src/gateway/server-methods/chat.ts index cb040350..22ead1ff 100644 --- a/src/gateway/server-methods/chat.ts +++ b/src/gateway/server-methods/chat.ts @@ -1,6 +1,6 @@ import fs from "node:fs"; import path from "node:path"; -import { CURRENT_SESSION_VERSION, SessionManager } from "@mariozechner/pi-coding-agent"; +import { CURRENT_SESSION_VERSION, SessionManager } from "@earendil-works/pi-coding-agent"; import { resolveSessionAgentId } from "../../agents/agent-scope.js"; import { resolveThinkingDefault } from "../../agents/model-selection.js"; import { resolveAgentTimeoutMs } from "../../agents/timeout.js"; diff --git a/src/gateway/test-helpers.mocks.ts b/src/gateway/test-helpers.mocks.ts index 3f1501bd..61d16411 100644 --- a/src/gateway/test-helpers.mocks.ts +++ b/src/gateway/test-helpers.mocks.ts @@ -243,20 +243,25 @@ vi.mock("../agents/pi-model-discovery.js", async () => { "../agents/pi-model-discovery.js", ); - class MockModelRegistry extends actual.ModelRegistry { - override getAll(): ReturnType { + // ModelRegistry now has a private constructor and cannot be subclassed. + // Patch the instance returned by discoverModels to intercept getAll(). + const mockedDiscoverModels = ((authStorage, agentDir) => { + const registry = actual.discoverModels(authStorage, agentDir); + const originalGetAll = registry.getAll.bind(registry); + registry.getAll = () => { if (!piSdkMock.enabled) { - return super.getAll(); + return originalGetAll(); } piSdkMock.discoverCalls += 1; // Cast to expected type for testing purposes - return piSdkMock.models as ReturnType; - } - } + return piSdkMock.models as ReturnType; + }; + return registry; + }) as typeof actual.discoverModels; return { ...actual, - ModelRegistry: MockModelRegistry, + discoverModels: mockedDiscoverModels, }; }); diff --git a/src/infra/outbound/message-action-runner.ts b/src/infra/outbound/message-action-runner.ts index 6fe0ea87..3ef9001c 100644 --- a/src/infra/outbound/message-action-runner.ts +++ b/src/infra/outbound/message-action-runner.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import { resolveSessionAgentId } from "../../agents/agent-scope.js"; import { readNumberParam, diff --git a/src/infra/outbound/outbound-send-service.ts b/src/infra/outbound/outbound-send-service.ts index 1ece9de6..94689734 100644 --- a/src/infra/outbound/outbound-send-service.ts +++ b/src/infra/outbound/outbound-send-service.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import { dispatchChannelMessageAction } from "../../channels/plugins/message-actions.js"; import type { ChannelId, ChannelThreadingToolContext } from "../../channels/plugins/types.js"; import type { MayrosConfig } from "../../config/config.js"; diff --git a/src/infra/outbound/tool-payload.ts b/src/infra/outbound/tool-payload.ts index 33a8d1fd..23712a65 100644 --- a/src/infra/outbound/tool-payload.ts +++ b/src/infra/outbound/tool-payload.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; export function extractToolPayload(result: AgentToolResult): unknown { if (result.details !== undefined) { diff --git a/src/media-understanding/providers/image.ts b/src/media-understanding/providers/image.ts index 9665a0ef..60ec8326 100644 --- a/src/media-understanding/providers/image.ts +++ b/src/media-understanding/providers/image.ts @@ -1,5 +1,5 @@ -import type { Api, Context, Model } from "@mariozechner/pi-ai"; -import { complete } from "@mariozechner/pi-ai"; +import type { Api, Context, Model } from "@earendil-works/pi-ai"; +import { complete } from "@earendil-works/pi-ai/compat"; import { minimaxUnderstandImage } from "../../agents/minimax-vlm.js"; import { getApiKeyForModel, requireApiKey } from "../../agents/model-auth.js"; import { ensureMayrosModelsJson } from "../../agents/models-config.js"; diff --git a/src/plugin-sdk/slack-message-actions.ts b/src/plugin-sdk/slack-message-actions.ts index 77b24b95..d1522e6c 100644 --- a/src/plugin-sdk/slack-message-actions.ts +++ b/src/plugin-sdk/slack-message-actions.ts @@ -1,4 +1,4 @@ -import type { AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import { readNumberParam, readStringParam } from "../agents/tools/common.js"; import type { ChannelMessageActionContext } from "../channels/plugins/types.js"; import { parseSlackBlocksInput } from "../slack/blocks-input.js"; diff --git a/src/plugins/types.ts b/src/plugins/types.ts index de30f31d..56d0e6b9 100644 --- a/src/plugins/types.ts +++ b/src/plugins/types.ts @@ -1,5 +1,5 @@ import type { IncomingMessage, ServerResponse } from "node:http"; -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; import type { Command } from "commander"; import type { AuthProfileCredential, OAuthCredential } from "../agents/auth-profiles/types.js"; import type { AnyAgentTool } from "../agents/tools/common.js"; diff --git a/src/providers/google-shared.ensures-function-call-comes-after-user-turn.test.ts b/src/providers/google-shared.ensures-function-call-comes-after-user-turn.test.ts index 9f209f3b..a6603e91 100644 --- a/src/providers/google-shared.ensures-function-call-comes-after-user-turn.test.ts +++ b/src/providers/google-shared.ensures-function-call-comes-after-user-turn.test.ts @@ -1,5 +1,5 @@ -import { convertMessages } from "@mariozechner/pi-ai/dist/providers/google-shared.js"; -import type { Context } from "@mariozechner/pi-ai/dist/types.js"; +import { convertMessages } from "@earendil-works/pi-ai/api/google-shared"; +import type { Context, Model } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { asRecord, @@ -70,7 +70,7 @@ describe("google-shared convertTools", () => { ], } as unknown as Context; - const contents = convertMessages(model, context); + const contents = convertMessages(model as unknown as Model<"google-generative-ai">, context); const parts = contents.flatMap((content) => content.parts ?? []); const toolCallPart = parts.find( (part) => typeof part === "object" && part !== null && "functionCall" in part, diff --git a/src/providers/google-shared.preserves-parameters-type-is-missing.test.ts b/src/providers/google-shared.preserves-parameters-type-is-missing.test.ts index 3dc27a4c..6b5c4265 100644 --- a/src/providers/google-shared.preserves-parameters-type-is-missing.test.ts +++ b/src/providers/google-shared.preserves-parameters-type-is-missing.test.ts @@ -1,5 +1,5 @@ -import { convertMessages, convertTools } from "@mariozechner/pi-ai/dist/providers/google-shared.js"; -import type { Context, Tool } from "@mariozechner/pi-ai/dist/types.js"; +import { convertMessages, convertTools } from "@earendil-works/pi-ai/api/google-shared"; +import type { Context, Tool } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { asRecord, diff --git a/src/providers/google-shared.test-helpers.ts b/src/providers/google-shared.test-helpers.ts index c98fad72..a4985426 100644 --- a/src/providers/google-shared.test-helpers.ts +++ b/src/providers/google-shared.test-helpers.ts @@ -1,4 +1,4 @@ -import type { Model } from "@mariozechner/pi-ai/dist/types.js"; +import type { Model } from "@earendil-works/pi-ai"; import { expect } from "vitest"; export const asRecord = (value: unknown): Record => { diff --git a/src/providers/qwen-portal-oauth.ts b/src/providers/qwen-portal-oauth.ts index 276b2e34..f5f1e982 100644 --- a/src/providers/qwen-portal-oauth.ts +++ b/src/providers/qwen-portal-oauth.ts @@ -1,4 +1,4 @@ -import type { OAuthCredentials } from "@mariozechner/pi-ai"; +import type { OAuthCredentials } from "@earendil-works/pi-ai"; import { formatCliCommand } from "../cli/command-format.js"; const QWEN_OAUTH_BASE_URL = "https://chat.qwen.ai"; diff --git a/src/security/audit-extra.async.ts b/src/security/audit-extra.async.ts index 8b26fd2a..f87a7072 100644 --- a/src/security/audit-extra.async.ts +++ b/src/security/audit-extra.async.ts @@ -1076,7 +1076,7 @@ export async function collectInstalledSkillsCodeSafetyFindings(params: { for (const workspaceDir of workspaceDirs) { const entries = loadWorkspaceSkillEntries(workspaceDir, { config: params.cfg }); for (const entry of entries) { - if (entry.skill.source === "mayros-bundled") { + if (entry.skill.sourceInfo.source === "mayros-bundled") { continue; } diff --git a/src/sessions/input-provenance.ts b/src/sessions/input-provenance.ts index 4540e680..6ba32fc4 100644 --- a/src/sessions/input-provenance.ts +++ b/src/sessions/input-provenance.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import type { AgentMessage } from "@earendil-works/pi-agent-core"; export const INPUT_PROVENANCE_KIND_VALUES = [ "external_user", diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index 92572565..0fd4121a 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -1,5 +1,6 @@ import { rmSync } from "node:fs"; -import { completeSimple, type TextContent } from "@mariozechner/pi-ai"; +import type { TextContent } from "@earendil-works/pi-ai"; +import { completeSimple } from "@earendil-works/pi-ai/compat"; import { EdgeTTS } from "node-edge-tts"; import { getApiKeyForModel, requireApiKey } from "../agents/model-auth.js"; import { diff --git a/src/tts/tts.test.ts b/src/tts/tts.test.ts index 38a2e762..546f12bc 100644 --- a/src/tts/tts.test.ts +++ b/src/tts/tts.test.ts @@ -1,4 +1,5 @@ -import { completeSimple, type AssistantMessage } from "@mariozechner/pi-ai"; +import type { AssistantMessage } from "@earendil-works/pi-ai"; +import { completeSimple } from "@earendil-works/pi-ai/compat"; import { describe, expect, it, vi, beforeEach } from "vitest"; import { getApiKeyForModel } from "../agents/model-auth.js"; import { resolveModel } from "../agents/pi-embedded-runner/model.js"; @@ -6,8 +7,11 @@ import type { MayrosConfig } from "../config/config.js"; import { withEnv } from "../test-utils/env.js"; import * as tts from "./tts.js"; -vi.mock("@mariozechner/pi-ai", () => ({ +vi.mock("@earendil-works/pi-ai/compat", () => ({ completeSimple: vi.fn(), +})); + +vi.mock("@earendil-works/pi-ai/oauth", () => ({ // Some auth helpers import oauth provider metadata at module load time. getOAuthProviders: () => [], getOAuthApiKey: vi.fn(async () => null), diff --git a/src/tui/commands.ts b/src/tui/commands.ts index a6244d52..4ee2c107 100644 --- a/src/tui/commands.ts +++ b/src/tui/commands.ts @@ -1,4 +1,4 @@ -import type { SlashCommand } from "@mariozechner/pi-tui"; +import type { SlashCommand } from "@earendil-works/pi-tui"; import { listChatCommands, listChatCommandsForConfig } from "../auto-reply/commands-registry.js"; import { formatThinkingLevels, listThinkingLevelLabels } from "../auto-reply/thinking.js"; import { discoverMarkdownCommands } from "../commands/markdown-commands.js"; diff --git a/src/tui/components/assistant-message.ts b/src/tui/components/assistant-message.ts index 6afdc6ac..2d9c3c84 100644 --- a/src/tui/components/assistant-message.ts +++ b/src/tui/components/assistant-message.ts @@ -1,4 +1,4 @@ -import { Container, Markdown, Spacer } from "@mariozechner/pi-tui"; +import { Container, Markdown, Spacer } from "@earendil-works/pi-tui"; import { markdownTheme, theme } from "../theme/theme.js"; export class AssistantMessageComponent extends Container { diff --git a/src/tui/components/chat-log.ts b/src/tui/components/chat-log.ts index 79ca5adb..41d142e1 100644 --- a/src/tui/components/chat-log.ts +++ b/src/tui/components/chat-log.ts @@ -1,5 +1,5 @@ -import type { Component } from "@mariozechner/pi-tui"; -import { Container, Spacer, Text } from "@mariozechner/pi-tui"; +import type { Component } from "@earendil-works/pi-tui"; +import { Container, Spacer, Text } from "@earendil-works/pi-tui"; import { theme } from "../theme/theme.js"; import { AssistantMessageComponent } from "./assistant-message.js"; import { ToolExecutionComponent } from "./tool-execution.js"; diff --git a/src/tui/components/custom-editor.ts b/src/tui/components/custom-editor.ts index ce2f5ffd..6cf0ecbc 100644 --- a/src/tui/components/custom-editor.ts +++ b/src/tui/components/custom-editor.ts @@ -1,4 +1,4 @@ -import { Editor, Key, matchesKey } from "@mariozechner/pi-tui"; +import { Editor, Key, matchesKey } from "@earendil-works/pi-tui"; import type { ClipboardImage } from "../clipboard-image.js"; import type { TuiKeybindingResolver } from "../keybinding-resolver.js"; import type { VimHandler } from "../vim-handler.js"; diff --git a/src/tui/components/filterable-select-list.ts b/src/tui/components/filterable-select-list.ts index 7a283487..49730607 100644 --- a/src/tui/components/filterable-select-list.ts +++ b/src/tui/components/filterable-select-list.ts @@ -1,12 +1,12 @@ -import type { Component } from "@mariozechner/pi-tui"; +import type { Component } from "@earendil-works/pi-tui"; import { Input, matchesKey, type SelectItem, SelectList, type SelectListTheme, - getEditorKeybindings, -} from "@mariozechner/pi-tui"; + getKeybindings, +} from "@earendil-works/pi-tui"; import chalk from "chalk"; import { fuzzyFilterLower, prepareSearchItems } from "./fuzzy-filter.js"; @@ -110,8 +110,8 @@ export class FilterableSelectList implements Component { } // Escape: clear filter or cancel - const kb = getEditorKeybindings(); - if (kb.matches(keyData, "selectCancel")) { + const kb = getKeybindings(); + if (kb.matches(keyData, "tui.select.cancel")) { if (this.filterText) { this.filterText = ""; this.input.setValue(""); diff --git a/src/tui/components/searchable-select-list.ts b/src/tui/components/searchable-select-list.ts index 8a27858e..5e55b157 100644 --- a/src/tui/components/searchable-select-list.ts +++ b/src/tui/components/searchable-select-list.ts @@ -1,13 +1,13 @@ import { type Component, - getEditorKeybindings, + getKeybindings, Input, isKeyRelease, matchesKey, type SelectItem, type SelectListTheme, truncateToWidth, -} from "@mariozechner/pi-tui"; +} from "@earendil-works/pi-tui"; import { stripAnsi, visibleWidth } from "../../terminal/ansi.js"; import { findWordBoundaryIndex, fuzzyFilterLower } from "./fuzzy-filter.js"; @@ -362,8 +362,8 @@ export class SearchableSelectList implements Component { return; } - const kb = getEditorKeybindings(); - if (kb.matches(keyData, "selectCancel")) { + const kb = getKeybindings(); + if (kb.matches(keyData, "tui.select.cancel")) { if (this.onCancel) { this.onCancel(); } diff --git a/src/tui/components/selectors.ts b/src/tui/components/selectors.ts index 46073fbc..aae9c4d1 100644 --- a/src/tui/components/selectors.ts +++ b/src/tui/components/selectors.ts @@ -1,4 +1,9 @@ -import { type SelectItem, SelectList, type SettingItem, SettingsList } from "@mariozechner/pi-tui"; +import { + type SelectItem, + SelectList, + type SettingItem, + SettingsList, +} from "@earendil-works/pi-tui"; import { filterableSelectListTheme, searchableSelectListTheme, diff --git a/src/tui/components/tool-execution.ts b/src/tui/components/tool-execution.ts index 4e98d2bc..931af40f 100644 --- a/src/tui/components/tool-execution.ts +++ b/src/tui/components/tool-execution.ts @@ -1,4 +1,4 @@ -import { Box, Container, Markdown, Spacer, Text } from "@mariozechner/pi-tui"; +import { Box, Container, Markdown, Spacer, Text } from "@earendil-works/pi-tui"; import { formatToolDetail, resolveToolDisplay } from "../../agents/tool-display.js"; import { renderDiff, parseDiffStats, formatDiffStatsLine } from "../diff-renderer.js"; import { linkifyFilePaths } from "../linkify-paths.js"; diff --git a/src/tui/components/user-message.ts b/src/tui/components/user-message.ts index fad77f42..8b879a92 100644 --- a/src/tui/components/user-message.ts +++ b/src/tui/components/user-message.ts @@ -1,4 +1,4 @@ -import { Container, Markdown, Spacer } from "@mariozechner/pi-tui"; +import { Container, Markdown, Spacer } from "@earendil-works/pi-tui"; import { markdownTheme, theme } from "../theme/theme.js"; export class UserMessageComponent extends Container { diff --git a/src/tui/components/welcome-screen.ts b/src/tui/components/welcome-screen.ts index 84bf4511..fe692b50 100644 --- a/src/tui/components/welcome-screen.ts +++ b/src/tui/components/welcome-screen.ts @@ -1,5 +1,5 @@ -import type { Component } from "@mariozechner/pi-tui"; -import { truncateToWidth } from "@mariozechner/pi-tui"; +import type { Component } from "@earendil-works/pi-tui"; +import { truncateToWidth } from "@earendil-works/pi-tui"; import chalk from "chalk"; import { visibleWidth } from "../../terminal/ansi.js"; import type { TuiStateAccess } from "../tui-types.js"; diff --git a/src/tui/enriched-autocomplete.test.ts b/src/tui/enriched-autocomplete.test.ts index 2ba76ac8..585ec789 100644 --- a/src/tui/enriched-autocomplete.test.ts +++ b/src/tui/enriched-autocomplete.test.ts @@ -1,7 +1,9 @@ import { describe, expect, it, vi } from "vitest"; -import type { AutocompleteItem, AutocompleteProvider } from "@mariozechner/pi-tui"; +import type { AutocompleteItem, AutocompleteProvider } from "@earendil-works/pi-tui"; import { EnrichedAutocompleteProvider, createEnrichedProvider } from "./enriched-autocomplete.js"; +const options = { signal: new AbortController().signal }; + function createMockBase( suggestions: { items: AutocompleteItem[]; prefix: string } | null = { items: [{ value: "file.ts", label: "file.ts" }], @@ -9,7 +11,7 @@ function createMockBase( }, ): AutocompleteProvider { return { - getSuggestions: vi.fn(() => suggestions), + getSuggestions: vi.fn(async () => suggestions), applyCompletion: vi.fn((_lines, cursorLine, cursorCol, _item, _prefix) => ({ lines: [], cursorLine, @@ -19,26 +21,26 @@ function createMockBase( } describe("EnrichedAutocompleteProvider", () => { - it("delegates to base when no queryFn provided", () => { + it("delegates to base when no queryFn provided", async () => { const base = createMockBase(); const provider = new EnrichedAutocompleteProvider(base); - const result = provider.getSuggestions(["@fi"], 0, 3); + const result = await provider.getSuggestions(["@fi"], 0, 3, options); expect(result).toEqual({ items: [{ value: "file.ts", label: "file.ts" }], prefix: "@" }); }); - it("delegates to base when base returns null", () => { + it("delegates to base when base returns null", async () => { const base = createMockBase(null); const queryFn = vi.fn(async () => []); const provider = new EnrichedAutocompleteProvider(base, queryFn); - const result = provider.getSuggestions(["@fi"], 0, 3); + const result = await provider.getSuggestions(["@fi"], 0, 3, options); expect(result).toBeNull(); }); - it("fires async query on @ prefix", () => { + it("fires async query on @ prefix", async () => { const base = createMockBase(); const queryFn = vi.fn(async () => [{ value: "sym:Foo", label: "Foo", description: "class" }]); const provider = new EnrichedAutocompleteProvider(base, queryFn); - provider.getSuggestions(["@fi"], 0, 3); + await provider.getSuggestions(["@fi"], 0, 3, options); expect(queryFn).toHaveBeenCalledWith("fi"); }); @@ -49,14 +51,14 @@ describe("EnrichedAutocompleteProvider", () => { const provider = new EnrichedAutocompleteProvider(base, queryFn); // First call triggers async fetch - provider.getSuggestions(["@fi"], 0, 3); + await provider.getSuggestions(["@fi"], 0, 3, options); // Wait for the query to resolve await vi.waitFor(() => expect(queryFn).toHaveBeenCalled()); // Small delay to allow cache to be set await new Promise((r) => setTimeout(r, 10)); // Second call should use cache - const result = provider.getSuggestions(["@fi"], 0, 3); + const result = await provider.getSuggestions(["@fi"], 0, 3, options); expect(result?.items).toHaveLength(2); expect(result?.items[1]?.value).toBe("sym:Foo"); }); @@ -72,21 +74,21 @@ describe("EnrichedAutocompleteProvider", () => { ]); const provider = new EnrichedAutocompleteProvider(base, queryFn); - provider.getSuggestions(["@fi"], 0, 3); + await provider.getSuggestions(["@fi"], 0, 3, options); await new Promise((r) => setTimeout(r, 10)); - const result = provider.getSuggestions(["@fi"], 0, 3); + const result = await provider.getSuggestions(["@fi"], 0, 3, options); expect(result?.items).toHaveLength(2); const values = result?.items.map((i) => i.value); expect(values).toContain("file.ts"); expect(values).toContain("other.ts"); }); - it("does not fire query when no @ prefix", () => { + it("does not fire query when no @ prefix", async () => { const base = createMockBase({ items: [], prefix: "/" }); const queryFn = vi.fn(async () => []); const provider = new EnrichedAutocompleteProvider(base, queryFn); - provider.getSuggestions(["hello"], 0, 5); + await provider.getSuggestions(["hello"], 0, 5, options); expect(queryFn).not.toHaveBeenCalled(); }); @@ -96,7 +98,7 @@ describe("EnrichedAutocompleteProvider", () => { throw new Error("network error"); }); const provider = new EnrichedAutocompleteProvider(base, queryFn); - const result = provider.getSuggestions(["@fi"], 0, 3); + const result = await provider.getSuggestions(["@fi"], 0, 3, options); expect(result).not.toBeNull(); // Wait for the rejected promise to settle await new Promise((r) => setTimeout(r, 10)); @@ -112,18 +114,18 @@ describe("EnrichedAutocompleteProvider", () => { const provider = new EnrichedAutocompleteProvider(base, queryFn, { maxCache: 2 }); // Fill cache with 2 entries - provider.getSuggestions(["@a"], 0, 2); + await provider.getSuggestions(["@a"], 0, 2, options); await new Promise((r) => setTimeout(r, 10)); - provider.getSuggestions(["@b"], 0, 2); + await provider.getSuggestions(["@b"], 0, 2, options); await new Promise((r) => setTimeout(r, 10)); // This should evict "a" - provider.getSuggestions(["@c"], 0, 2); + await provider.getSuggestions(["@c"], 0, 2, options); await new Promise((r) => setTimeout(r, 10)); // "a" should re-trigger query queryFn.mockClear(); - provider.getSuggestions(["@a"], 0, 2); + await provider.getSuggestions(["@a"], 0, 2, options); expect(queryFn).toHaveBeenCalledWith("a"); }); diff --git a/src/tui/enriched-autocomplete.ts b/src/tui/enriched-autocomplete.ts index 076f15a2..511ae21a 100644 --- a/src/tui/enriched-autocomplete.ts +++ b/src/tui/enriched-autocomplete.ts @@ -1,4 +1,8 @@ -import type { AutocompleteItem, AutocompleteProvider } from "@mariozechner/pi-tui"; +import type { + AutocompleteItem, + AutocompleteProvider, + AutocompleteSuggestions, +} from "@earendil-works/pi-tui"; type CachedEntry = { items: AutocompleteItem[]; @@ -27,12 +31,13 @@ export class EnrichedAutocompleteProvider implements AutocompleteProvider { this.ttlMs = opts?.ttlMs ?? 30_000; } - getSuggestions( + async getSuggestions( lines: string[], cursorLine: number, cursorCol: number, - ): { items: AutocompleteItem[]; prefix: string } | null { - const baseSuggestions = this.base.getSuggestions(lines, cursorLine, cursorCol); + options: { signal: AbortSignal; force?: boolean }, + ): Promise { + const baseSuggestions = await this.base.getSuggestions(lines, cursorLine, cursorCol, options); if (!this.queryFn || !baseSuggestions) { return baseSuggestions; } diff --git a/src/tui/keybinding-resolver.test.ts b/src/tui/keybinding-resolver.test.ts index 5fc874a1..db5b4c5b 100644 --- a/src/tui/keybinding-resolver.test.ts +++ b/src/tui/keybinding-resolver.test.ts @@ -6,16 +6,17 @@ const piTuiMocks = vi.hoisted(() => { config?: Record, ) { this._config = config; - }) as unknown as typeof import("@mariozechner/pi-tui").EditorKeybindingsManager & + }) as unknown as typeof import("@earendil-works/pi-tui").KeybindingsManager & ReturnType; return { matchesKey: vi.fn((_data: string, _key: string) => false), - setEditorKeybindings: vi.fn(), - EditorKeybindingsManager: MockManager, + setKeybindings: vi.fn(), + KeybindingsManager: MockManager, + TUI_KEYBINDINGS: {} as Record, }; }); -vi.mock("@mariozechner/pi-tui", () => ({ +vi.mock("@earendil-works/pi-tui", () => ({ ...piTuiMocks, Key: { ctrl: (k: string) => `ctrl+${k}`, shift: (k: string) => `shift+${k}` }, })); @@ -73,18 +74,22 @@ describe("DEFAULT_TUI_KEYBINDINGS", () => { }); describe("applyKeybindingsFromConfig", () => { - it("creates and sets an EditorKeybindingsManager", () => { - piTuiMocks.setEditorKeybindings.mockClear(); - piTuiMocks.EditorKeybindingsManager.mockClear(); + it("creates and sets an KeybindingsManager", () => { + piTuiMocks.setKeybindings.mockClear(); + piTuiMocks.KeybindingsManager.mockClear(); applyKeybindingsFromConfig({ cursorUp: "ctrl+k" }); - expect(piTuiMocks.EditorKeybindingsManager).toHaveBeenCalledWith({ cursorUp: "ctrl+k" }); - expect(piTuiMocks.setEditorKeybindings).toHaveBeenCalled(); + expect(piTuiMocks.KeybindingsManager).toHaveBeenCalledWith(piTuiMocks.TUI_KEYBINDINGS, { + cursorUp: "ctrl+k", + }); + expect(piTuiMocks.setKeybindings).toHaveBeenCalled(); }); it("filters out TUI-specific actions from editor config", () => { - piTuiMocks.EditorKeybindingsManager.mockClear(); + piTuiMocks.KeybindingsManager.mockClear(); applyKeybindingsFromConfig({ selectAgent: "ctrl+a", cursorDown: "ctrl+j" }); - expect(piTuiMocks.EditorKeybindingsManager).toHaveBeenCalledWith({ cursorDown: "ctrl+j" }); + expect(piTuiMocks.KeybindingsManager).toHaveBeenCalledWith(piTuiMocks.TUI_KEYBINDINGS, { + cursorDown: "ctrl+j", + }); }); }); diff --git a/src/tui/keybinding-resolver.ts b/src/tui/keybinding-resolver.ts index 192984dc..669c27ce 100644 --- a/src/tui/keybinding-resolver.ts +++ b/src/tui/keybinding-resolver.ts @@ -1,10 +1,11 @@ import { - type EditorKeybindingsConfig, - EditorKeybindingsManager, + type KeybindingsConfig, + KeybindingsManager, type KeyId, matchesKey, - setEditorKeybindings, -} from "@mariozechner/pi-tui"; + setKeybindings, + TUI_KEYBINDINGS, +} from "@earendil-works/pi-tui"; export type TuiAction = | "selectAgent" @@ -58,8 +59,8 @@ export class TuiKeybindingResolver { export function applyKeybindingsFromConfig( config?: Record, -): EditorKeybindingsManager { - const editorConfig: EditorKeybindingsConfig = {}; +): KeybindingsManager { + const editorConfig: KeybindingsConfig = {}; if (config) { for (const [action, keys] of Object.entries(config)) { if (action in DEFAULT_TUI_KEYBINDINGS) { @@ -70,8 +71,8 @@ export function applyKeybindingsFromConfig( : (keys as KeyId); } } - const manager = new EditorKeybindingsManager(editorConfig); - setEditorKeybindings(manager); + const manager = new KeybindingsManager(TUI_KEYBINDINGS, editorConfig); + setKeybindings(manager); return manager; } diff --git a/src/tui/theme/theme-factory.ts b/src/tui/theme/theme-factory.ts index 444580fe..edb80ab5 100644 --- a/src/tui/theme/theme-factory.ts +++ b/src/tui/theme/theme-factory.ts @@ -3,7 +3,7 @@ import type { MarkdownTheme, SelectListTheme, SettingsListTheme, -} from "@mariozechner/pi-tui"; +} from "@earendil-works/pi-tui"; import chalk from "chalk"; import { highlight, supportsLanguage } from "cli-highlight"; import { formatTerminalLink } from "../../utils.js"; diff --git a/src/tui/tui-command-handlers.ts b/src/tui/tui-command-handlers.ts index 2b504668..3e23a5ca 100644 --- a/src/tui/tui-command-handlers.ts +++ b/src/tui/tui-command-handlers.ts @@ -1,5 +1,5 @@ import { randomUUID } from "node:crypto"; -import type { Component, TUI } from "@mariozechner/pi-tui"; +import type { Component, TUI } from "@earendil-works/pi-tui"; import { listThinkingLevelLabels, normalizeUsageDisplay, diff --git a/src/tui/tui-local-shell.ts b/src/tui/tui-local-shell.ts index 94c850ca..9a2be368 100644 --- a/src/tui/tui-local-shell.ts +++ b/src/tui/tui-local-shell.ts @@ -1,5 +1,5 @@ import { spawn } from "node:child_process"; -import type { Component, SelectItem } from "@mariozechner/pi-tui"; +import type { Component, SelectItem } from "@earendil-works/pi-tui"; import { createSearchableSelectList } from "./components/selectors.js"; type LocalShellDeps = { diff --git a/src/tui/tui-overlays.test.ts b/src/tui/tui-overlays.test.ts index 070eb0a8..b2bcbd9d 100644 --- a/src/tui/tui-overlays.test.ts +++ b/src/tui/tui-overlays.test.ts @@ -1,4 +1,4 @@ -import type { Component } from "@mariozechner/pi-tui"; +import type { Component } from "@earendil-works/pi-tui"; import { describe, expect, it, vi } from "vitest"; import { createOverlayHandlers } from "./tui-overlays.js"; diff --git a/src/tui/tui-overlays.ts b/src/tui/tui-overlays.ts index 51ba45a9..fc9fa428 100644 --- a/src/tui/tui-overlays.ts +++ b/src/tui/tui-overlays.ts @@ -1,4 +1,4 @@ -import type { Component, TUI } from "@mariozechner/pi-tui"; +import type { Component, TUI } from "@earendil-works/pi-tui"; type OverlayHost = Pick; diff --git a/src/tui/tui-session-actions.test.ts b/src/tui/tui-session-actions.test.ts index f5ed5325..b28cf92a 100644 --- a/src/tui/tui-session-actions.test.ts +++ b/src/tui/tui-session-actions.test.ts @@ -53,7 +53,7 @@ describe("tui session actions", () => { const { refreshSessionInfo } = createSessionActions({ client: { listSessions } as unknown as GatewayChatClient, chatLog: { addSystem: vi.fn() } as unknown as import("./components/chat-log.js").ChatLog, - tui: { requestRender } as unknown as import("@mariozechner/pi-tui").TUI, + tui: { requestRender } as unknown as import("@earendil-works/pi-tui").TUI, opts: {}, state, agentNames: new Map(), diff --git a/src/tui/tui-session-actions.ts b/src/tui/tui-session-actions.ts index 528fbbe3..80d46c9b 100644 --- a/src/tui/tui-session-actions.ts +++ b/src/tui/tui-session-actions.ts @@ -1,4 +1,4 @@ -import type { Component, TUI } from "@mariozechner/pi-tui"; +import type { Component, TUI } from "@earendil-works/pi-tui"; import type { SessionsPatchResult } from "../gateway/protocol/index.js"; import { normalizeAgentId, diff --git a/src/tui/tui.ts b/src/tui/tui.ts index 36e7b4e3..b6618769 100644 --- a/src/tui/tui.ts +++ b/src/tui/tui.ts @@ -7,7 +7,7 @@ import { ProcessTerminal, Text, TUI, -} from "@mariozechner/pi-tui"; +} from "@earendil-works/pi-tui"; import { resolveDefaultAgentId } from "../agents/agent-scope.js"; import { VERSION } from "../version.js"; import { loadConfig } from "../config/config.js"; From fdf6b51491b438bf0b4ead2c27732bdeafa2b87f Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Mon, 13 Jul 2026 19:49:00 +0200 Subject: [PATCH 09/14] deps: bump agent stack to 0.80.6 and refresh runtime dependencies (#68) Move the four core libraries to the latest patch on the 0.80 line (@earendil-works/pi-agent-core, pi-ai, pi-coding-agent, pi-tui: 0.80.2 -> 0.80.6). The 0.80.6 release internally consumes zod 4.4.3, so align the workspace to zod ^4.4.3 and add a pnpm override pinning zod to 4.4.3 to keep a single resolved version across the tree. Refresh 21 runtime and dev dependencies to their current minor/patch releases: @aws-sdk/client-bedrock, @clack/prompts, @grammyjs/types, @homebridge/ciao, @noble/curves, @slack/bolt, @slack/web-api, @vitest/coverage-v8, ajv, dotenv, grammy, jiti, lit, markdown-it, oxlint, semver, tslog, tsx, vitest, ws. Exact-pinned and security-overridden dependencies (hono, tar, undici, yaml, typebox, playwright-core, etc.) are left untouched by design. Skip the symlink-based config test on Windows where unprivileged symlink creation is not permitted. --- extensions/feishu/package.json | 6 +- package.json | 53 +- pnpm-lock.yaml | 2218 +++++++++++++++----------------- src/config/includes.test.ts | 6 +- 4 files changed, 1098 insertions(+), 1185 deletions(-) diff --git a/extensions/feishu/package.json b/extensions/feishu/package.json index 970f57c8..05b33b24 100644 --- a/extensions/feishu/package.json +++ b/extensions/feishu/package.json @@ -10,7 +10,7 @@ "dependencies": { "@larksuiteoapi/node-sdk": "^1.59.0", "@sinclair/typebox": "0.34.48", - "zod": "^4.3.6" + "zod": "^4.4.3" }, "peerDependencies": { "@apilium/mayros": ">=0.1.0" @@ -22,10 +22,10 @@ "channel": { "id": "feishu", "label": "Feishu", - "selectionLabel": "Feishu/Lark (飞书)", + "selectionLabel": "Feishu/Lark (\u98de\u4e66)", "docsPath": "/channels/feishu", "docsLabel": "feishu", - "blurb": "飞书/Lark enterprise messaging with doc/wiki/drive tools.", + "blurb": "\u98de\u4e66/Lark enterprise messaging with doc/wiki/drive tools.", "aliases": [ "lark" ], diff --git a/package.json b/package.json index d4584c93..7d7519b3 100644 --- a/package.json +++ b/package.json @@ -160,45 +160,45 @@ }, "dependencies": { "@agentclientprotocol/sdk": "0.14.1", - "@aws-sdk/client-bedrock": "^3.1019.0", + "@aws-sdk/client-bedrock": "^3.1085.0", "@buape/carbon": "0.0.0-beta-20260216184201", - "@clack/prompts": "^1.0.1", + "@clack/prompts": "^1.7.0", "@discordjs/voice": "^0.19.0", - "@earendil-works/pi-agent-core": "^0.80.2", - "@earendil-works/pi-ai": "^0.80.2", - "@earendil-works/pi-coding-agent": "^0.80.2", - "@earendil-works/pi-tui": "^0.80.2", + "@earendil-works/pi-agent-core": "^0.80.6", + "@earendil-works/pi-ai": "^0.80.6", + "@earendil-works/pi-coding-agent": "^0.80.6", + "@earendil-works/pi-tui": "^0.80.6", "@grammyjs/runner": "^2.0.3", "@grammyjs/transformer-throttler": "^1.2.1", - "@homebridge/ciao": "^1.3.5", + "@homebridge/ciao": "^1.3.10", "@line/bot-sdk": "^10.6.0", "@lydell/node-pty": "1.2.0-beta.3", "@mozilla/readability": "^0.6.0", - "@noble/curves": "^2.0.1", + "@noble/curves": "^2.2.0", "@sinclair/typebox": "0.34.48", - "@slack/bolt": "^4.6.0", - "@slack/web-api": "^7.14.1", + "@slack/bolt": "^4.7.3", + "@slack/web-api": "^7.19.0", "@whiskeysockets/baileys": "7.0.0-rc.9", - "ajv": "^8.18.0", + "ajv": "^8.20.0", "chalk": "^5.6.2", "chokidar": "^5.0.0", "cli-highlight": "^2.1.11", "commander": "^14.0.3", "croner": "^10.0.1", "discord-api-types": "^0.38.40", - "dotenv": "^17.3.1", + "dotenv": "^17.4.2", "express": "^5.2.1", "fast-glob": "^3.3.3", "file-type": "^21.3.2", - "grammy": "^1.40.0", + "grammy": "^1.44.0", "hono": "4.12.7", "https-proxy-agent": "^7.0.6", - "jiti": "^2.6.1", + "jiti": "^2.7.0", "json5": "^2.2.3", "jszip": "^3.10.1", "linkedom": "^0.18.12", "long": "^5.3.2", - "markdown-it": "^14.1.1", + "markdown-it": "^14.3.0", "node-edge-tts": "^1.2.10", "opusscript": "^0.0.8", "osc-progress": "^0.3.0", @@ -206,18 +206,18 @@ "playwright-core": "1.58.2", "qrcode-terminal": "^0.12.0", "quickjs-emscripten": "^0.31.0", - "semver": "^7.7.4", + "semver": "^7.8.5", "sharp": "^0.34.5", "sqlite-vec": "0.1.7-alpha.2", "tar": "7.5.11", - "tslog": "^4.10.2", + "tslog": "^4.11.0", "undici": "^7.24.2", - "ws": "^8.19.0", + "ws": "^8.21.0", "yaml": "^2.8.3", - "zod": "^4.3.6" + "zod": "^4.4.3" }, "devDependencies": { - "@grammyjs/types": "^3.24.0", + "@grammyjs/types": "^3.28.0", "@lit-labs/signals": "^0.2.0", "@lit/context": "^1.1.6", "@types/express": "^5.0.6", @@ -227,16 +227,16 @@ "@types/semver": "^7.7.1", "@types/ws": "^8.18.1", "@typescript/native-preview": "7.0.0-dev.20260221.1", - "@vitest/coverage-v8": "^4.0.18", - "lit": "^3.3.2", + "@vitest/coverage-v8": "^4.1.10", + "lit": "^3.3.3", "oxfmt": "0.34.0", - "oxlint": "^1.49.0", + "oxlint": "^1.73.0", "oxlint-tsgolint": "^0.14.2", "signal-utils": "0.21.1", "tsdown": "^0.20.3", - "tsx": "^4.21.0", + "tsx": "^4.23.1", "typescript": "^5.9.3", - "vitest": "^4.0.18" + "vitest": "^4.1.10" }, "peerDependencies": { "@napi-rs/canvas": "^0.1.89", @@ -268,7 +268,8 @@ "path-to-regexp": ">=8.4.0", "brace-expansion": ">=5.0.5", "music-metadata": ">=11.12.3", - "yaml": ">=2.8.3" + "yaml": ">=2.8.3", + "zod": "4.4.3" }, "onlyBuiltDependencies": [ "@lydell/node-pty", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d458b3d5..38f7aa66 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,6 +25,7 @@ overrides: brace-expansion: '>=5.0.5' music-metadata: '>=11.12.3' yaml: '>=2.8.3' + zod: 4.4.3 importers: @@ -32,40 +33,40 @@ importers: dependencies: '@agentclientprotocol/sdk': specifier: 0.14.1 - version: 0.14.1(zod@4.3.6) + version: 0.14.1(zod@4.4.3) '@aws-sdk/client-bedrock': - specifier: ^3.1019.0 - version: 3.1019.0 + specifier: ^3.1085.0 + version: 3.1085.0 '@buape/carbon': specifier: 0.0.0-beta-20260216184201 version: 0.0.0-beta-20260216184201(hono@4.12.7)(opusscript@0.0.8) '@clack/prompts': - specifier: ^1.0.1 - version: 1.0.1 + specifier: ^1.7.0 + version: 1.7.0 '@discordjs/voice': specifier: ^0.19.0 version: 0.19.0(opusscript@0.0.8) '@earendil-works/pi-agent-core': - specifier: ^0.80.2 - version: 0.80.2(ws@8.19.0)(zod@4.3.6) + specifier: ^0.80.6 + version: 0.80.6(ws@8.21.0)(zod@4.4.3) '@earendil-works/pi-ai': - specifier: ^0.80.2 - version: 0.80.2(ws@8.19.0)(zod@4.3.6) + specifier: ^0.80.6 + version: 0.80.6(ws@8.21.0)(zod@4.4.3) '@earendil-works/pi-coding-agent': - specifier: ^0.80.2 - version: 0.80.2(ws@8.19.0)(zod@4.3.6) + specifier: ^0.80.6 + version: 0.80.6(ws@8.21.0)(zod@4.4.3) '@earendil-works/pi-tui': - specifier: ^0.80.2 - version: 0.80.2 + specifier: ^0.80.6 + version: 0.80.6 '@grammyjs/runner': specifier: ^2.0.3 - version: 2.0.3(grammy@1.40.0) + version: 2.0.3(grammy@1.44.0) '@grammyjs/transformer-throttler': specifier: ^1.2.1 - version: 1.2.1(grammy@1.40.0) + version: 1.2.1(grammy@1.44.0) '@homebridge/ciao': - specifier: ^1.3.5 - version: 1.3.5 + specifier: ^1.3.10 + version: 1.3.10 '@line/bot-sdk': specifier: ^10.6.0 version: 10.6.0 @@ -79,23 +80,23 @@ importers: specifier: ^0.1.89 version: 0.1.95 '@noble/curves': - specifier: ^2.0.1 - version: 2.0.1 + specifier: ^2.2.0 + version: 2.2.0 '@sinclair/typebox': specifier: 0.34.48 version: 0.34.48 '@slack/bolt': - specifier: ^4.6.0 - version: 4.6.0(@types/express@5.0.6) + specifier: ^4.7.3 + version: 4.7.3(@types/express@5.0.6) '@slack/web-api': - specifier: ^7.14.1 - version: 7.14.1 + specifier: ^7.19.0 + version: 7.19.0 '@whiskeysockets/baileys': specifier: 7.0.0-rc.9 version: 7.0.0-rc.9(sharp@0.34.5) ajv: - specifier: ^8.18.0 - version: 8.18.0 + specifier: ^8.20.0 + version: 8.20.0 chalk: specifier: ^5.6.2 version: 5.6.2 @@ -115,8 +116,8 @@ importers: specifier: ^0.38.40 version: 0.38.40 dotenv: - specifier: ^17.3.1 - version: 17.3.1 + specifier: ^17.4.2 + version: 17.4.2 express: specifier: ^5.2.1 version: 5.2.1 @@ -127,8 +128,8 @@ importers: specifier: '>=21.3.1' version: 21.3.2 grammy: - specifier: ^1.40.0 - version: 1.40.0 + specifier: ^1.44.0 + version: 1.44.0 hono: specifier: 4.12.7 version: 4.12.7 @@ -136,8 +137,8 @@ importers: specifier: ^7.0.6 version: 7.0.6 jiti: - specifier: ^2.6.1 - version: 2.6.1 + specifier: ^2.7.0 + version: 2.7.0 json5: specifier: ^2.2.3 version: 2.2.3 @@ -151,8 +152,8 @@ importers: specifier: ^5.3.2 version: 5.3.2 markdown-it: - specifier: ^14.1.1 - version: 14.1.1 + specifier: ^14.3.0 + version: 14.3.0 node-edge-tts: specifier: ^1.2.10 version: 1.2.10 @@ -178,8 +179,8 @@ importers: specifier: ^0.31.0 version: 0.31.0 semver: - specifier: ^7.7.4 - version: 7.7.4 + specifier: ^7.8.5 + version: 7.8.5 sharp: specifier: ^0.34.5 version: 0.34.5 @@ -190,24 +191,24 @@ importers: specifier: 7.5.11 version: 7.5.11 tslog: - specifier: ^4.10.2 - version: 4.10.2 + specifier: ^4.11.0 + version: 4.11.0 undici: specifier: '>=7.24.0' version: 7.24.2 ws: - specifier: ^8.19.0 - version: 8.19.0 + specifier: ^8.21.0 + version: 8.21.0 yaml: specifier: '>=2.8.3' version: 2.8.3 zod: - specifier: ^4.3.6 - version: 4.3.6 + specifier: 4.4.3 + version: 4.4.3 devDependencies: '@grammyjs/types': - specifier: ^3.24.0 - version: 3.24.0 + specifier: ^3.28.0 + version: 3.28.0 '@lit-labs/signals': specifier: ^0.2.0 version: 0.2.0 @@ -236,17 +237,17 @@ importers: specifier: 7.0.0-dev.20260221.1 version: 7.0.0-dev.20260221.1 '@vitest/coverage-v8': - specifier: ^4.0.18 - version: 4.0.18(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18))(vitest@4.0.18) + specifier: ^4.1.10 + version: 4.1.10(vitest@4.1.10) lit: - specifier: ^3.3.2 - version: 3.3.2 + specifier: ^3.3.3 + version: 3.3.3 oxfmt: specifier: 0.34.0 version: 0.34.0 oxlint: - specifier: ^1.49.0 - version: 1.50.0(oxlint-tsgolint@0.14.2) + specifier: ^1.73.0 + version: 1.73.0(oxlint-tsgolint@0.14.2) oxlint-tsgolint: specifier: ^0.14.2 version: 0.14.2 @@ -257,14 +258,14 @@ importers: specifier: ^0.20.3 version: 0.20.3(@typescript/native-preview@7.0.0-dev.20260221.1)(typescript@5.9.3) tsx: - specifier: ^4.21.0 - version: 4.21.0 + specifier: ^4.23.1 + version: 4.23.1 typescript: specifier: ^5.9.3 version: 5.9.3 vitest: - specifier: ^4.0.18 - version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + specifier: ^4.1.10 + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/coverage-v8@4.1.10)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3)) extensions/agent-mesh: dependencies: @@ -406,8 +407,8 @@ importers: specifier: 0.34.48 version: 0.34.48 zod: - specifier: ^4.3.6 - version: 4.3.6 + specifier: 4.4.3 + version: 4.4.3 extensions/google-antigravity-auth: devDependencies: @@ -473,8 +474,8 @@ importers: specifier: workspace:* version: link:../.. zod: - specifier: ^4.3.6 - version: 4.3.6 + specifier: 4.4.3 + version: 4.4.3 extensions/kakeru-bridge: dependencies: @@ -541,8 +542,8 @@ importers: specifier: '>=11.12.3' version: 11.12.3 zod: - specifier: ^4.3.6 - version: 4.3.6 + specifier: 4.4.3 + version: 4.4.3 extensions/mattermost: devDependencies: @@ -586,7 +587,7 @@ importers: version: 0.34.48 openai: specifier: ^6.22.0 - version: 6.25.0(ws@8.19.0)(zod@4.3.6) + version: 6.25.0(ws@8.21.0)(zod@4.4.3) devDependencies: '@apilium/mayros': specifier: workspace:* @@ -626,8 +627,8 @@ importers: specifier: workspace:* version: link:../.. zod: - specifier: ^4.3.6 - version: 4.3.6 + specifier: 4.4.3 + version: 4.4.3 extensions/nostr: dependencies: @@ -638,8 +639,8 @@ importers: specifier: ^2.23.1 version: 2.23.1(typescript@5.9.3) zod: - specifier: ^4.3.6 - version: 4.3.6 + specifier: 4.4.3 + version: 4.4.3 extensions/open-prose: devDependencies: @@ -750,8 +751,8 @@ importers: specifier: ^8.0.3 version: 8.0.3(@twurple/auth@8.0.3) zod: - specifier: ^4.3.6 - version: 4.3.6 + specifier: 4.4.3 + version: 4.4.3 devDependencies: '@apilium/mayros': specifier: workspace:* @@ -769,8 +770,8 @@ importers: specifier: ^8.19.0 version: 8.19.0 zod: - specifier: ^4.3.6 - version: 4.3.6 + specifier: 4.4.3 + version: 4.4.3 extensions/whatsapp: devDependencies: @@ -820,7 +821,7 @@ importers: version: 0.25.12 vitest: specifier: ^3.0.0 - version: 3.2.4(@types/node@25.3.0)(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18))(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + version: 3.2.4(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) ui: dependencies: @@ -850,30 +851,30 @@ importers: version: 0.21.1(signal-polyfill@0.2.2) vite: specifier: 7.3.1 - version: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + version: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) devDependencies: '@vitest/browser-playwright': specifier: 4.0.18 - version: 4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) + version: 4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3))(vitest@4.0.18) playwright: specifier: ^1.58.2 version: 1.58.2 vitest: specifier: 4.0.18 - version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) packages: '@agentclientprotocol/sdk@0.14.1': resolution: {integrity: sha512-b6r3PS3Nly+Wyw9U+0nOr47bV8tfS476EgyEMhoKvJCZLbgqoDFN7DJwkxL88RR0aiOqOYV1ZnESHqb+RmdH8w==} peerDependencies: - zod: ^3.25.0 || ^4.0.0 + zod: 4.4.3 '@anthropic-ai/sdk@0.91.1': resolution: {integrity: sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==} hasBin: true peerDependencies: - zod: ^3.25.0 || ^4.0.0 + zod: 4.4.3 peerDependenciesMeta: zod: optional: true @@ -899,82 +900,82 @@ packages: resolution: {integrity: sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-bedrock@3.1019.0': - resolution: {integrity: sha512-GWe/mqO8CQBmco6M0f9n7DZsItmxTarwvo1zxuVLiqFb8ondXDU+Ry/TNn6FXWHm6YRLm8DUPwaSmcckdGyZNQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/core@3.973.25': - resolution: {integrity: sha512-TNrx7eq6nKNOO62HWPqoBqPLXEkW6nLZQGwjL6lq1jZtigWYbK1NbCnT7mKDzbLMHZfuOECUt3n6CzxjUW9HWQ==} + '@aws-sdk/client-bedrock@3.1085.0': + resolution: {integrity: sha512-unzpjV2M++lBK6QN35vj2t6sQQsUm52i3SmdsZX/kz1kN5qlKaCZIwv3rJmKi8gLMRec9PowBvrRkzw3n72Fsg==} engines: {node: '>=20.0.0'} '@aws-sdk/core@3.974.23': resolution: {integrity: sha512-MiWR/uWjxjFXGzrE0Ghc5lWxUxzHsUWFhV+OX7M4cR9SrmrnZs6TXavnCWnzzdwJeFri34xQo81rvGNzK3c4BQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-env@3.972.23': - resolution: {integrity: sha512-EamaclJcCEaPHp6wiVknNMM2RlsPMjAHSsYSFLNENBM8Wz92QPc6cOn3dif6vPDQt0Oo4IEghDy3NMDCzY/IvA==} + '@aws-sdk/core@3.975.1': + resolution: {integrity: sha512-8qh/6EYb7hl/ZwVfQufhbMEZs1gQIc7GbdrIf4eprQJ7cv042+74nE6l3YDfyWNzb9iPXb8fRyYSHkNIk5eE6Q==} engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-env@3.972.49': resolution: {integrity: sha512-liB3yQNHCM9k/gu/w36XHMKPluT7HTlnGUhRbBGSISDQkcr/Sy1zsZabiuvQj8WG5yW573u9RehrBvvnIQ9OEQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.25': - resolution: {integrity: sha512-qPymamdPcLp6ugoVocG1y5r69ScNiRzb0hogX25/ij+Wz7c7WnsgjLTaz7+eB5BfRxeyUwuw5hgULMuwOGOpcw==} + '@aws-sdk/credential-provider-env@3.972.57': + resolution: {integrity: sha512-1RfJaF7SW1TOnvNGU7kaYjwUf5H3sfm+synGH1bHhRlqcnxCt3szebH3dmKEyY4tuGcbQ6ffzUT89cRitBV8OQ==} engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-http@3.972.51': resolution: {integrity: sha512-XET0H2oofciJ5lMRWNIvRjAP7Q3wv2XT+JtJJEdhPWUMwe3TvQ9qcxonpu7vXmNngncvFpi4E2It+Tamas/naA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-ini@3.972.26': - resolution: {integrity: sha512-xKxEAMuP6GYx2y5GET+d3aGEroax3AgGfwBE65EQAUe090lzyJ/RzxPX9s8v7Z6qAk0XwfQl+LrmH05X7YvTeg==} + '@aws-sdk/credential-provider-http@3.972.59': + resolution: {integrity: sha512-sRCkpTiFnCdQvuaRVjQ6SVoHu6i7RUpurVo1c4F81HWhPvUJ7Wdp5MNtSdX1O29CNXc8em3O5m52hCjVtAD9SA==} engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-ini@3.972.56': resolution: {integrity: sha512-IAmc61hbgQiHht9U3x0tnRwz0lzdwOwD/i9voRgdJrKamF+JtmrBOsW9GwB7mfFonNWOWL4qARWYrF8veEMe3w==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.26': - resolution: {integrity: sha512-EFcM8RM3TUxnZOfMJo++3PnyxFu1fL/huzmn3Vh+8IWRgqZawUD3cRwwOr+/4bE9DpyHaLOWFAjY0lfK5X9ZkQ==} + '@aws-sdk/credential-provider-ini@3.973.1': + resolution: {integrity: sha512-6d8H6ZAh3ZPKZ6fe1nG2OWeZEZPtt9ravoD1dezPdPtsSkJRoxGAnFSHwKT3E/Te6fHE30zRzjV6TD12rvF6yQ==} engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-login@3.972.55': resolution: {integrity: sha512-hBBkANo3cDn+h2qxxzER4a+J8JCO9o9Z/YYmU7iky6AcaarX5RRdRcHNC6SLdwY0vAXQygn6soUbDqPn3GghaA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.27': - resolution: {integrity: sha512-jXpxSolfFnPVj6GCTtx3xIdWNoDR7hYC/0SbetGZxOC9UnNmipHeX1k6spVstf7eWJrMhXNQEgXC0pD1r5tXIg==} + '@aws-sdk/credential-provider-login@3.972.63': + resolution: {integrity: sha512-GREWRrMj0XnNKMaVa/Mauoaui26qBEHu71WWqXbwZOu/jFQOnPZjTf7u0KtGKC8VGa6VUs9kDWGgocrKNLS9vw==} engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-node@3.972.58': resolution: {integrity: sha512-OyCLVmSI7pZO8hxwNVX6pXhTVlJqRBTp+ijdEfJSUj0RyjHnF602OfAarOzGq6wkGodeFkYBt8MmJ6A6ycRgWw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.23': - resolution: {integrity: sha512-IL/TFW59++b7MpHserjUblGrdP5UXy5Ekqqx1XQkERXBFJcZr74I7VaSrQT5dxdRMU16xGK4L0RQ5fQG1pMgnA==} + '@aws-sdk/credential-provider-node@3.972.66': + resolution: {integrity: sha512-f+qjRXZpz7sgzbc4QB+6nLKfyKFgRRXzWdXbsKPv/VhVRyHsDyq4yBWC/B75BAJpFIcUeI2XR/3gdWJ677zB4A==} engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-process@3.972.49': resolution: {integrity: sha512-C8h36lBuC/RnBSsjlO+dn6xZm3KbAl5vpJaVPAfQnMmz2/OISmKOc8XZcqMQgO2ADwBYNRMM6Kf3vz9G/TulMQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.972.26': - resolution: {integrity: sha512-c6ghvRb6gTlMznWhGxn/bpVCcp0HRaz4DobGVD9kI4vwHq186nU2xN/S7QGkm0lo0H2jQU8+dgpUFLxfTcwCOg==} + '@aws-sdk/credential-provider-process@3.972.57': + resolution: {integrity: sha512-TiVQhuU0pbhIZAUZacbPHMyzrIdiH+lnx+PMY/Pu/b93dJrq3wdZwzUJ0TPpvNxaqbHsxJvQZW3/h/beLiKq7Q==} engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-sso@3.972.55': resolution: {integrity: sha512-1FkOz74Ea5QGS9jtIoXp55T/IkSS3spv+nLTT07fRY/+T5xmEOqaYBVIaEmX4zTNvbV6g2lrtlaVKWEoNyJt3w==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.26': - resolution: {integrity: sha512-cXcS3+XD3iwhoXkM44AmxjmbcKueoLCINr1e+IceMmCySda5ysNIfiGBGe9qn5EMiQ9Jd7pP0AGFtcd6OV3Lvg==} + '@aws-sdk/credential-provider-sso@3.973.1': + resolution: {integrity: sha512-3foTZUJ4821Ij60X7K3NJroygiZLnbBmarN+T//O2cjkISan90zElN3NBmgSlDrTQ7Gs6z/yO8V7h60QNcDZHQ==} engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-web-identity@3.972.55': resolution: {integrity: sha512-g2BoECD1q01kTPByi56+VLVvdWDzMkKIcr77qixpqH0okw2t0U5CoPv+6S8v/D1Y2Wa6QKKtn6XAtDzP+Kfpvg==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-web-identity@3.972.63': + resolution: {integrity: sha512-8qZLFhM69eKcS37m459ctPR05Qimycm/74OPVioe6wNZabMT54GYhwBju0+J656RkMasNSawWQu+c8CmBe3TUQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/eventstream-handler-node@3.972.22': resolution: {integrity: sha512-tqPJv0dz4+O0hWGm1a6YekcMZyPhDFs/zH73Von7icaVT5n0Jqvm86typ3jRrG+qoUdPhALOnboRLTmnWQTlYQ==} engines: {node: '>=20.0.0'} @@ -983,44 +984,24 @@ packages: resolution: {integrity: sha512-OHpk8YoZi3yexPq8aFt1vN1IxA2zLKvsIR5GpWYylX/ve6kQmY7wxHNSFy/D3t2apMZ16rs76Co4dJWcDyIk3A==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-host-header@3.972.8': - resolution: {integrity: sha512-wAr2REfKsqoKQ+OkNqvOShnBoh+nkPurDKW7uAeVSu6kUECnWlSJiPvnoqxGlfousEY/v9LfS9sNc46hjSYDIQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-logger@3.972.8': - resolution: {integrity: sha512-CWl5UCM57WUFaFi5kB7IBY1UmOeLvNZAZ2/OZ5l20ldiJ3TiIz1pC65gYj8X0BCPWkeR1E32mpsCk1L1I4n+lA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-recursion-detection@3.972.9': - resolution: {integrity: sha512-/Wt5+CT8dpTFQxEJ9iGy/UGrXr7p2wlIOEHvIr/YcHYByzoLjrqkYqXdJjd9UIgWjv7eqV2HnFJen93UTuwfTQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-user-agent@3.972.26': - resolution: {integrity: sha512-AilFIh4rI/2hKyyGN6XrB0yN96W2o7e7wyrPWCM6QjZM1mcC/pVkW3IWWRvuBWMpVP8Fg+rMpbzeLQ6dTM4gig==} - engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-websocket@3.972.31': resolution: {integrity: sha512-ps1rumU1LybSFHaW9dTDgkhCMJLVaedEY78kKSzUDDY+b9974/g6aiaYYA0U9WV0oL4CJCJrVWG+EZ/qr4or7g==} engines: {node: '>= 14.0.0'} - '@aws-sdk/nested-clients@3.996.16': - resolution: {integrity: sha512-L7Qzoj/qQU1cL5GnYLQP5LbI+wlLCLoINvcykR3htKcQ4tzrPf2DOs72x933BM7oArYj1SKrkb2lGlsJHIic3g==} - engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.997.23': resolution: {integrity: sha512-gO93ZPsI2bxeFZD42f1/qjDw6FAZkNZcKRO94LIiT03fzOmcJ9e/tunxjVjA1Rl69ClmVJzz8H3G9CdKef10PA==} engines: {node: '>=20.0.0'} - '@aws-sdk/region-config-resolver@3.972.10': - resolution: {integrity: sha512-1dq9ToC6e070QvnVhhbAs3bb5r6cQ10gTVc6cyRV5uvQe7P138TV2uG2i6+Yok4bAkVAcx5AqkTEBUvWEtBlsQ==} + '@aws-sdk/nested-clients@3.997.31': + resolution: {integrity: sha512-BDHTpwcsZHEBNEJzOg/B1BkFYJxAXY50dau/NyVWs3d51F0WgIUGSWZot/Os+N3KpDhXeaXnz37mWffAvduREw==} engines: {node: '>=20.0.0'} '@aws-sdk/signature-v4-multi-region@3.996.35': resolution: {integrity: sha512-6L/VWs+Wch2stHemCGTmUNqKLMzURxQDK5boNG3Jn3kAOp71meDUuS5sbObpEvFxHDq0uWeSLFDNSYsjNt+Dlg==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.1019.0': - resolution: {integrity: sha512-OF+2RfRmUKyjzrRWlDcyju3RBsuqcrYDQ8TwrJg8efcOotMzuZN4U9mpVTIdATpmEc4lWNZBMSjPzrGm6JPnAQ==} + '@aws-sdk/signature-v4-multi-region@3.996.39': + resolution: {integrity: sha512-8+srXqYIF8KYMLC4FxMLEM5Ek7kUNibJu1R4m8/fUhhNYIZZz26oGtKkCr8I/HiG2fFQxBvaGgQZT4/mqRCSnA==} engines: {node: '>=20.0.0'} '@aws-sdk/token-providers@3.1048.0': @@ -1031,46 +1012,42 @@ packages: resolution: {integrity: sha512-pv80IzgGW4RnXWtft692chZOM9i6PhebVsLCcnaM4dBEPZva2fE6FXAHs76G7Rc7s3yGyX/68G0nZMrUy+Vmpg==} engines: {node: '>=20.0.0'} - '@aws-sdk/types@3.973.13': - resolution: {integrity: sha512-pEHZqRkAlHfnfAU9tK+WpKv/gBNjGJrHMgA3A0iYRGyswBS2t0pfez+lWlwktb3Bqa0ovh7w/QJTFwp3fDxLNg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/types@3.973.6': - resolution: {integrity: sha512-Atfcy4E++beKtwJHiDln2Nby8W/mam64opFPTiHEqgsthqeydFS1pY+OUlN1ouNOmf8ArPU/6cDS65anOP3KQw==} + '@aws-sdk/token-providers@3.1083.0': + resolution: {integrity: sha512-s0woKnxuHrExLc5L2ArIH5BMkbonHPtt+5hSBM8oknp9M6QTuUmmAmJ2E0EdzCGONrO+8+ADPqvv6UX0nNcc7A==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-endpoints@3.996.5': - resolution: {integrity: sha512-Uh93L5sXFNbyR5sEPMzUU8tJ++Ku97EY4udmC01nB8Zu+xfBPwpIwJ6F7snqQeq8h2pf+8SGN5/NoytfKgYPIw==} + '@aws-sdk/token-providers@3.1085.0': + resolution: {integrity: sha512-+QxFprsPw7GTCuRN86OFhDYowgkoT/+Gn0L7feWY1kpIwUoOgzLi24esQ6PgG6pf3tHE/vs5qFmO7QcFMP82TQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-locate-window@3.965.4': - resolution: {integrity: sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog==} + '@aws-sdk/types@3.973.13': + resolution: {integrity: sha512-pEHZqRkAlHfnfAU9tK+WpKv/gBNjGJrHMgA3A0iYRGyswBS2t0pfez+lWlwktb3Bqa0ovh7w/QJTFwp3fDxLNg==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-user-agent-browser@3.972.8': - resolution: {integrity: sha512-B3KGXJviV2u6Cdw2SDY2aDhoJkVfY/Q/Trwk2CMSkikE1Oi6gRzxhvhIfiRpHfmIsAhV4EA54TVEX8K6CbHbkA==} - - '@aws-sdk/util-user-agent-node@3.973.12': - resolution: {integrity: sha512-8phW0TS8ntENJgDcFewYT/Q8dOmarpvSxEjATu2GUBAutiHr++oEGCiBUwxslCMNvwW2cAPZNT53S/ym8zm/gg==} + '@aws-sdk/types@3.974.0': + resolution: {integrity: sha512-QIBrw90CDm4O0UaIIzkU6DrFdeJzEb2Va5EPEVpyldj6sHJxB6cshhStJuhZxk3wR3PmjJlYsjPmY1kNb+KGBg==} engines: {node: '>=20.0.0'} - peerDependencies: - aws-crt: '>=1.0.0' - peerDependenciesMeta: - aws-crt: - optional: true - '@aws-sdk/xml-builder@3.972.16': - resolution: {integrity: sha512-iu2pyvaqmeatIJLURLqx9D+4jKAdTH20ntzB6BFwjyN7V960r4jK32mx0Zf7YbtOYAbmbtQfDNuL60ONinyw7A==} + '@aws-sdk/util-locate-window@3.965.4': + resolution: {integrity: sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog==} engines: {node: '>=20.0.0'} '@aws-sdk/xml-builder@3.972.31': resolution: {integrity: sha512-SzE4Pgyl+hDF+BuyuzxUSpwnuUu9lJuO1YGgteG89/4Qv0+2IQiVQqdbPV32IozLvXWQChPQcdkk/sKvb1QHiQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/xml-builder@3.972.34': + resolution: {integrity: sha512-wHhWL1y7sN3enBA8POrPpQM5jCcmu2ozyhbRei4c8OjVcEaEs6yLucLa/pla457ggS/ysuy7bosagz3HaJkZXA==} + engines: {node: '>=20.0.0'} + '@aws/lambda-invoke-store@0.2.4': resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==} engines: {node: '>=18.0.0'} + '@aws/lambda-invoke-store@0.3.0': + resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==} + engines: {node: '>=18.0.0'} + '@azure/abort-controller@2.1.2': resolution: {integrity: sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==} engines: {node: '>=18.0.0'} @@ -1153,11 +1130,13 @@ packages: '@cacheable/utils@2.3.4': resolution: {integrity: sha512-knwKUJEYgIfwShABS1BX6JyJJTglAFcEU7EXqzTdiGCXur4voqkiJkdgZIQtWNFhynzDWERcTYv/sETMu3uJWA==} - '@clack/core@1.0.1': - resolution: {integrity: sha512-WKeyK3NOBwDOzagPR5H08rFk9D/WuN705yEbuZvKqlkmoLM2woKtXb10OO2k1NoSU4SFG947i2/SCYh+2u5e4g==} + '@clack/core@1.4.3': + resolution: {integrity: sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==} + engines: {node: '>= 20.12.0'} - '@clack/prompts@1.0.1': - resolution: {integrity: sha512-/42G73JkuYdyWZ6m8d/CJtBrGl1Hegyc7Fy78m5Ob+jF85TOUmLR5XLce/U3LxYAw0kJ8CT5aI99RIvPHcGp/Q==} + '@clack/prompts@1.7.0': + resolution: {integrity: sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==} + engines: {node: '>= 20.12.0'} '@cloudflare/workers-types@4.20260120.0': resolution: {integrity: sha512-B8pueG+a5S+mdK3z8oKu1ShcxloZ7qWb68IEyLLaepvdryIbNC7JVPcY0bWsjS56UQVKc5fnyRge3yZIwc9bxw==} @@ -1209,22 +1188,22 @@ packages: resolution: {integrity: sha512-UyX6rGEXzVyPzb1yvjHtPfTlnLvB5jX/stAMdiytHhfoydX+98hfympdOwsnTktzr+IRvphxTbdErgYDJkEsvw==} engines: {node: '>=22.12.0'} - '@earendil-works/pi-agent-core@0.80.2': - resolution: {integrity: sha512-BF9WPhixIFjT6Kp3Iz3H6ugkU+4AWotM8py96XE5pIK0arJbQKMWbR+dXSWWDEmR5yc/aFQODnuyowOEzMGO7Q==} + '@earendil-works/pi-agent-core@0.80.6': + resolution: {integrity: sha512-Lvn89ko42h5ETUb6Z0Ku6ldskEqXaTdQBYvSa0+7bdG9V6rUEpXptv5e0OVZ1HDcvi8s6/2lGCQWsxKX+DFHNw==} engines: {node: '>=22.19.0'} - '@earendil-works/pi-ai@0.80.2': - resolution: {integrity: sha512-5GNKfdrRJ4uZ5Zd9iudoXggi/BbUcKnD/xfRHtdR+7q4vWqPvfx8auFuaT+ewGBVI8K4wj87eigFQ/iCSuy9RQ==} + '@earendil-works/pi-ai@0.80.6': + resolution: {integrity: sha512-7xfLk8sANBp+bpPEbjoOZTbPxsa+++b1JXAoSJsNa3vbs9AHHEclmvg54XLQcxH+fuwaeti/g2jeIfJ+mVYLpA==} engines: {node: '>=22.19.0'} hasBin: true - '@earendil-works/pi-coding-agent@0.80.2': - resolution: {integrity: sha512-m9v7OUit0s9LklWfh61ca/XY5INjUzjtYtNZwy3cNvyjOLk3IpBgghP8aAp0iH35rLaiRwuuWiJ8t88ODMWY+A==} + '@earendil-works/pi-coding-agent@0.80.6': + resolution: {integrity: sha512-vcfD6tOk402isLl3Cm/qbn2O10TvgroMp1+/fEGM24ZdvETFCdOYv5VZ7m59EI5fPsjfSJh+CpQ5bhBrhfOg7g==} engines: {node: '>=22.19.0'} hasBin: true - '@earendil-works/pi-tui@0.80.2': - resolution: {integrity: sha512-OvOAMIbXiC9OSse17YMiXIsI9AS5XM/ZV8N/k+UzdlRpPILDQYmLElevgGW92kkXR8qHBClIdzhCjuzlBGvphA==} + '@earendil-works/pi-tui@0.80.6': + resolution: {integrity: sha512-bSuzS4EVSqEPj/Qr/p9eqCESfKsGuDNbl77EGci8Iaqqt/C/XCBZL1MjXaxSWW1NsT5afjp/Cb0NTPzOLv/aPA==} engines: {node: '>=22.19.0'} '@emnapi/core@1.8.1': @@ -1248,6 +1227,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.28.1': + resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.25.12': resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} engines: {node: '>=18'} @@ -1260,6 +1245,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.28.1': + resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.25.12': resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} engines: {node: '>=18'} @@ -1272,6 +1263,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.28.1': + resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.25.12': resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} engines: {node: '>=18'} @@ -1284,6 +1281,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.28.1': + resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.25.12': resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} engines: {node: '>=18'} @@ -1296,6 +1299,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.28.1': + resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.25.12': resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} @@ -1308,6 +1317,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.28.1': + resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.25.12': resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} engines: {node: '>=18'} @@ -1320,6 +1335,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.28.1': + resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.12': resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} @@ -1332,6 +1353,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.28.1': + resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.25.12': resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} @@ -1344,6 +1371,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.28.1': + resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.25.12': resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} engines: {node: '>=18'} @@ -1356,6 +1389,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.28.1': + resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.25.12': resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} engines: {node: '>=18'} @@ -1368,6 +1407,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.28.1': + resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.25.12': resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} engines: {node: '>=18'} @@ -1380,6 +1425,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.28.1': + resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.25.12': resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} engines: {node: '>=18'} @@ -1392,6 +1443,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.28.1': + resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.25.12': resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} engines: {node: '>=18'} @@ -1404,6 +1461,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.28.1': + resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.25.12': resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} engines: {node: '>=18'} @@ -1416,6 +1479,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.28.1': + resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.25.12': resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} engines: {node: '>=18'} @@ -1428,6 +1497,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.28.1': + resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.25.12': resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} engines: {node: '>=18'} @@ -1440,6 +1515,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.28.1': + resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.12': resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} @@ -1452,6 +1533,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.28.1': + resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.12': resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} engines: {node: '>=18'} @@ -1464,6 +1551,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.28.1': + resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.12': resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} @@ -1476,6 +1569,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.28.1': + resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.12': resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} @@ -1488,6 +1587,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.28.1': + resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openharmony-arm64@0.25.12': resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} @@ -1500,6 +1605,12 @@ packages: cpu: [arm64] os: [openharmony] + '@esbuild/openharmony-arm64@0.28.1': + resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.25.12': resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} @@ -1512,6 +1623,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.28.1': + resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.25.12': resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} engines: {node: '>=18'} @@ -1524,6 +1641,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.28.1': + resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.25.12': resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} @@ -1536,6 +1659,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.28.1': + resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.25.12': resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} @@ -1548,6 +1677,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.28.1': + resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@google/genai@1.52.0': resolution: {integrity: sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==} engines: {node: '>=20.0.0'} @@ -1569,8 +1704,8 @@ packages: peerDependencies: grammy: ^1.0.0 - '@grammyjs/types@3.24.0': - resolution: {integrity: sha512-qQIEs4lN5WqUdr4aT8MeU6UFpMbGYAvcvYSW1A4OO1PABGJQHz/KLON6qvpf+5RxaNDQBxiY2k2otIhg/AG7RQ==} + '@grammyjs/types@3.28.0': + resolution: {integrity: sha512-4JvXCdxRZHCje0M4gHzLwtB4bLno3WD28xd8CNfk4POWIu73BFnSvGeW6OQ5gPem4eYTEwkD9yDaXssixl6tMQ==} '@grpc/grpc-js@1.14.3': resolution: {integrity: sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==} @@ -1587,8 +1722,8 @@ packages: '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} - '@homebridge/ciao@1.3.5': - resolution: {integrity: sha512-f7MAw7YuoEYgJEQ1VyRcLHGuVmCpmXi65GVR8CAtPWPqIZf/HFr4vHzVpOfQMpEQw9Pt5uh07guuLt5HE8ruog==} + '@homebridge/ciao@1.3.10': + resolution: {integrity: sha512-ogAVdPZ9Fo3kSaULpq+acxbtbIvMtd2TDYEkqHIsqvQ9QHJnRNcjm8NQzegaBzJ3gUK1mVX07UWs2/B0NmabSw==} hasBin: true '@hono/node-server@1.19.10': @@ -2062,6 +2197,10 @@ packages: resolution: {integrity: sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==} engines: {node: '>= 20.19.0'} + '@noble/curves@2.2.0': + resolution: {integrity: sha512-T/BoHgFXirb0ENSPBquzX0rcjXeM6Lo892a2jlYJkqk83LqZx0l1Of7DzlKJ6jkpvMrkHSnAcgb5JegL8SeIkQ==} + engines: {node: '>= 20.19.0'} + '@noble/ed25519@3.0.0': resolution: {integrity: sha512-QyteqMNm0GLqfa5SoYbSC3+Pvykwpn95Zgth4MFVSMKBB75ELl9tX1LAVsN4c3HXOrakHsF2gL4zWDAYCcsnzg==} @@ -2069,6 +2208,10 @@ packages: resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==} engines: {node: '>= 20.19.0'} + '@noble/hashes@2.2.0': + resolution: {integrity: sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==} + engines: {node: '>= 20.19.0'} + '@node-llama-cpp/linux-arm64@3.17.1': resolution: {integrity: sha512-QK8opgd/AnGHvSQwIDXukrMNa760PLOxcu4OrxJn/CsHxiKucch0L4bDfu17XvlKiMoK41lXa6CKFm1kjVaGIQ==} engines: {node: '>=20.0.0'} @@ -2478,116 +2621,116 @@ packages: cpu: [x64] os: [win32] - '@oxlint/binding-android-arm-eabi@1.50.0': - resolution: {integrity: sha512-G7MRGk/6NCe+L8ntonRdZP7IkBfEpiZ/he3buLK6JkLgMHgJShXZ+BeOwADmspXez7U7F7L1Anf4xLSkLHiGTg==} + '@oxlint/binding-android-arm-eabi@1.73.0': + resolution: {integrity: sha512-HZQRN/UMBu+Ut+/9MiAChkbP4qZqrNOWBcNI45vOT40GVhbGR0JgHB87L48D4iAqFQIdVmeQYtV9RF89AjTKkg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxlint/binding-android-arm64@1.50.0': - resolution: {integrity: sha512-GeSuMoJWCVpovJi/e3xDSNgjeR8WEZ6MCXL6EtPiCIM2NTzv7LbflARINTXTJy2oFBYyvdf/l2PwHzYo6EdXvg==} + '@oxlint/binding-android-arm64@1.73.0': + resolution: {integrity: sha512-Gp+KJRylv2aW7thRpG5p1KTxZq4ZJFbWowrKzufNq9d3ssl3r3JviYV45/+p+7CN1Nv0zDd1e8Ex0b/HUDq4TQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxlint/binding-darwin-arm64@1.50.0': - resolution: {integrity: sha512-w3SY5YtxGnxCHPJ8Twl3KmS9oja1gERYk3AMoZ7Hv8P43ZtB6HVfs02TxvarxfL214Tm3uzvc2vn+DhtUNeKnw==} + '@oxlint/binding-darwin-arm64@1.73.0': + resolution: {integrity: sha512-3de96NdtXhxERMjIz7wsp2HYMY6pMQycGxFWac2mFecAx6VeARF/IqFb1QIaqiCRIdfzBwzTed+pCTCoiS+CYA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxlint/binding-darwin-x64@1.50.0': - resolution: {integrity: sha512-hNfogDqy7tvmllXKBSlHo6k5x7dhTUVOHbMSE15CCAcXzmqf5883aPvBYPOq9AE7DpDUQUZ1kVE22YbiGW+tuw==} + '@oxlint/binding-darwin-x64@1.73.0': + resolution: {integrity: sha512-5zx/uPW32TiaOeVY1dQ/H5iOf0K1HOdFKOJhLqGl4o63+i1fpzoqqu/mKtd7OFgFjNCdhlyTGgjVkQTZm1ELcg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxlint/binding-freebsd-x64@1.50.0': - resolution: {integrity: sha512-ykZevOWEyu0nsxolA911ucxpEv0ahw8jfEeGWOwwb/VPoE4xoexuTOAiPNlWZNJqANlJl7yp8OyzCtXTUAxotw==} + '@oxlint/binding-freebsd-x64@1.73.0': + resolution: {integrity: sha512-qNe4gKHaGnLuZJ8toUg90JAa0S2vTVvDw+0bRi3q1avXZXDT4u5mMeECf3nD4HYrbdn1O7dXqWut4onY/yx/Xg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxlint/binding-linux-arm-gnueabihf@1.50.0': - resolution: {integrity: sha512-hif3iDk7vo5GGJ4OLCCZAf2vjnU9FztGw4L0MbQL0M2iY9LKFtDMMiQAHmkF0PQGQMVbTYtPdXCLKVgdkiqWXQ==} + '@oxlint/binding-linux-arm-gnueabihf@1.73.0': + resolution: {integrity: sha512-cCehYh5hTbfShm/fxTD6wwrGUWIpvX+N5OxmAMhFhDeTGXvw+BeNj889tpxsFQ9ZLatQ6wImuY8tsKLZ+FMz7w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm-musleabihf@1.50.0': - resolution: {integrity: sha512-dVp9iSssiGAnTNey2Ruf6xUaQhdnvcFOJyRWd/mu5o2jVbFK15E5fbWGeFRfmuobu5QXuROtFga44+7DOS3PLg==} + '@oxlint/binding-linux-arm-musleabihf@1.73.0': + resolution: {integrity: sha512-d5j5GDU/2dMgjVhw7TQT9ITrsIr1Y02KEXKyVGIXUkD+KiaxE9TP65FS2ZdgTBemQvoRL+gSBdbrIm3cQIeacg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm64-gnu@1.50.0': - resolution: {integrity: sha512-1cT7yz2HA910CKA9NkH1ZJo50vTtmND2fkoW1oyiSb0j6WvNtJ0Wx2zoySfXWc/c+7HFoqRK5AbEoL41LOn9oA==} + '@oxlint/binding-linux-arm64-gnu@1.73.0': + resolution: {integrity: sha512-Eyf1SrP3+yR1DI3OJgOY2Pvrr9dWP9TK37xPaDYycwTtlGlI45erJAVIfH5/m/xosDt6BupJYEFi47bvbTuuyw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@oxlint/binding-linux-arm64-musl@1.50.0': - resolution: {integrity: sha512-++B3k/HEPFVlj89cOz8kWfQccMZB/aWL9AhsW7jPIkG++63Mpwb2cE9XOEsd0PATbIan78k2Gky+09uWM1d/gQ==} + '@oxlint/binding-linux-arm64-musl@1.73.0': + resolution: {integrity: sha512-IlT/OJApEDKaMmCooHuncgJZbbCe7T5QIWmTZBEtYscWvzPQuuEinVcid6kwQRVQOUdb7PUCz4jQHnaYXdfJXw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@oxlint/binding-linux-ppc64-gnu@1.50.0': - resolution: {integrity: sha512-Z9b/KpFMkx66w3gVBqjIC1AJBTZAGoI9+U+K5L4QM0CB/G0JSNC1es9b3Y0Vcrlvtdn8A+IQTkYjd/Q0uCSaZw==} + '@oxlint/binding-linux-ppc64-gnu@1.73.0': + resolution: {integrity: sha512-L+JYcb/vdg5fmcH08V6o0YYLU28cTH1SPNulwJdvK9NK49aXSkYy6oNpKBmddArVOXYqNepriDGiZ04G54kh1Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - '@oxlint/binding-linux-riscv64-gnu@1.50.0': - resolution: {integrity: sha512-jvmuIw8wRSohsQlFNIST5uUwkEtEJmOQYr33bf/K2FrFPXHhM4KqGekI3ShYJemFS/gARVacQFgBzzJKCAyJjg==} + '@oxlint/binding-linux-riscv64-gnu@1.73.0': + resolution: {integrity: sha512-Qtk0g3bKV6OwWjIm7R8kQN1uOZRKQt/MODK2a8QfkwhTpXBD53ozx5XLVWLGDQAVyp2otLW4D2wB98XfAfMPGA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - '@oxlint/binding-linux-riscv64-musl@1.50.0': - resolution: {integrity: sha512-x+UrN47oYNh90nmAAyql8eQaaRpHbDPu5guasDg10+OpszUQ3/1+1J6zFMmV4xfIEgTcUXG/oI5fxJhF4eWCNA==} + '@oxlint/binding-linux-riscv64-musl@1.73.0': + resolution: {integrity: sha512-wX0NQKZVxltkAOVmzFcpOaMpdaUvsq1Eqpx9tkAfl71UdkTlSo1R4AdAnGccR1Fm2+TzFgZ22CyyGuZ41RDr/A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - '@oxlint/binding-linux-s390x-gnu@1.50.0': - resolution: {integrity: sha512-i/JLi2ljLUIVfekMj4ISmdt+Hn11wzYUdRRrkVUYsCWw7zAy5xV7X9iA+KMyM156LTFympa7s3oKBjuCLoTAUQ==} + '@oxlint/binding-linux-s390x-gnu@1.73.0': + resolution: {integrity: sha512-vPe7UGBMWyiLTtnqS4xxgMQFSFGmtQwhwCxuiw6lXygaO6bVt0D8dFVg8Xv05eaiN3ybC0HXXHUAohFMFvqoCQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - '@oxlint/binding-linux-x64-gnu@1.50.0': - resolution: {integrity: sha512-/C7brhn6c6UUPccgSPCcpLQXcp+xKIW/3sji/5VZ8/OItL3tQ2U7KalHz887UxxSQeEOmd1kY6lrpuwFnmNqOA==} + '@oxlint/binding-linux-x64-gnu@1.73.0': + resolution: {integrity: sha512-2CwIWr9cemFC/CbRBWZvuk5mffz6ObmfFkfcC/9rTQ7f+icNhYr2kOjf9Rt8lLvugvkdGDOmkoVoFFHh6ClCTw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@oxlint/binding-linux-x64-musl@1.50.0': - resolution: {integrity: sha512-oDR1f+bGOYU8LfgtEW8XtotWGB63ghtcxk5Jm6IDTCk++rTA/IRMsjOid2iMd+1bW+nP9Mdsmcdc7VbPD3+iyQ==} + '@oxlint/binding-linux-x64-musl@1.73.0': + resolution: {integrity: sha512-nDadfJgg7NBBxG0N560wOe7LLX5QiYp6qBaI7viuk5EUORFBktU/NfV0MbTqU3gTqQDCh4VyxKdo5VADxk9w8Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@oxlint/binding-openharmony-arm64@1.50.0': - resolution: {integrity: sha512-4CmRGPp5UpvXyu4jjP9Tey/SrXDQLRvZXm4pb4vdZBxAzbFZkCyh0KyRy4txld/kZKTJlW4TO8N1JKrNEk+mWw==} + '@oxlint/binding-openharmony-arm64@1.73.0': + resolution: {integrity: sha512-wGjJC+NLH9xP+IKGn9RDW94ojJR/wPbg5WCnQjj/oReaOtCQthr8ws1zICe77JFmo4ouUdeTHHZL/ESGiF6Pmw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxlint/binding-win32-arm64-msvc@1.50.0': - resolution: {integrity: sha512-Fq0M6vsGcFsSfeuWAACDhd5KJrO85ckbEfe1EGuBj+KPyJz7KeWte2fSFrFGmNKNXyhEMyx4tbgxiWRujBM2KQ==} + '@oxlint/binding-win32-arm64-msvc@1.73.0': + resolution: {integrity: sha512-I7X47GPGljw225YUQ5SbC/rb1Kkdrd0yQf0x+hYxeKS6DpfjMbo9ccQPQ6LNY6BoJQ1sHhgDUGuMn5Vg5gHT6w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxlint/binding-win32-ia32-msvc@1.50.0': - resolution: {integrity: sha512-qTdWR9KwY/vxJGhHVIZG2eBOhidOQvOwzDxnX+jhW/zIVacal1nAhR8GLkiywW8BIFDkQKXo/zOfT+/DY+ns/w==} + '@oxlint/binding-win32-ia32-msvc@1.73.0': + resolution: {integrity: sha512-5lWj+3h+74Fm1jYOO9qkJA4xkAlZA099DkXppuXsk7UpnpZLttsefrZU469vChGaG6hcSqrkKXQOvMTZtbjeNg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxlint/binding-win32-x64-msvc@1.50.0': - resolution: {integrity: sha512-682t7npLC4G2Ca+iNlI9fhAKTcFPYYXJjwoa88H4q+u5HHHlsnL/gHULapX3iqp+A8FIJbgdylL5KMYo2LaluQ==} + '@oxlint/binding-win32-x64-msvc@1.73.0': + resolution: {integrity: sha512-WaNRvh4f6zY9CvUQk2YoA1O90ieWrIklI84+HXFr9Isjz9CSESrdqo/RtIYt4Dll/cAchqGDMehfaZd0vqEFZw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -2922,108 +3065,60 @@ packages: '@sinclair/typebox@0.34.48': resolution: {integrity: sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==} - '@slack/bolt@4.6.0': - resolution: {integrity: sha512-xPgfUs2+OXSugz54Ky07pA890+Qydk22SYToi8uGpXeHSt1JWwFJkRyd/9Vlg5I1AdfdpGXExDpwnbuN9Q/2dQ==} + '@slack/bolt@4.7.3': + resolution: {integrity: sha512-bODs8q/yNDWUPoxmQhFrRqLMA5vhB/PDizYWqb6CkQhLWEUo5JFtfJcmeU4ElGl6qSt++OKjSYNa4MPc77CleQ==} engines: {node: '>=18', npm: '>=8.6.0'} peerDependencies: '@types/express': ^5.0.0 - '@slack/logger@4.0.0': - resolution: {integrity: sha512-Wz7QYfPAlG/DR+DfABddUZeNgoeY7d1J39OCR2jR+v7VBsB8ezulDK5szTnDDPDwLH5IWhLvXIHlCFZV7MSKgA==} + '@slack/logger@4.0.1': + resolution: {integrity: sha512-6cmdPrV/RYfd2U0mDGiMK8S7OJqpCTm7enMLRR3edccsPX8j7zXTLnaEF4fhxxJJTAIOil6+qZrnUPTuaLvwrQ==} engines: {node: '>= 18', npm: '>= 8.6.0'} - '@slack/oauth@3.0.4': - resolution: {integrity: sha512-+8H0g7mbrHndEUbYCP7uYyBCbwqmm3E6Mo3nfsDvZZW74zKk1ochfH/fWSvGInYNCVvaBUbg3RZBbTp0j8yJCg==} + '@slack/oauth@3.0.5': + resolution: {integrity: sha512-exqFQySKhNDptWYSWhvRUJ4/+ndu2gayIy7vg/JfmJq3wGtGdHk531P96fAZyBm5c1Le3yaPYqv92rL4COlU3A==} engines: {node: '>=18', npm: '>=8.6.0'} - '@slack/socket-mode@2.0.5': - resolution: {integrity: sha512-VaapvmrAifeFLAFaDPfGhEwwunTKsI6bQhYzxRXw7BSujZUae5sANO76WqlVsLXuhVtCVrBWPiS2snAQR2RHJQ==} + '@slack/socket-mode@2.0.7': + resolution: {integrity: sha512-qYy07je71WnEHgRwmw12DlAnZLi5HXmdlI2WUzUK2LH/rYXQpP6uEg462S5CwfE8FoCKUdIigHtYnOOfzZH1lQ==} engines: {node: '>= 18', npm: '>= 8.6.0'} - '@slack/types@2.20.0': - resolution: {integrity: sha512-PVF6P6nxzDMrzPC8fSCsnwaI+kF8YfEpxf3MqXmdyjyWTYsZQURpkK7WWUWvP5QpH55pB7zyYL9Qem/xSgc5VA==} + '@slack/types@2.22.0': + resolution: {integrity: sha512-sZ9lIgJhPX2qft/tKWiklFlc0o1FWeI7QtciZJfW1+ErH1eGGHvOZ8e73sleTCFEFJp1q/R0WeS8Oa7AsiDprg==} engines: {node: '>= 12.13.0', npm: '>= 6.12.0'} - '@slack/web-api@7.14.1': - resolution: {integrity: sha512-RoygyteJeFswxDPJjUMESn9dldWVMD2xUcHHd9DenVavSfVC6FeVnSdDerOO7m8LLvw4Q132nQM4hX8JiF7dng==} + '@slack/web-api@7.19.0': + resolution: {integrity: sha512-ItjyjEZml+LDH8CjcCLRLJHh7VZtevPKExrRN3l5KWyBliyDnGAeoO4Y+K+fFBmRpKLYVPgqWMX4THldv2HVtA==} engines: {node: '>= 18', npm: '>= 8.6.0'} - '@smithy/abort-controller@4.2.12': - resolution: {integrity: sha512-xolrFw6b+2iYGl6EcOL7IJY71vvyZ0DJ3mcKtpykqPe2uscwtzDZJa1uVQXyP7w9Dd+kGwYnPbMsJrGISKiY/Q==} - engines: {node: '>=18.0.0'} - - '@smithy/config-resolver@4.4.13': - resolution: {integrity: sha512-iIzMC5NmOUP6WL6o8iPBjFhUhBZ9pPjpUpQYWMUFQqKyXXzOftbfK8zcQCz/jFV1Psmf05BK5ypx4K2r4Tnwdg==} - engines: {node: '>=18.0.0'} - - '@smithy/core@3.23.12': - resolution: {integrity: sha512-o9VycsYNtgC+Dy3I0yrwCqv9CWicDnke0L7EVOrZtJpjb2t0EjaEofmMrYc0T1Kn3yk32zm6cspxF9u9Bj7e5w==} - engines: {node: '>=18.0.0'} - '@smithy/core@3.26.0': resolution: {integrity: sha512-mLUktFAn+Pa2agl1J7VgtYNFWCX8/b4GMJSK1hCu4YCvtBfM6F8Os3EP4ry+DFFlXOf3wyvlgXhuUdFoy52D3g==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.2.12': - resolution: {integrity: sha512-cr2lR792vNZcYMriSIj+Um3x9KWrjcu98kn234xA6reOAFMmbRpQMOv8KPgEmLLtx3eldU6c5wALKFqNOhugmg==} + '@smithy/core@3.29.3': + resolution: {integrity: sha512-L+Ys6ecjk5vwPMAKHBpPKlJ3DkqwNcnfEISXBZIsVvWG/XKXfsAP8mwIYlTeLcd2ElHdesPI8OuOmJSFAPhm6A==} engines: {node: '>=18.0.0'} '@smithy/credential-provider-imds@4.4.2': resolution: {integrity: sha512-18UMDMyrAbDcpmL1gLUA7ww0fRTcdCrSjSJOi2Sbld+tVjwD/pW+OAwjlScFLR7vvBnhZrIPQ7kVuTf1mnJLug==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.3.15': - resolution: {integrity: sha512-T4jFU5N/yiIfrtrsb9uOQn7RdELdM/7HbyLNr6uO/mpkj1ctiVs7CihVr51w4LyQlXWDpXFn4BElf1WmQvZu/A==} + '@smithy/credential-provider-imds@4.4.8': + resolution: {integrity: sha512-q9J7JTiXrAhB8sDp4px97uEPT7CwKH61Co78grdNQvU8QZAdiuaSRhP0tUVf2ogy36RZTrlMU1rBmDEH+cnkiA==} engines: {node: '>=18.0.0'} '@smithy/fetch-http-handler@5.5.2': resolution: {integrity: sha512-Ei/UK/QMhq0rKaMqGPlOAkE2yS9DZeYmZdk1RAKc3vp3zxgleZHZyBLlZv8yLsxljX4svCRuMTD6u3LLIcU4Bg==} engines: {node: '>=18.0.0'} - '@smithy/hash-node@4.2.12': - resolution: {integrity: sha512-QhBYbGrbxTkZ43QoTPrK72DoYviDeg6YKDrHTMJbbC+A0sml3kSjzFtXP7BtbyJnXojLfTQldGdUR0RGD8dA3w==} - engines: {node: '>=18.0.0'} - - '@smithy/invalid-dependency@4.2.12': - resolution: {integrity: sha512-/4F1zb7Z8LOu1PalTdESFHR0RbPwHd3FcaG1sI3UEIriQTWakysgJr65lc1jj6QY5ye7aFsisajotH6UhWfm/g==} + '@smithy/fetch-http-handler@5.6.5': + resolution: {integrity: sha512-SuqeisTyPoiIPtIYru/sGxGyXzmZ+8nnFOhC+qRPglt06Ebd1yH//CDltZB2J/3WBNVhwfUaZ0EtHB3cm2X32g==} engines: {node: '>=18.0.0'} '@smithy/is-array-buffer@2.2.0': resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} engines: {node: '>=14.0.0'} - '@smithy/is-array-buffer@4.2.2': - resolution: {integrity: sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-content-length@4.2.12': - resolution: {integrity: sha512-YE58Yz+cvFInWI/wOTrB+DbvUVz/pLn5mC5MvOV4fdRUc6qGwygyngcucRQjAhiCEbmfLOXX0gntSIcgMvAjmA==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-endpoint@4.4.27': - resolution: {integrity: sha512-T3TFfUgXQlpcg+UdzcAISdZpj4Z+XECZ/cefgA6wLBd6V4lRi0svN2hBouN/be9dXQ31X4sLWz3fAQDf+nt6BA==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-retry@4.4.44': - resolution: {integrity: sha512-Y1Rav7m5CFRPQyM4CI0koD/bXjyjJu3EQxZZhtLGD88WIrBrQ7kqXM96ncd6rYnojwOo/u9MXu57JrEvu/nLrA==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-serde@4.2.15': - resolution: {integrity: sha512-ExYhcltZSli0pgAKOpQQe1DLFBLryeZ22605y/YS+mQpdNWekum9Ujb/jMKfJKgjtz1AZldtwA/wCYuKJgjjlg==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-stack@4.2.12': - resolution: {integrity: sha512-kruC5gRHwsCOuyCd4ouQxYjgRAym2uDlCvQ5acuMtRrcdfg7mFBg6blaxcJ09STpt3ziEkis6bhg1uwrWU7txw==} - engines: {node: '>=18.0.0'} - - '@smithy/node-config-provider@4.3.12': - resolution: {integrity: sha512-tr2oKX2xMcO+rBOjobSwVAkV05SIfUKz8iI53rzxEmgW3GOOPOv0UioSDk+J8OpRQnpnhsO3Af6IEBabQBVmiw==} - engines: {node: '>=18.0.0'} - - '@smithy/node-http-handler@4.5.0': - resolution: {integrity: sha512-Rnq9vQWiR1+/I6NZZMNzJHV6pZYyEHt2ZnuV3MG8z2NNenC4i/8Kzttz7CjZiHSmsN5frhXhg17z3Zqjjhmz1A==} - engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.7.3': resolution: {integrity: sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==} engines: {node: '>=18.0.0'} @@ -3032,122 +3127,34 @@ packages: resolution: {integrity: sha512-wfl1uwrAqMH9/pi4kqBo5LBcFwrJLxuDLqL7p7qNcJIFcyZDUc6pzhYk4CYv+DP7fIUpQCZumwNnkhPKS52osQ==} engines: {node: '>=18.0.0'} - '@smithy/property-provider@4.2.12': - resolution: {integrity: sha512-jqve46eYU1v7pZ5BM+fmkbq3DerkSluPr5EhvOcHxygxzD05ByDRppRwRPPpFrsFo5yDtCYLKu+kreHKVrvc7A==} - engines: {node: '>=18.0.0'} - - '@smithy/protocol-http@5.3.12': - resolution: {integrity: sha512-fit0GZK9I1xoRlR4jXmbLhoN0OdEpa96ul8M65XdmXnxXkuMxM0Y8HDT0Fh0Xb4I85MBvBClOzgSrV1X2s1Hxw==} - engines: {node: '>=18.0.0'} - - '@smithy/querystring-builder@4.2.12': - resolution: {integrity: sha512-6wTZjGABQufekycfDGMEB84BgtdOE/rCVTov+EDXQ8NHKTUNIp/j27IliwP7tjIU9LR+sSzyGBOXjeEtVgzCHg==} - engines: {node: '>=18.0.0'} - - '@smithy/querystring-parser@4.2.12': - resolution: {integrity: sha512-P2OdvrgiAKpkPNKlKUtWbNZKB1XjPxM086NeVhK+W+wI46pIKdWBe5QyXvhUm3MEcyS/rkLvY8rZzyUdmyDZBw==} - engines: {node: '>=18.0.0'} - - '@smithy/service-error-classification@4.2.12': - resolution: {integrity: sha512-LlP29oSQN0Tw0b6D0Xo6BIikBswuIiGYbRACy5ujw/JgWSzTdYj46U83ssf6Ux0GyNJVivs2uReU8pt7Eu9okQ==} - engines: {node: '>=18.0.0'} - - '@smithy/shared-ini-file-loader@4.4.7': - resolution: {integrity: sha512-HrOKWsUb+otTeo1HxVWeEb99t5ER1XrBi/xka2Wv6NVmTbuCUC1dvlrksdvxFtODLBjsC+PHK+fuy2x/7Ynyiw==} - engines: {node: '>=18.0.0'} - - '@smithy/signature-v4@5.3.12': - resolution: {integrity: sha512-B/FBwO3MVOL00DaRSXfXfa/TRXRheagt/q5A2NM13u7q+sHS59EOVGQNfG7DkmVtdQm5m3vOosoKAXSqn/OEgw==} + '@smithy/node-http-handler@4.9.5': + resolution: {integrity: sha512-bNqdxTQTxmLbomSmlkZFz8L6B/feQ2HHzw4L2zY7Ecp2XffYAZq2uzdWDdxJHJFbEvqd+SRuluJso0P8+xPdbw==} engines: {node: '>=18.0.0'} '@smithy/signature-v4@5.5.2': resolution: {integrity: sha512-7xHpmPY4rt0IOmeAA8EfjgEH8isT+587TCdy9H6a7d4OMi5CQ0oEHhWllunvPu4j4Cq0vTFwdxXN/kABWPjdyA==} engines: {node: '>=18.0.0'} - '@smithy/smithy-client@4.12.7': - resolution: {integrity: sha512-q3gqnwml60G44FECaEEsdQMplYhDMZYCtYhMCzadCnRnnHIobZJjegmdoUo6ieLQlPUzvrMdIJUpx6DoPmzANQ==} - engines: {node: '>=18.0.0'} - - '@smithy/types@4.13.1': - resolution: {integrity: sha512-787F3yzE2UiJIQ+wYW1CVg2odHjmaWLGksnKQHUrK/lYZSEcy1msuLVvxaR/sI2/aDe9U+TBuLsXnr3vod1g0g==} + '@smithy/signature-v4@5.6.4': + resolution: {integrity: sha512-B89bpf2t/y/wia6LZ+4JfHXYQT9PnVftsH05rgJKKIStS7r/4XSs9HOjtPoLtgcA6HCW9jVqX5DBbq7E0PAkiQ==} engines: {node: '>=18.0.0'} '@smithy/types@4.15.0': resolution: {integrity: sha512-Z5TAOxygoFvybJV3igo5SloFflSokHx2hu1eFA+DxDTcn+FtKxUSui+rbTRG1pAafMA888Z3MVvCWUuvCrTXjg==} engines: {node: '>=18.0.0'} - '@smithy/url-parser@4.2.12': - resolution: {integrity: sha512-wOPKPEpso+doCZGIlr+e1lVI6+9VAKfL4kZWFgzVgGWY2hZxshNKod4l2LXS3PRC9otH/JRSjtEHqQ/7eLciRA==} - engines: {node: '>=18.0.0'} - - '@smithy/util-base64@4.3.2': - resolution: {integrity: sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==} - engines: {node: '>=18.0.0'} - - '@smithy/util-body-length-browser@4.2.2': - resolution: {integrity: sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==} - engines: {node: '>=18.0.0'} - - '@smithy/util-body-length-node@4.2.3': - resolution: {integrity: sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==} + '@smithy/types@4.16.1': + resolution: {integrity: sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==} engines: {node: '>=18.0.0'} '@smithy/util-buffer-from@2.2.0': resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} engines: {node: '>=14.0.0'} - '@smithy/util-buffer-from@4.2.2': - resolution: {integrity: sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==} - engines: {node: '>=18.0.0'} - - '@smithy/util-config-provider@4.2.2': - resolution: {integrity: sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==} - engines: {node: '>=18.0.0'} - - '@smithy/util-defaults-mode-browser@4.3.43': - resolution: {integrity: sha512-Qd/0wCKMaXxev/z00TvNzGCH2jlKKKxXP1aDxB6oKwSQthe3Og2dMhSayGCnsma1bK/kQX1+X7SMP99t6FgiiQ==} - engines: {node: '>=18.0.0'} - - '@smithy/util-defaults-mode-node@4.2.47': - resolution: {integrity: sha512-qSRbYp1EQ7th+sPFuVcVO05AE0QH635hycdEXlpzIahqHHf2Fyd/Zl+8v0XYMJ3cgDVPa0lkMefU7oNUjAP+DQ==} - engines: {node: '>=18.0.0'} - - '@smithy/util-endpoints@3.3.3': - resolution: {integrity: sha512-VACQVe50j0HZPjpwWcjyT51KUQ4AnsvEaQ2lKHOSL4mNLD0G9BjEniQ+yCt1qqfKfiAHRAts26ud7hBjamrwig==} - engines: {node: '>=18.0.0'} - - '@smithy/util-hex-encoding@4.2.2': - resolution: {integrity: sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==} - engines: {node: '>=18.0.0'} - - '@smithy/util-middleware@4.2.12': - resolution: {integrity: sha512-Er805uFUOvgc0l8nv0e0su0VFISoxhJ/AwOn3gL2NWNY2LUEldP5WtVcRYSQBcjg0y9NfG8JYrCJaYDpupBHJQ==} - engines: {node: '>=18.0.0'} - - '@smithy/util-retry@4.2.12': - resolution: {integrity: sha512-1zopLDUEOwumjcHdJ1mwBHddubYF8GMQvstVCLC54Y46rqoHwlIU+8ZzUeaBcD+WCJHyDGSeZ2ml9YSe9aqcoQ==} - engines: {node: '>=18.0.0'} - - '@smithy/util-stream@4.5.20': - resolution: {integrity: sha512-4yXLm5n/B5SRBR2p8cZ90Sbv4zL4NKsgxdzCzp/83cXw2KxLEumt5p+GAVyRNZgQOSrzXn9ARpO0lUe8XSlSDw==} - engines: {node: '>=18.0.0'} - - '@smithy/util-uri-escape@4.2.2': - resolution: {integrity: sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==} - engines: {node: '>=18.0.0'} - '@smithy/util-utf8@2.3.0': resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} engines: {node: '>=14.0.0'} - '@smithy/util-utf8@4.2.2': - resolution: {integrity: sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==} - engines: {node: '>=18.0.0'} - - '@smithy/uuid@1.1.2': - resolution: {integrity: sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==} - engines: {node: '>=18.0.0'} - '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -3363,11 +3370,11 @@ packages: peerDependencies: vitest: 4.0.18 - '@vitest/coverage-v8@4.0.18': - resolution: {integrity: sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==} + '@vitest/coverage-v8@4.1.10': + resolution: {integrity: sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==} peerDependencies: - '@vitest/browser': 4.0.18 - vitest: 4.0.18 + '@vitest/browser': 4.1.10 + vitest: 4.1.10 peerDependenciesMeta: '@vitest/browser': optional: true @@ -3378,6 +3385,9 @@ packages: '@vitest/expect@4.0.18': resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==} + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} + '@vitest/mocker@3.2.4': resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} peerDependencies: @@ -3400,36 +3410,62 @@ packages: vite: optional: true + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + '@vitest/pretty-format@3.2.4': resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} '@vitest/pretty-format@4.0.18': resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==} + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} + '@vitest/runner@3.2.4': resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} '@vitest/runner@4.0.18': resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==} + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} + '@vitest/snapshot@3.2.4': resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} '@vitest/snapshot@4.0.18': resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==} + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} + '@vitest/spy@3.2.4': resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} '@vitest/spy@4.0.18': resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==} + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} + '@vitest/utils@3.2.4': resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} '@vitest/utils@4.0.18': resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} + '@whiskeysockets/baileys@7.0.0-rc.9': resolution: {integrity: sha512-YFm5gKXfDP9byCXCW3OPHKXLzrAKzolzgVUlRosHHgwbnf2YOO3XknkMm6J7+F0ns8OA0uuSBhgkRHTDtqkacw==} engines: {node: '>=20.0.0'} @@ -3468,12 +3504,16 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + agent-base@7.1.4: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} - ajv@8.18.0: - resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} another-json@0.2.0: resolution: {integrity: sha512-/Ndrl68UQLhnCdsAzEXLMFuOR546o2qbYRqCglaNHbjXrwG1ayTcdwr3zkSGOGtGXDyR5X9nCFfnyG2AFJIsqg==} @@ -3538,8 +3578,8 @@ packages: resolution: {integrity: sha512-trmleAnZ2PxN/loHWVhhx1qeOHSRXq4TDsBBxq3GqeJitfk3+jTQ+v/C1km/KYq9M7wKqCewMh+/NAvVH7m+bw==} engines: {node: '>=20.19.0'} - ast-v8-to-istanbul@0.3.11: - resolution: {integrity: sha512-Qya9fkoofMjCBNVdWINMjB5KZvkYfaO9/anwkWnjxibpWUxo5iHl2sOdP7/uAqaRuUYuoo8rDwnbaaKVFxoUvw==} + ast-v8-to-istanbul@1.0.4: + resolution: {integrity: sha512-0bC0/4bTSrnwdhU3IsZDwEdojvuPrSg59OYZfKsLRtJZ0u8VBx9DebfqqG8bRdCC0I7vjgxmPi41P0lpkhJHtA==} async-lock@1.4.1: resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==} @@ -3566,6 +3606,9 @@ packages: axios@1.13.5: resolution: {integrity: sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==} + axios@1.18.1: + resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==} + balanced-match@4.0.4: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} @@ -3755,6 +3798,9 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie-signature@1.0.7: resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} @@ -3876,8 +3922,8 @@ packages: domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - dotenv@17.3.1: - resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} + dotenv@17.4.2: + resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} engines: {node: '>=12'} dts-resolver@2.1.3: @@ -3945,6 +3991,9 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-module-lexer@2.3.1: + resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -3963,6 +4012,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.28.1: + resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -4017,15 +4071,17 @@ packages: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} + fast-string-truncated-width@3.0.3: + resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==} + + fast-string-width@3.0.2: + resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} + fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} - fast-xml-builder@1.1.4: - resolution: {integrity: sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==} - - fast-xml-parser@5.5.9: - resolution: {integrity: sha512-jldvxr1MC6rtiZKgrFnDSvT8xuH+eJqxqOBThUVjYrxssYTo1avZLGql5l0a0BAERR01CadYzZ83kVEkbyDg+g==} - hasBin: true + fast-wrap-ansi@0.2.2: + resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -4083,6 +4139,15 @@ packages: debug: optional: true + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -4193,8 +4258,8 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - grammy@1.40.0: - resolution: {integrity: sha512-ssuE7fc1AwqlUxHr931OCVW3fU+oFDjHZGgvIedPKXfTdjXvzP19xifvVGCnPtYVUig1Kz+gwxe4A9M5WdkT4Q==} + grammy@1.44.0: + resolution: {integrity: sha512-gGVykS5+c5f1tPV97LuU6IDRMawE2NzpwM9pNz58HQ35IZXDnYL3VOLvNzYognPSeBIOSzQXRu5w96V0aY8y8A==} engines: {node: ^12.20.0 || >=14.13.1} has-flag@4.0.0: @@ -4272,6 +4337,10 @@ packages: resolution: {integrity: sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==} engines: {node: '>=0.10'} + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} @@ -4395,10 +4464,6 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} - hasBin: true - jiti@2.7.0: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true @@ -4507,6 +4572,9 @@ packages: linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + linkify-it@5.0.2: + resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==} + lit-element@4.2.2: resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} @@ -4516,6 +4584,9 @@ packages: lit@3.3.2: resolution: {integrity: sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==} + lit@3.3.3: + resolution: {integrity: sha512-fycuvZg/hkpozL00lm1pEJH5nN/lr9ZXd6mJI2HSN4+Bzc+LDNdEApJ6HFbPkdFNHLvOplIIuJvxkS4XUxqirw==} + lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} @@ -4604,6 +4675,10 @@ packages: resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} hasBin: true + markdown-it@14.3.0: + resolution: {integrity: sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==} + hasBin: true + marked@17.0.3: resolution: {integrity: sha512-jt1v2ObpyOKR8p4XaUJVk3YWRJ5n+i4+rjQopxvV32rSndTJXvIzuUdWWIy/1pFQMkQmvTXawzDNqOH/CUmx6A==} engines: {node: '>= 20'} @@ -4842,7 +4917,7 @@ packages: hasBin: true peerDependencies: ws: ^8.18.0 - zod: ^3.25 || ^4.0 + zod: 4.4.3 peerDependenciesMeta: ws: optional: true @@ -4854,7 +4929,7 @@ packages: hasBin: true peerDependencies: ws: ^8.18.0 - zod: ^3.25 || ^4.0 + zod: 4.4.3 peerDependenciesMeta: ws: optional: true @@ -4881,15 +4956,18 @@ packages: resolution: {integrity: sha512-XJsFIQwnYJgXFlNDz2MncQMWYxwnfy4BCy73mdiFN/P13gEZrAfBU4Jmz2XXFf9UG0wPILdi7hYa6t0KmKQLhw==} hasBin: true - oxlint@1.50.0: - resolution: {integrity: sha512-iSJ4IZEICBma8cZX7kxIIz9PzsYLF2FaLAYN6RKu7VwRVKdu7RIgpP99bTZaGl//Yao7fsaGZLSEo5xBrI5ReQ==} + oxlint@1.73.0: + resolution: {integrity: sha512-u91G9TJzU6yqKWNZUYprQB07W7YvntZXaRxQ6CkoytepYhLWUXWsr1M8zUJ34VatNPuUAr3Z8GH+O2A331CluQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - oxlint-tsgolint: '>=0.14.1' + oxlint-tsgolint: '>=0.24.0' + vite-plus: '*' peerDependenciesMeta: oxlint-tsgolint: optional: true + vite-plus: + optional: true p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} @@ -4951,10 +5029,6 @@ packages: partial-json@0.1.7: resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} - path-expression-matcher@1.2.0: - resolution: {integrity: sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ==} - engines: {node: '>=14.0.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -5091,6 +5165,10 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + psl@1.15.0: resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} @@ -5272,6 +5350,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + send@0.19.2: resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} engines: {node: '>= 0.8.0'} @@ -5422,6 +5505,9 @@ packages: std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.2.0: + resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} + stdin-discarder@0.3.1: resolution: {integrity: sha512-reExS1kSGoElkextOcPkel4NE99S0BWxjUHQeDFnR8S993JxpPX7KU4MNmO19NXhlJp+8dmdCbKQVNgLJh2teA==} engines: {node: '>=18'} @@ -5479,9 +5565,6 @@ packages: strip-literal@3.1.0: resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} - strnum@2.2.2: - resolution: {integrity: sha512-DnR90I+jtXNSTXWdwrEy9FakW7UX+qUZg28gj5fk2vxxl7uS/3bpI4fjFYVmdK9etptYBPNkpahuQnEwhwECqA==} - strtok3@10.3.4: resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==} engines: {node: '>=18'} @@ -5538,6 +5621,10 @@ packages: resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + tinyspy@4.0.4: resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} @@ -5600,16 +5687,16 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tslog@4.10.2: - resolution: {integrity: sha512-XuELoRpMR+sq8fuWwX7P0bcj+PRNiicOKDEb3fGNURhxWVyykCi9BNq7c4uVz7h7P0sj8qgBsr5SWS6yBClq3g==} + tslog@4.11.0: + resolution: {integrity: sha512-gBe0FTKkRpOv3DenGipjQWQe073jNd1cOLj3nYfVM0/NP29sQzAIx6kfyfTTsQOiWMC+B+tSr289lNXtu7HCmQ==} engines: {node: '>=16'} tsscmp@1.0.6: resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} engines: {node: '>=0.6.x'} - tsx@4.21.0: - resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + tsx@4.23.1: + resolution: {integrity: sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==} engines: {node: '>=18.0.0'} hasBin: true @@ -5831,6 +5918,47 @@ packages: jsdom: optional: true + vitest@4.1.10: + resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-preview': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 + '@vitest/coverage-v8': 4.1.10 + '@vitest/ui': 4.1.10 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -5886,6 +6014,18 @@ packages: utf-8-validate: optional: true + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -5925,25 +6065,22 @@ packages: zod-to-json-schema@3.25.1: resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} peerDependencies: - zod: ^3.25 || ^4 - - zod@3.25.75: - resolution: {integrity: sha512-OhpzAmVzabPOL6C3A3gpAifqr9MqihV/Msx3gor2b2kviCgcb+HM9SEOpMWwwNp9MRunWnhtAKUoo0AHhjyPPg==} + zod: 4.4.3 - zod@4.3.6: - resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} snapshots: - '@agentclientprotocol/sdk@0.14.1(zod@4.3.6)': + '@agentclientprotocol/sdk@0.14.1(zod@4.4.3)': dependencies: - zod: 4.3.6 + zod: 4.4.3 - '@anthropic-ai/sdk@0.91.1(zod@4.3.6)': + '@anthropic-ai/sdk@0.91.1(zod@4.4.3)': dependencies: json-schema-to-ts: 3.1.1 optionalDependencies: - zod: 4.3.6 + zod: 4.4.3 '@aws-crypto/crc32@5.2.0': dependencies: @@ -5956,7 +6093,7 @@ snapshots: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.13 '@aws-sdk/util-locate-window': 3.965.4 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -5964,7 +6101,7 @@ snapshots: '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.13 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -5973,7 +6110,7 @@ snapshots: '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.13 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -5990,69 +6127,20 @@ snapshots: '@aws-sdk/types': 3.973.13 '@smithy/core': 3.26.0 '@smithy/fetch-http-handler': 5.5.2 - '@smithy/node-http-handler': 4.7.3 + '@smithy/node-http-handler': 4.8.2 '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/client-bedrock@3.1019.0': + '@aws-sdk/client-bedrock@3.1085.0': dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.25 - '@aws-sdk/credential-provider-node': 3.972.27 - '@aws-sdk/middleware-host-header': 3.972.8 - '@aws-sdk/middleware-logger': 3.972.8 - '@aws-sdk/middleware-recursion-detection': 3.972.9 - '@aws-sdk/middleware-user-agent': 3.972.26 - '@aws-sdk/region-config-resolver': 3.972.10 - '@aws-sdk/token-providers': 3.1019.0 - '@aws-sdk/types': 3.973.6 - '@aws-sdk/util-endpoints': 3.996.5 - '@aws-sdk/util-user-agent-browser': 3.972.8 - '@aws-sdk/util-user-agent-node': 3.973.12 - '@smithy/config-resolver': 4.4.13 - '@smithy/core': 3.23.12 - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/hash-node': 4.2.12 - '@smithy/invalid-dependency': 4.2.12 - '@smithy/middleware-content-length': 4.2.12 - '@smithy/middleware-endpoint': 4.4.27 - '@smithy/middleware-retry': 4.4.44 - '@smithy/middleware-serde': 4.2.15 - '@smithy/middleware-stack': 4.2.12 - '@smithy/node-config-provider': 4.3.12 - '@smithy/node-http-handler': 4.5.0 - '@smithy/protocol-http': 5.3.12 - '@smithy/smithy-client': 4.12.7 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 - '@smithy/util-base64': 4.3.2 - '@smithy/util-body-length-browser': 4.2.2 - '@smithy/util-body-length-node': 4.2.3 - '@smithy/util-defaults-mode-browser': 4.3.43 - '@smithy/util-defaults-mode-node': 4.2.47 - '@smithy/util-endpoints': 3.3.3 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-retry': 4.2.12 - '@smithy/util-utf8': 4.2.2 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/core@3.973.25': - dependencies: - '@aws-sdk/types': 3.973.6 - '@aws-sdk/xml-builder': 3.972.16 - '@smithy/core': 3.23.12 - '@smithy/node-config-provider': 4.3.12 - '@smithy/property-provider': 4.2.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/signature-v4': 5.3.12 - '@smithy/smithy-client': 4.12.7 - '@smithy/types': 4.13.1 - '@smithy/util-base64': 4.3.2 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-utf8': 4.2.2 + '@aws-sdk/core': 3.975.1 + '@aws-sdk/credential-provider-node': 3.972.66 + '@aws-sdk/token-providers': 3.1085.0 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/fetch-http-handler': 5.6.5 + '@smithy/node-http-handler': 4.9.5 + '@smithy/types': 4.16.1 tslib: 2.8.1 '@aws-sdk/core@3.974.23': @@ -6066,12 +6154,15 @@ snapshots: bowser: 2.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.23': + '@aws-sdk/core@3.975.1': dependencies: - '@aws-sdk/core': 3.973.25 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.974.0 + '@aws-sdk/xml-builder': 3.972.34 + '@aws/lambda-invoke-store': 0.3.0 + '@smithy/core': 3.29.3 + '@smithy/signature-v4': 5.6.4 + '@smithy/types': 4.16.1 + bowser: 2.14.1 tslib: 2.8.1 '@aws-sdk/credential-provider-env@3.972.49': @@ -6082,17 +6173,12 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.25': - dependencies: - '@aws-sdk/core': 3.973.25 - '@aws-sdk/types': 3.973.6 - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/node-http-handler': 4.5.0 - '@smithy/property-provider': 4.2.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/smithy-client': 4.12.7 - '@smithy/types': 4.13.1 - '@smithy/util-stream': 4.5.20 + '@aws-sdk/credential-provider-env@3.972.57': + dependencies: + '@aws-sdk/core': 3.975.1 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 tslib: 2.8.1 '@aws-sdk/credential-provider-http@3.972.51': @@ -6105,24 +6191,15 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.972.26': - dependencies: - '@aws-sdk/core': 3.973.25 - '@aws-sdk/credential-provider-env': 3.972.23 - '@aws-sdk/credential-provider-http': 3.972.25 - '@aws-sdk/credential-provider-login': 3.972.26 - '@aws-sdk/credential-provider-process': 3.972.23 - '@aws-sdk/credential-provider-sso': 3.972.26 - '@aws-sdk/credential-provider-web-identity': 3.972.26 - '@aws-sdk/nested-clients': 3.996.16 - '@aws-sdk/types': 3.973.6 - '@smithy/credential-provider-imds': 4.2.12 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/credential-provider-http@3.972.59': + dependencies: + '@aws-sdk/core': 3.975.1 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/fetch-http-handler': 5.6.5 + '@smithy/node-http-handler': 4.9.5 + '@smithy/types': 4.16.1 tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt '@aws-sdk/credential-provider-ini@3.972.56': dependencies: @@ -6140,18 +6217,21 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-login@3.972.26': - dependencies: - '@aws-sdk/core': 3.973.25 - '@aws-sdk/nested-clients': 3.996.16 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/credential-provider-ini@3.973.1': + dependencies: + '@aws-sdk/core': 3.975.1 + '@aws-sdk/credential-provider-env': 3.972.57 + '@aws-sdk/credential-provider-http': 3.972.59 + '@aws-sdk/credential-provider-login': 3.972.63 + '@aws-sdk/credential-provider-process': 3.972.57 + '@aws-sdk/credential-provider-sso': 3.973.1 + '@aws-sdk/credential-provider-web-identity': 3.972.63 + '@aws-sdk/nested-clients': 3.997.31 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/credential-provider-imds': 4.4.8 + '@smithy/types': 4.16.1 tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt '@aws-sdk/credential-provider-login@3.972.55': dependencies: @@ -6162,22 +6242,14 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-node@3.972.27': - dependencies: - '@aws-sdk/credential-provider-env': 3.972.23 - '@aws-sdk/credential-provider-http': 3.972.25 - '@aws-sdk/credential-provider-ini': 3.972.26 - '@aws-sdk/credential-provider-process': 3.972.23 - '@aws-sdk/credential-provider-sso': 3.972.26 - '@aws-sdk/credential-provider-web-identity': 3.972.26 - '@aws-sdk/types': 3.973.6 - '@smithy/credential-provider-imds': 4.2.12 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/credential-provider-login@3.972.63': + dependencies: + '@aws-sdk/core': 3.975.1 + '@aws-sdk/nested-clients': 3.997.31 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt '@aws-sdk/credential-provider-node@3.972.58': dependencies: @@ -6193,13 +6265,18 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-process@3.972.23': - dependencies: - '@aws-sdk/core': 3.973.25 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/credential-provider-node@3.972.66': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.57 + '@aws-sdk/credential-provider-http': 3.972.59 + '@aws-sdk/credential-provider-ini': 3.973.1 + '@aws-sdk/credential-provider-process': 3.972.57 + '@aws-sdk/credential-provider-sso': 3.973.1 + '@aws-sdk/credential-provider-web-identity': 3.972.63 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/credential-provider-imds': 4.4.8 + '@smithy/types': 4.16.1 tslib: 2.8.1 '@aws-sdk/credential-provider-process@3.972.49': @@ -6210,18 +6287,13 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.972.26': + '@aws-sdk/credential-provider-process@3.972.57': dependencies: - '@aws-sdk/core': 3.973.25 - '@aws-sdk/nested-clients': 3.996.16 - '@aws-sdk/token-providers': 3.1019.0 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.975.1 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt '@aws-sdk/credential-provider-sso@3.972.55': dependencies: @@ -6233,17 +6305,15 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-web-identity@3.972.26': + '@aws-sdk/credential-provider-sso@3.973.1': dependencies: - '@aws-sdk/core': 3.973.25 - '@aws-sdk/nested-clients': 3.996.16 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.975.1 + '@aws-sdk/nested-clients': 3.997.31 + '@aws-sdk/token-providers': 3.1083.0 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt '@aws-sdk/credential-provider-web-identity@3.972.55': dependencies: @@ -6254,6 +6324,15 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 + '@aws-sdk/credential-provider-web-identity@3.972.63': + dependencies: + '@aws-sdk/core': 3.975.1 + '@aws-sdk/nested-clients': 3.997.31 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 + tslib: 2.8.1 + '@aws-sdk/eventstream-handler-node@3.972.22': dependencies: '@aws-sdk/types': 3.973.13 @@ -6268,38 +6347,6 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/middleware-host-header@3.972.8': - dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@aws-sdk/middleware-logger@3.972.8': - dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@aws-sdk/middleware-recursion-detection@3.972.9': - dependencies: - '@aws-sdk/types': 3.973.6 - '@aws/lambda-invoke-store': 0.2.4 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@aws-sdk/middleware-user-agent@3.972.26': - dependencies: - '@aws-sdk/core': 3.973.25 - '@aws-sdk/types': 3.973.6 - '@aws-sdk/util-endpoints': 3.996.5 - '@smithy/core': 3.23.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - '@smithy/util-retry': 4.2.12 - tslib: 2.8.1 - '@aws-sdk/middleware-websocket@3.972.31': dependencies: '@aws-sdk/core': 3.974.23 @@ -6310,49 +6357,6 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.996.16': - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.25 - '@aws-sdk/middleware-host-header': 3.972.8 - '@aws-sdk/middleware-logger': 3.972.8 - '@aws-sdk/middleware-recursion-detection': 3.972.9 - '@aws-sdk/middleware-user-agent': 3.972.26 - '@aws-sdk/region-config-resolver': 3.972.10 - '@aws-sdk/types': 3.973.6 - '@aws-sdk/util-endpoints': 3.996.5 - '@aws-sdk/util-user-agent-browser': 3.972.8 - '@aws-sdk/util-user-agent-node': 3.973.12 - '@smithy/config-resolver': 4.4.13 - '@smithy/core': 3.23.12 - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/hash-node': 4.2.12 - '@smithy/invalid-dependency': 4.2.12 - '@smithy/middleware-content-length': 4.2.12 - '@smithy/middleware-endpoint': 4.4.27 - '@smithy/middleware-retry': 4.4.44 - '@smithy/middleware-serde': 4.2.15 - '@smithy/middleware-stack': 4.2.12 - '@smithy/node-config-provider': 4.3.12 - '@smithy/node-http-handler': 4.5.0 - '@smithy/protocol-http': 5.3.12 - '@smithy/smithy-client': 4.12.7 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 - '@smithy/util-base64': 4.3.2 - '@smithy/util-body-length-browser': 4.2.2 - '@smithy/util-body-length-node': 4.2.3 - '@smithy/util-defaults-mode-browser': 4.3.43 - '@smithy/util-defaults-mode-node': 4.2.47 - '@smithy/util-endpoints': 3.3.3 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-retry': 4.2.12 - '@smithy/util-utf8': 4.2.2 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - '@aws-sdk/nested-clients@3.997.23': dependencies: '@aws-crypto/sha256-browser': 5.2.0 @@ -6366,12 +6370,15 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/region-config-resolver@3.972.10': + '@aws-sdk/nested-clients@3.997.31': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/config-resolver': 4.4.13 - '@smithy/node-config-provider': 4.3.12 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.975.1 + '@aws-sdk/signature-v4-multi-region': 3.996.39 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/fetch-http-handler': 5.6.5 + '@smithy/node-http-handler': 4.9.5 + '@smithy/types': 4.16.1 tslib: 2.8.1 '@aws-sdk/signature-v4-multi-region@3.996.35': @@ -6381,17 +6388,12 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.1019.0': + '@aws-sdk/signature-v4-multi-region@3.996.39': dependencies: - '@aws-sdk/core': 3.973.25 - '@aws-sdk/nested-clients': 3.996.16 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.974.0 + '@smithy/signature-v4': 5.6.4 + '@smithy/types': 4.16.1 tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt '@aws-sdk/token-providers@3.1048.0': dependencies: @@ -6411,57 +6413,52 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/types@3.973.13': - dependencies: - '@smithy/types': 4.15.0 - tslib: 2.8.1 - - '@aws-sdk/types@3.973.6': + '@aws-sdk/token-providers@3.1083.0': dependencies: - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.975.1 + '@aws-sdk/nested-clients': 3.997.31 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.996.5': + '@aws-sdk/token-providers@3.1085.0': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 - '@smithy/util-endpoints': 3.3.3 + '@aws-sdk/core': 3.975.1 + '@aws-sdk/nested-clients': 3.997.31 + '@aws-sdk/types': 3.974.0 + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 tslib: 2.8.1 - '@aws-sdk/util-locate-window@3.965.4': + '@aws-sdk/types@3.973.13': dependencies: + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/util-user-agent-browser@3.972.8': + '@aws-sdk/types@3.974.0': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/types': 4.13.1 - bowser: 2.14.1 + '@smithy/types': 4.16.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.973.12': + '@aws-sdk/util-locate-window@3.965.4': dependencies: - '@aws-sdk/middleware-user-agent': 3.972.26 - '@aws-sdk/types': 3.973.6 - '@smithy/node-config-provider': 4.3.12 - '@smithy/types': 4.13.1 - '@smithy/util-config-provider': 4.2.2 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.972.16': + '@aws-sdk/xml-builder@3.972.31': dependencies: - '@smithy/types': 4.13.1 - fast-xml-parser: 5.5.9 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.972.31': + '@aws-sdk/xml-builder@3.972.34': dependencies: - '@smithy/types': 4.15.0 + '@smithy/types': 4.16.1 tslib: 2.8.1 '@aws/lambda-invoke-store@0.2.4': {} + '@aws/lambda-invoke-store@0.3.0': {} + '@azure/abort-controller@2.1.2': dependencies: tslib: 2.8.1 @@ -6569,15 +6566,16 @@ snapshots: hashery: 1.5.0 keyv: 5.6.0 - '@clack/core@1.0.1': + '@clack/core@1.4.3': dependencies: - picocolors: 1.1.1 + fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 - '@clack/prompts@1.0.1': + '@clack/prompts@1.7.0': dependencies: - '@clack/core': 1.0.1 - picocolors: 1.1.1 + '@clack/core': 1.4.3 + fast-string-width: 3.0.2 + fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 '@cloudflare/workers-types@4.20260120.0': @@ -6621,13 +6619,13 @@ snapshots: '@d-fischer/connection@9.0.0': dependencies: - '@d-fischer/isomorphic-ws': 7.0.2(ws@8.19.0) + '@d-fischer/isomorphic-ws': 7.0.2(ws@8.21.0) '@d-fischer/logger': 4.2.4 '@d-fischer/shared-utils': 3.6.4 '@d-fischer/typed-event-emitter': 3.3.3 '@types/ws': 8.18.1 tslib: 2.8.1 - ws: 8.19.0 + ws: 8.21.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -6638,9 +6636,9 @@ snapshots: '@d-fischer/escape-string-regexp@5.0.0': {} - '@d-fischer/isomorphic-ws@7.0.2(ws@8.19.0)': + '@d-fischer/isomorphic-ws@7.0.2(ws@8.21.0)': dependencies: - ws: 8.19.0 + ws: 8.21.0 '@d-fischer/logger@4.2.4': dependencies: @@ -6668,7 +6666,7 @@ snapshots: discord-api-types: 0.38.40 prism-media: 1.3.5(opusscript@0.0.8) tslib: 2.8.1 - ws: 8.19.0 + ws: 8.21.0 transitivePeerDependencies: - '@discordjs/opus' - bufferutil @@ -6677,9 +6675,9 @@ snapshots: - opusscript - utf-8-validate - '@earendil-works/pi-agent-core@0.80.2(ws@8.19.0)(zod@4.3.6)': + '@earendil-works/pi-agent-core@0.80.6(ws@8.21.0)(zod@4.4.3)': dependencies: - '@earendil-works/pi-ai': 0.80.2(ws@8.19.0)(zod@4.3.6) + '@earendil-works/pi-ai': 0.80.6(ws@8.21.0)(zod@4.4.3) ignore: 7.0.5 typebox: 1.1.38 yaml: 2.8.3 @@ -6691,9 +6689,9 @@ snapshots: - ws - zod - '@earendil-works/pi-ai@0.80.2(ws@8.19.0)(zod@4.3.6)': + '@earendil-works/pi-ai@0.80.6(ws@8.21.0)(zod@4.4.3)': dependencies: - '@anthropic-ai/sdk': 0.91.1(zod@4.3.6) + '@anthropic-ai/sdk': 0.91.1(zod@4.4.3) '@aws-sdk/client-bedrock-runtime': 3.1048.0 '@google/genai': 1.52.0 '@mistralai/mistralai': 2.2.6(@opentelemetry/api@1.9.0) @@ -6701,7 +6699,7 @@ snapshots: '@smithy/node-http-handler': 4.7.3 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 - openai: 6.26.0(ws@8.19.0)(zod@4.3.6) + openai: 6.26.0(ws@8.21.0)(zod@4.4.3) partial-json: 0.1.7 typebox: 1.1.38 transitivePeerDependencies: @@ -6712,11 +6710,11 @@ snapshots: - ws - zod - '@earendil-works/pi-coding-agent@0.80.2(ws@8.19.0)(zod@4.3.6)': + '@earendil-works/pi-coding-agent@0.80.6(ws@8.21.0)(zod@4.4.3)': dependencies: - '@earendil-works/pi-agent-core': 0.80.2(ws@8.19.0)(zod@4.3.6) - '@earendil-works/pi-ai': 0.80.2(ws@8.19.0)(zod@4.3.6) - '@earendil-works/pi-tui': 0.80.2 + '@earendil-works/pi-agent-core': 0.80.6(ws@8.21.0)(zod@4.4.3) + '@earendil-works/pi-ai': 0.80.6(ws@8.21.0)(zod@4.4.3) + '@earendil-works/pi-tui': 0.80.6 '@silvia-odwyer/photon-node': 0.3.4 chalk: 5.6.2 cross-spawn: 7.0.6 @@ -6742,7 +6740,7 @@ snapshots: - ws - zod - '@earendil-works/pi-tui@0.80.2': + '@earendil-works/pi-tui@0.80.6': dependencies: get-east-asian-width: 1.6.0 marked: 18.0.5 @@ -6769,178 +6767,256 @@ snapshots: '@esbuild/aix-ppc64@0.27.3': optional: true + '@esbuild/aix-ppc64@0.28.1': + optional: true + '@esbuild/android-arm64@0.25.12': optional: true '@esbuild/android-arm64@0.27.3': optional: true + '@esbuild/android-arm64@0.28.1': + optional: true + '@esbuild/android-arm@0.25.12': optional: true '@esbuild/android-arm@0.27.3': optional: true + '@esbuild/android-arm@0.28.1': + optional: true + '@esbuild/android-x64@0.25.12': optional: true '@esbuild/android-x64@0.27.3': optional: true + '@esbuild/android-x64@0.28.1': + optional: true + '@esbuild/darwin-arm64@0.25.12': optional: true '@esbuild/darwin-arm64@0.27.3': optional: true + '@esbuild/darwin-arm64@0.28.1': + optional: true + '@esbuild/darwin-x64@0.25.12': optional: true '@esbuild/darwin-x64@0.27.3': optional: true + '@esbuild/darwin-x64@0.28.1': + optional: true + '@esbuild/freebsd-arm64@0.25.12': optional: true '@esbuild/freebsd-arm64@0.27.3': optional: true + '@esbuild/freebsd-arm64@0.28.1': + optional: true + '@esbuild/freebsd-x64@0.25.12': optional: true '@esbuild/freebsd-x64@0.27.3': optional: true + '@esbuild/freebsd-x64@0.28.1': + optional: true + '@esbuild/linux-arm64@0.25.12': optional: true '@esbuild/linux-arm64@0.27.3': optional: true + '@esbuild/linux-arm64@0.28.1': + optional: true + '@esbuild/linux-arm@0.25.12': optional: true '@esbuild/linux-arm@0.27.3': optional: true + '@esbuild/linux-arm@0.28.1': + optional: true + '@esbuild/linux-ia32@0.25.12': optional: true '@esbuild/linux-ia32@0.27.3': optional: true + '@esbuild/linux-ia32@0.28.1': + optional: true + '@esbuild/linux-loong64@0.25.12': optional: true '@esbuild/linux-loong64@0.27.3': optional: true + '@esbuild/linux-loong64@0.28.1': + optional: true + '@esbuild/linux-mips64el@0.25.12': optional: true '@esbuild/linux-mips64el@0.27.3': optional: true + '@esbuild/linux-mips64el@0.28.1': + optional: true + '@esbuild/linux-ppc64@0.25.12': optional: true '@esbuild/linux-ppc64@0.27.3': optional: true + '@esbuild/linux-ppc64@0.28.1': + optional: true + '@esbuild/linux-riscv64@0.25.12': optional: true '@esbuild/linux-riscv64@0.27.3': optional: true + '@esbuild/linux-riscv64@0.28.1': + optional: true + '@esbuild/linux-s390x@0.25.12': optional: true '@esbuild/linux-s390x@0.27.3': optional: true + '@esbuild/linux-s390x@0.28.1': + optional: true + '@esbuild/linux-x64@0.25.12': optional: true '@esbuild/linux-x64@0.27.3': optional: true + '@esbuild/linux-x64@0.28.1': + optional: true + '@esbuild/netbsd-arm64@0.25.12': optional: true '@esbuild/netbsd-arm64@0.27.3': optional: true + '@esbuild/netbsd-arm64@0.28.1': + optional: true + '@esbuild/netbsd-x64@0.25.12': optional: true '@esbuild/netbsd-x64@0.27.3': optional: true + '@esbuild/netbsd-x64@0.28.1': + optional: true + '@esbuild/openbsd-arm64@0.25.12': optional: true '@esbuild/openbsd-arm64@0.27.3': optional: true + '@esbuild/openbsd-arm64@0.28.1': + optional: true + '@esbuild/openbsd-x64@0.25.12': optional: true '@esbuild/openbsd-x64@0.27.3': optional: true + '@esbuild/openbsd-x64@0.28.1': + optional: true + '@esbuild/openharmony-arm64@0.25.12': optional: true '@esbuild/openharmony-arm64@0.27.3': optional: true + '@esbuild/openharmony-arm64@0.28.1': + optional: true + '@esbuild/sunos-x64@0.25.12': optional: true '@esbuild/sunos-x64@0.27.3': optional: true + '@esbuild/sunos-x64@0.28.1': + optional: true + '@esbuild/win32-arm64@0.25.12': optional: true '@esbuild/win32-arm64@0.27.3': optional: true + '@esbuild/win32-arm64@0.28.1': + optional: true + '@esbuild/win32-ia32@0.25.12': optional: true '@esbuild/win32-ia32@0.27.3': optional: true + '@esbuild/win32-ia32@0.28.1': + optional: true + '@esbuild/win32-x64@0.25.12': optional: true '@esbuild/win32-x64@0.27.3': optional: true + '@esbuild/win32-x64@0.28.1': + optional: true + '@google/genai@1.52.0': dependencies: google-auth-library: 10.6.1 p-retry: 4.6.2 - protobufjs: 7.5.4 - ws: 8.19.0 + protobufjs: 7.6.4 + ws: 8.21.0 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - '@grammyjs/runner@2.0.3(grammy@1.40.0)': + '@grammyjs/runner@2.0.3(grammy@1.44.0)': dependencies: abort-controller: 3.0.0 - grammy: 1.40.0 + grammy: 1.44.0 - '@grammyjs/transformer-throttler@1.2.1(grammy@1.40.0)': + '@grammyjs/transformer-throttler@1.2.1(grammy@1.44.0)': dependencies: bottleneck: 2.19.5 - grammy: 1.40.0 + grammy: 1.44.0 - '@grammyjs/types@3.24.0': {} + '@grammyjs/types@3.28.0': {} '@grpc/grpc-js@1.14.3': dependencies: @@ -6960,7 +7036,7 @@ snapshots: '@hapi/hoek@9.3.0': {} - '@homebridge/ciao@1.3.5': + '@homebridge/ciao@1.3.10': dependencies: debug: 4.4.3 fast-deep-equal: 3.1.3 @@ -7177,7 +7253,7 @@ snapshots: lodash.pickby: 4.6.0 protobufjs: 7.5.4 qs: 6.14.2 - ws: 8.19.0 + ws: 8.21.0 transitivePeerDependencies: - bufferutil - debug @@ -7193,7 +7269,7 @@ snapshots: '@lit-labs/signals@0.2.0': dependencies: - lit: 3.3.2 + lit: 3.3.3 signal-polyfill: 0.2.2 '@lit-labs/ssr-dom-shim@1.5.1': {} @@ -7288,7 +7364,7 @@ snapshots: dependencies: debug: 4.4.3 uuid: 11.1.0 - zod: 3.25.75 + zod: 4.4.3 transitivePeerDependencies: - supports-color @@ -7301,7 +7377,7 @@ snapshots: jsonwebtoken: 9.0.3 jwks-rsa: 3.2.2 object-path: 0.11.8 - zod: 3.25.75 + zod: 4.4.3 transitivePeerDependencies: - debug - supports-color @@ -7309,9 +7385,9 @@ snapshots: '@mistralai/mistralai@2.2.6(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/semantic-conventions': 1.41.1 - ws: 8.19.0 - zod: 4.3.6 - zod-to-json-schema: 3.25.1(zod@4.3.6) + ws: 8.21.0 + zod: 4.4.3 + zod-to-json-schema: 3.25.1(zod@4.4.3) optionalDependencies: '@opentelemetry/api': 1.9.0 transitivePeerDependencies: @@ -7380,10 +7456,16 @@ snapshots: dependencies: '@noble/hashes': 2.0.1 + '@noble/curves@2.2.0': + dependencies: + '@noble/hashes': 2.2.0 + '@noble/ed25519@3.0.0': {} '@noble/hashes@2.0.1': {} + '@noble/hashes@2.2.0': {} + '@node-llama-cpp/linux-arm64@3.17.1': optional: true @@ -7750,61 +7832,61 @@ snapshots: '@oxlint-tsgolint/win32-x64@0.14.2': optional: true - '@oxlint/binding-android-arm-eabi@1.50.0': + '@oxlint/binding-android-arm-eabi@1.73.0': optional: true - '@oxlint/binding-android-arm64@1.50.0': + '@oxlint/binding-android-arm64@1.73.0': optional: true - '@oxlint/binding-darwin-arm64@1.50.0': + '@oxlint/binding-darwin-arm64@1.73.0': optional: true - '@oxlint/binding-darwin-x64@1.50.0': + '@oxlint/binding-darwin-x64@1.73.0': optional: true - '@oxlint/binding-freebsd-x64@1.50.0': + '@oxlint/binding-freebsd-x64@1.73.0': optional: true - '@oxlint/binding-linux-arm-gnueabihf@1.50.0': + '@oxlint/binding-linux-arm-gnueabihf@1.73.0': optional: true - '@oxlint/binding-linux-arm-musleabihf@1.50.0': + '@oxlint/binding-linux-arm-musleabihf@1.73.0': optional: true - '@oxlint/binding-linux-arm64-gnu@1.50.0': + '@oxlint/binding-linux-arm64-gnu@1.73.0': optional: true - '@oxlint/binding-linux-arm64-musl@1.50.0': + '@oxlint/binding-linux-arm64-musl@1.73.0': optional: true - '@oxlint/binding-linux-ppc64-gnu@1.50.0': + '@oxlint/binding-linux-ppc64-gnu@1.73.0': optional: true - '@oxlint/binding-linux-riscv64-gnu@1.50.0': + '@oxlint/binding-linux-riscv64-gnu@1.73.0': optional: true - '@oxlint/binding-linux-riscv64-musl@1.50.0': + '@oxlint/binding-linux-riscv64-musl@1.73.0': optional: true - '@oxlint/binding-linux-s390x-gnu@1.50.0': + '@oxlint/binding-linux-s390x-gnu@1.73.0': optional: true - '@oxlint/binding-linux-x64-gnu@1.50.0': + '@oxlint/binding-linux-x64-gnu@1.73.0': optional: true - '@oxlint/binding-linux-x64-musl@1.50.0': + '@oxlint/binding-linux-x64-musl@1.73.0': optional: true - '@oxlint/binding-openharmony-arm64@1.50.0': + '@oxlint/binding-openharmony-arm64@1.73.0': optional: true - '@oxlint/binding-win32-arm64-msvc@1.50.0': + '@oxlint/binding-win32-arm64-msvc@1.73.0': optional: true - '@oxlint/binding-win32-ia32-msvc@1.50.0': + '@oxlint/binding-win32-ia32-msvc@1.73.0': optional: true - '@oxlint/binding-win32-x64-msvc@1.50.0': + '@oxlint/binding-win32-x64-msvc@1.73.0': optional: true '@pinojs/redact@0.4.0': {} @@ -8027,13 +8109,13 @@ snapshots: '@sinclair/typebox@0.34.48': {} - '@slack/bolt@4.6.0(@types/express@5.0.6)': + '@slack/bolt@4.7.3(@types/express@5.0.6)': dependencies: - '@slack/logger': 4.0.0 - '@slack/oauth': 3.0.4 - '@slack/socket-mode': 2.0.5 - '@slack/types': 2.20.0 - '@slack/web-api': 7.14.1 + '@slack/logger': 4.0.1 + '@slack/oauth': 3.0.5 + '@slack/socket-mode': 2.0.7 + '@slack/types': 2.22.0 + '@slack/web-api': 7.19.0 '@types/express': 5.0.6 axios: 1.13.5 express: 5.2.1 @@ -8046,42 +8128,44 @@ snapshots: - supports-color - utf-8-validate - '@slack/logger@4.0.0': + '@slack/logger@4.0.1': dependencies: '@types/node': 25.3.0 - '@slack/oauth@3.0.4': + '@slack/oauth@3.0.5': dependencies: - '@slack/logger': 4.0.0 - '@slack/web-api': 7.14.1 + '@slack/logger': 4.0.1 + '@slack/web-api': 7.19.0 '@types/jsonwebtoken': 9.0.10 '@types/node': 25.3.0 jsonwebtoken: 9.0.3 transitivePeerDependencies: - debug + - supports-color - '@slack/socket-mode@2.0.5': + '@slack/socket-mode@2.0.7': dependencies: - '@slack/logger': 4.0.0 - '@slack/web-api': 7.14.1 + '@slack/logger': 4.0.1 + '@slack/web-api': 7.19.0 '@types/node': 25.3.0 '@types/ws': 8.18.1 eventemitter3: 5.0.4 - ws: 8.19.0 + ws: 8.21.0 transitivePeerDependencies: - bufferutil - debug + - supports-color - utf-8-validate - '@slack/types@2.20.0': {} + '@slack/types@2.22.0': {} - '@slack/web-api@7.14.1': + '@slack/web-api@7.19.0': dependencies: - '@slack/logger': 4.0.0 - '@slack/types': 2.20.0 + '@slack/logger': 4.0.1 + '@slack/types': 2.22.0 '@types/node': 25.3.0 '@types/retry': 0.12.0 - axios: 1.13.5 + axios: 1.18.1 eventemitter3: 5.0.4 form-data: 2.5.4 is-electron: 2.2.2 @@ -8091,33 +8175,7 @@ snapshots: retry: 0.13.1 transitivePeerDependencies: - debug - - '@smithy/abort-controller@4.2.12': - dependencies: - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/config-resolver@4.4.13': - dependencies: - '@smithy/node-config-provider': 4.3.12 - '@smithy/types': 4.13.1 - '@smithy/util-config-provider': 4.2.2 - '@smithy/util-endpoints': 3.3.3 - '@smithy/util-middleware': 4.2.12 - tslib: 2.8.1 - - '@smithy/core@3.23.12': - dependencies: - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 - '@smithy/util-base64': 4.3.2 - '@smithy/util-body-length-browser': 4.2.2 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-stream': 4.5.20 - '@smithy/util-utf8': 4.2.2 - '@smithy/uuid': 1.1.2 - tslib: 2.8.1 + - supports-color '@smithy/core@3.26.0': dependencies: @@ -8125,12 +8183,9 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.2.12': + '@smithy/core@3.29.3': dependencies: - '@smithy/node-config-provider': 4.3.12 - '@smithy/property-provider': 4.2.12 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 + '@smithy/types': 4.16.1 tslib: 2.8.1 '@smithy/credential-provider-imds@4.4.2': @@ -8139,12 +8194,10 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.3.15': + '@smithy/credential-provider-imds@4.4.8': dependencies: - '@smithy/protocol-http': 5.3.12 - '@smithy/querystring-builder': 4.2.12 - '@smithy/types': 4.13.1 - '@smithy/util-base64': 4.3.2 + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 tslib: 2.8.1 '@smithy/fetch-http-handler@5.5.2': @@ -8153,82 +8206,16 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@smithy/hash-node@4.2.12': - dependencies: - '@smithy/types': 4.13.1 - '@smithy/util-buffer-from': 4.2.2 - '@smithy/util-utf8': 4.2.2 - tslib: 2.8.1 - - '@smithy/invalid-dependency@4.2.12': + '@smithy/fetch-http-handler@5.6.5': dependencies: - '@smithy/types': 4.13.1 + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': dependencies: tslib: 2.8.1 - '@smithy/is-array-buffer@4.2.2': - dependencies: - tslib: 2.8.1 - - '@smithy/middleware-content-length@4.2.12': - dependencies: - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/middleware-endpoint@4.4.27': - dependencies: - '@smithy/core': 3.23.12 - '@smithy/middleware-serde': 4.2.15 - '@smithy/node-config-provider': 4.3.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 - '@smithy/util-middleware': 4.2.12 - tslib: 2.8.1 - - '@smithy/middleware-retry@4.4.44': - dependencies: - '@smithy/node-config-provider': 4.3.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/service-error-classification': 4.2.12 - '@smithy/smithy-client': 4.12.7 - '@smithy/types': 4.13.1 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-retry': 4.2.12 - '@smithy/uuid': 1.1.2 - tslib: 2.8.1 - - '@smithy/middleware-serde@4.2.15': - dependencies: - '@smithy/core': 3.23.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/middleware-stack@4.2.12': - dependencies: - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/node-config-provider@4.3.12': - dependencies: - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/node-http-handler@4.5.0': - dependencies: - '@smithy/abort-controller': 4.2.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/querystring-builder': 4.2.12 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - '@smithy/node-http-handler@4.7.3': dependencies: '@smithy/core': 3.26.0 @@ -8241,45 +8228,10 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@smithy/property-provider@4.2.12': - dependencies: - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/protocol-http@5.3.12': - dependencies: - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/querystring-builder@4.2.12': - dependencies: - '@smithy/types': 4.13.1 - '@smithy/util-uri-escape': 4.2.2 - tslib: 2.8.1 - - '@smithy/querystring-parser@4.2.12': - dependencies: - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/service-error-classification@4.2.12': - dependencies: - '@smithy/types': 4.13.1 - - '@smithy/shared-ini-file-loader@4.4.7': - dependencies: - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/signature-v4@5.3.12': + '@smithy/node-http-handler@4.9.5': dependencies: - '@smithy/is-array-buffer': 4.2.2 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - '@smithy/util-hex-encoding': 4.2.2 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-uri-escape': 4.2.2 - '@smithy/util-utf8': 4.2.2 + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 tslib: 2.8.1 '@smithy/signature-v4@5.5.2': @@ -8288,41 +8240,17 @@ snapshots: '@smithy/types': 4.15.0 tslib: 2.8.1 - '@smithy/smithy-client@4.12.7': - dependencies: - '@smithy/core': 3.23.12 - '@smithy/middleware-endpoint': 4.4.27 - '@smithy/middleware-stack': 4.2.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - '@smithy/util-stream': 4.5.20 - tslib: 2.8.1 - - '@smithy/types@4.13.1': + '@smithy/signature-v4@5.6.4': dependencies: + '@smithy/core': 3.29.3 + '@smithy/types': 4.16.1 tslib: 2.8.1 '@smithy/types@4.15.0': dependencies: tslib: 2.8.1 - '@smithy/url-parser@4.2.12': - dependencies: - '@smithy/querystring-parser': 4.2.12 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/util-base64@4.3.2': - dependencies: - '@smithy/util-buffer-from': 4.2.2 - '@smithy/util-utf8': 4.2.2 - tslib: 2.8.1 - - '@smithy/util-body-length-browser@4.2.2': - dependencies: - tslib: 2.8.1 - - '@smithy/util-body-length-node@4.2.3': + '@smithy/types@4.16.1': dependencies: tslib: 2.8.1 @@ -8331,82 +8259,11 @@ snapshots: '@smithy/is-array-buffer': 2.2.0 tslib: 2.8.1 - '@smithy/util-buffer-from@4.2.2': - dependencies: - '@smithy/is-array-buffer': 4.2.2 - tslib: 2.8.1 - - '@smithy/util-config-provider@4.2.2': - dependencies: - tslib: 2.8.1 - - '@smithy/util-defaults-mode-browser@4.3.43': - dependencies: - '@smithy/property-provider': 4.2.12 - '@smithy/smithy-client': 4.12.7 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/util-defaults-mode-node@4.2.47': - dependencies: - '@smithy/config-resolver': 4.4.13 - '@smithy/credential-provider-imds': 4.2.12 - '@smithy/node-config-provider': 4.3.12 - '@smithy/property-provider': 4.2.12 - '@smithy/smithy-client': 4.12.7 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/util-endpoints@3.3.3': - dependencies: - '@smithy/node-config-provider': 4.3.12 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/util-hex-encoding@4.2.2': - dependencies: - tslib: 2.8.1 - - '@smithy/util-middleware@4.2.12': - dependencies: - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/util-retry@4.2.12': - dependencies: - '@smithy/service-error-classification': 4.2.12 - '@smithy/types': 4.13.1 - tslib: 2.8.1 - - '@smithy/util-stream@4.5.20': - dependencies: - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/node-http-handler': 4.5.0 - '@smithy/types': 4.13.1 - '@smithy/util-base64': 4.3.2 - '@smithy/util-buffer-from': 4.2.2 - '@smithy/util-hex-encoding': 4.2.2 - '@smithy/util-utf8': 4.2.2 - tslib: 2.8.1 - - '@smithy/util-uri-escape@4.2.2': - dependencies: - tslib: 2.8.1 - '@smithy/util-utf8@2.3.0': dependencies: '@smithy/util-buffer-from': 2.2.0 tslib: 2.8.1 - '@smithy/util-utf8@4.2.2': - dependencies: - '@smithy/util-buffer-from': 4.2.2 - tslib: 2.8.1 - - '@smithy/uuid@1.1.2': - dependencies: - tslib: 2.8.1 - '@standard-schema/spec@1.1.0': {} '@swc/helpers@0.5.20': @@ -8683,83 +8540,49 @@ snapshots: - '@cypress/request' - supports-color - '@vitest/browser-playwright@4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18)': - dependencies: - '@vitest/browser': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) - playwright: 1.58.2 - tinyrainbow: 3.0.3 - vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - optional: true - - '@vitest/browser-playwright@4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18)': + '@vitest/browser-playwright@4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3))(vitest@4.0.18)': dependencies: - '@vitest/browser': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/browser': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3))(vitest@4.0.18) + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3)) playwright: 1.58.2 tinyrainbow: 3.0.3 - vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - - '@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18)': - dependencies: - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/utils': 4.0.18 - magic-string: 0.30.21 - pixelmatch: 7.1.0 - pngjs: 7.0.0 - sirv: 3.0.2 - tinyrainbow: 3.0.3 - vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) - ws: 8.19.0 + vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - optional: true - '@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18)': + '@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3))(vitest@4.0.18)': dependencies: - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3)) '@vitest/utils': 4.0.18 magic-string: 0.30.21 pixelmatch: 7.1.0 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.0.3 - vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) - ws: 8.19.0 + vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) + ws: 8.21.0 transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/coverage-v8@4.0.18(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18))(vitest@4.0.18)': + '@vitest/coverage-v8@4.1.10(vitest@4.1.10)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.0.18 - ast-v8-to-istanbul: 0.3.11 + '@vitest/utils': 4.1.10 + ast-v8-to-istanbul: 1.0.4 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-reports: 3.2.0 magicast: 0.5.2 obug: 2.1.1 - std-env: 3.10.0 - tinyrainbow: 3.0.3 - vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) - optionalDependencies: - '@vitest/browser': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) + std-env: 4.2.0 + tinyrainbow: 3.1.0 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/coverage-v8@4.1.10)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3)) '@vitest/expect@3.2.4': dependencies: @@ -8778,29 +8601,38 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.0.3 - '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/expect@4.1.10': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) - '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.0.18 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) - '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@4.1.10(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3))': dependencies: - '@vitest/spy': 4.0.18 + '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) '@vitest/pretty-format@3.2.4': dependencies: @@ -8810,6 +8642,10 @@ snapshots: dependencies: tinyrainbow: 3.0.3 + '@vitest/pretty-format@4.1.10': + dependencies: + tinyrainbow: 3.1.0 + '@vitest/runner@3.2.4': dependencies: '@vitest/utils': 3.2.4 @@ -8821,6 +8657,11 @@ snapshots: '@vitest/utils': 4.0.18 pathe: 2.0.3 + '@vitest/runner@4.1.10': + dependencies: + '@vitest/utils': 4.1.10 + pathe: 2.0.3 + '@vitest/snapshot@3.2.4': dependencies: '@vitest/pretty-format': 3.2.4 @@ -8833,12 +8674,21 @@ snapshots: magic-string: 0.30.21 pathe: 2.0.3 + '@vitest/snapshot@4.1.10': + dependencies: + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 + magic-string: 0.30.21 + pathe: 2.0.3 + '@vitest/spy@3.2.4': dependencies: tinyspy: 4.0.4 '@vitest/spy@4.0.18': {} + '@vitest/spy@4.1.10': {} + '@vitest/utils@3.2.4': dependencies: '@vitest/pretty-format': 3.2.4 @@ -8850,6 +8700,12 @@ snapshots: '@vitest/pretty-format': 4.0.18 tinyrainbow: 3.0.3 + '@vitest/utils@4.1.10': + dependencies: + '@vitest/pretty-format': 4.1.10 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + '@whiskeysockets/baileys@7.0.0-rc.9(sharp@0.34.5)': dependencies: '@cacheable/node-cache': 1.7.6 @@ -8862,7 +8718,7 @@ snapshots: pino: 9.14.0 protobufjs: 7.5.4 sharp: 0.34.5 - ws: 8.19.0 + ws: 8.21.0 transitivePeerDependencies: - bufferutil - supports-color @@ -8888,9 +8744,15 @@ snapshots: acorn@8.16.0: {} + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + agent-base@7.1.4: {} - ajv@8.18.0: + ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 fast-uri: 3.1.0 @@ -8949,7 +8811,7 @@ snapshots: estree-walker: 3.0.3 pathe: 2.0.3 - ast-v8-to-istanbul@0.3.11: + ast-v8-to-istanbul@1.0.4: dependencies: '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 @@ -8981,6 +8843,16 @@ snapshots: transitivePeerDependencies: - debug + axios@1.18.1: + dependencies: + follow-redirects: 1.16.0 + form-data: 2.5.4 + https-proxy-agent: 5.0.1 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + - supports-color + balanced-match@4.0.4: {} base64-js@1.5.1: {} @@ -9147,7 +9019,7 @@ snapshots: fs-extra: 11.3.4 node-api-headers: 1.8.0 rc: 1.2.8 - semver: 7.7.4 + semver: 7.8.5 tar: 7.5.11 url-join: 4.0.1 which: 6.0.1 @@ -9191,6 +9063,8 @@ snapshots: content-type@1.0.5: {} + convert-source-map@2.0.0: {} + cookie-signature@1.0.7: {} cookie-signature@1.2.2: {} @@ -9281,7 +9155,7 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 - dotenv@17.3.1: {} + dotenv@17.4.2: {} dts-resolver@2.1.3: {} @@ -9326,6 +9200,8 @@ snapshots: es-module-lexer@1.7.0: {} + es-module-lexer@2.3.1: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -9395,6 +9271,35 @@ snapshots: '@esbuild/win32-ia32': 0.27.3 '@esbuild/win32-x64': 0.27.3 + esbuild@0.28.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.1 + '@esbuild/android-arm': 0.28.1 + '@esbuild/android-arm64': 0.28.1 + '@esbuild/android-x64': 0.28.1 + '@esbuild/darwin-arm64': 0.28.1 + '@esbuild/darwin-x64': 0.28.1 + '@esbuild/freebsd-arm64': 0.28.1 + '@esbuild/freebsd-x64': 0.28.1 + '@esbuild/linux-arm': 0.28.1 + '@esbuild/linux-arm64': 0.28.1 + '@esbuild/linux-ia32': 0.28.1 + '@esbuild/linux-loong64': 0.28.1 + '@esbuild/linux-mips64el': 0.28.1 + '@esbuild/linux-ppc64': 0.28.1 + '@esbuild/linux-riscv64': 0.28.1 + '@esbuild/linux-s390x': 0.28.1 + '@esbuild/linux-x64': 0.28.1 + '@esbuild/netbsd-arm64': 0.28.1 + '@esbuild/netbsd-x64': 0.28.1 + '@esbuild/openbsd-arm64': 0.28.1 + '@esbuild/openbsd-x64': 0.28.1 + '@esbuild/openharmony-arm64': 0.28.1 + '@esbuild/sunos-x64': 0.28.1 + '@esbuild/win32-arm64': 0.28.1 + '@esbuild/win32-ia32': 0.28.1 + '@esbuild/win32-x64': 0.28.1 + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -9498,17 +9403,17 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 - fast-uri@3.1.0: {} + fast-string-truncated-width@3.0.3: {} - fast-xml-builder@1.1.4: + fast-string-width@3.0.2: dependencies: - path-expression-matcher: 1.2.0 + fast-string-truncated-width: 3.0.3 - fast-xml-parser@5.5.9: + fast-uri@3.1.0: {} + + fast-wrap-ansi@0.2.2: dependencies: - fast-xml-builder: 1.1.4 - path-expression-matcher: 1.2.0 - strnum: 2.2.2 + fast-string-width: 3.0.2 fastq@1.20.1: dependencies: @@ -9573,6 +9478,8 @@ snapshots: follow-redirects@1.15.11: {} + follow-redirects@1.16.0: {} + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 @@ -9700,9 +9607,9 @@ snapshots: graceful-fs@4.2.11: {} - grammy@1.40.0: + grammy@1.44.0: dependencies: - '@grammyjs/types': 3.24.0 + '@grammyjs/types': 3.28.0 abort-controller: 3.0.0 debug: 4.4.3 node-fetch: 2.7.0 @@ -9794,6 +9701,13 @@ snapshots: jsprim: 2.0.2 sshpk: 1.18.0 + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 @@ -9924,8 +9838,6 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 - jiti@2.6.1: {} - jiti@2.7.0: {} jose@4.15.9: {} @@ -9974,7 +9886,7 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.7.4 + semver: 7.8.5 jsprim@2.0.2: dependencies: @@ -10046,6 +9958,10 @@ snapshots: dependencies: uc.micro: 2.1.0 + linkify-it@5.0.2: + dependencies: + uc.micro: 2.1.0 + lit-element@4.2.2: dependencies: '@lit-labs/ssr-dom-shim': 1.5.1 @@ -10062,6 +9978,12 @@ snapshots: lit-element: 4.2.2 lit-html: 3.3.2 + lit@3.3.3: + dependencies: + '@lit/reactive-element': 2.1.2 + lit-element: 4.2.2 + lit-html: 3.3.2 + lodash.camelcase@4.3.0: {} lodash.clonedeep@4.5.0: {} @@ -10136,7 +10058,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.4 + semver: 7.8.5 markdown-it@14.1.1: dependencies: @@ -10147,6 +10069,15 @@ snapshots: punycode.js: 2.3.1 uc.micro: 2.1.0 + markdown-it@14.3.0: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.2 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + marked@17.0.3: {} marked@18.0.5: {} @@ -10262,7 +10193,7 @@ snapshots: node-edge-tts@1.2.10: dependencies: https-proxy-agent: 7.0.6 - ws: 8.19.0 + ws: 8.21.0 yargs: 17.7.2 transitivePeerDependencies: - bufferutil @@ -10301,7 +10232,7 @@ snapshots: ora: 9.3.0 pretty-ms: 9.3.0 proper-lockfile: 4.1.2 - semver: 7.7.4 + semver: 7.8.5 simple-git: 3.33.0 slice-ansi: 8.0.0 stdout-update: 4.0.1 @@ -10376,15 +10307,15 @@ snapshots: dependencies: mimic-function: 5.0.1 - openai@6.25.0(ws@8.19.0)(zod@4.3.6): + openai@6.25.0(ws@8.21.0)(zod@4.4.3): optionalDependencies: - ws: 8.19.0 - zod: 4.3.6 + ws: 8.21.0 + zod: 4.4.3 - openai@6.26.0(ws@8.19.0)(zod@4.3.6): + openai@6.26.0(ws@8.21.0)(zod@4.4.3): optionalDependencies: - ws: 8.19.0 - zod: 4.3.6 + ws: 8.21.0 + zod: 4.4.3 opusscript@0.0.8: {} @@ -10434,27 +10365,27 @@ snapshots: '@oxlint-tsgolint/win32-arm64': 0.14.2 '@oxlint-tsgolint/win32-x64': 0.14.2 - oxlint@1.50.0(oxlint-tsgolint@0.14.2): + oxlint@1.73.0(oxlint-tsgolint@0.14.2): optionalDependencies: - '@oxlint/binding-android-arm-eabi': 1.50.0 - '@oxlint/binding-android-arm64': 1.50.0 - '@oxlint/binding-darwin-arm64': 1.50.0 - '@oxlint/binding-darwin-x64': 1.50.0 - '@oxlint/binding-freebsd-x64': 1.50.0 - '@oxlint/binding-linux-arm-gnueabihf': 1.50.0 - '@oxlint/binding-linux-arm-musleabihf': 1.50.0 - '@oxlint/binding-linux-arm64-gnu': 1.50.0 - '@oxlint/binding-linux-arm64-musl': 1.50.0 - '@oxlint/binding-linux-ppc64-gnu': 1.50.0 - '@oxlint/binding-linux-riscv64-gnu': 1.50.0 - '@oxlint/binding-linux-riscv64-musl': 1.50.0 - '@oxlint/binding-linux-s390x-gnu': 1.50.0 - '@oxlint/binding-linux-x64-gnu': 1.50.0 - '@oxlint/binding-linux-x64-musl': 1.50.0 - '@oxlint/binding-openharmony-arm64': 1.50.0 - '@oxlint/binding-win32-arm64-msvc': 1.50.0 - '@oxlint/binding-win32-ia32-msvc': 1.50.0 - '@oxlint/binding-win32-x64-msvc': 1.50.0 + '@oxlint/binding-android-arm-eabi': 1.73.0 + '@oxlint/binding-android-arm64': 1.73.0 + '@oxlint/binding-darwin-arm64': 1.73.0 + '@oxlint/binding-darwin-x64': 1.73.0 + '@oxlint/binding-freebsd-x64': 1.73.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.73.0 + '@oxlint/binding-linux-arm-musleabihf': 1.73.0 + '@oxlint/binding-linux-arm64-gnu': 1.73.0 + '@oxlint/binding-linux-arm64-musl': 1.73.0 + '@oxlint/binding-linux-ppc64-gnu': 1.73.0 + '@oxlint/binding-linux-riscv64-gnu': 1.73.0 + '@oxlint/binding-linux-riscv64-musl': 1.73.0 + '@oxlint/binding-linux-s390x-gnu': 1.73.0 + '@oxlint/binding-linux-x64-gnu': 1.73.0 + '@oxlint/binding-linux-x64-musl': 1.73.0 + '@oxlint/binding-openharmony-arm64': 1.73.0 + '@oxlint/binding-win32-arm64-msvc': 1.73.0 + '@oxlint/binding-win32-ia32-msvc': 1.73.0 + '@oxlint/binding-win32-x64-msvc': 1.73.0 oxlint-tsgolint: 0.14.2 p-finally@1.0.0: {} @@ -10507,8 +10438,6 @@ snapshots: partial-json@0.1.7: {} - path-expression-matcher@1.2.0: {} - path-key@3.1.1: {} path-scurry@1.11.1: @@ -10612,14 +10541,14 @@ snapshots: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.1 + '@protobufjs/fetch': 1.1.1 '@protobufjs/float': 1.0.2 '@protobufjs/inquire': 1.1.0 '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 + '@protobufjs/utf8': 1.1.1 '@types/node': 25.3.0 long: 5.3.2 @@ -10659,6 +10588,8 @@ snapshots: proxy-from-env@1.1.0: {} + proxy-from-env@2.1.0: {} + psl@1.15.0: dependencies: punycode: 2.3.1 @@ -10878,6 +10809,8 @@ snapshots: semver@7.8.0: {} + semver@7.8.5: {} + send@0.19.2: dependencies: debug: 2.6.9 @@ -10938,7 +10871,7 @@ snapshots: dependencies: '@img/colour': 1.0.0 detect-libc: 2.1.2 - semver: 7.7.4 + semver: 7.8.5 optionalDependencies: '@img/sharp-darwin-arm64': 0.34.5 '@img/sharp-darwin-x64': 0.34.5 @@ -11095,6 +11028,8 @@ snapshots: std-env@3.10.0: {} + std-env@4.2.0: {} + stdin-discarder@0.3.1: {} stdout-update@4.0.1: @@ -11157,8 +11092,6 @@ snapshots: dependencies: js-tokens: 9.0.1 - strnum@2.2.2: {} - strtok3@10.3.4: dependencies: '@tokenizer/token': 0.3.0 @@ -11211,6 +11144,8 @@ snapshots: tinyrainbow@3.0.3: {} + tinyrainbow@3.1.0: {} + tinyspy@4.0.4: {} to-regex-range@5.0.1: @@ -11252,7 +11187,7 @@ snapshots: picomatch: 4.0.4 rolldown: 1.0.0-rc.3 rolldown-plugin-dts: 0.22.1(@typescript/native-preview@7.0.0-dev.20260221.1)(rolldown@1.0.0-rc.3)(typescript@5.9.3) - semver: 7.7.4 + semver: 7.8.5 tinyexec: 1.0.2 tinyglobby: 0.2.15 tree-kill: 1.2.2 @@ -11269,14 +11204,13 @@ snapshots: tslib@2.8.1: {} - tslog@4.10.2: {} + tslog@4.11.0: {} tsscmp@1.0.6: {} - tsx@4.21.0: + tsx@4.23.1: dependencies: - esbuild: 0.27.3 - get-tsconfig: 4.13.6 + esbuild: 0.28.1 optionalDependencies: fsevents: 2.3.3 @@ -11359,13 +11293,13 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite-node@3.2.4(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3): + vite-node@3.2.4(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) transitivePeerDependencies: - '@types/node' - jiti @@ -11380,22 +11314,7 @@ snapshots: - tsx - yaml - vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3): - dependencies: - esbuild: 0.27.3 - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - postcss: 8.5.6 - rollup: 4.59.0 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 25.3.0 - fsevents: 2.3.3 - jiti: 2.6.1 - tsx: 4.21.0 - yaml: 2.8.3 - - vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3): + vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3): dependencies: esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.4) @@ -11407,14 +11326,14 @@ snapshots: '@types/node': 25.3.0 fsevents: 2.3.3 jiti: 2.7.0 - tsx: 4.21.0 + tsx: 4.23.1 yaml: 2.8.3 - vitest@3.2.4(@types/node@25.3.0)(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18))(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3): + vitest@3.2.4(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -11432,12 +11351,11 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) - vite-node: 3.2.4(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) + vite-node: 3.2.4(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.3.0 - '@vitest/browser': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) transitivePeerDependencies: - jiti - less @@ -11452,10 +11370,10 @@ snapshots: - tsx - yaml - vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3): + vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3): dependencies: '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3)) '@vitest/pretty-format': 4.0.18 '@vitest/runner': 4.0.18 '@vitest/snapshot': 4.0.18 @@ -11472,12 +11390,12 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/node': 25.3.0 - '@vitest/browser-playwright': 4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) + '@vitest/browser-playwright': 4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3))(vitest@4.0.18) transitivePeerDependencies: - jiti - less @@ -11491,44 +11409,34 @@ snapshots: - tsx - yaml - vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/browser-playwright@4.0.18)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3): + vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(@vitest/coverage-v8@4.1.10)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3)): dependencies: - '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/pretty-format': 4.0.18 - '@vitest/runner': 4.0.18 - '@vitest/snapshot': 4.0.18 - '@vitest/spy': 4.0.18 - '@vitest/utils': 4.0.18 - es-module-lexer: 1.7.0 + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + es-module-lexer: 2.3.1 expect-type: 1.3.0 magic-string: 0.30.21 obug: 2.1.1 pathe: 2.0.3 picomatch: 4.0.4 - std-env: 3.10.0 + std-env: 4.2.0 tinybench: 2.9.0 tinyexec: 1.0.2 tinyglobby: 0.2.15 - tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3) + tinyrainbow: 3.1.0 + vite: 7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/node': 25.3.0 - '@vitest/browser-playwright': 4.0.18(playwright@1.58.2)(vite@7.3.1(@types/node@25.3.0)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.0.18) + '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml web-streams-polyfill@3.3.3: {} @@ -11572,6 +11480,8 @@ snapshots: ws@8.19.0: {} + ws@8.21.0: {} + y18n@5.0.8: {} yallist@4.0.0: {} @@ -11606,10 +11516,8 @@ snapshots: yoctocolors@2.1.2: {} - zod-to-json-schema@3.25.1(zod@4.3.6): + zod-to-json-schema@3.25.1(zod@4.4.3): dependencies: - zod: 4.3.6 - - zod@3.25.75: {} + zod: 4.4.3 - zod@4.3.6: {} + zod@4.4.3: {} diff --git a/src/config/includes.test.ts b/src/config/includes.test.ts index 064198e4..de3ed0c5 100644 --- a/src/config/includes.test.ts +++ b/src/config/includes.test.ts @@ -565,7 +565,11 @@ describe("security: path traversal protection (CWE-22)", () => { expect(resolve(obj, files, rootConfigPath)).toEqual({ root: true }); }); - it("allows include files when the config root path is a symlink", async () => { + // Creating symlinks on Windows requires Developer Mode or admin rights + // (EPERM otherwise), so skip this case there. CI runs on Linux where + // unprivileged symlink creation works. + const itSymlink = process.platform === "win32" ? it.skip : it; + itSymlink("allows include files when the config root path is a symlink", async () => { const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "mayros-includes-symlink-")); try { const realRoot = path.join(tempRoot, "real"); From bb5e96624096af00e793a37718d6143485816a55 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Mon, 13 Jul 2026 19:50:26 +0200 Subject: [PATCH 10/14] Terminal UI: accessible-mode parity, robustness, and visual consistency (#67) * fix(tui): resolve readline temporal-dead-zone in accessible mode The accessible TUI created its readline interface after wiring the gateway client's disconnect handler and after client.start(). If the client disconnected in that window, the handler referenced the readline binding before its initialization, throwing a ReferenceError. Move the readline creation before the disconnect wiring so the reference is always initialized. * feat(tui): make Ctrl+C abort the active run Ctrl+C now follows a three-state priority: abort an active run, clear non-empty input, or exit on a second press within one second. Escape remains a secondary abort path. This unblocks users of modal editors (where Escape is consumed to switch modes) and aligns the interrupt behavior with terminal conventions. * feat(tui): share slash-command handling between graphical and accessible modes The accessible TUI previously supported only /quit and /exit. Introduce a renderer-agnostic shared command core (shared-commands.ts) that calls the gateway client directly and reports results through an injected text sink. The accessible TUI now routes /abort, /new, /reset, /compact, /status, /sessions, /session , /model, and /help through this core, reaching feature parity with the graphical TUI for every command that does not require a visual picker. The graphical TUI continues to use its full handler for overlay-based commands. Both TUIs share logic (the gateway calls and command parsing) without sharing presentation. * fix(tui): render diffs with theme colors The diff renderer hardcoded chalk.green/red/cyan/white, so added and removed lines were hard to read under light or high-contrast themes. Thread optional DiffColors through renderDiff and formatDiffStatsLine; when the TUI calls them it passes the active theme's success/error/ accent/dim functions, keeping diff colors consistent across every theme preset. Callers without a theme fall back to the previous defaults. * refactor(terminal): align CLI palette with the TUI dark palette The CLI and the terminal UI used different accent colors (orange in the CLI, gold in the TUI), so running `mayros` then `mayros code` showed two different identities. Derive the CLI palette tokens from the TUI dark palette so both surfaces share accent, success, warn, and error values. The CLI's accentBright maps to the TUI accentSoft; accentDim is a darkened accent; info reuses accentSoft. The visual identity is now consistent across every Mayros surface. * feat(tui): enable extended keyboard protocols where supported Add term-capabilities.ts to detect and manage extended keyboard protocols. Capable terminals (kitty, WezTerm, ghostty get the kitty keyboard protocol; iTerm, vscode, tmux, windows-terminal, Apple Terminal get xterm modifyOtherKeys level 2) are upgraded at TUI startup so modifier combinations like Shift+Enter and Ctrl+Shift survive instead of being collapsed by plain raw-mode stdin. The protocol is popped on exit/SIGINT/SIGTERM so the terminal is restored for the shell. Detection is conservative: terminals outside the allow-list get no upgrade, so escape sequences are never emitted to a terminal that cannot parse them back. * chore(tui): remove unused input-history store The input-history store was never wired into the TUI main loop; it was dead code that looked like a feature. Remove it and its test to reduce confusion. Cross-session input history can be reintroduced as a real feature later, but shipping a dormant implementation invites false confidence. * test(tui): align session rename test with the new API and skip symlink on Windows The session rename API field changed from displayName to label in the 0.80 surface; update the assertion to match the implementation. The symlink-follows test requires Developer Mode or admin rights to create a symlink on Windows (EPERM otherwise), so skip it on win32; CI on Linux exercises it normally. --- src/terminal/palette.ts | 20 +-- src/tui/a11y-tui.ts | 50 +++++-- src/tui/components/tool-execution.ts | 13 +- src/tui/diff-renderer.ts | 47 +++++-- src/tui/file-mention.test.ts | 6 +- src/tui/input-history-store.test.ts | 48 ------- src/tui/input-history-store.ts | 47 ------- src/tui/session-manager.test.ts | 2 +- src/tui/shared-commands.test.ts | 159 ++++++++++++++++++++++ src/tui/shared-commands.ts | 188 +++++++++++++++++++++++++++ src/tui/term-capabilities.test.ts | 86 ++++++++++++ src/tui/term-capabilities.ts | 122 +++++++++++++++++ src/tui/tui-command-handlers.ts | 9 +- src/tui/tui.ts | 19 ++- 14 files changed, 689 insertions(+), 127 deletions(-) delete mode 100644 src/tui/input-history-store.test.ts delete mode 100644 src/tui/input-history-store.ts create mode 100644 src/tui/shared-commands.test.ts create mode 100644 src/tui/shared-commands.ts create mode 100644 src/tui/term-capabilities.test.ts create mode 100644 src/tui/term-capabilities.ts diff --git a/src/terminal/palette.ts b/src/terminal/palette.ts index 44fb5947..637c8582 100644 --- a/src/terminal/palette.ts +++ b/src/terminal/palette.ts @@ -1,12 +1,14 @@ // Mayros palette tokens for CLI/UI theming. "mayros seam" == use this palette. -// Keep in sync with docs/cli/index.md (CLI palette section). +// Values are derived from the TUI dark palette (src/tui/theme/palettes.ts) so +// the CLI and the terminal UI share the same identity. Keep in sync with +// docs/cli/index.md (CLI palette section). export const MAYROS_PALETTE = { - accent: "#FF5A2D", - accentBright: "#FF7A3D", - accentDim: "#D14A22", - info: "#FF8A5B", - success: "#2FBF71", - warn: "#FFB020", - error: "#E23D2D", - muted: "#8B7F77", + accent: "#F6C453", + accentBright: "#F2A65A", + accentDim: "#C49A3E", + info: "#F2A65A", + success: "#7DD3A5", + warn: "#F0C987", + error: "#F97066", + muted: "#7B7F87", } as const; diff --git a/src/tui/a11y-tui.ts b/src/tui/a11y-tui.ts index dbeaaf25..0873775d 100644 --- a/src/tui/a11y-tui.ts +++ b/src/tui/a11y-tui.ts @@ -2,6 +2,7 @@ import process from "node:process"; import readline from "node:readline"; import { randomUUID } from "node:crypto"; import { GatewayChatClient, resolveGatewayConnection, type GatewayEvent } from "./gateway-chat.js"; +import { handleSharedCommand } from "./shared-commands.js"; import { TuiStreamAssembler } from "./tui-stream-assembler.js"; import { A11yRenderer } from "./a11y-renderer.js"; import type { TuiOptions } from "./tui-types.js"; @@ -22,7 +23,7 @@ export async function runA11yTui(opts: TuiOptions): Promise { password: connection.password, }); - const sessionKey = opts.session ?? "main"; + let sessionKey = opts.session ?? "main"; const assembler = new TuiStreamAssembler(); const showThinking = opts.thinking === "on" || opts.thinking === "verbose"; @@ -95,6 +96,15 @@ export async function runA11yTui(opts: TuiOptions): Promise { } }; + // Declare the readline interface before wiring client disconnect handling, + // so a disconnect between client.start() and the readline creation cannot + // reference `rl` in its temporal dead zone. + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + prompt: "> ", + }); + client.onDisconnected = (reason: string) => { renderer.emit({ type: "system", text: `Disconnected: ${reason}` }); rl.close(); @@ -125,15 +135,9 @@ export async function runA11yTui(opts: TuiOptions): Promise { }); } - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - prompt: "> ", - }); - rl.prompt(); - rl.on("line", (line) => { + rl.on("line", async (line) => { const text = line.trim(); if (!text) { rl.prompt(); @@ -147,6 +151,36 @@ export async function runA11yTui(opts: TuiOptions): Promise { return; } + // Route slash commands through the shared command core so the accessible + // TUI reaches feature parity with the graphical TUI for the commands that + // do not require a visual picker (abort, reset, compact, status, etc.). + if (text.startsWith("/")) { + const [name, ...rest] = text.slice(1).split(/\s+/); + if (name) { + const sink = { + info: (msg: string) => renderer.emit({ type: "system", text: msg }), + error: (msg: string) => renderer.emit({ type: "system", text: msg }), + }; + const handled = await handleSharedCommand( + { + client, + sessionKey, + getActiveRunId: () => currentRunId, + onSessionChanged: (key) => { + sessionKey = key; + }, + }, + name.toLowerCase(), + rest.join(" ").trim(), + sink, + ); + if (handled.handled) { + rl.prompt(); + return; + } + } + } + const runId = randomUUID(); currentRunId = runId; lastOutputLength = 0; diff --git a/src/tui/components/tool-execution.ts b/src/tui/components/tool-execution.ts index 931af40f..80f71059 100644 --- a/src/tui/components/tool-execution.ts +++ b/src/tui/components/tool-execution.ts @@ -133,9 +133,18 @@ export class ToolExecutionComponent extends Container { const isDiff = DIFF_TOOLS.has(this.toolName) && raw && !this.isPartial; if (isDiff) { - const colored = renderDiff(raw); + const colored = renderDiff(raw, { + add: theme.success, + del: theme.error, + header: (t) => theme.bold(t), + hunk: theme.accent, + context: theme.dim, + }); const stats = parseDiffStats(raw); - const statsLine = formatDiffStatsLine(stats); + const statsLine = formatDiffStatsLine(stats, { + add: theme.success, + del: theme.error, + }); const maxLines = this.expanded ? Infinity : DIFF_PREVIEW_LINES; const display = colored.length > maxLines diff --git a/src/tui/diff-renderer.ts b/src/tui/diff-renderer.ts index 08955eee..08ea1889 100644 --- a/src/tui/diff-renderer.ts +++ b/src/tui/diff-renderer.ts @@ -13,6 +13,29 @@ export type DiffStats = { deletions: number; }; +/** + * Color functions for diff rendering, each taking text and returning it styled. + * Matches the shape of the TUI theme color functions so the active palette can + * be passed straight through, keeping diff colors consistent with the theme + * (correct under light and high-contrast presets). + */ +export type DiffColors = { + add: (text: string) => string; + del: (text: string) => string; + header: (text: string) => string; + hunk: (text: string) => string; + context: (text: string) => string; +}; + +/** Default (terminal-default) colors used when no theme is supplied. */ +const DEFAULT_DIFF_COLORS: DiffColors = { + add: (t) => chalk.green(t), + del: (t) => chalk.red(t), + header: (t) => chalk.bold(chalk.white(t)), + hunk: (t) => chalk.cyan(t), + context: (t) => chalk.dim(t), +}; + export function parseDiffLines(raw: string): DiffLine[] { const lines: DiffLine[] = []; for (const text of raw.split("\n")) { @@ -36,20 +59,21 @@ export function parseDiffLines(raw: string): DiffLine[] { return lines; } -export function renderDiff(raw: string): string[] { +export function renderDiff(raw: string, colors?: Partial): string[] { + const c = { ...DEFAULT_DIFF_COLORS, ...colors }; const parsed = parseDiffLines(raw); return parsed.map((line) => { switch (line.type) { case "add": - return chalk.green(line.text); + return c.add(line.text); case "del": - return chalk.red(line.text); + return c.del(line.text); case "header": - return chalk.bold(chalk.white(line.text)); + return c.header(line.text); case "hunk": - return chalk.cyan(line.text); + return c.hunk(line.text); default: - return chalk.dim(line.text); + return c.context(line.text); } }); } @@ -80,10 +104,15 @@ export function renderDiffStats(raw: string): DiffStats { * Format a single-line summary of diff stats with colors. * Example: "+5 -3 (2 files)" */ -export function formatDiffStatsLine(stats: DiffStats): string { +export function formatDiffStatsLine( + stats: DiffStats, + colors?: { add?: (text: string) => string; del?: (text: string) => string }, +): string { + const add = colors?.add ?? ((t: string) => chalk.green(t)); + const del = colors?.del ?? ((t: string) => chalk.red(t)); const parts: string[] = []; - if (stats.additions > 0) parts.push(chalk.green(`+${stats.additions}`)); - if (stats.deletions > 0) parts.push(chalk.red(`-${stats.deletions}`)); + if (stats.additions > 0) parts.push(add(`+${stats.additions}`)); + if (stats.deletions > 0) parts.push(del(`-${stats.deletions}`)); const fileLabel = stats.files === 1 ? "1 file" : `${stats.files} files`; return parts.length > 0 ? `${parts.join(" ")} (${fileLabel})` : `(${fileLabel})`; } diff --git a/src/tui/file-mention.test.ts b/src/tui/file-mention.test.ts index 25db18f4..03375616 100644 --- a/src/tui/file-mention.test.ts +++ b/src/tui/file-mention.test.ts @@ -108,7 +108,11 @@ describe("file-mention", () => { expect(result.mediaAttachments).toHaveLength(0); }); - it("follows symlinks to regular files", async () => { + // Creating symlinks on Windows requires Developer Mode or admin rights + // (EPERM otherwise), so skip this case there. CI runs on Linux where + // unprivileged symlink creation works. + const itSymlink = process.platform === "win32" ? it.skip : it; + itSymlink("follows symlinks to regular files", async () => { const realPath = path.join(tmpDir, "real.txt"); const linkPath = path.join(tmpDir, "link.txt"); await fs.writeFile(realPath, "linked content"); diff --git a/src/tui/input-history-store.test.ts b/src/tui/input-history-store.test.ts deleted file mode 100644 index 91b6ae13..00000000 --- a/src/tui/input-history-store.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach } from "vitest"; -import { createInputHistoryStore } from "./input-history-store.js"; -import { mkdirSync, rmSync } from "node:fs"; -import { join } from "node:path"; -import { tmpdir } from "node:os"; - -describe("InputHistoryStore", () => { - const testDir = join(tmpdir(), "mayros-history-test-" + Date.now()); - let originalHome: string | undefined; - - beforeEach(() => { - originalHome = process.env.HOME; - // We test the module functions directly without HOME override since - // the store uses homedir() at call time - mkdirSync(testDir, { recursive: true }); - }); - - afterEach(() => { - process.env.HOME = originalHome; - try { - rmSync(testDir, { recursive: true }); - } catch {} - }); - - it("load returns empty array when file does not exist", () => { - const store = createInputHistoryStore(); - // Default file may or may not exist, but function should not throw - expect(() => store.load()).not.toThrow(); - }); - - it("load returns empty array for invalid JSON", () => { - const store = createInputHistoryStore(); - expect(() => store.load()).not.toThrow(); - }); - - it("createInputHistoryStore returns object with load/save/append", () => { - const store = createInputHistoryStore(); - expect(typeof store.load).toBe("function"); - expect(typeof store.save).toBe("function"); - expect(typeof store.append).toBe("function"); - }); - - it("append does not throw for empty strings", () => { - const store = createInputHistoryStore(); - expect(() => store.append("")).not.toThrow(); - expect(() => store.append(" ")).not.toThrow(); - }); -}); diff --git a/src/tui/input-history-store.ts b/src/tui/input-history-store.ts deleted file mode 100644 index 18cc6a4c..00000000 --- a/src/tui/input-history-store.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { readFileSync, writeFileSync, mkdirSync } from "node:fs"; -import { join, dirname } from "node:path"; -import { homedir } from "node:os"; - -const HISTORY_FILE = join(homedir(), ".mayros", "input-history.json"); -const MAX_ENTRIES = 500; - -export type InputHistoryStore = { - load(): string[]; - save(entries: string[]): void; - append(entry: string): void; -}; - -export function createInputHistoryStore(): InputHistoryStore { - function load(): string[] { - try { - const data = readFileSync(HISTORY_FILE, "utf-8"); - const parsed = JSON.parse(data); - if (Array.isArray(parsed)) - return parsed.filter((e): e is string => typeof e === "string").slice(-MAX_ENTRIES); - } catch { - /* first run or corrupted */ - } - return []; - } - - function save(entries: string[]): void { - const trimmed = entries.slice(-MAX_ENTRIES); - try { - mkdirSync(dirname(HISTORY_FILE), { recursive: true }); - writeFileSync(HISTORY_FILE, JSON.stringify(trimmed), "utf-8"); - } catch { - /* read-only fs, ignore */ - } - } - - function append(entry: string): void { - if (!entry.trim()) return; - const current = load(); - // Deduplicate: remove previous occurrence - const deduped = current.filter((e) => e !== entry); - deduped.push(entry); - save(deduped); - } - - return { load, save, append }; -} diff --git a/src/tui/session-manager.test.ts b/src/tui/session-manager.test.ts index a792a19a..51c8cc6f 100644 --- a/src/tui/session-manager.test.ts +++ b/src/tui/session-manager.test.ts @@ -62,7 +62,7 @@ describe("SessionManager", () => { const client = createMockClient(); const mgr = new SessionManager({ client: client as never, currentAgentId: "default" }); await mgr.renameSession("s-abc", "New Name"); - expect(client.patchSession).toHaveBeenCalledWith({ key: "s-abc", displayName: "New Name" }); + expect(client.patchSession).toHaveBeenCalledWith({ key: "s-abc", label: "New Name" }); }); it("deletes a session via reset", async () => { diff --git a/src/tui/shared-commands.test.ts b/src/tui/shared-commands.test.ts new file mode 100644 index 00000000..762e9328 --- /dev/null +++ b/src/tui/shared-commands.test.ts @@ -0,0 +1,159 @@ +import { describe, expect, it, vi } from "vitest"; +import { handleSharedCommand } from "./shared-commands.js"; +import type { GatewayChatClient } from "./gateway-chat.js"; + +/** + * Unit tests for the shared slash-command core. + * + * The shared handler lets the accessible TUI reach parity with the graphical + * TUI for commands that do not require a visual picker. These tests pin the + * contract: each recognized command calls the right gateway method and + * reports through the injected sink, while unrecognized commands fall through. + */ + +function makeClientStub(overrides: Partial = {}): GatewayChatClient { + const base = { + abortChat: vi.fn().mockResolvedValue({ ok: true, aborted: true }), + resetSession: vi.fn().mockResolvedValue({ ok: true }), + compactSession: vi.fn().mockResolvedValue({ ok: true, compacted: true }), + getStatus: vi.fn().mockResolvedValue({ version: "1.2.3", sessions: 2 }), + listSessions: vi.fn().mockResolvedValue({ + sessions: [{ key: "main", title: "Main" }], + }), + listModels: vi + .fn() + .mockResolvedValue([{ id: "anthropic/claude", name: "Claude", provider: "anthropic" }]), + }; + return { ...base, ...overrides } as unknown as GatewayChatClient; +} + +function makeSink() { + const messages: { kind: "info" | "error"; text: string }[] = []; + return { + sink: { + info: (text: string) => messages.push({ kind: "info", text }), + error: (text: string) => messages.push({ kind: "error", text }), + }, + messages, + }; +} + +describe("handleSharedCommand", () => { + it("aborts the active run when one exists", async () => { + const client = makeClientStub(); + const { sink, messages } = makeSink(); + const result = await handleSharedCommand( + { client, sessionKey: "main", getActiveRunId: () => "run-1" }, + "abort", + "", + sink, + ); + expect(result.handled).toBe(true); + expect(client.abortChat).toHaveBeenCalledWith({ sessionKey: "main", runId: "run-1" }); + expect(messages).toContainEqual({ kind: "info", text: "aborted" }); + }); + + it("reports no active run when getActiveRunId returns null", async () => { + const client = makeClientStub(); + const { sink, messages } = makeSink(); + const result = await handleSharedCommand( + { client, sessionKey: "main", getActiveRunId: () => null }, + "abort", + "", + sink, + ); + expect(result.handled).toBe(true); + expect(client.abortChat).not.toHaveBeenCalled(); + expect(messages[0]?.text).toBe("no active run"); + }); + + it("resets the session on /new", async () => { + const client = makeClientStub(); + const onSessionChanged = vi.fn(); + const { sink, messages } = makeSink(); + const result = await handleSharedCommand( + { client, sessionKey: "main", onSessionChanged }, + "new", + "", + sink, + ); + expect(result.handled).toBe(true); + expect(client.resetSession).toHaveBeenCalledWith("main", "new"); + expect(messages[0]?.text).toBe("session reset"); + expect(onSessionChanged).toHaveBeenCalledWith("main"); + }); + + it("compacts the session context", async () => { + const client = makeClientStub(); + const { sink, messages } = makeSink(); + const result = await handleSharedCommand({ client, sessionKey: "main" }, "compact", "", sink); + expect(result.handled).toBe(true); + expect(client.compactSession).toHaveBeenCalledWith({ key: "main" }); + expect(messages[0]?.text).toBe("context compacted"); + }); + + it("switches session when given an argument", async () => { + const client = makeClientStub(); + const onSessionChanged = vi.fn(); + const { sink, messages } = makeSink(); + const result = await handleSharedCommand( + { client, sessionKey: "main", onSessionChanged }, + "session", + "work", + sink, + ); + expect(result.handled).toBe(true); + expect(onSessionChanged).toHaveBeenCalledWith("work"); + expect(messages[0]?.text).toContain("work"); + }); + + it("lists sessions when called without an argument", async () => { + const client = makeClientStub(); + const { sink, messages } = makeSink(); + const result = await handleSharedCommand({ client, sessionKey: "main" }, "sessions", "", sink); + expect(result.handled).toBe(true); + expect(client.listSessions).toHaveBeenCalled(); + expect(messages[0]?.text).toContain("main"); + }); + + it("lists available models", async () => { + const client = makeClientStub(); + const { sink, messages } = makeSink(); + const result = await handleSharedCommand({ client, sessionKey: "main" }, "model", "", sink); + expect(result.handled).toBe(true); + expect(client.listModels).toHaveBeenCalled(); + expect(messages[0]?.text).toContain("anthropic/claude"); + }); + + it("returns help text on /help", async () => { + const client = makeClientStub(); + const { sink, messages } = makeSink(); + const result = await handleSharedCommand({ client, sessionKey: "main" }, "help", "", sink); + expect(result.handled).toBe(true); + expect(messages[0]?.text).toContain("/abort"); + expect(messages[0]?.text).toContain("/compact"); + }); + + it("reports errors through the sink when a gateway call fails", async () => { + const client = makeClientStub({ + getStatus: vi.fn().mockRejectedValue(new Error("gateway down")), + }); + const { sink, messages } = makeSink(); + const result = await handleSharedCommand({ client, sessionKey: "main" }, "status", "", sink); + expect(result.handled).toBe(true); + expect(messages[0]?.kind).toBe("error"); + expect(messages[0]?.text).toContain("status failed"); + }); + + it("falls through (handled: false) for unknown commands", async () => { + const client = makeClientStub(); + const { sink } = makeSink(); + const result = await handleSharedCommand( + { client, sessionKey: "main" }, + "totally-unknown-command", + "", + sink, + ); + expect(result.handled).toBe(false); + }); +}); diff --git a/src/tui/shared-commands.ts b/src/tui/shared-commands.ts new file mode 100644 index 00000000..fcea0a27 --- /dev/null +++ b/src/tui/shared-commands.ts @@ -0,0 +1,188 @@ +/** + * Renderer-agnostic slash-command handling shared between the graphical TUI + * and the accessible (text-mode) TUI. + * + * The graphical TUI dispatches most commands through its own full handler + * (tui-command-handlers.ts) because it has overlays, pickers, and rich + * rendering. The accessible TUI has none of that, so it routes a focused set + * of commands through this shared core, which calls the gateway client + * directly and reports results as plain text via the injected render sink. + * + * This closes the feature-parity gap without forcing both TUIs to share a + * renderer: the logic is shared, the presentation is not. + */ + +import type { GatewayChatClient } from "./gateway-chat.js"; + +/** Sink for status/system messages produced by shared commands. */ +export type SharedCommandSink = { + /** Surface a normal informational message. */ + info: (text: string) => void; + /** Surface an error message. */ + error: (text: string) => void; +}; + +export type SharedCommandContext = { + client: GatewayChatClient; + sessionKey: string; + /** Active run id, if any, for abort. */ + getActiveRunId?: () => string | null; + /** Called after a session reset/switch so the caller can update its state. */ + onSessionChanged?: (sessionKey: string) => void; +}; + +export type HandleSharedCommandResult = { + /** true if the command was recognized and handled here. */ + handled: boolean; +}; + +/** + * Handle a focused set of slash commands against the gateway client. + * Returns { handled: true } when the command was recognized; the caller + * should not fall through to sending it as a chat message in that case. + */ +export async function handleSharedCommand( + ctx: SharedCommandContext, + name: string, + args: string, + sink: SharedCommandSink, +): Promise { + switch (name) { + case "abort": { + const runId = ctx.getActiveRunId?.() ?? null; + if (!runId) { + sink.info("no active run"); + return { handled: true }; + } + try { + await ctx.client.abortChat({ sessionKey: ctx.sessionKey, runId }); + sink.info("aborted"); + } catch (err) { + sink.error(`abort failed: ${String(err)}`); + } + return { handled: true }; + } + + case "new": + case "reset": { + try { + await ctx.client.resetSession(ctx.sessionKey, name === "new" ? "new" : "reset"); + sink.info("session reset"); + ctx.onSessionChanged?.(ctx.sessionKey); + } catch (err) { + sink.error(`reset failed: ${String(err)}`); + } + return { handled: true }; + } + + case "compact": { + try { + const result = await ctx.client.compactSession({ key: ctx.sessionKey }); + if (result.compacted) { + sink.info("context compacted"); + } else { + sink.info(`compaction skipped: ${result.reason ?? "no change"}`); + } + } catch (err) { + sink.error(`compact failed: ${String(err)}`); + } + return { handled: true }; + } + + case "status": { + try { + const status = await ctx.client.getStatus(); + const summary = formatStatusSummary(status); + sink.info(summary); + } catch (err) { + sink.error(`status failed: ${String(err)}`); + } + return { handled: true }; + } + + case "sessions": + case "session": { + if (name === "sessions" || !args) { + try { + const result = await ctx.client.listSessions({ limit: 20 }); + const lines = formatSessionList(result); + sink.info(lines || "no sessions"); + } catch (err) { + sink.error(`session list failed: ${String(err)}`); + } + return { handled: true }; + } + // `/session ` — switch by setting currentSessionKey on the caller. + ctx.onSessionChanged?.(args.trim()); + sink.info(`switched to ${args.trim()}`); + return { handled: true }; + } + + case "models": + case "model": { + try { + const models = await ctx.client.listModels(); + if (models.length === 0) { + sink.info("no models configured"); + } else { + const lines = models.map((m) => ` ${m.id}${m.name ? ` — ${m.name}` : ""}`).join("\n"); + sink.info(`Available models:\n${lines}`); + } + } catch (err) { + sink.error(`model list failed: ${String(err)}`); + } + return { handled: true }; + } + + case "help": { + sink.info(SHARED_HELP_TEXT); + return { handled: true }; + } + + default: + return { handled: false }; + } +} + +function formatStatusSummary(status: unknown): string { + if (!status || typeof status !== "object") return String(status); + const s = status as Record; + const parts: string[] = []; + if (typeof s.version === "string") parts.push(`gateway ${s.version}`); + if (typeof s.uptime === "number") parts.push(`uptime ${Math.round(s.uptime)}s`); + if (s.model && typeof s.model === "object") { + const m = s.model as Record; + if (typeof m.id === "string") parts.push(`model ${m.id}`); + } + if (typeof s.sessions === "number") parts.push(`${s.sessions} sessions`); + return parts.length > 0 ? parts.join(" · ") : "status unavailable"; +} + +function formatSessionList(result: unknown): string { + if (!result || typeof result !== "object") return ""; + const r = result as Record; + const sessions = Array.isArray(r.sessions) ? r.sessions : []; + if (sessions.length === 0) return ""; + return sessions + .map((entry, i) => { + const e = entry as Record; + const key = typeof e.key === "string" ? e.key : `session-${i}`; + const title = typeof e.title === "string" ? e.title : ""; + return ` ${key}${title ? ` — ${title}` : ""}`; + }) + .join("\n"); +} + +const SHARED_HELP_TEXT = `Available commands in accessible mode: + /abort Abort the active run + /new Reset the session (new conversation) + /reset Reset the session + /compact Compact session context + /status Show gateway status + /sessions List recent sessions + /session Switch to a session by key + /model List available models + /help Show this help + /quit, /exit Exit + +Type a message and press Enter to send.`; diff --git a/src/tui/term-capabilities.test.ts b/src/tui/term-capabilities.test.ts new file mode 100644 index 00000000..d75d3dcb --- /dev/null +++ b/src/tui/term-capabilities.test.ts @@ -0,0 +1,86 @@ +import { describe, expect, it } from "vitest"; +import { detectKeyboardProtocol, enableKeyboardProtocol } from "./term-capabilities.js"; + +describe("detectKeyboardProtocol", () => { + it("returns kitty for kitty/WezTerm/ghostty terminals", () => { + expect(detectKeyboardProtocol({ TERM_PROGRAM: "kitty" } as NodeJS.ProcessEnv)).toBe("kitty"); + expect(detectKeyboardProtocol({ TERM_PROGRAM: "WezTerm" } as NodeJS.ProcessEnv)).toBe("kitty"); + expect(detectKeyboardProtocol({ TERM_PROGRAM: "ghostty" } as NodeJS.ProcessEnv)).toBe("kitty"); + }); + + it("returns modify-other-keys for iTerm/vscode/tmux/windows-terminal", () => { + expect(detectKeyboardProtocol({ TERM_PROGRAM: "iTerm.app" } as NodeJS.ProcessEnv)).toBe( + "modify-other-keys", + ); + expect(detectKeyboardProtocol({ TERM_PROGRAM: "vscode" } as NodeJS.ProcessEnv)).toBe( + "modify-other-keys", + ); + expect(detectKeyboardProtocol({ TERM_PROGRAM: "tmux" } as NodeJS.ProcessEnv)).toBe( + "modify-other-keys", + ); + expect(detectKeyboardProtocol({ TERM_PROGRAM: "windows-terminal" } as NodeJS.ProcessEnv)).toBe( + "modify-other-keys", + ); + }); + + it("prefers LC_TERMINAL over TERM_PROGRAM (survives tmux on macOS)", () => { + expect( + detectKeyboardProtocol({ + LC_TERMINAL: "iTerm.app", + TERM_PROGRAM: "tmux", + } as NodeJS.ProcessEnv), + ).toBe("modify-other-keys"); + }); + + it("returns none for terminals not in the allow-list", () => { + expect(detectKeyboardProtocol({ TERM_PROGRAM: "xterm-256color" } as NodeJS.ProcessEnv)).toBe( + "none", + ); + expect(detectKeyboardProtocol({} as NodeJS.ProcessEnv)).toBe("none"); + }); +}); + +describe("enableKeyboardProtocol", () => { + it("returns a none-handle and writes nothing when protocol is none", () => { + const written: string[] = []; + const stream = { write: (s: string) => written.push(s) } as unknown as NodeJS.WritableStream; + const handle = enableKeyboardProtocol(stream); + expect(handle.protocol).toBe("none"); + expect(written).toHaveLength(0); + handle.disable(); // no-op, does not throw + }); + + it("writes the kitty push sequence for kitty terminals", () => { + const written: string[] = []; + const stream = { write: (s: string) => written.push(s) } as unknown as NodeJS.WritableStream; + const original = process.env.TERM_PROGRAM; + process.env.TERM_PROGRAM = "kitty"; + try { + const handle = enableKeyboardProtocol(stream); + expect(handle.protocol).toBe("kitty"); + expect(written.join("")).toContain("\x1b[>1u"); + handle.disable(); + expect(written.join("")).toContain("\x1b[ { + const written: string[] = []; + const stream = { write: (s: string) => written.push(s) } as unknown as NodeJS.WritableStream; + const original = process.env.TERM_PROGRAM; + process.env.TERM_PROGRAM = "kitty"; + try { + const handle = enableKeyboardProtocol(stream); + handle.disable(); + handle.disable(); + const popCount = written.filter((s) => s.includes("\x1b[ 1 u push / CSI < u pop) + * 2. xterm modifyOtherKeys level 2 (CSI > 4 ; 2 u / CSI < 4 u) + * + * Detection is conservative: only terminals in the known-good allow-list are + * upgraded, so we never emit escape sequences a terminal cannot parse back. + */ + +import process from "node:process"; + +/** Terminal identifiers that reliably support an extended keyboard protocol. */ +const EXTENDED_KEY_TERMINALS = new Set([ + "iTerm.app", + "kitty", + "WezTerm", + "ghostty", + "tmux", + "vscode", + "windows-terminal", + "Apple_Terminal", +]); + +type Protocol = "kitty" | "modify-other-keys" | "none"; + +function detectTerminal(): string { + // LC_TERMINAL survives tmux on macOS where TERM_PROGRAM is overwritten. + return ( + process.env.LC_TERMINAL || process.env.TERM_PROGRAM || process.env.TERM_PROGRAM_VERSION || "" + ); +} + +/** Decide which protocol to enable, if any, for the current terminal. */ +export function detectKeyboardProtocol(env: NodeJS.ProcessEnv = process.env): Protocol { + const id = env.LC_TERMINAL || env.TERM_PROGRAM || ""; + if (!id || !EXTENDED_KEY_TERMINALS.has(id)) { + return "none"; + } + // Kitty, WezTerm, Ghostty implement the kitty protocol natively. + // iTerm, vscode, Apple Terminal, tmux, windows-terminal support modifyOtherKeys. + if (id === "kitty" || id === "WezTerm" || id === "ghostty") { + return "kitty"; + } + return "modify-other-keys"; +} + +/** Escape: CSI */ +const CSI = "\x1b["; + +function pushSequence(protocol: Protocol): string { + switch (protocol) { + case "kitty": + // Kitty keyboard protocol: push flags 1 (disambiguate escape keys). + return `${CSI}>1u`; + case "modify-other-keys": + // xterm modifyOtherKeys level 2. + return `${CSI}>4;2u`; + default: + return ""; + } +} + +function popSequence(protocol: Protocol): string { + switch (protocol) { + case "kitty": + return `${CSI} void; +}; + +/** + * Enable the best supported extended keyboard protocol on the given stream + * (defaults to stdout). Returns a handle whose `disable()` pops the protocol; + * call it on exit, on every signal, and on uncaught errors. + */ +export function enableKeyboardProtocol( + stream: NodeJS.WritableStream = process.stdout, +): KeyboardProtocolHandle { + const protocol = detectKeyboardProtocol(); + const push = pushSequence(protocol); + if (push) { + try { + stream.write(push); + } catch { + // Writing to a closed stream must never break startup. + } + } + let disabled = false; + return { + protocol, + disable: () => { + if (disabled || protocol === "none") return; + disabled = true; + const pop = popSequence(protocol); + if (pop) { + try { + stream.write(pop); + } catch { + // Best-effort cleanup. + } + } + }, + }; +} diff --git a/src/tui/tui-command-handlers.ts b/src/tui/tui-command-handlers.ts index 3e23a5ca..b67b5091 100644 --- a/src/tui/tui-command-handlers.ts +++ b/src/tui/tui-command-handlers.ts @@ -24,6 +24,7 @@ import { formatContextVisualization } from "./context-visualizer.js"; import { renderDiff, renderDiffStats } from "./diff-renderer.js"; import { compactMessages } from "./compact-handler.js"; import { SessionManager, formatSessionLine } from "./session-manager.js"; +import { theme } from "./theme/theme.js"; import { applyOutputStyle, isValidOutputStyle, OUTPUT_STYLE_NAMES } from "./output-styles.js"; import type { OutputStyle } from "./output-styles.js"; import { THEME_PRESETS } from "./theme/palettes.js"; @@ -679,7 +680,13 @@ export function createCommandHandlers(context: CommandHandlerContext) { chatLog.addSystem( `${stats.files} file(s) changed, +${stats.additions} -${stats.deletions}`, ); - for (const line of renderDiff(raw)) { + for (const line of renderDiff(raw, { + add: theme.success, + del: theme.error, + header: (t) => theme.bold(t), + hunk: theme.accent, + context: theme.dim, + })) { chatLog.addSystem(line); } } catch (err) { diff --git a/src/tui/tui.ts b/src/tui/tui.ts index b6618769..872eb8e5 100644 --- a/src/tui/tui.ts +++ b/src/tui/tui.ts @@ -26,6 +26,7 @@ import { ChatLog } from "./components/chat-log.js"; import { CustomEditor } from "./components/custom-editor.js"; import { WelcomeScreen } from "./components/welcome-screen.js"; import { GatewayChatClient } from "./gateway-chat.js"; +import { enableKeyboardProtocol } from "./term-capabilities.js"; import type { ThemePreset } from "./theme/palettes.js"; import { THEME_PRESETS } from "./theme/palettes.js"; import { editorTheme, theme, setThemePreset } from "./theme/theme.js"; @@ -904,6 +905,15 @@ export async function runTui(opts: TuiOptions) { }; editor.onCtrlC = () => { const now = Date.now(); + // Tri-state, in priority order: + // 1. an active run → abort it + // 2. non-empty input → clear it + // 3. double Ctrl+C within 1s → exit + // Escape remains a secondary abort path. + if (activeChatRunId) { + void abortActive(); + return; + } if (editor.getText().trim().length > 0) { editor.setText(""); setActivityStatus("cleared input"); @@ -1030,10 +1040,17 @@ export async function runTui(opts: TuiOptions) { updateHeader(); setConnectionStatus("connecting"); updateFooter(); + // Enable extended keyboard protocols (kitty / modifyOtherKeys) so modifier + // combinations like Shift+Enter survive in capable terminals. The handle + // restores the terminal on exit. + const keyboardProtocol = enableKeyboardProtocol(); tui.start(); client.start(); await new Promise((resolve) => { - const finish = () => resolve(); + const finish = () => { + keyboardProtocol.disable(); + resolve(); + }; process.once("exit", finish); process.once("SIGINT", finish); process.once("SIGTERM", finish); From 4e7527dd59df5a50d5a6d0df6b0b9a31109970a8 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Tue, 14 Jul 2026 00:10:07 +0200 Subject: [PATCH 11/14] Terminal UI: streaming performance, auto-theme, and per-section visibility (#69) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(tui): auto-detect dark/light theme from the terminal When config.ui.theme is unset or set to "auto", query the terminal for its color-scheme preference before the first render. The detection uses two concurrent queries with a 150 ms timeout each: the DSR color-scheme report (CSI ? 996 n, a direct dark/light answer) and the OSC 11 background-color query (parsed to RGB and classified via Rec. 709 relative luminance). The fastest signal wins; an unresponsive terminal falls back to the default dark preset without blocking startup. Add "auto" to the ui.theme config type so users can opt in explicitly, and document the query ladder in term-capabilities.ts. The manual /theme command continues to override the detected preset for the session. * test(tui): cover paste-collapse and grapheme caret behavior Add no-regression coverage for the two input features inherited from the terminal UI dependency: grapheme-aware caret movement (Intl.Segmenter) and paste-collapse markers. Both are implemented in the Editor class the TUI extends, so the tests pin the environment contract rather than the Editor internals. The grapheme tests verify that emoji with skin-tone modifiers, flag emoji, and CJK characters each count as a single grapheme — the invariant the caret relies on. The paste-marker tests verify the marker shape ([paste #N +M lines], [paste #N M chars], [paste #N]) so that cursor movement and submission expansion keep working if the format changes upstream. Also update the welcome-screen quick-start hint to reflect that Ctrl+C now aborts the active run (Esc remains a secondary path). * perf(tui): split streaming markdown at the stable block boundary Re-parsing the full markdown on every streaming delta is O(n²) over a response. Split the assistant message text at the last stable block boundary (a blank line outside any open code fence) into a stable prefix and an active suffix. Only the suffix is re-parsed per delta; the prefix reuses the Markdown component's internal render cache, which turns the per-delta cost into O(n). Add stream-boundary.ts with a pure, unit-tested findStableBoundary function that walks backwards through blank lines and skips any that sit inside an open code fence. Refactor AssistantMessageComponent to hold two Markdown instances (prefix + suffix) and only update the prefix when its text actually grows. * feat(tui): per-section detail visibility for tools and thinking Replace the binary expanded/collapsed toggle with a three-state model: hidden, collapsed, and expanded. Each section cycles independently via its keyboard shortcut. - Tools (Ctrl+O): hidden renders only the header line, collapsed shows a 12-line preview, expanded shows the full output. - Thinking (Ctrl+T): hidden suppresses thinking text, collapsed and expanded both show it (a truncated thinking mode is deferred to a follow-up that restructures the composer). The section state is the new source of truth in TuiStateAccess; the existing toolsExpanded and showThinking fields are kept as compatibility shims. Add a nextSectionState helper and unit tests for the cycle. --- src/config/types.mayros.ts | 4 +- src/tui/components/assistant-message.ts | 39 ++++++++++-- src/tui/components/chat-log.ts | 8 +++ src/tui/components/tool-execution.ts | 26 ++++++-- src/tui/components/welcome-screen.ts | 2 +- src/tui/paste-grapheme.test.ts | 82 +++++++++++++++++++++++++ src/tui/section-visibility.test.ts | 28 +++++++++ src/tui/stream-boundary.test.ts | 69 +++++++++++++++++++++ src/tui/stream-boundary.ts | 64 +++++++++++++++++++ src/tui/term-capabilities.test.ts | 67 +++++++++++++++++++- src/tui/term-capabilities.ts | 46 ++++++++++++++ src/tui/tui-event-handlers.test.ts | 2 + src/tui/tui-session-actions.test.ts | 2 + src/tui/tui-types.ts | 21 +++++++ src/tui/tui.ts | 43 +++++++++++-- 15 files changed, 484 insertions(+), 19 deletions(-) create mode 100644 src/tui/paste-grapheme.test.ts create mode 100644 src/tui/section-visibility.test.ts create mode 100644 src/tui/stream-boundary.test.ts create mode 100644 src/tui/stream-boundary.ts diff --git a/src/config/types.mayros.ts b/src/config/types.mayros.ts index 8c8bdc4e..ec33a448 100644 --- a/src/config/types.mayros.ts +++ b/src/config/types.mayros.ts @@ -68,8 +68,8 @@ export type MayrosConfig = { ui?: { /** Accent color for Mayros UI chrome (hex). */ seamColor?: string; - /** TUI color theme preset. */ - theme?: "dark" | "light" | "high-contrast"; + /** TUI color theme preset, or "auto" to detect from the terminal. */ + theme?: "auto" | "dark" | "light" | "high-contrast"; /** Enable vim editing mode in the TUI. */ vim?: boolean; /** Custom keybindings for TUI actions. */ diff --git a/src/tui/components/assistant-message.ts b/src/tui/components/assistant-message.ts index 2d9c3c84..dfe79712 100644 --- a/src/tui/components/assistant-message.ts +++ b/src/tui/components/assistant-message.ts @@ -1,21 +1,50 @@ import { Container, Markdown, Spacer } from "@earendil-works/pi-tui"; +import { findStableBoundary } from "../stream-boundary.js"; import { markdownTheme, theme } from "../theme/theme.js"; +/** + * Renders an assistant message with incremental markdown parsing. + * + * The text is split at the last stable block boundary (see findStableBoundary) + * into a stable prefix and an active suffix. Only the suffix is re-parsed on + * each streaming delta; the prefix reuses the Markdown component's internal + * render cache, turning the per-delta cost from O(n²) into O(n). + */ export class AssistantMessageComponent extends Container { - private body: Markdown; + private stablePrefix: Markdown; + private activeSuffix: Markdown; + private committedPrefixText = ""; constructor(text: string) { super(); - this.body = new Markdown(text, 1, 0, markdownTheme, { + this.addChild(new Spacer(1)); + this.stablePrefix = this.createMarkdown(""); + this.activeSuffix = this.createMarkdown(""); + this.addChild(this.stablePrefix); + this.addChild(this.activeSuffix); + if (text) this.setText(text); + } + + private createMarkdown(text: string): Markdown { + return new Markdown(text, 1, 0, markdownTheme, { // Keep assistant body text in terminal default foreground so contrast // follows the user's terminal theme (dark or light). color: (line) => theme.assistantText(line), }); - this.addChild(new Spacer(1)); - this.addChild(this.body); } setText(text: string) { - this.body.setText(text); + const boundary = findStableBoundary(text); + const prefixText = boundary > 0 ? text.slice(0, boundary) : ""; + const suffixText = boundary > 0 ? text.slice(boundary) : text; + + // Only update the prefix when it actually grew — this is what lets the + // Markdown cache hit on every delta once a block is committed. + if (prefixText !== this.committedPrefixText) { + this.committedPrefixText = prefixText; + this.stablePrefix.setText(prefixText); + } + // The suffix always changes on each delta. + this.activeSuffix.setText(suffixText); } } diff --git a/src/tui/components/chat-log.ts b/src/tui/components/chat-log.ts index 41d142e1..18187496 100644 --- a/src/tui/components/chat-log.ts +++ b/src/tui/components/chat-log.ts @@ -1,5 +1,6 @@ import type { Component } from "@earendil-works/pi-tui"; import { Container, Spacer, Text } from "@earendil-works/pi-tui"; +import type { SectionState } from "../tui-types.js"; import { theme } from "../theme/theme.js"; import { AssistantMessageComponent } from "./assistant-message.js"; import { ToolExecutionComponent } from "./tool-execution.js"; @@ -207,4 +208,11 @@ export class ChatLog extends Container { tool.setExpanded(expanded); } } + + setToolSectionState(state: SectionState) { + this.toolsExpanded = state === "expanded"; + for (const tool of this.toolById.values()) { + tool.setSectionState(state); + } + } } diff --git a/src/tui/components/tool-execution.ts b/src/tui/components/tool-execution.ts index 80f71059..df48c41e 100644 --- a/src/tui/components/tool-execution.ts +++ b/src/tui/components/tool-execution.ts @@ -64,7 +64,7 @@ export class ToolExecutionComponent extends Container { private toolName: string; private args: unknown; private result?: ToolResult; - private expanded = false; + private sectionState: import("../tui-types.js").SectionState = "collapsed"; private isError = false; private isPartial = true; @@ -92,10 +92,20 @@ export class ToolExecutionComponent extends Container { } setExpanded(expanded: boolean) { - this.expanded = expanded; + this.sectionState = expanded ? "expanded" : "collapsed"; this.refresh(); } + setSectionState(state: import("../tui-types.js").SectionState) { + this.sectionState = state; + this.refresh(); + } + + /** When hidden, the component renders only the header line. */ + get isHidden(): boolean { + return this.sectionState === "hidden"; + } + setResult(result: ToolResult | undefined, opts?: { isError?: boolean }) { this.result = result; this.isPartial = false; @@ -132,6 +142,14 @@ export class ToolExecutionComponent extends Container { const raw = extractText(this.result); const isDiff = DIFF_TOOLS.has(this.toolName) && raw && !this.isPartial; + // Hidden: only the header line, no output body. + if (this.sectionState === "hidden") { + this.output.setText(""); + return; + } + + const isExpanded = this.sectionState === "expanded"; + if (isDiff) { const colored = renderDiff(raw, { add: theme.success, @@ -145,7 +163,7 @@ export class ToolExecutionComponent extends Container { add: theme.success, del: theme.error, }); - const maxLines = this.expanded ? Infinity : DIFF_PREVIEW_LINES; + const maxLines = isExpanded ? Infinity : DIFF_PREVIEW_LINES; const display = colored.length > maxLines ? [...colored.slice(0, maxLines), "…", statsLine] @@ -157,7 +175,7 @@ export class ToolExecutionComponent extends Container { : this.isPartial ? "…" : ""; - if (!this.expanded && text) { + if (!isExpanded && text) { const lines = text.split("\n"); const preview = lines.length > PREVIEW_LINES ? `${lines.slice(0, PREVIEW_LINES).join("\n")}\n…` : text; diff --git a/src/tui/components/welcome-screen.ts b/src/tui/components/welcome-screen.ts index fe692b50..88cc23ce 100644 --- a/src/tui/components/welcome-screen.ts +++ b/src/tui/components/welcome-screen.ts @@ -137,7 +137,7 @@ export class WelcomeScreen implements Component { ["/help", "all commands"], ["/agents", "switch agents"], ["Ctrl+V", "paste images"], - ["Esc", "abort run"], + ["Ctrl+C", "abort run / exit"], ]; const sessionHeader = bold(accent("Session")); diff --git a/src/tui/paste-grapheme.test.ts b/src/tui/paste-grapheme.test.ts new file mode 100644 index 00000000..767b8e2e --- /dev/null +++ b/src/tui/paste-grapheme.test.ts @@ -0,0 +1,82 @@ +import { describe, expect, it } from "vitest"; + +/** + * No-regression coverage for the paste-collapse and grapheme-aware caret + * behavior inherited from the terminal UI dependency. + * + * Both features are implemented inside the Editor class the TUI extends, so + * these tests pin the environment contract (Intl.Segmenter availability and + * the paste-marker shape) rather than the Editor internals. If either + * contract breaks, the TUI's caret or paste handling degrades silently. + */ + +describe("grapheme-aware caret contract", () => { + it("Intl.Segmenter is available with grapheme granularity", () => { + const segmenter = new Intl.Segmenter("en", { granularity: "grapheme" }); + expect(segmenter).toBeDefined(); + const segments = [...segmenter.segment("ab")]; + expect(segments.length).toBe(2); + }); + + it("treats emoji with skin-tone modifiers as a single grapheme", () => { + // 👩🏻 is woman (U+1F469) + light skin tone (U+1F3FB) — two code points, + // one user-perceived character. The caret must jump over it atomically. + const segmenter = new Intl.Segmenter("en", { granularity: "grapheme" }); + const segments = [...segmenter.segment("👩🏻")]; + expect(segments.length).toBe(1); + }); + + it("treats a flag emoji (regional indicator pair) as a single grapheme", () => { + // 🇲🇽 is U+1F1F2 + U+1F1FD — two regional indicator symbols, one flag. + const segmenter = new Intl.Segmenter("en", { granularity: "grapheme" }); + const segments = [...segmenter.segment("🇲🇽")]; + expect(segments.length).toBe(1); + }); + + it("treats CJK characters as one grapheme each", () => { + const segmenter = new Intl.Segmenter("en", { granularity: "grapheme" }); + const segments = [...segmenter.segment("你好")]; + expect(segments.length).toBe(2); + }); +}); + +/** + * The paste-marker shape used by the Editor to collapse large pastes into a + * single atomic token. The regex must match the formats the Editor emits so + * that cursor movement and submission expansion keep working. If the format + * ever changes upstream, this test surfaces the break. + */ +const PASTE_MARKER_REGEX = /\[paste #(\d+)( (\+\d+ lines|\d+ chars))?\]/; + +describe("paste-collapse marker contract", () => { + it("matches a multi-line paste marker", () => { + expect(PASTE_MARKER_REGEX.test("[paste #1 +42 lines]")).toBe(true); + }); + + it("matches a character-count paste marker", () => { + expect(PASTE_MARKER_REGEX.test("[paste #2 1500 chars]")).toBe(true); + }); + + it("matches a bare paste marker (no count)", () => { + expect(PASTE_MARKER_REGEX.test("[paste #3]")).toBe(true); + }); + + it("does not match arbitrary bracketed text", () => { + expect(PASTE_MARKER_REGEX.test("[not a paste]")).toBe(false); + expect(PASTE_MARKER_REGEX.test("[paste foo]")).toBe(false); + }); + + it("a paste marker is a single atomic grapheme for cursor movement", () => { + // When the Editor segments text containing a paste marker, the marker + // must be treated as one unit so arrow keys jump over it in one press. + // We approximate this by checking the marker has no internal whitespace + // graphemes that a naive split would create. + const marker = "[paste #1 +42 lines]"; + const segmenter = new Intl.Segmenter("en", { granularity: "grapheme" }); + const segments = [...segmenter.segment(marker)]; + // The marker contains spaces, so it has multiple graphemes — the Editor + // applies its own marker-aware segmentation on top. This test documents + // that the marker is a compact, single-line token (no embedded newlines). + expect(segments.some((s) => s.segment.includes("\n"))).toBe(false); + }); +}); diff --git a/src/tui/section-visibility.test.ts b/src/tui/section-visibility.test.ts new file mode 100644 index 00000000..d0f273ff --- /dev/null +++ b/src/tui/section-visibility.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, it } from "vitest"; +import { SECTION_CYCLE, nextSectionState } from "./tui-types.js"; + +describe("nextSectionState", () => { + it("cycles hidden → collapsed", () => { + expect(nextSectionState("hidden")).toBe("collapsed"); + }); + + it("cycles collapsed → expanded", () => { + expect(nextSectionState("collapsed")).toBe("expanded"); + }); + + it("cycles expanded → hidden (wraps around)", () => { + expect(nextSectionState("expanded")).toBe("hidden"); + }); + + it("the cycle covers all three states in order", () => { + expect(SECTION_CYCLE).toEqual(["hidden", "collapsed", "expanded"]); + }); + + it("produces a full cycle back to the start after 3 steps", () => { + let state: "hidden" | "collapsed" | "expanded" = "hidden"; + state = nextSectionState(state); + state = nextSectionState(state); + state = nextSectionState(state); + expect(state).toBe("hidden"); + }); +}); diff --git a/src/tui/stream-boundary.test.ts b/src/tui/stream-boundary.test.ts new file mode 100644 index 00000000..f948eeec --- /dev/null +++ b/src/tui/stream-boundary.test.ts @@ -0,0 +1,69 @@ +import { describe, expect, it } from "vitest"; +import { findStableBoundary } from "./stream-boundary.js"; + +describe("findStableBoundary", () => { + it("returns 0 for empty text", () => { + expect(findStableBoundary("")).toBe(0); + }); + + it("returns 0 for a single paragraph with no blank line", () => { + expect(findStableBoundary("hello world")).toBe(0); + }); + + it("splits at the last blank line between paragraphs", () => { + const text = "first paragraph\n\nsecond paragraph"; + const boundary = findStableBoundary(text); + expect(text.slice(0, boundary)).toBe("first paragraph\n\n"); + expect(text.slice(boundary)).toBe("second paragraph"); + }); + + it("splits at the last of multiple blank lines", () => { + const text = "para one\n\npara two\n\npara three"; + const boundary = findStableBoundary(text); + expect(text.slice(boundary)).toBe("para three"); + }); + + it("keeps an open code fence in the suffix (does not split mid-fence)", () => { + const text = "intro\n\n```ts\nconst x = 1;\n// still in fence"; + const boundary = findStableBoundary(text); + // The blank line before the fence opens is a stable boundary (fence count + // is 0 there), so "intro" becomes the stable prefix and the open fence + // stays in the suffix — which is correct, the prefix is a complete block. + expect(text.slice(0, boundary)).toBe("intro\n\n"); + expect(text.slice(boundary)).toBe("```ts\nconst x = 1;\n// still in fence"); + }); + + it("splits after a closed code fence", () => { + const text = "intro\n\n```ts\nconst x = 1;\n```\n\nnext paragraph"; + const boundary = findStableBoundary(text); + expect(text.slice(boundary)).toBe("next paragraph"); + expect(text.slice(0, boundary)).toContain("```"); + expect(text.slice(0, boundary)).toContain("```ts"); + }); + + it("handles multiple closed fences", () => { + const text = "a\n\n```ts\ncode1\n```\n\nb\n\n```py\ncode2\n```\n\nc"; + const boundary = findStableBoundary(text); + expect(text.slice(boundary)).toBe("c"); + }); + + it("treats tilde fences the same as backtick fences", () => { + const text = "intro\n\n~~~ts\nconst x = 1;\n~~~\n\nafter"; + const boundary = findStableBoundary(text); + expect(text.slice(boundary)).toBe("after"); + }); + + it("returns 0 when the only blank line is inside an open fence", () => { + const text = "```ts\n\nconst x = 1;\n// open"; + const boundary = findStableBoundary(text); + expect(boundary).toBe(0); + }); + + it("handles trailing newlines", () => { + const text = "paragraph\n\n"; + const boundary = findStableBoundary(text); + // The boundary is after the blank line; suffix is empty. + expect(text.slice(0, boundary)).toBe("paragraph\n\n"); + expect(text.slice(boundary)).toBe(""); + }); +}); diff --git a/src/tui/stream-boundary.ts b/src/tui/stream-boundary.ts new file mode 100644 index 00000000..e8fe78c6 --- /dev/null +++ b/src/tui/stream-boundary.ts @@ -0,0 +1,64 @@ +/** + * Stable-boundary detection for incremental markdown streaming. + * + * When streaming a model response, re-parsing the full markdown on every delta + * is O(n²). Splitting the text at the last stable block boundary lets the + * prefix be cached (it never changes once committed) and only the suffix is + * re-parsed per delta, turning the cost into O(n). + * + * A "stable boundary" is a blank line (`\n\n`) that sits outside any open code + * fence, because that is where a markdown block (paragraph, heading, code + * block, list) is guaranteed to be complete. Splitting inside an open fence or + * mid-paragraph would orphan partial tokens and change the rendering. + */ + +const FENCE_LINE = /^\s*(`{3,}|~{3,})/; + +/** + * Count the number of code-fence lines in the text up to (but not including) + * the given end index. An odd count means a fence is currently open. + */ +function fenceCountUpTo(text: string, endIndex: number): number { + let count = 0; + let pos = 0; + while (pos < endIndex) { + const eol = text.indexOf("\n", pos); + const lineEnd = eol === -1 || eol >= endIndex ? endIndex : eol; + const line = text.slice(pos, lineEnd); + if (FENCE_LINE.test(line)) count++; + if (eol === -1 || eol >= endIndex) break; + pos = eol + 1; + } + return count; +} + +/** + * Find the index of the last stable block boundary in the text — the position + * just after a `\n\n` that is outside any open code fence. Returns 0 when no + * stable boundary exists (the entire text is a single in-flight block). + * + * The return value is the start index of the suffix (the unstable part); + * `text.slice(0, result)` is the stable prefix, `text.slice(result)` is the + * suffix. + */ +export function findStableBoundary(text: string): number { + if (!text) return 0; + + // Walk backwards through `\n\n` occurrences, returning the first one that + // sits in an even-fence-count region (i.e. outside any open fence). + let searchFrom = text.length; + while (searchFrom > 0) { + const boundary = text.lastIndexOf("\n\n", searchFrom - 1); + if (boundary === -1) return 0; + + // The boundary is stable only if fences are balanced before it. + const fencesBefore = fenceCountUpTo(text, boundary); + if (fencesBefore % 2 === 0) { + return boundary + 2; // start of the block after the blank line + } + + // Inside an open fence — keep walking back. + searchFrom = boundary; + } + return 0; +} diff --git a/src/tui/term-capabilities.test.ts b/src/tui/term-capabilities.test.ts index d75d3dcb..8cff30ca 100644 --- a/src/tui/term-capabilities.test.ts +++ b/src/tui/term-capabilities.test.ts @@ -1,5 +1,11 @@ -import { describe, expect, it } from "vitest"; -import { detectKeyboardProtocol, enableKeyboardProtocol } from "./term-capabilities.js"; +import { describe, expect, it, vi } from "vitest"; +import { + detectKeyboardProtocol, + detectTerminalColorScheme, + enableKeyboardProtocol, + relativeLuminance, + type TerminalColorQuerier, +} from "./term-capabilities.js"; describe("detectKeyboardProtocol", () => { it("returns kitty for kitty/WezTerm/ghostty terminals", () => { @@ -84,3 +90,60 @@ describe("enableKeyboardProtocol", () => { } }); }); + +describe("relativeLuminance", () => { + it("returns ~0 for black", () => { + expect(relativeLuminance({ r: 0, g: 0, b: 0 })).toBeCloseTo(0, 1); + }); + + it("returns ~1 for white", () => { + expect(relativeLuminance({ r: 255, g: 255, b: 255 })).toBeCloseTo(1, 1); + }); + + it("weights green more than red and blue (Rec. 709)", () => { + const lum = relativeLuminance({ r: 0, g: 255, b: 0 }); + expect(lum).toBeGreaterThan(0.7); + }); + + it("classifies a dark navy background as dark (< 0.5)", () => { + expect(relativeLuminance({ r: 30, g: 30, b: 40 })).toBeLessThan(0.5); + }); +}); + +describe("detectTerminalColorScheme", () => { + function makeQuerier( + scheme: "dark" | "light" | undefined, + bg: { r: number; g: number; b: number } | undefined, + ): TerminalColorQuerier { + return { + queryTerminalColorScheme: vi.fn().mockResolvedValue(scheme), + queryTerminalBackgroundColor: vi.fn().mockResolvedValue(bg), + }; + } + + it("returns the DSR scheme when available (dark)", async () => { + const tui = makeQuerier("dark", undefined); + expect(await detectTerminalColorScheme(tui)).toBe("dark"); + }); + + it("returns the DSR scheme when available (light)", async () => { + const tui = makeQuerier("light", undefined); + expect(await detectTerminalColorScheme(tui)).toBe("light"); + }); + + it("falls back to OSC 11 luminance when DSR is unsupported", async () => { + // DSR returns undefined; bright background → light + const tui = makeQuerier(undefined, { r: 250, g: 250, b: 250 }); + expect(await detectTerminalColorScheme(tui)).toBe("light"); + }); + + it("classifies a dark background via OSC 11", async () => { + const tui = makeQuerier(undefined, { r: 20, g: 20, b: 25 }); + expect(await detectTerminalColorScheme(tui)).toBe("dark"); + }); + + it("falls back to dark when neither query responds", async () => { + const tui = makeQuerier(undefined, undefined); + expect(await detectTerminalColorScheme(tui)).toBe("dark"); + }); +}); diff --git a/src/tui/term-capabilities.ts b/src/tui/term-capabilities.ts index 3d2f2c3b..6234acf4 100644 --- a/src/tui/term-capabilities.ts +++ b/src/tui/term-capabilities.ts @@ -17,6 +17,14 @@ import process from "node:process"; +/** Minimal surface of the TUI instance needed for terminal color queries. */ +export type TerminalColorQuerier = { + queryTerminalColorScheme(opts: { timeoutMs: number }): Promise<"dark" | "light" | undefined>; + queryTerminalBackgroundColor(opts: { + timeoutMs: number; + }): Promise<{ r: number; g: number; b: number } | undefined>; +}; + /** Terminal identifiers that reliably support an extended keyboard protocol. */ const EXTENDED_KEY_TERMINALS = new Set([ "iTerm.app", @@ -120,3 +128,41 @@ export function enableKeyboardProtocol( }, }; } + +// --------------------------------------------------------------------------- +// Terminal color-scheme detection (dark/light auto-theme) +// --------------------------------------------------------------------------- + +/** + * Compute the relative luminance of an RGB color using the Rec. 709 weighting. + * Values >= 0.5 are considered "light" backgrounds. + */ +export function relativeLuminance(rgb: { r: number; g: number; b: number }): number { + return (0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b) / 255; +} + +/** + * Detect whether the terminal has a dark or light background, using the best + * available signal. Returns "dark" when no signal is available (the prior + * default). + * + * Query ladder, fastest signal wins: + * 1. DSR color-scheme (`CSI ? 996 n`) — terminals reply with a direct + * dark/light answer. Cleanest signal when supported. + * 2. OSC 11 background color — parse the RGB reply and compute luminance. + * 3. Fallback to "dark". + * + * Both queries are run concurrently and each has a 150 ms timeout, so an + * unresponsive terminal adds at most ~150 ms to startup before falling back. + */ +export async function detectTerminalColorScheme( + tui: TerminalColorQuerier, +): Promise<"dark" | "light"> { + const [scheme, bg] = await Promise.all([ + tui.queryTerminalColorScheme({ timeoutMs: 150 }), + tui.queryTerminalBackgroundColor({ timeoutMs: 150 }), + ]); + if (scheme === "dark" || scheme === "light") return scheme; + if (bg) return relativeLuminance(bg) >= 0.5 ? "light" : "dark"; + return "dark"; +} diff --git a/src/tui/tui-event-handlers.test.ts b/src/tui/tui-event-handlers.test.ts index 11409889..fe1c60a0 100644 --- a/src/tui/tui-event-handlers.test.ts +++ b/src/tui/tui-event-handlers.test.ts @@ -40,6 +40,8 @@ describe("tui-event-handlers: handleAgentEvent", () => { autoMessageSent: false, toolsExpanded: false, showThinking: false, + toolSectionState: "collapsed", + thinkingSectionState: "collapsed", connectionStatus: "connected", activityStatus: "idle", statusTimeout: null, diff --git a/src/tui/tui-session-actions.test.ts b/src/tui/tui-session-actions.test.ts index b28cf92a..47f96d3c 100644 --- a/src/tui/tui-session-actions.test.ts +++ b/src/tui/tui-session-actions.test.ts @@ -39,6 +39,8 @@ describe("tui session actions", () => { autoMessageSent: false, toolsExpanded: false, showThinking: false, + toolSectionState: "collapsed", + thinkingSectionState: "collapsed", pendingImages: new Map(), connectionStatus: "connected", activityStatus: "idle", diff --git a/src/tui/tui-types.ts b/src/tui/tui-types.ts index a9c27d6c..e3bb69c3 100644 --- a/src/tui/tui-types.ts +++ b/src/tui/tui-types.ts @@ -1,3 +1,21 @@ +/** + * Per-section detail visibility. Replaces the previous binary expanded/not + * with a three-state model: + * - "hidden": the section renders only a header line (or nothing). + * - "collapsed": a bounded preview (tool output: first N lines). + * - "expanded": full content. + */ +export type SectionState = "hidden" | "collapsed" | "expanded"; + +export type SectionKey = "thinking" | "tools"; + +export const SECTION_CYCLE: SectionState[] = ["hidden", "collapsed", "expanded"]; + +export function nextSectionState(current: SectionState): SectionState { + const idx = SECTION_CYCLE.indexOf(current); + return SECTION_CYCLE[(idx + 1) % SECTION_CYCLE.length]; +} + export type TuiOptions = { url?: string; token?: string; @@ -109,6 +127,9 @@ export type TuiStateAccess = { autoMessageSent: boolean; toolsExpanded: boolean; showThinking: boolean; + /** Per-section detail visibility (the source of truth; toolsExpanded/showThinking are shims). */ + toolSectionState: SectionState; + thinkingSectionState: SectionState; connectionStatus: string; activityStatus: string; statusTimeout: ReturnType | null; diff --git a/src/tui/tui.ts b/src/tui/tui.ts index 872eb8e5..ca5e3eb6 100644 --- a/src/tui/tui.ts +++ b/src/tui/tui.ts @@ -27,6 +27,7 @@ import { CustomEditor } from "./components/custom-editor.js"; import { WelcomeScreen } from "./components/welcome-screen.js"; import { GatewayChatClient } from "./gateway-chat.js"; import { enableKeyboardProtocol } from "./term-capabilities.js"; +import { detectTerminalColorScheme } from "./term-capabilities.js"; import type { ThemePreset } from "./theme/palettes.js"; import { THEME_PRESETS } from "./theme/palettes.js"; import { editorTheme, theme, setThemePreset } from "./theme/theme.js"; @@ -41,11 +42,13 @@ import { createSessionActions } from "./tui-session-actions.js"; import type { AgentSummary, PendingImage, + SectionState, SessionInfo, SessionScope, TuiOptions, TuiStateAccess, } from "./tui-types.js"; +import { nextSectionState } from "./tui-types.js"; import { buildWaitingStatusMessage, defaultWaitingPhrases } from "./tui-waiting.js"; export { resolveFinalAssistantText } from "./tui-formatters.js"; @@ -280,7 +283,10 @@ export async function runTui(opts: TuiOptions) { } const configTheme = config.ui?.theme; - if (configTheme && THEME_PRESETS.includes(configTheme as ThemePreset)) { + // "auto" (or unset) defers to terminal color-scheme detection after the TUI + // instance is created; until then the default "dark" preset is in place. + const themeIsAuto = !configTheme || configTheme === "auto"; + if (!themeIsAuto && THEME_PRESETS.includes(configTheme as ThemePreset)) { setThemePreset(configTheme as ThemePreset); } const keybindingsConfig = config.ui?.keybindings; @@ -302,6 +308,8 @@ export async function runTui(opts: TuiOptions) { let wasDisconnected = false; let toolsExpanded = false; let showThinking = false; + let toolSectionState: SectionState = "collapsed"; + let thinkingSectionState: SectionState = "collapsed"; let pairingHintShown = false; let gatewayDownHintShown = false; let outputStyle: string | undefined; @@ -421,6 +429,18 @@ export async function runTui(opts: TuiOptions) { set showThinking(value) { showThinking = value; }, + get toolSectionState() { + return toolSectionState; + }, + set toolSectionState(value) { + toolSectionState = value; + }, + get thinkingSectionState() { + return thinkingSectionState; + }, + set thinkingSectionState(value) { + thinkingSectionState = value; + }, get connectionStatus() { return connectionStatus; }, @@ -518,6 +538,13 @@ export async function runTui(opts: TuiOptions) { }); const tui = new TUI(new ProcessTerminal()); + // Auto-detect the terminal's dark/light preference before the first render. + // Queries run concurrently with a short timeout, so an unresponsive terminal + // falls back to the default "dark" preset without blocking startup. + if (themeIsAuto) { + const detected = await detectTerminalColorScheme(tui); + setThemePreset(detected); + } const dedupeBackspace = createBackspaceDeduper(); tui.addInputListener((data) => { const next = dedupeBackspace(data); @@ -937,9 +964,10 @@ export async function runTui(opts: TuiOptions) { process.exit(0); }; editor.onCtrlO = () => { - toolsExpanded = !toolsExpanded; - chatLog.setToolsExpanded(toolsExpanded); - setActivityStatus(toolsExpanded ? "tools expanded" : "tools collapsed"); + toolSectionState = nextSectionState(toolSectionState); + toolsExpanded = toolSectionState === "expanded"; + chatLog.setToolSectionState(toolSectionState); + setActivityStatus(`tools: ${toolSectionState}`); tui.requestRender(); }; editor.onCtrlL = () => { @@ -952,7 +980,12 @@ export async function runTui(opts: TuiOptions) { void openSessionSelector(); }; editor.onCtrlT = () => { - showThinking = !showThinking; + thinkingSectionState = nextSectionState(thinkingSectionState); + // Thinking text is baked into the assistant message at compose time, so + // toggling requires reloading history. "hidden" suppresses thinking; + // "collapsed" and "expanded" both show it (a truncated mode would require + // restructuring the composer — deferred to a follow-up). + showThinking = thinkingSectionState !== "hidden"; void loadHistory(); }; editor.onShiftTab = () => { From ea1b5b4c99fdf7d5020e6eec9c31a978be338da7 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Tue, 14 Jul 2026 05:30:04 +0200 Subject: [PATCH 12/14] feat(tui): disable vim mode and remove dead code (#70) The vim mode implementation was structurally broken: the editor bridge that connects vim motions to the buffer was never wired, so every editing operation silently no-op'd while the mode indicator claimed vim was active. Keys were consumed without editing, leaving users with a non-functional editor. Disable vim honestly instead of leaving the broken experience: /vim now reports that the feature is unavailable, the dead handler and tests are removed (730 LOC), all vim wiring is stripped from the TUI, the config flag is deprecated, and docs are updated. Emacs/readline-style keybindings remain available. --- README.md | 19 +- docs/platforms/tui-redesign.md | 2 +- src/config/types.mayros.ts | 2 +- src/tui/commands.ts | 2 +- src/tui/components/custom-editor.ts | 12 - src/tui/keybinding-resolver.test.ts | 5 +- src/tui/keybinding-resolver.ts | 4 +- src/tui/tui-command-handlers.ts | 4 +- src/tui/tui.ts | 16 +- src/tui/vim-handler.test.ts | 302 -------------------- src/tui/vim-handler.ts | 428 ---------------------------- 11 files changed, 17 insertions(+), 779 deletions(-) delete mode 100644 src/tui/vim-handler.test.ts delete mode 100644 src/tui/vim-handler.ts diff --git a/README.md b/README.md index a1f15900..360b393a 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,6 @@ mayros -p "refactor auth flow" # headless mode (non-interactive) - 🎨 3 themes (dark, light, high-contrast) — `/theme` - 📝 3 output styles (standard, explanatory, learning) — `/style` -- ⌨️ Vim mode with motions, operators, undo — `/vim` - 📋 `Ctrl+V` image paste from clipboard - 📊 `/diff` inline diff viewer · `/context` token usage chart - 🗺️ `/plan` semantic plan mode (Cortex-backed) @@ -165,15 +164,15 @@ mayros -p "refactor auth flow" # headless mode (non-interactive) **Slash commands (30+):** -| Command | Description | Command | Description | -| ---------------- | ----------------- | ---------------- | -------------------- | -| `/help` | List all commands | `/plan` | Semantic plan mode | -| `/new` | Reset session | `/diff` | Show pending changes | -| `/compact` | Compact context | `/context` | Token usage chart | -| `/think ` | Set thinking | `/theme` | Cycle themes | -| `/model ` | Switch model | `/vim` | Toggle vim mode | -| `/permission` | Permission mode | `/copy` | Copy last response | -| `/fast` | Fast mode | `/export [file]` | Export session | +| Command | Description | Command | Description | +| ---------------- | ----------------- | ------------- | -------------------- | +| `/help` | List all commands | `/plan` | Semantic plan mode | +| `/new` | Reset session | `/diff` | Show pending changes | +| `/compact` | Compact context | `/context` | Token usage chart | +| `/think ` | Set thinking | `/theme` | Cycle themes | +| `/model ` | Switch model | `/permission` | Permission mode | +| `/fast` | Fast mode | `/copy` | Copy last response | +| `/export [file]` | Export session | `/context` | Token usage chart | **Markdown-driven extensibility:** diff --git a/docs/platforms/tui-redesign.md b/docs/platforms/tui-redesign.md index edc609c2..e98a9834 100644 --- a/docs/platforms/tui-redesign.md +++ b/docs/platforms/tui-redesign.md @@ -81,7 +81,7 @@ Priorities are assigned as P0 (correctness or blocker), P1 (high-value polish), ### P0 — Correctness and blockers -1. **Verify the vim bridge is connected.** If the editor bridge is never set from the TUI side, every vim motion that relies on it silently no-ops. Confirm or fix before any further vim work. +1. ~~**Verify the vim bridge is connected.**~~ **Resolved: vim mode has been disabled.** The bridge was never wired and the rendering dependency does not expose the cursor API needed to fix it cleanly. The `/vim` command now reports that the feature is unavailable, the dead handler and its tests have been removed, and the config flag is deprecated. Emacs/readline-style keybindings (Ctrl+A/E/W/U/K) remain available via the editor. 2. **Accessibility TUI feature parity.** Either linearize the graphical renderer for screen readers or bring slash commands, session switching, and abort into the accessibility TUI. The current split excludes users from most functionality. ### P1 — High-value polish diff --git a/src/config/types.mayros.ts b/src/config/types.mayros.ts index ec33a448..b77abeab 100644 --- a/src/config/types.mayros.ts +++ b/src/config/types.mayros.ts @@ -70,7 +70,7 @@ export type MayrosConfig = { seamColor?: string; /** TUI color theme preset, or "auto" to detect from the terminal. */ theme?: "auto" | "dark" | "light" | "high-contrast"; - /** Enable vim editing mode in the TUI. */ + /** Deprecated: vim mode is not available. Kept for config backward compat. */ vim?: boolean; /** Custom keybindings for TUI actions. */ keybindings?: Record; diff --git a/src/tui/commands.ts b/src/tui/commands.ts index 4ee2c107..e10f4273 100644 --- a/src/tui/commands.ts +++ b/src/tui/commands.ts @@ -148,7 +148,7 @@ export function getSlashCommands(options: SlashCommandOptions = {}): SlashComman }, { name: "vim", - description: "Toggle vim editing mode", + description: "Vim mode (unavailable)", }, { name: "permission", diff --git a/src/tui/components/custom-editor.ts b/src/tui/components/custom-editor.ts index 6cf0ecbc..02095400 100644 --- a/src/tui/components/custom-editor.ts +++ b/src/tui/components/custom-editor.ts @@ -1,7 +1,6 @@ import { Editor, Key, matchesKey } from "@earendil-works/pi-tui"; import type { ClipboardImage } from "../clipboard-image.js"; import type { TuiKeybindingResolver } from "../keybinding-resolver.js"; -import type { VimHandler } from "../vim-handler.js"; const BRACKET_PASTE_START = "\x1b[200~"; const BRACKET_PASTE_END = "\x1b[201~"; @@ -25,7 +24,6 @@ export class CustomEditor extends Editor { onAltEnter?: () => void; onImagePaste?: (image: ImagePasteEvent) => void; tuiResolver?: TuiKeybindingResolver; - vimHandler?: VimHandler; private imageCounter = 0; captureClipboardImage: (() => ClipboardImage | null) | null = null; @@ -58,12 +56,6 @@ export class CustomEditor extends Editor { // No image on clipboard — ignore the empty paste return; } - // Vim mode intercept: if vim is in normal mode, consume keys there. - if (this.vimHandler?.isNormalMode()) { - if (this.vimHandler.handleKey(data)) { - return; - } - } if (matchesKey(data, Key.alt("enter")) && this.onAltEnter) { this.onAltEnter(); return; @@ -118,10 +110,6 @@ export class CustomEditor extends Editor { return; } if (matchesKey(data, Key.escape) && !this.isShowingAutocomplete()) { - // In vim insert mode, Escape switches to normal mode - if (this.vimHandler && this.vimHandler.handleKey(data)) { - return; - } if (this.onEscape) { this.onEscape(); return; diff --git a/src/tui/keybinding-resolver.test.ts b/src/tui/keybinding-resolver.test.ts index db5b4c5b..f02a1189 100644 --- a/src/tui/keybinding-resolver.test.ts +++ b/src/tui/keybinding-resolver.test.ts @@ -56,9 +56,9 @@ describe("TuiKeybindingResolver", () => { expect(piTuiMocks.matchesKey).toHaveBeenCalledWith("\x07", "ctrl+g"); }); - it("returns false when action has no keys", () => { + it("returns false when the data does not match any action", () => { const resolver = new TuiKeybindingResolver(); - expect(resolver.matches("\x00", "toggleVim")).toBe(false); + expect(resolver.matches("\x00", "toggleTools")).toBe(false); }); }); @@ -69,7 +69,6 @@ describe("DEFAULT_TUI_KEYBINDINGS", () => { expect(DEFAULT_TUI_KEYBINDINGS).toHaveProperty("selectSession"); expect(DEFAULT_TUI_KEYBINDINGS).toHaveProperty("toggleTools"); expect(DEFAULT_TUI_KEYBINDINGS).toHaveProperty("toggleThinking"); - expect(DEFAULT_TUI_KEYBINDINGS).toHaveProperty("toggleVim"); }); }); diff --git a/src/tui/keybinding-resolver.ts b/src/tui/keybinding-resolver.ts index 669c27ce..bd8c2dd3 100644 --- a/src/tui/keybinding-resolver.ts +++ b/src/tui/keybinding-resolver.ts @@ -12,8 +12,7 @@ export type TuiAction = | "selectModel" | "selectSession" | "toggleTools" - | "toggleThinking" - | "toggleVim"; + | "toggleThinking"; export const DEFAULT_TUI_KEYBINDINGS: Record = { selectAgent: "ctrl+g", @@ -21,7 +20,6 @@ export const DEFAULT_TUI_KEYBINDINGS: Record = { selectSession: "ctrl+p", toggleTools: "ctrl+o", toggleThinking: "ctrl+t", - toggleVim: "ctrl+shift+v", }; export class TuiKeybindingResolver { diff --git a/src/tui/tui-command-handlers.ts b/src/tui/tui-command-handlers.ts index b67b5091..aa83d21c 100644 --- a/src/tui/tui-command-handlers.ts +++ b/src/tui/tui-command-handlers.ts @@ -773,9 +773,7 @@ export function createCommandHandlers(context: CommandHandlerContext) { } break; case "vim": { - const enabled = !state.vimEnabled; - state.vimEnabled = enabled; - chatLog.addSystem(`vim mode ${enabled ? "enabled" : "disabled"}`); + chatLog.addSystem("vim mode is not available in this build"); break; } case "permission": { diff --git a/src/tui/tui.ts b/src/tui/tui.ts index ca5e3eb6..88438ac2 100644 --- a/src/tui/tui.ts +++ b/src/tui/tui.ts @@ -34,7 +34,6 @@ import { editorTheme, theme, setThemePreset } from "./theme/theme.js"; import { createCommandHandlers } from "./tui-command-handlers.js"; import { createEventHandlers } from "./tui-event-handlers.js"; import { MouseHandler, createMouseInputListener } from "./mouse-handler.js"; -import { VimHandler } from "./vim-handler.js"; import { formatTokens } from "./tui-formatters.js"; import { createLocalShellRunner } from "./tui-local-shell.js"; import { createOverlayHandlers } from "./tui-overlays.js"; @@ -316,8 +315,7 @@ export async function runTui(opts: TuiOptions) { let permissionMode: "auto" | "ask" | "deny" = "auto"; let fastMode = false; let previousThinkingLevel: string | undefined; - let vimEnabled = config.ui?.vim ?? false; - const vimHandler = new VimHandler(); + let vimEnabled = false; const mouseHandler = new MouseHandler({ scrollLines: 3, scrollAcceleration: true, @@ -476,12 +474,6 @@ export async function runTui(opts: TuiOptions) { }, set vimEnabled(value) { vimEnabled = value ?? false; - if (vimEnabled) { - vimHandler.enable(); - } else { - vimHandler.disable(); - } - updateFooter(); }, get permissionMode() { return permissionMode; @@ -560,14 +552,10 @@ export async function runTui(opts: TuiOptions) { const chatLog = new ChatLog(); const editor = new CustomEditor(tui, editorTheme); editor.tuiResolver = tuiResolver; - editor.vimHandler = vimHandler; editor.captureClipboardImage = captureClipboardImage; editor.onImagePaste = (img) => { pendingImages.set(img.marker, { base64: img.base64, mimeType: img.mimeType }); }; - if (vimEnabled) { - vimHandler.enable(); - } // Mouse scroll → ChatLog scroll + re-render mouseHandler.onScroll((direction, lines) => { @@ -818,7 +806,6 @@ export async function runTui(opts: TuiOptions) { const reasoning = sessionInfo.reasoningLevel ?? "off"; const reasoningLabel = reasoning === "on" ? "reasoning" : reasoning === "stream" ? "reasoning:stream" : null; - const vimLabel = vimEnabled ? vimHandler.getModeIndicator() : null; const permLabel = permissionMode !== "auto" ? `perm ${permissionMode}` : null; const fastLabel = fastMode ? "FAST" : null; const footerParts = [ @@ -829,7 +816,6 @@ export async function runTui(opts: TuiOptions) { verbose !== "off" ? `verbose ${verbose}` : null, reasoningLabel, tokens, - vimLabel, permLabel, fastLabel, ].filter(Boolean); diff --git a/src/tui/vim-handler.test.ts b/src/tui/vim-handler.test.ts deleted file mode 100644 index 978639c9..00000000 --- a/src/tui/vim-handler.test.ts +++ /dev/null @@ -1,302 +0,0 @@ -import { describe, expect, it, beforeEach } from "vitest"; -import { VimHandler } from "./vim-handler.js"; -import type { EditorBridge } from "./vim-handler.js"; - -function createMockBridge(initialText = ""): EditorBridge & { - text: string; - line: number; - col: number; -} { - const state = { text: initialText, line: 0, col: 0 }; - return { - get text() { - return state.text; - }, - set text(v) { - state.text = v; - }, - get line() { - return state.line; - }, - set line(v) { - state.line = v; - }, - get col() { - return state.col; - }, - set col(v) { - state.col = v; - }, - getText: () => state.text, - setText: (v) => { - state.text = v; - }, - getCursorPosition: () => ({ line: state.line, col: state.col }), - setCursorPosition: (l, c) => { - state.line = l; - state.col = c; - }, - }; -} - -describe("VimHandler", () => { - let vim: VimHandler; - let bridge: ReturnType; - - beforeEach(() => { - vim = new VimHandler(); - bridge = createMockBridge("hello world"); - vim.setBridge(bridge); - }); - - describe("mode management", () => { - it("starts in insert mode", () => { - expect(vim.getMode()).toBe("insert"); - expect(vim.isNormalMode()).toBe(false); - }); - - it("switches to normal mode on enable()", () => { - vim.enable(); - expect(vim.getMode()).toBe("normal"); - expect(vim.isNormalMode()).toBe(true); - }); - - it("switches to insert mode on disable()", () => { - vim.enable(); - vim.disable(); - expect(vim.getMode()).toBe("insert"); - }); - - it("shows correct mode indicator", () => { - expect(vim.getModeIndicator()).toBe("-- INSERT --"); - vim.enable(); - expect(vim.getModeIndicator()).toBe("-- NORMAL --"); - }); - }); - - describe("insert mode", () => { - it("does not consume regular keys", () => { - expect(vim.handleKey("a")).toBe(false); - expect(vim.handleKey("x")).toBe(false); - }); - - it("consumes Escape to switch to normal", () => { - expect(vim.handleKey("\x1b")).toBe(true); - expect(vim.getMode()).toBe("normal"); - }); - }); - - describe("normal mode — mode switching", () => { - beforeEach(() => { - vim.enable(); - }); - - it("i switches to insert", () => { - expect(vim.handleKey("i")).toBe(true); - expect(vim.getMode()).toBe("insert"); - }); - - it("a switches to insert and moves cursor right", () => { - bridge.col = 2; - vim.handleKey("a"); - expect(vim.getMode()).toBe("insert"); - expect(bridge.col).toBe(3); - }); - - it("I switches to insert and moves to line start", () => { - bridge.col = 5; - vim.handleKey("I"); - expect(vim.getMode()).toBe("insert"); - expect(bridge.col).toBe(0); - }); - - it("A switches to insert and moves to line end", () => { - vim.handleKey("A"); - expect(vim.getMode()).toBe("insert"); - expect(bridge.col).toBe(11); // "hello world".length - }); - - it("o inserts line below and enters insert mode", () => { - vim.handleKey("o"); - expect(vim.getMode()).toBe("insert"); - expect(bridge.text).toBe("hello world\n"); - expect(bridge.line).toBe(1); - }); - - it("O inserts line above and enters insert mode", () => { - vim.handleKey("O"); - expect(vim.getMode()).toBe("insert"); - expect(bridge.text).toBe("\nhello world"); - expect(bridge.line).toBe(0); - }); - }); - - describe("normal mode — cursor motions", () => { - beforeEach(() => { - vim.enable(); - bridge.col = 5; - }); - - it("h moves cursor left", () => { - vim.handleKey("h"); - expect(bridge.col).toBe(4); - }); - - it("l moves cursor right", () => { - vim.handleKey("l"); - expect(bridge.col).toBe(6); - }); - - it("0 moves to line start", () => { - vim.handleKey("0"); - expect(bridge.col).toBe(0); - }); - - it("$ moves to line end", () => { - vim.handleKey("$"); - expect(bridge.col).toBe(11); - }); - - it("j moves down", () => { - bridge.text = "line1\nline2"; - bridge.line = 0; - bridge.col = 2; - vim.handleKey("j"); - expect(bridge.line).toBe(1); - }); - - it("k moves up", () => { - bridge.text = "line1\nline2"; - bridge.line = 1; - bridge.col = 0; - vim.handleKey("k"); - expect(bridge.line).toBe(0); - }); - - it("w moves to next word", () => { - bridge.col = 0; - vim.handleKey("w"); - expect(bridge.col).toBe(6); // start of "world" - }); - - it("b moves to previous word start", () => { - bridge.col = 8; - vim.handleKey("b"); - expect(bridge.col).toBe(6); // start of "world" - }); - }); - - describe("normal mode — count prefix", () => { - beforeEach(() => { - vim.enable(); - bridge.col = 0; - }); - - it("3l moves cursor 3 right", () => { - vim.handleKey("3"); - vim.handleKey("l"); - expect(bridge.col).toBe(3); - }); - - it("2h moves cursor 2 left", () => { - bridge.col = 5; - vim.handleKey("2"); - vim.handleKey("h"); - expect(bridge.col).toBe(3); - }); - }); - - describe("normal mode — editing", () => { - beforeEach(() => { - vim.enable(); - }); - - it("x deletes char at cursor", () => { - bridge.col = 0; - vim.handleKey("x"); - expect(bridge.text).toBe("ello world"); - }); - - it("D deletes to end of line", () => { - bridge.col = 5; - vim.handleKey("D"); - expect(bridge.text).toBe("hello"); - }); - - it("C deletes to end and enters insert", () => { - bridge.col = 5; - vim.handleKey("C"); - expect(bridge.text).toBe("hello"); - expect(vim.getMode()).toBe("insert"); - }); - - it("dd deletes entire line", () => { - bridge.text = "first\nsecond\nthird"; - bridge.line = 1; - vim.handleKey("d"); - vim.handleKey("d"); - expect(bridge.text).toBe("first\nthird"); - }); - - it("cc deletes line and enters insert", () => { - bridge.text = "first\nsecond\nthird"; - bridge.line = 1; - vim.handleKey("c"); - vim.handleKey("c"); - expect(bridge.text).toBe("first\nthird"); - expect(vim.getMode()).toBe("insert"); - }); - - it("yy + p yanks and pastes line", () => { - bridge.text = "hello"; - bridge.col = 2; - vim.handleKey("y"); - vim.handleKey("y"); - vim.handleKey("p"); - // Paste inserts after cursor (col 2): "hel" + "hello" + "lo" - expect(bridge.text).toBe("helhellolo"); - }); - - it("u undoes last edit", () => { - bridge.col = 0; - vim.handleKey("x"); - expect(bridge.text).toBe("ello world"); - vim.handleKey("u"); - expect(bridge.text).toBe("hello world"); - }); - }); - - describe("normal mode — key consumption", () => { - beforeEach(() => { - vim.enable(); - }); - - it("all known keys are consumed", () => { - for (const key of [ - "h", - "j", - "k", - "l", - "w", - "b", - "0", - "$", - "i", - "a", - "x", - "u", - "p", - "D", - "C", - ]) { - const result = vim.handleKey(key); - expect(result, `key '${key}' should be consumed`).toBe(true); - vim.enable(); // Reset to normal mode - } - }); - - it("unknown keys are still consumed in normal mode", () => { - expect(vim.handleKey("z")).toBe(true); - }); - }); -}); diff --git a/src/tui/vim-handler.ts b/src/tui/vim-handler.ts deleted file mode 100644 index fa0d2938..00000000 --- a/src/tui/vim-handler.ts +++ /dev/null @@ -1,428 +0,0 @@ -export type VimMode = "normal" | "insert"; - -type MotionResult = - | { - type: "cursor"; - delta: number; - } - | { - type: "line-start" | "line-end" | "word-forward" | "word-backward"; - }; - -type OperatorPending = "d" | "c" | "y" | null; - -export type VimState = { - mode: VimMode; - countPrefix: string; - operator: OperatorPending; - lastYank: string; -}; - -export type EditorBridge = { - getText: () => string; - setText: (value: string) => void; - getCursorPosition: () => { line: number; col: number }; - setCursorPosition: (line: number, col: number) => void; -}; - -export class VimHandler { - private state: VimState; - private bridge: EditorBridge | null = null; - private undoStack: string[] = []; - private maxUndo = 50; - - constructor() { - this.state = { - mode: "insert", - countPrefix: "", - operator: null, - lastYank: "", - }; - } - - setBridge(bridge: EditorBridge): void { - this.bridge = bridge; - } - - getMode(): VimMode { - return this.state.mode; - } - - getModeIndicator(): string { - return this.state.mode === "normal" ? "-- NORMAL --" : "-- INSERT --"; - } - - isNormalMode(): boolean { - return this.state.mode === "normal"; - } - - enable(): void { - this.state.mode = "normal"; - this.state.countPrefix = ""; - this.state.operator = null; - } - - disable(): void { - this.state.mode = "insert"; - this.state.countPrefix = ""; - this.state.operator = null; - } - - /** - * Handle a keypress in vim mode. - * Returns true if the key was consumed (not passed to editor). - */ - handleKey(key: string): boolean { - if (this.state.mode === "insert") { - // Escape → switch to normal mode - if (key === "\x1b" || key === "\u001b") { - this.state.mode = "normal"; - this.state.countPrefix = ""; - this.state.operator = null; - return true; - } - return false; - } - - // Normal mode - return this.handleNormalMode(key); - } - - private getCount(): number { - const n = parseInt(this.state.countPrefix, 10); - this.state.countPrefix = ""; - return isNaN(n) || n < 1 ? 1 : Math.min(n, 999); - } - - private pushUndo(): void { - if (!this.bridge) return; - const text = this.bridge.getText(); - this.undoStack.push(text); - if (this.undoStack.length > this.maxUndo) { - this.undoStack.shift(); - } - } - - private handleNormalMode(key: string): boolean { - // Count prefix accumulation - if (/^[1-9]$/.test(key) || (this.state.countPrefix.length > 0 && /^[0-9]$/.test(key))) { - this.state.countPrefix += key; - return true; - } - - // Operator pending (d, c, y) - if (this.state.operator === null && (key === "d" || key === "c" || key === "y")) { - this.state.operator = key; - return true; - } - - // dd, cc, yy — whole-line operations - if (this.state.operator && key === this.state.operator) { - const count = this.getCount(); - this.handleLinewiseOp(this.state.operator, count); - this.state.operator = null; - return true; - } - - // operator + motion - if (this.state.operator) { - const motion = this.resolveMotion(key); - if (motion) { - this.handleOperatorMotion(this.state.operator, motion); - this.state.operator = null; - return true; - } - // Invalid motion — cancel operator - this.state.operator = null; - this.state.countPrefix = ""; - return true; - } - - const count = this.getCount(); - - // Mode switches - switch (key) { - case "i": - this.state.mode = "insert"; - return true; - case "a": - this.state.mode = "insert"; - this.moveCursor(1); - return true; - case "I": - this.state.mode = "insert"; - this.moveToLineStart(); - return true; - case "A": - this.state.mode = "insert"; - this.moveToLineEnd(); - return true; - case "o": - this.state.mode = "insert"; - this.insertLineBelow(); - return true; - case "O": - this.state.mode = "insert"; - this.insertLineAbove(); - return true; - } - - // Motions - switch (key) { - case "h": - this.moveCursor(-count); - return true; - case "l": - this.moveCursor(count); - return true; - case "j": - this.moveVertical(count); - return true; - case "k": - this.moveVertical(-count); - return true; - case "w": - for (let i = 0; i < count; i++) this.moveWordForward(); - return true; - case "b": - for (let i = 0; i < count; i++) this.moveWordBackward(); - return true; - case "0": - this.moveToLineStart(); - return true; - case "$": - this.moveToLineEnd(); - return true; - } - - // Editing commands - switch (key) { - case "x": - this.deleteCharsAtCursor(count); - return true; - case "D": - this.deleteToEndOfLine(); - return true; - case "C": - this.deleteToEndOfLine(); - this.state.mode = "insert"; - return true; - case "p": - this.paste(); - return true; - case "u": - this.undo(); - return true; - } - - return true; - } - - private resolveMotion(key: string): MotionResult | null { - switch (key) { - case "h": - return { type: "cursor", delta: -1 }; - case "l": - return { type: "cursor", delta: 1 }; - case "w": - return { type: "word-forward" }; - case "b": - return { type: "word-backward" }; - case "0": - return { type: "line-start" }; - case "$": - return { type: "line-end" }; - default: - return null; - } - } - - private handleLinewiseOp(op: OperatorPending, count: number): void { - if (!this.bridge) return; - this.pushUndo(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const { line } = this.bridge.getCursorPosition(); - const start = Math.min(line, lines.length - 1); - const end = Math.min(start + count, lines.length); - const deleted = lines.splice(start, end - start); - this.state.lastYank = deleted.join("\n"); - - if (op === "d" || op === "c") { - this.bridge.setText(lines.join("\n")); - const newLine = Math.min(start, Math.max(0, lines.length - 1)); - this.bridge.setCursorPosition(newLine, 0); - } - if (op === "c") { - this.state.mode = "insert"; - } - } - - private handleOperatorMotion(op: OperatorPending, _motion: MotionResult): void { - // Simplified: for non-linewise motions, behave like single-char operations - if (!this.bridge) return; - if (op === "d") { - this.deleteCharsAtCursor(1); - } else if (op === "c") { - this.deleteCharsAtCursor(1); - this.state.mode = "insert"; - } else if (op === "y") { - const text = this.bridge.getText(); - const lines = text.split("\n"); - const { line } = this.bridge.getCursorPosition(); - this.state.lastYank = lines[line] ?? ""; - } - } - - private moveCursor(delta: number): void { - if (!this.bridge) return; - const { line, col } = this.bridge.getCursorPosition(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const currentLine = lines[line] ?? ""; - const newCol = Math.max(0, Math.min(currentLine.length, col + delta)); - this.bridge.setCursorPosition(line, newCol); - } - - private moveVertical(delta: number): void { - if (!this.bridge) return; - const { line, col } = this.bridge.getCursorPosition(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const newLine = Math.max(0, Math.min(lines.length - 1, line + delta)); - const targetLine = lines[newLine] ?? ""; - const newCol = Math.min(col, targetLine.length); - this.bridge.setCursorPosition(newLine, newCol); - } - - private moveToLineStart(): void { - if (!this.bridge) return; - const { line } = this.bridge.getCursorPosition(); - this.bridge.setCursorPosition(line, 0); - } - - private moveToLineEnd(): void { - if (!this.bridge) return; - const { line } = this.bridge.getCursorPosition(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const currentLine = lines[line] ?? ""; - this.bridge.setCursorPosition(line, currentLine.length); - } - - private moveWordForward(): void { - if (!this.bridge) return; - const { line, col } = this.bridge.getCursorPosition(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const currentLine = lines[line] ?? ""; - - let newCol = col; - // Skip current word chars - while (newCol < currentLine.length && /\w/.test(currentLine[newCol] ?? "")) { - newCol++; - } - // Skip whitespace - while (newCol < currentLine.length && /\s/.test(currentLine[newCol] ?? "")) { - newCol++; - } - if (newCol >= currentLine.length && line < lines.length - 1) { - this.bridge.setCursorPosition(line + 1, 0); - } else { - this.bridge.setCursorPosition(line, newCol); - } - } - - private moveWordBackward(): void { - if (!this.bridge) return; - const { line, col } = this.bridge.getCursorPosition(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const currentLine = lines[line] ?? ""; - - let newCol = col; - if (newCol > 0) newCol--; - // Skip whitespace backwards - while (newCol > 0 && /\s/.test(currentLine[newCol] ?? "")) { - newCol--; - } - // Skip word chars backwards - while (newCol > 0 && /\w/.test(currentLine[newCol - 1] ?? "")) { - newCol--; - } - if (newCol <= 0 && col === 0 && line > 0) { - const prevLine = lines[line - 1] ?? ""; - this.bridge.setCursorPosition(line - 1, prevLine.length); - } else { - this.bridge.setCursorPosition(line, newCol); - } - } - - private deleteCharsAtCursor(count: number): void { - if (!this.bridge) return; - this.pushUndo(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const { line, col } = this.bridge.getCursorPosition(); - const currentLine = lines[line] ?? ""; - const deleted = currentLine.slice(col, col + count); - this.state.lastYank = deleted; - lines[line] = currentLine.slice(0, col) + currentLine.slice(col + count); - this.bridge.setText(lines.join("\n")); - this.bridge.setCursorPosition(line, Math.min(col, (lines[line] ?? "").length)); - } - - private deleteToEndOfLine(): void { - if (!this.bridge) return; - this.pushUndo(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const { line, col } = this.bridge.getCursorPosition(); - const currentLine = lines[line] ?? ""; - this.state.lastYank = currentLine.slice(col); - lines[line] = currentLine.slice(0, col); - this.bridge.setText(lines.join("\n")); - } - - private insertLineBelow(): void { - if (!this.bridge) return; - this.pushUndo(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const { line } = this.bridge.getCursorPosition(); - lines.splice(line + 1, 0, ""); - this.bridge.setText(lines.join("\n")); - this.bridge.setCursorPosition(line + 1, 0); - } - - private insertLineAbove(): void { - if (!this.bridge) return; - this.pushUndo(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const { line } = this.bridge.getCursorPosition(); - lines.splice(line, 0, ""); - this.bridge.setText(lines.join("\n")); - this.bridge.setCursorPosition(line, 0); - } - - private paste(): void { - if (!this.bridge || !this.state.lastYank) return; - this.pushUndo(); - const text = this.bridge.getText(); - const lines = text.split("\n"); - const { line, col } = this.bridge.getCursorPosition(); - const currentLine = lines[line] ?? ""; - lines[line] = currentLine.slice(0, col + 1) + this.state.lastYank + currentLine.slice(col + 1); - this.bridge.setText(lines.join("\n")); - this.bridge.setCursorPosition(line, col + this.state.lastYank.length); - } - - private undo(): void { - if (!this.bridge || this.undoStack.length === 0) return; - const prev = this.undoStack.pop()!; - this.bridge.setText(prev); - const lines = prev.split("\n"); - this.bridge.setCursorPosition(Math.min(lines.length - 1, 0), 0); - } -} From 1a2b8fa0a3d02357ffe6d4e8222ae332b162f8f5 Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Tue, 14 Jul 2026 13:19:44 +0200 Subject: [PATCH 13/14] Theme system v2: custom palettes, colorblind presets, and monochrome (#72) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(tui): custom themes, colorblind palettes, and monochrome mode Generalize the theme system so users can define custom palettes in ~/.mayros/themes/*.json. Each file must contain the 22 palette color tokens as #RRGGBB hex strings; the loader validates, caches by mtime, and registers them so /theme and config.ui.theme accept custom names alongside the built-ins. Add three new built-in palettes: - colorblind-dark and colorblind-light: Okabe-Ito hues that avoid the red/green pairing for error/success (error = vermilion, success = sky blue), so deuteranopic and protanopic users get distinguishable semantic colors. - monochrome: all tokens use the same foreground, for NO_COLOR environments or users who prefer a minimal terminal. Generalize ThemePreset from a closed union to string (with BuiltinPreset for the 13 built-ins), add a custom palette registry, and relax the /theme handler and config guards to accept custom names. The loader runs at TUI startup before the config theme is resolved. * chore(tui): dedupe theme presets and migrate stderr to subsystem logger Remove the duplicated THEME_PRESETS array from commands.ts (it was a local copy that had already drifted — missing the three new palettes added in the theme system update). Import the canonical list from palettes.ts instead so there is a single source of truth. Migrate the three process.stderr.write call sites in tui-command-handlers.ts (fast-mode) and compact-handler.ts to the shared subsystem logger (createSubsystemLogger("tui")), so TUI diagnostics route through the same logging infrastructure as the rest of the codebase instead of writing raw stderr. --- src/tui/commands.ts | 13 +-- src/tui/compact-handler.ts | 10 +- src/tui/theme/palettes.test.ts | 7 +- src/tui/theme/palettes.ts | 138 ++++++++++++++++++++++++++- src/tui/theme/theme-loader.test.ts | 71 ++++++++++++++ src/tui/theme/theme-loader.ts | 147 +++++++++++++++++++++++++++++ src/tui/tui-command-handlers.ts | 29 ++++-- src/tui/tui.ts | 15 ++- 8 files changed, 397 insertions(+), 33 deletions(-) create mode 100644 src/tui/theme/theme-loader.test.ts create mode 100644 src/tui/theme/theme-loader.ts diff --git a/src/tui/commands.ts b/src/tui/commands.ts index e10f4273..42b71b19 100644 --- a/src/tui/commands.ts +++ b/src/tui/commands.ts @@ -3,24 +3,13 @@ import { listChatCommands, listChatCommandsForConfig } from "../auto-reply/comma import { formatThinkingLevels, listThinkingLevelLabels } from "../auto-reply/thinking.js"; import { discoverMarkdownCommands } from "../commands/markdown-commands.js"; import type { MayrosConfig } from "../config/types.js"; +import { THEME_PRESETS } from "./theme/palettes.js"; const VERBOSE_LEVELS = ["on", "off"]; const REASONING_LEVELS = ["on", "off"]; const ELEVATED_LEVELS = ["on", "off", "ask", "full"]; const ACTIVATION_LEVELS = ["mention", "always"]; const USAGE_FOOTER_LEVELS = ["off", "tokens", "full"]; -const THEME_PRESETS = [ - "dark", - "light", - "high-contrast", - "dracula", - "github-dark", - "github-light", - "solarized-dark", - "solarized-light", - "atom-one-dark", - "ayu-dark", -]; const OUTPUT_STYLES = ["standard", "explanatory", "learning"]; const PERMISSION_MODES = ["auto", "ask", "deny"]; diff --git a/src/tui/compact-handler.ts b/src/tui/compact-handler.ts index f3a2ec89..83c561e4 100644 --- a/src/tui/compact-handler.ts +++ b/src/tui/compact-handler.ts @@ -5,6 +5,10 @@ * then creates a summary replacing the history. */ +import { createSubsystemLogger } from "../logging/subsystem.js"; + +const logger = createSubsystemLogger("tui"); + export type CompactOptions = { messages: Array<{ role: string; content: string }>; sessionKey: string; @@ -184,9 +188,9 @@ export async function compactMessages(options: CompactOptions): Promise { - it("has 10 theme presets", () => { - expect(THEME_PRESETS).toHaveLength(10); + it("has the expected number of theme presets", () => { + expect(THEME_PRESETS).toHaveLength(13); }); it("includes all expected presets", () => { @@ -40,6 +40,9 @@ describe("Theme Palettes", () => { expect(THEME_PRESETS).toContain("solarized-light"); expect(THEME_PRESETS).toContain("atom-one-dark"); expect(THEME_PRESETS).toContain("ayu-dark"); + expect(THEME_PRESETS).toContain("colorblind-dark"); + expect(THEME_PRESETS).toContain("colorblind-light"); + expect(THEME_PRESETS).toContain("monochrome"); }); for (const preset of [ diff --git a/src/tui/theme/palettes.ts b/src/tui/theme/palettes.ts index 7cb0997d..e388739d 100644 --- a/src/tui/theme/palettes.ts +++ b/src/tui/theme/palettes.ts @@ -1,7 +1,11 @@ -export type ThemePreset = +/** Built-in theme presets shipped with the TUI. */ +export type BuiltinPreset = | "dark" | "light" | "high-contrast" + | "colorblind-dark" + | "colorblind-light" + | "monochrome" | "dracula" | "github-dark" | "github-light" @@ -10,6 +14,13 @@ export type ThemePreset = | "atom-one-dark" | "ayu-dark"; +/** + * A theme preset name. Either a built-in or a custom theme loaded from + * `~/.mayros/themes/*.json`. The string is resolved through the palette + * registry (builtin switch → custom registry → dark fallback). + */ +export type ThemePreset = string; + export type Palette = { text: string; dim: string; @@ -285,10 +296,99 @@ export const AYU_DARK_PALETTE: Palette = { success: "#AAD94C", }; -export const THEME_PRESETS: ThemePreset[] = [ +/** + * Colorblind-optimized dark palette using Okabe-Ito hues. + * Avoids red/green pairing for error/success — error uses vermilion + * (orange-red), success uses sky blue. Accent is amber. + */ +export const COLORBLIND_DARK_PALETTE: Palette = { + text: "#E8E3D5", + dim: "#7B7F87", + accent: "#E69F00", + accentSoft: "#F0E442", + border: "#3C414B", + userBg: "#2B2F36", + userText: "#F3EEE0", + systemText: "#9BA3B2", + toolPendingBg: "#1F2A2F", + toolSuccessBg: "#1E2D23", + toolErrorBg: "#2F1F1F", + toolTitle: "#E69F00", + toolOutput: "#E1DACB", + quote: "#56B4E9", + quoteBorder: "#3B4D6B", + code: "#F0E442", + codeBlock: "#1E232A", + codeBorder: "#343A45", + link: "#56B4E9", + filePath: "#56B4E9", + error: "#D55E00", + success: "#56B4E9", +}; + +/** Colorblind-optimized light palette (Okabe-Ito on light background). */ +export const COLORBLIND_LIGHT_PALETTE: Palette = { + text: "#2B2F36", + dim: "#6B7080", + accent: "#0072B2", + accentSoft: "#009E73", + border: "#D0D5DD", + userBg: "#F0F1F3", + userText: "#2B2F36", + systemText: "#6B7080", + toolPendingBg: "#EDF0F3", + toolSuccessBg: "#E6F4EA", + toolErrorBg: "#FCE8E6", + toolTitle: "#0072B2", + toolOutput: "#3C414B", + quote: "#0072B2", + quoteBorder: "#B8CCE0", + code: "#D55E00", + codeBlock: "#EDF0F3", + codeBorder: "#D0D5DD", + link: "#0072B2", + filePath: "#0072B2", + error: "#D55E00", + success: "#0072B2", +}; + +/** + * Monochrome palette — all tokens use the same foreground. Semantic + * differentiation is lost (no color), useful for `NO_COLOR` environments + * or users who prefer a minimal terminal. + */ +export const MONOCHROME_PALETTE: Palette = { + text: "#FFFFFF", + dim: "#AAAAAA", + accent: "#FFFFFF", + accentSoft: "#CCCCCC", + border: "#888888", + userBg: "#666666", + userText: "#FFFFFF", + systemText: "#CCCCCC", + toolPendingBg: "#444444", + toolSuccessBg: "#444444", + toolErrorBg: "#444444", + toolTitle: "#FFFFFF", + toolOutput: "#CCCCCC", + quote: "#CCCCCC", + quoteBorder: "#888888", + code: "#FFFFFF", + codeBlock: "#333333", + codeBorder: "#666666", + link: "#FFFFFF", + filePath: "#FFFFFF", + error: "#FFFFFF", + success: "#FFFFFF", +}; + +export const BUILTIN_THEME_PRESETS: BuiltinPreset[] = [ "dark", "light", "high-contrast", + "colorblind-dark", + "colorblind-light", + "monochrome", "dracula", "github-dark", "github-light", @@ -298,12 +398,41 @@ export const THEME_PRESETS: ThemePreset[] = [ "ayu-dark", ]; +/** Backward-compatible alias for the built-in preset list. */ +export const THEME_PRESETS: BuiltinPreset[] = BUILTIN_THEME_PRESETS; + +// --- Custom theme registry ------------------------------------------------- + +/** Registry of custom palettes loaded from `~/.mayros/themes/*.json`. */ +const customPaletteRegistry = new Map(); + +/** Register a custom palette under a name. */ +export function registerCustomPalette(name: string, palette: Palette): void { + customPaletteRegistry.set(name, palette); +} + +/** Clear all custom palettes (used by the theme loader before re-scanning). */ +export function clearCustomPalettes(): void { + customPaletteRegistry.clear(); +} + +/** List all currently registered custom theme names. */ +export function listCustomThemeNames(): string[] { + return [...customPaletteRegistry.keys()]; +} + export function resolvePalette(preset: ThemePreset): Palette { switch (preset) { case "light": return LIGHT_PALETTE; case "high-contrast": return HIGH_CONTRAST_PALETTE; + case "colorblind-dark": + return COLORBLIND_DARK_PALETTE; + case "colorblind-light": + return COLORBLIND_LIGHT_PALETTE; + case "monochrome": + return MONOCHROME_PALETTE; case "dracula": return DRACULA_PALETTE; case "github-dark": @@ -318,7 +447,10 @@ export function resolvePalette(preset: ThemePreset): Palette { return ATOM_ONE_DARK_PALETTE; case "ayu-dark": return AYU_DARK_PALETTE; - default: + default: { + const custom = customPaletteRegistry.get(preset); + if (custom) return custom; return DARK_PALETTE; + } } } diff --git a/src/tui/theme/theme-loader.test.ts b/src/tui/theme/theme-loader.test.ts new file mode 100644 index 00000000..4abe5db8 --- /dev/null +++ b/src/tui/theme/theme-loader.test.ts @@ -0,0 +1,71 @@ +import { describe, expect, it } from "vitest"; +import { validatePalette } from "./theme-loader.js"; +import type { Palette } from "./palettes.js"; + +/** + * Theme loader unit tests. + * + * The discoverCustomThemes function hits the filesystem and is tested + * implicitly via integration; these tests cover the pure validation logic + * that gates which JSON files become registered palettes. + */ + +const VALID_PALETTE: Palette = { + text: "#E8E3D5", + dim: "#7B7F87", + accent: "#F6C453", + accentSoft: "#F2A65A", + border: "#3C414B", + userBg: "#2B2F36", + userText: "#F3EEE0", + systemText: "#9BA3B2", + toolPendingBg: "#1F2A2F", + toolSuccessBg: "#1E2D23", + toolErrorBg: "#2F1F1F", + toolTitle: "#F6C453", + toolOutput: "#E1DACB", + quote: "#8CC8FF", + quoteBorder: "#3B4D6B", + code: "#F0C987", + codeBlock: "#1E232A", + codeBorder: "#343A45", + link: "#7DD3A5", + filePath: "#87CEEB", + error: "#F97066", + success: "#7DD3A5", +}; + +describe("validatePalette", () => { + it("accepts a valid palette with all 22 hex tokens", () => { + expect(validatePalette(VALID_PALETTE)).not.toBeNull(); + }); + + it("rejects null", () => { + expect(validatePalette(null)).toBeNull(); + }); + + it("rejects a non-object", () => { + expect(validatePalette("not a palette")).toBeNull(); + }); + + it("rejects a palette missing a key", () => { + const incomplete = { ...VALID_PALETTE } as Partial; + delete incomplete.success; + expect(validatePalette(incomplete)).toBeNull(); + }); + + it("rejects a palette with a non-hex color", () => { + const bad = { ...VALID_PALETTE, accent: "red" }; + expect(validatePalette(bad)).toBeNull(); + }); + + it("rejects a palette with a 3-digit hex", () => { + const bad = { ...VALID_PALETTE, accent: "#F63" }; + expect(validatePalette(bad)).toBeNull(); + }); + + it("accepts lowercase hex", () => { + const lower = { ...VALID_PALETTE, accent: "#f6c453" }; + expect(validatePalette(lower)).not.toBeNull(); + }); +}); diff --git a/src/tui/theme/theme-loader.ts b/src/tui/theme/theme-loader.ts new file mode 100644 index 00000000..d4d6d546 --- /dev/null +++ b/src/tui/theme/theme-loader.ts @@ -0,0 +1,147 @@ +/** + * Custom theme loader. + * + * Discovers user-defined theme palettes from `~/.mayros/themes/*.json` and + * registers them so they can be selected via `/theme ` or configured + * as `config.ui.theme = ""`. Each file must contain a JSON object with + * the 22 palette color tokens (all `#RRGGBB` hex strings). + * + * The loader caches by file mtime and rescans on demand, mirroring the + * markdown-commands discovery pattern. + */ + +import { readFile, stat } from "node:fs/promises"; +import path from "node:path"; +import { resolveStateDir } from "../../config/paths.js"; +import { + clearCustomPalettes, + listCustomThemeNames, + registerCustomPalette, + type Palette, +} from "./palettes.js"; + +const HEX_COLOR = /^#[0-9A-Fa-f]{6}$/; + +const PALETTE_KEYS: ReadonlyArray = [ + "text", + "dim", + "accent", + "accentSoft", + "border", + "userBg", + "userText", + "systemText", + "toolPendingBg", + "toolSuccessBg", + "toolErrorBg", + "toolTitle", + "toolOutput", + "quote", + "quoteBorder", + "code", + "codeBlock", + "codeBorder", + "link", + "filePath", + "error", + "success", +]; + +/** Cache entry: the parsed palette + the file mtime that produced it. */ +type CacheEntry = { palette: Palette; mtimeMs: number }; + +const cache = new Map(); +let lastScanMtime = 0; + +/** Resolve the user themes directory (`~/.mayros/themes`). */ +export function resolveUserThemesDir(): string { + return path.join(resolveStateDir(), "themes"); +} + +/** Validate that a value is a valid palette object with all 22 hex tokens. */ +export function validatePalette(value: unknown): Palette | null { + if (typeof value !== "object" || value === null) return null; + const obj = value as Record; + const palette = {} as Palette; + for (const key of PALETTE_KEYS) { + const val = obj[key]; + if (typeof val !== "string" || !HEX_COLOR.test(val)) return null; + palette[key] = val; + } + return palette; +} + +/** + * Scan `~/.mayros/themes/*.json`, validate each file, and register valid + * palettes. Returns the list of names that were registered. Invalid files + * are silently skipped (best-effort, like other config discovery). + */ +export async function discoverCustomThemes(): Promise { + const dir = resolveUserThemesDir(); + let entries: import("node:fs").Dirent[]; + try { + const { readdir } = await import("node:fs/promises"); + entries = await readdir(dir, { withFileTypes: true }); + } catch { + // Directory doesn't exist or is unreadable — no custom themes. + clearCustomPalettes(); + cache.clear(); + return []; + } + + // Track the newest mtime to know if a rescan is needed. + let newestMtime = 0; + const validFiles = entries.filter((e) => e.isFile() && e.name.endsWith(".json")); + + // Clear and re-register from scratch (simplest correct approach). + clearCustomPalettes(); + const registered: string[] = []; + + for (const entry of validFiles) { + const filePath = path.join(dir, entry.name); + const themeName = entry.name.slice(0, -5); // strip .json + + try { + const stats = await stat(filePath); + newestMtime = Math.max(newestMtime, stats.mtimeMs); + + // Use cache if the file hasn't changed. + const cached = cache.get(themeName); + if (cached && cached.mtimeMs === stats.mtimeMs) { + registerCustomPalette(themeName, cached.palette); + registered.push(themeName); + continue; + } + + const content = await readFile(filePath, "utf8"); + const parsed: unknown = JSON.parse(content); + const palette = validatePalette(parsed); + if (palette) { + cache.set(themeName, { palette, mtimeMs: stats.mtimeMs }); + registerCustomPalette(themeName, palette); + registered.push(themeName); + } + } catch { + // Invalid JSON, unreadable file, or validation failure — skip. + } + } + + // Clean stale cache entries for files that no longer exist. + const validNames = new Set(registered); + for (const name of cache.keys()) { + if (!validNames.has(name)) cache.delete(name); + } + + lastScanMtime = newestMtime; + return registered; +} + +/** List all theme names available: builtins + custom. */ +export function allThemeNames(builtins: readonly string[]): string[] { + return [...builtins, ...listCustomThemeNames()]; +} + +/** Check if a rescan is needed by comparing directory mtime. */ +export function needsRescan(): boolean { + return lastScanMtime === 0; +} diff --git a/src/tui/tui-command-handlers.ts b/src/tui/tui-command-handlers.ts index aa83d21c..3cbb69ee 100644 --- a/src/tui/tui-command-handlers.ts +++ b/src/tui/tui-command-handlers.ts @@ -1,5 +1,8 @@ import { randomUUID } from "node:crypto"; import type { Component, TUI } from "@earendil-works/pi-tui"; +import { createSubsystemLogger } from "../logging/subsystem.js"; + +const logger = createSubsystemLogger("tui"); import { listThinkingLevelLabels, normalizeUsageDisplay, @@ -27,8 +30,8 @@ import { SessionManager, formatSessionLine } from "./session-manager.js"; import { theme } from "./theme/theme.js"; import { applyOutputStyle, isValidOutputStyle, OUTPUT_STYLE_NAMES } from "./output-styles.js"; import type { OutputStyle } from "./output-styles.js"; -import { THEME_PRESETS } from "./theme/palettes.js"; -import type { ThemePreset } from "./theme/palettes.js"; +import { THEME_PRESETS, listCustomThemeNames } from "./theme/palettes.js"; +import type { BuiltinPreset } from "./theme/palettes.js"; import { setThemePreset, getThemePreset } from "./theme/theme.js"; import type { ChatLog } from "./components/chat-log.js"; import { @@ -735,7 +738,7 @@ export function createCommandHandlers(context: CommandHandlerContext) { })); const themeSelector = createSelectList(themeItems, themeItems.length); themeSelector.onSelect = (item) => { - setThemePreset(item.value as ThemePreset); + setThemePreset(item.value); chatLog.addSystem(`theme set to ${item.value}`); closeOverlay(); tui.requestRender(); @@ -748,11 +751,16 @@ export function createCommandHandlers(context: CommandHandlerContext) { tui.requestRender(); break; } - if (!THEME_PRESETS.includes(preset as ThemePreset)) { - chatLog.addSystem(`unknown theme. usage: /theme <${THEME_PRESETS.join("|")}>`); + if ( + !THEME_PRESETS.includes(preset as BuiltinPreset) && + !listCustomThemeNames().includes(preset) + ) { + chatLog.addSystem( + `unknown theme. usage: /theme <${THEME_PRESETS.join("|")}> or a custom theme name`, + ); break; } - setThemePreset(preset as ThemePreset); + setThemePreset(preset); chatLog.addSystem(`theme set to ${preset}`); break; } @@ -808,7 +816,7 @@ export function createCommandHandlers(context: CommandHandlerContext) { applySessionInfoFromPatch(result); } catch (err) { // Best-effort — fast mode works locally even without gateway - process.stderr.write(`[fast-mode] failed to set thinking off: ${String(err)}\n`); + logger.warn("fast-mode: failed to set thinking off", { error: String(err) }); } state.outputStyle = "standard"; chatLog.addSystem("fast mode enabled (thinking: off, style: standard)"); @@ -823,9 +831,10 @@ export function createCommandHandlers(context: CommandHandlerContext) { applySessionInfoFromPatch(result); } catch (err) { // Best-effort — restore may fail if gateway is unreachable - process.stderr.write( - `[fast-mode] failed to restore thinking ${prevLevel}: ${String(err)}\n`, - ); + logger.warn("fast-mode: failed to restore thinking", { + level: prevLevel, + error: String(err), + }); } chatLog.addSystem(`fast mode disabled (thinking: ${prevLevel})`); } diff --git a/src/tui/tui.ts b/src/tui/tui.ts index 88438ac2..031f2b86 100644 --- a/src/tui/tui.ts +++ b/src/tui/tui.ts @@ -28,8 +28,9 @@ import { WelcomeScreen } from "./components/welcome-screen.js"; import { GatewayChatClient } from "./gateway-chat.js"; import { enableKeyboardProtocol } from "./term-capabilities.js"; import { detectTerminalColorScheme } from "./term-capabilities.js"; -import type { ThemePreset } from "./theme/palettes.js"; +import type { BuiltinPreset } from "./theme/palettes.js"; import { THEME_PRESETS } from "./theme/palettes.js"; +import { discoverCustomThemes } from "./theme/theme-loader.js"; import { editorTheme, theme, setThemePreset } from "./theme/theme.js"; import { createCommandHandlers } from "./tui-command-handlers.js"; import { createEventHandlers } from "./tui-event-handlers.js"; @@ -281,12 +282,20 @@ export async function runTui(opts: TuiOptions) { return; } + // Discover custom themes from ~/.mayros/themes/*.json before resolving the + // config theme, so a custom theme name in config.ui.theme works on startup. + await discoverCustomThemes(); + const configTheme = config.ui?.theme; // "auto" (or unset) defers to terminal color-scheme detection after the TUI // instance is created; until then the default "dark" preset is in place. const themeIsAuto = !configTheme || configTheme === "auto"; - if (!themeIsAuto && THEME_PRESETS.includes(configTheme as ThemePreset)) { - setThemePreset(configTheme as ThemePreset); + if (!themeIsAuto && THEME_PRESETS.includes(configTheme as BuiltinPreset)) { + setThemePreset(configTheme); + } else if (!themeIsAuto) { + // Could be a custom theme name — set it; resolvePalette falls back to + // dark if the name isn't registered yet. + setThemePreset(configTheme); } const keybindingsConfig = config.ui?.keybindings; applyKeybindingsFromConfig(keybindingsConfig); From 583891e5bc99cac11ce9e33c48330b6ba3591b6e Mon Sep 17 00:00:00 2001 From: ApiliumDevTeam Date: Tue, 14 Jul 2026 13:58:23 +0200 Subject: [PATCH 14/14] TUI: cross-platform clipboard, inline images, and helper extraction (#74) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(tui): cross-platform clipboard support for Windows and Wayland The /copy command and teleport export hardcoded pbcopy/xclip, so they were broken on Windows (no pbcopy/xclip) and Wayland (no xclip under pure Wayland). Replace the spawn and shell-pipeline approaches with the existing cross-platform copyToClipboard helper from infra/clipboard.ts, which has a fallback chain covering pbcopy, xclip, wl-copy, clip.exe, and PowerShell Set-Clipboard. Add Windows and Wayland support to clipboard image capture: - Windows: PowerShell + System.Windows.Forms to read clipboard PNG. - Wayland: wl-paste -t image/png when WAYLAND_DISPLAY is set, with xclip fallback for XWayland sessions. * feat(tui): render image content blocks inline where supported Tool results that contain image content blocks now render inline using the terminal image component when the terminal supports it (Kitty graphics protocol or iTerm2 inline images). The Image component handles capability detection internally and falls back to a text placeholder ([image/png 12kb]) when the terminal cannot display images, so no escape sequences leak to unsupported terminals. Backend change: stop stripping the base64 data from image content blocks in sanitizeToolResult. The omitted: true flag already prevents the image from entering the model context, so retaining data does not inflate token usage — it only makes the base64 available for TUI rendering. * refactor(tui): extract pure helpers from tui.ts into tui-helpers.ts Move 7 standalone functions (createEditorSubmitHandler, shouldEnableWindowsGitBashPasteFallback, createSubmitBurstCoalescer, resolveTuiSessionKey, tryInlinePairingApproval, resolveGatewayDisconnectState, createBackspaceDeduper) out of tui.ts into a dedicated tui-helpers.ts module. These functions are pure factories and resolvers with no dependency on the TUI instance or mutable state, and are already covered by tui.test.ts. Reduces tui.ts from 1087 to 883 LOC. Further extraction of the state factory, status renderer, and connection handlers is tracked as a follow-up — the remaining sections are tightly coupled to runTui's closures and require more careful refactoring. --- src/agents/pi-embedded-subscribe.tools.ts | 7 +- src/tui/clipboard-image.ts | 77 ++++++- src/tui/components/tool-execution.ts | 27 ++- src/tui/tui-command-handlers.ts | 25 +-- src/tui/tui-helpers.ts | 228 +++++++++++++++++++++ src/tui/tui.ts | 237 ++-------------------- 6 files changed, 362 insertions(+), 239 deletions(-) create mode 100644 src/tui/tui-helpers.ts diff --git a/src/agents/pi-embedded-subscribe.tools.ts b/src/agents/pi-embedded-subscribe.tools.ts index ea398338..e40f617e 100644 --- a/src/agents/pi-embedded-subscribe.tools.ts +++ b/src/agents/pi-embedded-subscribe.tools.ts @@ -104,9 +104,10 @@ export function sanitizeToolResult(result: unknown): unknown { if (type === "image") { const data = typeof entry.data === "string" ? entry.data : undefined; const bytes = data ? data.length : undefined; - const cleaned = { ...entry }; - delete cleaned.data; - return { ...cleaned, bytes, omitted: true }; + // Retain `data` so the TUI can render images inline. The `omitted: true` + // flag tells the model layer to skip this block when building the prompt, + // so the base64 never inflates the token context. + return { ...entry, bytes, omitted: true }; } return entry; }); diff --git a/src/tui/clipboard-image.ts b/src/tui/clipboard-image.ts index edefa664..ff4c1fc4 100644 --- a/src/tui/clipboard-image.ts +++ b/src/tui/clipboard-image.ts @@ -13,15 +13,23 @@ export type ClipboardImage = { * Attempts to capture an image from the system clipboard. * Returns the image as base64 + mimeType, or null if no image is on the clipboard. * - * Supports macOS (pbpaste/osascript) and Linux (xclip). + * Supports macOS (osascript), Linux (xclip or wl-paste on Wayland), and + * Windows (PowerShell + System.Windows.Forms). */ export function captureClipboardImage(): ClipboardImage | null { if (process.platform === "darwin") { return captureMacOS(); } if (process.platform === "linux") { + // Wayland: prefer wl-paste when WAYLAND_DISPLAY is set. + if (process.env.WAYLAND_DISPLAY) { + return captureWayland() ?? captureLinux(); + } return captureLinux(); } + if (process.platform === "win32") { + return captureWindows(); + } return null; } @@ -124,3 +132,70 @@ function captureLinux(): ClipboardImage | null { return null; } } + +/** Capture clipboard image on Wayland via wl-paste. */ +function captureWayland(): ClipboardImage | null { + try { + // Check available MIME types + const types = execSync("wl-paste -l", { + encoding: "utf-8", + timeout: 3000, + stdio: ["pipe", "pipe", "pipe"], + }); + if (!types.includes("image/png")) { + return null; + } + } catch { + return null; + } + + try { + const buf = execSync("wl-paste -t image/png", { + timeout: 5000, + stdio: ["pipe", "pipe", "pipe"], + maxBuffer: 50 * 1024 * 1024, + }); + if (buf.length === 0) { + return null; + } + return { + base64: buf.toString("base64"), + mimeType: "image/png", + }; + } catch { + return null; + } +} + +/** Capture clipboard image on Windows via PowerShell + System.Windows.Forms. */ +function captureWindows(): ClipboardImage | null { + // PowerShell script: check if clipboard has an image, get it as PNG bytes, + // and write base64 to stdout. + const script = [ + "Add-Type -AssemblyName System.Windows.Forms", + "Add-Type -AssemblyName System.Drawing", + "$img = [System.Windows.Forms.Clipboard]::GetImage()", + "if ($null -eq $img) { exit 1 }", + "$ms = New-Object System.IO.MemoryStream", + "$img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)", + "[Console]::OpenStandardOutput().Write($ms.ToArray(), 0, $ms.Length)", + ].join("; "); + + try { + const buf = execSync(`powershell -NoProfile -Command "${script}"`, { + timeout: 5000, + stdio: ["pipe", "pipe", "pipe"], + maxBuffer: 50 * 1024 * 1024, + windowsHide: true, + }); + if (buf.length === 0) { + return null; + } + return { + base64: buf.toString("base64"), + mimeType: "image/png", + }; + } catch { + return null; + } +} diff --git a/src/tui/components/tool-execution.ts b/src/tui/components/tool-execution.ts index df48c41e..200c6792 100644 --- a/src/tui/components/tool-execution.ts +++ b/src/tui/components/tool-execution.ts @@ -1,4 +1,4 @@ -import { Box, Container, Markdown, Spacer, Text } from "@earendil-works/pi-tui"; +import { Box, Container, Image, Markdown, Spacer, Text } from "@earendil-works/pi-tui"; import { formatToolDetail, resolveToolDisplay } from "../../agents/tool-display.js"; import { renderDiff, parseDiffStats, formatDiffStatsLine } from "../diff-renderer.js"; import { linkifyFilePaths } from "../linkify-paths.js"; @@ -11,6 +11,8 @@ type ToolResultContent = { mimeType?: string; bytes?: number; omitted?: boolean; + /** Base64-encoded image data, retained for inline rendering. */ + data?: string; }; type ToolResult = { @@ -61,6 +63,7 @@ export class ToolExecutionComponent extends Container { private header: Text; private argsLine: Text; private output: Markdown; + private imageContainer: Container; private toolName: string; private args: unknown; private result?: ToolResult; @@ -78,11 +81,13 @@ export class ToolExecutionComponent extends Container { this.output = new Markdown("", 0, 0, markdownTheme, { color: (line) => theme.toolOutput(line), }); + this.imageContainer = new Container(); this.addChild(new Spacer(1)); this.addChild(this.box); this.box.addChild(this.header); this.box.addChild(this.argsLine); this.box.addChild(this.output); + this.box.addChild(this.imageContainer); this.refresh(); } @@ -145,9 +150,29 @@ export class ToolExecutionComponent extends Container { // Hidden: only the header line, no output body. if (this.sectionState === "hidden") { this.output.setText(""); + this.imageContainer.clear(); return; } + // Render inline images from image content blocks that carry base64 data. + // The Image component handles terminal capability detection internally + // (Kitty/iTerm2) and falls back to a text placeholder when unsupported. + this.imageContainer.clear(); + if (this.result?.content && !this.isPartial) { + for (const entry of this.result.content) { + if (entry.type === "image" && entry.data) { + const mime = entry.mimeType ?? "image/png"; + try { + const img = new Image(entry.data, mime, { fallbackColor: theme.dim }); + this.imageContainer.addChild(img); + } catch { + // If Image construction fails, the text placeholder from + // extractText already covers this block. + } + } + } + } + const isExpanded = this.sectionState === "expanded"; if (isDiff) { diff --git a/src/tui/tui-command-handlers.ts b/src/tui/tui-command-handlers.ts index 3cbb69ee..c5e830ef 100644 --- a/src/tui/tui-command-handlers.ts +++ b/src/tui/tui-command-handlers.ts @@ -1,5 +1,6 @@ import { randomUUID } from "node:crypto"; import type { Component, TUI } from "@earendil-works/pi-tui"; +import { copyToClipboard } from "../infra/clipboard.js"; import { createSubsystemLogger } from "../logging/subsystem.js"; const logger = createSubsystemLogger("tui"); @@ -12,7 +13,7 @@ import { expandMarkdownCommand, findMarkdownCommand } from "../commands/markdown import type { SessionsPatchResult } from "../gateway/protocol/index.js"; import { formatRelativeTimestamp } from "../infra/format-time/format-relative.ts"; import { normalizeAgentId } from "../routing/session-key.js"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; import { writeFileSync } from "node:fs"; import { helpText, parseCommand } from "./commands.js"; import { undo, listUndoEntries } from "./undo-manager.js"; @@ -888,14 +889,10 @@ export function createCommandHandlers(context: CommandHandlerContext) { break; } try { - const proc = spawn( - process.platform === "darwin" ? "pbcopy" : "xclip", - process.platform === "darwin" ? [] : ["-selection", "clipboard"], - { stdio: ["pipe", "ignore", "ignore"] }, + const ok = await copyToClipboard(lastText); + chatLog.addSystem( + ok ? "last response copied to clipboard" : "copy failed: no clipboard tool found", ); - proc.stdin?.write(lastText); - proc.stdin?.end(); - chatLog.addSystem("last response copied to clipboard"); } catch (err) { chatLog.addSystem(`copy failed: ${String(err)}`); } @@ -1238,14 +1235,14 @@ export function createCommandHandlers(context: CommandHandlerContext) { } const token = exportSession(payload); - // Copy to clipboard + // Copy to clipboard using the cross-platform clipboard helper + // (pbcopy / xclip / wl-copy / clip.exe / PowerShell fallback). try { - execSync( - `echo -n "${token}" | pbcopy 2>/dev/null || echo -n "${token}" | xclip -sel clipboard 2>/dev/null || echo -n "${token}" | xsel --clipboard 2>/dev/null`, - { encoding: "utf-8" }, - ); + const ok = await copyToClipboard(token); chatLog.addSystem( - `Session exported to clipboard (${token.length} chars, ${messages.length} messages). Share this token to import on another device.`, + ok + ? `Session exported to clipboard (${token.length} chars, ${messages.length} messages). Share this token to import on another device.` + : `Session token (no clipboard tool found):\n${token}`, ); } catch { chatLog.addSystem(`Session token:\n${token}`); diff --git a/src/tui/tui-helpers.ts b/src/tui/tui-helpers.ts new file mode 100644 index 00000000..2af978fb --- /dev/null +++ b/src/tui/tui-helpers.ts @@ -0,0 +1,228 @@ +/** + * Pure helper functions extracted from tui.ts. + * + * These functions have no dependency on the TUI instance, the gateway client, + * or any mutable state — they are pure factories and resolvers tested in + * tui.test.ts. Extracting them keeps tui.ts focused on wiring. + */ + +import { Key, matchesKey } from "@earendil-works/pi-tui"; +import { buildAgentMainSessionKey } from "../routing/session-key.js"; +import type { SessionScope } from "./tui-types.js"; + +export function createEditorSubmitHandler(params: { + editor: { + setText: (value: string) => void; + addToHistory: (value: string) => void; + }; + handleCommand: (value: string) => Promise | void; + sendMessage: (value: string) => Promise | void; + handleBangLine: (value: string) => Promise | void; +}) { + return (text: string) => { + const raw = text; + const value = raw.trim(); + params.editor.setText(""); + + // Keep previous behavior: ignore empty/whitespace-only submissions. + if (!value) { + return; + } + + // Bash mode: only if the very first character is '!' and it's not just '!'. + // IMPORTANT: use the raw (untrimmed) text so leading spaces do NOT trigger. + // Per requirement: a lone '!' should be treated as a normal message. + if (raw.startsWith("!") && raw !== "!") { + params.editor.addToHistory(raw); + void params.handleBangLine(raw); + return; + } + + // Enable built-in editor prompt history navigation (up/down). + params.editor.addToHistory(value); + + if (value.startsWith("/")) { + void params.handleCommand(value); + return; + } + + void params.sendMessage(value); + }; +} + +export function shouldEnableWindowsGitBashPasteFallback(params?: { + platform?: string; + env?: NodeJS.ProcessEnv; +}): boolean { + const platform = params?.platform ?? process.platform; + if (platform !== "win32") { + return false; + } + const env = params?.env ?? process.env; + const msystem = (env.MSYSTEM ?? "").toUpperCase(); + const shell = env.SHELL ?? ""; + const termProgram = (env.TERM_PROGRAM ?? "").toLowerCase(); + if (msystem.startsWith("MINGW") || msystem.startsWith("MSYS")) { + return true; + } + if (shell.toLowerCase().includes("bash")) { + return true; + } + return termProgram.includes("mintty"); +} + +export function createSubmitBurstCoalescer(params: { + submit: (value: string) => void; + enabled: boolean; + burstWindowMs?: number; + now?: () => number; + setTimer?: typeof setTimeout; + clearTimer?: typeof clearTimeout; +}) { + const windowMs = Math.max(1, params.burstWindowMs ?? 50); + const now = params.now ?? (() => Date.now()); + const setTimer = params.setTimer ?? setTimeout; + const clearTimer = params.clearTimer ?? clearTimeout; + let pending: string | null = null; + let pendingAt = 0; + let flushTimer: ReturnType | null = null; + + const clearFlushTimer = () => { + if (!flushTimer) { + return; + } + clearTimer(flushTimer); + flushTimer = null; + }; + + const flushPending = () => { + if (pending === null) { + return; + } + const value = pending; + pending = null; + pendingAt = 0; + clearFlushTimer(); + params.submit(value); + }; + + const scheduleFlush = () => { + clearFlushTimer(); + flushTimer = setTimer(() => { + flushPending(); + }, windowMs); + }; + + return (value: string) => { + if (!params.enabled) { + params.submit(value); + return; + } + if (value.includes("\n")) { + flushPending(); + params.submit(value); + return; + } + const ts = now(); + if (pending === null) { + pending = value; + pendingAt = ts; + scheduleFlush(); + return; + } + if (ts - pendingAt <= windowMs) { + pending = `${pending}\n${value}`; + pendingAt = ts; + scheduleFlush(); + return; + } + flushPending(); + pending = value; + pendingAt = ts; + scheduleFlush(); + }; +} + +export function resolveTuiSessionKey(params: { + raw?: string; + sessionScope: SessionScope; + currentAgentId: string; + sessionMainKey: string; +}) { + const trimmed = (params.raw ?? "").trim(); + if (!trimmed) { + if (params.sessionScope === "global") { + return "global"; + } + return buildAgentMainSessionKey({ + agentId: params.currentAgentId, + mainKey: params.sessionMainKey, + }); + } + if (trimmed === "global" || trimmed === "unknown") { + return trimmed; + } + if (trimmed.startsWith("agent:")) { + return trimmed; + } + return `agent:${params.currentAgentId}:${trimmed}`; +} + +export async function tryInlinePairingApproval(): Promise { + try { + const { listDevicePairing, approveDevicePairing } = await import("../infra/device-pairing.js"); + const list = await listDevicePairing(); + if (!list.pending.length) return false; + const latest = list.pending.reduce((a, b) => (b.ts > a.ts ? b : a)); + return (await approveDevicePairing(latest.requestId)) !== null; + } catch { + return false; + } +} + +export function resolveGatewayDisconnectState(reason?: string): { + connectionStatus: string; + activityStatus: string; + pairingHint?: string; + gatewayDownHint?: string; +} { + const reasonLabel = reason?.trim() ? reason.trim() : "closed"; + if (/pairing required/i.test(reasonLabel)) { + return { + connectionStatus: `gateway disconnected: ${reasonLabel}`, + activityStatus: "pairing required: run mayros devices list", + pairingHint: + "Pairing required. Run `mayros devices list`, approve your request ID, then reconnect.", + }; + } + if (/ECONNREFUSED|connect failed/i.test(reasonLabel)) { + return { + connectionStatus: "gateway not running", + activityStatus: "start gateway with: mayros gateway run", + gatewayDownHint: + "Gateway is not responding. Start it with `mayros gateway run` or `mayros onboard`.", + }; + } + return { + connectionStatus: `gateway disconnected: ${reasonLabel}`, + activityStatus: "idle", + }; +} + +export function createBackspaceDeduper(params?: { dedupeWindowMs?: number; now?: () => number }) { + const dedupeWindowMs = Math.max(0, Math.floor(params?.dedupeWindowMs ?? 8)); + const now = params?.now ?? (() => Date.now()); + let lastBackspaceAt = -1; + + return (data: string): string => { + if (!matchesKey(data, Key.backspace)) { + return data; + } + const ts = now(); + if (lastBackspaceAt >= 0 && ts - lastBackspaceAt <= dedupeWindowMs) { + return ""; + } + lastBackspaceAt = ts; + return data; + }; +} diff --git a/src/tui/tui.ts b/src/tui/tui.ts index 031f2b86..5718f8b1 100644 --- a/src/tui/tui.ts +++ b/src/tui/tui.ts @@ -1,9 +1,7 @@ import { CombinedAutocompleteProvider, Container, - Key, Loader, - matchesKey, ProcessTerminal, Text, TUI, @@ -13,7 +11,6 @@ import { VERSION } from "../version.js"; import { loadConfig } from "../config/config.js"; import { isLoopbackHost } from "../gateway/net.js"; import { - buildAgentMainSessionKey, normalizeAgentId, normalizeMainKey, parseAgentSessionKey, @@ -53,223 +50,23 @@ import { buildWaitingStatusMessage, defaultWaitingPhrases } from "./tui-waiting. export { resolveFinalAssistantText } from "./tui-formatters.js"; export type { TuiOptions } from "./tui-types.js"; - -export function createEditorSubmitHandler(params: { - editor: { - setText: (value: string) => void; - addToHistory: (value: string) => void; - }; - handleCommand: (value: string) => Promise | void; - sendMessage: (value: string) => Promise | void; - handleBangLine: (value: string) => Promise | void; -}) { - return (text: string) => { - const raw = text; - const value = raw.trim(); - params.editor.setText(""); - - // Keep previous behavior: ignore empty/whitespace-only submissions. - if (!value) { - return; - } - - // Bash mode: only if the very first character is '!' and it's not just '!'. - // IMPORTANT: use the raw (untrimmed) text so leading spaces do NOT trigger. - // Per requirement: a lone '!' should be treated as a normal message. - if (raw.startsWith("!") && raw !== "!") { - params.editor.addToHistory(raw); - void params.handleBangLine(raw); - return; - } - - // Enable built-in editor prompt history navigation (up/down). - params.editor.addToHistory(value); - - if (value.startsWith("/")) { - void params.handleCommand(value); - return; - } - - void params.sendMessage(value); - }; -} - -export function shouldEnableWindowsGitBashPasteFallback(params?: { - platform?: string; - env?: NodeJS.ProcessEnv; -}): boolean { - const platform = params?.platform ?? process.platform; - if (platform !== "win32") { - return false; - } - const env = params?.env ?? process.env; - const msystem = (env.MSYSTEM ?? "").toUpperCase(); - const shell = env.SHELL ?? ""; - const termProgram = (env.TERM_PROGRAM ?? "").toLowerCase(); - if (msystem.startsWith("MINGW") || msystem.startsWith("MSYS")) { - return true; - } - if (shell.toLowerCase().includes("bash")) { - return true; - } - return termProgram.includes("mintty"); -} - -export function createSubmitBurstCoalescer(params: { - submit: (value: string) => void; - enabled: boolean; - burstWindowMs?: number; - now?: () => number; - setTimer?: typeof setTimeout; - clearTimer?: typeof clearTimeout; -}) { - const windowMs = Math.max(1, params.burstWindowMs ?? 50); - const now = params.now ?? (() => Date.now()); - const setTimer = params.setTimer ?? setTimeout; - const clearTimer = params.clearTimer ?? clearTimeout; - let pending: string | null = null; - let pendingAt = 0; - let flushTimer: ReturnType | null = null; - - const clearFlushTimer = () => { - if (!flushTimer) { - return; - } - clearTimer(flushTimer); - flushTimer = null; - }; - - const flushPending = () => { - if (pending === null) { - return; - } - const value = pending; - pending = null; - pendingAt = 0; - clearFlushTimer(); - params.submit(value); - }; - - const scheduleFlush = () => { - clearFlushTimer(); - flushTimer = setTimer(() => { - flushPending(); - }, windowMs); - }; - - return (value: string) => { - if (!params.enabled) { - params.submit(value); - return; - } - if (value.includes("\n")) { - flushPending(); - params.submit(value); - return; - } - const ts = now(); - if (pending === null) { - pending = value; - pendingAt = ts; - scheduleFlush(); - return; - } - if (ts - pendingAt <= windowMs) { - pending = `${pending}\n${value}`; - pendingAt = ts; - scheduleFlush(); - return; - } - flushPending(); - pending = value; - pendingAt = ts; - scheduleFlush(); - }; -} - -export function resolveTuiSessionKey(params: { - raw?: string; - sessionScope: SessionScope; - currentAgentId: string; - sessionMainKey: string; -}) { - const trimmed = (params.raw ?? "").trim(); - if (!trimmed) { - if (params.sessionScope === "global") { - return "global"; - } - return buildAgentMainSessionKey({ - agentId: params.currentAgentId, - mainKey: params.sessionMainKey, - }); - } - if (trimmed === "global" || trimmed === "unknown") { - return trimmed; - } - if (trimmed.startsWith("agent:")) { - return trimmed; - } - return `agent:${params.currentAgentId}:${trimmed}`; -} - -async function tryInlinePairingApproval(): Promise { - try { - const { listDevicePairing, approveDevicePairing } = await import("../infra/device-pairing.js"); - const list = await listDevicePairing(); - if (!list.pending.length) return false; - const latest = list.pending.reduce((a, b) => (b.ts > a.ts ? b : a)); - return (await approveDevicePairing(latest.requestId)) !== null; - } catch { - return false; - } -} - -export function resolveGatewayDisconnectState(reason?: string): { - connectionStatus: string; - activityStatus: string; - pairingHint?: string; - gatewayDownHint?: string; -} { - const reasonLabel = reason?.trim() ? reason.trim() : "closed"; - if (/pairing required/i.test(reasonLabel)) { - return { - connectionStatus: `gateway disconnected: ${reasonLabel}`, - activityStatus: "pairing required: run mayros devices list", - pairingHint: - "Pairing required. Run `mayros devices list`, approve your request ID, then reconnect.", - }; - } - if (/ECONNREFUSED|connect failed/i.test(reasonLabel)) { - return { - connectionStatus: "gateway not running", - activityStatus: "start gateway with: mayros gateway run", - gatewayDownHint: - "Gateway is not responding. Start it with `mayros gateway run` or `mayros onboard`.", - }; - } - return { - connectionStatus: `gateway disconnected: ${reasonLabel}`, - activityStatus: "idle", - }; -} - -export function createBackspaceDeduper(params?: { dedupeWindowMs?: number; now?: () => number }) { - const dedupeWindowMs = Math.max(0, Math.floor(params?.dedupeWindowMs ?? 8)); - const now = params?.now ?? (() => Date.now()); - let lastBackspaceAt = -1; - - return (data: string): string => { - if (!matchesKey(data, Key.backspace)) { - return data; - } - const ts = now(); - if (lastBackspaceAt >= 0 && ts - lastBackspaceAt <= dedupeWindowMs) { - return ""; - } - lastBackspaceAt = ts; - return data; - }; -} +export { + createEditorSubmitHandler, + shouldEnableWindowsGitBashPasteFallback, + createSubmitBurstCoalescer, + resolveTuiSessionKey, + resolveGatewayDisconnectState, + createBackspaceDeduper, +} from "./tui-helpers.js"; +import { + createEditorSubmitHandler, + shouldEnableWindowsGitBashPasteFallback, + createSubmitBurstCoalescer, + resolveTuiSessionKey, + resolveGatewayDisconnectState, + createBackspaceDeduper, + tryInlinePairingApproval, +} from "./tui-helpers.js"; export async function runTui(opts: TuiOptions) { const config = loadConfig();