diff --git a/.env.example b/.env.example index c9541f1..159ea8a 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,5 @@ -# Set SLACK_*, DISCORD_*, and/or TELEGRAM_BOT_TOKEN — the bot starts an adapter -# for each platform whose secrets are present (any one, or several at once). +# Set SLACK_*, DISCORD_*, TELEGRAM_BOT_TOKEN, and/or WHATSAPP_* — the bot starts +# an adapter for each platform whose secrets are present (any one, or several at once). # ── Slack credentials (from api.slack.com/apps → your app) ────────────── # Set both to run on Slack; leave blank to skip Slack. @@ -25,27 +25,43 @@ SLACK_APP_TOKEN=xapp-... # (no public URL or webhook setup needed). # TELEGRAM_BOT_TOKEN= -# ── Persistence (optional) ────────────────────────────────────────────── -# Optional Redis-backed durable store. Used by `pnpm demo:restart` (and any -# bot that passes `store: { adapter: createRedisStore({ url }) }`). Leave blank -# for the in-memory default. With it set, interactive actions (e.g. an approval -# card's button) survive a bot restart — see `app/demo-restart.tsx`. -# Start a local one with `docker compose up -d`. -# REDIS_URL=redis://localhost:6379 - # ── Agent backend (runtime.ts) ────────────────────────────────────────── -# The AG-UI endpoint the bridge POSTs to. Default points at the local -# CopilotKit runtime started by `pnpm runtime`. +# The AG-UI endpoint the bridge POSTs to. REQUIRED — the bridge exits at +# startup if this is unset; there is no code-level fallback. The value below +# is a template pointing at the local CopilotKit runtime started by +# `pnpm runtime`; change it if you deploy the runtime elsewhere. AGENT_URL=http://localhost:8200/api/copilotkit/agent/triage/run # Optional auth header forwarded to the agent (for a deployed runtime). # AGENT_AUTH_HEADER=Bearer ... -# Model for the BuiltInAgent. provider/model — the runtime resolves the -# provider and reads the matching API key below. Defaults to openai/gpt-5.5. -# AGENT_MODEL=anthropic/claude-sonnet-4.5 +# ── Intelligence channel mode — app/managed.ts (`pnpm channel`) ────────── +# Runs the SAME bot over the CopilotKit Intelligence Realtime Gateway instead +# of a native adapter — this process holds NO Slack tokens (Intelligence owns +# the Slack edge). The agent brain reuses AGENT_URL / AGENT_AUTH_HEADER above. +# All values come from your CopilotKit Intelligence project + channel setup. +# Gateway runner WebSocket URL (the /runner endpoint). +# INTELLIGENCE_GATEWAY_WS_URL=wss://dev.intelligence.copilotkit.ai/runner +# Project runtime API key (cpk-{projectId}_...), presented as the socket auth token. +# INTELLIGENCE_API_KEY=cpk-... +# Authoritative org/project/channel scope (from the Intelligence dashboard): +# INTELLIGENCE_ORG_ID=org_... +# INTELLIGENCE_PROJECT_ID=123 +# INTELLIGENCE_CHANNEL_ID=channel_... +# The registered channel name (lowercase kebab). Defaults to "kitebot". +# INTELLIGENCE_CHANNEL_NAME=kitebot +# Optional stable runtime instance id; auto-generated (rti_...) if unset. +# INTELLIGENCE_RUNTIME_INSTANCE_ID=rti_... + +# Model for the BuiltInAgent. The runtime is OpenAI-only (it uses OpenAI's +# Responses API via TanStack AI's `openaiText` adapter, needed for the +# `web_search` provider tool) — there is no multi-provider resolution. +# AGENT_MODEL only accepts an OpenAI model id, optionally prefixed with +# "openai/" (the prefix is stripped); defaults to openai/gpt-5.5. +# AGENT_MODEL=openai/gpt-5.5 OPENAI_API_KEY=sk-... -# ANTHROPIC_API_KEY=sk-ant-... -# GOOGLE_API_KEY=... +# ANTHROPIC_API_KEY / GOOGLE_API_KEY are NOT supported by this runtime today +# (runtime.ts never reads them) — do not set AGENT_MODEL to an anthropic/... or +# google/... value. # ── Linear MCP ────────────────────────────────────────────────────────── # The hosted Linear MCP accepts a raw API key as a bearer token (no OAuth @@ -69,6 +85,12 @@ NOTION_TOKEN=ntn_... NOTION_MCP_AUTH_TOKEN=choose-a-strong-shared-secret # Override only if the sidecar runs elsewhere; default is the local sidecar. # NOTION_MCP_URL=http://127.0.0.1:3001/mcp +# Port the `pnpm notion-mcp` sidecar listens on (scripts/start-notion-mcp.ts). +# Must agree with the port in NOTION_MCP_URL above. Defaults to 3001. +# NOTION_MCP_PORT=3001 +# Notion-Version header the sidecar sends to the Notion API. Defaults to +# 2022-06-28; override only if you need a newer Notion API version. +# NOTION_VERSION=2022-06-28 # ── WhatsApp Cloud API (optional — omit to run Slack-only) ────────────── # From your Meta App → WhatsApp → API Setup. Leave WHATSAPP_ACCESS_TOKEN blank diff --git a/README.md b/README.md index 7b0739c..7950bcf 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ renders rich results right in the conversation. Think of it as having Claude in workspace, except **open-source and self-hosted**: you own the runtime, bring your own model, and wire it to your own tools. No per-seat pricing, no lock-in. -It's built on **[`@copilotkit/bot`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot)** — +It's built on **[`@copilotkit/channels`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels)** — CopilotKit's open SDK for chat-platform agents (Slack first; the same code also runs on Discord, Telegram, and WhatsApp). Clone it, point it at your model and tools, and you own the whole stack. @@ -14,19 +14,31 @@ the whole stack. https://github.com/user-attachments/assets/a74fa1cb-add0-463e-a23c-aa09b95d5135 -▶️ **[Watch the demo](https://github.com/user-attachments/assets/a74fa1cb-add0-463e-a23c-aa09b95d5135)** (~50s) — an OpenTag agent working a Slack thread: it renders a breakdown, a table, and a bar chart inline (**generative UI**) and files a ticket only after an **Approve** gate (**human-in-the-loop**). +▶️ **[Watch the demo](https://github.com/user-attachments/assets/a74fa1cb-add0-463e-a23c-aa09b95d5135)** (~50s) — a KiteBot agent working a Slack thread: it renders a breakdown, a table, and a bar chart inline (**generative UI**) and files a ticket only after an **Approve** gate (**human-in-the-loop**). > **Two ways to run it:** **host it on your own** with the open-source SDK below — or skip the ops and **[sign up for the managed service →](https://go.copilotkit.ai/opentag-managed-gh)** coming soon from CopilotKit. The managed service will be part of our Enterprise Intelligence platform. You'll be able to use our cloud-hosting or enterprises can host it on their own infra. +> +> Note: the **Intelligence Gateway** mode below is part of "host it on your own" — you run that +> process yourself and bring your own CopilotKit Intelligence project. It's distinct from the +> fully-hosted **managed service** above, which is still on the waitlist. -## Quick start (self-hosted) +## Quick start -OpenTag ships inside the [CopilotKit monorepo](https://github.com/CopilotKit/CopilotKit) as a -first-class example (`examples/slack`). That's the dependable way to run it today while the -bot SDK packages finish publishing to npm. (A standalone `npm install` from this repo lights -up the moment they land — see [setup.md](./setup.md).) +OpenTag's packages are published on npm — a standalone `pnpm install` in this repo pulls in +everything you need, no monorepo required. -You'll run two processes: the **agent** (the LLM backend) and the **bot** (the Slack -connection) — and set three secrets. +You'll run two processes: the **agent backend** (`pnpm runtime`) and **the bot**. For the bot, +pick one of two modes: + +- **Intelligence Gateway — recommended.** `pnpm channel` runs the bot over the CopilotKit + Intelligence Realtime Gateway. This process never holds a Slack token — Intelligence owns + the Slack edge — so there's less for you to run and secure. You still run this process + yourself and bring your own CopilotKit Intelligence project — it's not the fully-hosted + managed service described below. +- **Self-hosted.** `pnpm dev` (or `pnpm start`) runs the bot locally and talks to Slack (and + Discord/Telegram/WhatsApp) directly with your own platform tokens. + +Both modes talk to the same agent backend over AG-UI. ### The packages @@ -36,44 +48,58 @@ OpenTag is a thin layer on top of a handful of CopilotKit packages. The `pnpm in | Package | Role | | --- | --- | -| [`@copilotkit/bot`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot) | The platform-agnostic bot engine — threading, tool calls, the human-in-the-loop gate. | +| [`@copilotkit/channels`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels) | The platform-agnostic bot engine — threading, tool calls, the human-in-the-loop gate. | | [`@copilotkit/runtime`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/runtime) | The AG-UI agent backend that runs your LLM and tools. | -| [`@copilotkit/bot-ui`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-ui) | Cross-platform JSX for rich messages (Block Kit on Slack, Components V2 on Discord, HTML on Telegram). | -| [`@copilotkit/bot-slack`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-slack) | The Slack adapter — or swap it for the platform you're targeting (below). | +| [`@copilotkit/channels-ui`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-ui) | Cross-platform JSX for rich messages (Block Kit on Slack, Components V2 on Discord, HTML on Telegram). | +| [`@copilotkit/channels-slack`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-slack) | The Slack adapter — or swap it for the platform you're targeting (below). | **Optional** — add only what you use: | Package | When you need it | | --- | --- | -| [`@copilotkit/bot-discord`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-discord) · [`-telegram`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-telegram) · [`-whatsapp`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-whatsapp) | Running on a platform other than Slack — one adapter per platform. | -| [`@copilotkit/bot-store-redis`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-store-redis) | Durable thread persistence across restarts (defaults to in-memory without it). | +| [`@copilotkit/channels-discord`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-discord) · [`-telegram`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-telegram) · [`-whatsapp`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-whatsapp) | Running on a platform other than Slack — one adapter per platform. | +| [`@copilotkit/channels-intelligence`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-intelligence) | Runs the bot over the CopilotKit Intelligence Realtime Gateway instead of holding platform tokens — see `app/managed.ts`. | **1. Create a Slack app.** At [api.slack.com/apps](https://api.slack.com/apps?new_app=1) → *From a manifest* → paste [`slack-app-manifest.yaml`](./slack-app-manifest.yaml). Install it, then grab the **Bot User OAuth Token** (`xoxb-…`) and an **App-Level Token** (`xapp-…`, with the -`connections:write` scope). Step-by-step in [setup.md](./setup.md#1-create-a-slack-app). +`connections:write` scope) — needed for self-hosted mode, or to register the app with your +CopilotKit Intelligence project for Intelligence mode. Step-by-step in +[setup.md](./setup.md#1-create-a-slack-app). -**2. Set three secrets** in `.env` (`cp .env.example .env`): +**2. Set your secrets** in `.env` (`cp .env.example .env`): ```bash +OPENAI_API_KEY=sk-... # the agent runs on OpenAI's Responses API (required for web search) + +# Self-hosted mode: SLACK_BOT_TOKEN=xoxb-... SLACK_APP_TOKEN=xapp-... -OPENAI_API_KEY=sk-... # or ANTHROPIC_API_KEY — bring your own model + +# Intelligence Gateway mode — full list in .env.example: +INTELLIGENCE_GATEWAY_WS_URL=wss://... +INTELLIGENCE_API_KEY=cpk-... +INTELLIGENCE_ORG_ID=org_... +INTELLIGENCE_PROJECT_ID=... +INTELLIGENCE_CHANNEL_ID=channel_... ``` -**3. Run it** from the CopilotKit monorepo root: +**3. Run it:** ```bash pnpm install -pnpm --filter slack-example runtime # the agent backend, on :8200 -pnpm --filter slack-example dev # the bot +pnpm runtime # the agent backend, on :8200 + +pnpm channel # recommended — the bot over the Intelligence Gateway +# or +pnpm dev # alternative — the bot, self-hosted ``` **4. Talk to it.** @mention the bot in any channel thread: -> @OpenTag summarize this thread and file it as a bug +> @KiteBot summarize this thread and file it as a bug -That's the whole loop. To wire up Linear, Notion, inline charts, Redis persistence, or to run +That's the whole loop. To wire up Linear, Notion, inline charts, or to run on Discord / Telegram / WhatsApp, see **[setup.md](./setup.md)**. We won't lie to you, though. Setting up hosting for chat agents is not easy. To skip all of that heartache, go [join the waitlist](https://go.copilotkit.ai/opentag-managed-gh) for the CopilotKit managed service as part of our Intelligence platform, both cloud-hosted or self-hosted. diff --git a/app/commands/__tests__/commands.test.ts b/app/commands/__tests__/commands.test.ts index f03b28a..7a4a446 100644 --- a/app/commands/__tests__/commands.test.ts +++ b/app/commands/__tests__/commands.test.ts @@ -1,8 +1,8 @@ import { describe, it, expect, vi } from "vitest"; -import { renderToIR } from "@copilotkit/bot-ui"; -import type { BotNode } from "@copilotkit/bot-ui"; +import { renderToIR } from "@copilotkit/channels-ui"; +import type { BotNode } from "@copilotkit/channels-ui"; import { appCommands } from "../index.js"; -import type { CommandContext } from "@copilotkit/bot"; +import type { CommandContext } from "@copilotkit/channels"; function tags(node: BotNode | unknown, acc: string[] = []): string[] { if (!node || typeof node !== "object") return acc; @@ -74,6 +74,27 @@ describe("example slash commands", () => { expect(thread.post).toHaveBeenCalledTimes(1); }); + it("/agent logs and posts an apology when runAgent rejects", async () => { + const thread = fakeThread(); + thread.runAgent.mockRejectedValueOnce(new Error("backend unavailable")); + const consoleError = vi.spyOn(console, "error").mockImplementation(() => {}); + + await byName("agent").handler( + ctx({ + command: "agent", + text: "why is prod down", + thread: thread as never, + }), + ); + + expect(consoleError).toHaveBeenCalled(); + expect(thread.post).toHaveBeenCalledWith( + expect.stringMatching(/sorry.*error/i), + ); + + consoleError.mockRestore(); + }); + it("/triage runs the agent with a triage prompt", async () => { const thread = fakeThread(); await byName("triage").handler( @@ -85,7 +106,23 @@ describe("example slash commands", () => { ); }); - it("/preview posts an ephemeral draft and reports the native path", async () => { + it("/triage with text passes the note through in the triage prompt", async () => { + const thread = fakeThread(); + await byName("triage").handler( + ctx({ + command: "triage", + text: "checkout is failing", + thread: thread as never, + }), + ); + expect(thread.runAgent).toHaveBeenCalledTimes(1); + expect(thread.runAgent.mock.calls[0]![0]).toMatchObject({ + prompt: + "Triage this and propose Linear issues to file: checkout is failing", + }); + }); + + it("/preview posts an ephemeral draft on the native (non-fallback) path", async () => { const preview = appCommands.find((c) => c.name === "preview")!; expect(preview).toBeDefined(); const postEphemeral = vi @@ -104,6 +141,8 @@ describe("example slash commands", () => { const [user, , opts] = postEphemeral.mock.calls[0]!; expect(user).toEqual({ id: "U1", name: "Ada" }); expect(opts).toEqual({ fallbackToDM: true }); + // Native path (ok, no fallback) is silent — no follow-up narration post. + expect(post).not.toHaveBeenCalled(); }); it("/preview asks for a title when none is given", async () => { @@ -122,6 +161,24 @@ describe("example slash commands", () => { expect(postEphemeral).not.toHaveBeenCalled(); }); + it("/preview with no user says it can't tell who you are", async () => { + const preview = byName("preview"); + const postEphemeral = vi.fn(); + const post = vi.fn().mockResolvedValue({ id: "1" }); + await preview.handler({ + thread: { postEphemeral, post } as never, + command: "preview", + text: "Login broken", + options: {}, + user: undefined, + platform: "slack", + } as never); + expect(postEphemeral).not.toHaveBeenCalled(); + expect(post).toHaveBeenCalledWith( + expect.stringMatching(/couldn.t tell who you are/i), + ); + }); + it("/file-issue opens the rich modal on Slack", async () => { const cmd = appCommands.find((c) => c.name === "file-issue")!; expect(cmd).toBeDefined(); diff --git a/app/commands/index.ts b/app/commands/index.ts index 1d387bd..aa0c216 100644 --- a/app/commands/index.ts +++ b/app/commands/index.ts @@ -11,12 +11,37 @@ * surfaces with native structured args (e.g. Discord). The `options` schema * is optional and used there for registration/typing. */ -import { defineBotCommand } from "@copilotkit/bot"; -import type { BotCommand } from "@copilotkit/bot"; +import { defineBotCommand } from "@copilotkit/channels"; +import type { BotCommand } from "@copilotkit/channels"; +import type { Thread as BotThread } from "@copilotkit/channels-ui"; import { senderContext } from "../sender-context.js"; import { IssueCard } from "../components/index.js"; import { FileIssueModal } from "../modals/file-issue.js"; +/** + * `thread.runAgent` can reject (backend failure, network error, etc). Unlike + * `onMention` (which wraps its own call), the slash-command handlers below + * called it bare, so a failure only surfaced as an unhandledRejection and the + * user saw nothing. This wraps the call so we always log and tell the user + * something went wrong instead of going silent. + */ +async function runAgentSafely( + commandName: string, + thread: Pick, + input: Parameters[0], +): Promise { + try { + await thread.runAgent(input); + } catch (err) { + console.error(`[command] ${commandName} run failed`, err); + await thread + .post("Sorry — I hit an error handling that. Please try again.") + .catch((postErr: unknown) => + console.error(`[command] ${commandName} failed to post error`, postErr), + ); + } +} + export const appCommands: BotCommand[] = [ // `/agent ` — a mention-free entry point. (Previously hardcoded in the // adapter; now an ordinary, app-owned command.) Runs the agent with the @@ -30,7 +55,7 @@ export const appCommands: BotCommand[] = [ await thread.post("Usage: `/agent `"); return; } - await thread.runAgent({ + await runAgentSafely("agent", thread, { prompt: text, context: senderContext(user, thread.platform), }); @@ -47,7 +72,7 @@ export const appCommands: BotCommand[] = [ const prompt = text ? `Triage this and propose Linear issues to file: ${text}` : "Triage the current conversation: summarize it and propose Linear issues to file."; - await thread.runAgent({ + await runAgentSafely("triage", thread, { prompt, context: senderContext(user, thread.platform), }); @@ -114,7 +139,7 @@ export const appCommands: BotCommand[] = [ "Modals aren't supported here — let's do it in chat instead. " + "Tell me the issue title and a short description and I'll file it.", ); - await thread.runAgent({ + await runAgentSafely("file-issue", thread, { prompt: "The user wants to file a Linear issue but this platform has no modal form. " + "Ask them for a title and description, then (after the usual confirm) file it.", diff --git a/app/components/__tests__/components.test.tsx b/app/components/__tests__/components.test.tsx index 94c7e6b..8b5c5d6 100644 --- a/app/components/__tests__/components.test.tsx +++ b/app/components/__tests__/components.test.tsx @@ -1,6 +1,6 @@ /** * Block Kit parity tests for the JSX render components. Each component is a - * `@copilotkit/bot-ui` `ComponentFn`; we assert the full + * `@copilotkit/channels-ui` `ComponentFn`; we assert the full * `renderSlackMessage(renderToIR(<… />))` output — both the `blocks` and the * attachment `accent` — against the legacy `defineSlackComponent` shapes. * @@ -15,12 +15,13 @@ * so they render identically on both Slack and Telegram. */ import { describe, it, expect } from "vitest"; -import { renderToIR } from "@copilotkit/bot-ui"; -import { renderSlackMessage } from "@copilotkit/bot-slack"; -import { renderTelegram } from "@copilotkit/bot-telegram"; +import { renderToIR } from "@copilotkit/channels-ui"; +import { renderSlackMessage } from "@copilotkit/channels-slack"; +import { renderTelegram } from "@copilotkit/channels-telegram"; import { IssueList } from "../issue-list.js"; import { IssueCard } from "../issue-card.js"; import { PageList } from "../page-list.js"; +import { accentForIssues } from "../_status.js"; describe("IssueList component", () => { it("renders exactly three blocks: header, a single section with one line per issue, and a count footer", () => { @@ -121,6 +122,55 @@ describe("IssueList component", () => { // No urgent/high priority → Linear purple. expect(accent).toBe("#5E6AD2"); }); + + it("trims titles longer than TITLE_MAX (70 chars) with an ellipsis", () => { + const longTitle = "x".repeat(80); + const { blocks } = renderSlackMessage( + renderToIR( + , + ), + ); + const section = blocks[1] as { text: { text: string } }; + expect(section.text.text).toContain(`${"x".repeat(70)}…`); + expect(section.text.text).not.toContain("x".repeat(71)); + }); + + it("includes priority in the per-row meta line, and omits it gracefully when absent", () => { + const { blocks } = renderSlackMessage( + renderToIR( + , + ), + ); + const section = blocks[1] as { text: { text: string } }; + const lines = section.text.text.split("\n"); + // Priority sits alongside assignee/updated in the meta, matching the + // existing " · " separator convention. + expect(lines[0]).toContain("Alem · High · 2d ago"); + // No priority → no dangling separator, still falls back to unassigned. + expect(lines[1]).toContain("unassigned"); + expect(lines[1]).not.toContain("·"); + }); +}); + +describe("accentForIssues", () => { + it("maps a list whose hottest priority is 'High' to the high (hot) accent", () => { + expect( + accentForIssues([{ priority: "Low" }, { priority: "High" }]), + ).toBe("#F2994A"); + }); }); describe("IssueCard component", () => { @@ -246,6 +296,23 @@ describe("PageList component", () => { // Notion-dark accent. expect(accent).toBe("#2F3437"); }); + + it("caps rendered pages at 15 and reports the overflow in the footer", () => { + const pages = Array.from({ length: 20 }, (_, i) => ({ + title: `Page ${i + 1}`, + })); + const { blocks } = renderSlackMessage( + renderToIR(), + ); + const json = JSON.stringify(blocks); + expect(json).toContain("*Page 1*"); + expect(json).toContain("*Page 15*"); + expect(json).not.toContain("*Page 16*"); + // Footer surfaces the overflow, mirroring issue-list's pattern. + expect(JSON.stringify(blocks[blocks.length - 1])).toContain( + "Showing 15 of 20 pages", + ); + }); }); // ── Telegram parity tests ──────────────────────────────────────────────────── diff --git a/app/components/index.ts b/app/components/index.ts index cb76a14..823bf9d 100644 --- a/app/components/index.ts +++ b/app/components/index.ts @@ -1,6 +1,6 @@ /** * App-specific render components — agent-renderable Block Kit cards authored - * with the `@copilotkit/bot-ui` JSX vocabulary. + * with the `@copilotkit/channels-ui` JSX vocabulary. * * Each component is a plain `ComponentFn` returning a `` tree; its * exported zod prop schema doubles as the render-tool input schema. Render a diff --git a/app/components/issue-card.tsx b/app/components/issue-card.tsx index 7383ef9..fbe9f2f 100644 --- a/app/components/issue-card.tsx +++ b/app/components/issue-card.tsx @@ -7,7 +7,7 @@ * Use it for one issue — when the user asks about a specific issue, or * right after creating one (it doubles as the "filed!" confirmation). * - * Authored with the `@copilotkit/bot-ui` JSX vocabulary; the Block Kit + * Authored with the `@copilotkit/channels-ui` JSX vocabulary; the Block Kit * shapes are produced by `renderSlackMessage(renderToIR())`. */ import { z } from "zod"; @@ -19,8 +19,8 @@ import { Header, Message, Section, -} from "@copilotkit/bot-ui"; -import type { BotNode } from "@copilotkit/bot-ui"; +} from "@copilotkit/channels-ui"; +import type { BotNode } from "@copilotkit/channels-ui"; import { accentForIssue, priorityGlyph, stateGlyph } from "./_status.js"; export const issueCardSchema = z.object({ diff --git a/app/components/issue-list.tsx b/app/components/issue-list.tsx index 1339c43..9a3c71f 100644 --- a/app/components/issue-list.tsx +++ b/app/components/issue-list.tsx @@ -1,7 +1,7 @@ /** * `issue_list` — renders a set of Linear issues as a compact Block Kit card: * a header, ONE section with one scannable line per issue (status dot + linked - * identifier + title + assignee · updated), and a count footer. + * identifier + title + assignee · priority · updated), and a count footer. * * This is deliberately a fixed THREE-block layout (header + section + context) * regardless of issue count: a card-per-issue layout (~3 blocks each) blows @@ -13,11 +13,11 @@ * it wants shown; the Slack formatting lives here. For a single issue (or * right after creating one) prefer `issue_card`, which shows a full grid. * - * Authored with the `@copilotkit/bot-ui` JSX vocabulary. + * Authored with the `@copilotkit/channels-ui` JSX vocabulary. */ import { z } from "zod"; -import { Context, Header, Message, Section } from "@copilotkit/bot-ui"; -import type { BotNode } from "@copilotkit/bot-ui"; +import { Context, Header, Message, Section } from "@copilotkit/channels-ui"; +import type { BotNode } from "@copilotkit/channels-ui"; import { accentForIssues, stateGlyph } from "./_status.js"; const issueSchema = z.object({ @@ -68,7 +68,7 @@ export function IssueList({ heading, issues }: IssueListProps): BotNode { issue.title.length > TITLE_MAX ? `${issue.title.slice(0, TITLE_MAX)}…` : issue.title; - const meta = `${issue.assignee ?? "unassigned"}${issue.updated ? ` · ${issue.updated}` : ""}`; + const meta = `${issue.assignee ?? "unassigned"}${issue.priority ? ` · ${issue.priority}` : ""}${issue.updated ? ` · ${issue.updated}` : ""}`; return `${stateGlyph(issue.state)} ${idLink} ${title} — ${meta}`; }); diff --git a/app/components/page-list.tsx b/app/components/page-list.tsx index 2f4101b..31d905b 100644 --- a/app/components/page-list.tsx +++ b/app/components/page-list.tsx @@ -3,14 +3,21 @@ * a header, then one row per page (📄 linked title + a greyed snippet and * optional last-edited), with dividers and a count footer. * + * Each page row renders as its own section (+ optional context + divider), + * so a long list produces many blocks — unlike `issue_list`, which folds + * every issue into a single fixed section. To avoid blowing past Slack's + * per-attachment block limit (and getting the whole message rejected with + * `invalid_attachments`), we cap the rendered rows at `MAX` and surface the + * overflow in the footer, mirroring `issue-list.tsx`'s approach. + * * The agent searches Notion via MCP and passes the pages it wants to * surface; the Slack formatting lives here. * - * Authored with the `@copilotkit/bot-ui` JSX vocabulary. + * Authored with the `@copilotkit/channels-ui` JSX vocabulary. */ import { z } from "zod"; -import { Context, Divider, Header, Message, Section } from "@copilotkit/bot-ui"; -import type { BotNode } from "@copilotkit/bot-ui"; +import { Context, Divider, Header, Message, Section } from "@copilotkit/channels-ui"; +import type { BotNode } from "@copilotkit/channels-ui"; import { ACCENT } from "./_status.js"; const pageSchema = z.object({ @@ -38,10 +45,14 @@ export const pageListSchema = z.object({ export type PageListProps = z.infer; type Page = z.infer; +/** Max pages rendered inline; the rest are summarized in the footer. */ +const MAX = 15; + /** Render a list of Notion pages as a Block Kit card. */ export function PageList({ heading, pages }: PageListProps): BotNode { + const shown = pages.slice(0, MAX); const rows: BotNode[] = []; - pages.forEach((page: Page, i: number) => { + shown.forEach((page: Page, i: number) => { const titleLink = page.url ? `[**${page.title}**](${page.url})` : `**${page.title}**`; @@ -57,14 +68,19 @@ export function PageList({ heading, pages }: PageListProps): BotNode { rows.push(
{`📄 ${titleLink}`}
); if (meta) rows.push({meta}); - if (i < pages.length - 1) rows.push(); + if (i < shown.length - 1) rows.push(); }); + const footer = + pages.length > MAX + ? `Showing ${MAX} of ${pages.length} pages` + : `${pages.length} page${pages.length === 1 ? "" : "s"}`; + return (
{`📚 ${heading ?? "Notion pages"}`}
{rows} - {`${pages.length} page${pages.length === 1 ? "" : "s"}`} + {footer}
); } diff --git a/app/context/app-context.ts b/app/context/app-context.ts index f59a618..ebeea11 100644 --- a/app/context/app-context.ts +++ b/app/context/app-context.ts @@ -9,13 +9,13 @@ * `context` on every turn; the agent backend surfaces them as a * system-level "App Context:" message. */ -import type { ContextEntry } from "@copilotkit/bot"; +import type { ContextEntry } from "@copilotkit/channels"; export const appContext: ReadonlyArray = [ { description: "Bot identity & tone", value: [ - "You are the team's on-call triage assistant. Be concise and action-", + "You are KiteBot, the team's on-call triage assistant. Be concise and action-", "oriented — responders are mid-incident. Lead with the answer, then any", "links. Prefer rendering issues/pages as cards over long prose.", ].join("\n"), diff --git a/app/demo-restart.tsx b/app/demo-restart.tsx deleted file mode 100644 index 0c66845..0000000 --- a/app/demo-restart.tsx +++ /dev/null @@ -1,217 +0,0 @@ -/** - * Durable-action restart demo — proves an interactive action survives a bot - * restart. Minimal (Slack only, NO agent backend): on @mention it posts an - * approval card whose **Create button's onClick does the work directly** - * (self-contained — no agent run, no awaitChoice). Because the action snapshot - * is persisted in the configured `store` and the component is registered at - * startup via `components`, the click re-fires after a process restart. - * - * Redis is OPTIONAL: - * • No `REDIS_URL` -> in-memory store (default). Runs out of the box, but a - * click that lands after a restart degrades to "action expired". - * • With `REDIS_URL` -> Redis-backed store. Kill + restart the bot between - * posting and clicking, and the action still fires (durable). - * - * Linear is OPTIONAL: with `LINEAR_API_KEY` the Create button files a real - * Linear issue; without it, it just resolves the card (so the demo runs with - * only Slack tokens). - * - * Run: - * pnpm demo:restart # in-memory, no Redis needed - * docker compose up -d && REDIS_URL=redis://localhost:6379 pnpm demo:restart - */ -import "dotenv/config"; -import { createBot } from "@copilotkit/bot"; -import type { StoreConfig } from "@copilotkit/bot"; -import { slack } from "@copilotkit/bot-slack"; -import { createRedisStore } from "@copilotkit/bot-store-redis"; -import { - Message, - Header, - Section, - Context, - Actions, - Button, -} from "@copilotkit/bot-ui"; -import type { InteractionContext } from "@copilotkit/bot-ui"; - -function required(name: string): string { - const v = process.env[name]; - if (!v) { - console.error(`Missing required env var: ${name}`); - process.exit(1); - } - return v; -} - -const LINEAR_API_KEY = process.env.LINEAR_API_KEY; -const REDIS_URL = process.env.REDIS_URL; - -// --- Optional Linear write (direct GraphQL; no agent / MCP) ------------------ -async function linearGraphQL(query: string, variables: object): Promise { - const res = await fetch("https://api.linear.app/graphql", { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: LINEAR_API_KEY as string, - }, - body: JSON.stringify({ query, variables }), - }); - const json = (await res.json()) as { data?: T; errors?: unknown }; - if (!res.ok || json.errors) { - throw new Error( - `Linear API error: ${JSON.stringify(json.errors ?? res.status)}`, - ); - } - return json.data as T; -} - -async function createLinearIssue( - title: string, -): Promise<{ identifier: string; url: string }> { - const teamKey = required("LINEAR_TEAM_KEY"); - const teams = await linearGraphQL<{ teams: { nodes: { id: string }[] } }>( - `query($key: String!) { teams(filter: { key: { eq: $key } }) { nodes { id } } }`, - { key: teamKey }, - ); - const teamId = teams.teams.nodes[0]?.id; - if (!teamId) throw new Error(`No Linear team with key ${teamKey}`); - const created = await linearGraphQL<{ - issueCreate: { - success: boolean; - issue: { identifier: string; url: string }; - }; - }>( - `mutation($teamId: String!, $title: String!) { - issueCreate(input: { teamId: $teamId, title: $title }) { - success issue { identifier url } - } - }`, - { teamId, title }, - ); - if (!created.issueCreate.success) - throw new Error("Linear issueCreate failed"); - return created.issueCreate.issue; -} - -// --- The durable HITL card (self-contained onClick does the write) ----------- -interface ConfirmCreateIssueProps { - title: string; -} - -export function ConfirmCreateIssue({ title }: ConfirmCreateIssueProps) { - return ( - -
{`📝 Create Linear issue?`}
-
{`**${title}**`}
- - {REDIS_URL - ? "🔒 Nothing is written until you click **Create**. Kill + restart the bot first to prove durability." - : "🔒 Nothing is written until you click **Create**. (Set REDIS_URL for restart-durable actions.)"} - - - - - -
- ); -} - -async function main() { - // Redis is optional: configure a durable backend only when REDIS_URL is set; - // otherwise omit `adapter` and the bot uses the in-memory default. - const store: StoreConfig | undefined = REDIS_URL - ? { adapter: createRedisStore({ url: REDIS_URL }) } - : undefined; - - const bot = createBot({ - adapters: [ - slack({ - botToken: required("SLACK_BOT_TOKEN"), - appToken: required("SLACK_APP_TOKEN"), - }), - ], - store, - // Registered at startup so a click landing AFTER a restart can re-render - // this component from the persisted snapshot and re-fire its onClick. - components: [ConfirmCreateIssue], - }); - - bot.onMention(async ({ thread, message }) => { - const title = message.text.trim().slice(0, 120) || "Untitled (demo)"; - await thread.post(); - }); - - await bot.start(); - console.log( - `[demo] up (pid ${process.pid}) — store: ${REDIS_URL ? "redis (durable)" : "in-memory"}, ` + - `write: ${LINEAR_API_KEY ? "linear" : "demo (no LINEAR_API_KEY)"}. @mention the bot.`, - ); - - const stop = async () => { - await bot.stop(); - process.exit(0); - }; - process.on("SIGINT", () => void stop()); - process.on("SIGTERM", () => void stop()); -} - -main().catch((err) => { - console.error("[demo] fatal", err); - process.exit(1); -}); diff --git a/app/human-in-the-loop/__tests__/confirm-write-tool.test.tsx b/app/human-in-the-loop/__tests__/confirm-write-tool.test.tsx index bba556b..d223b44 100644 --- a/app/human-in-the-loop/__tests__/confirm-write-tool.test.tsx +++ b/app/human-in-the-loop/__tests__/confirm-write-tool.test.tsx @@ -1,6 +1,6 @@ -import { describe, it, expect } from "vitest"; -import { renderToIR, type BotNode } from "@copilotkit/bot-ui"; -import { renderSlackMessage } from "@copilotkit/bot-slack"; +import { describe, it, expect, vi } from "vitest"; +import { renderToIR, type BotNode } from "@copilotkit/channels-ui"; +import { renderSlackMessage } from "@copilotkit/channels-slack"; import { confirmWriteTool } from "../confirm-write-tool.js"; /** A fake thread whose `awaitChoice` records the posted UI and returns a fixed choice. */ @@ -53,4 +53,22 @@ describe("confirm_write tool", () => { "The user DECLINED — do not write; acknowledge and stop.", ); }); + + it("returns a NO-RESPONSE message and logs when awaitChoice resolves null (timeout/dismissed)", async () => { + const { thread } = fakeThread(null); + const consoleError = vi + .spyOn(console, "error") + .mockImplementation(() => undefined); + + const result = await confirmWriteTool.handler( + { action: "Create Linear issue" }, + { thread, platform: "slack" } as never, + ); + + expect(result).toMatch(/no response/i); + expect(result).not.toMatch(/APPROVED/); + expect(consoleError).toHaveBeenCalled(); + + consoleError.mockRestore(); + }); }); diff --git a/app/human-in-the-loop/__tests__/confirm-write.test.tsx b/app/human-in-the-loop/__tests__/confirm-write.test.tsx index c6b9ae6..fbe98bd 100644 --- a/app/human-in-the-loop/__tests__/confirm-write.test.tsx +++ b/app/human-in-the-loop/__tests__/confirm-write.test.tsx @@ -4,8 +4,8 @@ import { type BotNode, type InteractionContext, type ClickHandler, -} from "@copilotkit/bot-ui"; -import { renderSlackMessage } from "@copilotkit/bot-slack"; +} from "@copilotkit/channels-ui"; +import { renderSlackMessage } from "@copilotkit/channels-slack"; import { ConfirmWrite } from "../confirm-write.js"; /** Children of an IR node as an array (empty if none). */ diff --git a/app/human-in-the-loop/confirm-write-tool.tsx b/app/human-in-the-loop/confirm-write-tool.tsx index 1db0e82..71fa7b1 100644 --- a/app/human-in-the-loop/confirm-write-tool.tsx +++ b/app/human-in-the-loop/confirm-write-tool.tsx @@ -10,7 +10,7 @@ * performs the write once this returns `{ confirmed: true }`. */ import { z } from "zod"; -import { defineBotTool } from "@copilotkit/bot"; +import { defineBotTool } from "@copilotkit/channels"; import { ConfirmWrite } from "./confirm-write.js"; export const confirmWriteSchema = z.object({ @@ -39,7 +39,13 @@ export const confirmWriteTool = defineBotTool({ const choice = await thread.awaitChoice<{ confirmed?: boolean }>( , ); - return choice?.confirmed + if (choice == null) { + console.error( + "[confirm-write] no choice resolved (timeout/dismissed)", + ); + return "NO RESPONSE — the confirmation card was dismissed or timed out; do not write."; + } + return choice.confirmed ? "The user APPROVED the write — proceed." : "The user DECLINED — do not write; acknowledge and stop."; }, diff --git a/app/human-in-the-loop/confirm-write.tsx b/app/human-in-the-loop/confirm-write.tsx index 1e5eab8..e180aed 100644 --- a/app/human-in-the-loop/confirm-write.tsx +++ b/app/human-in-the-loop/confirm-write.tsx @@ -22,8 +22,8 @@ import { Context, Actions, Button, -} from "@copilotkit/bot-ui"; -import type { InteractionContext } from "@copilotkit/bot-ui"; +} from "@copilotkit/channels-ui"; +import type { InteractionContext } from "@copilotkit/channels-ui"; export interface ConfirmWriteProps { /** Short imperative title of the write, e.g. 'Create Linear issue'. */ @@ -43,13 +43,17 @@ export function ConfirmWrite({ action, detail }: ConfirmWriteProps) { value={{ confirmed: true }} style="primary" onClick={async ({ thread, message }: InteractionContext) => { - await thread.update( - message.ref, - -
{`✅ ${action}`}
- {"✅ Approved — writing now."} -
, - ); + try { + await thread.update( + message.ref, + +
{`✅ ${action}`}
+ {"✅ Approved — writing now."} +
, + ); + } catch (err) { + console.error("[confirm-write] onClick failed", err); + } }} > Create @@ -58,13 +62,17 @@ export function ConfirmWrite({ action, detail }: ConfirmWriteProps) { value={{ confirmed: false }} style="danger" onClick={async ({ thread, message }: InteractionContext) => { - await thread.update( - message.ref, - -
{`🚫 ${action}`}
- {"🚫 Declined — nothing was written."} -
, - ); + try { + await thread.update( + message.ref, + +
{`🚫 ${action}`}
+ {"🚫 Declined — nothing was written."} +
, + ); + } catch (err) { + console.error("[confirm-write] onClick failed", err); + } }} > Cancel diff --git a/app/index.ts b/app/index.ts index 5944d4d..c2758a0 100644 --- a/app/index.ts +++ b/app/index.ts @@ -5,7 +5,7 @@ * that runs on the chat-platform side of the bot for this deployment. * * MULTI-PLATFORM: this single app drives Slack, Discord, Telegram, and/or - * WhatsApp from one process. `@copilotkit/bot`'s `createBot` accepts an array + * WhatsApp from one process. `@copilotkit/channels`'s `createBot` accepts an array * of adapters and starts them all, so we include each platform's adapter only * when its secrets are present. Drop in `SLACK_*` to run Slack, `DISCORD_*` for * Discord, `TELEGRAM_BOT_TOKEN` for Telegram, `WHATSAPP_*` for WhatsApp — or any @@ -17,29 +17,29 @@ * here in the file you copy from to start a new bot. */ import "dotenv/config"; -import { createBot } from "@copilotkit/bot"; -import type { PlatformAdapter, BotTool, ContextEntry } from "@copilotkit/bot"; +import { createBot } from "@copilotkit/channels"; +import type { PlatformAdapter, BotTool, ContextEntry } from "@copilotkit/channels"; import { slack, defaultSlackTools, defaultSlackContext, SanitizingHttpAgent, -} from "@copilotkit/bot-slack"; +} from "@copilotkit/channels-slack"; import { discord, defaultDiscordTools, defaultDiscordContext, -} from "@copilotkit/bot-discord"; +} from "@copilotkit/channels-discord"; import { telegram, defaultTelegramTools, defaultTelegramContext, -} from "@copilotkit/bot-telegram"; +} from "@copilotkit/channels-telegram"; import { whatsapp, defaultWhatsAppTools, defaultWhatsAppContext, -} from "@copilotkit/bot-whatsapp"; +} from "@copilotkit/channels-whatsapp"; import { appTools } from "./tools/index.js"; import { appContext } from "./context/app-context.js"; import { appCommands } from "./commands/index.js"; @@ -84,9 +84,9 @@ async function main() { // `:wrench:` rows, or pane "is using `tool`…" status). Tools still run; // only the display is hidden. showToolStatus: false, - // Kite keeps DMs conversational and responds to explicit app mentions + // KiteBot keeps DMs conversational and responds to explicit app mentions // in channels/threads. Plain channel thread replies stay quiet unless - // they mention Kite again. + // they mention KiteBot again. respondTo: { directMessages: true, appMentions: { reply: "thread" }, @@ -150,9 +150,9 @@ async function main() { // routes there); locally it defaults to 3000. Fail loud on a malformed // PORT rather than letting `Number("abc")` → NaN reach `server.listen()`. const port = process.env.PORT ? Number(process.env.PORT) : 3000; - if (!Number.isInteger(port) || port < 0) { + if (!Number.isInteger(port) || port < 1 || port > 65535) { console.error( - `Invalid PORT: "${process.env.PORT}" is not a valid port number`, + `Invalid PORT: "${process.env.PORT}" is not a valid port number (must be an integer between 1 and 65535)`, ); process.exit(1); } @@ -228,7 +228,9 @@ async function main() { console.error("[bot] agent run failed", err); await thread .post("Sorry — I hit an error handling that. Please try again.") - .catch(() => {}); + .catch((postErr: unknown) => + console.error("[bot] failed to post agent error", postErr), + ); } }); @@ -244,16 +246,20 @@ async function main() { // platforms without suggested-prompt support no-op. bot.onThreadStarted(async ({ thread, user }) => { if (!user?.name) return; - await thread.setSuggestedPrompts([ - { - title: `Triage ${user.name}'s issues`, - message: "Triage my open issues", - }, - { - title: "What shipped this week?", - message: "Summarize what shipped this week", - }, - ]); + try { + await thread.setSuggestedPrompts([ + { + title: `Triage ${user.name}'s issues`, + message: "Triage my open issues", + }, + { + title: "What shipped this week?", + message: "Summarize what shipped this week", + }, + ]); + } catch (err) { + console.error("[bot] onThreadStarted failed", err); + } }); await bot.start(); @@ -263,13 +269,27 @@ async function main() { const shutdown = async (signal: string) => { console.log(`\n[bot] received ${signal}, stopping…`); - await bot.stop(); + let exitCode = 0; + try { + await bot.stop(); + } catch (err) { + console.error("[bot] error stopping bot", err); + exitCode = 1; + } // Tear down the shared headless browser used for chart/diagram rendering. - await closeBrowser(); - process.exit(0); + await closeBrowser().catch((err: unknown) => + console.error("[bot] browser cleanup failed (continuing shutdown)", err), + ); + process.exit(exitCode); + }; + const runShutdown = (signal: string): void => { + shutdown(signal).catch((err: unknown) => { + console.error(`[bot] fatal during ${signal} shutdown`, err); + process.exit(1); + }); }; - process.on("SIGINT", () => void shutdown("SIGINT")); - process.on("SIGTERM", () => void shutdown("SIGTERM")); + process.on("SIGINT", () => runShutdown("SIGINT")); + process.on("SIGTERM", () => runShutdown("SIGTERM")); } // Fail loud, not silent: surface any stray async error (e.g. a throw deep in an diff --git a/app/managed.test.ts b/app/managed.test.ts new file mode 100644 index 0000000..cc30168 --- /dev/null +++ b/app/managed.test.ts @@ -0,0 +1,103 @@ +import { describe, it, expect } from "vitest"; +import type { AgentContentPart } from "@copilotkit/channels-ui"; +import { + createKiteBot, + promptFromMessage, + buildAgentHeaders, + parseProjectId, +} from "./managed.js"; + +describe("createKiteBot", () => { + it("declares the kitebot channel name", () => { + const bot = createKiteBot({ agentUrl: "http://localhost:8200" }); + expect(bot.name).toBe("kitebot"); + }); + + it("registers the app's slash commands on the bot", () => { + const bot = createKiteBot({ agentUrl: "http://localhost:8200" }); + // createBot normalizes slash-command names (hyphens -> underscores): + // app/commands declares "file-issue"; commandNames reports "file_issue". + expect(bot.commandNames).toContain("file_issue"); + }); + + it("honors a custom channel name", () => { + const bot = createKiteBot({ + agentUrl: "http://localhost:8200", + channelName: "kite-bot", + }); + expect(bot.name).toBe("kite-bot"); + }); +}); + +describe("promptFromMessage", () => { + it("returns contentParts when present", () => { + const parts: AgentContentPart[] = [{ type: "text", text: "hi" }]; + expect( + promptFromMessage({ contentParts: parts, text: "hi" }), + ).toBe(parts); + }); + + it("falls back to text when contentParts is empty", () => { + expect(promptFromMessage({ contentParts: [], text: "hello" })).toBe( + "hello", + ); + }); + + it("falls back to text when contentParts is absent", () => { + expect(promptFromMessage({ text: "hello" })).toBe("hello"); + }); +}); + +describe("buildAgentHeaders", () => { + it("returns undefined when no auth header is given", () => { + expect(buildAgentHeaders(undefined)).toBeUndefined(); + }); + + it("wraps the auth header value in an Authorization object", () => { + expect(buildAgentHeaders("Bearer abc123")).toEqual({ + Authorization: "Bearer abc123", + }); + }); +}); + +describe("parseProjectId", () => { + it("parses a valid positive integer string", () => { + expect(parseProjectId("42")).toBe(42); + }); + + it("throws on \"0\"", () => { + expect(() => parseProjectId("0")).toThrow( + /Invalid INTELLIGENCE_PROJECT_ID/, + ); + }); + + it("throws on a non-numeric string", () => { + expect(() => parseProjectId("abc")).toThrow( + /Invalid INTELLIGENCE_PROJECT_ID/, + ); + }); + + it("throws when undefined", () => { + expect(() => parseProjectId(undefined)).toThrow( + /Invalid INTELLIGENCE_PROJECT_ID/, + ); + }); + + it("throws on a negative integer string", () => { + expect(() => parseProjectId("-5")).toThrow( + /Invalid INTELLIGENCE_PROJECT_ID/, + ); + }); + + it("throws on a non-integer float string", () => { + expect(() => parseProjectId("1.5")).toThrow( + /Invalid INTELLIGENCE_PROJECT_ID/, + ); + }); + + it("throws on an empty string", () => { + expect(() => parseProjectId("")).toThrow( + /Invalid INTELLIGENCE_PROJECT_ID/, + ); + }); +}); diff --git a/app/managed.ts b/app/managed.ts new file mode 100644 index 0000000..36fa059 --- /dev/null +++ b/app/managed.ts @@ -0,0 +1,227 @@ +/** + * Intelligence channel host for KiteBot — the "managed" run mode. + * + * Unlike app/index.ts (self-hosted: holds Slack tokens, talks to Slack + * directly), this process holds NO platform credentials. It runs the SAME bot + * over the CopilotKit Intelligence Realtime Gateway: it declares one channel + * ("kitebot") to the gateway and streams render frames back. Intelligence owns + * the Slack edge (signed ingress + Connector Outbox egress). + * + * The bot's brain is an external AG-UI agent reached over HTTP at AGENT_URL — + * for now the runtime.ts triage backend; in Phase 2 a LangGraph deep agent. + * intelligenceAdapter is exclusive, so the bot is created WITHOUT a native + * adapter and startChannelsOverRealtimeGateway attaches the channel transport. + * + * Run: `pnpm channel` with INTELLIGENCE_* + AGENT_URL set (see .env.example). + */ +import "dotenv/config"; +import { randomUUID } from "node:crypto"; +import { createBot } from "@copilotkit/channels"; +import type { Bot } from "@copilotkit/channels"; +import type { AgentContentPart } from "@copilotkit/channels-ui"; +import { + SanitizingHttpAgent, + defaultSlackTools, + defaultSlackContext, +} from "@copilotkit/channels-slack"; +import { startChannelsOverRealtimeGateway } from "@copilotkit/channels-intelligence"; +import { appTools } from "./tools/index.js"; +import { appContext } from "./context/app-context.js"; +import { appCommands } from "./commands/index.js"; +import { senderContext } from "./sender-context.js"; +import { fileIssueSubmit, FILE_ISSUE_CALLBACK } from "./modals/file-issue.js"; +import { closeBrowser } from "./render/browser.js"; + +const required = (name: string): string => { + const v = process.env[name]; + if (!v) { + console.error(`Missing required env var: ${name}`); + process.exit(1); + } + return v; +}; + +export interface CreateKiteBotOptions { + /** AG-UI agent endpoint the bot's HttpAgent posts to. */ + agentUrl: string; + /** Optional Authorization header value forwarded to the agent. */ + agentAuthHeader?: string; + /** Intelligence channel name (lowercase kebab). Defaults to "kitebot". */ + channelName?: string; +} + +/** + * Pick the prompt to send to the agent for the current turn. Managed history + * does NOT include the in-flight turn, so the current message is always + * passed explicitly — preferring multimodal parts when present. + */ +export function promptFromMessage(message: { + contentParts?: AgentContentPart[]; + text: string; +}): string | AgentContentPart[] { + return message.contentParts?.length ? message.contentParts : message.text; +} + +/** Build the Authorization header object forwarded to the agent, if any. */ +export function buildAgentHeaders( + authHeader?: string, +): { Authorization: string } | undefined { + return authHeader ? { Authorization: authHeader } : undefined; +} + +/** Parse and validate INTELLIGENCE_PROJECT_ID, throwing on any invalid value. */ +export function parseProjectId(raw: string | undefined): number { + const n = Number(raw); + if (!Number.isInteger(n) || n <= 0) { + throw new Error(`Invalid INTELLIGENCE_PROJECT_ID: "${raw}"`); + } + return n; +} + +/** + * Build the KiteBot bot: same tools/context/commands/handlers as the native + * bot, minus any platform adapter (the intelligenceAdapter is attached at + * activation by startChannelsOverRealtimeGateway). Pure — no network, no env + * reads — so it is unit-testable. + */ +export function createKiteBot(opts: CreateKiteBotOptions): Bot { + const channelName = opts.channelName ?? "kitebot"; + const agentHeaders = buildAgentHeaders(opts.agentAuthHeader); + + const bot = createBot({ + name: channelName, + agent: (threadId: string) => { + const a = new SanitizingHttpAgent({ + url: opts.agentUrl, + headers: agentHeaders, + }); + a.threadId = threadId; + return a; + }, + tools: [...appTools, ...defaultSlackTools], + context: [...appContext, ...defaultSlackContext], + commands: appCommands, + }); + + // Managed history does NOT include the in-flight turn, so pass the current + // message explicitly as `prompt` (prefer multimodal parts). Mirrors the + // native bot's onMention otherwise. + bot.onMention(async ({ thread, message }) => { + try { + await thread.runAgent({ + prompt: promptFromMessage(message), + context: senderContext(message.user, thread.platform), + }); + } catch (err) { + console.error("[channel] agent run failed", err); + await thread + .post("Sorry — I hit an error handling that. Please try again.") + .catch((postErr: unknown) => + console.error("[channel] failed to post agent error", postErr), + ); + } + }); + + bot.onModalSubmit(FILE_ISSUE_CALLBACK, fileIssueSubmit); + + bot.onThreadStarted(async ({ thread, user }) => { + if (!user?.name) return; + try { + await thread.setSuggestedPrompts([ + { + title: `Triage ${user.name}'s issues`, + message: "Triage my open issues", + }, + { + title: "What shipped this week?", + message: "Summarize what shipped this week", + }, + ]); + } catch (err) { + console.error("[channel] onThreadStarted failed", err); + } + }); + + return bot; +} + +async function main() { + const channelName = process.env.INTELLIGENCE_CHANNEL_NAME ?? "kitebot"; + + const bot = createKiteBot({ + agentUrl: required("AGENT_URL"), + agentAuthHeader: process.env.AGENT_AUTH_HEADER, + channelName, + }); + + let projectId: number; + try { + projectId = parseProjectId(process.env.INTELLIGENCE_PROJECT_ID); + } catch (e) { + const msg = e instanceof Error ? e.message : String(e); + console.error(msg); + process.exit(1); + } + + const handle = await startChannelsOverRealtimeGateway([bot], { + wsUrl: required("INTELLIGENCE_GATEWAY_WS_URL"), + apiKey: required("INTELLIGENCE_API_KEY"), + scope: { + organizationId: required("INTELLIGENCE_ORG_ID"), + projectId, + channelId: required("INTELLIGENCE_CHANNEL_ID"), + channelName, + }, + runtimeInstanceId: + process.env.INTELLIGENCE_RUNTIME_INSTANCE_ID ?? + `rti_${randomUUID().replace(/-/g, "")}`, + adapter: "slack", + // DEBUG-ONLY: meta can contain message content — drop or trim in production. + log: (msg, meta) => console.log(`[channel] ${msg}`, meta ?? ""), + }); + console.log( + `[channel] KiteBot channel "${channelName}" started over Realtime Gateway on project ${projectId}`, + ); + + const shutdown = async (signal: string) => { + console.log(`\n[channel] received ${signal}, stopping…`); + let exitCode = 0; + try { + await handle.stop(); + } catch (err) { + console.error("[channel] error stopping channel runtime", err); + exitCode = 1; + } + await closeBrowser().catch((err: unknown) => + console.error( + "[channel] browser cleanup failed (continuing shutdown)", + err, + ), + ); + process.exit(exitCode); + }; + const runShutdown = (signal: string): void => { + shutdown(signal).catch((err: unknown) => { + console.error(`[channel] fatal during ${signal} shutdown`, err); + process.exit(1); + }); + }; + process.on("SIGINT", () => runShutdown("SIGINT")); + process.on("SIGTERM", () => runShutdown("SIGTERM")); +} + +process.on("unhandledRejection", (reason) => { + console.error("[channel] unhandledRejection:", reason); +}); +process.on("uncaughtException", (err) => { + console.error("[channel] uncaughtException:", err); +}); + +// Only start the gateway connection when executed directly (`pnpm channel`), +// not when the test imports `createKiteBot`. +if (process.argv[1] && process.argv[1].endsWith("managed.ts")) { + main().catch((err: unknown) => { + console.error("[channel] fatal: failed to start channel runtime", err); + process.exit(1); + }); +} diff --git a/app/modals/__tests__/file-issue.test.tsx b/app/modals/__tests__/file-issue.test.tsx index 7b91d96..066073a 100644 --- a/app/modals/__tests__/file-issue.test.tsx +++ b/app/modals/__tests__/file-issue.test.tsx @@ -1,12 +1,13 @@ import { describe, it, expect, vi } from "vitest"; -import { renderToIR } from "@copilotkit/bot-ui"; +import { renderToIR } from "@copilotkit/channels-ui"; import { FileIssueModal, fileIssueSubmit, issueFromValues, FILE_ISSUE_CALLBACK, } from "../file-issue.js"; -import type { BotNode } from "@copilotkit/bot-ui"; +import type { BotNode } from "@copilotkit/channels-ui"; +import { senderContext } from "../../sender-context.js"; function tags(node: BotNode | unknown, acc: string[] = []): string[] { if (!node || typeof node !== "object") return acc; @@ -114,6 +115,33 @@ describe("fileIssueSubmit", () => { ).resolves.toBeUndefined(); }); + it("runs the agent with the interpolated prompt and sender context on a valid submit", async () => { + const runAgent = vi.fn( + (_input?: { prompt: string; context: unknown }) => + new Promise(() => {}), + ); + const thread = { runAgent, platform: "slack" }; + const user = { id: "U1", name: "Ada Lovelace", email: "ada@example.com" }; + await fileIssueSubmit({ + values: { + title: "Login broken", + description: "500 on submit", + type: "bug", + priority: "High", + }, + thread, + user, + } as never); + + expect(runAgent).toHaveBeenCalledTimes(1); + const call = runAgent.mock.calls[0]![0]!; + expect(call.prompt).toContain("- Title: Login broken"); + expect(call.prompt).toContain("- Type: bug"); + expect(call.prompt).toContain("- Priority: High"); + expect(call.prompt).toContain("- Description: 500 on submit"); + expect(call.context).toEqual(senderContext(user, thread.platform)); + }); + it("posts a failure message to the thread when runAgent rejects", async () => { const post = vi.fn().mockResolvedValue({ id: "m1" }); const thread = { diff --git a/app/modals/file-issue.tsx b/app/modals/file-issue.tsx index b464f73..cebf48a 100644 --- a/app/modals/file-issue.tsx +++ b/app/modals/file-issue.tsx @@ -15,9 +15,9 @@ import { ModalSelect, ModalSelectOption, RadioButtons, -} from "@copilotkit/bot-ui"; -import type { ModalView } from "@copilotkit/bot-ui"; -import type { ModalSubmitHandler } from "@copilotkit/bot"; +} from "@copilotkit/channels-ui"; +import type { ModalView } from "@copilotkit/channels-ui"; +import type { ModalSubmitHandler } from "@copilotkit/channels"; import { senderContext } from "../sender-context.js"; export const FILE_ISSUE_CALLBACK = "file_issue"; @@ -75,7 +75,9 @@ export const fileIssueSubmit: ModalSubmitHandler = async ({ console.error("[bot] file-issue modal run failed", err); void thread .post("Sorry — I couldn't file that issue. Please try again.") - .catch(() => {}); + .catch((postErr: unknown) => + console.error("[file-issue] failed to post error", postErr), + ); }); }; @@ -118,5 +120,8 @@ export function FileIssueModal({ rich }: { rich: boolean }): ModalView { ) : null} + // JSX expressions type as `JSX.Element` (= `BotNode`, not `ModalView`) per + // the channels-ui jsx-runtime, so the narrower literal `type: "modal"` needs + // an explicit assertion even though `Modal` itself returns `ModalView`. ) as ModalView; } diff --git a/app/sender-context.ts b/app/sender-context.ts index 3262a30..87e3d88 100644 --- a/app/sender-context.ts +++ b/app/sender-context.ts @@ -1,5 +1,5 @@ -import type { ContextEntry } from "@copilotkit/bot"; -import type { PlatformUser } from "@copilotkit/bot-ui"; +import type { ContextEntry } from "@copilotkit/channels"; +import type { PlatformUser } from "@copilotkit/channels-ui"; /** * Build the per-turn context naming the requesting user, so the agent can act diff --git a/app/tools/__tests__/read-thread.test.ts b/app/tools/__tests__/read-thread.test.ts index 77f4195..60198d2 100644 --- a/app/tools/__tests__/read-thread.test.ts +++ b/app/tools/__tests__/read-thread.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, vi } from "vitest"; import { readThreadTool } from "../read-thread.js"; -import type { ThreadMessage } from "@copilotkit/bot-ui"; +import type { ThreadMessage } from "@copilotkit/channels-ui"; /** The ctx a BotTool handler receives. */ type HandlerCtx = Parameters[1]; @@ -75,6 +75,22 @@ describe("read_thread tool", () => { expect(out.messages[0]?.user).toBe("unknown"); }); + it("falls back to the handle when the user has no name", async () => { + const ctx = makeCtx([ + { + user: { id: "UBOB", handle: "bob" }, + text: "on it", + ts: "1700000000.000400", + }, + ]); + + const out = (await readThreadTool.handler({}, ctx)) as { + messages: Array<{ user: string }>; + }; + + expect(out.messages[0]?.user).toBe("bob"); + }); + it("calls thread.getMessages once", async () => { const ctx = makeCtx([]); await readThreadTool.handler({}, ctx); diff --git a/app/tools/__tests__/render-table.test.tsx b/app/tools/__tests__/render-table.test.tsx index e377137..074dfe2 100644 --- a/app/tools/__tests__/render-table.test.tsx +++ b/app/tools/__tests__/render-table.test.tsx @@ -5,8 +5,8 @@ * `renderToIR` → `renderSlackMessage` yields the expected Block Kit shape. */ import { describe, it, expect } from "vitest"; -import { renderToIR } from "@copilotkit/bot-ui"; -import { renderSlackMessage } from "@copilotkit/bot-slack"; +import { renderToIR } from "@copilotkit/channels-ui"; +import { renderSlackMessage } from "@copilotkit/channels-slack"; import { renderTableTool, toMonospaceTable, clamp } from "../render-table.js"; type HandlerCtx = Parameters[1]; @@ -46,10 +46,20 @@ describe("toMonospaceTable", () => { const out = toMonospaceTable(COLS, ROWS); expect(out.startsWith("```\n")).toBe(true); expect(out.endsWith("\n```")).toBe(true); - // "Priority" (8) is the widest in column 2, so "High" is padded to width 8. - expect(out).toContain("| CPK-1 | High |"); + // "Priority" (8) is the widest in column 2 and is align: "right", so + // "High" (4) is left-padded (padStart) to width 8, not right-padded. + expect(out).toContain("| CPK-1 | High |"); expect(out).toContain("| Issue | Priority |"); }); + + it("right-aligns cells (padStart) in columns with align: 'right'", () => { + // Column 2 ("Priority", align: right) is 8 chars wide; "Low" (3) should be + // left-padded with 5 spaces, not right-padded (padEnd) like a left-aligned cell. + const out = toMonospaceTable(COLS, ROWS); + expect(out).toContain("| CPK-2 | Low |"); + // Column 1 ("Issue", no align — defaults left) still pads on the right. + expect(out).toContain("| CPK-1 |"); + }); }); describe("render_table tool", () => { @@ -118,13 +128,17 @@ describe("render_table tool", () => { { columns: COLS, rows: manyRows }, ctx, )) as string; - expect(out).toBe("Rendered the table for the user."); + // The drop is reported back to the agent... + expect(out).toContain("only the first 99 of 150 rows shown"); const { blocks } = renderSlackMessage(renderToIR(posts[0] as never)); const table = blocks.find((b) => b.type === "table") as | TableBlock | undefined; // 99 data rows + 1 header row. expect(table?.rows).toHaveLength(100); + // ...and also posted into the thread so the user sees it, not just the agent. + const text = JSON.stringify(blocks); + expect(text).toContain("only the first 99 of 150 rows shown"); }); it("clamps to 20 columns and reports the drop", async () => { @@ -137,12 +151,14 @@ describe("render_table tool", () => { { columns: manyCols, rows: [wideRow] }, ctx, )) as string; - expect(out).toBe("Rendered the table for the user."); + expect(out).toContain("only the first 20 of 25 columns shown"); const { blocks } = renderSlackMessage(renderToIR(posts[0] as never)); const table = blocks.find((b) => b.type === "table") as | TableBlock | undefined; expect(table?.rows?.[0]).toHaveLength(20); + const text = JSON.stringify(blocks); + expect(text).toContain("only the first 20 of 25 columns shown"); }); }); diff --git a/app/tools/__tests__/render-tools.test.ts b/app/tools/__tests__/render-tools.test.ts index eacfe83..6797327 100644 --- a/app/tools/__tests__/render-tools.test.ts +++ b/app/tools/__tests__/render-tools.test.ts @@ -1,10 +1,23 @@ +/** + * Covers the `render_chart` and `render_diagram` tools (render-chart.tsx / + * render-diagram.tsx) — the agent-facing tools that render a Chart.js config + * or Mermaid source to a PNG and post it via `thread.postFile`, plus a small + * JSX caption card posted first via `thread.post`. The `issue_card` / + * `issue_list` / `page_list` render-tool wrappers are covered separately in + * render-tools.test.tsx. + */ import { describe, it, expect, vi, beforeEach } from "vitest"; -import { renderToIR } from "@copilotkit/bot-ui"; -import { renderSlackMessage } from "@copilotkit/bot-slack"; +import { renderToIR } from "@copilotkit/channels-ui"; +import { renderSlackMessage } from "@copilotkit/channels-slack"; + +// The exact PNG buffer instance `renderChart` resolves with, so tests can +// assert `postFile` was handed the real render output — not just a filename. +const CHART_PNG = Buffer.from("CHARTPNG"); +const DIAGRAM_PNG = Buffer.from("DIAGRAMPNG"); // Mock the local renderers so no headless browser is launched. -const renderChart = vi.fn(async () => Buffer.from("CHARTPNG")); -const renderDiagram = vi.fn(async () => Buffer.from("DIAGRAMPNG")); +const renderChart = vi.fn(async () => CHART_PNG); +const renderDiagram = vi.fn(async () => DIAGRAM_PNG); vi.mock("../../render/chart.js", () => ({ renderChart })); vi.mock("../../render/diagram.js", () => ({ renderDiagram })); @@ -14,8 +27,11 @@ const { renderDiagramTool } = await import("../render-diagram.js"); /** The ctx a BotTool handler receives. */ type HandlerCtx = Parameters[1]; -function makeCtx() { - const postFile = vi.fn(async () => ({ ok: true, fileId: "F1" })); +function makeCtx(opts?: { + postFileResult?: { ok: boolean; fileId?: string; error?: string }; +}) { + const postFileResult = opts?.postFileResult ?? { ok: true, fileId: "F1" }; + const postFile = vi.fn(async () => postFileResult); const posts: unknown[] = []; const thread = { post: vi.fn(async (ui: unknown) => { @@ -51,12 +67,13 @@ describe("render_chart tool", () => { ); expect(postFile).toHaveBeenCalledWith( expect.objectContaining({ + bytes: CHART_PNG, filename: "revenue-q2.png", title: "Revenue Q2", }), ); expect(out).toBe("Rendered and posted the chart image to the thread."); - // The caption card was posted after the upload. + // The caption card was posted before the upload. expect(posts).toHaveLength(1); const { blocks } = renderSlackMessage(renderToIR(posts[0] as never)); expect(JSON.stringify(blocks)).toContain("📊"); @@ -81,6 +98,57 @@ describe("render_chart tool", () => { expect(out).toContain("Chart.js render failed"); expect(postFile).not.toHaveBeenCalled(); }); + + it("accepts a stringified chartSpec and parses it before rendering", async () => { + const { ctx, postFile } = makeCtx(); + const out = (await renderChartTool.handler( + { + title: "Stringified", + chartSpec: JSON.stringify({ + type: "line", + data: { labels: ["a", "b"], datasets: [{ data: [1, 2] }] }, + }) as never, + }, + ctx, + )) as string; + expect(renderChart).toHaveBeenCalledWith( + expect.objectContaining({ type: "line" }), + ); + expect(postFile).toHaveBeenCalledWith( + expect.objectContaining({ bytes: CHART_PNG }), + ); + expect(out).toBe("Rendered and posted the chart image to the thread."); + }); + + it("returns an error (does not throw or render) when the stringified chartSpec is unparseable", async () => { + const { ctx, postFile } = makeCtx(); + const out = (await renderChartTool.handler( + { title: "Broken", chartSpec: "{not json" as never }, + ctx, + )) as string; + expect(out).toContain("Chart render failed"); + expect(out).toContain("unparseable string"); + expect(renderChart).not.toHaveBeenCalled(); + expect(postFile).not.toHaveBeenCalled(); + }); + + it("tells the agent when postFile rejects the upload (res.ok === false)", async () => { + const { ctx } = makeCtx({ + postFileResult: { ok: false, error: "file too large" }, + }); + const out = (await renderChartTool.handler( + { + title: "Too Big", + chartSpec: { + type: "bar", + data: { labels: ["a"], datasets: [{ data: [1] }] }, + }, + }, + ctx, + )) as string; + expect(out).toContain("Chart render failed"); + expect(out).toContain("file too large"); + }); }); describe("render_diagram tool", () => { @@ -92,7 +160,7 @@ describe("render_diagram tool", () => { )) as string; expect(renderDiagram).toHaveBeenCalledWith("flowchart TD\n A-->B"); expect(postFile).toHaveBeenCalledWith( - expect.objectContaining({ filename: "flow.png" }), + expect.objectContaining({ bytes: DIAGRAM_PNG, filename: "flow.png" }), ); expect(out).toBe("Rendered and posted the diagram image to the thread."); expect(posts).toHaveLength(1); diff --git a/app/tools/__tests__/render-tools.test.tsx b/app/tools/__tests__/render-tools.test.tsx index 9e41608..523e158 100644 --- a/app/tools/__tests__/render-tools.test.tsx +++ b/app/tools/__tests__/render-tools.test.tsx @@ -6,8 +6,8 @@ * shape — i.e. the tool posted the right component. */ import { describe, it, expect } from "vitest"; -import { renderToIR } from "@copilotkit/bot-ui"; -import { renderSlackMessage } from "@copilotkit/bot-slack"; +import { renderToIR } from "@copilotkit/channels-ui"; +import { renderSlackMessage } from "@copilotkit/channels-slack"; import { issueCardTool, issueListTool, pageListTool } from "../render-tools.js"; /** A fake `thread` that records each posted Renderable. */ diff --git a/app/tools/__tests__/showcase-tools.test.tsx b/app/tools/__tests__/showcase-tools.test.tsx index 6622251..9a70b23 100644 --- a/app/tools/__tests__/showcase-tools.test.tsx +++ b/app/tools/__tests__/showcase-tools.test.tsx @@ -7,13 +7,13 @@ * updates the message in place with a green "Acknowledged" card. */ import { describe, it, expect, vi } from "vitest"; -import { renderToIR } from "@copilotkit/bot-ui"; +import { renderToIR } from "@copilotkit/channels-ui"; import type { BotNode, InteractionContext, ClickHandler, -} from "@copilotkit/bot-ui"; -import { renderSlackMessage } from "@copilotkit/bot-slack"; +} from "@copilotkit/channels-ui"; +import { renderSlackMessage } from "@copilotkit/channels-slack"; import { showIncidentTool, showStatusTool, @@ -47,18 +47,29 @@ function findWithProp( type: string, prop: string, ): BotNode | undefined { + return findAllWithProp(nodes, type, prop)[0]; +} + +/** Depth-first: find every IR node whose `type` matches and that has the named prop. */ +function findAllWithProp( + nodes: BotNode[], + type: string, + prop: string, +): BotNode[] { + const matches: BotNode[] = []; for (const node of nodes) { - if (node.type === type && node.props && prop in node.props) return node; + if (node.type === type && node.props && prop in node.props) { + matches.push(node); + } const children = node.props?.children; const childArr = Array.isArray(children) ? (children as BotNode[]) : children && typeof children === "object" ? [children as BotNode] : []; - const found = findWithProp(childArr, type, prop); - if (found) return found; + matches.push(...findAllWithProp(childArr, type, prop)); } - return undefined; + return matches; } describe("show_incident render-tool", () => { @@ -130,6 +141,80 @@ describe("show_incident render-tool", () => { expect(JSON.stringify(blocks)).toContain("✅ Acknowledged · Checkout 500s"); expect(JSON.stringify(blocks)).toContain("Ack'd by Alem"); }); + + it("the Escalate button's onClick posts a paging notice", async () => { + const { posts, thread } = fakeThread(); + await showIncidentTool.handler( + { + id: "INC-1", + title: "Checkout 500s", + severity: "SEV1", + summary: "Error rate spiking on /checkout.", + }, + { thread } as unknown as IncidentCtx, + ); + + const ir = renderToIR(posts[0] as never); + // The card has two buttons (Acknowledge, Escalate) — find the Escalate one + // by its `value.action`. + const buttons = findAllWithProp(ir, "button", "onClick"); + const escalateButton = buttons.find( + (b) => (b.props?.value as { action?: string })?.action === "escalate", + ); + expect(escalateButton).toBeDefined(); + + const onClick = escalateButton?.props.onClick as ClickHandler; + + await onClick({ + thread, + message: { + ref: { id: "m1" }, + text: "", + user: { id: "U1" }, + platform: "slack", + }, + user: { id: "U1", name: "Alem" }, + action: { id: "a1" }, + values: {}, + platform: "slack", + } as unknown as InteractionContext); + + expect(thread.post).toHaveBeenCalledWith( + "🚨 Escalating *Checkout 500s* — paging the next on-call.", + ); + }); + + it("uses the SEV2 accent (#F2994A)", async () => { + const { posts, thread } = fakeThread(); + await showIncidentTool.handler( + { + id: "INC-2", + title: "Latency spike", + severity: "SEV2", + summary: "p99 latency elevated.", + }, + { thread } as unknown as IncidentCtx, + ); + + const { accent } = renderSlackMessage(renderToIR(posts[0] as never)); + expect(accent).toBe("#F2994A"); // SEV2 + }); + + it("uses the SEV3 accent (#5E6AD2)", async () => { + const { posts, thread } = fakeThread(); + await showIncidentTool.handler( + { + id: "INC-3", + title: "Minor blip", + severity: "SEV3", + summary: "Transient error rate uptick.", + }, + { thread } as unknown as IncidentCtx, + ); + + const { accent } = renderSlackMessage(renderToIR(posts[0] as never)); + expect(accent).toBe("#5E6AD2"); // SEV3 + }); }); describe("show_status render-tool", () => { diff --git a/app/tools/index.ts b/app/tools/index.ts index 257a85a..4e4371f 100644 --- a/app/tools/index.ts +++ b/app/tools/index.ts @@ -19,7 +19,7 @@ import { showLinksTool, } from "./showcase-tools.js"; import { confirmWriteTool } from "../human-in-the-loop/index.js"; -import type { BotTool } from "@copilotkit/bot"; +import type { BotTool } from "@copilotkit/channels"; /** * Every tool is a plain `BotTool`: its handler receives the generic diff --git a/app/tools/read-thread.ts b/app/tools/read-thread.ts index 1ba0e84..7249acf 100644 --- a/app/tools/read-thread.ts +++ b/app/tools/read-thread.ts @@ -11,7 +11,7 @@ * needed. */ import { z } from "zod"; -import { defineBotTool } from "@copilotkit/bot"; +import { defineBotTool } from "@copilotkit/channels"; export const readThreadTool = defineBotTool({ name: "read_thread", diff --git a/app/tools/render-chart.tsx b/app/tools/render-chart.tsx index bb07ee8..ec45c2a 100644 --- a/app/tools/render-chart.tsx +++ b/app/tools/render-chart.tsx @@ -7,8 +7,8 @@ * (``) so the tool doubles as a render-tool demo. */ import { z } from "zod"; -import { Context } from "@copilotkit/bot-ui"; -import { defineBotTool } from "@copilotkit/bot"; +import { Context } from "@copilotkit/channels-ui"; +import { defineBotTool } from "@copilotkit/channels"; import { renderChart } from "../render/chart.js"; const schema = z.object({ diff --git a/app/tools/render-diagram.tsx b/app/tools/render-diagram.tsx index c6a6816..cbbc01d 100644 --- a/app/tools/render-diagram.tsx +++ b/app/tools/render-diagram.tsx @@ -7,8 +7,8 @@ * render-tool demo. */ import { z } from "zod"; -import { Context } from "@copilotkit/bot-ui"; -import { defineBotTool } from "@copilotkit/bot"; +import { Context } from "@copilotkit/channels-ui"; +import { defineBotTool } from "@copilotkit/channels"; import { renderDiagram } from "../render/diagram.js"; const schema = z.object({ diff --git a/app/tools/render-table.tsx b/app/tools/render-table.tsx index e7b378d..5e93965 100644 --- a/app/tools/render-table.tsx +++ b/app/tools/render-table.tsx @@ -4,15 +4,23 @@ * issues with several fields, metrics parsed from an uploaded CSV, side-by-side * comparisons — anything where a chart isn't the right shape. * - * Authored as JSX over `@copilotkit/bot-ui`'s `//` vocabulary + * Authored as JSX over `@copilotkit/channels-ui`'s `
//` vocabulary * and posted via `thread.post`. If the platform rejects the native Table block, * we fall back to a column-aligned monospace (code-fenced) table posted as a * platform-neutral `` so the data always lands — the same look the * bridge gives GFM tables in prose. */ import { z } from "zod"; -import { Message, Header, Section, Table, Row, Cell } from "@copilotkit/bot-ui"; -import { defineBotTool } from "@copilotkit/bot"; +import { + Message, + Header, + Section, + Table, + Row, + Cell, + Context, +} from "@copilotkit/channels-ui"; +import { defineBotTool } from "@copilotkit/channels"; const schema = z.object({ title: z @@ -39,7 +47,7 @@ const schema = z.object({ .array(z.array(z.coerce.string())) .describe( "Data rows; each row is an array of cell values in column order " + - "(numbers are fine — they're rendered as text). Max 100 rows.", + "(numbers are fine — they're rendered as text). Max 99 rows.", ), }); @@ -83,7 +91,13 @@ export function toMonospaceTable(cols: Column[], dataRows: string[][]): string { ); const fmt = (row: string[]) => "| " + - cols.map((_, c) => (row[c] ?? "").padEnd(widths[c] ?? 0)).join(" | ") + + cols + .map((col, c) => { + const cell = row[c] ?? ""; + const width = widths[c] ?? 0; + return col.align === "right" ? cell.padStart(width) : cell.padEnd(width); + }) + .join(" | ") + " |"; return "```\n" + [fmt(header), ...body.map(fmt)].join("\n") + "\n```"; } @@ -95,10 +109,15 @@ export const renderTableTool = defineBotTool({ "columns (each with a header and optional alignment) and rows (arrays of " + "cell values in column order). Use for 'show as a table' — issue lists " + "with several fields, metrics from a CSV, comparisons — when a chart " + - "isn't the right shape. Max 20 columns and 100 rows.", + "isn't the right shape. Max 20 columns and 99 rows.", parameters: schema, async handler({ title, columns, rows }, { thread }) { - const { cols, dataRows } = clamp(columns, rows); + const { cols, dataRows, notes } = clamp(columns, rows); + // When rows/columns were truncated, surface it both to the user (a + // trailing note under the table) and to the agent (appended to + // the returned status string), so a silent drop never happens. + const noteBlock = notes.length > 0 ? {notes.join("; ")} : null; + const noteSuffix = notes.length > 0 ? ` (${notes.join("; ")})` : ""; const table = ( @@ -112,25 +131,31 @@ export const renderTableTool = defineBotTool({ ))}
+ {noteBlock}
); try { await thread.post(table); - return "Rendered the table for the user."; - } catch { + return `Rendered the table for the user.${noteSuffix}`; + } catch (err) { // Native Table block not accepted (platform unsupported) — post the same // data as a monospace code-fenced table via a platform-neutral // so it still lands on any adapter. + console.error( + "[render-table] native table post failed, falling back to monospace", + err, + ); const mono = toMonospaceTable(cols, dataRows); const fallback = ( {title ?
{title}
: null}
{mono}
+ {noteBlock}
); await thread.post(fallback); - return "Rendered the table (monospace fallback) for the user."; + return `Rendered the table (monospace fallback) for the user.${noteSuffix}`; } }, }); diff --git a/app/tools/render-tools.tsx b/app/tools/render-tools.tsx index 83da148..c821a35 100644 --- a/app/tools/render-tools.tsx +++ b/app/tools/render-tools.tsx @@ -1,11 +1,11 @@ /** * Render-tools — the agent-facing wrappers that turn the JSX render * components into `BotTool`s. The agent calls `issue_card` / `issue_list` / - * `page_list`; each handler renders the finished `@copilotkit/bot-ui` + * `page_list`; each handler renders the finished `@copilotkit/channels-ui` * component (`` etc.) and posts it to the thread via * `thread.post`. */ -import { defineBotTool } from "@copilotkit/bot"; +import { defineBotTool } from "@copilotkit/channels"; import { IssueCard, IssueList, diff --git a/app/tools/showcase-tools.tsx b/app/tools/showcase-tools.tsx index f383137..4e0b537 100644 --- a/app/tools/showcase-tools.tsx +++ b/app/tools/showcase-tools.tsx @@ -1,6 +1,6 @@ /** * Showcase render-tools — three small JSX `BotTool`s that demonstrate the - * `@copilotkit/bot-ui` vocabulary end-to-end: + * `@copilotkit/channels-ui` vocabulary end-to-end: * * - `show_incident` — an interactive card whose `Acknowledge`/`Escalate` * buttons carry inline `onClick` handlers. These are FIRE-AND-FORGET @@ -20,9 +20,9 @@ import { Field, Actions, Button, -} from "@copilotkit/bot-ui"; -import type { InteractionContext } from "@copilotkit/bot-ui"; -import { defineBotTool } from "@copilotkit/bot"; +} from "@copilotkit/channels-ui"; +import type { InteractionContext } from "@copilotkit/channels-ui"; +import { defineBotTool } from "@copilotkit/channels"; // ── show_incident ────────────────────────────────────────────────────────── @@ -54,13 +54,17 @@ export function IncidentCard({ id, title, severity, summary }: IncidentProps) { value={{ action: "ack", id }} style="primary" onClick={async ({ thread, user, message }: InteractionContext) => { - await thread.update( - message.ref, - -
{`✅ Acknowledged · ${title}`}
- {`Ack'd by ${user?.name ?? user?.id ?? "someone"}`} -
, - ); + try { + await thread.update( + message.ref, + +
{`✅ Acknowledged · ${title}`}
+ {`Ack'd by ${user?.name ?? user?.id ?? "someone"}`} +
, + ); + } catch (err) { + console.error("[showcase] onClick failed", err); + } }} > Acknowledge @@ -69,9 +73,13 @@ export function IncidentCard({ id, title, severity, summary }: IncidentProps) { value={{ action: "escalate", id }} style="danger" onClick={async ({ thread }: InteractionContext) => { - await thread.post( - `🚨 Escalating *${title}* — paging the next on-call.`, - ); + try { + await thread.post( + `🚨 Escalating *${title}* — paging the next on-call.`, + ); + } catch (err) { + console.error("[showcase] onClick failed", err); + } }} > Escalate diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index b3444c1..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,9 +0,0 @@ -# UNCOMMITTED demo helper — local Redis for the durable-action restart test. -# docker compose up -d # start Redis on localhost:6379 -# docker compose down # stop it -services: - redis: - image: redis:7-alpine - container_name: slack-demo-redis - ports: - - "6379:6379" diff --git a/docs/superpowers/plans/2026-07-15-kitebot-intelligence-foundation.md b/docs/superpowers/plans/2026-07-15-kitebot-intelligence-foundation.md new file mode 100644 index 0000000..12b9d82 --- /dev/null +++ b/docs/superpowers/plans/2026-07-15-kitebot-intelligence-foundation.md @@ -0,0 +1,597 @@ +# KiteBot on CopilotKit Intelligence — Phase 1 Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Migrate OpenTag off the deprecated `@copilotkit/bot*` packages onto `@copilotkit/channels*`, drop Redis, rename the bot to KiteBot, and add a unified v2 `CopilotRuntime` Intelligence channel host that connects the provisioned `kitebot` channel. + +**Architecture:** Two env-driven processes. `runtime.ts` stays the AG-UI agent backend (`CopilotSseRuntime` + `BuiltInAgent` "triage", `:8200`). A new `app/managed.ts` is the channel host: a `CopilotRuntime` in *intelligence* mode that declares one `createChannel({ name: "kitebot" })` whose agent is an `HttpAgent` pointed at `AGENT_URL`. Channel activation happens when `createCopilotNodeListener` builds its handler; `listener.channels.ready()` awaits it. The existing `app/index.ts` self-hosted Slack path is retained. + +**Tech Stack:** TypeScript (ESM, NodeNext), `@copilotkit/runtime@^1.62.3` (`/v2`, `/v2/node`), `@copilotkit/channels*@^0.1.x`, `@copilotkit/channels-intelligence`, `@ag-ui/client`, `tsx`, `vitest`. + +**Spec:** `docs/superpowers/specs/2026-07-15-kitebot-intelligence-foundation-design.md` + +--- + +## File map + +| File | Change | Responsibility | +| --- | --- | --- | +| `package.json` | modify | deps: `bot*`→`channels*`, drop redis-store, add channels-intelligence; scripts: add `channel`, drop `demo:restart`; description | +| `tsconfig.json`, `vitest.config.ts` | modify | `jsxImportSource` → `@copilotkit/channels-ui` | +| `app/demo-restart.tsx` | delete | Redis demo (dropped) | +| `docker-compose.yml` | delete | Redis-only helper (dropped) | +| `app/**/*.ts(x)`, `runtime.ts` | modify | import specifier `@copilotkit/bot`→`@copilotkit/channels` | +| `slack-app-manifest.yaml`, `slack-app-manifest.json` | modify | display name → KiteBot | +| `runtime.ts`, `app/context/app-context.ts`, `app/index.ts` | modify | persona → KiteBot | +| `app/managed.ts` | create | Intelligence channel host (unified `CopilotRuntime`) | +| `app/managed.test.ts` | create | unit test for the channel wiring | +| `.env.example` | modify | add `INTELLIGENCE_*`, remove Redis block | +| `README.md`, `setup.md` | modify | bot→channels, lead with Intelligence, drop Redis, KiteBot mentions | + +--- + +## Task 1: Dependency & build-config migration + +**Files:** +- Modify: `package.json` +- Modify: `tsconfig.json:17` +- Modify: `vitest.config.ts:6` + +- [ ] **Step 1: Rewrite the dependency block in `package.json`** + +Replace the `dependencies` block's CopilotKit entries and the `description`. The full `dependencies` object becomes: + +```json + "dependencies": { + "@copilotkit/channels": "^0.1.1", + "@copilotkit/channels-discord": "^0.1.1", + "@copilotkit/channels-intelligence": "^0.1.1", + "@copilotkit/channels-slack": "^0.1.2", + "@copilotkit/channels-telegram": "^0.1.1", + "@copilotkit/channels-ui": "^0.1.1", + "@copilotkit/channels-whatsapp": "^0.1.1", + "@copilotkit/runtime": "^1.62.3", + "@tanstack/ai": "^0.32.0", + "@tanstack/ai-mcp": "^0.1.3", + "@tanstack/ai-openai": "^0.15.2", + "@slack/bolt": "^4.2.0", + "@slack/types": "^2.21.1", + "playwright": "^1.49.0", + "zod": "^3.25.76" + }, +``` + +And update `description` (line 5) to: + +```json + "description": "OpenTag — an open-source, self-hosted alternative to Claude in Slack: run your own AI agent on your infrastructure, with your model and your tools. Built on @copilotkit/channels; also runs on Discord, Telegram & WhatsApp.", +``` + +- [ ] **Step 2: Update the `scripts` block in `package.json`** + +Add a `channel` script and remove `demo:restart`. The `scripts` block becomes: + +```json + "scripts": { + "dev": "tsx watch app/index.ts", + "start": "tsx app/index.ts", + "channel": "tsx app/managed.ts", + "runtime": "tsx runtime.ts", + "notion-mcp": "tsx scripts/start-notion-mcp.ts", + "check-types": "tsc --noEmit -p tsconfig.json", + "test": "vitest run", + "e2e": "tsx e2e/run.ts", + "e2e:restart": "tsx e2e/restart-recovery.ts", + "e2e:telegram": "tsx e2e/telegram-run.ts" + }, +``` + +- [ ] **Step 3: Update `jsxImportSource` in both config files** + +In `tsconfig.json:17` change `"jsxImportSource": "@copilotkit/bot-ui"` → `"jsxImportSource": "@copilotkit/channels-ui"`. + +In `vitest.config.ts:6` change `jsxImportSource: "@copilotkit/bot-ui",` → `jsxImportSource: "@copilotkit/channels-ui",`. + +- [ ] **Step 4: Install and verify resolution** + +Run: `pnpm install` +Expected: completes without "No matching version" / unresolved-package errors for any `@copilotkit/channels*` package. + +- [ ] **Step 5: Commit** + +```bash +git add package.json tsconfig.json vitest.config.ts pnpm-lock.yaml +git commit -m "build: migrate deps @copilotkit/bot* -> @copilotkit/channels* + add channels-intelligence" +``` + +--- + +## Task 2: Drop Redis + +**Files:** +- Delete: `app/demo-restart.tsx` +- Delete: `docker-compose.yml` +- Modify: `.env.example:28-34` (Redis block) + +Do this BEFORE the rename (Task 3) so the blind `bot`→`channels` replacement never touches the `@copilotkit/bot-store-redis` import (which has no `channels-*` equivalent). + +- [ ] **Step 1: Delete the Redis demo files** + +```bash +git rm app/demo-restart.tsx docker-compose.yml +``` + +- [ ] **Step 2: Remove the Redis block from `.env.example`** + +Delete these lines (currently `.env.example:28-34`): + +``` +# ── Persistence (optional) ────────────────────────────────────────────── +# Optional Redis-backed durable store. Used by `pnpm demo:restart` (and any +# bot that passes `store: { adapter: createRedisStore({ url }) }`). Leave blank +# for the in-memory default. With it set, interactive actions (e.g. an approval +# card's button) survive a bot restart — see `app/demo-restart.tsx`. +# Start a local one with `docker compose up -d`. +# REDIS_URL=redis://localhost:6379 +``` + +- [ ] **Step 3: Verify no Redis references remain** + +Run: `grep -rn "REDIS_URL\|bot-store-redis\|demo-restart\|createRedisStore\|docker compose\|docker-compose" . --include='*.ts' --include='*.tsx' --include='*.json' --include='*.md' | grep -v node_modules` +Expected: no matches in `package.json`, `.env.example`, or `app/`. (Matches may remain in `README.md`/`setup.md` — those are cleaned in Task 6. `e2e/restart-recovery.ts` is fine; it does not reference Redis.) + +- [ ] **Step 4: Commit** + +```bash +git add -A +git commit -m "chore: drop Redis persistence (demo-restart, docker-compose, env block)" +``` + +--- + +## Task 3: Mechanical rename `@copilotkit/bot*` → `@copilotkit/channels*` + +**Files:** +- Modify: every `.ts`/`.tsx` under `app/` plus `runtime.ts` + +The single substring replacement `@copilotkit/bot` → `@copilotkit/channels` is correct for all variants: `@copilotkit/bot-ui`→`@copilotkit/channels-ui`, `@copilotkit/bot-slack`→`@copilotkit/channels-slack`, and bare `@copilotkit/bot`→`@copilotkit/channels`. API identifiers (`createBot`, `defineBotTool`, `BotNode`, `BotTool`, `slack`, …) are unchanged and MUST NOT be touched. + +- [ ] **Step 1: Apply the replacement across source** + +```bash +grep -rl '@copilotkit/bot' app runtime.ts --include='*.ts' --include='*.tsx' \ + | xargs sed -i '' 's|@copilotkit/bot|@copilotkit/channels|g' +``` + +- [ ] **Step 2: Verify zero `@copilotkit/bot` specifiers remain in source** + +Run: `grep -rn '@copilotkit/bot' app runtime.ts --include='*.ts' --include='*.tsx'` +Expected: no matches. + +- [ ] **Step 3: Typecheck** + +Run: `pnpm check-types` +Expected: PASS (exit 0), no "Cannot find module '@copilotkit/channels...'" errors. + +- [ ] **Step 4: Run the existing test suite** + +Run: `pnpm test` +Expected: PASS — all existing `app/**/*.test.ts(x)` tests green (they import `renderToIR`, `renderSlackMessage`, etc. from the renamed packages). + +- [ ] **Step 5: Commit** + +```bash +git add app runtime.ts +git commit -m "refactor: rename imports @copilotkit/bot* -> @copilotkit/channels* (no logic change)" +``` + +--- + +## Task 4: Rename the bot → KiteBot (identity only) + +**Files:** +- Modify: `slack-app-manifest.yaml:2,7` +- Modify: `slack-app-manifest.json:3,14` +- Modify: `runtime.ts:139` (system prompt opening) +- Modify: `app/context/app-context.ts:16-21` (identity entry) +- Modify: `app/index.ts:87-89` (comments) + +- [ ] **Step 1: Rename the Slack app display name (both manifests)** + +In `slack-app-manifest.yaml`, change both `name: CopilotKit Triage` (line 2) and `display_name: CopilotKit Triage` (line 7) to `KiteBot`. + +In `slack-app-manifest.json`, change `"name": "CopilotKit Triage"` (line 3) and `"display_name": "CopilotKit Triage"` (line 14) to `"KiteBot"`. + +- [ ] **Step 2: Name the persona in the agent system prompt** + +In `runtime.ts`, change the first line of `SYSTEM_PROMPT` (line 139) from: + +```ts + "You are an on-call triage assistant living in a Slack workspace. You help", +``` + +to: + +```ts + "You are KiteBot, an on-call triage assistant living in a Slack workspace. You help", +``` + +- [ ] **Step 3: Name the persona in app context** + +In `app/context/app-context.ts`, change the identity entry's first value line (line 18) from: + +```ts + "You are the team's on-call triage assistant. Be concise and action-", +``` + +to: + +```ts + "You are KiteBot, the team's on-call triage assistant. Be concise and action-", +``` + +- [ ] **Step 4: Update the "Kite" comments in `app/index.ts`** + +In `app/index.ts` (lines 87-89), replace the two occurrences of `Kite` in the comment with `KiteBot`: + +```ts + // KiteBot keeps DMs conversational and responds to explicit app mentions + // in channels/threads. Plain channel thread replies stay quiet unless + // they mention KiteBot again. +``` + +(If OpenTag's `app/index.ts` comment wording differs, apply the same `Kite`→`KiteBot` substitution to whatever comment text is present.) + +- [ ] **Step 5: Verify and typecheck** + +Run: `grep -rn "CopilotKit Triage" slack-app-manifest.yaml slack-app-manifest.json` +Expected: no matches. +Run: `pnpm check-types` +Expected: PASS. + +- [ ] **Step 6: Commit** + +```bash +git add slack-app-manifest.yaml slack-app-manifest.json runtime.ts app/context/app-context.ts app/index.ts +git commit -m "feat: rename bot identity to KiteBot (display name + persona)" +``` + +--- + +## Task 5: Intelligence channel host (`app/managed.ts`) + +**Files:** +- Create: `app/managed.ts` +- Create: `app/managed.test.ts` + +The entrypoint exports a pure `createKiteBotChannel()` factory (testable without a gateway) and a `main()` that wires it into a `CopilotRuntime` and activates it. + +- [ ] **Step 1: Write the failing test** + +Create `app/managed.test.ts`: + +```ts +import { describe, it, expect } from "vitest"; +import { createKiteBotChannel } from "./managed.js"; + +describe("createKiteBotChannel", () => { + it("declares the kitebot channel with no direct adapter (managed-eligible)", () => { + const channel = createKiteBotChannel({ agentUrl: "http://localhost:8200" }); + expect(channel.name).toBe("kitebot"); + // A managed (Intelligence) channel carries NO direct platform adapter; + // the intelligenceAdapter is attached later at activation. + expect(channel.adapters).toHaveLength(0); + }); + + it("registers the app's slash commands on the channel", () => { + const channel = createKiteBotChannel({ agentUrl: "http://localhost:8200" }); + // appCommands includes /file-issue among others; assert it surfaced. + expect(channel.commandNames).toContain("file-issue"); + }); + + it("honors a custom channel name", () => { + const channel = createKiteBotChannel({ + agentUrl: "http://localhost:8200", + channelName: "kite-bot", + }); + expect(channel.name).toBe("kite-bot"); + }); +}); +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `pnpm vitest run app/managed.test.ts` +Expected: FAIL — cannot resolve `./managed.js` / `createKiteBotChannel is not a function`. + +- [ ] **Step 3: Write `app/managed.ts`** + +Create `app/managed.ts`: + +```ts +/** + * Intelligence channel host for KiteBot — the "managed" run mode. + * + * Unlike `app/index.ts` (self-hosted: holds Slack tokens, talks to Slack + * directly), this process holds NO platform credentials. It runs a v2 + * `CopilotRuntime` in *intelligence* mode that declares ONE channel ("kitebot") + * to the CopilotKit Intelligence realtime gateway. Intelligence owns the Slack + * edge (signed ingress + Connector Outbox egress); this runtime just receives + * leased deliveries and streams render frames back. + * + * The channel's brain is an external AG-UI agent reached over HTTP at + * `AGENT_URL` — for now the `runtime.ts` triage backend; in Phase 2 a LangGraph + * deep agent. The bot's tools/context/commands/handlers are identical to the + * native bot; only the transport differs. + * + * Run: `pnpm channel` with INTELLIGENCE_* + AGENT_URL set (see `.env.example`). + */ +import "dotenv/config"; +import { createServer } from "node:http"; +import { CopilotRuntime, CopilotKitIntelligence } from "@copilotkit/runtime/v2"; +import { createCopilotNodeListener } from "@copilotkit/runtime/v2/node"; +import { createChannel } from "@copilotkit/channels"; +import type { Channel } from "@copilotkit/channels"; +import { + SanitizingHttpAgent, + defaultSlackTools, + defaultSlackContext, +} from "@copilotkit/channels-slack"; +import { appTools } from "./tools/index.js"; +import { appContext } from "./context/app-context.js"; +import { appCommands } from "./commands/index.js"; +import { senderContext } from "./sender-context.js"; +import { fileIssueSubmit, FILE_ISSUE_CALLBACK } from "./modals/file-issue.js"; +import { closeBrowser } from "./render/browser.js"; + +const required = (name: string): string => { + const v = process.env[name]; + if (!v) { + console.error(`Missing required env var: ${name}`); + process.exit(1); + } + return v; +}; + +export interface CreateKiteBotChannelOptions { + /** AG-UI agent endpoint the channel's HttpAgent posts to. */ + agentUrl: string; + /** Optional Authorization header value forwarded to the agent. */ + agentAuthHeader?: string; + /** Intelligence channel name (lowercase kebab). Defaults to "kitebot". */ + channelName?: string; +} + +/** + * Build the KiteBot channel: the same tools/context/commands/handlers as the + * native bot, minus any platform adapter (the intelligenceAdapter is attached + * at activation). Pure — no network, no env reads — so it is unit-testable. + */ +export function createKiteBotChannel( + opts: CreateKiteBotChannelOptions, +): Channel { + const channelName = opts.channelName ?? "kitebot"; + const agentHeaders = opts.agentAuthHeader + ? { Authorization: opts.agentAuthHeader } + : undefined; + + const channel = createChannel({ + name: channelName, + agent: (threadId: string) => { + const a = new SanitizingHttpAgent({ url: opts.agentUrl, headers: agentHeaders }); + a.threadId = threadId; + return a; + }, + tools: [...appTools, ...defaultSlackTools], + context: [...appContext, ...defaultSlackContext], + commands: appCommands, + }); + + // Turn handler: the managed history endpoint does NOT include the in-flight + // turn, so pass the current message explicitly as `prompt` (prefer multimodal + // parts). Mirrors the native bot's onMention otherwise. + channel.onMention(async ({ thread, message }) => { + try { + await thread.runAgent({ + prompt: message.contentParts?.length ? message.contentParts : message.text, + context: senderContext(message.user, thread.platform), + }); + } catch (err) { + console.error("[channel] agent run failed", err); + await thread + .post("Sorry — I hit an error handling that. Please try again.") + .catch((postErr: unknown) => + console.error("[channel] failed to post agent error", postErr), + ); + } + }); + + channel.onModalSubmit(FILE_ISSUE_CALLBACK, fileIssueSubmit); + + channel.onThreadStarted(async ({ thread, user }) => { + if (!user?.name) return; + await thread.setSuggestedPrompts([ + { title: `Triage ${user.name}'s issues`, message: "Triage my open issues" }, + { title: "What shipped this week?", message: "Summarize what shipped this week" }, + ]); + }); + + return channel; +} + +async function main() { + const intelligence = new CopilotKitIntelligence({ + apiUrl: required("INTELLIGENCE_API_URL"), + wsUrl: required("INTELLIGENCE_GATEWAY_WS_URL"), + apiKey: required("INTELLIGENCE_API_KEY"), + }); + + const channel = createKiteBotChannel({ + agentUrl: required("AGENT_URL"), + agentAuthHeader: process.env.AGENT_AUTH_HEADER, + channelName: process.env.INTELLIGENCE_CHANNEL_NAME, + }); + + const runtime = new CopilotRuntime({ agents: {}, intelligence, channels: [channel] }); + + const listener = createCopilotNodeListener({ runtime, basePath: "/" }); + const port = Number(process.env.PORT ?? 8300); + const server = createServer(listener); + server.listen(port, () => console.log(`[channel] runtime listening on :${port}`)); + + // Channels activate at handler creation; await readiness so a failed gateway + // connect surfaces here instead of silently leaving the channel "Waiting". + await listener.channels?.ready(); + console.log(`[channel] KiteBot channel "${channel.name}" activated on Intelligence`); + + const shutdown = async (signal: string) => { + console.log(`\n[channel] received ${signal}, stopping…`); + let exitCode = 0; + try { + await listener.channels?.stop?.(); + } catch (err) { + console.error("[channel] error stopping channels", err); + exitCode = 1; + } + server.close(); + await closeBrowser().catch((err: unknown) => + console.error("[channel] browser cleanup failed (continuing shutdown)", err), + ); + process.exit(exitCode); + }; + const runShutdown = (signal: string): void => { + shutdown(signal).catch((err: unknown) => { + console.error(`[channel] fatal during ${signal} shutdown`, err); + process.exit(1); + }); + }; + process.on("SIGINT", () => runShutdown("SIGINT")); + process.on("SIGTERM", () => runShutdown("SIGTERM")); +} + +process.on("unhandledRejection", (reason) => { + console.error("[channel] unhandledRejection:", reason); +}); +process.on("uncaughtException", (err) => { + console.error("[channel] uncaughtException:", err); +}); + +// Only run the server when executed directly (`pnpm channel`), not when the +// test imports `createKiteBotChannel`. +if (process.argv[1] && process.argv[1].endsWith("managed.ts")) { + main().catch((err: unknown) => { + console.error("[channel] fatal: failed to start channel runtime", err); + process.exit(1); + }); +} +``` + +- [ ] **Step 4: Run the test to verify it passes** + +Run: `pnpm vitest run app/managed.test.ts` +Expected: PASS (3 tests). If `channel.commandNames` does not contain `"file-issue"`, inspect `app/commands/index.ts` for the actual command name and update the assertion to a command that IS declared. + +- [ ] **Step 5: Typecheck the whole project** + +Run: `pnpm check-types` +Expected: PASS. If `createCopilotNodeListener` / `CopilotRuntime` option names differ from the installed `@copilotkit/runtime` typings, adjust to the typed signature (e.g. `basePath`, `cors`) — the shape here matches `runtime.ts`'s existing `createCopilotNodeListener({ runtime, basePath, cors })` usage. + +- [ ] **Step 6: Commit** + +```bash +git add app/managed.ts app/managed.test.ts +git commit -m "feat: add Intelligence channel host (unified CopilotRuntime v2) for KiteBot" +``` + +--- + +## Task 6: Env & docs + +**Files:** +- Modify: `.env.example` +- Modify: `README.md` +- Modify: `setup.md` + +- [ ] **Step 1: Add the Intelligence env block to `.env.example`** + +Insert this block immediately after the "Agent backend (runtime.ts)" section (after the `AGENT_AUTH_HEADER` line, ~`.env.example:41`): + +``` +# ── Intelligence channel mode — app/managed.ts (`pnpm channel`) ────────── +# Runs the SAME bot over the CopilotKit Intelligence realtime gateway instead +# of a native adapter — it holds NO Slack tokens (Intelligence owns the Slack +# edge). The agent brain reuses AGENT_URL / AGENT_AUTH_HEADER above. +# Base API URL of the Intelligence platform (dev shown). +# INTELLIGENCE_API_URL=https://dev.intelligence.copilotkit.ai/api +# Intelligence websocket base (runner/client paths are derived from this). +# INTELLIGENCE_GATEWAY_WS_URL=wss://dev.intelligence.copilotkit.ai +# Project API key (cpk-{projectId}_...); the project id is parsed from it. +# INTELLIGENCE_API_KEY=cpk-... +# The registered channel name (lowercase kebab). Defaults to "kitebot". +# INTELLIGENCE_CHANNEL_NAME=kitebot +``` + +- [ ] **Step 2: Rename bot→channels in `README.md` and `setup.md`, lead with Intelligence, drop Redis, KiteBot mentions** + +In `README.md`: +- Replace every `@copilotkit/bot` occurrence with `@copilotkit/channels` (package names + URLs) in the package tables and prose. +- Remove the `@copilotkit/bot-store-redis` "Optional" table row. +- Add a `@copilotkit/channels-intelligence` row under a new heading or the Optional table: "Runs the bot over CopilotKit Intelligence (managed gateway) instead of holding platform tokens — see `app/managed.ts`." +- Reframe the "Quick start" so the **Intelligence/managed deployment is the recommended default** (a `pnpm channel` path with `INTELLIGENCE_*`), and self-hosted (`pnpm dev`) is the "run it yourself locally" alternative. Note packages now publish to npm (standalone `pnpm install` works). +- Change the `@OpenTag` mention examples to `@KiteBot`, and "an OpenTag agent" prose (line 17) to "a KiteBot agent". Keep the OpenTag project title/branding. + +In `setup.md`: +- Replace every `@copilotkit/bot` with `@copilotkit/channels` (lines ~53-55, 174). +- Remove the `@copilotkit/bot-store-redis` reference (~line 174) and any Redis/`docker compose` persistence section. +- Update the "Standalone (once `@copilotkit/bot-*` publish)" heading (~line 74) — packages ARE published now; reword to reflect that standalone `pnpm install` works, and drop the "Why not standalone yet?" caveat (~line 87). +- Add a short "Intelligence channel mode" subsection describing `pnpm channel` + the `INTELLIGENCE_*` env. + +- [ ] **Step 3: Verify no stale references** + +Run: `grep -rn "@copilotkit/bot\b\|bot-store-redis\|CopilotKit Triage\|REDIS_URL" README.md setup.md .env.example` +Expected: no matches. (`@copilotkit/channels*` matches are expected and correct.) + +- [ ] **Step 4: Commit** + +```bash +git add .env.example README.md setup.md +git commit -m "docs: channels rename, lead with Intelligence deploy, drop Redis, KiteBot mentions" +``` + +--- + +## Task 7: Full verification + +**Files:** none (verification only) + +- [ ] **Step 1: Clean typecheck + tests** + +Run: `pnpm check-types && pnpm test` +Expected: both PASS (exit 0). + +- [ ] **Step 2: Prove the migration is complete** + +Run: `grep -rn "@copilotkit/bot" . --include='*.ts' --include='*.tsx' --include='*.json' --include='*.md' | grep -v node_modules | grep -v docs/superpowers` +Expected: no matches. + +- [ ] **Step 3: Manual gateway smoke test (requires live INTELLIGENCE_* creds)** + +Fill `.env` with the real dev values (`INTELLIGENCE_API_URL`, `INTELLIGENCE_GATEWAY_WS_URL`, `INTELLIGENCE_API_KEY`, `INTELLIGENCE_CHANNEL_NAME=kitebot`, `AGENT_URL=http://localhost:8200/api/copilotkit/agent/triage/run`, and the model/MCP keys), then in two terminals: + +Run: `pnpm runtime` → expect `[slack-runtime] agent "triage" ready`. +Run: `pnpm channel` → expect `[channel] KiteBot channel "kitebot" activated on Intelligence` (no gateway/auth error). +Then check the Intelligence dashboard: KiteBot status flips **Waiting for runtime → live**, agent declared. + +If activation errors with a channel-name mismatch, set `INTELLIGENCE_CHANNEL_NAME` to the exact registered slug and retry (no code change). + +- [ ] **Step 4: Behavioral check in Slack** + +@mention KiteBot in the connected workspace: it replies, renders a card (e.g. "Triage my open issues"), and the confirm-before-write HITL gate fires on a file-issue — behavior identical to the native bot. + +--- + +## Notes for the executor +- Do NOT touch API identifiers during the rename — only package specifiers move (`createBot`, `defineBotTool`, `BotNode`, `slack()` stay). +- Task order matters: Redis (Task 2) is deleted before the rename (Task 3) so `@copilotkit/bot-store-redis` is never mis-rewritten. +- `sed -i ''` is macOS/BSD syntax (empty backup arg). On GNU/Linux use `sed -i`. +- The two dashboard-derived values (`INTELLIGENCE_API_URL`/`_GATEWAY_WS_URL` bases and the channel-name slug) are env-configurable — a wrong value is a config fix, not a code change. diff --git a/docs/superpowers/specs/2026-07-15-kitebot-intelligence-foundation-design.md b/docs/superpowers/specs/2026-07-15-kitebot-intelligence-foundation-design.md new file mode 100644 index 0000000..e601c71 --- /dev/null +++ b/docs/superpowers/specs/2026-07-15-kitebot-intelligence-foundation-design.md @@ -0,0 +1,177 @@ +# KiteBot on CopilotKit Intelligence — Phase 1 (Foundation) + +**Date:** 2026-07-15 +**Branch:** `jerel/copilotkit-channels-intelligence-40037b` +**Status:** Design — awaiting review + +## North star (context, not all in this phase) + +Turn OpenTag into a **one-click, customizable, Intelligence-connected** template whose +bot is **KiteBot**, running on the CopilotKit **Channels + Intelligence** stack, with a +**LangGraph deep-agent** brain (for LangChain co-marketing). The full objective: + +- [ ] LangChain / LangGraph **deep agents** (co-marketing) — *Phase 2* +- [ ] **One-click install** (Railway template) — *Phase 3* +- [x] **Customizable** — the `app/` channel surface stays hackable (all phases) +- [x] **Setup with CopilotKit Intelligence** — *this phase* + +This spec covers **Phase 1 only**: migrate off the deprecated `@copilotkit/bot*` +packages, drop Redis, rename the bot to KiteBot, and stand up the **unified v2 +`CopilotRuntime` Intelligence runtime** that connects the already-provisioned KiteBot +channel (dashboard status: *"Waiting for runtime"*). Phases 2–3 get their own specs. + +## Background — what's already true + +- The `@copilotkit/bot*` packages were **renamed** to `@copilotkit/channels*`. API + identifiers are unchanged (`createBot`→still exists, plus new `createChannel`; + `defineBotTool`, `slack()`, `BotNode`, etc.). Only import specifiers + `jsxImportSource` move. +- All packages are **published on npm**: `@copilotkit/channels@0.1.1`, + `@copilotkit/channels-intelligence@0.1.1`, `@copilotkit/channels-slack@0.1.2`, + `@copilotkit/runtime@1.62.3` (exposes `/v2`, `/v2/node`, `/v2/express`). OpenTag's + old "can't run standalone until packages publish" caveat is **resolved** — a plain + `pnpm install` from this repo now works. +- The KiteBot channel exists on Intelligence (dev): display name **KiteBot**, id + `channel_019f670e-8b1c-71a4-97af-7dffb34198b2`, Slack provider (webhook + `https://dev.intelligence.copilotkit.ai/api/channels/adapters/slack/events`), status + **Waiting for runtime**, agent **Not declared**. +- Current OpenTag runs a **two-process** model: `runtime.ts` (a v2 `CopilotSseRuntime` + hosting a `BuiltInAgent` "triage" on `:8200`) + `app/index.ts` (a `createBot` Slack + bridge). `app/` is a near-verbatim fork of upstream `examples/slack`. + +## Target architecture (Phase 1) + +Two processes, both env-driven so local == deployed: + +1. **Channel host** — a NEW unified `CopilotRuntime` (v2, *intelligence* mode). Holds NO + Slack tokens; connects to the Intelligence Realtime Gateway, **declares the `kitebot` + channel**, and streams render frames back. Intelligence owns the Slack edge. This is + the process whose connection flips the dashboard from *Waiting for runtime* → live. + +2. **Agent backend** — the EXISTING `runtime.ts` (`CopilotSseRuntime` + `BuiltInAgent` + "triage") on `:8200`, unchanged except for the KiteBot persona rename. The channel's + agent points at it via `HttpAgent`. In Phase 2 the `DEEP_AGENT_URL` is repointed at a + LangGraph deep-agent service; nothing else in the channel host changes. + +The channel definition carries the same customizable surface `createBot` had — the +app's `tools`, `context`, `commands`, HITL gate, and generative-UI renderers — so `app/` +remains the "make it your own" layer. + +### Channel host — verified-runnable shape + +```ts +import { createServer } from "node:http"; +import { CopilotRuntime, CopilotKitIntelligence } from "@copilotkit/runtime/v2"; +import { createCopilotNodeListener } from "@copilotkit/runtime/v2/node"; +import { createChannel } from "@copilotkit/channels"; // plural — @copilotkit/channel does NOT exist +import { SanitizingHttpAgent, defaultSlackTools, defaultSlackContext } from "@copilotkit/channels-slack"; +// app surface (migrated bot* -> channels*): +import { appTools } from "./tools/index.js"; +import { appContext } from "./context/app-context.js"; +import { appCommands } from "./commands/index.js"; +import { senderContext } from "./sender-context.js"; +import { fileIssueSubmit, FILE_ISSUE_CALLBACK } from "./modals/file-issue.js"; + +const intelligence = new CopilotKitIntelligence({ + apiUrl: process.env.INTELLIGENCE_API_URL!, // https://dev.intelligence.copilotkit.ai/api + wsUrl: process.env.INTELLIGENCE_GATEWAY_WS_URL!, // wss base; runner/client paths derived + apiKey: process.env.INTELLIGENCE_API_KEY!, // cpk-{projectId}_... ; projectId parsed from it +}); + +const channel = createChannel({ + name: process.env.INTELLIGENCE_CHANNEL_NAME ?? "kitebot", // MUST match the registered channel name (lowercase kebab) + agent: (threadId) => { + const a = new SanitizingHttpAgent({ url: process.env.AGENT_URL! }); + a.threadId = threadId; + return a; + }, + tools: [...appTools, ...defaultSlackTools], + context: [...appContext, ...defaultSlackContext], + commands: appCommands, +}); +// turn + feature handlers (onMention with explicit prompt, onModalSubmit, onThreadStarted) +// ported from upstream examples/slack/app/managed.ts + +const runtime = new CopilotRuntime({ agents: {}, intelligence, channels: [channel] }); + +const listener = createCopilotNodeListener({ runtime, basePath: "/" }); +createServer(listener).listen(Number(process.env.PORT ?? 8300)); +await listener.channels?.ready(); // channels activate at handler creation; this awaits readiness +``` + +**Binding model (verified in source):** `projectId` is parsed from the `cpk-…` API key; +the channel binds by **`name`** (not by channel id); provider defaults to `"slack"`. So +the channel id, org id, project id, and a runtime-instance id are **not** inputs in this +path — three secrets + the channel name are the whole config. + +## Scope of changes + +### 1. Dependencies & build config +- `package.json`: replace the six `@copilotkit/bot*` deps with `@copilotkit/channels*` + (`channels`, `channels-ui`, `channels-slack`, `channels-discord`, `channels-telegram`, + `channels-whatsapp`); **drop** `@copilotkit/bot-store-redis`; **add** + `@copilotkit/channels-intelligence`. Pin to published ranges (`^0.1.1` / `^0.1.2` as + appropriate); bump `@copilotkit/runtime` to `^1.62.3`. Update the `description` string. +- `tsconfig.json` + `vitest.config.ts`: `jsxImportSource: "@copilotkit/bot-ui"` → + `"@copilotkit/channels-ui"`. + +### 2. Mechanical source rename (`app/**`) +- Find-and-replace import specifiers `@copilotkit/bot* → @copilotkit/channels*` across all + `.ts`/`.tsx` (source + tests) and matching doc-comments. **No logic changes.** + +### 3. Add the Intelligence channel-host entrypoint +- New `app/managed.ts` — the unified `CopilotRuntime` above (turn/feature handlers ported + from upstream `examples/slack/app/managed.ts`, incl. the multimodal `contentParts` + prompt). New `channel` npm script (`tsx app/managed.ts`). +- New `app/managed.test.ts` — ported from upstream. + +### 4. Drop Redis +- Delete `app/demo-restart.tsx`, delete `docker-compose.yml` (confirm Redis-only first), + remove the `demo:restart` script, remove the Redis block from `.env.example`, remove + Redis mentions from README/setup.md. + +### 5. Env + docs +- `.env.example`: add an `INTELLIGENCE_*` block (`INTELLIGENCE_API_URL`, + `INTELLIGENCE_GATEWAY_WS_URL`, `INTELLIGENCE_API_KEY`, `INTELLIGENCE_CHANNEL_NAME`, + `AGENT_URL`); remove the Redis block. +- `README.md` + `setup.md`: rename bot→channels; **lead with the Intelligence/managed + deployment as the default** documented path, self-hosted (`index.ts`) as the alternative; + drop the Redis row/section; add a `@copilotkit/channels-intelligence` entry. + +### 6. Rename bot → KiteBot (identity only; project stays "OpenTag") +- `slack-app-manifest.yaml` + `.json`: `display_information.name` and + `bot_user.display_name` `"CopilotKit Triage"` → **"KiteBot"**. +- `runtime.ts` `SYSTEM_PROMPT` + `app/context/app-context.ts`: name the persona + ("You are **KiteBot**, an on-call triage assistant…"). +- `app/index.ts` comments: "Kite" → "KiteBot". +- Channel machine name: **`kitebot`** (lowercase kebab; the display persona is "KiteBot"). +- README `@OpenTag` mention examples → **`@KiteBot`**; "OpenTag agent" prose → "KiteBot". + +### 7. npm scripts default +- Keep `dev`/`start` = self-hosted (`index.ts`) so `git clone && pnpm dev` runs out-of-box. +- Add `channel` = `tsx app/managed.ts` (the Intelligence run mode). +- README frames Intelligence as the recommended deployment; the runnable default script + stays self-hosted. *(Open to flipping — see Open Questions.)* + +## Verification (definition of done for Phase 1) +1. `pnpm check-types` and `pnpm test` pass. +2. `grep -r "@copilotkit/bot" .` (excluding node_modules) returns **zero** matches. +3. `pnpm runtime` (agent backend, `:8200`) + `pnpm channel` (channel host, `:8300`) + both start; the channel host connects to the gateway and the KiteBot dashboard flips + **Waiting for runtime → live** with the agent declared. +4. An @mention of KiteBot in the connected Slack workspace round-trips: agent replies, + renders a card, and the HITL gate works — behaviorally identical to the native bot. + +## Out of scope (later phases) +- **Phase 2:** stand up the LangGraph deep-agent AG-UI service; repoint `AGENT_URL` + /`DEEP_AGENT_URL` at it (co-marketing). +- **Phase 3:** Railway one-click template (`railway.json`, deploy button, two-service + wiring, docs). + +## Open questions / confirmations needed from the user +1. **Channel name slug** — dashboard display is "KiteBot"; the registered `name` must be + lowercase kebab. Confirm it is **`kitebot`** (vs `kite-bot`), else activation fails and + the channel stays *Waiting for runtime*. +2. **Dev endpoint bases** — confirm `INTELLIGENCE_API_URL` + (`https://dev.intelligence.copilotkit.ai/api`?) and `INTELLIGENCE_GATEWAY_WS_URL` + (`wss://dev.intelligence.copilotkit.ai/…` base). API key (`cpk-…`) assumed already in hand. +3. **Scripts default** — keep `dev`/`start` self-hosted (recommended) or flip to `managed.ts`? diff --git a/package.json b/package.json index 8331229..a58a13b 100644 --- a/package.json +++ b/package.json @@ -2,13 +2,13 @@ "name": "opentag", "version": "0.2.0", "private": true, - "description": "OpenTag — an open-source, self-hosted alternative to Claude in Slack: run your own AI agent on your infrastructure, with your model and your tools. Built on @copilotkit/bot; also runs on Discord, Telegram & WhatsApp.", + "description": "OpenTag — an open-source, self-hosted alternative to Claude in Slack: run your own AI agent on your infrastructure, with your model and your tools. Built on @copilotkit/channels; also runs on Discord, Telegram & WhatsApp.", "license": "MIT", "type": "module", "scripts": { "dev": "tsx watch app/index.ts", "start": "tsx app/index.ts", - "demo:restart": "tsx app/demo-restart.tsx", + "channel": "tsx app/managed.ts", "runtime": "tsx runtime.ts", "notion-mcp": "tsx scripts/start-notion-mcp.ts", "check-types": "tsc --noEmit -p tsconfig.json", @@ -18,14 +18,14 @@ "e2e:telegram": "tsx e2e/telegram-run.ts" }, "dependencies": { - "@copilotkit/bot": "^0.1.0", - "@copilotkit/bot-discord": "^0.1.0", - "@copilotkit/bot-slack": "^0.1.0", - "@copilotkit/bot-store-redis": "^0.1.0", - "@copilotkit/bot-telegram": "^0.1.0", - "@copilotkit/bot-ui": "^0.1.0", - "@copilotkit/bot-whatsapp": "^0.1.0", - "@copilotkit/runtime": "^1.61.2", + "@copilotkit/channels": "^0.1.1", + "@copilotkit/channels-discord": "^0.0.3", + "@copilotkit/channels-intelligence": "^0.1.1", + "@copilotkit/channels-slack": "^0.1.2", + "@copilotkit/channels-telegram": "^0.0.4", + "@copilotkit/channels-ui": "^0.1.1", + "@copilotkit/channels-whatsapp": "^0.0.2", + "@copilotkit/runtime": "^1.62.3", "@tanstack/ai": "^0.32.0", "@tanstack/ai-mcp": "^0.1.3", "@tanstack/ai-openai": "^0.15.2", @@ -41,5 +41,10 @@ "tsx": "^4.19.2", "typescript": "^5.6.3", "vitest": "^4.1.3" + }, + "pnpm": { + "overrides": { + "rxjs": "^7.8.2" + } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..9e7f141 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,4920 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + rxjs: ^7.8.2 + +importers: + + .: + dependencies: + '@copilotkit/channels': + specifier: ^0.1.1 + version: 0.1.1(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76) + '@copilotkit/channels-discord': + specifier: ^0.0.3 + version: 0.0.3(@ag-ui/core@0.0.57)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1))) + '@copilotkit/channels-intelligence': + specifier: ^0.1.1 + version: 0.1.1(@ag-ui/core@0.0.57)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76) + '@copilotkit/channels-slack': + specifier: ^0.1.2 + version: 0.1.2(@types/express@5.0.6)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1))) + '@copilotkit/channels-telegram': + specifier: ^0.0.4 + version: 0.0.4(@ag-ui/core@0.0.57)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1))) + '@copilotkit/channels-ui': + specifier: ^0.1.1 + version: 0.1.1(@ag-ui/core@0.0.57) + '@copilotkit/channels-whatsapp': + specifier: ^0.0.2 + version: 0.0.2(@ag-ui/core@0.0.57)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76) + '@copilotkit/runtime': + specifier: ^1.62.3 + version: 1.62.3(@cfworker/json-schema@4.1.1)(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(@langchain/langgraph-sdk@1.9.27(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1)))(@opentelemetry/api@1.9.1)(langchain@1.5.3(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(openai@6.47.0(ws@8.21.1)(zod@3.25.76)) + '@slack/bolt': + specifier: ^4.2.0 + version: 4.7.3(@types/express@5.0.6) + '@slack/types': + specifier: ^2.21.1 + version: 2.22.0 + '@tanstack/ai': + specifier: ^0.32.0 + version: 0.32.0(@opentelemetry/api@1.9.1) + '@tanstack/ai-mcp': + specifier: ^0.1.3 + version: 0.1.10(@cfworker/json-schema@4.1.1)(@opentelemetry/api@1.9.1)(zod@3.25.76) + '@tanstack/ai-openai': + specifier: ^0.15.2 + version: 0.15.10(@tanstack/ai@0.32.0(@opentelemetry/api@1.9.1))(ws@8.21.1)(zod@3.25.76) + playwright: + specifier: ^1.49.0 + version: 1.61.1 + zod: + specifier: ^3.25.76 + version: 3.25.76 + devDependencies: + '@notionhq/notion-mcp-server': + specifier: ^2.2.1 + version: 2.4.1(@cfworker/json-schema@4.1.1)(js-yaml@4.3.0) + '@types/node': + specifier: ^22.10.0 + version: 22.20.1 + dotenv: + specifier: ^16.4.5 + version: 16.6.1 + tsx: + specifier: ^4.19.2 + version: 4.23.1 + typescript: + specifier: ^5.6.3 + version: 5.9.3 + vitest: + specifier: ^4.1.3 + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)) + +packages: + + '@ag-ui/a2ui-middleware@0.0.10': + resolution: {integrity: sha512-2BQFUQ9vJzUAQSR0dNW/ijhyH8KpiRWISSLTP6mIe6ENyQ2cM1/XLG38/Dcb69olcs36gtZADZzAQWcno5H6fA==} + peerDependencies: + '@ag-ui/client': '>=0.0.40' + rxjs: ^7.8.2 + + '@ag-ui/a2ui-toolkit@0.0.4': + resolution: {integrity: sha512-9VPmgpCAsFVICk7z23kh+Kp/BwYMxw0D0KGjOiKXhm1MAH+Wid2iC3yKsXso+q7UZZiyhWgeDUSgaAkltyLmGg==} + + '@ag-ui/client@0.0.54': + resolution: {integrity: sha512-N5UVXEBV5gPHqTuMoR/21brconRn42URf+MB4L8OniCJKqLcl/qUJb5kMamK0nnfBhDfPs/uq7LxDn6bsDJzJg==} + + '@ag-ui/client@0.0.57': + resolution: {integrity: sha512-Xap2alG9Z0/j5kb3x4D7oTpe2sw1dfrC9rgJJr2NZu5vKcm8dzIPNd31mF2B4zS3BKqYIu245yxKPhEtT30MHw==} + + '@ag-ui/core@0.0.52': + resolution: {integrity: sha512-Xo0bUaNV56EqylzcrAuhUkQX7et7+SZIrqZZtEByGwEq/I1EHny6ZMkWHLkKR7UNi0FJZwJyhKYmKJS3B2SEgA==} + + '@ag-ui/core@0.0.54': + resolution: {integrity: sha512-Ilx31OvRQaZfU7jSArGqz06JZKOsAt8zWiCPJljyp9zR6Tzl18oyfx8o6FsuGfAktGRe50GI9SCCxNXXysZwtA==} + + '@ag-ui/core@0.0.57': + resolution: {integrity: sha512-gho1OWjNE6E3Rl7ZEZ1wr2CEpUHjLFU0FqzCZZk439TicLu+BfLCMkMokB07bMGlRmbJ60hM6LW60iOVauCx+Q==} + + '@ag-ui/encoder@0.0.54': + resolution: {integrity: sha512-0dPuE/eAeBRBDj/OOj5AW8SoP1r0dufmoOdrtKgmf+dlbVXKSNkDDHGrrvIWFPxwvPTWhHeN6wnsVUayWpUsGg==} + + '@ag-ui/encoder@0.0.57': + resolution: {integrity: sha512-ifD9NctR4xyPDR58xF9GK1bj/S8oECFkTeDfuYD8tXdbcOstIJ2TOqU2zhiCKnw7Vw+zR9Qv3TbsM9E7Gi9X3Q==} + + '@ag-ui/langgraph@0.0.42': + resolution: {integrity: sha512-dXasEbGQFJcasdoy5khYyDHZHYoD1/i7hioaP8cejfw+Dss4tLvN8ndzD6c5j0hmANaKscekl+zkF7UQq3sI9w==} + peerDependencies: + '@ag-ui/client': '>=0.0.42' + '@ag-ui/core': '>=0.0.42' + + '@ag-ui/mcp-apps-middleware@0.0.3': + resolution: {integrity: sha512-Z+NZQXj4J+Y/2PLNsiyhNzRWFtTT2sAoC5dztoAlIsdfzvLvYEa52YGdHesNTN85JJqaIrYxQ8e31IBpKjrnoA==} + peerDependencies: + '@ag-ui/client': '>=0.0.40' + + '@ag-ui/mcp-middleware@0.0.1': + resolution: {integrity: sha512-TayUu7kB+jXUTPRUJesNvJYrP+0weTL9F2VJJ8QQ4sWxY/Ihjo+GgFYgJZYNcLwbo1DKgmVJtdm2XUouPCbxeg==} + peerDependencies: + rxjs: ^7.8.2 + + '@ag-ui/proto@0.0.54': + resolution: {integrity: sha512-IPF+xeFaBAKKP2FO74MaVTkKUP8VaGGkbPzORCvC5TLDdGs+oQgQFqz+XoBeksQGE14+jgLWiAr9EPXdhqr1NA==} + + '@ag-ui/proto@0.0.57': + resolution: {integrity: sha512-pPENOZt0P6ibH8sCTgq05wLYXi5t3P9B5r/1bWYehXjUxtyOdnukSlWM++SsCIwUXsQdm/b3aBgGjEeTF7RenA==} + + '@ai-sdk/anthropic@2.0.86': + resolution: {integrity: sha512-Zwh6GgGmR1u/Gyv1Q+atapY+BZ/RwYULLu7hSxR3QcXwte2MbxVMywI/HI/rMw3ucA5h1RfSqJejx07BvbPgrA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/anthropic@3.0.97': + resolution: {integrity: sha512-OWX0YIgLv8kNjhIle0kVuUVr2tv3HA7+qTfgtTbUhU6iUK9kJFByYPxLvYzbke+XSBG708Vl9qRlFgq6qyGjdw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/gateway@3.0.151': + resolution: {integrity: sha512-gsKEm1LleR/xm1FiJjnNxf1ZUKZryj20STsKJB7TdMcaiRqQgeHrdYWv/DNSA8ZBkRahHC+wEYHaI0VR9/EOwQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/google-vertex@3.0.150': + resolution: {integrity: sha512-ZTrndRxG35CCBH40BFnY86H9QzgB6ocRhjnq3S97d4HW6WO1aegbz6s78wNl3smjD3B/VM6eVdh7oRvPvfRoCA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/google@2.0.81': + resolution: {integrity: sha512-tFdXV+vymLadFlAmHiv7vVrGkDulA5/Ew8nxOOL4gGuhOa+AJ5t9TPk4pqw8bT/Inq6tEhQweC4AHMOnMLQxYA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/google@3.0.94': + resolution: {integrity: sha512-s9vWtsReWMElsmL0R/JfLuBPvgS64pwS4D/8AOGu8fvqBhRkGegsG4q1aNZn30SEox2yfQi76aAFLB5J542Rmg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/mcp@1.0.62': + resolution: {integrity: sha512-9yyXNnIkRhHkSpb6l4Ch1AwAasZ8ohOSOCTSIfvVL+DizDPCH9QH26Pbs4xUEOD1zn9Th43IEmnFcf1Vdh+dAQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/openai-compatible@1.0.44': + resolution: {integrity: sha512-SFZAzWy3d3bvNMekVwiJlu7hr/jNMD2dXBZdoInkFI9gTYt13thvVtYimlgZ25QmZRMRA+fmAkIdBF6+/+nEWQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/openai@3.0.85': + resolution: {integrity: sha512-/j7rPYswnWhStDbaO75gLVwq+Tm73vCquFCNTuYYyxY31TP0ZG7d0ZANIjiVlNDEVqQqXNBeMrEzGCpSN4QnKg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider-utils@3.0.29': + resolution: {integrity: sha512-4oNFrqBcy24KNclF1tWp/7ks+kSkDF6VZ1ccIfQoFVIgAAaoNH8bOTbOadVa4Dk70ghsh32caSHYWlzBI8F10g==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider-utils@4.0.39': + resolution: {integrity: sha512-XPR6o7561RYUkfYlLYouWsvm6Gv2tYIQy5pttGRkvML98u138ClPThn5yiQg5rMQutTtZLB+GUC8qFFCzDKQQQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider@2.0.3': + resolution: {integrity: sha512-h88OPkavHTiN9tMn2l5awAznGB0lXzjcLhgR1/rvjB2zlLprsNxbM2tt6OJsHUxduLC3klq0/eqaSf6fX5XVww==} + engines: {node: '>=18'} + + '@ai-sdk/provider@3.0.14': + resolution: {integrity: sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA==} + engines: {node: '>=18'} + + '@bufbuild/protobuf@2.12.1': + resolution: {integrity: sha512-BvAMfS6LrgZiryOAZ4pBYucu4wG/Ei/9o9DZ9akbREnMLbPJiom2i8b9C8IsKErQoiKqVhrerzt3kOT/RrzLHg==} + + '@cfworker/json-schema@4.1.1': + resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + + '@copilotkit/channels-discord@0.0.3': + resolution: {integrity: sha512-UXkWHcQJ9kLDkkGMXC3NyHuYwdVxWW09uyn1wm9er5tcL5/ZK12gvqgnj7G5j5pF7VI0qWXQ+ZvO3uZENo7o0A==} + + '@copilotkit/channels-intelligence@0.1.1': + resolution: {integrity: sha512-lS3vzbuRaeLTE+ucdsinBd9YHdm4lqUjvA57wowGMs+/WUZKzKCLGiE9BYOErQzo0PaM8MTx8TomTzNSny287w==} + + '@copilotkit/channels-slack@0.1.2': + resolution: {integrity: sha512-h8VR+raH1GvdNxEuNcpGMe7TayZxzj33xobq6RCCU4hLu15jadCyYj9CXArYIcwyManlbWE5jqi6n8cla23E0g==} + + '@copilotkit/channels-telegram@0.0.4': + resolution: {integrity: sha512-LyzGU9wHVPPc7MsR9+w1kBXcEqotI3k8XRJLola99ktzEpAtXTwCmBlnyh+j7UTCMXsRTjKz9eC6ULxDy82GbQ==} + + '@copilotkit/channels-ui@0.1.1': + resolution: {integrity: sha512-wQ099E62DEhIuKz8O9Iqy1VP4qCyLtS8d5EwfF2MK8m8amWtuyyTUxV8vC1q9ecJMgAwCtKmeW/fYQR8NsLiXQ==} + + '@copilotkit/channels-whatsapp@0.0.2': + resolution: {integrity: sha512-T2eCeY6NXSAZbdQsARhhpLGsXP667wWqgsWpMPXy+dULvGhemw/ueyijV5/kEzMnxlaBoZ4TuGClXweMtDxZfw==} + + '@copilotkit/channels@0.1.1': + resolution: {integrity: sha512-v/cOFfRZWKXstrj06YZmR5kikE9XhXluuJa81hZEhZ4I9C3U+Lnao1K5pL5DtmhUbowynMvBedVUNqKwGFLCvQ==} + peerDependencies: + vitest: ^4.0.0 + peerDependenciesMeta: + vitest: + optional: true + + '@copilotkit/core@1.62.3': + resolution: {integrity: sha512-Iw0XTJDylh4DTL1qqqoDSvMeL4lXGWfn8UAunnvYtVZ2BF3gs6Lw6K/yOQ0gGQKMqIxeQmgLVclErxwBcaJ8KQ==} + engines: {node: '>=18'} + + '@copilotkit/license-verifier@0.5.0': + resolution: {integrity: sha512-vrwKtIpYwF0FT9ZoYASH8owa2cGV0dhDvJGaCRaRMStwDxpc6DRdydKkhx8cWZXyBRxEYcq/Vygv4JvevhQQdQ==} + + '@copilotkit/runtime@1.62.3': + resolution: {integrity: sha512-pOyQbd0IGH/rmyZ7yoGodc2FRicO3AXBI6y7lQDGjbat2lI9SLhsGQve7O3QfeYH0UZ4T9019EgnnKtSN7ImUQ==} + peerDependencies: + '@anthropic-ai/sdk': ^0.57.0 + '@langchain/aws': '>=0.1.9' + '@langchain/community': '>=0.3.58' + '@langchain/core': '>=0.3.66' + '@langchain/google-gauth': '>=0.1.0' + '@langchain/langgraph-sdk': '>=0.1.2' + '@langchain/openai': '>=0.4.2' + groq-sdk: '>=0.3.0 <1.0.0' + langchain: '>=0.3.3' + openai: ^4.85.1 || >=5.0.0 + peerDependenciesMeta: + '@anthropic-ai/sdk': + optional: true + '@langchain/aws': + optional: true + '@langchain/community': + optional: true + '@langchain/google-gauth': + optional: true + '@langchain/langgraph-sdk': + optional: true + '@langchain/openai': + optional: true + groq-sdk: + optional: true + langchain: + optional: true + openai: + optional: true + + '@copilotkit/shared@1.62.3': + resolution: {integrity: sha512-dfqaYjfJzTIjMBUMOHGZGoZ+v9pumsBuM1FMi5Sb66WkzxbtIKN0CCbYXXIHd0xsEo1pa8u1vZSN30sBtJuQ7g==} + peerDependencies: + '@ag-ui/core': '>=0.0.48' + + '@discordjs/builders@1.14.1': + resolution: {integrity: sha512-gSKkhXLqs96TCzk66VZuHHl8z2bQMJFGwrXC0f33ngK+FLNau4hU1PYny3DNJfNdSH+gVMzE85/d5FQ2BpcNwQ==} + engines: {node: '>=16.11.0'} + + '@discordjs/collection@1.5.3': + resolution: {integrity: sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==} + engines: {node: '>=16.11.0'} + + '@discordjs/collection@2.1.1': + resolution: {integrity: sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==} + engines: {node: '>=18'} + + '@discordjs/formatters@0.6.2': + resolution: {integrity: sha512-y4UPwWhH6vChKRkGdMB4odasUbHOUwy7KL+OVwF86PvT6QVOwElx+TiI1/6kcmcEe+g5YRXJFiXSXUdabqZOvQ==} + engines: {node: '>=16.11.0'} + + '@discordjs/rest@2.6.2': + resolution: {integrity: sha512-c5HI3hJuRWWrnpyCZAUYfIUTAEv9weX4tE2UfDqtM3ztizdKE9RFEf3G5IWhPyO+kPldUDpGv02XJAQzdUTC9Q==} + engines: {node: '>=18'} + + '@discordjs/util@1.2.0': + resolution: {integrity: sha512-3LKP7F2+atl9vJFhaBjn4nOaSWahZ/yWjOvA4e5pnXkt2qyXRCHLxoBQy81GFtLGCq7K9lPm9R517M1U+/90Qg==} + engines: {node: '>=18'} + + '@discordjs/ws@1.2.3': + resolution: {integrity: sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw==} + engines: {node: '>=16.11.0'} + + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + + '@envelop/core@5.5.1': + resolution: {integrity: sha512-3DQg8sFskDo386TkL5j12jyRAdip/8yzK3x7YGbZBgobZ4aKXrvDU0GppU0SnmrpQnNaiTUsxBs9LKkwQ/eyvw==} + engines: {node: '>=18.0.0'} + + '@envelop/instrumentation@1.0.0': + resolution: {integrity: sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw==} + engines: {node: '>=18.0.0'} + + '@envelop/types@5.2.1': + resolution: {integrity: sha512-CsFmA3u3c2QoLDTfEpGr4t25fjMU31nyvse7IzWTvb0ZycuPjMjb0fjlheh+PbhBYb9YLugnT2uY6Mwcg1o+Zg==} + engines: {node: '>=18.0.0'} + + '@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.28.1': + resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.28.1': + resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + engines: {node: '>=18'} + cpu: [arm] + 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.28.1': + resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.28.1': + resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@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.28.1': + resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.28.1': + resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + engines: {node: '>=18'} + cpu: [arm64] + 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.28.1': + resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + engines: {node: '>=18'} + cpu: [ia32] + 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.28.1': + resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + engines: {node: '>=18'} + cpu: [mips64el] + 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.28.1': + resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + engines: {node: '>=18'} + cpu: [riscv64] + 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.28.1': + resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.28.1': + resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.28.1': + resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.28.1': + resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + engines: {node: '>=18'} + cpu: [arm64] + 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.28.1': + resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.28.1': + resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.28.1': + resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + engines: {node: '>=18'} + cpu: [arm64] + 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.28.1': + resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@fastify/busboy@3.2.0': + resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==} + + '@grammyjs/types@3.28.0': + resolution: {integrity: sha512-4JvXCdxRZHCje0M4gHzLwtB4bLno3WD28xd8CNfk4POWIu73BFnSvGeW6OQ5gPem4eYTEwkD9yDaXssixl6tMQ==} + + '@graphql-tools/executor@1.5.5': + resolution: {integrity: sha512-JAdn4G+ehthnGdJABS+wO6LxAIcoGPiSRHIz1ECYLtaQGkpFIdqH6BLUbZcToX/W/nmOG0kTFLoepCGkugbsBA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/merge@9.2.0': + resolution: {integrity: sha512-kChDH/sOxm3TCICup5NgTiz/aJBk+5GAuC0lfJS8FcRfsqZvlCkNwpsYTGAATBCJMrgZ9+csRugCjS97jPcNMw==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/schema@10.0.36': + resolution: {integrity: sha512-g8S5aLirZInoi3NojzmBxwsZfVawOE0UBlVWYe8kDAR0FxS0riBDiyW7JnlAKayooHMRAMwGaze4RQU3VTTyig==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/utils@10.11.0': + resolution: {integrity: sha512-iBFR9GXIs0gCD+yc3hoNswViL1O5josI33dUqiNStFI/MHLCEPduasceAcazRH77YONKNiviHBV8f7OgcT4o2Q==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/utils@11.2.0': + resolution: {integrity: sha512-eu9h1R3j/wWc4rvmYJF5AKtlwniDzstrZ/c6KSz+HdI+n7I7iog9xyKmBfpUwSbG1TqPNZBzWjFMkzdYOKq6Bg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-typed-document-node/core@3.2.0': + resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-yoga/logger@2.0.1': + resolution: {integrity: sha512-Nv0BoDGLMg9QBKy9cIswQ3/6aKaKjlTh87x3GiBg2Z4RrjyrM48DvOOK0pJh1C1At+b0mUIM67cwZcFTDLN4sA==} + engines: {node: '>=18.0.0'} + + '@graphql-yoga/plugin-defer-stream@3.21.2': + resolution: {integrity: sha512-B+hwCIPsZHPxH3zsRhBFlMAAuuBMR7SrGVPvGt0ftn3iG2HB1zyOeUIm6ylwVF7G2sN0bw8Z7ZXPdnmI1tgq3A==} + engines: {node: '>=18.0.0'} + peerDependencies: + graphql: ^15.2.0 || ^16.0.0 + graphql-yoga: ^5.21.2 + + '@graphql-yoga/subscription@5.0.5': + resolution: {integrity: sha512-oCMWOqFs6QV96/NZRt/ZhTQvzjkGB4YohBOpKM4jH/lDT4qb7Lex/aGCxpi/JD9njw3zBBtMqxbaC22+tFHVvw==} + engines: {node: '>=18.0.0'} + + '@graphql-yoga/typed-event-target@3.0.2': + resolution: {integrity: sha512-ZpJxMqB+Qfe3rp6uszCQoag4nSw42icURnBRfFYSOmTgEeOe4rD0vYlbA8spvCu2TlCesNTlEN9BLWtQqLxabA==} + engines: {node: '>=18.0.0'} + + '@hono/node-server@1.19.14': + resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} + engines: {node: '>=18.14.1'} + peerDependencies: + hono: ^4 + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@langchain/core@1.2.3': + resolution: {integrity: sha512-F+L5SsciykwDl7eDxacnhDTcWe1IF6jetzfkvI5PPfq6ogWHO7xcjU90SGh/3lqbbS0tgun+qF01KIqxawrCsA==} + engines: {node: '>=20'} + + '@langchain/langgraph-checkpoint@1.1.3': + resolution: {integrity: sha512-wgzdQNeEsdw1e+4lvlj0tdq/RYR/k1vPin10g0ymGoehZDDgd9nvIllGXSXN4TFgF9sf5qQP/KTkOcLfeseIhA==} + engines: {node: '>=18'} + peerDependencies: + '@langchain/core': ^1.1.48 + + '@langchain/langgraph-sdk@1.9.27': + resolution: {integrity: sha512-EHGFsxawniLw2pGVUDLSSdMriASIP4oz0Mihytb50iRsIqhmODzGBWW7iLWA/0hqavggNpqjat4WD7LjmxiXSQ==} + peerDependencies: + '@langchain/core': ^1.1.48 + react: ^18 || ^19 + react-dom: ^18 || ^19 + svelte: ^4.0.0 || ^5.0.0 + vue: ^3.0.0 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + svelte: + optional: true + vue: + optional: true + + '@langchain/langgraph@1.4.8': + resolution: {integrity: sha512-DN1Np1XefdBEbp1qBKlt39cwoL743AAGpR5Ipja0gY2YbWvsoQnOTIrjnj/orSAhaUYsdTKS8VSWdFzsHZo6Ig==} + engines: {node: '>=18'} + peerDependencies: + '@langchain/core': ^1.1.48 + zod: ^3.25.32 || ^4.2.0 + + '@langchain/protocol@0.0.18': + resolution: {integrity: sha512-XW1egQtPfsGI41w2AMZNFZrUIwFSQHTjVMZs0OaTpCAvht/QLoaPN8FQcsysMVypOhupG28J29yOorrc70otBQ==} + + '@lukeed/csprng@1.1.0': + resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} + engines: {node: '>=8'} + + '@lukeed/uuid@2.0.1': + resolution: {integrity: sha512-qC72D4+CDdjGqJvkFMMEAtancHUQ7/d/tAiHf64z8MopFDmcrtbcJuerDtFceuAfQJ2pDSfCKCtbqoGBNnwg0w==} + engines: {node: '>=8'} + + '@modelcontextprotocol/sdk@1.29.0': + resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} + engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true + + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@notionhq/notion-mcp-server@2.4.1': + resolution: {integrity: sha512-D/LixSjTgWi3LrE386yFp+/JHQg768stP5AnWR7SY7p9anDi1NR8Wl6RA4bIKVfLf1kReBVKMbPaDKpM4rm89A==} + hasBin: true + + '@opentelemetry/api@1.9.1': + resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} + engines: {node: '>=8.0.0'} + + '@oxc-project/types@0.139.0': + resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + + '@protobuf-ts/protoc@2.11.1': + resolution: {integrity: sha512-mUZJaV0daGO6HUX90o/atzQ6A7bbN2RSuHtdwo8SSF2Qoe3zHwa4IHyCN1evftTeHfLmdz+45qo47sL+5P8nyg==} + hasBin: true + + '@remix-run/node-fetch-server@0.13.3': + resolution: {integrity: sha512-UfjOXed/DQteaM5VyTfqTeGpHwyL2J5aoRGY6cydip4tt1ehNNeSwuXCC7AEGE0RWBs/7bgKxYkL/B/+UDe4AA==} + + '@repeaterjs/repeater@3.1.0': + resolution: {integrity: sha512-TaoVksZRSx2KWYYpyLQtMQXXeS98VsgZImzW65xmiVgbYhXLk+aEsmzPLirqVuE4/XuUapH2iMtxUzaBNDzdSQ==} + + '@rolldown/binding-android-arm64@1.1.5': + resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.1.5': + resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.1.5': + resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.1.5': + resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.1.5': + resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.1.5': + resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.1.5': + resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.1.5': + resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.1.5': + resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.1.5': + resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.1.5': + resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.1.5': + resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.1.5': + resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@sapphire/async-queue@1.5.5': + resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@sapphire/shapeshift@4.0.0': + resolution: {integrity: sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==} + engines: {node: '>=v16'} + + '@sapphire/snowflake@3.5.5': + resolution: {integrity: sha512-xzvBr1Q1c4lCe7i6sRnrofxeO1QTP/LKQ6A6qy0iB4x5yfiSfARMEQEghojzTNALDTcv8En04qYNIco9/K9eZQ==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@scarf/scarf@1.4.0': + resolution: {integrity: sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==} + + '@segment/analytics-core@1.8.2': + resolution: {integrity: sha512-5FDy6l8chpzUfJcNlIcyqYQq4+JTUynlVoCeCUuVz+l+6W0PXg+ljKp34R4yLVCcY5VVZohuW+HH0VLWdwYVAg==} + + '@segment/analytics-generic-utils@1.2.0': + resolution: {integrity: sha512-DfnW6mW3YQOLlDQQdR89k4EqfHb0g/3XvBXkovH1FstUN93eL1kfW9CsDcVQyH3bAC5ZsFyjA/o/1Q2j0QeoWw==} + + '@segment/analytics-node@2.3.0': + resolution: {integrity: sha512-fOXLL8uY0uAWw/sTLmezze80hj8YGgXXlAfvSS6TUmivk4D/SP0C0sxnbpFdkUzWg2zT64qWIZj26afEtSnxUA==} + engines: {node: '>=20'} + + '@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.1': + resolution: {integrity: sha512-6cmdPrV/RYfd2U0mDGiMK8S7OJqpCTm7enMLRR3edccsPX8j7zXTLnaEF4fhxxJJTAIOil6+qZrnUPTuaLvwrQ==} + engines: {node: '>= 18', npm: '>= 8.6.0'} + + '@slack/oauth@3.0.5': + resolution: {integrity: sha512-exqFQySKhNDptWYSWhvRUJ4/+ndu2gayIy7vg/JfmJq3wGtGdHk531P96fAZyBm5c1Le3yaPYqv92rL4COlU3A==} + engines: {node: '>=18', npm: '>=8.6.0'} + + '@slack/socket-mode@2.0.7': + resolution: {integrity: sha512-qYy07je71WnEHgRwmw12DlAnZLi5HXmdlI2WUzUK2LH/rYXQpP6uEg462S5CwfE8FoCKUdIigHtYnOOfzZH1lQ==} + engines: {node: '>= 18', npm: '>= 8.6.0'} + + '@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.19.0': + resolution: {integrity: sha512-ItjyjEZml+LDH8CjcCLRLJHh7VZtevPKExrRN3l5KWyBliyDnGAeoO4Y+K+fFBmRpKLYVPgqWMX4THldv2HVtA==} + engines: {node: '>= 18', npm: '>= 8.6.0'} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@tanstack/ai-event-client@0.6.3': + resolution: {integrity: sha512-aQb+v9a4T+uDS3VuDGKOdhwPvr2iwjHVweroXHwbasmvClFqV6WJhoekv74VJrhJrlwz8wVMEPcwlKHxnSAzLQ==} + peerDependencies: + '@tanstack/ai': 0.32.0 + + '@tanstack/ai-event-client@0.6.8': + resolution: {integrity: sha512-h7/HLz9u2LF9ba6uKFMnSZkFlkzQONJ5u3Hi+4qGxpsHyvcGRtW6v186jaFLoklndhEwyC49ytkC4eafi7Qq8w==} + + '@tanstack/ai-mcp@0.1.10': + resolution: {integrity: sha512-J6PDw9KOpc5C6/L5IYq4SBnzhTUqjfSHcyOuE+ESVbhTeEctnKTH2IT50JZ46sVinmGUSgQ67j2YuItLZoJRWw==} + hasBin: true + + '@tanstack/ai-openai@0.15.10': + resolution: {integrity: sha512-S/mbplx7sf3lhJrMZBTIBteaaWID6LuNBW8MkOk1I12x0fCmHxZaisf4fKILekcrZ6WniqVNyOLKrJnDD+T2PQ==} + peerDependencies: + '@tanstack/ai': ^0.39.0 + zod: ^4.0.0 + + '@tanstack/ai-utils@0.3.1': + resolution: {integrity: sha512-fgbjd5DohL3k5rTWr/KInauLVYMiHVm0cnmTsNrzL3cr4wWhEld5vmFSrjiwUWACAuONjZa+uBXuS+ZSO8fwDQ==} + + '@tanstack/ai@0.32.0': + resolution: {integrity: sha512-8Saiyws4irNkxPcyLOucquYaEFEGUVBCrBJmfr1W6z1oDVDYF+pwb31rOLjN0/xqbGCHzjOaXc4TLAZS3kPS4g==} + engines: {node: '>=18'} + peerDependencies: + '@opentelemetry/api': '>=1.9.0' + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + + '@tanstack/ai@0.37.0': + resolution: {integrity: sha512-5vM8XCBUyk6whQZ7gAiM1nX+NqvOAOZqAJrFxlo6g+vIvIfqfNqcD378E7kmZIIt5idFkzA8/IH/00oQDsZRyg==} + engines: {node: '>=18'} + peerDependencies: + '@opentelemetry/api': '>=1.9.0' + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + + '@tanstack/devtools-event-client@0.4.4': + resolution: {integrity: sha512-6T5Yop/793YI+H+5J8Hsyj4kCih9sl4t3ElLgKioW5hk3ocn+ZdSJ94tT7vL7uabxSugWYBZlOTMPzEw2puvQw==} + engines: {node: '>=18'} + hasBin: true + + '@tanstack/openai-base@0.9.6': + resolution: {integrity: sha512-vHF5VTKrLrb0c+fLm4hdd5xOKsYUI1/Qt3bLaFYMeUogfYq1LIZlEGUb4EJaFaMYLrjIuep+exjpaHx0TY9kMQ==} + peerDependencies: + '@tanstack/ai': ^0.39.0 + + '@tanstack/pacer@0.20.1': + resolution: {integrity: sha512-ZNQ1bIL6eUXVKdic0tiImvBVkWrg/IoSK6VIacTrO3d3HAGnd70qFJNJagR/YOJIOw4EKGWnodwpYZkN1pWuVQ==} + engines: {node: '>=18'} + + '@tanstack/store@0.9.3': + resolution: {integrity: sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==} + + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + + '@types/body-parser@1.19.6': + resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/express-serve-static-core@5.1.2': + resolution: {integrity: sha512-d3KvEXBSo/lOAMc2u6fkyDHBvetBHeqD7wm/AcXfLpSOQwlmG9D/aQ0SFswVjv05p7ullQS7Mjohj6/VdbZuTg==} + + '@types/express@5.0.6': + resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} + + '@types/http-errors@2.0.5': + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/jsonwebtoken@9.0.10': + resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/node@22.20.1': + resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==} + + '@types/qs@6.15.1': + resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + + '@types/send@1.2.1': + resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} + + '@types/serve-static@2.2.0': + resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} + + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + + '@types/validator@13.15.10': + resolution: {integrity: sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@vercel/oidc@3.2.0': + resolution: {integrity: sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug==} + engines: {node: '>= 20'} + + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} + + '@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@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} + + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} + + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} + + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} + + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} + + '@vladfrangu/async_event_emitter@2.4.7': + resolution: {integrity: sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@whatwg-node/disposablestack@0.0.6': + resolution: {integrity: sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==} + engines: {node: '>=18.0.0'} + + '@whatwg-node/events@0.1.2': + resolution: {integrity: sha512-ApcWxkrs1WmEMS2CaLLFUEem/49erT3sxIVjpzU5f6zmVcnijtDSrhoK2zVobOIikZJdH63jdAXOrvjf6eOUNQ==} + engines: {node: '>=18.0.0'} + + '@whatwg-node/fetch@0.10.13': + resolution: {integrity: sha512-b4PhJ+zYj4357zwk4TTuF2nEe0vVtOrwdsrNo5hL+u1ojXNhh1FgJ6pg1jzDlwlT4oBdzfSwaBwMCtFCsIWg8Q==} + engines: {node: '>=18.0.0'} + + '@whatwg-node/node-fetch@0.8.6': + resolution: {integrity: sha512-BDMdYFcerLQkwA2RTldxOqRCs6ZQD1S7UgP3pUdGUkcbgTrP/V5ko77ZkCww9DHmC4lpoYuwigGfQYj285gMvA==} + engines: {node: '>=18.0.0'} + + '@whatwg-node/promise-helpers@1.3.2': + resolution: {integrity: sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA==} + engines: {node: '>=16.0.0'} + + '@whatwg-node/server@0.11.0': + resolution: {integrity: sha512-VSdkwnJRr8Yv9UgB2aXB3VUPWwd6Oqnn0hycFwhg9pZgWxJXb7JmhsiXe9tmpMwjHFxli12PGcz9aI63YYloGQ==} + engines: {node: '>=18.0.0'} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + 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'} + + ai@6.0.228: + resolution: {integrity: sha512-3TXPF+meV/B0ObVWqLZDfTo0UjT9eKQX+QO5B8n7TSyLxnU3U9FHKxRp7U9mGuTVh7fdo2OtU0J8uGFR4EStsg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + + axios@1.18.1: + resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bath-es5@3.0.3: + resolution: {integrity: sha512-PdCioDToH3t84lP40kUFCKWCOCH389Dl1kbC8FGoqOwamxsmqxxnJSXdkTOsPoNHXjem4+sJ+bbNoQm5zeCqxg==} + + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + + body-parser@1.20.6: + resolution: {integrity: sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + body-parser@2.3.0: + resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} + engines: {node: '>=18'} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + clarinet@0.12.6: + resolution: {integrity: sha512-0FR+TrvLbYHLjhzs9oeIbd3yfZmd4u2DzYQEjUTm2dNfh4Y/9RIRWPjsm3aBtrVEpjKI7+lWa4ouqEXoml84mQ==} + engines: {chrome: '>=16.0.912', firefox: '>=0.8.0', node: '>=0.3.6'} + + class-transformer@0.5.1: + resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} + + class-validator@0.14.4: + resolution: {integrity: sha512-AwNusCCam51q703dW82x95tOqQp6oC9HNUl724KxJJOfnKscI8dOloXFgyez7LbTTKWuRBA37FScqVbJEoq8Yw==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-disposition@1.1.0: + resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} + engines: {node: '>=18'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + content-type@2.0.0: + resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} + engines: {node: '>=18'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + + cross-inspect@1.0.1: + resolution: {integrity: sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A==} + engines: {node: '>=16.0.0'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dereference-json-schema@0.2.2: + resolution: {integrity: sha512-w8dUsJyrzH4Zsj8W/tKcjLsmcTKXfdNf+n3BBm1SAfnqpaCodgEUWqQGJ+pNb9NOqPwYMGvUnZZ8nQfeFjJlbQ==} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + discord-api-types@0.38.50: + resolution: {integrity: sha512-J2n/bpIETX3DQ6AJ7/0xbsTLmYiJQtO/LKcXKC1YDbB56OUwtDbdXOFE8Q4g8jVGHBR2VAy1+D4ngaIgkMNV9w==} + + discord.js@14.27.0: + resolution: {integrity: sha512-qHbFlFG2N7y3LjPySYsL6A1+BnX6bkTVgo842EX0CqVPk/KTMwZkojPHEXKsQUpWZNyz5BISNHK1cPpQw0+m4A==} + engines: {node: '>=18'} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + + dset@3.1.4: + resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} + engines: {node: '>=4'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@2.3.1: + resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + 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'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + eventsource-parser@3.1.0: + resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} + engines: {node: '>=18.0.0'} + + eventsource@3.0.7: + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} + + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + engines: {node: '>=12.0.0'} + + express-rate-limit@8.5.2: + resolution: {integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==} + engines: {node: '>= 16'} + peerDependencies: + express: '>= 4.11' + + express@4.22.2: + resolution: {integrity: sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==} + engines: {node: '>= 0.10.0'} + + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} + engines: {node: '>= 18'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-patch@3.1.1: + resolution: {integrity: sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + fast-uri@3.1.3: + resolution: {integrity: sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + finalhandler@1.3.2: + resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} + engines: {node: '>= 0.8'} + + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} + + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} + engines: {node: '>= 6'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gaxios@7.2.0: + resolution: {integrity: sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg==} + engines: {node: '>=18'} + + gcp-metadata@8.1.2: + resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} + engines: {node: '>=18'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + google-auth-library@10.9.0: + resolution: {integrity: sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg==} + engines: {node: '>=18'} + + google-logging-utils@1.1.3: + resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==} + engines: {node: '>=14'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + grammy@1.44.0: + resolution: {integrity: sha512-gGVykS5+c5f1tPV97LuU6IDRMawE2NzpwM9pNz58HQ35IZXDnYL3VOLvNzYognPSeBIOSzQXRu5w96V0aY8y8A==} + engines: {node: ^12.20.0 || >=14.13.1} + + graphql-query-complexity@0.12.0: + resolution: {integrity: sha512-fWEyuSL6g/+nSiIRgIipfI6UXTI7bAxrpPlCY1c0+V3pAEUo1ybaKmSBgNr1ed2r+agm1plJww8Loig9y6s2dw==} + peerDependencies: + graphql: ^14.6.0 || ^15.0.0 || ^16.0.0 + + graphql-scalars@1.25.0: + resolution: {integrity: sha512-b0xyXZeRFkne4Eq7NAnL400gStGqG/Sx9VqX0A05nHyEbv57UJnWKsjNnrpVqv5e/8N1MUxkt0wwcRXbiyKcFg==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + + graphql-yoga@5.21.2: + resolution: {integrity: sha512-IIRF/3xtjj2D6caAWL9177hQ8tV3mWB3hve1GRnz7njPhQ3iY1jFtSp98fNGv0yV9kaPh9kKQ8JWdJZnedVmDw==} + engines: {node: '>=18.0.0'} + peerDependencies: + graphql: ^15.2.0 || ^16.0.0 + + graphql@16.14.2: + resolution: {integrity: sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + + hono@4.12.30: + resolution: {integrity: sha512-emn+JoJjrN9YTpRDS5it/UI2SO9BAE37T6I3d963RxcZ81G9A4pr2SZTEiiaiKbzx+NKRg5BZ89fCL7gCJCUog==} + engines: {node: '>=16.9.0'} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + 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'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.7.3: + resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ip-address@10.2.0: + resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} + engines: {node: '>= 12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-electron@2.2.2: + resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-network-error@1.3.2: + resolution: {integrity: sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==} + engines: {node: '>=16'} + + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isexe@3.1.5: + resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} + engines: {node: '>=18'} + + jose@5.10.0: + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + + jose@6.2.3: + resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + js-tiktoken@1.0.21: + resolution: {integrity: sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==} + + js-yaml@4.3.0: + resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + hasBin: true + + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + jsonwebtoken@9.0.3: + resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} + engines: {node: '>=12', npm: '>=6'} + + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + + langchain@1.5.3: + resolution: {integrity: sha512-YRYPy1xPq4CgKe0NdPoscYHnKBW5cViEyWiZsUKQfN3xL1X5DpGlIpaBQg1A/t6o9ePKE7J5b7nqrfLz8t7/Rw==} + engines: {node: '>=20'} + peerDependencies: + '@langchain/core': ^1.2.1 + + langsmith@0.8.3: + resolution: {integrity: sha512-3y1PRTmY24wiN8NiMb0CcNI2LwgovsKAz+ymVmBSmUx4nXL+GlmPY6Ju7FGeaPV1DMfQs9SjceNZHIfY2XYMKQ==} + peerDependencies: + '@opentelemetry/api': '*' + '@opentelemetry/exporter-trace-otlp-proto': '*' + '@opentelemetry/sdk-trace-base': '*' + openai: '*' + ws: '>=7' + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@opentelemetry/exporter-trace-otlp-proto': + optional: true + '@opentelemetry/sdk-trace-base': + optional: true + openai: + optional: true + ws: + optional: true + + libphonenumber-js@1.13.8: + resolution: {integrity: sha512-80xal1m93rADejw2pMp2MSzFhHCPLEspjHxnH2UtqI+DgAmElsbmLMiqk9niwH9NWAfjsRtaJI+qBrOEmRx9nQ==} + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. + + lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + + lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + magic-bytes.js@1.13.0: + resolution: {integrity: sha512-afO2mnxW7GDTXMm5/AoN1WuOcdoKhtgXjIvHmobqTD1grNplhGdv3PFOyjCVmrnOZBIT/gD/koDKpYG+0mvHcg==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mustache@4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true + + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + obug@2.1.3: + resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} + engines: {node: '>=12.20.0'} + + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + openai@6.47.0: + resolution: {integrity: sha512-xYr+R9woSzWxVxeiqkkNbHhv89tZDEI6eBMbrdPnv3poh+mijHvbhS35a+3o6xHa411/ns8j5ENY3So9DCXWYw==} + peerDependencies: + '@aws-sdk/credential-provider-node': '>=3.972.0 <4' + '@smithy/hash-node': '>=4.3.0 <5' + '@smithy/signature-v4': '>=5.4.0 <6' + ws: ^8.18.0 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + '@aws-sdk/credential-provider-node': + optional: true + '@smithy/hash-node': + optional: true + '@smithy/signature-v4': + optional: true + ws: + optional: true + zod: + optional: true + + openapi-client-axios@7.9.0: + resolution: {integrity: sha512-1VRBbbNQTz6pAWFALXrqr88GclEb+LirqbzmLnFzqOlnCFC2Ao5Gv4JYf783+A8PQbEAu5Or4Rg32RaetllnwA==} + peerDependencies: + axios: '>=0.25.0' + js-yaml: ^4.1.0 + + openapi-schema-validator@12.1.3: + resolution: {integrity: sha512-xTHOmxU/VQGUgo7Cm0jhwbklOKobXby+/237EG967+3TQEYJztMgX9Q5UE2taZKwyKPUq0j11dngpGjUuxz1hQ==} + + openapi-types@12.1.3: + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + + p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + + p-queue@6.6.2: + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} + + p-queue@9.3.1: + resolution: {integrity: sha512-POWdiIPmsUPGwb4FeQ4OBg46aqmcInSWe45CKDsGHiOBiVQM9chqfQTuqhuTzcg2Vz9faTI65at0KkVyVEiCHw==} + engines: {node: '>=20'} + + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + p-retry@7.1.1: + resolution: {integrity: sha512-J5ApzjyRkkf601HpEeykoiCvzHQjWxPAHhyjFcEUP2SWq0+35NKh8TLhpLw+Dkq5TZBFvUM6UigdE9hIVYTl5w==} + engines: {node: '>=20'} + + p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + + p-timeout@7.0.1: + resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==} + engines: {node: '>=20'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + partial-json@0.1.7: + resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-to-regexp@0.1.13: + resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==} + + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + phoenix@1.8.9: + resolution: {integrity: sha512-/2qzAZB3P2s08fFAYaG65lqaNFmVXUSlXdY4/JDdDKIC81y2cFWkPwI8gycy4VLpv197JwZ5PpBf3VhoG32yGA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-pretty@11.3.0: + resolution: {integrity: sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==} + hasBin: true + + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + + pino@9.14.0: + resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==} + hasBin: true + + pkce-challenge@5.0.1: + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} + engines: {node: '>=16.20.0'} + + playwright-core@1.61.1: + resolution: {integrity: sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.61.1: + resolution: {integrity: sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==} + engines: {node: '>=18'} + hasBin: true + + postcss@8.5.19: + resolution: {integrity: sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ==} + engines: {node: ^10 || ^12 || >=14} + + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + qs@6.15.3: + resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} + engines: {node: '>=0.6'} + + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + range-parser@1.3.0: + resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==} + engines: {node: '>= 0.6'} + + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} + + raw-body@3.0.2: + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} + + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + rolldown@1.1.5: + resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + + 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'} + + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} + + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + engines: {node: '>= 0.8.0'} + + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + sonic-boom@4.2.1: + resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + std-env@4.2.0: + resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + thread-stream@3.2.0: + resolution: {integrity: sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + ts-mixer@6.0.4: + resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsscmp@1.0.6: + resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} + engines: {node: '>=0.6.x'} + + tsx@4.23.1: + resolution: {integrity: sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==} + engines: {node: '>=18.0.0'} + hasBin: true + + type-graphql@2.0.0-rc.1: + resolution: {integrity: sha512-HCu4j3jR0tZvAAoO7DMBT3MRmah0DFRe5APymm9lXUghXA0sbhiMf6SLRafRYfk0R0KiUQYRduuGP3ap1RnF1Q==} + engines: {node: '>= 18.12.0'} + peerDependencies: + class-validator: '>=0.14.0' + graphql: ^16.8.1 + graphql-scalars: ^1.22.4 + peerDependenciesMeta: + class-validator: + optional: true + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + type-is@2.1.0: + resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} + engines: {node: '>= 18'} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + undici@6.27.0: + resolution: {integrity: sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==} + engines: {node: '>=18.17'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + untruncate-json@0.0.1: + resolution: {integrity: sha512-4W9enDK4X1y1s2S/Rz7ysw6kDuMS3VmRjMFg7GZrNO+98OSe+x5Lh7PKYoVjy3lW/1wmhs6HW0lusnQRHgMarA==} + + urlpattern-polyfill@10.1.0: + resolution: {integrity: sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + uuid@11.1.1: + resolution: {integrity: sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==} + hasBin: true + + validator@13.15.35: + resolution: {integrity: sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==} + engines: {node: '>= 0.10'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vite@8.1.4: + resolution: {integrity: sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.3.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + 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'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@5.0.0: + resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.21.1: + resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==} + 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'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} + engines: {node: '>=12'} + + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + + zod@3.24.1: + resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + +snapshots: + + '@ag-ui/a2ui-middleware@0.0.10(@ag-ui/client@0.0.57)(rxjs@7.8.2)': + dependencies: + '@ag-ui/a2ui-toolkit': 0.0.4 + '@ag-ui/client': 0.0.57 + clarinet: 0.12.6 + rxjs: 7.8.2 + + '@ag-ui/a2ui-toolkit@0.0.4': {} + + '@ag-ui/client@0.0.54': + dependencies: + '@ag-ui/core': 0.0.54 + '@ag-ui/encoder': 0.0.54 + '@ag-ui/proto': 0.0.54 + '@types/uuid': 10.0.0 + compare-versions: 6.1.1 + fast-json-patch: 3.1.1 + rxjs: 7.8.2 + untruncate-json: 0.0.1 + uuid: 11.1.1 + zod: 3.25.76 + + '@ag-ui/client@0.0.57': + dependencies: + '@ag-ui/core': 0.0.57 + '@ag-ui/encoder': 0.0.57 + '@ag-ui/proto': 0.0.57 + '@types/uuid': 10.0.0 + compare-versions: 6.1.1 + fast-json-patch: 3.1.1 + rxjs: 7.8.2 + untruncate-json: 0.0.1 + uuid: 11.1.1 + zod: 3.25.76 + + '@ag-ui/core@0.0.52': + dependencies: + zod: 3.25.76 + + '@ag-ui/core@0.0.54': + dependencies: + zod: 3.25.76 + + '@ag-ui/core@0.0.57': + dependencies: + zod: 3.25.76 + + '@ag-ui/encoder@0.0.54': + dependencies: + '@ag-ui/core': 0.0.54 + '@ag-ui/proto': 0.0.54 + + '@ag-ui/encoder@0.0.57': + dependencies: + '@ag-ui/core': 0.0.57 + '@ag-ui/proto': 0.0.57 + + '@ag-ui/langgraph@0.0.42(@ag-ui/client@0.0.57)(@ag-ui/core@0.0.57)(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1)': + dependencies: + '@ag-ui/a2ui-toolkit': 0.0.4 + '@ag-ui/client': 0.0.57 + '@ag-ui/core': 0.0.57 + '@langchain/core': 1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + '@langchain/langgraph-sdk': 1.9.27(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1)) + langchain: 1.5.3(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + partial-json: 0.1.7 + rxjs: 7.8.2 + transitivePeerDependencies: + - '@opentelemetry/api' + - '@opentelemetry/exporter-trace-otlp-proto' + - '@opentelemetry/sdk-trace-base' + - openai + - react + - react-dom + - svelte + - vue + - ws + + '@ag-ui/mcp-apps-middleware@0.0.3(@ag-ui/client@0.0.57)(@cfworker/json-schema@4.1.1)(zod@3.25.76)': + dependencies: + '@ag-ui/client': 0.0.57 + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76) + rxjs: 7.8.2 + transitivePeerDependencies: + - '@cfworker/json-schema' + - supports-color + - zod + + '@ag-ui/mcp-middleware@0.0.1(@cfworker/json-schema@4.1.1)(rxjs@7.8.2)(zod@3.25.76)': + dependencies: + '@ag-ui/client': 0.0.54 + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76) + rxjs: 7.8.2 + transitivePeerDependencies: + - '@cfworker/json-schema' + - supports-color + - zod + + '@ag-ui/proto@0.0.54': + dependencies: + '@ag-ui/core': 0.0.54 + '@bufbuild/protobuf': 2.12.1 + '@protobuf-ts/protoc': 2.11.1 + + '@ag-ui/proto@0.0.57': + dependencies: + '@ag-ui/core': 0.0.57 + '@bufbuild/protobuf': 2.12.1 + '@protobuf-ts/protoc': 2.11.1 + + '@ai-sdk/anthropic@2.0.86(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.29(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/anthropic@3.0.97(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.14 + '@ai-sdk/provider-utils': 4.0.39(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/gateway@3.0.151(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.14 + '@ai-sdk/provider-utils': 4.0.39(zod@3.25.76) + '@vercel/oidc': 3.2.0 + zod: 3.25.76 + + '@ai-sdk/google-vertex@3.0.150(zod@3.25.76)': + dependencies: + '@ai-sdk/anthropic': 2.0.86(zod@3.25.76) + '@ai-sdk/google': 2.0.81(zod@3.25.76) + '@ai-sdk/openai-compatible': 1.0.44(zod@3.25.76) + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.29(zod@3.25.76) + google-auth-library: 10.9.0 + zod: 3.25.76 + transitivePeerDependencies: + - supports-color + + '@ai-sdk/google@2.0.81(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.29(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/google@3.0.94(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.14 + '@ai-sdk/provider-utils': 4.0.39(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/mcp@1.0.62(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.14 + '@ai-sdk/provider-utils': 4.0.39(zod@3.25.76) + pkce-challenge: 5.0.1 + zod: 3.25.76 + + '@ai-sdk/openai-compatible@1.0.44(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.29(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/openai@3.0.85(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.14 + '@ai-sdk/provider-utils': 4.0.39(zod@3.25.76) + zod: 3.25.76 + + '@ai-sdk/provider-utils@3.0.29(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.1.0 + zod: 3.25.76 + + '@ai-sdk/provider-utils@4.0.39(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 3.0.14 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.1.0 + zod: 3.25.76 + + '@ai-sdk/provider@2.0.3': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/provider@3.0.14': + dependencies: + json-schema: 0.4.0 + + '@bufbuild/protobuf@2.12.1': {} + + '@cfworker/json-schema@4.1.1': {} + + '@copilotkit/channels-discord@0.0.3(@ag-ui/core@0.0.57)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))': + dependencies: + '@ag-ui/client': 0.0.57 + '@copilotkit/channels': 0.1.1(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76) + '@copilotkit/channels-ui': 0.1.1(@ag-ui/core@0.0.57) + discord.js: 14.27.0 + zod: 3.25.76 + transitivePeerDependencies: + - '@ag-ui/core' + - bufferutil + - encoding + - utf-8-validate + - vitest + + '@copilotkit/channels-intelligence@0.1.1(@ag-ui/core@0.0.57)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76)': + dependencies: + '@ag-ui/client': 0.0.57 + '@copilotkit/channels': 0.1.1(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76) + '@copilotkit/channels-ui': 0.1.1(@ag-ui/core@0.0.57) + phoenix: 1.8.9 + transitivePeerDependencies: + - '@ag-ui/core' + - encoding + - vitest + - zod + + '@copilotkit/channels-slack@0.1.2(@types/express@5.0.6)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))': + dependencies: + '@ag-ui/client': 0.0.57 + '@ag-ui/core': 0.0.57 + '@copilotkit/channels': 0.1.1(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76) + '@copilotkit/channels-ui': 0.1.1(@ag-ui/core@0.0.57) + '@copilotkit/core': 1.62.3(@ag-ui/core@0.0.57)(zod@3.25.76) + '@copilotkit/shared': 1.62.3(@ag-ui/core@0.0.57) + '@slack/bolt': 4.7.3(@types/express@5.0.6) + '@slack/types': 2.22.0 + '@slack/web-api': 7.19.0 + rxjs: 7.8.2 + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + transitivePeerDependencies: + - '@types/express' + - bufferutil + - debug + - encoding + - supports-color + - utf-8-validate + - vitest + + '@copilotkit/channels-telegram@0.0.4(@ag-ui/core@0.0.57)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))': + dependencies: + '@ag-ui/client': 0.0.57 + '@copilotkit/channels': 0.1.1(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76) + '@copilotkit/channels-ui': 0.1.1(@ag-ui/core@0.0.57) + grammy: 1.44.0 + zod: 3.25.76 + transitivePeerDependencies: + - '@ag-ui/core' + - encoding + - supports-color + - vitest + + '@copilotkit/channels-ui@0.1.1(@ag-ui/core@0.0.57)': + dependencies: + '@copilotkit/shared': 1.62.3(@ag-ui/core@0.0.57) + transitivePeerDependencies: + - '@ag-ui/core' + - encoding + + '@copilotkit/channels-whatsapp@0.0.2(@ag-ui/core@0.0.57)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76)': + dependencies: + '@ag-ui/client': 0.0.57 + '@copilotkit/channels': 0.1.1(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76) + '@copilotkit/channels-ui': 0.1.1(@ag-ui/core@0.0.57) + transitivePeerDependencies: + - '@ag-ui/core' + - encoding + - vitest + - zod + + '@copilotkit/channels@0.1.1(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)))(zod@3.25.76)': + dependencies: + '@ag-ui/client': 0.0.57 + '@ag-ui/core': 0.0.57 + '@copilotkit/channels-ui': 0.1.1(@ag-ui/core@0.0.57) + '@copilotkit/core': 1.62.3(@ag-ui/core@0.0.57)(zod@3.25.76) + '@copilotkit/shared': 1.62.3(@ag-ui/core@0.0.57) + zod-to-json-schema: 3.25.2(zod@3.25.76) + optionalDependencies: + vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)) + transitivePeerDependencies: + - encoding + - zod + + '@copilotkit/core@1.62.3(@ag-ui/core@0.0.57)(zod@3.25.76)': + dependencies: + '@ag-ui/client': 0.0.57 + '@copilotkit/shared': 1.62.3(@ag-ui/core@0.0.57) + '@tanstack/pacer': 0.20.1 + phoenix: 1.8.9 + rxjs: 7.8.2 + zod-to-json-schema: 3.25.2(zod@3.25.76) + transitivePeerDependencies: + - '@ag-ui/core' + - encoding + - zod + + '@copilotkit/license-verifier@0.5.0': {} + + '@copilotkit/runtime@1.62.3(@cfworker/json-schema@4.1.1)(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(@langchain/langgraph-sdk@1.9.27(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1)))(@opentelemetry/api@1.9.1)(langchain@1.5.3(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(openai@6.47.0(ws@8.21.1)(zod@3.25.76))': + dependencies: + '@ag-ui/a2ui-middleware': 0.0.10(@ag-ui/client@0.0.57)(rxjs@7.8.2) + '@ag-ui/client': 0.0.57 + '@ag-ui/core': 0.0.57 + '@ag-ui/encoder': 0.0.57 + '@ag-ui/langgraph': 0.0.42(@ag-ui/client@0.0.57)(@ag-ui/core@0.0.57)(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + '@ag-ui/mcp-apps-middleware': 0.0.3(@ag-ui/client@0.0.57)(@cfworker/json-schema@4.1.1)(zod@3.25.76) + '@ag-ui/mcp-middleware': 0.0.1(@cfworker/json-schema@4.1.1)(rxjs@7.8.2)(zod@3.25.76) + '@ai-sdk/anthropic': 3.0.97(zod@3.25.76) + '@ai-sdk/google': 3.0.94(zod@3.25.76) + '@ai-sdk/google-vertex': 3.0.150(zod@3.25.76) + '@ai-sdk/mcp': 1.0.62(zod@3.25.76) + '@ai-sdk/openai': 3.0.85(zod@3.25.76) + '@copilotkit/license-verifier': 0.5.0 + '@copilotkit/shared': 1.62.3(@ag-ui/core@0.0.57) + '@graphql-yoga/plugin-defer-stream': 3.21.2(graphql-yoga@5.21.2(graphql@16.14.2))(graphql@16.14.2) + '@hono/node-server': 1.19.14(hono@4.12.30) + '@langchain/core': 1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76) + '@remix-run/node-fetch-server': 0.13.3 + '@scarf/scarf': 1.4.0 + '@segment/analytics-node': 2.3.0 + ai: 6.0.228(zod@3.25.76) + clarinet: 0.12.6 + class-transformer: 0.5.1 + class-validator: 0.14.4 + cors: 2.8.6 + express: 4.22.2 + graphql: 16.14.2 + graphql-scalars: 1.25.0(graphql@16.14.2) + graphql-yoga: 5.21.2(graphql@16.14.2) + hono: 4.12.30 + partial-json: 0.1.7 + phoenix: 1.8.9 + pino: 9.14.0 + pino-pretty: 11.3.0 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + type-graphql: 2.0.0-rc.1(class-validator@0.14.4)(graphql-scalars@1.25.0(graphql@16.14.2))(graphql@16.14.2) + uuid: 10.0.0 + ws: 8.21.1 + zod: 3.25.76 + optionalDependencies: + '@langchain/langgraph-sdk': 1.9.27(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1)) + langchain: 1.5.3(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + openai: 6.47.0(ws@8.21.1)(zod@3.25.76) + transitivePeerDependencies: + - '@cfworker/json-schema' + - '@opentelemetry/api' + - '@opentelemetry/exporter-trace-otlp-proto' + - '@opentelemetry/sdk-trace-base' + - bufferutil + - encoding + - react + - react-dom + - supports-color + - svelte + - utf-8-validate + - vue + + '@copilotkit/shared@1.62.3(@ag-ui/core@0.0.57)': + dependencies: + '@ag-ui/client': 0.0.57 + '@ag-ui/core': 0.0.57 + '@copilotkit/license-verifier': 0.5.0 + '@segment/analytics-node': 2.3.0 + '@standard-schema/spec': 1.1.0 + chalk: 4.1.2 + graphql: 16.14.2 + partial-json: 0.1.7 + uuid: 11.1.1 + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + transitivePeerDependencies: + - encoding + + '@discordjs/builders@1.14.1': + dependencies: + '@discordjs/formatters': 0.6.2 + '@discordjs/util': 1.2.0 + '@sapphire/shapeshift': 4.0.0 + discord-api-types: 0.38.50 + fast-deep-equal: 3.1.3 + ts-mixer: 6.0.4 + tslib: 2.8.1 + + '@discordjs/collection@1.5.3': {} + + '@discordjs/collection@2.1.1': {} + + '@discordjs/formatters@0.6.2': + dependencies: + discord-api-types: 0.38.50 + + '@discordjs/rest@2.6.2': + dependencies: + '@discordjs/collection': 2.1.1 + '@discordjs/util': 1.2.0 + '@sapphire/async-queue': 1.5.5 + '@sapphire/snowflake': 3.5.5 + '@vladfrangu/async_event_emitter': 2.4.7 + discord-api-types: 0.38.50 + magic-bytes.js: 1.13.0 + tslib: 2.8.1 + undici: 6.27.0 + + '@discordjs/util@1.2.0': + dependencies: + discord-api-types: 0.38.50 + + '@discordjs/ws@1.2.3': + dependencies: + '@discordjs/collection': 2.1.1 + '@discordjs/rest': 2.6.2 + '@discordjs/util': 1.2.0 + '@sapphire/async-queue': 1.5.5 + '@types/ws': 8.18.1 + '@vladfrangu/async_event_emitter': 2.4.7 + discord-api-types: 0.38.50 + tslib: 2.8.1 + ws: 8.21.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@emnapi/core@1.11.1': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@envelop/core@5.5.1': + dependencies: + '@envelop/instrumentation': 1.0.0 + '@envelop/types': 5.2.1 + '@whatwg-node/promise-helpers': 1.3.2 + tslib: 2.8.1 + + '@envelop/instrumentation@1.0.0': + dependencies: + '@whatwg-node/promise-helpers': 1.3.2 + tslib: 2.8.1 + + '@envelop/types@5.2.1': + dependencies: + '@whatwg-node/promise-helpers': 1.3.2 + tslib: 2.8.1 + + '@esbuild/aix-ppc64@0.28.1': + optional: true + + '@esbuild/android-arm64@0.28.1': + optional: true + + '@esbuild/android-arm@0.28.1': + optional: true + + '@esbuild/android-x64@0.28.1': + optional: true + + '@esbuild/darwin-arm64@0.28.1': + optional: true + + '@esbuild/darwin-x64@0.28.1': + optional: true + + '@esbuild/freebsd-arm64@0.28.1': + optional: true + + '@esbuild/freebsd-x64@0.28.1': + optional: true + + '@esbuild/linux-arm64@0.28.1': + optional: true + + '@esbuild/linux-arm@0.28.1': + optional: true + + '@esbuild/linux-ia32@0.28.1': + optional: true + + '@esbuild/linux-loong64@0.28.1': + optional: true + + '@esbuild/linux-mips64el@0.28.1': + optional: true + + '@esbuild/linux-ppc64@0.28.1': + optional: true + + '@esbuild/linux-riscv64@0.28.1': + optional: true + + '@esbuild/linux-s390x@0.28.1': + optional: true + + '@esbuild/linux-x64@0.28.1': + optional: true + + '@esbuild/netbsd-arm64@0.28.1': + optional: true + + '@esbuild/netbsd-x64@0.28.1': + optional: true + + '@esbuild/openbsd-arm64@0.28.1': + optional: true + + '@esbuild/openbsd-x64@0.28.1': + optional: true + + '@esbuild/openharmony-arm64@0.28.1': + optional: true + + '@esbuild/sunos-x64@0.28.1': + optional: true + + '@esbuild/win32-arm64@0.28.1': + optional: true + + '@esbuild/win32-ia32@0.28.1': + optional: true + + '@esbuild/win32-x64@0.28.1': + optional: true + + '@fastify/busboy@3.2.0': {} + + '@grammyjs/types@3.28.0': {} + + '@graphql-tools/executor@1.5.5(graphql@16.14.2)': + dependencies: + '@graphql-tools/utils': 11.2.0(graphql@16.14.2) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.14.2) + '@repeaterjs/repeater': 3.1.0 + '@whatwg-node/disposablestack': 0.0.6 + '@whatwg-node/promise-helpers': 1.3.2 + graphql: 16.14.2 + tslib: 2.8.1 + + '@graphql-tools/merge@9.2.0(graphql@16.14.2)': + dependencies: + '@graphql-tools/utils': 11.2.0(graphql@16.14.2) + graphql: 16.14.2 + tslib: 2.8.1 + + '@graphql-tools/schema@10.0.36(graphql@16.14.2)': + dependencies: + '@graphql-tools/merge': 9.2.0(graphql@16.14.2) + '@graphql-tools/utils': 11.2.0(graphql@16.14.2) + graphql: 16.14.2 + tslib: 2.8.1 + + '@graphql-tools/utils@10.11.0(graphql@16.14.2)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.14.2) + '@whatwg-node/promise-helpers': 1.3.2 + cross-inspect: 1.0.1 + graphql: 16.14.2 + tslib: 2.8.1 + + '@graphql-tools/utils@11.2.0(graphql@16.14.2)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.14.2) + '@whatwg-node/promise-helpers': 1.3.2 + cross-inspect: 1.0.1 + graphql: 16.14.2 + tslib: 2.8.1 + + '@graphql-typed-document-node/core@3.2.0(graphql@16.14.2)': + dependencies: + graphql: 16.14.2 + + '@graphql-yoga/logger@2.0.1': + dependencies: + tslib: 2.8.1 + + '@graphql-yoga/plugin-defer-stream@3.21.2(graphql-yoga@5.21.2(graphql@16.14.2))(graphql@16.14.2)': + dependencies: + '@graphql-tools/utils': 10.11.0(graphql@16.14.2) + graphql: 16.14.2 + graphql-yoga: 5.21.2(graphql@16.14.2) + + '@graphql-yoga/subscription@5.0.5': + dependencies: + '@graphql-yoga/typed-event-target': 3.0.2 + '@repeaterjs/repeater': 3.1.0 + '@whatwg-node/events': 0.1.2 + tslib: 2.8.1 + + '@graphql-yoga/typed-event-target@3.0.2': + dependencies: + '@repeaterjs/repeater': 3.1.0 + tslib: 2.8.1 + + '@hono/node-server@1.19.14(hono@4.12.30)': + dependencies: + hono: 4.12.30 + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1)': + dependencies: + '@cfworker/json-schema': 4.1.1 + '@standard-schema/spec': 1.1.0 + js-tiktoken: 1.0.21 + langsmith: 0.8.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + mustache: 4.2.0 + p-queue: 6.6.2 + zod: 3.25.76 + transitivePeerDependencies: + - '@opentelemetry/api' + - '@opentelemetry/exporter-trace-otlp-proto' + - '@opentelemetry/sdk-trace-base' + - openai + - ws + + '@langchain/langgraph-checkpoint@1.1.3(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))': + dependencies: + '@langchain/core': 1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + + '@langchain/langgraph-sdk@1.9.27(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))': + dependencies: + '@langchain/core': 1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + '@langchain/protocol': 0.0.18 + '@types/json-schema': 7.0.15 + p-queue: 9.3.1 + p-retry: 7.1.1 + + '@langchain/langgraph@1.4.8(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(zod@3.25.76)': + dependencies: + '@langchain/core': 1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + '@langchain/langgraph-checkpoint': 1.1.3(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1)) + '@langchain/langgraph-sdk': 1.9.27(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1)) + '@langchain/protocol': 0.0.18 + '@standard-schema/spec': 1.1.0 + zod: 3.25.76 + transitivePeerDependencies: + - react + - react-dom + - svelte + - vue + + '@langchain/protocol@0.0.18': {} + + '@lukeed/csprng@1.1.0': {} + + '@lukeed/uuid@2.0.1': + dependencies: + '@lukeed/csprng': 1.1.0 + + '@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.24.1)': + dependencies: + '@hono/node-server': 1.19.14(hono@4.12.30) + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.1.0 + express: 5.2.1 + express-rate-limit: 8.5.2(express@5.2.1) + hono: 4.12.30 + jose: 6.2.3 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 3.24.1 + zod-to-json-schema: 3.25.2(zod@3.24.1) + optionalDependencies: + '@cfworker/json-schema': 4.1.1 + transitivePeerDependencies: + - supports-color + + '@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76)': + dependencies: + '@hono/node-server': 1.19.14(hono@4.12.30) + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.1.0 + express: 5.2.1 + express-rate-limit: 8.5.2(express@5.2.1) + hono: 4.12.30 + jose: 6.2.3 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + optionalDependencies: + '@cfworker/json-schema': 4.1.1 + transitivePeerDependencies: + - supports-color + + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@notionhq/notion-mcp-server@2.4.1(@cfworker/json-schema@4.1.1)(js-yaml@4.3.0)': + dependencies: + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.24.1) + axios: 1.18.1 + express: 4.22.2 + form-data: 4.0.6 + mustache: 4.2.0 + node-fetch: 3.3.2 + openapi-client-axios: 7.9.0(axios@1.18.1)(js-yaml@4.3.0) + openapi-schema-validator: 12.1.3 + openapi-types: 12.1.3 + which: 5.0.0 + yargs: 17.7.3 + zod: 3.24.1 + transitivePeerDependencies: + - '@cfworker/json-schema' + - debug + - js-yaml + - supports-color + + '@opentelemetry/api@1.9.1': {} + + '@oxc-project/types@0.139.0': {} + + '@pinojs/redact@0.4.0': {} + + '@protobuf-ts/protoc@2.11.1': {} + + '@remix-run/node-fetch-server@0.13.3': {} + + '@repeaterjs/repeater@3.1.0': {} + + '@rolldown/binding-android-arm64@1.1.5': + optional: true + + '@rolldown/binding-darwin-arm64@1.1.5': + optional: true + + '@rolldown/binding-darwin-x64@1.1.5': + optional: true + + '@rolldown/binding-freebsd-x64@1.1.5': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.1.5': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-x64-musl@1.1.5': + optional: true + + '@rolldown/binding-openharmony-arm64@1.1.5': + optional: true + + '@rolldown/binding-wasm32-wasi@1.1.5': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.1.5': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.1.5': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@sapphire/async-queue@1.5.5': {} + + '@sapphire/shapeshift@4.0.0': + dependencies: + fast-deep-equal: 3.1.3 + lodash: 4.18.1 + + '@sapphire/snowflake@3.5.5': {} + + '@scarf/scarf@1.4.0': {} + + '@segment/analytics-core@1.8.2': + dependencies: + '@lukeed/uuid': 2.0.1 + '@segment/analytics-generic-utils': 1.2.0 + dset: 3.1.4 + tslib: 2.8.1 + + '@segment/analytics-generic-utils@1.2.0': + dependencies: + tslib: 2.8.1 + + '@segment/analytics-node@2.3.0': + dependencies: + '@lukeed/uuid': 2.0.1 + '@segment/analytics-core': 1.8.2 + '@segment/analytics-generic-utils': 1.2.0 + buffer: 6.0.3 + jose: 5.10.0 + node-fetch: 2.7.0 + tslib: 2.8.1 + transitivePeerDependencies: + - encoding + + '@slack/bolt@4.7.3(@types/express@5.0.6)': + dependencies: + '@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.18.1 + express: 5.2.1 + path-to-regexp: 8.4.2 + raw-body: 3.0.2 + tsscmp: 1.0.6 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + '@slack/logger@4.0.1': + dependencies: + '@types/node': 22.20.1 + + '@slack/oauth@3.0.5': + dependencies: + '@slack/logger': 4.0.1 + '@slack/web-api': 7.19.0 + '@types/jsonwebtoken': 9.0.10 + '@types/node': 22.20.1 + jsonwebtoken: 9.0.3 + transitivePeerDependencies: + - debug + - supports-color + + '@slack/socket-mode@2.0.7': + dependencies: + '@slack/logger': 4.0.1 + '@slack/web-api': 7.19.0 + '@types/node': 22.20.1 + '@types/ws': 8.18.1 + eventemitter3: 5.0.4 + ws: 8.21.1 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + '@slack/types@2.22.0': {} + + '@slack/web-api@7.19.0': + dependencies: + '@slack/logger': 4.0.1 + '@slack/types': 2.22.0 + '@types/node': 22.20.1 + '@types/retry': 0.12.0 + axios: 1.18.1 + eventemitter3: 5.0.4 + form-data: 4.0.6 + is-electron: 2.2.2 + is-stream: 2.0.1 + p-queue: 6.6.2 + p-retry: 4.6.2 + retry: 0.13.1 + transitivePeerDependencies: + - debug + - supports-color + + '@standard-schema/spec@1.1.0': {} + + '@tanstack/ai-event-client@0.6.3(@tanstack/ai@0.32.0(@opentelemetry/api@1.9.1))': + dependencies: + '@tanstack/ai': 0.32.0(@opentelemetry/api@1.9.1) + '@tanstack/devtools-event-client': 0.4.4 + + '@tanstack/ai-event-client@0.6.8': + dependencies: + '@tanstack/devtools-event-client': 0.4.4 + + '@tanstack/ai-mcp@0.1.10(@cfworker/json-schema@4.1.1)(@opentelemetry/api@1.9.1)(zod@3.25.76)': + dependencies: + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76) + '@tanstack/ai': 0.37.0(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - '@cfworker/json-schema' + - '@opentelemetry/api' + - supports-color + - zod + + '@tanstack/ai-openai@0.15.10(@tanstack/ai@0.32.0(@opentelemetry/api@1.9.1))(ws@8.21.1)(zod@3.25.76)': + dependencies: + '@tanstack/ai': 0.32.0(@opentelemetry/api@1.9.1) + '@tanstack/ai-utils': 0.3.1 + '@tanstack/openai-base': 0.9.6(@tanstack/ai@0.32.0(@opentelemetry/api@1.9.1))(ws@8.21.1)(zod@3.25.76) + openai: 6.47.0(ws@8.21.1)(zod@3.25.76) + zod: 3.25.76 + transitivePeerDependencies: + - '@aws-sdk/credential-provider-node' + - '@smithy/hash-node' + - '@smithy/signature-v4' + - ws + + '@tanstack/ai-utils@0.3.1': {} + + '@tanstack/ai@0.32.0(@opentelemetry/api@1.9.1)': + dependencies: + '@ag-ui/core': 0.0.52 + '@standard-schema/spec': 1.1.0 + '@tanstack/ai-event-client': 0.6.3(@tanstack/ai@0.32.0(@opentelemetry/api@1.9.1)) + partial-json: 0.1.7 + optionalDependencies: + '@opentelemetry/api': 1.9.1 + + '@tanstack/ai@0.37.0(@opentelemetry/api@1.9.1)': + dependencies: + '@ag-ui/core': 0.0.52 + '@standard-schema/spec': 1.1.0 + '@tanstack/ai-event-client': 0.6.8 + '@tanstack/ai-utils': 0.3.1 + partial-json: 0.1.7 + optionalDependencies: + '@opentelemetry/api': 1.9.1 + + '@tanstack/devtools-event-client@0.4.4': {} + + '@tanstack/openai-base@0.9.6(@tanstack/ai@0.32.0(@opentelemetry/api@1.9.1))(ws@8.21.1)(zod@3.25.76)': + dependencies: + '@tanstack/ai': 0.32.0(@opentelemetry/api@1.9.1) + '@tanstack/ai-utils': 0.3.1 + openai: 6.47.0(ws@8.21.1)(zod@3.25.76) + transitivePeerDependencies: + - '@aws-sdk/credential-provider-node' + - '@smithy/hash-node' + - '@smithy/signature-v4' + - ws + - zod + + '@tanstack/pacer@0.20.1': + dependencies: + '@tanstack/devtools-event-client': 0.4.4 + '@tanstack/store': 0.9.3 + + '@tanstack/store@0.9.3': {} + + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/body-parser@1.19.6': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.20.1 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 22.20.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.9': {} + + '@types/express-serve-static-core@5.1.2': + dependencies: + '@types/node': 22.20.1 + '@types/qs': 6.15.1 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 + + '@types/express@5.0.6': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 5.1.2 + '@types/serve-static': 2.2.0 + + '@types/http-errors@2.0.5': {} + + '@types/json-schema@7.0.15': {} + + '@types/jsonwebtoken@9.0.10': + dependencies: + '@types/ms': 2.1.0 + '@types/node': 22.20.1 + + '@types/ms@2.1.0': {} + + '@types/node@22.20.1': + dependencies: + undici-types: 6.21.0 + + '@types/qs@6.15.1': {} + + '@types/range-parser@1.2.7': {} + + '@types/retry@0.12.0': {} + + '@types/semver@7.7.1': {} + + '@types/send@1.2.1': + dependencies: + '@types/node': 22.20.1 + + '@types/serve-static@2.2.0': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 22.20.1 + + '@types/uuid@10.0.0': {} + + '@types/validator@13.15.10': {} + + '@types/ws@8.18.1': + dependencies: + '@types/node': 22.20.1 + + '@vercel/oidc@3.2.0': {} + + '@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@4.1.10(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1))': + dependencies: + '@vitest/spy': 4.1.10 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1) + + '@vitest/pretty-format@4.1.10': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.1.10': + dependencies: + '@vitest/utils': 4.1.10 + 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@4.1.10': {} + + '@vitest/utils@4.1.10': + dependencies: + '@vitest/pretty-format': 4.1.10 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + + '@vladfrangu/async_event_emitter@2.4.7': {} + + '@whatwg-node/disposablestack@0.0.6': + dependencies: + '@whatwg-node/promise-helpers': 1.3.2 + tslib: 2.8.1 + + '@whatwg-node/events@0.1.2': + dependencies: + tslib: 2.8.1 + + '@whatwg-node/fetch@0.10.13': + dependencies: + '@whatwg-node/node-fetch': 0.8.6 + urlpattern-polyfill: 10.1.0 + + '@whatwg-node/node-fetch@0.8.6': + dependencies: + '@fastify/busboy': 3.2.0 + '@whatwg-node/disposablestack': 0.0.6 + '@whatwg-node/promise-helpers': 1.3.2 + tslib: 2.8.1 + + '@whatwg-node/promise-helpers@1.3.2': + dependencies: + tslib: 2.8.1 + + '@whatwg-node/server@0.11.0': + dependencies: + '@envelop/instrumentation': 1.0.0 + '@whatwg-node/disposablestack': 0.0.6 + '@whatwg-node/fetch': 0.10.13 + '@whatwg-node/promise-helpers': 1.3.2 + tslib: 2.8.1 + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.0.0 + + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + agent-base@7.1.4: {} + + ai@6.0.228(zod@3.25.76): + dependencies: + '@ai-sdk/gateway': 3.0.151(zod@3.25.76) + '@ai-sdk/provider': 3.0.14 + '@ai-sdk/provider-utils': 4.0.39(zod@3.25.76) + '@opentelemetry/api': 1.9.1 + zod: 3.25.76 + + ajv-formats@2.1.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + array-flatten@1.1.1: {} + + assertion-error@2.0.1: {} + + asynckit@0.4.0: {} + + atomic-sleep@1.0.0: {} + + axios@1.18.1: + dependencies: + follow-redirects: 1.16.0 + form-data: 4.0.6 + https-proxy-agent: 5.0.1 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + - supports-color + + base64-js@1.5.1: {} + + bath-es5@3.0.3: {} + + bignumber.js@9.3.1: {} + + body-parser@1.20.6: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.15.3 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + body-parser@2.3.0: + dependencies: + bytes: 3.1.2 + content-type: 2.0.0 + debug: 4.4.3 + http-errors: 2.0.1 + iconv-lite: 0.7.3 + on-finished: 2.4.1 + qs: 6.15.3 + raw-body: 3.0.2 + type-is: 2.1.0 + transitivePeerDependencies: + - supports-color + + buffer-equal-constant-time@1.0.1: {} + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + chai@6.2.2: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + clarinet@0.12.6: {} + + class-transformer@0.5.1: {} + + class-validator@0.14.4: + dependencies: + '@types/validator': 13.15.10 + libphonenumber-js: 1.13.8 + validator: 13.15.35 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + compare-versions@6.1.1: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-disposition@1.1.0: {} + + content-type@1.0.5: {} + + content-type@2.0.0: {} + + convert-source-map@2.0.0: {} + + cookie-signature@1.0.7: {} + + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cross-inspect@1.0.1: + dependencies: + tslib: 2.8.1 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + data-uri-to-buffer@4.0.1: {} + + dateformat@4.6.3: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + delayed-stream@1.0.0: {} + + depd@2.0.0: {} + + dereference-json-schema@0.2.2: {} + + destroy@1.2.0: {} + + detect-libc@2.1.2: {} + + discord-api-types@0.38.50: {} + + discord.js@14.27.0: + dependencies: + '@discordjs/builders': 1.14.1 + '@discordjs/collection': 1.5.3 + '@discordjs/formatters': 0.6.2 + '@discordjs/rest': 2.6.2 + '@discordjs/util': 1.2.0 + '@discordjs/ws': 1.2.3 + '@sapphire/snowflake': 3.5.5 + discord-api-types: 0.38.50 + fast-deep-equal: 3.1.3 + lodash.snakecase: 4.1.1 + magic-bytes.js: 1.13.0 + tslib: 2.8.1 + undici: 6.27.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + dotenv@16.6.1: {} + + dset@3.1.4: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + ee-first@1.1.1: {} + + emoji-regex@8.0.0: {} + + encodeurl@2.0.0: {} + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@2.3.1: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + 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: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + eventemitter3@4.0.7: {} + + eventemitter3@5.0.4: {} + + events@3.3.0: {} + + eventsource-parser@3.1.0: {} + + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.1.0 + + expect-type@1.4.0: {} + + express-rate-limit@8.5.2(express@5.2.1): + dependencies: + express: 5.2.1 + ip-address: 10.2.0 + + express@4.22.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.6 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.2 + fresh: 0.5.2 + http-errors: 2.0.1 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.13 + proxy-addr: 2.0.7 + qs: 6.15.3 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.2 + serve-static: 1.16.3 + setprototypeof: 1.2.0 + statuses: 2.0.2 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + express@5.2.1: + dependencies: + accepts: 2.0.0 + body-parser: 2.3.0 + content-disposition: 1.1.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.3 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.1 + fresh: 2.0.0 + http-errors: 2.0.1 + merge-descriptors: 2.0.0 + mime-types: 3.0.2 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.15.3 + range-parser: 1.3.0 + router: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 + statuses: 2.0.2 + type-is: 2.1.0 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + extend@3.0.2: {} + + fast-copy@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + fast-json-patch@3.1.1: {} + + fast-safe-stringify@2.1.1: {} + + fast-uri@3.1.3: {} + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + finalhandler@1.3.2: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + finalhandler@2.1.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + follow-redirects@1.16.0: {} + + form-data@4.0.6: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + fresh@2.0.0: {} + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gaxios@7.2.0: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + node-fetch: 3.3.2 + transitivePeerDependencies: + - supports-color + + gcp-metadata@8.1.2: + dependencies: + gaxios: 7.2.0 + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + google-auth-library@10.9.0: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.2.0 + gcp-metadata: 8.1.2 + google-logging-utils: 1.1.3 + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + + google-logging-utils@1.1.3: {} + + gopd@1.2.0: {} + + grammy@1.44.0: + dependencies: + '@grammyjs/types': 3.28.0 + abort-controller: 3.0.0 + debug: 4.4.3 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + - supports-color + + graphql-query-complexity@0.12.0(graphql@16.14.2): + dependencies: + graphql: 16.14.2 + lodash.get: 4.4.2 + + graphql-scalars@1.25.0(graphql@16.14.2): + dependencies: + graphql: 16.14.2 + tslib: 2.8.1 + + graphql-yoga@5.21.2(graphql@16.14.2): + dependencies: + '@envelop/core': 5.5.1 + '@envelop/instrumentation': 1.0.0 + '@graphql-tools/executor': 1.5.5(graphql@16.14.2) + '@graphql-tools/schema': 10.0.36(graphql@16.14.2) + '@graphql-tools/utils': 10.11.0(graphql@16.14.2) + '@graphql-yoga/logger': 2.0.1 + '@graphql-yoga/subscription': 5.0.5 + '@whatwg-node/fetch': 0.10.13 + '@whatwg-node/promise-helpers': 1.3.2 + '@whatwg-node/server': 0.11.0 + graphql: 16.14.2 + lru-cache: 10.4.3 + tslib: 2.8.1 + + graphql@16.14.2: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + help-me@5.0.0: {} + + hono@4.12.30: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + 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 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.7.3: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + inherits@2.0.4: {} + + ip-address@10.2.0: {} + + ipaddr.js@1.9.1: {} + + is-electron@2.2.2: {} + + is-fullwidth-code-point@3.0.0: {} + + is-network-error@1.3.2: {} + + is-promise@4.0.0: {} + + is-stream@2.0.1: {} + + isexe@2.0.0: {} + + isexe@3.1.5: {} + + jose@5.10.0: {} + + jose@6.2.3: {} + + joycon@3.1.1: {} + + js-tiktoken@1.0.21: + dependencies: + base64-js: 1.5.1 + + js-yaml@4.3.0: + dependencies: + argparse: 2.0.1 + + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + + json-schema-traverse@1.0.0: {} + + json-schema-typed@8.0.2: {} + + json-schema@0.4.0: {} + + jsonwebtoken@9.0.3: + dependencies: + jws: 4.0.1 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.8.5 + + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.1: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + + langchain@1.5.3(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1): + dependencies: + '@langchain/core': 1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + '@langchain/langgraph': 1.4.8(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1))(zod@3.25.76) + '@langchain/langgraph-checkpoint': 1.1.3(@langchain/core@1.2.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1)) + langsmith: 0.8.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1) + zod: 3.25.76 + transitivePeerDependencies: + - '@opentelemetry/api' + - '@opentelemetry/exporter-trace-otlp-proto' + - '@opentelemetry/sdk-trace-base' + - openai + - react + - react-dom + - svelte + - vue + - ws + + langsmith@0.8.3(@opentelemetry/api@1.9.1)(openai@6.47.0(ws@8.21.1)(zod@3.25.76))(ws@8.21.1): + dependencies: + p-queue: 6.6.2 + optionalDependencies: + '@opentelemetry/api': 1.9.1 + openai: 6.47.0(ws@8.21.1)(zod@3.25.76) + ws: 8.21.1 + + libphonenumber-js@1.13.8: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lodash.get@4.4.2: {} + + lodash.includes@4.3.0: {} + + lodash.isboolean@3.0.3: {} + + lodash.isinteger@4.0.4: {} + + lodash.isnumber@3.0.3: {} + + lodash.isplainobject@4.0.6: {} + + lodash.isstring@4.0.1: {} + + lodash.merge@4.6.2: {} + + lodash.once@4.1.1: {} + + lodash.snakecase@4.1.1: {} + + lodash@4.18.1: {} + + lru-cache@10.4.3: {} + + magic-bytes.js@1.13.0: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: {} + + media-typer@0.3.0: {} + + media-typer@1.1.0: {} + + merge-descriptors@1.0.3: {} + + merge-descriptors@2.0.0: {} + + methods@1.1.2: {} + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + mime@1.6.0: {} + + minimist@1.2.8: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + mustache@4.2.0: {} + + nanoid@3.3.16: {} + + negotiator@0.6.3: {} + + negotiator@1.0.0: {} + + node-domexception@1.0.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + obug@2.1.3: {} + + on-exit-leak-free@2.1.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + openai@6.47.0(ws@8.21.1)(zod@3.25.76): + optionalDependencies: + ws: 8.21.1 + zod: 3.25.76 + + openapi-client-axios@7.9.0(axios@1.18.1)(js-yaml@4.3.0): + dependencies: + axios: 1.18.1 + bath-es5: 3.0.3 + dereference-json-schema: 0.2.2 + js-yaml: 4.3.0 + openapi-types: 12.1.3 + + openapi-schema-validator@12.1.3: + dependencies: + ajv: 8.20.0 + ajv-formats: 2.1.1(ajv@8.20.0) + lodash.merge: 4.6.2 + openapi-types: 12.1.3 + + openapi-types@12.1.3: {} + + p-finally@1.0.0: {} + + p-queue@6.6.2: + dependencies: + eventemitter3: 4.0.7 + p-timeout: 3.2.0 + + p-queue@9.3.1: + dependencies: + eventemitter3: 5.0.4 + p-timeout: 7.0.1 + + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + p-retry@7.1.1: + dependencies: + is-network-error: 1.3.2 + + p-timeout@3.2.0: + dependencies: + p-finally: 1.0.0 + + p-timeout@7.0.1: {} + + parseurl@1.3.3: {} + + partial-json@0.1.7: {} + + path-key@3.1.1: {} + + path-to-regexp@0.1.13: {} + + path-to-regexp@8.4.2: {} + + pathe@2.0.3: {} + + phoenix@1.8.9: {} + + picocolors@1.1.1: {} + + picomatch@4.0.5: {} + + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@11.3.0: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pump: 3.0.4 + readable-stream: 4.7.0 + secure-json-parse: 2.7.0 + sonic-boom: 4.2.1 + strip-json-comments: 3.1.1 + + pino-std-serializers@7.1.0: {} + + pino@9.14.0: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.1 + thread-stream: 3.2.0 + + pkce-challenge@5.0.1: {} + + playwright-core@1.61.1: {} + + playwright@1.61.1: + dependencies: + playwright-core: 1.61.1 + optionalDependencies: + fsevents: 2.3.2 + + postcss@8.5.19: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + process-warning@5.0.0: {} + + process@0.11.10: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-from-env@2.1.0: {} + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + qs@6.15.3: + dependencies: + es-define-property: 1.0.1 + side-channel: 1.1.1 + + quick-format-unescaped@4.0.4: {} + + range-parser@1.2.1: {} + + range-parser@1.3.0: {} + + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + raw-body@3.0.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.7.3 + unpipe: 1.0.0 + + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + real-require@0.2.0: {} + + reflect-metadata@0.2.2: {} + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + retry@0.13.1: {} + + rolldown@1.1.5: + dependencies: + '@oxc-project/types': 0.139.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.1.5 + '@rolldown/binding-darwin-arm64': 1.1.5 + '@rolldown/binding-darwin-x64': 1.1.5 + '@rolldown/binding-freebsd-x64': 1.1.5 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.5 + '@rolldown/binding-linux-arm64-gnu': 1.1.5 + '@rolldown/binding-linux-arm64-musl': 1.1.5 + '@rolldown/binding-linux-ppc64-gnu': 1.1.5 + '@rolldown/binding-linux-s390x-gnu': 1.1.5 + '@rolldown/binding-linux-x64-gnu': 1.1.5 + '@rolldown/binding-linux-x64-musl': 1.1.5 + '@rolldown/binding-openharmony-arm64': 1.1.5 + '@rolldown/binding-wasm32-wasi': 1.1.5 + '@rolldown/binding-win32-arm64-msvc': 1.1.5 + '@rolldown/binding-win32-x64-msvc': 1.1.5 + + router@2.2.0: + dependencies: + debug: 4.4.3 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.4.2 + transitivePeerDependencies: + - supports-color + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-buffer@5.2.1: {} + + safe-stable-stringify@2.5.0: {} + + safer-buffer@2.1.2: {} + + secure-json-parse@2.7.0: {} + + semver@7.8.5: {} + + send@0.19.2: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.3.0 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.3: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + sonic-boom@4.2.1: + dependencies: + atomic-sleep: 1.0.0 + + source-map-js@1.2.1: {} + + split2@4.2.0: {} + + stackback@0.0.2: {} + + statuses@2.0.2: {} + + std-env@4.2.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + thread-stream@3.2.0: + dependencies: + real-require: 0.2.0 + + tinybench@2.9.0: {} + + tinyexec@1.2.4: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + tinyrainbow@3.1.0: {} + + toidentifier@1.0.1: {} + + tr46@0.0.3: {} + + ts-mixer@6.0.4: {} + + tslib@2.8.1: {} + + tsscmp@1.0.6: {} + + tsx@4.23.1: + dependencies: + esbuild: 0.28.1 + optionalDependencies: + fsevents: 2.3.3 + + type-graphql@2.0.0-rc.1(class-validator@0.14.4)(graphql-scalars@1.25.0(graphql@16.14.2))(graphql@16.14.2): + dependencies: + '@graphql-yoga/subscription': 5.0.5 + '@types/node': 22.20.1 + '@types/semver': 7.7.1 + graphql: 16.14.2 + graphql-query-complexity: 0.12.0(graphql@16.14.2) + graphql-scalars: 1.25.0(graphql@16.14.2) + semver: 7.8.5 + tslib: 2.8.1 + optionalDependencies: + class-validator: 0.14.4 + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + type-is@2.1.0: + dependencies: + content-type: 2.0.0 + media-typer: 1.1.0 + mime-types: 3.0.2 + + typescript@5.9.3: {} + + undici-types@6.21.0: {} + + undici@6.27.0: {} + + unpipe@1.0.0: {} + + untruncate-json@0.0.1: {} + + urlpattern-polyfill@10.1.0: {} + + utils-merge@1.0.1: {} + + uuid@10.0.0: {} + + uuid@11.1.1: {} + + validator@13.15.35: {} + + vary@1.1.2: {} + + vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.5 + postcss: 8.5.19 + rolldown: 1.1.5 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 22.20.1 + esbuild: 0.28.1 + fsevents: 2.3.3 + tsx: 4.23.1 + + vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)): + dependencies: + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1)) + '@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.4.0 + magic-string: 0.30.21 + obug: 2.1.3 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 4.2.0 + tinybench: 2.9.0 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 8.1.4(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@opentelemetry/api': 1.9.1 + '@types/node': 22.20.1 + transitivePeerDependencies: + - msw + + web-streams-polyfill@3.3.3: {} + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@5.0.0: + dependencies: + isexe: 3.1.5 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + ws@8.21.1: {} + + y18n@5.0.8: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.3: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + zod-to-json-schema@3.25.2(zod@3.24.1): + dependencies: + zod: 3.24.1 + + zod-to-json-schema@3.25.2(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod@3.24.1: {} + + zod@3.25.76: {} diff --git a/runtime.ts b/runtime.ts index df0fc74..55c8b7e 100644 --- a/runtime.ts +++ b/runtime.ts @@ -1,24 +1,30 @@ /** - * Agent backend for the Slack triage assistant. + * Agent backend for the KiteBot triage assistant. * - * This is the brain behind the Slack bridge: a single CopilotKit + * This is the brain behind the chat bridge: a single CopilotKit * `BuiltInAgent` (LLM + MCP) served over AG-UI by a `CopilotSseRuntime`. * It replaces the old vendored Python/LangGraph showcase backend — there * is no Python, no `langgraph dev`, no A2UI middleware. Everything is a * few dozen lines of TypeScript. * + * The bridge (`app/index.ts`) fronts this same backend with the + * platform-specific `@copilotkit/channels-*` packages (Slack, Discord, + * Telegram, WhatsApp) and cross-platform `@copilotkit/channels-ui` + * components, so this runtime itself has no platform-specific code. + * * What it does * ------------ * The agent connects to **Linear** and **Notion** via their MCP servers - * and acts as an on-call / triage assistant inside Slack: it pulls and + * and acts as an on-call / triage assistant inside chat: it pulls and * files Linear issues, finds Notion runbooks, and writes incident * threads up as Notion postmortems. The data access is entirely MCP — * the agent discovers the available tools (list/search/create issues, * search/create pages) from each server at runtime. * - * The Slack-side primitives (read_thread, the confirm_write HITL picker, - * the issue/page Block Kit components) are forwarded to the agent as - * client-provided tools by the bridge on every run — see `app/index.ts`. + * The chat-side primitives (read_thread, the confirm_write HITL picker, + * the issue/page @copilotkit/channels-ui components) are forwarded to the + * agent as client-provided tools by the bridge on every run — see + * `app/index.ts`. * * Auth & deployment * ----------------- @@ -35,7 +41,7 @@ * A server is only wired up when its credentials are present, so the bot * runs Linear-only, Notion-only, or both. * - * Exposed route (the bridge's `AGENT_URL`): + * Exposed route (the bridge's `AGENT_URL`, shared by every platform): * POST http://localhost:8200/api/copilotkit/agent/triage/run */ import "dotenv/config"; @@ -129,14 +135,14 @@ async function connectMcp(transport: McpHttpTransport) { if (mcpTransports().length === 0) { console.warn( - "[slack-runtime] No MCP servers configured. Set LINEAR_API_KEY and/or " + + "[runtime] No MCP servers configured. Set LINEAR_API_KEY and/or " + "NOTION_MCP_AUTH_TOKEN in .env — without them the bot can chat and " + "search the web but can't read or write Linear/Notion.", ); } const SYSTEM_PROMPT = [ - "You are an on-call triage assistant living in a Slack workspace. You help", + "You are KiteBot, an on-call triage assistant living in your team's chat workspace. You help", "an engineering team turn incident chatter into tracked work: you pull and", "file Linear issues, find Notion runbooks, and write incident threads up as", "Notion postmortems.", @@ -164,7 +170,7 @@ const SYSTEM_PROMPT = [ " the ~15 most recent and note the rest (e.g. 'showing 15 of 39') instead of", " dumping the whole backlog; a 39-row card is noise, not an answer.", "- Use get_issue for one issue; render it with issue_card.", - "- To act on a Slack conversation (e.g. 'write this thread up'), call the", + "- To act on a chat conversation (e.g. 'write this thread up'), call the", " read_thread tool to fetch the messages first — never invent thread content.", "", "Files & visuals: uploaded files arrive in the message as content you can", @@ -176,7 +182,7 @@ const SYSTEM_PROMPT = [ "column order; set a column's align to 'right' for numeric columns). When", "asked to diagram a flow/architecture/timeline, call render_diagram with", "Mermaid source. render_chart and render_diagram post an image; render_table", - "posts a Slack table. If render_diagram returns an error, fix the Mermaid and", + "posts a table. If render_diagram returns an error, fix the Mermaid and", "retry. These are read/reply actions — no confirm_write needed.", "- render_chart / render_diagram post a TITLED image themselves (a caption", " header followed by the image). Do NOT narrate the act with a separate", @@ -187,7 +193,7 @@ const SYSTEM_PROMPT = [ "- If more than one file is in the thread and the request doesn't make clear", " which one to use, ASK which file (list them by name) instead of guessing.", "", - "Acting per-user: each turn's context names the Requesting Slack user, with", + "Acting per-user: each turn's context names the requesting user, with", 'their name and email. When someone says "my issues", "assigned to me", or', '"file this for me", use that email/name to find their Linear user, then:', "- Querying: filter Linear by that person (assignee), so each user gets THEIR", @@ -239,8 +245,11 @@ const SYSTEM_PROMPT = [ // agent runs on the OpenAI Responses API via TanStack AI's `openaiText` // adapter. Override the model with AGENT_MODEL (a bare OpenAI id, or // "openai/" — the prefix is stripped); defaults to gpt-5.5. The cast is -// needed because AGENT_MODEL is dynamic and `openaiText` types its argument to -// the known OpenAI model literals. +// needed because AGENT_MODEL is a dynamic (env-sourced) string while +// `openaiText` types its argument to the known OpenAI model literal union — +// the cast is a trapdoor around that check, so the env value is NOT validated +// against the union; an unsupported/misspelled model id will only surface as +// an OpenAI API error at request time, not a compile-time or startup check. const model = (process.env["AGENT_MODEL"] ?? "openai/gpt-5.5").replace( /^openai\//, "", @@ -276,9 +285,13 @@ const agent = new BuiltInAgent({ clients.push(result.value); } else { unavailable.push(transports[i]!.name); + const msg = + result.reason instanceof Error + ? result.reason.message + : String(result.reason); console.error( - `[slack-runtime] MCP "${transports[i]!.name}" unavailable this turn:`, - (result.reason as Error)?.message ?? result.reason, + `[runtime] MCP "${transports[i]!.name}" unavailable this turn:`, + msg, ); } }); @@ -293,7 +306,7 @@ const agent = new BuiltInAgent({ ? `\n\nDATA SOURCE STATUS: ${unavailable.join(" and ")} ${isAre} ` + `temporarily UNAVAILABLE this turn (connection failed), so ${itsTheir} ` + `tools are not loaded. Everything else — web search, rendering cards/` + - `charts, reading the Slack thread — still works normally. ONLY if the ` + + `charts, reading the thread — still works normally. ONLY if the ` + `user asks for something that needs ${unavailable.join(" or ")}, tell ` + `them that source is temporarily unreachable and to try again shortly; ` + `never invent data or claim a write/read succeeded.` @@ -308,10 +321,7 @@ const agent = new BuiltInAgent({ // confirm_write HITL) forwarded on every run — passed as client-side // tools so the model can call them and the bot renders/gates them via // the AG-UI client-tool round-trip. MCP tools come in via `mcp` below. - tools: [ - webSearchTool({ type: "web_search" }), - ...(clientTools as never[]), - ], + tools: [webSearchTool({ type: "web_search" }), ...clientTools], ...(clients.length > 0 ? { mcp: { clients } } : {}), // TanStack AI needs the full AbortController (not just the signal). abortController: ctx.abortController, @@ -330,16 +340,22 @@ const listener = createCopilotNodeListener({ }); const port = Number(process.env["PORT"] ?? 8200); +if (!Number.isInteger(port) || port < 1 || port > 65535) { + console.error( + `Invalid PORT: "${process.env["PORT"]}" is not a valid port number`, + ); + process.exit(1); +} createServer(listener).listen(port, () => { console.log( - `[slack-runtime] listening on http://localhost:${port}/api/copilotkit/agent/triage/run`, + `[runtime] listening on http://localhost:${port}/api/copilotkit/agent/triage/run`, ); const connected = [ process.env["LINEAR_API_KEY"] ? "Linear" : null, process.env["NOTION_MCP_AUTH_TOKEN"] ? "Notion" : null, ].filter(Boolean); console.log( - `[slack-runtime] agent "triage" ready · MCP: ${ + `[runtime] agent "triage" ready · MCP: ${ connected.length ? connected.join(", ") : "none" }`, ); diff --git a/scripts/start-notion-mcp.ts b/scripts/start-notion-mcp.ts index b06d02c..945fef9 100644 --- a/scripts/start-notion-mcp.ts +++ b/scripts/start-notion-mcp.ts @@ -49,7 +49,7 @@ const openApiHeaders = JSON.stringify({ // absent from the child env (dotenv loaded it into process.env, so delete it // after the spread) — if present, the server ignores OPENAPI_MCP_HEADERS and // drops the Notion-Version header. -const childEnv = { +const childEnv: NodeJS.ProcessEnv = { ...process.env, OPENAPI_MCP_HEADERS: openApiHeaders, AUTH_TOKEN: authToken, @@ -65,8 +65,6 @@ const child = spawn( "http", "--port", port, - "--auth-token", - authToken, ], { stdio: "inherit", diff --git a/setup.md b/setup.md index ac70b18..eb63d78 100644 --- a/setup.md +++ b/setup.md @@ -1,15 +1,16 @@ # OpenTag — setup & configuration Everything beyond the [quick start](./README.md#quick-start): the full Slack app walkthrough, -the complete environment reference, running standalone vs. from the monorepo, wiring up Linear / -Notion / inline charts / Redis, the other chat platforms, slash commands, tests, and how the -pieces fit together. +the complete environment reference, running standalone vs. from the monorepo, the Intelligence +Gateway channel mode, wiring up Linear / Notion / inline charts, the other chat platforms, +slash commands, tests, and how the pieces fit together. - [How it fits together](#how-it-fits-together) -- [Running it](#running-it) — monorepo today, standalone soon +- [Running it](#running-it) — monorepo or standalone, self-hosted or Intelligence Gateway +- [Intelligence channel mode](#intelligence-channel-mode) - [1. Create a Slack app](#1-create-a-slack-app) - [2. Environment variables](#2-environment-variables) -- [3. Integrations](#3-integrations) — Linear, Notion, charts, Redis +- [3. Integrations](#3-integrations) — Linear, Notion, charts - [Other platforms](#other-platforms) — Discord, Telegram, WhatsApp - [Slash commands](#slash-commands) - [Files → charts, diagrams & tables](#files--charts-diagrams--tables) @@ -18,31 +19,38 @@ pieces fit together. ## How it fits together ``` -Slack / Discord / Telegram / WhatsApp ──@mention──▶ bot (app/) ──AG-UI──▶ runtime (runtime.ts) +Slack / Discord / Telegram / WhatsApp ──@mention──▶ KiteBot (app/) ──AG-UI──▶ runtime (runtime.ts) │ BuiltInAgent (LLM) ├── Linear MCP (hosted) └── Notion MCP (sidecar) ``` Three moving parts: the **chat-platform app(s)** in `app/`, the **agent** (`runtime.ts`), and — -if you use Notion — a small **Notion MCP sidecar**. The bot speaks to the agent over +if you use Notion — a small **Notion MCP sidecar**. KiteBot speaks to the agent over [AG-UI](https://docs.ag-ui.com); the agent is one CopilotKit `BuiltInAgent` (an LLM plus optional MCP tools — no Python, no LangGraph). +KiteBot runs in one of two modes: **self-hosted** (`pnpm dev` → `app/index.ts`, holds the Slack +tokens directly) or **Intelligence Gateway** (`pnpm channel` → `app/managed.ts`, over the +CopilotKit Intelligence Realtime Gateway — see [Intelligence channel +mode](#intelligence-channel-mode)). Both modes talk to the same agent backend +(`pnpm runtime` → `runtime.ts`) via `AGENT_URL`. + | Concept | Where | | -------------------------------------------------------------------- | ------------------------------------------------------------------ | | `createBot({ adapters, agent, tools, context, commands })` | [`app/index.ts`](./app/index.ts) | | Multi-adapter wiring (Slack/Discord/Telegram/WhatsApp, secret-gated) | [`app/index.ts`](./app/index.ts) | | `read_thread` — grounds the agent in the real conversation | [`app/tools/read-thread.ts`](./app/tools/read-thread.ts) | | Render-tools + JSX components (issue card/list, Notion pages) | [`app/tools/render-tools.tsx`](./app/tools/render-tools.tsx), [`app/components/`](./app/components/) | -| Chart / diagram / table rendering (Playwright → PNG) | [`app/tools/render-chart.tsx`](./app/tools/render-chart.tsx), `render-diagram.tsx`, `render-table.tsx`, [`app/render/`](./app/render/) | +| Chart / diagram rendering (Playwright → PNG) | [`app/tools/render-chart.tsx`](./app/tools/render-chart.tsx), `render-diagram.tsx`, [`app/render/`](./app/render/) | +| Table rendering (native `` block, monospace fallback) | [`app/tools/render-table.tsx`](./app/tools/render-table.tsx) | | Status / incident / links showcase cards | [`app/tools/showcase-tools.tsx`](./app/tools/showcase-tools.tsx), [`app/components/_status.ts`](./app/components/_status.ts) | | Blocking **human-in-the-loop** gate (`confirm_write`) | [`app/human-in-the-loop/confirm-write.tsx`](./app/human-in-the-loop/confirm-write.tsx) | | Slash commands (`/agent`, `/triage`, `/preview`, `/file-issue`) | [`app/commands/index.ts`](./app/commands/index.ts) | | A Block Kit **modal** (`/file-issue`) | [`app/modals/file-issue.tsx`](./app/modals/file-issue.tsx) | | The agent backend — one `BuiltInAgent` (LLM + Linear/Notion MCP) | [`runtime.ts`](./runtime.ts) | -- **`app/`** is the platform-agnostic bot. **This is the directory you copy to start your own bot.** +- **`app/`** is the platform-agnostic KiteBot code. **This is the directory you copy to start your own bot.** - **`runtime.ts`** is the agent backend, served over AG-UI. - **`e2e/`** holds live test harnesses (the Slack harness is being migrated to the new `createBot` API; the Telegram harness is a working manual-trigger smoke test — see @@ -50,49 +58,75 @@ optional MCP tools — no Python, no LangGraph). It's built on: -- **[`@copilotkit/bot`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot)** — the platform-agnostic bot engine. -- **[`@copilotkit/bot-slack`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-slack)** / **[`-discord`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-discord)** / **[`-telegram`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-telegram)** / **[`-whatsapp`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-whatsapp)** — the platform adapters. -- **[`@copilotkit/bot-ui`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-ui)** — a cross-platform JSX vocabulary for rich messages (Block Kit on Slack, Components V2 on Discord, HTML on Telegram). +- **[`@copilotkit/channels`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels)** — the platform-agnostic bot engine. +- **[`@copilotkit/channels-slack`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-slack)** / **[`-discord`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-discord)** / **[`-telegram`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-telegram)** / **[`-whatsapp`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-whatsapp)** — the platform adapters. +- **[`@copilotkit/channels-ui`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-ui)** — a cross-platform JSX vocabulary for rich messages (Block Kit on Slack, Components V2 on Discord, HTML on Telegram). +- **[`@copilotkit/channels-intelligence`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/channels-intelligence)** — runs the same KiteBot over the CopilotKit Intelligence Realtime Gateway (Intelligence Gateway mode, no platform tokens in this process). - **[`@copilotkit/runtime`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/runtime)** — the AG-UI agent backend. ## Running it -### From the monorepo (works today) +### From the monorepo -Until the bot SDK packages publish a coherent `0.1.x` set to npm, the dependable path is to run -this code as `examples/slack` inside the -[CopilotKit monorepo](https://github.com/CopilotKit/CopilotKit), which builds the adapters from +If you're working inside the [CopilotKit monorepo](https://github.com/CopilotKit/CopilotKit), +this code runs there as `examples/slack`, building the `@copilotkit/channels*` adapters from source: ```bash pnpm install # repo root pnpm --filter slack-example notion-mcp # only if using Notion → http://127.0.0.1:3001/mcp pnpm --filter slack-example runtime # CopilotKit runtime on :8200, agent "triage" -pnpm --filter slack-example dev # the bot (tsx watch app/index.ts) +pnpm --filter slack-example dev # KiteBot (tsx watch app/index.ts) ``` -### Standalone (once `@copilotkit/bot-*` publish) +### Standalone (npm) -`npm install` here, then run the same three processes via this repo's scripts: +The `@copilotkit/channels*` packages are published on npm, so a plain `npm install` here works +as-is — no monorepo required: ```bash npm install npm run notion-mcp # terminal 1 — only if using Notion npm run runtime # terminal 2 — the agent backend on :8200 -npm run dev # terminal 3 — the bot +npm run dev # terminal 3 — KiteBot, self-hosted (holds the Slack tokens) ``` The chart/diagram renderers need a Chromium binary: `npx playwright install chromium`. -> **Why not standalone yet?** `@copilotkit/bot-telegram`, `-whatsapp`, and `-store-redis` aren't -> on npm yet, and the published bot packages need a coherent `0.1.x` release. The moment they -> land, `npm install` in this repo works as-is. +## Intelligence channel mode + +`pnpm channel` (`app/managed.ts`) runs the same KiteBot over the **CopilotKit Intelligence +Realtime Gateway** instead of a native platform adapter — this process holds **no Slack tokens**; +Intelligence owns the Slack edge (signed ingress + Connector Outbox egress) and streams render +frames back over `@copilotkit/channels-intelligence`. It's the Intelligence Gateway counterpart to +the self-hosted `pnpm dev` mode described above — you still run this process yourself and bring +your own CopilotKit Intelligence project. + +```bash +npm run runtime # terminal 1 — the agent backend on :8200 (same as self-hosted) +npm run channel # terminal 2 — the Intelligence Gateway KiteBot (tsx app/managed.ts) +``` + +Configure it with: + +| Variable | What it's for | +| --- | --- | +| `INTELLIGENCE_GATEWAY_WS_URL` | The Intelligence Realtime Gateway websocket endpoint. | +| `INTELLIGENCE_API_KEY` | Auth for the gateway connection. | +| `INTELLIGENCE_ORG_ID` / `INTELLIGENCE_PROJECT_ID` / `INTELLIGENCE_CHANNEL_ID` | Scopes the connection to your Intelligence org/project/channel. | +| `INTELLIGENCE_CHANNEL_NAME` | The registered channel name (lowercase kebab). Defaults to `kitebot`. | + +The agent backend is still required in this mode — `pnpm runtime` (`runtime.ts`) — the Intelligence +channel host points its `AGENT_URL` at it exactly like the self-hosted KiteBot does. `AGENT_URL` +itself is required in every mode (the process exits at startup if it's unset); `.env.example` ships +it pre-filled with the local runtime URL as a template, not as a code-level default. See +[`.env.example`](./.env.example) for the full annotated list. ## 1. Create a Slack app 1. Go to → **From a manifest** → paste [`slack-app-manifest.yaml`](./slack-app-manifest.yaml). The manifest declares all four slash - commands, the assistant pane, the `users:read.email` scope, and **Socket Mode** (so the bot + commands, the assistant pane, the `users:read.email` scope, and **Socket Mode** (so KiteBot connects outbound — no public URL needed). 2. **OAuth & Permissions** → **Install to Workspace** → copy the `xoxb-` **Bot User OAuth Token** → this is your `SLACK_BOT_TOKEN`. @@ -104,9 +138,10 @@ and summarized under [Other platforms](#other-platforms).) ## 2. Environment variables -Copy the template and fill in the platform(s) and integrations you want — the bot starts an +Copy the template and fill in the platform(s) and integrations you want — KiteBot starts an adapter for each platform whose secrets are present, and the agent wires up whichever data -sources have credentials. +sources have credentials. (Running in [Intelligence channel mode](#intelligence-channel-mode) +instead uses the `INTELLIGENCE_*` variables in place of the platform tokens below.) ```bash cp .env.example .env @@ -115,15 +150,15 @@ cp .env.example .env | Variable | What it's for | | --- | --- | | `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` | Run on Slack (see [step 1](#1-create-a-slack-app)). | -| `OPENAI_API_KEY` | The model. Or set `ANTHROPIC_API_KEY` / `GOOGLE_API_KEY` and `AGENT_MODEL`. | -| `AGENT_MODEL` | `provider/model` override. Defaults to `openai/gpt-5.5`. | +| `OPENAI_API_KEY` | The model. Required — the runtime is OpenAI-only (it runs on the OpenAI Responses API, needed for `web_search`); `ANTHROPIC_API_KEY` / `GOOGLE_API_KEY` are not read by this runtime. | +| `AGENT_MODEL` | OpenAI model id override, optionally prefixed `openai/` (stripped). Defaults to `openai/gpt-5.5`. | | `LINEAR_API_KEY` / `LINEAR_TEAM_KEY` | Wire up Linear (linear.app → Settings → API → Personal API keys). | | `NOTION_TOKEN` / `NOTION_MCP_AUTH_TOKEN` | Wire up Notion (see [Notion](#notion)). | | `DISCORD_BOT_TOKEN` / `DISCORD_APP_ID` | Run on Discord. | | `TELEGRAM_BOT_TOKEN` | Run on Telegram. | | `WHATSAPP_ACCESS_TOKEN` (+ siblings) | Run on WhatsApp Cloud API. | -| `REDIS_URL` | Optional durable store (see [Redis](#redis-persistence)). | -| `AGENT_URL` | Where the bot POSTs (defaults to the local runtime: `…/agent/triage/run`). | +| `INTELLIGENCE_GATEWAY_WS_URL` / `INTELLIGENCE_API_KEY` / `INTELLIGENCE_ORG_ID` / `INTELLIGENCE_PROJECT_ID` / `INTELLIGENCE_CHANNEL_ID` / `INTELLIGENCE_CHANNEL_NAME` | Run in [Intelligence channel mode](#intelligence-channel-mode) instead of holding platform tokens directly. | +| `AGENT_URL` | Where KiteBot POSTs. **Required** — the process exits at startup if unset; the template value points at the local runtime (`…/agent/triage/run`). | Every integration is independent — set only what you need. The full annotated list, including the WhatsApp webhook details, is in [`.env.example`](./.env.example). @@ -168,14 +203,6 @@ The chart/diagram libraries load from a CDN into a **local** headless browser (o `CHART_JS_URL` / `MERMAID_URL`) — your data is rendered locally and never sent to a rendering service. Requires a Chromium binary: `npx playwright install chromium`. -### Redis persistence - -By default, interactive state is in-memory. Pass a -[`@copilotkit/bot-store-redis`](https://github.com/CopilotKit/CopilotKit/tree/main/packages/bot-store-redis) -store to `createBot` (set `REDIS_URL`; `docker compose up -d` starts a local Redis) so an -Approve/Cancel click still resolves **after a restart** — see -[`app/demo-restart.tsx`](./app/demo-restart.tsx) and the `demo:restart` script. - ## Other platforms The same `app/` code runs on every platform — `createBot` takes an array of adapters, and @@ -199,7 +226,7 @@ Four app-owned commands, registered via `createBot({ commands })` - **`/agent `** — a mention-free entry point; runs the agent with the command text. - **`/triage [note]`** — summarizes the conversation and proposes issues to file. -- **`/preview `** — privately previews the issue the bot would file (only you see it); +- **`/preview <title>`** — privately previews the issue KiteBot would file (only you see it); degrades to a DM where ephemerals aren't supported. - **`/file-issue`** — opens a structured issue **modal**; degrades to a conversational flow on platforms without modals (e.g. Telegram). @@ -208,13 +235,15 @@ On Slack, all four must be declared under **Slash Commands** — the manifest al ## Files → charts, diagrams & tables -Upload a file and the bot analyzes it: images and **PDFs** go straight to the model; CSV/JSON/text +Upload a file and KiteBot analyzes it: images and **PDFs** go straight to the model; CSV/JSON/text are decoded and handed over as text. Then ask it to visualize: > chart revenue by month · diagram this incident flow · show it as a table -> **PDFs and images need a vision/document-capable model.** The default `openai/gpt-5.5` reads -> both natively, as do recent Claude and Gemini models. +> **PDFs and images need a vision/document-capable model.** The runtime is OpenAI-only, and the +> default `openai/gpt-5.5` reads both natively. If you override `AGENT_MODEL`, pick another +> vision/document-capable OpenAI model — non-OpenAI model ids (Claude, Gemini, etc.) are not +> supported by this runtime. ## Tests diff --git a/slack-app-manifest.json b/slack-app-manifest.json index 3bd8d0a..eadac88 100644 --- a/slack-app-manifest.json +++ b/slack-app-manifest.json @@ -1,6 +1,6 @@ { "display_information": { - "name": "CopilotKit Triage", + "name": "KiteBot", "description": "On-call triage assistant \u2014 query/file Linear issues and find/write Notion pages from Slack.", "background_color": "#1a1a1a" }, @@ -11,7 +11,7 @@ "messages_tab_read_only_enabled": false }, "bot_user": { - "display_name": "CopilotKit Triage", + "display_name": "KiteBot", "always_online": true }, "assistant_view": { diff --git a/slack-app-manifest.yaml b/slack-app-manifest.yaml index 28f43f3..97e216a 100644 --- a/slack-app-manifest.yaml +++ b/slack-app-manifest.yaml @@ -1,10 +1,10 @@ display_information: - name: CopilotKit Triage + name: KiteBot description: On-call triage assistant — query/file Linear issues and find/write Notion pages from Slack. background_color: "#1a1a1a" features: bot_user: - display_name: CopilotKit Triage + display_name: KiteBot always_online: true # App Home: enable the Messages tab so users can DM the bot (and so the tab # isn't read-only — otherwise Slack shows "Sending messages to this app has diff --git a/tsconfig.json b/tsconfig.json index abddf5f..e736d85 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,8 +14,8 @@ "lib": ["es2022", "dom"], "types": ["node"], "jsx": "react-jsx", - "jsxImportSource": "@copilotkit/bot-ui" + "jsxImportSource": "@copilotkit/channels-ui" }, - "include": ["app/**/*.ts", "app/**/*.tsx", "runtime.ts"], - "exclude": ["node_modules", "agent", "e2e"] + "include": ["app/**/*.ts", "app/**/*.tsx", "runtime.ts", "scripts/**/*.ts"], + "exclude": ["node_modules", "e2e"] } diff --git a/vitest.config.ts b/vitest.config.ts index 2d73ffd..b03a7fd 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,7 +3,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ esbuild: { jsx: "automatic", - jsxImportSource: "@copilotkit/bot-ui", + jsxImportSource: "@copilotkit/channels-ui", }, test: { include: ["app/**/*.test.ts", "app/**/*.test.tsx"],