diff --git a/.env.example b/.env.example index 9f6d59f..29bbc80 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,30 @@ +# Agent settings: place these in apps/agent/.env. +# Use the key for the selected provider; never expose keys to the browser. +ANTHROPIC_API_KEY= OPENAI_API_KEY= -# LLM model — strong models are required for reliable UI generation -# Recommended: gpt-5.4, gpt-5.4-pro, claude-opus-4-6, gemini-3.1-pro -LLM_MODEL=gpt-5.4-2026-03-05 +# chat-latest follows ChatGPT Instant. gpt-* uses OpenAI; claude-* uses Anthropic. +# Model access/availability must be verified with your provider. +# Blank or unsupported model prefixes fail at startup. +# Keys are optional for BYOK-only hosting; visitors enter both keys in the app. +LLM_MODEL=chat-latest + +# Jev selects the renderer and visualization before each new user turn. +TYPESAFE_API_KEY= +JEV_MODEL=jev-latest + +# Frontend settings: place these in apps/app/.env.local. +# LANGGRAPH_DEPLOYMENT_URL defaults to http://localhost:8123. +# LANGGRAPH_DEPLOYMENT_URL=http://localhost:8123 +# MCP_SERVER_URL=http://localhost:3100/mcp + +# Telemetry (docs/telemetry.md): anonymous install counts, on by default. +# Set either to turn it off. +# DO_NOT_TRACK=1 +# COPILOTKIT_TELEMETRY_DISABLED=1 +# OIUI_DISTRIBUTION=self_hosted +# Optional browser page analytics; leave unset unless you want them. +# NEXT_PUBLIC_POSTHOG_KEY= # Rate limiting (per IP) — disabled by default RATE_LIMIT_ENABLED=false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90adaae..9dc6787 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,9 @@ on: schedule: - cron: "0 0 * * *" # Run daily at midnight UTC +permissions: + contents: read + jobs: smoke: name: Smoke / ${{ matrix.os }} / Node ${{ matrix.node }} @@ -20,15 +23,17 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: ${{ matrix.node }} - name: Install pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 - name: Install dependencies (monorepo) run: pnpm install @@ -107,15 +112,17 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: 22 - name: Install pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 - name: Install dependencies run: pnpm install @@ -123,16 +130,40 @@ jobs: - name: Run linting run: pnpm lint + - name: Run tests + run: pnpm test + + agent-tests: + name: Agent tests (pytest) + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false + + - name: Install uv + run: pip install uv + + - name: Sync agent dependencies + working-directory: apps/agent + run: uv sync + + - name: Run pytest + working-directory: apps/agent + run: uv run pytest -q + notify-slack: name: Notify Slack on Failure runs-on: ubuntu-latest - needs: [smoke, lint] + needs: [smoke, lint, agent-tests] if: | failure() && github.event_name == 'schedule' steps: - name: Notify Slack - uses: slackapi/slack-github-action@v2.1.0 + uses: slackapi/slack-github-action@b0fa283ad8fea605de13dc3f449259339835fc52 # v2.1.0 with: webhook: ${{ secrets.SLACK_WEBHOOK_URL }} webhook-type: incoming-webhook diff --git a/.gitignore b/.gitignore index b352c66..cb30952 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,9 @@ bun.lockb # Turbo .turbo +# Telemetry installation id (docs/telemetry.md) +.open-intelligent-ui + # Tools .claude diff --git a/CLAUDE.md b/CLAUDE.md index 6070bc5..d41dcb4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,286 +1,44 @@ -# CopilotKit + LangGraph Todo Demo +# Open Generative UI by CopilotKit -## Purpose +This repository builds a general assistant experience around **answers you can interact with**: understand a topic, compare options, or make a useful tool. It is not primarily a todo-list template. Existing todo and form tools are compatibility examples, not the product's organizing concept. -This repository serves as both a **showcase** and **template** for building AI agents with CopilotKit and LangGraph. It demonstrates how CopilotKit can drive interactive UI beyond just chat, using a **collaborative todo list** as the primary example. +## Boundaries and source of truth -**Target audience:** Developers evaluating CopilotKit or starting new projects with AI agents. +- Frontend: `apps/app/`, Next.js and CopilotKit v2. +- Agent: `apps/agent/main.py`, `src/prompt.py`, `src/model.py`, and `skills/`. +- Custom UI: `apps/app/src/components/generative-ui/open-generative-ui/`. +- Validated host callbacks: `apps/app/src/lib/sandbox/`. +- Standalone MCP: `apps/mcp/`; its HTML assembler and legacy bridge are separate from the web app. +- Shared styling: `packages/design-system/`. -## Core Concept +Use the product name in visible copy. Preserve repository URLs, package names, `openGenerativeUI`, `generateSandboxedUi`, activity/event names, and deployment service names unless a task explicitly migrates them. -The todo list demonstrates **agent-driven UI** where: -- The agent can manipulate application state (adding todos, updating status, organizing tasks) -- Users can interact with the same state (editing titles, checking off tasks, deleting todos) -- Both agent and user changes update the same shared state -- The UI reactively updates based on agent state changes +## Agent behavior -This uses CopilotKit's **v2 agent state pattern** where state lives in the agent and syncs to the frontend. +Choose text for direct answers, native components when their schemas fit, and custom UI when a diagram or interaction helps. There is no mandatory acknowledgement/plan/build/narrate sequence. Distinct sections may use multiple tools; do not repeat a successful build merely because it returned "UI generated". -## Architecture +Label sample assumptions and distinguish user inputs, retrieved evidence, and calculated values. `query_data` returns a metadata envelope with bundled sample CSV rows and does not apply its query. There is no built-in live weather or business-data connection. Never imply a mock form authenticates or persists data. -This is a **Turborepo monorepo** with three apps: +Generated controls must work, validate numerical edge cases, support keyboard access and narrow screens, and expose useful errors. Use the user's selected values when sending a deliberate follow-up. Each follow-up is a new turn/output; do not assume a cross-call patch API or persist iframe state through rerenders. -### Repository Structure +## Streaming contract -``` -apps/ -├── app/ # Next.js frontend -│ ├── src/ -│ │ ├── app/ -│ │ │ ├── page.tsx # Main page - wires up all components -│ │ │ └── api/copilotkit/ # CopilotKit API route -│ │ ├── components/ -│ │ │ ├── canvas/ # Todo list UI -│ │ │ │ ├── index.tsx # Canvas container -│ │ │ │ ├── todo-list.tsx # Todo list with columns -│ │ │ │ ├── todo-column.tsx # Column (pending/completed) -│ │ │ │ └── todo-card.tsx # Individual todo card -│ │ │ ├── example-layout/ # Layout: chat + canvas side-by-side -│ │ │ └── generative-ui/ # Example generative UI components -│ │ └── hooks/ -│ │ ├── use-generative-ui-examples.tsx # Example CopilotKit patterns -│ │ └── use-example-suggestions.tsx # Chat suggestions -├── agent/ # LangGraph Python agent -│ ├── main.py # Agent entry point -│ └── src/ -│ ├── todos.py # Todo tools and state schema -│ └── query.py # Example data query tool -└── mcp/ # MCP (Model Context Protocol) integration -``` - -## Key Pattern: Agent State with CopilotKit v2 - -The todo list uses **CopilotKit v2's agent state pattern** where state lives in the agent backend and syncs bidirectionally with the frontend. - -### How It Works - -1. **Agent defines state schema and tools** (Python) - ```python - # apps/agent/src/todos.py - class Todo(TypedDict): - id: str - title: str - description: str - emoji: str - status: Literal["pending", "completed"] - - class AgentState(TypedDict): - todos: list[Todo] - - @tool - def manage_todos(todos: list[Todo], runtime: ToolRuntime) -> Command: - """Manage the current todos.""" - return Command(update={"todos": todos, ...}) - ``` - -2. **Frontend reads from agent state** - ```typescript - // apps/app/src/components/canvas/index.tsx - const { agent } = useAgent(); - - return ( - agent.setState({ todos: updatedTodos })} - isAgentRunning={agent.isRunning} - /> - ); - ``` - -3. **User interactions update agent state** - ```typescript - // User clicks checkbox → frontend calls agent.setState() - const toggleStatus = (todo) => { - const updated = todos.map(t => - t.id === todo.id ? { ...t, status: t.status === "completed" ? "pending" : "completed" } : t - ); - agent.setState({ todos: updated }); - }; - ``` - -4. **Agent can manipulate state via tools** - - The agent calls `manage_todos` tool to update the todo list - - Both user and agent changes update the same `agent.state.todos` - - Frontend automatically re-renders when state changes - -### Why This Pattern? - -- **Single source of truth**: State lives in the agent, not duplicated in frontend -- **Bidirectional sync**: User changes → agent state, Agent changes → UI update -- **Simple**: No need for separate frontend state management -- **Observable**: Agent has full visibility into state changes - -## Implementation Details - -### Agent Backend - -**Agent Definition** (`apps/agent/main.py`): -```python -from langchain.agents import create_agent -from copilotkit import CopilotKitMiddleware -from src.todos import todo_tools, AgentState - -agent = create_agent( - model="gpt-5.2", - tools=[*todo_tools, ...], # manage_todos, get_todos - middleware=[CopilotKitMiddleware()], - state_schema=AgentState, # Defines state shape - system_prompt="You are a helpful assistant..." -) -``` - -**Todo Tools** (`apps/agent/src/todos.py`): -```python -@tool -def manage_todos(todos: list[Todo], runtime: ToolRuntime) -> Command: - """Manage the current todos.""" - # Ensure todos have unique IDs - for todo in todos: - if "id" not in todo or not todo["id"]: - todo["id"] = str(uuid.uuid4()) - - # Update agent state - return Command(update={ - "todos": todos, - "messages": [ToolMessage(...)] - }) - -@tool -def get_todos(runtime: ToolRuntime): - """Get the current todos.""" - return runtime.state.get("todos", []) -``` - -### Frontend - -**Canvas Component** (`apps/app/src/components/canvas/index.tsx`): -```typescript -export function Canvas() { - const { agent } = useAgent(); // CopilotKit v2 hook - - return ( -
- agent.setState({ todos: updatedTodos })} - // React to agent execution - isAgentRunning={agent.isRunning} - /> -
- ); -} -``` - -**Todo List** (`apps/app/src/components/canvas/todo-list.tsx`): -```typescript -export function TodoList({ todos, onUpdate, isAgentRunning }: TodoListProps) { - const toggleStatus = (todo: Todo) => { - const updated = todos.map((t) => - t.id === todo.id - ? { ...t, status: t.status === "completed" ? "pending" : "completed" } - : t - ); - onUpdate(updated); // Calls agent.setState() - }; - - const addTodo = () => { - const newTodo = { id: crypto.randomUUID(), ... }; - onUpdate([...todos, newTodo]); - }; - - return ( -
- - -
- ); -} -``` - -### How State Flows - -1. **User adds/edits todo** → Frontend calls `agent.setState({ todos: [...] })` -2. **Agent state updates** → CopilotKit syncs to backend -3. **Agent observes change** → Can respond via `manage_todos` tool -4. **Agent modifies todos** → Calls `manage_todos` tool -5. **State syncs to frontend** → `agent.state.todos` updates -6. **UI re-renders** → React sees new state and updates display +Emit `initialHeight`, `placeholderMessages`, `css`, `html`, `jsFunctions`, `jsExpressions` in that order. Styles belong in `css`; functions and invocations use their separate channels. Those JavaScript channels run as classic scripts, so dynamic imports with await belong inside async functions, never at top level. -**Key insight**: State lives in the agent, frontend just reads/writes to it via CopilotKit hooks. +Use the existing validated `Websandbox.connection.remote.sendPrompt({ text })` and HTTPS `openLink({ url })` bridge. Do not replace it with unrestricted parent messages. The sandbox has no same-origin storage or fetch access. Preserve preview isolation, final sandbox initialization, and incremental streaming behavior. -## Tech Stack +## Configuration and checks -- **Frontend**: Next.js 16, React 19, TailwindCSS 4 -- **Agent**: LangGraph (Python), OpenAI GPT-5.2 -- **CopilotKit**: React hooks for agent integration (v2) -- **Monorepo**: Turborepo with pnpm workspaces -- **Other**: MCP (Model Context Protocol) integration, Recharts for generative UI examples - -## Development - -This is a Turborepo monorepo using pnpm workspaces. +The local default model is `chat-latest` (ChatGPT Instant). `claude-*` requires `ANTHROPIC_API_KEY`; `chat-latest` and `gpt-*` require `OPENAI_API_KEY`. Jev routing requires `TYPESAFE_API_KEY`. Do not invent native model APIs or silently change pinned model IDs. See `render.yaml` for its separate explicit deployment model setting. ```bash -# Install dependencies (all apps) pnpm install - -# Start all apps (app, agent, mcp) -pnpm dev - -# Start individually -pnpm dev:app # Next.js frontend on port 3000 -pnpm dev:agent # LangGraph agent on port 8123 -pnpm dev:mcp # MCP server - -# Build all apps -pnpm build - -# Lint all apps +pnpm test +uv run --directory apps/agent pytest pnpm lint +pnpm build ``` -### Environment Setup - -```bash -# Set OpenAI API key for the agent -echo 'OPENAI_API_KEY=your-key-here' > apps/agent/.env -``` - -## Design Principles - -1. **Simple over complex** - The todo list is intentionally simple and focused -2. **CopilotKit v2 patterns** - Uses modern agent state management -3. **Template-first** - Code is meant to be forked and extended -4. **Showcasing agent-driven UI** - Demonstrates AI manipulating application state beyond chat - -## Future Enhancements - -Possible extensions to demonstrate more CopilotKit capabilities: -- Todo categories/tags/priorities -- Agent-driven task organization (auto-categorize, suggest priorities) -- Due dates and reminders -- Subtasks and dependencies -- Export/import todo lists -- Undo/redo with state history -- Real-time collaboration - ---- - -## Key Takeaways for Developers - -**State Management Pattern**: This app uses CopilotKit v2's agent state pattern where: -- State is defined in the agent backend (Python TypedDict) -- Frontend reads via `agent.state.todos` -- Frontend writes via `agent.setState({ todos: ... })` -- Agent can modify state via tools (`manage_todos`) -- Changes sync bidirectionally automatically - -**When extending this template**: -- Define state schema in the agent (`AgentState`) -- Create tools that manipulate state via `Command(update={...})` -- Use `useAgent()` hook in frontend to read/write state -- Let CopilotKit handle the sync - no manual state management needed +Use focused tests while developing, then relevant workspace checks. Inspect the [launch workflow](docs/deployment.md#verification-and-launch) for browser and live-provider validation. A rendered chat shell does not prove AI generation works. Keep secrets out of source, generated UI, logs, and screenshots. Do not describe a local build as a deployed release. -This pattern works great for **agent-driven applications** where the AI needs to manipulate structured application state, not just chat. +See [Architecture](docs/architecture.md) and [Product and agent behavior](docs/interactive-answers.md). diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index bd56e3d..daee366 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,4 +1,4 @@ -# Code of Conduct for Open Generative UI +# Code of Conduct for Open Intelligent UI ## Table of Contents @@ -16,7 +16,7 @@ ## 1. Statement of Purpose -Open Generative UI is an open-source showcase and template for building rich, interactive AI-generated UI with [CopilotKit](https://copilotkit.ai) and [LangGraph](https://langchain-ai.github.io/langgraph/). As part of the CopilotKit ecosystem, our Code of Conduct aims to foster a collaborative, respectful, and innovative community that empowers contributors and users alike. By adhering to this code, we can ensure that our community thrives and remains a welcoming space for everyone. +Open Intelligent UI is an open-source showcase and template for building rich, interactive AI-generated UI with [CopilotKit](https://copilotkit.ai) and [LangGraph](https://langchain-ai.github.io/langgraph/). As part of the CopilotKit ecosystem, our Code of Conduct aims to foster a collaborative, respectful, and innovative community that empowers contributors and users alike. By adhering to this code, we can ensure that our community thrives and remains a welcoming space for everyone. --- @@ -96,7 +96,7 @@ Consequences for violating the Code of Conduct will be determined based on the s This Code of Conduct applies to all participants in the CopilotKit community, including contributors, maintainers, and users, both online and offline. It encompasses interactions in the following areas: -- GitHub discussions and issues on the [open-generative-ui](https://github.com/CopilotKit/open-generative-ui) repository +- GitHub discussions and issues on the [OpenIntelligentUI](https://github.com/CopilotKit/OpenIntelligentUI) repository - The broader [CopilotKit Discord](https://discord.gg/6dffbvGU3D) - Community meetings and events - Social media platforms @@ -112,6 +112,6 @@ This Code of Conduct is adapted from the [CopilotKit Code of Conduct](https://gi ## 9. Get Involved -We invite you to contribute to Open Generative UI! Whether through code, documentation, or community engagement, your participation is invaluable. For more information on how to contribute, please check our [Contributing Guide](./CONTRIBUTING.md). +We invite you to contribute to Open Intelligent UI! Whether through code, documentation, or community engagement, your participation is invaluable. For more information on how to contribute, please check our [Contributing Guide](./CONTRIBUTING.md). Thank you for being part of the CopilotKit community! Together, we can build a safe, respectful, and innovative space for all. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7a5fbb7..27fd03b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,14 +12,14 @@ We love community contributions! That said, we want to make sure we're all on th Investing a lot of time and effort just to find out it doesn't align with the project feels awful, and we don't want that to happen. It also helps to make sure the work you're planning isn't already in progress. -Please file an issue first: [https://github.com/CopilotKit/OpenGenerativeUI/issues](https://github.com/CopilotKit/OpenGenerativeUI/issues) +Please file an issue first: [https://github.com/CopilotKit/OpenIntelligentUI/issues](https://github.com/CopilotKit/OpenIntelligentUI/issues) Or, reach out to us on Discord: https://discord.com/invite/6dffbvGU3D Ready to contribute but seeking guidance? Reach out to us directly on [Discord](https://discord.gg/6dffbvGU3D) for immediate assistance! Alternatively, you're welcome to raise an issue and one of our dedicated maintainers will promptly steer you in the right direction! ## Found a bug? -If you find a bug in the source code, you can help us by [submitting an issue](https://github.com/CopilotKit/OpenGenerativeUI/issues/new) to our GitHub Repository. Even better, you can submit a Pull Request with a fix. +If you find a bug in the source code, you can help us by [submitting an issue](https://github.com/CopilotKit/OpenIntelligentUI/issues/new) to our GitHub Repository. Even better, you can submit a Pull Request with a fix. ## Missing a feature? @@ -29,7 +29,7 @@ So, you've got an awesome feature in mind? Throw it over to us by [creating an i ## Step 1: Make a fork -Fork the [open-generative-ui](https://github.com/CopilotKit/OpenGenerativeUI/issues) repository to your GitHub account. This means that you'll have a copy of the repository under _your-GitHub-username/open-generative-ui_. +Fork the [OpenIntelligentUI](https://github.com/CopilotKit/OpenIntelligentUI) repository to your GitHub account. This means that you'll have a copy of the repository under _your-GitHub-username/OpenIntelligentUI_. ## Step 2: Clone the repository to your local machine @@ -61,10 +61,10 @@ Or manually: ```bash pnpm install -echo 'OPENAI_API_KEY=your-key-here' > apps/agent/.env +echo 'ANTHROPIC_API_KEY=your-key-here' > apps/agent/.env ``` -Then add your real OpenAI API key to `apps/agent/.env`. +Then add your real Anthropic API key to `apps/agent/.env`. ### 3) Run the Project diff --git a/Makefile b/Makefile index 020b7e1..bc30108 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ install: ## Install all dependencies (Node + Python) setup: install ## Full setup: install deps and create .env from template @if [ ! -f apps/agent/.env ]; then \ - echo "OPENAI_API_KEY=your-key-here" > apps/agent/.env; \ - echo "Created apps/agent/.env — add your OpenAI API key"; \ + printf '%s\n' 'OPENAI_API_KEY=' 'TYPESAFE_API_KEY=' 'LLM_MODEL=chat-latest' 'JEV_MODEL=jev-latest' > apps/agent/.env; \ + echo "Created apps/agent/.env — set OPENAI_API_KEY and TYPESAFE_API_KEY"; \ else \ echo "apps/agent/.env already exists, skipping"; \ fi diff --git a/README.md b/README.md index 0d6aa78..26671fa 100644 --- a/README.md +++ b/README.md @@ -1,186 +1,218 @@ -# Open Generative UI +
-An open-source showcase for building rich, interactive AI-generated UI with [CopilotKit](https://copilotkit.ai) and [LangChain Deep Agents](https://docs.langchain.com/oss/python/deepagents/overview). Ask the agent to visualize algorithms, create 3D animations, render charts, or generate interactive diagrams — all rendered as live HTML/SVG inside a sandboxed iframe. +# Open Intelligent UI -https://github.com/user-attachments/assets/ed28c734-e54e-4412-873f-4801da544a7f +### Answers you can interact with. -https://github.com/user-attachments/assets/ba7db70d-07c0-49af-b221-f962f30245e2 +**An open-source chat interface that turns questions into explanations, comparisons, and working tools.** -## What It Does +Built with [CopilotKit](https://github.com/CopilotKit/CopilotKit) and [AG-UI](https://docs.ag-ui.com/introduction). · [Get started](#get-started) · [Overview](#overview) · [Demos](#demo-scenes) · [Architecture](#how-it-works) · [Contributing](CONTRIBUTING.md) -The agent produces **generative UI** — not just text responses, but fully interactive visual components: +[![CI](https://github.com/CopilotKit/OpenIntelligentUI/actions/workflows/ci.yml/badge.svg)](https://github.com/CopilotKit/OpenIntelligentUI/actions/workflows/ci.yml) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -- **Algorithm visualizations** — binary search, BFS vs DFS, sorting algorithms -- **3D animations** — interactive WebGL/CSS3D scenes -- **Charts & diagrams** — pie charts, bar charts, network diagrams -- **Interactive widgets** — forms, simulations, math plots +[![GitHub Trending: #5 Repository Of The Day](https://trendshift.io/api/badge/repositories/24005)](https://trendshift.io/repositories/24005) +[![Trendshift: #3 TypeScript Repository Of The Day](https://trendshift.io/api/badge/trendshift/repositories/24005/daily?language=TypeScript)](https://trendshift.io/repositories/24005) -All visuals are rendered in sandboxed iframes with automatic light/dark theming, progressive reveal animations, and responsive sizing. +Clone the project, connect your model and visualization router, and adapt the interface and agent to your own workflows. -## Quick Start +[**Building with Open Intelligent UI? Talk to an engineer →**](https://www.copilotkit.ai/talk-to-an-engineer?ref=openintelligentui_readme&utm_source=github&utm_medium=readme&utm_campaign=openintelligentui) -```bash -make setup # Install deps + create .env template -# Edit apps/agent/.env with your real OpenAI API key -make dev # Start all services -``` +
-> **Strong models required.** Generative UI demands high-capability models that can produce complex, well-structured HTML/SVG in a single pass. Set `LLM_MODEL` in your `.env` to one of: -> -> | Model | Provider | -> |-------|----------| -> | `gpt-5.4` / `gpt-5.4-pro` | OpenAI | -> | `claude-opus-4-6` | Anthropic | -> | `gemini-3.1-pro` | Google | -> -> Smaller or weaker models will produce broken layouts, missing interactivity, or incomplete visualizations. - -- **App**: http://localhost:3000 -- **Agent**: http://localhost:8123 - -### Available Commands - -| Command | Description | -|---------|-------------| -| `make setup` | Install all dependencies and create `.env` template | -| `make dev` | Start all services (frontend + agent + mcp) | -| `make dev-app` | Start Next.js frontend only | -| `make dev-agent` | Start LangGraph agent only | -| `make dev-mcp` | Start MCP server only | -| `make build` | Build all apps | -| `make lint` | Lint all apps | -| `make clean` | Clean build artifacts | -| `make help` | Show all available commands | - -You can also use `pnpm` directly (`pnpm dev`, `pnpm dev:app`, `pnpm dev:agent`, etc.). - -## MCP Server (Self-Hosted) - -The repo includes a standalone [Model Context Protocol](https://modelcontextprotocol.io) server that exposes the design system, skill instructions, and an HTML document assembler to any MCP-compatible client — including Claude Desktop, Claude Code, and Cursor. - -### What it provides - -- **`assemble_document` tool** — wraps HTML fragments with the full design system CSS and bridge JS, returning an iframe-ready document -- **Skill resources** — browse and read skill instruction documents (`skills://list`, `skills://{name}`) -- **Prompt templates** — pre-composed prompts for widgets, SVG diagrams, and advanced visualizations - -### Claude Desktop (stdio) - -Add to your Claude Desktop config (`claude_desktop_config.json`): - -```json -{ - "mcpServers": { - "open-generative-ui": { - "command": "node", - "args": ["dist/stdio.js"], - "cwd": "/path/to/apps/mcp" - } - } -} -``` +--- + +
+ +
+ +https://github.com/user-attachments/assets/eb1666c1-e177-410b-96eb-9eb5c5534d95 + +
+ +
+ +_The 54-second launch film: ask, explore a 3D explanation, compare options, use a calculator, and follow a coastal itinerary. These are rendered launch scenes; the app runs the agent for each request._ + +## Overview + +Ask a question, explore an idea, compare your options, or make a tool for the moment. The agent chooses a direct text answer, a native component, or a custom interactive UI based on what helps you accomplish the task. + +- **Understand** — explore a mechanism, step through an explanation, or change a variable. +- **Compare** — examine criteria, assumptions, and tradeoffs side by side. +- **Make a tool** — use a calculator, planner, or interactive model with working controls. + +The interface opens directly to chat. Type your request or choose a starter suggestion to begin an agent run. Text, native components, and generated interactive answers appear in the conversation. Sample numbers are illustrations, not live business or weather data. + +## Demo scenes + +From the launch film: explanations, comparisons, working tools, and maps in one conversation. + +### Explore in 3D + +Rotate an airplane with labeled pitch, roll, and yaw axes. Change the angles, play a smooth demonstration, or reset the view. + +
+ +
+ +https://github.com/user-attachments/assets/d0f96662-c8c0-4b25-8c0a-c26b032eb463 + +
+ +
+ +_3D plane · 4 seconds._ + +### Turn comparisons into charts + +Compare exact values in a table, then ask a follow-up to visualize the differences. Jev selects A2UI for basic tables and Open Generative UI for charts and more complex visuals. + +
+ +
+ +https://github.com/user-attachments/assets/36c67a73-ddcf-4d64-b76a-ff659c988836 + +
+ +
+ +_Tables and charts · 8 seconds. Plan names and prices are illustrative._ + +### Make a tool for the moment + +Split a bill with controls for the total, tip, and group size. Calculations update as you change the inputs. + +
+ +
+ +https://github.com/user-attachments/assets/a878a71c-2189-4313-848d-49216b52ce5b + +
-### Claude Code / HTTP clients +
+ +_Bill splitter · 5 seconds._ + +### Follow a trip on the map + +Explore a coastal itinerary with numbered pins and destination photos. The app uses live USGS tiles, credits its photos, and lets you pause, replay, or select a stop. Connections illustrate the itinerary; they are not verified driving directions. + +
+ +
+ +https://github.com/user-attachments/assets/2dd65441-e0e7-4813-891f-9bd476e873d6 + +
+ +
+ +_Coastal map · 4 seconds._ + +
+Scene gallery + +| 3D explanations | Tables → charts | +| --- | --- | +| ![3D airplane with pitch, roll, and yaw controls](https://github.com/user-attachments/assets/b74a1551-a096-4c12-84e8-af79949a2df6) | ![A plan comparison becomes a cost-per-seat chart](https://github.com/user-attachments/assets/6a25cc1d-d401-4914-b4f8-6488f3b17005) | +| Explore aircraft rotation with labeled axes and sliders. | Compare exact values, then visualize them with a follow-up. | + +| Interactive tools | Maps | +| --- | --- | +| ![Bill splitter recalculating the share per person](https://github.com/user-attachments/assets/dea3c40b-025c-4d50-8fef-b14c50e3ca62) | ![California coastal itinerary with numbered map pins and photo cards](https://github.com/user-attachments/assets/098d4aad-95a9-4229-aae6-2de38f1eaa69) | +| Change the group size and tip; the calculation updates. | Follow a coastal itinerary with map pins and destination photos. | + +
+ +## Try it + +- **Animate a coastal trip** — a real USGS map with numbered pins, credited destination photos, and a six-second pin-drop sequence. Pause, replay, or select a stop. Connections are illustrative, not verified driving directions. +- **Pitch, Roll & Yaw** — rotate a 3D airplane with labeled axes, angle controls, smooth demonstrations, and reset. +- **Find your kind of weekend** — compare trip ideas and adjust your preferences. +- **Split the bill fairly** — change the total, tip, and group size in a working calculator. + +These starters run the agent; they are not prerecorded responses. Jev chooses the presentation, so outputs can vary. Map tiles and destination photos require network access. Streaming answers preserve your reading position, reveal text as it enters view, and show the copy action on hover or keyboard focus (always available on touch). + + + +## Get started + +Prerequisites: Node.js 22+, pnpm 9+, Python 3.12+, and [uv](https://docs.astral.sh/uv/). ```bash -# Start the HTTP server -cd apps/mcp && pnpm dev +git clone https://github.com/CopilotKit/OpenIntelligentUI.git +cd OpenIntelligentUI +make setup +# Optional: set shared OPENAI_API_KEY and TYPESAFE_API_KEY in apps/agent/.env +# Or use API keys in the chat header after starting the app +make dev ``` -Add to `.mcp.json`: +Open the [app](http://localhost:3000). The [agent health endpoint](http://localhost:8123/health) confirms the agent service is running. See [Getting started](docs/getting-started.md) for configuration and verification. -```json -{ - "openGenerativeUI": { - "url": "http://localhost:3100/mcp" - } -} -``` +The default model is `chat-latest`, OpenAI’s documented alias for the latest ChatGPT Instant model, requiring `OPENAI_API_KEY`. Jev (`jev-latest`, requiring `TYPESAFE_API_KEY`) selects the renderer and visualization for each user turn. Basic tables use A2UI; charts, diagrams, calculators, and maps use Open Generative UI. Provider failures are surfaced instead of silently substituting another router or model. See [Visualization routing](docs/visualization-routing.md). -See [apps/mcp/README.md](apps/mcp/README.md) for full configuration, Docker deployment, and API reference. +## Use your own API keys -## Architecture +The chat asks for both keys before sending your first message or example prompt and keeps your draft while you set them up. Open **API keys** in the chat header, enter an OpenAI key and a Jev key, then choose **Test connection** and **Save keys**. The connection test makes a small request to each provider. Your keys use `chat-latest` for answers and `jev-latest` for visualization routing, with usage billed to your provider accounts. -Turborepo monorepo with three packages: +Keys stay in browser memory until refresh or **Clear keys**; the app does not save them in browser storage. Requests send them through the application server to their respective providers. They are kept out of chat state and checkpoints, and hosted LangSmith tracing is disabled for requests using your keys. Only use this feature on a deployment whose operator you trust. Saving or clearing keys starts a new chat; **New chat** keeps your keys for the current session. -``` -apps/ -├── app/ Next.js 16 frontend (CopilotKit v2, React 19, Tailwind 4) -├── agent/ Deep Agent (deepagents + CopilotKit middleware, skills-based) -└── mcp/ Standalone MCP server (design system + skills + document assembler) -``` +The agent can run without shared provider keys. Visitors must then supply both keys before chatting. Configured server credentials remain available to direct API clients that omit visitor keys; the chat interface requires visitors to add their own keys. + +## How it works -### Deep Agent + Skills +The Python Deep Agent uses a task-first system prompt and focused skills. CopilotKit carries the agent stream to the Next.js app. Native components handle supported structured tasks; `generateSandboxedUi` streams custom HTML, CSS, and JavaScript into an isolated iframe. -The agent backend uses [LangChain Deep Agents](https://docs.langchain.com/oss/python/deepagents/overview) (`create_deep_agent`) with a skills-based architecture. Instead of injecting all visualization instructions into the system prompt, skills are defined as `SKILL.md` files in `apps/agent/skills/` and loaded on-demand via progressive disclosure: +Custom UI parameters must arrive in this order: +`initialHeight` → `placeholderMessages` → `css` → `html` → `jsFunctions` → `jsExpressions` + +Local controls run inside the sandbox. A user-clicked follow-up can send selected values through the validated host bridge and start another agent turn. Prior outputs remain separate conversation artifacts; there is no cross-call patch API. See [Product and agent behavior](docs/interactive-answers.md) and [Architecture](docs/architecture.md). + +```text +apps/app/ Next.js + CopilotKit frontend +apps/agent/ Python Deep Agent + FastAPI +apps/mcp/ Optional standalone MCP server +packages/design-system/ Shared theme, SVG, and form styles ``` -apps/agent/skills/ -├── advanced-visualization/SKILL.md # UI mockups, dashboards, Chart.js, generative art -├── master-playbook/SKILL.md # Response philosophy, decision trees, narration patterns -└── svg-diagrams/SKILL.md # SVG generation rules, component patterns, diagram types + +## Development + +```bash +make dev-app # Frontend +make dev-agent # Agent +make dev-mcp # Optional MCP server +pnpm test # JavaScript workspace tests +uv run --directory apps/agent pytest +make lint +make build ``` -Deep agents also provide built-in planning (`write_todos`), filesystem tools, and sub-agent support. - -### How It Works - -1. **User sends a prompt** via the CopilotKit chat UI -2. **Deep agent decides** whether to respond with text, call a tool, or render a visual component — consulting relevant skills as needed -3. **`widgetRenderer`** — a frontend `useComponent` hook — receives the agent's HTML and renders it in a sandboxed iframe -4. **Skeleton loading** shows while the iframe loads, then content fades in smoothly -5. **ResizeObserver** inside the iframe reports content height back to the parent for seamless auto-sizing - -### Key CopilotKit Patterns - -| Pattern | Hook | Example | -|---------|------|---------| -| Generative UI | `useComponent` | Pie charts, bar charts, widget renderer | -| Frontend tools | `useFrontendTool` | Theme toggle | -| Human-in-the-loop | `useHumanInTheLoop` | Meeting scheduler | -| Default tool render | `useDefaultRenderTool` | Tool execution status | - -## Decision Matrix — Picking the Right Visual - -| User asks about... | Output type | Technology | -|-----------------------------|--------------------------|---------------------| -| How X works (physical) | Illustrative diagram | SVG | -| How X works (abstract) | Interactive explainer | HTML + inline SVG | -| Process / steps | Flowchart | SVG | -| Architecture / containment | Structural diagram | SVG | -| Database schema / ERD | Relationship diagram | Mermaid | -| Trends over time | Line chart | Chart.js | -| Category comparison | Bar chart | Chart.js | -| Part of whole | Doughnut chart | Chart.js | -| KPIs / metrics | Dashboard | HTML metric cards | -| Design a UI | Mockup | HTML | -| Choose between options | Comparison cards | HTML grid | -| Cyclic process | Step-through | HTML stepper | -| Physics / math | Simulation | Canvas + JS | -| Function / equation | Plotter | SVG + JS | -| Data exploration | Sortable table | HTML + JS | -| Creative / decorative | Art / illustration | SVG | -| 3D visualization | 3D scene | Three.js | -| Music / audio | Synthesizer | Tone.js | -| Network / graph | Force layout | D3.js | -| Quick factual answer | Plain text | None | -| Code solution | Code block | None | -| Emotional support | Warm text | None | - -## Tech Stack - -Next.js 16, React 19, Tailwind CSS 4, LangChain Deep Agents, LangGraph, CopilotKit v2, Turborepo, Recharts - -## Star History - - - - - - Star History Chart - - +The [launch workflow](docs/deployment.md#verification-and-launch) includes browser checks and a real provider smoke test. Tests and builds alone do not verify model access or a deployment. + +## Standalone MCP + +The optional MCP server exposes skill resources, prompt templates, and `assemble_document`. The assembler returns an HTML document as text; a compatible host must render it and implement its bridge. It is distinct from the web app's streaming Websandbox integration. + +See the [MCP server guide](apps/mcp/README.md) for HTTP, stdio, and Docker configuration. + +## Compatibility and documentation + +Built with CopilotKit. The `openGenerativeUI` runtime API and `generateSandboxedUi` tool power the streaming experience. + +- [Documentation index](docs/README.md) +- [Bring these patterns to your app](docs/bring-to-your-app.md) +- [Source repository](https://github.com/CopilotKit/OpenIntelligentUI) +- [Telemetry and how to turn it off](docs/telemetry.md) + +## Contributing + +See [Contributing](CONTRIBUTING.md) for the development workflow and [the documentation index](docs/README.md) for guides to the agent, rendering, and deployment. ## License -MIT +[MIT](LICENSE). diff --git a/apps/agent/main.py b/apps/agent/main.py index 4283880..9fec803 100644 --- a/apps/agent/main.py +++ b/apps/agent/main.py @@ -5,88 +5,60 @@ import os import warnings -from pathlib import Path from dotenv import load_dotenv from fastapi import FastAPI -from copilotkit import CopilotKitMiddleware, LangGraphAGUIAgent +from fastapi.responses import JSONResponse +from copilotkit import CopilotKitMiddleware from ag_ui_langgraph import add_langgraph_fastapi_endpoint from deepagents import create_deep_agent -from langchain_openai import ChatOpenAI +from src.anthropic_compat import ConsecutiveSystemMessagesMiddleware from src.bounded_memory_saver import BoundedMemorySaver +from src.model import build_model, RequestModelMiddleware, CredentialScopedModel +from src.credentials import ( + CredentialsMiddleware, + CredentialScopedAgent, + current_credentials, + validate_credentials, +) +from src.visualization_router import JevVisualizationMiddleware +from src.skill_backend import SKILL_SOURCES, build_agent_backend from src.query import query_data from src.todos import AgentState, todo_tools from src.form import generate_form +from src.trip_images import get_trip_stop_images from src.plan import plan_visualization +from src.prompt import SYSTEM_PROMPT load_dotenv() agent = create_deep_agent( - model=ChatOpenAI(model=os.environ.get("LLM_MODEL", "gpt-5.4-2026-03-05")), - tools=[query_data, plan_visualization, *todo_tools, generate_form], - middleware=[CopilotKitMiddleware()], + model=CredentialScopedModel(fallback=build_model(allow_unconfigured=True)), + tools=[query_data, get_trip_stop_images, plan_visualization, *todo_tools, generate_form], + middleware=[ + RequestModelMiddleware(), + CopilotKitMiddleware(), + JevVisualizationMiddleware(), + ConsecutiveSystemMessagesMiddleware(), + ], context_schema=AgentState, - skills=[str(Path(__file__).parent / "skills")], + skills=SKILL_SOURCES, + backend=build_agent_backend, checkpointer=BoundedMemorySaver(max_threads=200), - system_prompt=""" - You are a helpful assistant that helps users understand CopilotKit and LangGraph used together. - - Be brief in your explanations of CopilotKit and LangGraph, 1 to 2 sentences. - - When demonstrating charts, always call the query_data tool to fetch all data from the database first. - - ## Visual Response Skills - - You have the ability to produce rich, interactive visual responses using the - `widgetRenderer` component. When a user asks you to visualize, explain visually, - diagram, or illustrate something, you MUST use the `widgetRenderer` component - instead of plain text. - - The `widgetRenderer` component accepts three parameters: - - title: A short title for the visualization - - description: A one-sentence description of what the visualization shows - - html: A self-contained HTML fragment with inline - - - -
- - - -
- - ``` -### Math Visualizations -For plotting functions, showing geometric relationships, or exploring equations. +A jsExpression can invoke `setupScene().catch(showSetupError);`. The html must +include an initially readable explanation and an element with id="status". +A ` -``` +Check empty inputs, finite numbers, domain limits, and denominators. HTML min/max +alone do not validate values typed by users. A numeric-input example: -### Sortable / Filterable Data Tables -```html - - - - - - - - - - - - - - - -
NameValueStatus
- - -``` - ---- - -## Part 4: Chart.js — Advanced Patterns - -### Dark Mode Awareness -```javascript -const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches; -const textColor = isDark ? '#c2c0b6' : '#3d3d3a'; -const gridColor = isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)'; -const tooltipBg = isDark ? '#2C2C2A' : '#fff'; -``` - -Canvas cannot read CSS variables — always detect dark mode and use -hardcoded hex values. - -### Wrapper Pattern (Critical for Sizing) -```html -
- -
``` -- Height goes on the wrapper div ONLY, never on canvas. -- Always set `responsive: true, maintainAspectRatio: false`. -- For horizontal bar charts: height = (bars x 40) + 80 pixels. -### Custom Legend (Always Use This) -Disable Chart.js default legend and build HTML: -```javascript -plugins: { legend: { display: false } } -``` -```html -
- - Series A — 65% - - - Series B — 35% - -
-``` - -### Dashboard Layout -Metric cards on top -> chart below -> sendPrompt for drill-down: -```html - -
- -
- - -
- -
-``` - -### Chart Type Selection Guide -| Data pattern | Chart type | -|----------------------------|---------------------| -| Trend over time | Line | -| Category comparison | Vertical bar | -| Ranking (few items) | Horizontal bar | -| Part of whole | Doughnut | -| Distribution | Histogram (bar) | -| Correlation (2 variables) | Scatter | -| Multi-variable comparison | Radar | -| Range / uncertainty | Line with fill area | - ---- - -## Part 5: Generative Art and Illustration - -For when the user asks for something creative, decorative, or aesthetic. - -### When to Use -- "Draw me a sunset" / "Create a pattern" -- Decorative headers or visual breaks -- Mood illustrations for creative writing -- Abstract visualizations of data or music - -### Rules (Different from Diagrams) -- Fill the canvas — art should feel rich, not sparse -- Bold colors are encouraged. You can use custom hex freely. -- Layered overlapping shapes create depth -- Organic forms with `` curves, ``, `` -- Texture via repetition (hatching, dots, parallel lines) -- Geometric patterns with `` -- NO gradients, shadows, blur, or glow (still flat aesthetic) - -### Pattern: Geometric Art -```svg - - - - - - - - - - - - - -``` - -### Pattern: Radial Symmetry -```svg - - - - - - - - - - - - -``` - -### Pattern: Landscape with Layered Shapes -For physical scenes, use ALL hardcoded hex (no theme classes): -```svg - - - - - - - - - - - -``` - ---- - -## Part 6: Advanced Patterns - -### Tabbed / Multi-View Interfaces -Since content streams top-down, don't use `display: none` during streaming. -Instead, render all content stacked, then use post-stream JS to create tabs: - -```html -
- - - -
- -
-
-
- - -``` - -### sendPrompt() — Chat-Driven Interactivity -A global function that sends a message as if the user typed it. -Use it when the user's next action benefits from AI thinking: - -```html - - ``` -**Use for**: drill-downs, follow-up questions, "explain this part". -**Don't use for**: filtering, sorting, toggling — handle those in JS. -Append ` ↗` to button text when it triggers sendPrompt. - -### Responsive Grid Pattern -```css -display: grid; -grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); -gap: 12px; -``` -Use `minmax(0, 1fr)` if children have large min-content that could overflow. - -### CSS Animations (Subtle and Purposeful) -```css -/* Only animate transform and opacity for performance */ -@keyframes fadeSlideIn { - from { opacity: 0; transform: translateY(8px); } - to { opacity: 1; transform: translateY(0); } -} - -/* Always respect user preferences */ -@media (prefers-reduced-motion: reduce) { - *, *::before, *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - } -} - -/* Flowing particles / convection currents */ -@keyframes flow { to { stroke-dashoffset: -20; } } -.flowing { - stroke-dasharray: 5 5; - animation: flow 1.6s linear infinite; -} - -/* Pulsing for active elements */ -@keyframes pulse { - 0%, 100% { opacity: 0.3; } - 50% { opacity: 0.7; } -} -``` - ---- - -## Part 7: External Libraries (CDN Allowlist) - -Only these CDN origins work (CSP-enforced): -- `cdnjs.cloudflare.com` -- `esm.sh` -- `cdn.jsdelivr.net` -- `unpkg.com` - -### Useful Libraries - -**Chart.js** (data visualization): -```html - -``` - -**Three.js** (3D graphics) — use ES module import (import map resolves bare specifiers): -```html - -``` -Alternative UMD (global `THREE` variable): -```html - -``` - -**D3.js** (advanced data viz, force layouts, geographic maps): -```html - -``` - -**Mermaid** (ERDs, sequence diagrams, class diagrams): -```html - -``` - -**Tone.js** (audio synthesis): -```html - -``` - -### Three.js Coordinate Conventions - -Three.js uses a **right-handed Y-up** coordinate system: -- **X** = right (positive) / left (negative) -- **Y** = up (positive) / down (negative) -- **Z** = toward the viewer (positive) / away from the viewer (negative) - -**Critical for vehicles and aircraft:** The fuselage/body extends along **Z** (nose at -Z, tail at +Z). Wings extend along **X** (left/right). The vertical stabilizer extends along **Y**. - -When building an aircraft from primitives: -- **Fuselage** = cylinder or box, long axis along **Z** (use `geometry` default or rotate 90° around X) -- **Wings** = flat box, wide along **X**, thin along **Y**, short along **Z** -- **Tail fin** = flat box, tall along **Y**, thin along **X**, short along **Z** - -```javascript -// Correct aircraft orientation example: -// Fuselage along Z -const fuselage = new THREE.Mesh( - new THREE.CylinderGeometry(0.15, 0.08, 2.0, 12), - material -); -fuselage.rotation.x = Math.PI / 2; // CylinderGeometry default is Y-up, rotate to Z-forward - -// Wings along X -const wing = new THREE.Mesh( - new THREE.BoxGeometry(2.5, 0.03, 0.4), // wide X, thin Y, short Z - material -); - -// Vertical stabilizer along Y -const tailFin = new THREE.Mesh( - new THREE.BoxGeometry(0.03, 0.4, 0.3), // thin X, tall Y, short Z - material -); -tailFin.position.set(0, 0.2, 0.9); // above and behind -``` - -**Rotation axes for flight dynamics:** -- **Pitch** = rotation around **X** (nose up/down) -- **Roll** = rotation around **Z** (wings tilt) -- **Yaw** = rotation around **Y** (nose left/right) - -**Common mistake:** Using the wing box as the fuselage (wide along X instead of Z). Always verify: the longest dimension of the fuselage should be along Z. - ---- - -## Part 8: Quality Checklist - -Before producing any visual, run through this: - -### Functional -- [ ] Does it work without JavaScript during streaming? (Content visible) -- [ ] Do all interactive controls have event handlers? -- [ ] Are all displayed numbers rounded properly? -- [ ] Does the canvas/SVG fit within the container width? - -### Visual -- [ ] Dark mode test: would every element be readable on near-black? -- [ ] No hardcoded text colors in HTML (use CSS variables) -- [ ] No gradients, shadows, blur, or glow -- [ ] Borders are 0.5px (except 2px for featured item accent) -- [ ] Font weights are only 400 or 500 -- [ ] All text is sentence case - -### Content -- [ ] Explanatory text is in the response, not inside the widget -- [ ] No titles or headings embedded in the HTML output -- [ ] Visual is self-explanatory without reading the narration -- [ ] Narration adds value beyond what the visual shows -- [ ] Offered a clear "go deeper" path - -### Accessibility -- [ ] `@media (prefers-reduced-motion: reduce)` for all animations -- [ ] Text contrast is sufficient (dark text on light fills, vice versa) -- [ ] Interactive elements are large enough to click (min 44px touch target) -- [ ] No information conveyed by color alone - ---- - -## Part 9: Decision Matrix — Picking the Right Visual - -| User asks about... | Output type | Technology | -|-----------------------------|--------------------------|---------------------| -| How X works (physical) | Illustrative diagram | SVG | -| How X works (abstract) | Interactive explainer | HTML + inline SVG | -| Process / steps | Flowchart | SVG | -| Architecture / containment | Structural diagram | SVG | -| Database schema / ERD | Relationship diagram | Mermaid | -| Trends over time | Line chart | Chart.js | -| Category comparison | Bar chart | Chart.js | -| Part of whole | Doughnut chart | Chart.js | -| KPIs / metrics | Dashboard | HTML metric cards | -| Design a UI | Mockup | HTML | -| Choose between options | Comparison cards | HTML grid | -| Cyclic process | Step-through | HTML stepper | -| Physics / math | Simulation | Canvas + JS | -| Function / equation | Plotter | SVG + JS | -| Data exploration | Sortable table | HTML + JS | -| Creative / decorative | Art / illustration | SVG | -| 3D visualization | 3D scene | Three.js | -| Music / audio | Synthesizer | Tone.js | -| Network / graph | Force layout | D3.js | -| Quick factual answer | Plain text | None | -| Code solution | Code block | None | -| Emotional support | Warm text | None | +Fit all stops once. Keep the camera steady while playing so the user can follow +the sequential pin drops; do not fly between stops or auto-scroll the chat. In activateStop, +only update classes/aria-current if the index changed. On arrival, keep the active +card visible by setting the horizontal card strip's scrollLeft to the card's +offsetLeft minus the strip's offsetLeft, clamped to the strip's scrollable range. +Do this only on stop changes, never per frame. Never use scrollIntoView during autoplay. A manual +pin/card click calls controller.seek(index), highlights the card and may gently +pan the map (no animation for reduced motion). Include visible Pause/Resume and +Replay buttons and a polite text status updated only when the active stop changes. +Disable Pause at completion; Replay restarts from the first stop. + +Start once after at least one successful basemap tile load and after wiring all +controls, not on every tile event. Respect prefers-reduced-motion: the controller +shows the completed route without autoplay. It pauses when the page becomes +hidden and cleans up on pagehide. Offscreen content must never scroll itself into +view; a user scrolling back to a paused tour can press Resume. Keep the default sequence around six seconds, and do not loop indefinitely. Handle errors in the ordinary visible status. diff --git a/apps/agent/skills/master-playbook/SKILL.md b/apps/agent/skills/master-playbook/SKILL.md index e18be59..d4a2388 100644 --- a/apps/agent/skills/master-playbook/SKILL.md +++ b/apps/agent/skills/master-playbook/SKILL.md @@ -1,438 +1,101 @@ --- -name: "Master Agent Playbook" -description: "Philosophy, decision-making framework, and technical skills for delivering visual, interactive, and educational AI responses." +name: "master-playbook" +description: "Choose text, native components, or a custom interactive answer for understanding, comparing, and making tools." allowed-tools: [] --- -# Master Agent Playbook: Making AI Responses Extraordinary +# Open Generative UI response playbook -This playbook teaches an AI coding agent how to go beyond plain text and deliver -responses that are visual, interactive, and deeply educational. It covers the -philosophy, decision-making, and technical skills needed. +Answer the task directly. Use text for a short answer, writing, or code; A2UI Table for basic tabular answers; generateSandboxedUi for charts, diagrams +and custom interaction. Follow Jev’s renderer and visualization decision. Native rendering is not evidence of live data. ---- - -## Part 1: The Core Philosophy - -### Think Like a Teacher, Not a Search Engine - -Bad: "A load path is the route that forces take through a structure to the ground." -Good: [draws an interactive building cross-section with loads flowing downward] - -The principle: **Show, don't just tell.** Before writing any response, ask: -- Would a diagram make this click faster than a paragraph? -- Would an interactive widget let the user explore the concept themselves? -- Would a worked example teach better than a definition? - -### The Response Decision Tree +- Understand: show relationships or mechanisms, with a meaningful variable or stepper. +- Compare: make criteria and assumptions visible; use a table for simple cases, + editable weights or filters only when they help a decision. +- Make a tool: deliver working controls, validated calculations, outputs, and reset. -``` -User asks a question - | - +- Is it a quick factual answer? -> Answer in 1-2 sentences. - | - +- Is it conceptual / "how does X work"? - | +- Is it spatial or visual? -> SVG illustrative diagram - | +- Is it a process/flow? -> SVG flowchart or HTML stepper - | +- Is it data-driven? -> Interactive chart (Chart.js / Recharts) - | +- Is it abstract but explorable? -> Interactive HTML widget with controls - | - +- Is it "build me X"? -> Working code artifact, fully functional - | - +- Is it a comparison? -> Side-by-side table or comparative visual - | - +- Is it emotional/personal? -> Warm text response. No visuals needed. -``` - -### The 3-Layer Response Pattern +There is no mandatory acknowledgement/plan/build/narrate sequence. +plan_visualization is optional. Multiple distinct sections are welcome when needed; +avoid duplicate builds after a successful "UI generated" result. Add prose only +when it helps. A refinement uses the current request and explicit selections; no +cross-call patch or expression-append API is provided. -Great responses layer information: +## Data and assumptions -1. **Hook** (1-2 sentences): Validate the question, set context. -2. **Visual** (diagram/widget): The core explanation, rendered visually. -3. **Narration** (2-4 paragraphs): Walk through the visual, add nuance, - connect to what the user already knows. Offer to go deeper. - -Never dump a visual without narration. Never narrate without visuals -when visuals would help. - ---- +Label user data, retrieved sources, calculated results, and illustrative values. +The query_data tool returns all rows of bundled sample db.csv, without filtering. +It is not a live database and is unnecessary for unrelated charts. Never invent +current weather, prices, or business data. Ask for essential missing inputs or +provide clearly labeled sample assumptions. Show units and calculation assumptions +inside the UI. Do not create credential forms or claim external actions succeeded. -## Part 2: Skill — Interactive HTML Widgets +## Tool contract -For concepts that benefit from user exploration. More powerful than -static SVGs — users can manipulate parameters and see results. +For generateSandboxedUi, emit these parameters in this EXACT order: -### When to Use -- The concept has a variable the user could tweak (temperature, rate, count) -- The system has states the user could toggle (on/off, mode A/B) -- The explanation benefits from stepping through stages -- Data exploration or filtering is involved +1. initialHeight — estimated finished height. +2. placeholderMessages — 2-4 short progress messages. +3. css — all styles. The placeholder remains until css is complete; keep the css parameter lean. +4. html — readable body markup, no style blocks or monolithic scripts. +5. jsFunctions — named behavior functions. +6. jsExpressions — small synchronous invocations. -### Template: Interactive Widget with Controls +The sandbox has no same-origin access: no localStorage, sessionStorage, cookies, +IndexedDB, or same-origin fetch. No parent DOM access. Theme variables, form styles, +and SVG color classes are pre-injected. An importmap supports three, gsap, d3, +and chart.js. jsFunctions and jsExpressions are classic scripts: top-level await +is invalid. Dynamic imports belong inside an async function; catch failures. +The advanced skill covers libraries and responsive rendering. -```html - +## Functional and accessible answers - - - - - +Use semantic headings, labels connected to inputs, keyboard-operable buttons, +visible focus, and readable text. Let layouts wrap at phone widths; use responsive +SVG viewBox or canvas containers. Keep content readable during streaming before +JavaScript arrives. Respect reduced motion and provide pause/reset for animation. - -
- -
+Validate number inputs with valueAsNumber, Number.isFinite, and domain bounds. +Reject blanks and zero divisors; never display NaN/Infinity or a stale result as a +valid answer. Format units and precision. Reset controls and results consistently. +Sorting should preserve the current filter. Every enabled control must do real work. +Use textContent for untrusted data, not HTML string interpolation. - -``` +## Follow-up bridge -### Template: Step-Through Explainer +Local controls run in JavaScript. User-clicked follow-ups can ask the agent for +reasoning through Websandbox.connection.remote.sendPrompt. Include current values +in the request; label the button as an action that sends a message. Never send on +load, timers, or ordinary input changes. Do not send secrets. -For cyclic or staged processes (event loops, biological cycles, pipelines). +html parameter: ```html - - -
- -
- -
- -
- - Step 1 of 4 -
- - + +

``` -### CSS Animation Patterns (for live diagrams) - -```css -/* Flowing particles along a path */ -@keyframes flow { - to { stroke-dashoffset: -20; } -} -.flowing { - stroke-dasharray: 5 5; - animation: flow 1.6s linear infinite; -} - -/* Pulsing glow for active elements */ -@keyframes pulse { - 0%, 100% { opacity: 0.3; } - 50% { opacity: 0.7; } -} -.pulsing { animation: pulse 2s ease-in-out infinite; } - -/* Flickering (for flames, sparks) */ -@keyframes flicker { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.8; } -} - -/* Always respect reduced motion preferences */ -@media (prefers-reduced-motion: reduce) { - *, *::before, *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; +jsFunctions parameter (replace scenario text with the validated current selection): + +```js +async function askAboutSelection(button) { + const status = document.getElementById("followup-status"); + button.disabled = true; + status.textContent = "Sending question…"; + try { + await Websandbox.connection.remote.sendPrompt({ + text: "Explain the assumptions behind the scenario shown above.", + }); + status.textContent = "Question sent."; + } catch (error) { + status.textContent = + "Could not send. Please try again or type your question in chat."; + } finally { + button.disabled = false; } } ``` ---- - -## Part 3: Skill — Data Visualization - -### When to Use -- Comparing quantities -- Showing trends over time -- Displaying distributions or proportions -- Making data explorable - -### Approach: Inline SVG Charts (No Dependencies) - -For simple charts, hand-draw in SVG. No library needed. - -```svg - - - - - - - - - - Q1 - $42k - - -``` - -### Approach: Chart.js (For Complex/Interactive Charts) - -When you need tooltips, responsive legends, animations: - -```html - - - -``` - ---- - -## Part 4: Skill — Mermaid Diagrams - -For relationship diagrams (ERDs, class diagrams, sequence diagrams) where -precise layout math isn't worth doing by hand. - -```html -
- -``` - -Use Mermaid for: ERDs, class diagrams, sequence diagrams, Gantt charts. -Use hand-drawn SVG for: everything else (flowcharts, architecture, -illustrative diagrams) — you get much better control. - ---- - -## Part 5: Skill — Explanatory Writing Between Visuals - -### Narration Patterns - -**The Walk-Through**: Point at parts of the visual and explain them. -> "Starting at the top, the roof deck collects distributed loads across -> its surface. These get channeled into the rafters below, which act -> like one-way bridges..." - -**The "Why It Matters"**: Connect the visual to real consequences. -> "This is why lower columns are always larger — they're carrying the -> accumulated weight of every floor above." - -**The "Common Mistake"**: Anticipate misconceptions. -> "One thing that trips people up: removing a single column doesn't just -> lose that member — it breaks the entire load chain." - -**The "Go Deeper" Offer**: End with expansion paths. -> "Want me to show how lateral loads (wind, seismic) take a completely -> different path?" - -### Tone Rules -- Warm and direct. Not academic, not dumbed-down. -- Use "you" and "we" freely. -- Analogies and metaphors are powerful. Use them. -- Short paragraphs (2-4 sentences). No walls of text. -- Bold key terms on first introduction, then don't re-bold. -- Never use bullet points for explanations. Prose only. -- Ask at most one question per response. - ---- - -## Part 6: Skill — Knowing What NOT to Visualize - -Not everything needs a diagram. Skip visuals when: - -- The answer is a single fact or number -- The user is venting or emotional (empathy, not charts) -- The topic is purely textual (writing, editing, drafting) -- A code snippet is the answer (just show the code) -- The user explicitly asked for brief/concise - -### The "Would They Screenshot This?" Test - -If the user would likely screenshot or save the visual to reference -later, it was worth making. If not, just use text. - ---- - -## Part 7: Putting It All Together - -### Example Response Structure (Complex Technical Question) - -``` -[1-2 sentence hook validating the question] - -[Visual: SVG diagram or interactive widget] - -[Walk-through narration: 3-4 paragraphs explaining the visual, - pointing at specific parts, noting key insights] - -[One "go deeper" offer with 2-3 specific directions] -``` - -### Example Response Structure (Simple Question with Visual Aid) - -``` -[Direct answer in 1-2 sentences] - -[Small supporting visual if it adds value] - -[One additional insight or context sentence] -``` - -### Quality Checklist Before Responding - -- [ ] Did I pick the right format? (text vs SVG vs interactive vs chart) -- [ ] Is the visual self-explanatory even without the narration? -- [ ] Does the narration add value beyond what the visual shows? -- [ ] Are colors meaningful, not decorative? -- [ ] Does it work in dark mode? -- [ ] Is the response concise? (Cut anything that doesn't teach) -- [ ] Did I offer a clear next step? - ---- - -## Appendix: Quick Reference - -| Concept Type | Best Format | -|-------------------------|------------------------------| -| How X works (physical) | Illustrative SVG diagram | -| How X works (abstract) | Interactive HTML + SVG | -| Process / workflow | SVG flowchart | -| Architecture | SVG structural diagram | -| Data relationships | Mermaid ERD | -| Trends / comparisons | Chart.js or SVG bar chart | -| Cyclic process | HTML step-through widget | -| System states | Interactive widget + toggles | -| Quick answer | Plain text | -| Code solution | Code block / artifact | -| Emotional support | Warm text only | +External links use Websandbox.connection.remote.openLink({ url }) with HTTPS. +Do not use the standalone MCP renderer's global postMessage helpers in this host. diff --git a/apps/agent/skills/svg-diagrams/SKILL.md b/apps/agent/skills/svg-diagrams/SKILL.md index fedb655..e1a426f 100644 --- a/apps/agent/skills/svg-diagrams/SKILL.md +++ b/apps/agent/skills/svg-diagrams/SKILL.md @@ -1,5 +1,5 @@ --- -name: "SVG Diagram Generation" +name: "svg-diagrams" description: "Generating rich inline SVG diagrams to visually explain systems, processes, architectures, and abstract concepts." allowed-tools: [] --- @@ -10,6 +10,12 @@ You can generate rich, inline SVG diagrams to visually explain concepts. Use thi --- +## Delivery + +Diagrams ship through the `generateSandboxedUi` tool: the SVG markup goes in the `html` parameter, where it streams to the user element by element. SVG presentation attributes (`fill`, `stroke`, `font-size`) carry all styling here — if a diagram needs CSS animation classes, declare them in the `css` parameter, never in a `", + html: ["
"], + }, + "Css escape" + ); + expect(doc).not.toContain(""); + expect(doc).toContain("body{color:red}<\\/style>"); + }); + + it("tolerates empty and missing fields", () => { + const doc = assembleStandaloneHtmlFromActivity({}); + expect(doc.startsWith("")).toBe(true); + expect(doc).toContain('`; +export interface StandaloneActivityContent { + css?: string; + html?: string[]; + jsFunctions?: string; + jsExpressions?: string[]; +} + +const WEBSANDBOX_STUB = `window.Websandbox = { connection: { remote: { sendPrompt: async () => {}, openLink: async ({ url }) => { if (/^https:/.test(url)) window.open(url, "_blank", "noopener,noreferrer"); } } } };`; + +function escapeScriptClose(js: string): string { + return js.replace(/<\/script/gi, "<\\/script"); +} + +function escapeStyleClose(css: string): string { + return css.replace(/<\/style/gi, "<\\/style"); +} /** - * Wrap a raw HTML fragment (the same string passed to WidgetRenderer) - * in a standalone document that works when opened in a browser. + * Wrap an open-generative-ui activity payload in a standalone document that + * works when opened in a browser: importmap first, then the same design-system + * css composition the live renderer injects, then the generated css, a + * Websandbox stub so exported bridge calls degrade gracefully, the joined html + * chunks, and finally the generated js in ONE classic (non-module) script: + * jsFunctions at top level — so function declarations become window globals, + * matching the live websandbox rail where inline onclick="fn()" handlers + * resolve them — followed by the jsExpressions inside an async IIFE so they + * can use `await` (dynamic import() still resolves via the importmap in + * classic scripts). */ -export function assembleStandaloneHtml(html: string, title: string): string { +export function assembleStandaloneHtmlFromActivity( + content: StandaloneActivityContent, + title = "generated-widget" +): string { + const body = content.html?.join("") ?? ""; + const expressions = content.jsExpressions ?? []; + const scriptParts = [ + ...(content.jsFunctions ? [escapeScriptClose(content.jsFunctions)] : []), + ...(expressions.length > 0 + ? [ + `(async () => { +${expressions.map(escapeScriptClose).join("\n")} +})();`, + ] + : []), + ]; + const generatedScript = + scriptParts.length > 0 + ? `` + : ""; return ` ${escapeHtml(title)} - ${IMPORT_MAP} + ${IMPORTMAP_SCRIPT_TAG} + ${TRIP_ANIMATOR_SCRIPT} + ${content.css ? `\n ` : ""} + -
- ${html} -
- + ${body} + ${generatedScript} `; } diff --git a/apps/app/src/components/generative-ui/open-generative-ui/__tests__/open-generative-ui-renderer.test.tsx b/apps/app/src/components/generative-ui/open-generative-ui/__tests__/open-generative-ui-renderer.test.tsx new file mode 100644 index 0000000..65cdb2a --- /dev/null +++ b/apps/app/src/components/generative-ui/open-generative-ui/__tests__/open-generative-ui-renderer.test.tsx @@ -0,0 +1,650 @@ +import { render, cleanup, act } from "@testing-library/react"; +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import React from "react"; +import { z } from "zod"; +import { + SandboxFunctionsContext, + type SandboxFunction, +} from "@copilotkit/react-core/v2"; +import { IDIOMORPH_JS } from "../../idiomorph-inline"; +import { + OpenGenUIActivityRenderer, + OPEN_GEN_UI_ACTIVITY_RENDERER, + LOADING_PHRASES, + type OpenGenUIContent, +} from "../index"; +import { THROTTLE_MS } from "../renderer"; + +// The react-core v2 dist entry imports index.css, which vitest's node loader +// rejects (same precedent as src/lib/sandbox/__tests__/prompt-bridge.test.tsx) +// — mock the module with a faithful context + hook pair. +vi.mock("@copilotkit/react-core/v2", async () => { + const { createContext, useContext } = await import("react"); + const SandboxFunctionsContext = createContext([]); + return { + SandboxFunctionsContext, + useSandboxFunctions: () => useContext(SandboxFunctionsContext), + }; +}); + +// Mock the websandbox loader seam. @jetbrains/websandbox is a transitive +// dependency of @copilotkit/react-core that pnpm strict isolation makes +// unresolvable from this package, so vite's import-analysis rejects a direct +// vi.mock("@jetbrains/websandbox") at transform time. The mock shape below +// mirrors the canonical OpenGenerativeUIRenderer.test.tsx websandbox mock. +const mockRun = vi.fn().mockResolvedValue(undefined); +const mockDestroy = vi.fn(); +let mockIframe: HTMLIFrameElement; +let mockPromiseResolve: () => void; +let mockPromise: Promise; + +function resetMockPromise() { + mockPromise = new Promise((resolve) => { + mockPromiseResolve = resolve; + }); +} + +const mockCreate = vi.fn( + ( + _localApi: Record, + options: { frameContainer: HTMLElement; frameContent: string } + ) => { + mockIframe = document.createElement("iframe"); + options.frameContainer.appendChild(mockIframe); + return { + iframe: mockIframe, + promise: mockPromise, + run: mockRun, + destroy: mockDestroy, + }; + } +); + +vi.mock("../websandbox-loader", () => ({ + loadWebsandbox: async () => ({ + create: ( + ...args: [ + Record, + { frameContainer: HTMLElement; frameContent: string }, + ] + ) => mockCreate(...args), + }), +})); + +/** Flush the dynamic import() microtask so the sandbox gets created */ +async function flushImport() { + await act(async () => { + await new Promise((r) => setTimeout(r, 0)); + }); +} + +async function resolveSandboxReady() { + await act(async () => { + mockPromiseResolve(); + await mockPromise; + }); + await flushImport(); +} + +function rendererElement(content: OpenGenUIContent) { + return ( + + ); +} + +function renderRenderer(content: OpenGenUIContent) { + return render(rendererElement(content)); +} + +function runCallsContaining(needle: string) { + return mockRun.mock.calls.filter( + (c: unknown[]) => typeof c[0] === "string" && (c[0] as string).includes(needle) + ); +} + +describe("OpenGenUIActivityRenderer", () => { + beforeEach(() => { + vi.clearAllMocks(); + resetMockPromise(); + }); + + afterEach(() => { + cleanup(); + }); + + it("renders loading placeholder and no sandbox when there is no html", async () => { + const { container } = renderRenderer({ initialHeight: 300, generating: true }); + await flushImport(); + + // The root is the constant ExportOverlay wrapper; the frame div with the + // height style is its child. + const div = container.querySelector("div[style]")!; + expect(div.style.height).toBe("300px"); + expect(container.textContent).toContain(LOADING_PHRASES[0]); + expect(mockCreate).not.toHaveBeenCalled(); + }); + + it("creates no sandbox while css is incomplete, even as html chunks stream", async () => { + const { rerender } = renderRenderer({ + html: ["
Streaming
"], + htmlComplete: false, + generating: true, + }); + await flushImport(); + + expect(mockCreate).not.toHaveBeenCalled(); + + rerender( + rendererElement({ + html: ["
Streaming
", "

More

"], + htmlComplete: false, + generating: true, + }) + ); + await act(async () => { + await new Promise((r) => setTimeout(r, THROTTLE_MS + 100)); + }); + await flushImport(); + + expect(mockCreate).not.toHaveBeenCalled(); + }, 10000); + + it("creates the preview sandbox once cssComplete and injects design system + generated css via run()", async () => { + renderRenderer({ + css: "body{--marker:gen-css}", + cssComplete: true, + html: ["
Hello
"], + htmlComplete: false, + generating: true, + }); + await flushImport(); + + expect(mockCreate).toHaveBeenCalledTimes(1); + const [localApi, options] = mockCreate.mock.calls[0]!; + expect(options.frameContent).toBe(""); + expect(Object.keys(localApi)).toHaveLength(0); + + await resolveSandboxReady(); + + const headCalls = runCallsContaining("document.head.innerHTML"); + expect(headCalls.length).toBeGreaterThanOrEqual(1); + const headCode = headCalls[headCalls.length - 1]![0] as string; + expect(headCode).toContain("--color-background-primary"); + expect(headCode).toContain("svg text.t"); + expect(headCode).toContain("fadeSlideIn"); + expect(headCode).toContain("--marker:gen-css"); + }); + + it("injects Idiomorph once and morphs preview body updates with an innerHTML fallback", async () => { + const { rerender } = renderRenderer({ + css: "body{--marker:gen-css}", + cssComplete: true, + html: ["
Hello
"], + htmlComplete: false, + generating: true, + }); + await flushImport(); + await resolveSandboxReady(); + + const idiomorphInjections = () => + mockRun.mock.calls.filter((c: unknown[]) => c[0] === IDIOMORPH_JS).length; + expect(idiomorphInjections()).toBe(1); + + const morphCalls = runCallsContaining("Idiomorph.morph"); + expect(morphCalls.length).toBeGreaterThanOrEqual(1); + const morphCode = morphCalls[morphCalls.length - 1]![0] as string; + expect(morphCode).toContain("Idiomorph.morph(document.body"); + expect(morphCode).toContain("morphStyle: 'innerHTML'"); + // Streaming entrance animation: new nodes are tagged morph-enter so the + // design system's fadeSlideIn rule animates them in (legacy bridge parity). + expect(morphCode).toContain("beforeNodeAdded"); + expect(morphCode).toContain("morph-enter"); + expect(morphCode).toContain("document.body.innerHTML"); + expect(morphCode).toContain("Hello"); + // processPartialHtml must have stripped the wrapper before morph. + expect(morphCode).not.toContain(""); + + rerender( + rendererElement({ + css: "body{--marker:gen-css}", + cssComplete: true, + html: ["
Hello
", "

World

"], + htmlComplete: false, + generating: true, + }) + ); + await act(async () => { + await new Promise((r) => setTimeout(r, THROTTLE_MS + 100)); + }); + await flushImport(); + + const updatedMorphCalls = runCallsContaining("Idiomorph.morph"); + expect(updatedMorphCalls[updatedMorphCalls.length - 1]![0]).toContain("World"); + expect(idiomorphInjections()).toBe(1); + }, 10000); + + it("builds final frameContent ordered importmap -> design system -> generated css -> generated html, with sandbox functions as localApi", async () => { + const handler = vi.fn().mockResolvedValue(42); + const fns: SandboxFunction[] = [ + { + name: "addToCart", + description: "Add item to cart", + parameters: z.object({ itemId: z.string() }), + handler, + }, + ]; + + render( + + {rendererElement({ + css: "body{--marker:gen-css}", + cssComplete: true, + html: ['
Done
'], + htmlComplete: true, + generating: false, + })} +
+ ); + await flushImport(); + + expect(mockCreate).toHaveBeenCalledTimes(1); + const [localApi, options] = mockCreate.mock.calls[0]!; + expect(localApi.addToCart).toBe(handler); + + const frameContent = options.frameContent as string; + const importmapIdx = frameContent.indexOf('
Hi
') + ).toBe("
Hi
"); + }); + + it("strips unterminated `; diff --git a/apps/app/src/components/generative-ui/open-generative-ui/websandbox-loader.ts b/apps/app/src/components/generative-ui/open-generative-ui/websandbox-loader.ts new file mode 100644 index 0000000..7986402 --- /dev/null +++ b/apps/app/src/components/generative-ui/open-generative-ui/websandbox-loader.ts @@ -0,0 +1,29 @@ +export interface SandboxInstance { + iframe: HTMLIFrameElement; + promise: Promise; + run: (code: string) => Promise; + destroy: () => void; +} + +export interface WebsandboxModule { + create: ( + localApi: Record unknown>, + options: { + frameContainer: HTMLElement; + frameContent: string; + allowAdditionalAttributes: string; + } + ) => SandboxInstance; +} + +type WebsandboxNamespace = { + default?: WebsandboxModule & { default?: WebsandboxModule }; +}; + +// websandbox ships a UMD bundle with its own webpack `default` export. +// Consumer bundlers wrap CJS under another `.default`, resulting in +// mod.default.default for the actual Websandbox class. +export async function loadWebsandbox(): Promise { + const mod = (await import("@jetbrains/websandbox")) as WebsandboxNamespace; + return (mod.default?.default ?? mod.default) as WebsandboxModule; +} diff --git a/apps/app/src/components/generative-ui/open-generative-ui/websandbox.d.ts b/apps/app/src/components/generative-ui/open-generative-ui/websandbox.d.ts new file mode 100644 index 0000000..682ccb8 --- /dev/null +++ b/apps/app/src/components/generative-ui/open-generative-ui/websandbox.d.ts @@ -0,0 +1,5 @@ +// @jetbrains/websandbox is a transitive dependency of @copilotkit/react-core +// (pnpm strict isolation — no hoisted types). Shorthand declaration so the +// dynamic import in websandbox-loader.ts typechecks; the loader narrows the +// module shape itself. +declare module "@jetbrains/websandbox"; diff --git a/apps/app/src/components/generative-ui/plan-card.test.tsx b/apps/app/src/components/generative-ui/plan-card.test.tsx new file mode 100644 index 0000000..daee2fb --- /dev/null +++ b/apps/app/src/components/generative-ui/plan-card.test.tsx @@ -0,0 +1,23 @@ +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/react"; +import "@testing-library/jest-dom/vitest"; +import { PlanCard } from "@/components/generative-ui/plan-card"; + +describe("PlanCard", () => { + it("renders the completed plan with technology and key elements", () => { + render( + + ); + + expect(screen.getByText("Plan: inline SVG")).toBeInTheDocument(); + expect( + screen.getByText("Render a bar chart of monthly revenue") + ).toBeInTheDocument(); + expect(screen.getByText("12 bars")).toBeInTheDocument(); + }); +}); diff --git a/apps/app/src/components/generative-ui/table-catalog.test.tsx b/apps/app/src/components/generative-ui/table-catalog.test.tsx new file mode 100644 index 0000000..01a4d24 --- /dev/null +++ b/apps/app/src/components/generative-ui/table-catalog.test.tsx @@ -0,0 +1,68 @@ +import { useEffect } from "react"; +import { afterEach, describe, expect, it } from "vitest"; +import { cleanup, render, screen } from "@testing-library/react"; +import { + A2UIProvider, + A2UIRenderer, + useA2UIActions, +} from "@copilotkit/a2ui-renderer"; +import { DataTable, tableCatalog } from "./table-catalog"; + +afterEach(cleanup); +const props = { + title: "Quarterly sales", + columns: ["Quarter", "Sales"], + rows: [ + ["Q1", "$100"], + ["Q2", "$200"], + ], + source: "User-provided data", +}; +function Surface() { + const { processMessages } = useA2UIActions(); + useEffect(() => { + processMessages([ + { + createSurface: { + surfaceId: "test", + catalogId: "copilotkit://open-generative-ui-tables", + }, + }, + { + updateComponents: { + surfaceId: "test", + components: [{ id: "root", component: "Table", ...props }], + }, + }, + ]); + }, [processMessages]); + return ; +} +describe("A2UI table catalog", () => { + it("renders real A2UI operations through the catalog", async () => { + render( + + + , + ); + expect( + await screen.findByRole("table", { name: "Quarterly sales" }), + ).toBeTruthy(); + expect(screen.getAllByRole("columnheader")).toHaveLength(2); + expect(screen.getByText("$200")).toBeTruthy(); + expect(screen.getByText("User-provided data")).toBeTruthy(); + }); + it("rejects mismatched rows instead of mislabeling data", () => { + render(); + expect(screen.getByRole("alert").textContent).toContain("invalid rows"); + }); + it("renders untrusted values as text", () => { + const { container } = render( + alert(1)", "100"]] }} + />, + ); + expect(container.querySelector("script")).toBeNull(); + expect(screen.getByText("")).toBeTruthy(); + }); +}); diff --git a/apps/app/src/components/generative-ui/table-catalog.tsx b/apps/app/src/components/generative-ui/table-catalog.tsx new file mode 100644 index 0000000..fa34141 --- /dev/null +++ b/apps/app/src/components/generative-ui/table-catalog.tsx @@ -0,0 +1,78 @@ +"use client"; + +import { createCatalog } from "@copilotkit/a2ui-renderer"; +import { z } from "zod"; + +export const TableProps = z.object({ + title: z.string().max(300), + columns: z.array(z.string().max(200)).min(1).max(12), + rows: z.array(z.array(z.string().max(2000)).max(12)).max(200), + source: z + .string() + .max(1000) + .describe( + "Data provenance: user-provided, calculated, sourced, or explicitly illustrative.", + ), +}); + +export function DataTable({ props }: { props: z.infer }) { + const parsed = TableProps.safeParse(props); + if ( + !parsed.success || + parsed.data.rows.some((row) => row.length !== parsed.data.columns.length) + ) { + return ( +

+ This table has invalid rows or columns. Ask the assistant to regenerate + it. +

+ ); + } + const { title, columns, rows, source } = parsed.data; + return ( +
+
+ + + + + {columns.map((column, index) => ( + + ))} + + + + {rows.map((row, index) => ( + + {row.map((cell, column) => ( + + ))} + + ))} + +
{title}
+ {column} +
{cell}
+ {rows.length === 0 &&

No rows to display.

} +
+

{source}

+
+ ); +} + +export const tableCatalog = createCatalog( + { + Table: { + props: TableProps, + description: + "An accessible basic data table. Every row must match the columns. Use exact values and label data provenance.", + }, + }, + { Table: DataTable }, + { catalogId: "copilotkit://open-generative-ui-tables" }, +); diff --git a/apps/app/src/components/generative-ui/widget-renderer.tsx b/apps/app/src/components/generative-ui/widget-renderer.tsx deleted file mode 100644 index 11e7d44..0000000 --- a/apps/app/src/components/generative-ui/widget-renderer.tsx +++ /dev/null @@ -1,729 +0,0 @@ -"use client"; - -import { useEffect, useRef, useState, useCallback } from "react"; -import { z } from "zod"; -import { ExportOverlay } from "./export-overlay"; -import { IDIOMORPH_JS } from "./idiomorph-inline"; - -// ─── Zod Schema (CopilotKit parameter contract) ───────────────────── -export const WidgetRendererProps = z.object({ - title: z - .string() - .describe("Short title for the visualization, e.g. 'Binary Search' or 'Load Balancer Architecture'"), - description: z - .string() - .describe("One-sentence explanation of what this visualization demonstrates"), - html: z - .string() - .describe( - "Self-contained HTML fragment with inline - - -
- ${initialHtml} -
- - - -`; -} - -// ─── Loading Phrases ───────────────────────────────────────────────── -const LOADING_PHRASES = [ - "Sketching pixels", - "Wiring up nodes", - "Painting gradients", - "Compiling visuals", - "Arranging atoms", - "Rendering magic", - "Polishing edges", -]; - -function useLoadingPhrase(active: boolean) { - const [index, setIndex] = useState(0); - useEffect(() => { - if (!active) return; - const interval = setInterval(() => { - setIndex((i) => (i + 1) % LOADING_PHRASES.length); - }, 1800); - return () => clearInterval(interval); - }, [active]); - return LOADING_PHRASES[index]; -} - -// ─── React Component ───────────────────────────────────────────────── - -export function WidgetRenderer({ title, html }: WidgetRendererProps) { - const iframeRef = useRef(null); - const [height, setHeight] = useState(0); - const [loaded, setLoaded] = useState(false); - // Whether the iframe shell has been initialized - const shellReadyRef = useRef(false); - // Track the last html sent to the iframe to avoid redundant updates - const committedHtmlRef = useRef(""); - // Tracks whether html content has settled (stopped changing) - const [htmlSettled, setHtmlSettled] = useState(false); - const [prevHtml, setPrevHtml] = useState(html); - const settledTimerRef = useRef | null>(null); - const fadeTimerRef = useRef | null>(null); - const [fadingOut, setFadingOut] = useState(false); - - const handleMessage = useCallback((e: MessageEvent) => { - // Only handle messages from our own iframe - if ( - iframeRef.current && - e.source === iframeRef.current.contentWindow && - e.data?.type === "widget-resize" && - typeof e.data.height === "number" - ) { - setHeight(Math.max(50, Math.min(e.data.height, 4000))); - } - }, []); - - useEffect(() => { - window.addEventListener("message", handleMessage); - return () => window.removeEventListener("message", handleMessage); - }, [handleMessage]); - - // Reset settled/fade state when html changes (adjust state during render) - if (html !== prevHtml) { - setPrevHtml(html); - setHtmlSettled(false); - setFadingOut(false); - } - - // Initialize the iframe shell once when html first appears. - // Shell loads EMPTY so partial streaming fragments (e.g. unclosed - - - -
- - - -
- - -``` - -### Math Visualizations -For plotting functions, showing geometric relationships, or exploring equations. - -**Pattern: Function Plotter with SVG** -```html - - - - - - x - y - - - - -
- - -
- - -``` - -### Sortable / Filterable Data Tables -```html - - - - - - - - - - - - - - - -
NameValueStatus
- - -``` - ---- - -## Part 4: Chart.js — Advanced Patterns - -### Dark Mode Awareness -```javascript -const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches; -const textColor = isDark ? '#c2c0b6' : '#3d3d3a'; -const gridColor = isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)'; -const tooltipBg = isDark ? '#2C2C2A' : '#fff'; -``` - -Canvas cannot read CSS variables — always detect dark mode and use -hardcoded hex values. - -### Wrapper Pattern (Critical for Sizing) -```html -
- -
-``` -- Height goes on the wrapper div ONLY, never on canvas. -- Always set `responsive: true, maintainAspectRatio: false`. -- For horizontal bar charts: height = (bars × 40) + 80 pixels. - -### Custom Legend (Always Use This) -Disable Chart.js default legend and build HTML: -```javascript -plugins: { legend: { display: false } } -``` -```html -
- - Series A — 65% - - - Series B — 35% - -
-``` - -### Dashboard Layout -Metric cards on top → chart below → sendPrompt for drill-down: -```html - -
- -
- - -
- -
-``` - -### Chart Type Selection Guide -| Data pattern | Chart type | -|----------------------------|---------------------| -| Trend over time | Line | -| Category comparison | Vertical bar | -| Ranking (few items) | Horizontal bar | -| Part of whole | Doughnut | -| Distribution | Histogram (bar) | -| Correlation (2 variables) | Scatter | -| Multi-variable comparison | Radar | -| Range / uncertainty | Line with fill area | - ---- - -## Part 5: Generative Art and Illustration - -For when the user asks for something creative, decorative, or aesthetic. - -### When to Use -- "Draw me a sunset" / "Create a pattern" -- Decorative headers or visual breaks -- Mood illustrations for creative writing -- Abstract visualizations of data or music - -### Rules (Different from Diagrams) -- Fill the canvas — art should feel rich, not sparse -- Bold colors are encouraged. You can use custom hex freely. -- Layered overlapping shapes create depth -- Organic forms with `` curves, ``, `` -- Texture via repetition (hatching, dots, parallel lines) -- Geometric patterns with `` -- NO gradients, shadows, blur, or glow (still flat aesthetic) - -### Pattern: Geometric Art -```svg - - - - - - - - - - - - - -``` - -### Pattern: Radial Symmetry -```svg - - - - - - - - - - - - -``` - -### Pattern: Landscape with Layered Shapes -For physical scenes, use ALL hardcoded hex (no theme classes): -```svg - - - - - - - - - - - -``` - ---- - -## Part 6: Advanced Patterns - -### Tabbed / Multi-View Interfaces -Since content streams top-down, don't use `display: none` during streaming. -Instead, render all content stacked, then use post-stream JS to create tabs: - -```html -
- - - -
- -
-
-
- - -``` - -### sendPrompt() — Chat-Driven Interactivity -A global function that sends a message as if the user typed it. -Use it when the user's next action benefits from AI thinking: - -```html - - -``` - -**Use for**: drill-downs, follow-up questions, "explain this part". -**Don't use for**: filtering, sorting, toggling — handle those in JS. -Append ` ↗` to button text when it triggers sendPrompt. - -### Responsive Grid Pattern -```css -display: grid; -grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); -gap: 12px; -``` -Use `minmax(0, 1fr)` if children have large min-content that could overflow. - -### CSS Animations (Subtle and Purposeful) -```css -/* Only animate transform and opacity for performance */ -@keyframes fadeSlideIn { - from { opacity: 0; transform: translateY(8px); } - to { opacity: 1; transform: translateY(0); } -} - -/* Always respect user preferences */ -@media (prefers-reduced-motion: reduce) { - *, *::before, *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - } -} - -/* Flowing particles / convection currents */ -@keyframes flow { to { stroke-dashoffset: -20; } } -.flowing { - stroke-dasharray: 5 5; - animation: flow 1.6s linear infinite; -} - -/* Pulsing for active elements */ -@keyframes pulse { - 0%, 100% { opacity: 0.3; } - 50% { opacity: 0.7; } -} -``` - ---- - -## Part 7: External Libraries (CDN Allowlist) - -Only these CDN origins work (CSP-enforced): -- `cdnjs.cloudflare.com` -- `esm.sh` -- `cdn.jsdelivr.net` -- `unpkg.com` - -### Useful Libraries - -**Chart.js** (data visualization): -```html - -``` - -**Three.js** (3D graphics): -```html - -``` - -**D3.js** (advanced data viz, force layouts, geographic maps): -```html - -``` - -**Mermaid** (ERDs, sequence diagrams, class diagrams): -```html - -``` - -**Tone.js** (audio synthesis): -```html - -``` - ---- - -## Part 8: Quality Checklist - -Before producing any visual, run through this: - -### Functional -- [ ] Does it work without JavaScript during streaming? (Content visible) -- [ ] Do all interactive controls have event handlers? -- [ ] Are all displayed numbers rounded properly? -- [ ] Does the canvas/SVG fit within the container width? - -### Visual -- [ ] Dark mode test: would every element be readable on near-black? -- [ ] No hardcoded text colors in HTML (use CSS variables) -- [ ] No gradients, shadows, blur, or glow -- [ ] Borders are 0.5px (except 2px for featured item accent) -- [ ] Font weights are only 400 or 500 -- [ ] All text is sentence case - -### Content -- [ ] Explanatory text is in the response, not inside the widget -- [ ] No titles or headings embedded in the HTML output -- [ ] Visual is self-explanatory without reading the narration -- [ ] Narration adds value beyond what the visual shows -- [ ] Offered a clear "go deeper" path - -### Accessibility -- [ ] `@media (prefers-reduced-motion: reduce)` for all animations -- [ ] Text contrast is sufficient (dark text on light fills, vice versa) -- [ ] Interactive elements are large enough to click (min 44px touch target) -- [ ] No information conveyed by color alone - ---- - -## Part 9: Decision Matrix — Picking the Right Visual - -| User asks about... | Output type | Technology | -|-----------------------------|--------------------------|---------------------| -| How X works (physical) | Illustrative diagram | SVG | -| How X works (abstract) | Interactive explainer | HTML + inline SVG | -| Process / steps | Flowchart | SVG | -| Architecture / containment | Structural diagram | SVG | -| Database schema / ERD | Relationship diagram | Mermaid | -| Trends over time | Line chart | Chart.js | -| Category comparison | Bar chart | Chart.js | -| Part of whole | Doughnut chart | Chart.js | -| KPIs / metrics | Dashboard | HTML metric cards | -| Design a UI | Mockup | HTML | -| Choose between options | Comparison cards | HTML grid | -| Cyclic process | Step-through | HTML stepper | -| Physics / math | Simulation | Canvas + JS | -| Function / equation | Plotter | SVG + JS | -| Data exploration | Sortable table | HTML + JS | -| Creative / decorative | Art / illustration | SVG | -| 3D visualization | 3D scene | Three.js | -| Music / audio | Synthesizer | Tone.js | -| Network / graph | Force layout | D3.js | -| Quick factual answer | Plain text | None | -| Code solution | Code block | None | -| Emotional support | Warm text | None | +# Open Generative UI — interactive implementation + +Read the master playbook for routing and the standalone assemble_document contract. +This server returns HTML text with theme CSS and legacy postMessage helpers. It +has no injected importmap or Websandbox connection. generateSandboxedUi in the web +app uses a separate streaming contract; do not mix the two environments. + +## Structure + +Supply html with styles and scripts suitable for an isolated iframe. Use theme +variables such as --color-text-primary, --color-text-secondary, +--color-background-secondary, --color-border-tertiary, and --border-radius-md. +Keep useful content visible before scripts load. Include headings, assumptions, +sources, units, and instructions where they help a self-contained answer. + +Use responsive grids, wrapping controls, and viewBox SVG. For charts, bound the +container height and resize with its container. Resolve theme colors for canvas +using getComputedStyle. Provide a textual summary or accessible table alongside +canvas. Respect reduced motion; pause animation and keep one loop per simulation. +Use real Three.js geometry and responsive camera controls for 3D when it is useful. +Dispose resources on teardown and display initialization failures visibly. + +## Numeric tools + +For input[type=number], read valueAsNumber, reject non-finite values and out-of-range +inputs, and check denominators. min/max alone do not validate user typing. Show a +clear error and mark invalid fields; avoid stale output. Preserve internal precision +and format displayed values with Intl.NumberFormat. Include units, assumptions, +reset behavior, and the formula used. Never eval a user-supplied expression. + +## Controls + +Use native buttons with clear labels, explicit input labels, visible keyboard focus, +and role=status for feedback. Forms must prevent unwanted navigation; non-submit +buttons use type=button. Use buttons inside sortable table headers. Sorting and +filtering should use the same state and preserve one another. Insert data using +textContent rather than interpolating values into HTML. Interactive tabs require +proper keyboard/ARIA behavior; simple toggle buttons can use aria-pressed instead. + +## Libraries and network + +Allowed script CDN origins are cdnjs.cloudflare.com, esm.sh, cdn.jsdelivr.net, +and unpkg.com. Load pinned library URLs and handle errors; bare imports require an +explicit importmap, which this renderer does not inject. Module scripts may use +imports; classic scripts cannot use top-level await. Styles are inline under the +current CSP; do not assume arbitrary stylesheet or API URLs work. Do not rely on +cookies, localStorage, or parent DOM in a properly isolated sandbox. + +## Follow-up actions + +Use sendPrompt(text) only when a consuming host explicitly supports the legacy +bridge. It posts a request without delivery acknowledgement. Do not claim success +or substitute this helper for the web app's validated +Websandbox.connection.remote.sendPrompt({ text }). Include selected values only +following a deliberate user click. Local controls must not send chat messages. +The standalone host must validate requests; never send credentials or secrets. + +## Evidence + +Show user data or genuine retrieved evidence. Explicitly label sample metrics, +comparison weights, and simulation assumptions. No fabricated current weather, +market prices, business records, or citations. A renderer supplies no live data. diff --git a/apps/mcp/skills/master-agent-playbook.txt b/apps/mcp/skills/master-agent-playbook.txt index e27ff25..7c76329 100644 --- a/apps/mcp/skills/master-agent-playbook.txt +++ b/apps/mcp/skills/master-agent-playbook.txt @@ -1,432 +1,51 @@ -# Master Agent Playbook: Making AI Responses Extraordinary - -This playbook teaches an AI coding agent how to go beyond plain text and deliver -responses that are visual, interactive, and deeply educational. It covers the -philosophy, decision-making, and technical skills needed. - ---- - -## Part 1: The Core Philosophy - -### Think Like a Teacher, Not a Search Engine - -Bad: "A load path is the route that forces take through a structure to the ground." -Good: [draws an interactive building cross-section with loads flowing downward] - -The principle: **Show, don't just tell.** Before writing any response, ask: -- Would a diagram make this click faster than a paragraph? -- Would an interactive widget let the user explore the concept themselves? -- Would a worked example teach better than a definition? - -### The Response Decision Tree - -``` -User asks a question - │ - ├─ Is it a quick factual answer? → Answer in 1-2 sentences. - │ - ├─ Is it conceptual / "how does X work"? - │ ├─ Is it spatial or visual? → SVG illustrative diagram - │ ├─ Is it a process/flow? → SVG flowchart or HTML stepper - │ ├─ Is it data-driven? → Interactive chart (Chart.js / Recharts) - │ └─ Is it abstract but explorable? → Interactive HTML widget with controls - │ - ├─ Is it "build me X"? → Working code artifact, fully functional - │ - ├─ Is it a comparison? → Side-by-side table or comparative visual - │ - └─ Is it emotional/personal? → Warm text response. No visuals needed. -``` - -### The 3-Layer Response Pattern - -Great responses layer information: - -1. **Hook** (1-2 sentences): Validate the question, set context. -2. **Visual** (diagram/widget): The core explanation, rendered visually. -3. **Narration** (2-4 paragraphs): Walk through the visual, add nuance, - connect to what the user already knows. Offer to go deeper. - -Never dump a visual without narration. Never narrate without visuals -when visuals would help. - ---- - -## Part 2: Skill — Interactive HTML Widgets - -For concepts that benefit from user exploration. More powerful than -static SVGs — users can manipulate parameters and see results. - -### When to Use -- The concept has a variable the user could tweak (temperature, rate, count) -- The system has states the user could toggle (on/off, mode A/B) -- The explanation benefits from stepping through stages -- Data exploration or filtering is involved - -### Template: Interactive Widget with Controls - -```html - - - - - - - - - -
- -
- - -``` - -### Template: Step-Through Explainer - -For cyclic or staged processes (event loops, biological cycles, pipelines). - -```html - - -
- -
- -
- -
- - Step 1 of 4 -
- - -``` - -### CSS Animation Patterns (for live diagrams) - -```css -/* Flowing particles along a path */ -@keyframes flow { - to { stroke-dashoffset: -20; } -} -.flowing { - stroke-dasharray: 5 5; - animation: flow 1.6s linear infinite; -} - -/* Pulsing glow for active elements */ -@keyframes pulse { - 0%, 100% { opacity: 0.3; } - 50% { opacity: 0.7; } -} -.pulsing { animation: pulse 2s ease-in-out infinite; } - -/* Flickering (for flames, sparks) */ -@keyframes flicker { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.8; } -} - -/* Always respect reduced motion preferences */ -@media (prefers-reduced-motion: reduce) { - *, *::before, *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - } -} -``` - ---- - -## Part 3: Skill — Data Visualization - -### When to Use -- Comparing quantities -- Showing trends over time -- Displaying distributions or proportions -- Making data explorable - -### Approach: Inline SVG Charts (No Dependencies) - -For simple charts, hand-draw in SVG. No library needed. - -```svg - - - - - - - - - - Q1 - $42k - - -``` - -### Approach: Chart.js (For Complex/Interactive Charts) - -When you need tooltips, responsive legends, animations: - -```html - - - -``` - ---- - -## Part 4: Skill — Mermaid Diagrams - -For relationship diagrams (ERDs, class diagrams, sequence diagrams) where -precise layout math isn't worth doing by hand. - -```html -
- -``` - -Use Mermaid for: ERDs, class diagrams, sequence diagrams, Gantt charts. -Use hand-drawn SVG for: everything else (flowcharts, architecture, -illustrative diagrams) — you get much better control. - ---- - -## Part 5: Skill — Explanatory Writing Between Visuals - -### Narration Patterns - -**The Walk-Through**: Point at parts of the visual and explain them. -> "Starting at the top, the roof deck collects distributed loads across -> its surface. These get channeled into the rafters below, which act -> like one-way bridges..." - -**The "Why It Matters"**: Connect the visual to real consequences. -> "This is why lower columns are always larger — they're carrying the -> accumulated weight of every floor above." - -**The "Common Mistake"**: Anticipate misconceptions. -> "One thing that trips people up: removing a single column doesn't just -> lose that member — it breaks the entire load chain." - -**The "Go Deeper" Offer**: End with expansion paths. -> "Want me to show how lateral loads (wind, seismic) take a completely -> different path?" - -### Tone Rules -- Warm and direct. Not academic, not dumbed-down. -- Use "you" and "we" freely. -- Analogies and metaphors are powerful. Use them. -- Short paragraphs (2-4 sentences). No walls of text. -- Bold key terms on first introduction, then don't re-bold. -- Never use bullet points for explanations. Prose only. -- Ask at most one question per response. - ---- - -## Part 6: Skill — Knowing What NOT to Visualize - -Not everything needs a diagram. Skip visuals when: - -- The answer is a single fact or number -- The user is venting or emotional (empathy, not charts) -- The topic is purely textual (writing, editing, drafting) -- A code snippet is the answer (just show the code) -- The user explicitly asked for brief/concise - -### The "Would They Screenshot This?" Test - -If the user would likely screenshot or save the visual to reference -later, it was worth making. If not, just use text. - ---- - -## Part 7: Putting It All Together - -### Example Response Structure (Complex Technical Question) - -``` -[1-2 sentence hook validating the question] - -[Visual: SVG diagram or interactive widget] - -[Walk-through narration: 3-4 paragraphs explaining the visual, - pointing at specific parts, noting key insights] - -[One "go deeper" offer with 2-3 specific directions] -``` - -### Example Response Structure (Simple Question with Visual Aid) - -``` -[Direct answer in 1-2 sentences] - -[Small supporting visual if it adds value] - -[One additional insight or context sentence] -``` - -### Quality Checklist Before Responding - -- [ ] Did I pick the right format? (text vs SVG vs interactive vs chart) -- [ ] Is the visual self-explanatory even without the narration? -- [ ] Does the narration add value beyond what the visual shows? -- [ ] Are colors meaningful, not decorative? -- [ ] Does it work in dark mode? -- [ ] Is the response concise? (Cut anything that doesn't teach) -- [ ] Did I offer a clear next step? - ---- - -## Appendix: Quick Reference - -| Concept Type | Best Format | -|-------------------------|------------------------------| -| How X works (physical) | Illustrative SVG diagram | -| How X works (abstract) | Interactive HTML + SVG | -| Process / workflow | SVG flowchart | -| Architecture | SVG structural diagram | -| Data relationships | Mermaid ERD | -| Trends / comparisons | Chart.js or SVG bar chart | -| Cyclic process | HTML step-through widget | -| System states | Interactive widget + toggles | -| Quick answer | Plain text | -| Code solution | Code block / artifact | -| Emotional support | Warm text only | +# Open Generative UI by CopilotKit — response playbook + +Give people answers they can interact with when interaction helps. Choose text for +simple facts, writing, and code. Use native tools when the connected host exposes a +suitable component. Use a custom UI for an explainer, comparison, or useful tool. + +Understand: show relationships and allow meaningful exploration. +Compare: show criteria, assumptions, and tradeoffs; keep simple comparisons simple. +Make a tool: supply functional inputs, validated computation, outputs, and reset. + +There is no required acknowledgement/plan/build/narrate ceremony. Multiple distinct +sections are welcome. Avoid repeating a successful build or duplicating its content +in narration. Use headings and explanations inside the artifact when helpful. + +## This server's actual contract + +This standalone MCP server exposes assemble_document with title, description, and +html. Supply a self-contained HTML body fragment including any inline style and +script blocks. It returns an HTML document as text; it does not itself display a UI, +fetch data, deploy a site, execute a transaction, or provide an agent conversation. +The consuming host must render it in an isolated iframe and implement bridge handling. + +Theme variables, form styles, and SVG classes are injected. The standalone document +has legacy sendPrompt(text) and openLink(url) helpers posting messages to its parent. +They do not acknowledge delivery: do not claim a question was sent or an action +completed merely because the helper returned. A compatible host must validate +message source, text, URLs, and authorization. Without host support, offer ordinary +instructions rather than follow-up buttons that cannot work. Trigger messages only +on deliberate user clicks, never on load, timers, or routine input changes. + +This differs from the web app's generateSandboxedUi tool. When that tool is actually +available, follow its ordered six-field contract and validated Websandbox bridge, +not this standalone helper API. Do not assume this MCP renderer injects an importmap +or provides Websandbox.connection.remote. + +## Reliable data and controls + +Distinguish actual user/tool data, calculations, and labeled sample assumptions. +Never invent current weather, prices, business metrics, retrieval times, or sources. +A visual component is not a data source. If required facts cannot be retrieved, +ask for data or offer explicitly illustrative inputs. Do not collect credentials or +imply mock forms authenticate or persist records. + +All enabled controls must work. Validate blanks, non-finite numbers, bounds, and +zero divisors; show useful errors rather than NaN/Infinity or stale results. +State units and formulas, format precision, and reset state consistently. +Keep local calculations and filtering local. Use textContent for untrusted values. + +Use semantic headings and labels, keyboard-operable controls, visible focus, +adequate contrast, reduced motion, and responsive layouts. Provide text alternatives +for charts. Do not rely on color alone. Show library-loading errors visibly. diff --git a/apps/mcp/skills/svg-diagram-skill.txt b/apps/mcp/skills/svg-diagram-skill.txt index 2a28385..90f2742 100644 --- a/apps/mcp/skills/svg-diagram-skill.txt +++ b/apps/mcp/skills/svg-diagram-skill.txt @@ -13,7 +13,7 @@ You can generate rich, inline SVG diagrams to visually explain concepts. Use thi ## SVG Setup -Always use this template: +Use this template as a starting point; add an accessible title and description: ```svg @@ -28,10 +28,10 @@ Always use this template: ``` -- **Width is always 680px** via viewBox. Set `width="100%"` so it scales responsively. +- **680px is a useful default coordinate width** via viewBox. Set `width="100%"` so it scales responsively. - **H (height)** = bottom-most element's y + height + 40px padding. Don't guess — compute it. - **Safe content area**: x=40 to x=640, y=40 to y=(H-40). -- **No wrapping divs**, no ``, ``, ``, or DOCTYPE. +- **Body fragments only**: no ``, ``, ``, or DOCTYPE. - **Background is transparent** — the host provides the background. --- @@ -190,7 +190,7 @@ For complex topics, use multiple smaller SVGs instead of one dense one: ## Example: Simple 3-Step Flow ```svg - + @@ -243,3 +243,11 @@ For complex topics, use multiple smaller SVGs instead of one dense one: - **Annotations on the side**: Put explanatory labels in the right margin (x > 560) with leader lines pointing to the relevant element. - **Consistent heights**: All boxes of the same type should be the same height. - **Whitespace is your friend**: Don't fill every pixel. Breathing room makes diagrams readable. + +## Host and accessibility + +Use assemble_document for the standalone MCP HTML contract. If the web app exposes +generateSandboxedUi, follow that tool's separate ordered streaming parameters. +Diagrams are optional when text is clearer. Include an accessible title/description +and keep labels readable on narrow screens. Reflow complex diagrams instead of +shrinking all text. Label illustrative data; never invent current evidence. diff --git a/apps/mcp/src/renderer.ts b/apps/mcp/src/renderer.ts index 8ae8238..8e1400b 100644 --- a/apps/mcp/src/renderer.ts +++ b/apps/mcp/src/renderer.ts @@ -1,293 +1,7 @@ -// OpenGenerativeUI Design System CSS and Bridge JS -// Forked from apps/app/src/components/generative-ui/widget-renderer.tsx -// WARNING: Keep in sync with the source widget-renderer.tsx when the design system changes. +// OpenIntelligentUI document assembly for the MCP server. +// Design-system CSS is single-sourced from @repo/design-system. -const THEME_CSS = ` -:root { - --color-background-primary: #ffffff; - --color-background-secondary: #f7f6f3; - --color-background-tertiary: #efeee9; - --color-background-info: #E6F1FB; - --color-background-danger: #FCEBEB; - --color-background-success: #EAF3DE; - --color-background-warning: #FAEEDA; - - --color-text-primary: #1a1a1a; - --color-text-secondary: #73726c; - --color-text-tertiary: #9c9a92; - --color-text-info: #185FA5; - --color-text-danger: #A32D2D; - --color-text-success: #3B6D11; - --color-text-warning: #854F0B; - - --color-border-primary: rgba(0, 0, 0, 0.4); - --color-border-secondary: rgba(0, 0, 0, 0.3); - --color-border-tertiary: rgba(0, 0, 0, 0.15); - --color-border-info: #185FA5; - --color-border-danger: #A32D2D; - --color-border-success: #3B6D11; - --color-border-warning: #854F0B; - - --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; - --font-serif: Georgia, "Times New Roman", serif; - --font-mono: "SF Mono", "Fira Code", "Fira Mono", monospace; - - --border-radius-md: 8px; - --border-radius-lg: 12px; - --border-radius-xl: 16px; - - --p: var(--color-text-primary); - --s: var(--color-text-secondary); - --t: var(--color-text-tertiary); - --bg2: var(--color-background-secondary); - --b: var(--color-border-tertiary); -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background-primary: #1a1a18; - --color-background-secondary: #2c2c2a; - --color-background-tertiary: #222220; - --color-background-info: #0C447C; - --color-background-danger: #501313; - --color-background-success: #173404; - --color-background-warning: #412402; - - --color-text-primary: #e8e6de; - --color-text-secondary: #9c9a92; - --color-text-tertiary: #73726c; - --color-text-info: #85B7EB; - --color-text-danger: #F09595; - --color-text-success: #97C459; - --color-text-warning: #EF9F27; - - --color-border-primary: rgba(255, 255, 255, 0.4); - --color-border-secondary: rgba(255, 255, 255, 0.3); - --color-border-tertiary: rgba(255, 255, 255, 0.15); - --color-border-info: #85B7EB; - --color-border-danger: #F09595; - --color-border-success: #97C459; - --color-border-warning: #EF9F27; - } -} -`; - -const SVG_CLASSES_CSS = ` -svg text.t { font: 400 14px var(--font-sans); fill: var(--p); } -svg text.ts { font: 400 12px var(--font-sans); fill: var(--s); } -svg text.th { font: 500 14px var(--font-sans); fill: var(--p); } - -svg .box > rect, svg .box > circle, svg .box > ellipse { fill: var(--bg2); stroke: var(--b); } -svg .node { cursor: pointer; } -svg .node:hover { opacity: 0.8; } -svg .arr { stroke: var(--s); stroke-width: 1.5; fill: none; } -svg .leader { stroke: var(--t); stroke-width: 0.5; stroke-dasharray: 4 4; fill: none; } - -/* Purple */ -svg .c-purple > rect, svg .c-purple > circle, svg .c-purple > ellipse, -svg rect.c-purple, svg circle.c-purple, svg ellipse.c-purple { fill: #EEEDFE; stroke: #534AB7; } -svg .c-purple text.th, svg .c-purple text.t { fill: #3C3489; } -svg .c-purple text.ts { fill: #534AB7; } - -/* Teal */ -svg .c-teal > rect, svg .c-teal > circle, svg .c-teal > ellipse, -svg rect.c-teal, svg circle.c-teal, svg ellipse.c-teal { fill: #E1F5EE; stroke: #0F6E56; } -svg .c-teal text.th, svg .c-teal text.t { fill: #085041; } -svg .c-teal text.ts { fill: #0F6E56; } - -/* Coral */ -svg .c-coral > rect, svg .c-coral > circle, svg .c-coral > ellipse, -svg rect.c-coral, svg circle.c-coral, svg ellipse.c-coral { fill: #FAECE7; stroke: #993C1D; } -svg .c-coral text.th, svg .c-coral text.t { fill: #712B13; } -svg .c-coral text.ts { fill: #993C1D; } - -/* Pink */ -svg .c-pink > rect, svg .c-pink > circle, svg .c-pink > ellipse, -svg rect.c-pink, svg circle.c-pink, svg ellipse.c-pink { fill: #FBEAF0; stroke: #993556; } -svg .c-pink text.th, svg .c-pink text.t { fill: #72243E; } -svg .c-pink text.ts { fill: #993556; } - -/* Gray */ -svg .c-gray > rect, svg .c-gray > circle, svg .c-gray > ellipse, -svg rect.c-gray, svg circle.c-gray, svg ellipse.c-gray { fill: #F1EFE8; stroke: #5F5E5A; } -svg .c-gray text.th, svg .c-gray text.t { fill: #444441; } -svg .c-gray text.ts { fill: #5F5E5A; } - -/* Blue */ -svg .c-blue > rect, svg .c-blue > circle, svg .c-blue > ellipse, -svg rect.c-blue, svg circle.c-blue, svg ellipse.c-blue { fill: #E6F1FB; stroke: #185FA5; } -svg .c-blue text.th, svg .c-blue text.t { fill: #0C447C; } -svg .c-blue text.ts { fill: #185FA5; } - -/* Green */ -svg .c-green > rect, svg .c-green > circle, svg .c-green > ellipse, -svg rect.c-green, svg circle.c-green, svg ellipse.c-green { fill: #EAF3DE; stroke: #3B6D11; } -svg .c-green text.th, svg .c-green text.t { fill: #27500A; } -svg .c-green text.ts { fill: #3B6D11; } - -/* Amber */ -svg .c-amber > rect, svg .c-amber > circle, svg .c-amber > ellipse, -svg rect.c-amber, svg circle.c-amber, svg ellipse.c-amber { fill: #FAEEDA; stroke: #854F0B; } -svg .c-amber text.th, svg .c-amber text.t { fill: #633806; } -svg .c-amber text.ts { fill: #854F0B; } - -/* Red */ -svg .c-red > rect, svg .c-red > circle, svg .c-red > ellipse, -svg rect.c-red, svg circle.c-red, svg ellipse.c-red { fill: #FCEBEB; stroke: #A32D2D; } -svg .c-red text.th, svg .c-red text.t { fill: #791F1F; } -svg .c-red text.ts { fill: #A32D2D; } - -@media (prefers-color-scheme: dark) { - svg text.t { fill: #e8e6de; } - svg text.ts { fill: #9c9a92; } - svg text.th { fill: #e8e6de; } - - svg .c-purple > rect, svg .c-purple > circle, svg .c-purple > ellipse, - svg rect.c-purple, svg circle.c-purple, svg ellipse.c-purple { fill: #3C3489; stroke: #AFA9EC; } - svg .c-purple text.th, svg .c-purple text.t { fill: #CECBF6; } - svg .c-purple text.ts { fill: #AFA9EC; } - - svg .c-teal > rect, svg .c-teal > circle, svg .c-teal > ellipse, - svg rect.c-teal, svg circle.c-teal, svg ellipse.c-teal { fill: #085041; stroke: #5DCAA5; } - svg .c-teal text.th, svg .c-teal text.t { fill: #9FE1CB; } - svg .c-teal text.ts { fill: #5DCAA5; } - - svg .c-coral > rect, svg .c-coral > circle, svg .c-coral > ellipse, - svg rect.c-coral, svg circle.c-coral, svg ellipse.c-coral { fill: #712B13; stroke: #F0997B; } - svg .c-coral text.th, svg .c-coral text.t { fill: #F5C4B3; } - svg .c-coral text.ts { fill: #F0997B; } - - svg .c-pink > rect, svg .c-pink > circle, svg .c-pink > ellipse, - svg rect.c-pink, svg circle.c-pink, svg ellipse.c-pink { fill: #72243E; stroke: #ED93B1; } - svg .c-pink text.th, svg .c-pink text.t { fill: #F4C0D1; } - svg .c-pink text.ts { fill: #ED93B1; } - - svg .c-gray > rect, svg .c-gray > circle, svg .c-gray > ellipse, - svg rect.c-gray, svg circle.c-gray, svg ellipse.c-gray { fill: #444441; stroke: #B4B2A9; } - svg .c-gray text.th, svg .c-gray text.t { fill: #D3D1C7; } - svg .c-gray text.ts { fill: #B4B2A9; } - - svg .c-blue > rect, svg .c-blue > circle, svg .c-blue > ellipse, - svg rect.c-blue, svg circle.c-blue, svg ellipse.c-blue { fill: #0C447C; stroke: #85B7EB; } - svg .c-blue text.th, svg .c-blue text.t { fill: #B5D4F4; } - svg .c-blue text.ts { fill: #85B7EB; } - - svg .c-green > rect, svg .c-green > circle, svg .c-green > ellipse, - svg rect.c-green, svg circle.c-green, svg ellipse.c-green { fill: #27500A; stroke: #97C459; } - svg .c-green text.th, svg .c-green text.t { fill: #C0DD97; } - svg .c-green text.ts { fill: #97C459; } - - svg .c-amber > rect, svg .c-amber > circle, svg .c-amber > ellipse, - svg rect.c-amber, svg circle.c-amber, svg ellipse.c-amber { fill: #633806; stroke: #EF9F27; } - svg .c-amber text.th, svg .c-amber text.t { fill: #FAC775; } - svg .c-amber text.ts { fill: #EF9F27; } - - svg .c-red > rect, svg .c-red > circle, svg .c-red > ellipse, - svg rect.c-red, svg circle.c-red, svg ellipse.c-red { fill: #791F1F; stroke: #F09595; } - svg .c-red text.th, svg .c-red text.t { fill: #F7C1C1; } - svg .c-red text.ts { fill: #F09595; } -} -`; - -const FORM_STYLES_CSS = ` -* { box-sizing: border-box; margin: 0; } -html { background: transparent; } -body { - font-family: var(--font-sans); - font-size: 16px; - line-height: 1.7; - color: var(--color-text-primary); - background: transparent; - -webkit-font-smoothing: antialiased; -} -button { - font-family: inherit; - font-size: 14px; - padding: 6px 16px; - border: 0.5px solid var(--color-border-secondary); - border-radius: var(--border-radius-md); - background: transparent; - color: var(--color-text-primary); - cursor: pointer; - transition: background 0.15s, transform 0.1s; -} -button:hover { background: var(--color-background-secondary); } -button:active { transform: scale(0.98); } -input[type="text"], -input[type="number"], -input[type="email"], -input[type="search"], -textarea, -select { - font-family: inherit; - font-size: 14px; - padding: 6px 12px; - height: 36px; - border: 0.5px solid var(--color-border-tertiary); - border-radius: var(--border-radius-md); - background: var(--color-background-primary); - color: var(--color-text-primary); - transition: border-color 0.15s; -} -input:hover, textarea:hover, select:hover { border-color: var(--color-border-secondary); } -input:focus, textarea:focus, select:focus { - outline: none; - border-color: var(--color-border-primary); - box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.06); -} -textarea { height: auto; min-height: 80px; resize: vertical; } -input::placeholder, textarea::placeholder { color: var(--color-text-tertiary); } -input[type="range"] { - -webkit-appearance: none; - appearance: none; - height: 4px; - background: var(--color-border-tertiary); - border-radius: 2px; - border: none; - outline: none; -} -input[type="range"]::-webkit-slider-thumb { - -webkit-appearance: none; - width: 18px; height: 18px; - border-radius: 50%; - background: var(--color-background-primary); - border: 0.5px solid var(--color-border-secondary); - cursor: pointer; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} -input[type="range"]::-moz-range-thumb { - width: 18px; height: 18px; - border-radius: 50%; - background: var(--color-background-primary); - border: 0.5px solid var(--color-border-secondary); - cursor: pointer; -} -input[type="checkbox"], input[type="radio"] { - width: 16px; height: 16px; - accent-color: var(--color-text-info); -} -a { color: var(--color-text-info); text-decoration: none; } -a:hover { text-decoration: underline; } -#content > * { - animation: fadeSlideIn 0.4s ease-out both; -} -#content > *:nth-child(1) { animation-delay: 0s; } -#content > *:nth-child(2) { animation-delay: 0.06s; } -#content > *:nth-child(3) { animation-delay: 0.12s; } -#content > *:nth-child(4) { animation-delay: 0.18s; } -#content > *:nth-child(5) { animation-delay: 0.24s; } -#content > *:nth-child(n+6) { animation-delay: 0.3s; } -@keyframes fadeSlideIn { - from { opacity: 0; transform: translateY(8px); } - to { opacity: 1; transform: translateY(0); } -} -@media (prefers-reduced-motion: reduce) { - *, *::before, *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - } -} -`; +import { THEME_CSS, SVG_CLASSES_CSS, FORM_STYLES_CSS } from "@repo/design-system"; const BRIDGE_JS = ` window.sendPrompt = function(text) { diff --git a/apps/mcp/src/server.ts b/apps/mcp/src/server.ts index b7328ae..a2caf8a 100644 --- a/apps/mcp/src/server.ts +++ b/apps/mcp/src/server.ts @@ -1,4 +1,7 @@ -import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { + McpServer, + ResourceTemplate, +} from "@modelcontextprotocol/sdk/server/mcp.js"; import * as z from "zod"; import { listSkills, loadSkill } from "./skills.js"; import { assembleDocument } from "./renderer.js"; @@ -13,7 +16,10 @@ export function createMcpServer(): McpServer { server.registerResource( "skills-list", "skills://list", - { description: "JSON array of available skill names", mimeType: "application/json" }, + { + description: "JSON array of available skill names", + mimeType: "application/json", + }, async () => ({ contents: [ { @@ -22,7 +28,7 @@ export function createMcpServer(): McpServer { text: JSON.stringify(listSkills()), }, ], - }) + }), ); server.registerResource( @@ -36,7 +42,10 @@ export function createMcpServer(): McpServer { })), }), }), - { description: "Full text of a skill instruction document", mimeType: "text/plain" }, + { + description: "Full text of a skill instruction document", + mimeType: "text/plain", + }, async (uri, { name }) => ({ contents: [ { @@ -45,7 +54,7 @@ export function createMcpServer(): McpServer { text: loadSkill(name as string), }, ], - }) + }), ); // Prompts: pre-composed skill prompts @@ -59,7 +68,7 @@ export function createMcpServer(): McpServer { content: { type: "text", text: loadSkill("master-agent-playbook") }, }, ], - }) + }), ); server.registerPrompt( @@ -72,7 +81,7 @@ export function createMcpServer(): McpServer { content: { type: "text", text: loadSkill("svg-diagram-skill") }, }, ], - }) + }), ); server.registerPrompt( @@ -85,7 +94,7 @@ export function createMcpServer(): McpServer { content: { type: "text", text: loadSkill("agent-skills-vol2") }, }, ], - }) + }), ); // Tool: assemble complete HTML document with design system @@ -93,17 +102,23 @@ export function createMcpServer(): McpServer { "assemble_document", { description: - "Wraps HTML with OpenGenerativeUI theme CSS, SVG classes, form styles, and bridge JS. " + + "Wraps HTML with Open Intelligent UI theme CSS, SVG classes, form styles, and bridge JS. " + "Returns a complete iframe-ready HTML document.", inputSchema: { title: z.string().describe("Short title for the visualization"), - description: z.string().describe("One-sentence explanation of what this shows"), - html: z.string().describe("Self-contained HTML fragment with inline
x
"); + + it("embeds the single-sourced design-system css before the injected html", () => { + // Theme tokens, SVG classes, and form styles from @repo/design-system. + const themeIdx = doc.indexOf("--color-background-primary"); + const svgIdx = doc.indexOf(".c-purple"); + const formIdx = doc.indexOf("button:hover"); + const htmlIdx = doc.indexOf("
x
"); + expect(themeIdx).toBeGreaterThanOrEqual(0); + expect(svgIdx).toBeGreaterThanOrEqual(0); + expect(formIdx).toBeGreaterThanOrEqual(0); + expect(htmlIdx).toBeGreaterThan(themeIdx); + expect(htmlIdx).toBeGreaterThan(svgIdx); + }); + + it("injects the CSP meta tag with the CDN allowlist", () => { + expect(doc).toContain('http-equiv="Content-Security-Policy"'); + for (const origin of [ + "https://cdnjs.cloudflare.com", + "https://esm.sh", + "https://cdn.jsdelivr.net", + "https://unpkg.com", + ]) { + expect(doc).toContain(origin); + } + }); + + it("wraps the html in #content and includes the bridge + resize script", () => { + expect(doc).toContain('
'); + expect(doc).toContain("window.sendPrompt = function"); + expect(doc).toContain("window.openLink = function"); + expect(doc).toContain("widget-resize"); + expect(doc).toContain("ResizeObserver"); + }); +}); diff --git a/apps/mcp/tests/skills.test.ts b/apps/mcp/tests/skills.test.ts new file mode 100644 index 0000000..57a35e1 --- /dev/null +++ b/apps/mcp/tests/skills.test.ts @@ -0,0 +1,10 @@ +import { describe, it, expect } from "vitest"; +import { listSkills } from "../src/skills"; + +describe("listSkills", () => { + it("returns an array containing the bundled skills", () => { + const skills = listSkills(); + expect(Array.isArray(skills)).toBe(true); + expect(skills).toContain("master-agent-playbook"); + }); +}); diff --git a/apps/mcp/vitest.config.ts b/apps/mcp/vitest.config.ts new file mode 100644 index 0000000..f624398 --- /dev/null +++ b/apps/mcp/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + }, +}); diff --git a/docker/Dockerfile.app b/docker/Dockerfile.app index d24d140..0ae73b2 100644 --- a/docker/Dockerfile.app +++ b/docker/Dockerfile.app @@ -10,9 +10,11 @@ WORKDIR /app # Install pnpm RUN corepack enable && corepack prepare pnpm@latest --activate -# Copy package files +# Copy package files (every workspace manifest the app depends on must be +# present or pnpm install fails to resolve workspace:* dependencies) COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ COPY apps/app/package.json ./apps/app/ +COPY packages/design-system/package.json ./packages/design-system/ COPY turbo.json ./ # Install dependencies @@ -25,6 +27,7 @@ WORKDIR /app # Copy dependencies from deps stage COPY --from=deps /app/node_modules ./node_modules COPY --from=deps /app/apps/app/node_modules ./apps/app/node_modules +COPY --from=deps /app/packages/design-system/node_modules ./packages/design-system/node_modules # Copy source code COPY . . @@ -32,8 +35,9 @@ COPY . . # Enable pnpm RUN corepack enable && corepack prepare pnpm@latest --activate -# Build the Next.js app -RUN pnpm --filter @repo/app build +# Build the Next.js app and its workspace dependencies (turbo's build task +# dependsOn ^build, so @repo/design-system dist/ is produced first) +RUN pnpm exec turbo run build --filter=@repo/app # Production image FROM base AS runner diff --git a/docs/README.md b/docs/README.md index 9663b05..b5fc402 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,25 +1,22 @@ -# Open Generative UI Documentation +# Open Intelligent UI documentation -Open Generative UI is a showcase and template for building AI agents with [CopilotKit](https://copilotkit.ai) and [LangGraph](https://langchain-ai.github.io/langgraph/). It demonstrates agent-driven UI where an AI agent and users collaboratively manipulate shared application state. +**Answers you can interact with**, by [CopilotKit](https://copilotkit.ai). The agent chooses text, native components, or custom interactive answers to help people understand, compare, and make tools. -## Prerequisites +Local prerequisites: Node.js 22+, pnpm 9+, Python 3.12+, uv, an OpenAI key for the default `chat-latest` answer model, and a TypeSafe key for Jev visualization routing. `claude-*` overrides use Anthropic instead of OpenAI. -- Node.js 22+ -- Python 3.12+ -- [pnpm](https://pnpm.io/) 9+ -- [uv](https://docs.astral.sh/uv/) (Python package manager) -- An OpenAI API key +| Guide | Description | +| ---------------------------------------------------- | ------------------------------------------------------ | +| [Getting started](getting-started.md) | Install, configure, and verify the project | +| [Product and agent behavior](interactive-answers.md) | Response selection, examples, evidence, and follow-ups | +| [Visualization routing](visualization-routing.md) | Jev, A2UI tables, charts, diagrams, and maps | +| [Architecture](architecture.md) | Agent, runtime, streaming renderer, and sandbox | +| [Deployment](deployment.md) | Configuration and launch verification | +| [Telemetry](telemetry.md) | What usage data is sent and how to turn it off | +| [Bring to your app](bring-to-your-app.md) | Adopt the integration patterns | +| [Agent state](agent-state.md) | Shared state examples | +| [Generative UI](generative-ui.md) | Native component examples | +| [Agent tools](agent-tools.md) | Python tool examples | +| [Human in the loop](human-in-the-loop.md) | Collect user input through tools | +| [MCP integration](mcp-integration.md) | Optional MCP integration | -## Documentation - -| Guide | Description | -|-------|-------------| -| [Getting Started](getting-started.md) | Install, configure, and run the project | -| [Architecture](architecture.md) | How the monorepo and request flow are structured | -| [Agent State](agent-state.md) | Bidirectional state sync between agent and frontend | -| [Generative UI](generative-ui.md) | Register React components the agent can render | -| [Agent Tools](agent-tools.md) | Create Python tools that read and update state | -| [Human in the Loop](human-in-the-loop.md) | Pause the agent to collect user input | -| [MCP Integration](mcp-integration.md) | Optional Model Context Protocol server | -| [Deployment](deployment.md) | Deploy to Render or other platforms | -| [Bring to Your App](bring-to-your-app.md) | Adopt these patterns in your own project | +Existing API and package identifiers retain their original names for compatibility. The lower-level example guides describe reusable patterns; the product behavior and current setup guides above define the experience. diff --git a/docs/agent-state.md b/docs/agent-state.md index 6124bc9..708dccf 100644 --- a/docs/agent-state.md +++ b/docs/agent-state.md @@ -29,7 +29,7 @@ The state schema is passed to the agent via `context_schema`: # apps/agent/main.py agent = create_deep_agent( - model=ChatOpenAI(model="gpt-5.4-2026-03-05"), + model=ChatAnthropic(model="claude-fable-5"), tools=[...], middleware=[CopilotKitMiddleware()], context_schema=AgentState, # ← state schema diff --git a/docs/agent-tools.md b/docs/agent-tools.md index dbe2217..83b6446 100644 --- a/docs/agent-tools.md +++ b/docs/agent-tools.md @@ -60,6 +60,7 @@ def manage_todos(todos: list[Todo], runtime: ToolRuntime) -> Command: ``` Key points: + - `Command(update={...})` merges the update into agent state - Include a `ToolMessage` in the `messages` list to acknowledge the tool call - Use `runtime.tool_call_id` for the message's `tool_call_id` @@ -82,10 +83,19 @@ with open(Path(__file__).parent / "db.csv") as f: @tool def query_data(query: str): - """Query the financial transactions database. Call this before creating charts.""" - return _data + """Return bundled sample rows. The query is context only and is not applied.""" + return { + "source": "Bundled db.csv sample dataset", + "is_sample": True, + "query_applied": False, + "rows": [dict(row) for row in _data], + } ``` +This tool does not retrieve live business metrics or filter its rows. Use it for +sample-data requests, and label sample values inside any resulting UI. Charts +based on user-provided data or other sources do not need to call this tool. + ## Registering Tools with the Agent Add tools to the agent's `tools` list in `apps/agent/main.py`: @@ -96,7 +106,7 @@ from src.query import query_data from src.plan import plan_visualization agent = create_deep_agent( - model=ChatOpenAI(model="gpt-5.4-2026-03-05"), + model=ChatAnthropic(model="claude-fable-5"), tools=[query_data, plan_visualization, *todo_tools], middleware=[CopilotKitMiddleware()], context_schema=AgentState, @@ -108,7 +118,8 @@ You can pass individual tools or spread a list of tools. ## Example: Adding a New Tool -Say you want to add a tool that fetches weather data: +This example adds a sample weather tool for demonstrating a renderer. Its values +are illustrative; it does not fetch current weather. **1. Create the tool** (`apps/agent/src/weather.py`): @@ -116,24 +127,34 @@ Say you want to add a tool that fetches weather data: from langchain.tools import tool @tool -def get_weather(city: str): - """Get the current weather for a city.""" - # Your implementation here - return {"city": city, "temp": 72, "condition": "sunny"} +def get_sample_weather(city: str): + """Return illustrative weather values for a sample UI, not current conditions.""" + return { + "city": city, + "temp": 72, + "temperature_unit": "F", + "condition": "sunny", + "is_sample": True, + "source": "Illustrative values from this example", + } ``` **2. Register it** in `apps/agent/main.py`: ```python -from src.weather import get_weather +from src.weather import get_sample_weather agent = create_deep_agent( - tools=[query_data, plan_visualization, *todo_tools, get_weather], + tools=[query_data, plan_visualization, *todo_tools, get_sample_weather], ... ) ``` -The agent can now call `get_weather` when a user asks about weather. If you want a custom UI for the result, register a `useRenderTool` on the frontend (see [Generative UI](generative-ui.md)). +The agent can call `get_sample_weather` when a user requests a sample weather UI. +Label the displayed values as sample data. A real current-weather tool needs an +actual data-provider integration, source attribution, and error handling. If you +want a custom UI for the result, register a `useRenderTool` on the frontend (see +[Generative UI](generative-ui.md)). ## Next Steps diff --git a/docs/architecture.md b/docs/architecture.md index fdcdcde..f233317 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,90 +1,69 @@ # Architecture -## Monorepo Structure +Open Generative UI combines a Python agent with a CopilotKit runtime and a browser renderer. The `openGenerativeUI` runtime API and `generateSandboxedUi` tool connect them. -This is a Turborepo monorepo with three apps: +## Components -``` -apps/ -├── app/ Next.js 16 frontend (React 19, TailwindCSS 4) -├── agent/ Python LangGraph agent (FastAPI, OpenAI) -└── mcp/ Model Context Protocol server (optional) -``` +| Location | Responsibility | +| ------------------------- | --------------------------------------------------------- | +| `apps/app/` | Next.js frontend and `/api/copilotkit` runtime route | +| `apps/agent/` | FastAPI, LangGraph, Deep Agent, tools, prompt, and skills | +| `apps/mcp/` | Optional standalone MCP resources and HTML assembler | +| `packages/design-system/` | Shared theme, SVG classes, and form styles | -The frontend and MCP server are managed by pnpm workspaces. The Python agent is managed separately with `uv`. +Node packages use pnpm/Turborepo. The Python agent uses uv. -## Request Flow +## Request flow -``` -Browser - │ - ▼ -Next.js App (:3000) - │ - ├── /api/copilotkit ← CopilotKit API route - │ │ - │ ▼ - │ CopilotRuntime - │ │ - │ ▼ - │ LangGraphHttpAgent ──→ FastAPI Agent (:8123) - │ │ - │ ├── LangGraph tools - │ ├── CopilotKitMiddleware - │ └── State management - │ - └── React UI - │ - ├── useAgent() ← Read/write agent state - ├── useComponent() ← Register generative UI - ├── useFrontendTool() ← Agent-callable frontend actions - └── useHumanInTheLoop() ← Interactive prompts +```text +User prompt or chat starter suggestion + → CopilotKit chat / agent run + → Next.js /api/copilotkit + → LangGraphHttpAgent → FastAPI agent + → model + applicable tools and skills + → text, native component, or generateSandboxedUi + → CopilotKit activity stream → browser renderer ``` -## Key Files +The agent uses `create_deep_agent`, CopilotKit middleware, an Anthropic compatibility middleware, and `BoundedMemorySaver(max_threads=200)`. The checkpoint store is process memory, not durable shared storage. Restarting or scaling the agent can lose or split conversation state. -### Frontend (`apps/app/`) +`src/model.py` chooses ChatAnthropic for `claude-*` and ChatOpenAI for `gpt-*`. It checks the selected provider's key before constructing the client. The local default is unchanged; deployed configuration can override it. -| File | Purpose | -|------|---------| -| `src/app/layout.tsx` | Wraps the app with `` and `` | -| `src/app/page.tsx` | Main page — chat UI, demo gallery, background | -| `src/app/api/copilotkit/route.ts` | Connects CopilotKit runtime to the LangGraph agent | -| `src/hooks/use-generative-ui-examples.tsx` | Registers all generative UI components | -| `src/hooks/use-example-suggestions.tsx` | Chat suggestion prompts | -| `src/components/generative-ui/` | Chart, widget, and interactive components | +`src/prompt.py` and the three agent skills guide response selection. Plain text is appropriate for direct answers. Native components handle supported structured tasks; custom UI serves useful diagrams, comparisons, calculators, and simulations. Planning is optional. See [Product and agent behavior](interactive-answers.md). -### Agent (`apps/agent/`) +## Streaming custom UI -| File | Purpose | -|------|---------| -| `main.py` | Agent definition, FastAPI app, system prompt | -| `src/todos.py` | `AgentState` schema and todo tools | -| `src/query.py` | Sample data query tool | -| `src/plan.py` | Visualization planning tool | -| `src/form.py` | Form generation tool (AG-UI) | -| `src/bounded_memory_saver.py` | Memory-capped checkpointer | -| `skills/` | Skill documents loaded at startup | +The runtime enables `openGenerativeUI`; its middleware translates `generateSandboxedUi` into `open-generative-ui` activity messages. The tool's ordered fields are: -### MCP (`apps/mcp/`) +1. `initialHeight` +2. `placeholderMessages` +3. `css` +4. `html` +5. `jsFunctions` +6. `jsExpressions` -| File | Purpose | -|------|---------| -| `src/server.ts` | MCP resources, prompts, and tools | -| `src/renderer.ts` | HTML document assembly with design system | -| `src/skills.ts` | Skill file loader | -| `src/index.ts` | HTTP server | -| `src/stdio.ts` | Stdio transport for Claude Desktop | +The renderer holds the placeholder until CSS is complete, progressively updates a preview iframe, then initializes the final Websandbox iframe. Shared theme CSS and a CDN importmap are injected. JavaScript function/expression channels execute as classic scripts, so top-level await is invalid; asynchronous imports belong inside async functions. -## State Sync +The sandbox has no same-origin access to storage or host APIs. The host exposes validated `sendPrompt({ text })` and HTTPS `openLink({ url })` callbacks through `Websandbox.connection.remote`. Resize messages are checked and bounded before setting iframe height. Keep these boundaries intact when modifying the renderer. -State flows bidirectionally between the agent and frontend via CopilotKit: +A follow-up starts a new agent turn. Prior generated outputs serve as separate snapshots of that answer; their local controls can still change their own UI. There is no supported cross-call DOM patch API, and arbitrary iframe control state is not automatically synchronized to the agent. Follow-up buttons should include relevant selected values explicitly. -``` -Frontend Agent -──────── ───── -agent.state.todos ◄──────── AgentState.todos -agent.setState(...) ────────► Command(update={...}) -``` +## Chat and evidence + +The page always displays CopilotChat, with three task-oriented starter suggestions. User prompts run the shared agent; answers and interactive components appear in that conversation. New chat starts a fresh thread. `query_data` returns an envelope with source metadata and all bundled sample CSV rows; its natural-language query is not applied. Neither a renderer nor a native card establishes a live data connection. + +Legacy todo tools remain in the agent and can manipulate their supported state; the login-form schema is a nonfunctional demonstration. They do not define the main product experience. + +## Standalone MCP + +The MCP server exposes skills, prompts, and `assemble_document`. The assembler returns HTML text with shared styles and legacy postMessage helpers. A consuming host must render the document in isolation and validate bridge requests. This server does not supply the web app's Websandbox bridge or importmap, and assembling a document does not display or deploy it. + +## Key implementation files + +- Agent: `apps/agent/main.py`, `src/model.py`, `src/prompt.py`, `src/query.py`, `skills/`. +- Runtime: `apps/app/src/app/api/copilotkit/route.ts`, `src/lib/copilotkit-runtime-options.ts`. +- Renderer: `apps/app/src/components/generative-ui/open-generative-ui/`. +- Host bridge: `apps/app/src/lib/sandbox/`. +- MCP assembly: `apps/mcp/src/server.ts`, `src/renderer.ts`. -Both the user (via React UI) and the agent (via tools) can modify the same state. CopilotKit handles synchronization automatically. See [Agent State](agent-state.md) for details. +See [Deployment](deployment.md) for runtime configuration and operational limits. diff --git a/docs/bring-to-your-app.md b/docs/bring-to-your-app.md index e681ec8..d8867d2 100644 --- a/docs/bring-to-your-app.md +++ b/docs/bring-to-your-app.md @@ -68,7 +68,7 @@ export const POST = async (req: NextRequest) => { Install dependencies: ```bash -pip install copilotkit langgraph langchain langchain-openai fastapi uvicorn ag-ui-langgraph deepagents +pip install copilotkit langgraph langchain langchain-anthropic fastapi uvicorn ag-ui-langgraph deepagents ``` Create the agent: @@ -81,12 +81,12 @@ from fastapi import FastAPI from copilotkit import CopilotKitMiddleware, LangGraphAGUIAgent from ag_ui_langgraph import add_langgraph_fastapi_endpoint from deepagents import create_deep_agent -from langchain_openai import ChatOpenAI +from langchain_anthropic import ChatAnthropic load_dotenv() agent = create_deep_agent( - model=ChatOpenAI(model=os.environ.get("LLM_MODEL", "gpt-5.4-2026-03-05")), + model=ChatAnthropic(model=os.environ.get("LLM_MODEL", "claude-fable-5")), tools=[], # add your tools here middleware=[CopilotKitMiddleware()], system_prompt="You are a helpful assistant.", diff --git a/docs/deployment.md b/docs/deployment.md index 9d19ea4..1bbf12d 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -1,98 +1,83 @@ # Deployment -## Render +This guide describes how to deploy Open Generative UI; it does not establish that a release is deployed. Keep existing service names and URLs intact when changing visible product branding. -The project includes a `render.yaml` for one-click deployment to [Render](https://render.com/). +## Render blueprint -### Services +The repository's `render.yaml` defines two services: -**Agent** (Python): -- Runtime: Python 3.12.6 -- Build: `pip install uv && uv sync` -- Start: `uv run uvicorn main:app --host 0.0.0.0 --port $PORT` -- Health check: `GET /health` -- Root directory: `apps/agent` +| Service | Runtime and root | Build | Start / health | +| -------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- | +| `open-generative-ui-agent` | Python 3.12.6, `apps/agent` | `pip install uv && uv sync` | `uv run uvicorn main:app --host 0.0.0.0 --port $PORT`, `/health` | +| `open-generative-ui-app` | Node 22, repository root | `corepack enable && pnpm install --no-frozen-lockfile && pnpm exec turbo run build --filter=@repo/app` | `pnpm --filter @repo/app start`, `/api/health` | -**Frontend** (Node): -- Runtime: Node 22 -- Build: `corepack enable && pnpm install --no-frozen-lockfile && pnpm --filter @repo/app build` -- Start: `pnpm --filter @repo/app start` -- Health check: `GET /api/health` -- Root directory: (repo root) +For shared credentials, the blueprint and Python factory default to `LLM_MODEL=chat-latest`, using `OPENAI_API_KEY`. Jev visualization routing uses `TYPESAFE_API_KEY`; `JEV_MODEL` defaults to `jev-latest`. Verify access to the selected model before launch; a configured model name does not prove availability. -### Environment Variables +| Variable | Service | Purpose | +| ----------------------------------------- | ------------- | ----------------------------------------------------------------------------------- | +| `LLM_MODEL` | Agent | `claude-*` routes to Anthropic; `gpt-*` routes to OpenAI | +| `ANTHROPIC_API_KEY` | Agent | Required when selecting Anthropic | +| `OPENAI_API_KEY` | Agent | Required when selecting OpenAI | +| `LANGSMITH_API_KEY` | As configured | Optional tracing configuration | +| `LANGGRAPH_DEPLOYMENT_URL` | Frontend | Blueprint obtains agent host:port via `fromService`; runtime normalizes it to a URL | +| `RATE_LIMIT_ENABLED` | Frontend | Defaults to `false` in blueprint | +| `RATE_LIMIT_WINDOW_MS` / `RATE_LIMIT_MAX` | Frontend | Request-limit configuration | +| `MCP_SERVER_URL` | Frontend | Optional MCP integration | -| Variable | Service | Required | Notes | -|----------|---------|----------|-------| -| `OPENAI_API_KEY` | Agent | Yes | Your OpenAI API key | -| `LLM_MODEL` | Agent | No | Defaults to `gpt-5.4-2026-03-05` | -| `LANGSMITH_API_KEY` | Agent | No | For LangSmith tracing | -| `LANGGRAPH_DEPLOYMENT_URL` | Frontend | Auto | Injected from agent service via `fromService` | -| `SKIP_INSTALL_DEPS` | Frontend | No | Set to `true` to skip redundant installs | +The agent rejects blank or unsupported model names at startup. Missing shared provider keys allow a BYOK-only deployment; requests without visitor keys receive a credentials-required response. Never put provider keys in public frontend variables. -### Auto-Scaling +To deploy, connect your repository to a Render Blueprint, review its explicit model setting, supply the corresponding provider secret, and deploy the reviewed revision. The blueprint links the frontend to the agent; verify the resulting connection with an actual prompt. -Both services are configured with: -- Min instances: 1 -- Max instances: 3 -- Memory target: 80% -- CPU target: 70% +Both services declare scaling from one to three instances. Agent checkpoints currently live in bounded process memory, and the frontend rate limiter is process-local. Scaling or restarting can lose/split conversation state and changes effective rate-limit behavior. Durable shared state and coordinated limits require additional infrastructure. -### Deploy +## Visitor API keys -1. Fork the repository -2. Create a new **Blueprint** on Render -3. Connect your forked repo -4. Add `OPENAI_API_KEY` as a secret -5. Deploy +Visitors can supply OpenAI and Jev keys through **API keys** in the chat header. The Next.js runtime forwards only `x-openai-api-key` and `x-jev-api-key` to the configured agent, creating a separate runtime instance per request. The Python ASGI middleware strips these headers before the inner application and scopes credentials to the entire streaming request without changing process environment variables. BYOK conversations have credential-specific checkpoint IDs, separate from shared-mode conversations. Both keys are required; partial pairs never fall back to server secrets. -Render reads `render.yaml` and creates both services. The frontend automatically gets the agent URL via service discovery. +`POST /api/provider-keys` proxies connection validation to the agent’s `POST /credentials/validate`. It performs small real provider requests and returns only fixed error messages. BYOK always uses the standard OpenAI endpoint and `chat-latest`; Jev uses `jev-latest`. Hosted LangSmith tracing is disabled for BYOK. The application does not persist the keys, but its server necessarily receives them: use HTTPS externally and a trusted private or TLS connection between frontend and agent. Do not configure infrastructure to log credential headers. -## General Deployment +## Other hosts -For other platforms, you need to deploy two services: - -### 1. Agent (Python) +Run the agent: ```bash cd apps/agent -pip install uv uv sync uv run uvicorn main:app --host 0.0.0.0 --port 8123 ``` -Requirements: -- Python 3.12+ -- `OPENAI_API_KEY` environment variable -- Port exposed for the frontend to reach - -### 2. Frontend (Node) +Supply the provider key and optional `LLM_MODEL` in that service's environment. Run the frontend from the repository root: ```bash -# From repo root corepack enable -pnpm install -pnpm --filter @repo/app build +pnpm install --frozen-lockfile +pnpm exec turbo run build --filter=@repo/app LANGGRAPH_DEPLOYMENT_URL=http://your-agent-host:8123 pnpm --filter @repo/app start ``` -Requirements: -- Node 22+ -- `LANGGRAPH_DEPLOYMENT_URL` pointing to the agent service -- Port 3000 exposed +Use a reachable agent URL appropriate to your network. Expose the frontend through your host's normal HTTPS routing. The optional MCP server is a separate deployment; see its [guide](../apps/mcp/README.md). A frontend Dockerfile is available at `docker/Dockerfile.app`. + +## Verification and launch -### Health Checks +1. Review the exact revision and provider configuration. Keep service identifiers stable and ensure secrets remain server-side. +2. Run the automated checks from the repository root: -| Service | Endpoint | Expected | -|---------|----------|----------| -| Agent | `GET /health` | `{"status": "ok"}` | -| Frontend | `GET /api/health` | 200 OK | + ```bash + pnpm test + uv run --directory apps/agent pytest + pnpm lint + pnpm build + ``` -## Docker + Turbo builds shared dependencies for workspace checks. For isolated MCP tests, build `@repo/design-system` first. -A Dockerfile for the frontend is available at `docker/Dockerfile.app`. The agent can be containerized with a standard Python Dockerfile using `uv`. +3. Check the chat layout at desktop and narrow widths. Exercise the composer, starter suggestions, and New chat. For generated tools, check keyboard controls, visible focus, numerical boundaries, and reset behavior. +4. Make real provider-backed requests for a direct text answer, an explainer, a comparison, and a working calculator. Verify streaming reaches the interactive final sandbox. Confirm current-data requests do not fabricate evidence. +5. Exercise a user-clicked follow-up with selected values. Confirm it starts a new turn/output, preserves earlier artifacts, and reports relevant errors. Check that ordinary controls do not send prompts. +6. Check analytics before launch: set `OIUI_DISTRIBUTION` and `NEXT_PUBLIC_POSTHOG_KEY` on the frontend, then confirm a page view and the two install events arrive in PostHog (see [Telemetry](telemetry.md)). +7. Deploy the reviewed revision. Confirm both health endpoints return `{"status":"ok"}`, then repeat a real prompt against the deployed frontend. Health checks alone do not test provider authentication, streaming, or browser behavior. +8. Record the deployed revision, environment, checks actually performed, and remaining limitations. If validation fails, use the host's rollback workflow to restore a known working revision. -## Next Steps +A rendered chat interface alone is not a model smoke test; verify a real response. Do not describe local test success as a deployed launch. See [Getting started](getting-started.md) and [Architecture](architecture.md) for setup and runtime details. -- [Getting Started](getting-started.md) — Local development setup -- [Architecture](architecture.md) — Understand the service topology +Set `APP_URL` on the frontend to the public custom-domain origin when using one. Social image metadata uses this value, then `RENDER_EXTERNAL_URL`, then the existing demo hostname. diff --git a/docs/generative-ui.md b/docs/generative-ui.md index 5ae2f2f..bf48be7 100644 --- a/docs/generative-ui.md +++ b/docs/generative-ui.md @@ -2,19 +2,19 @@ Generative UI lets the agent render React components directly in the chat. Instead of responding with text, the agent can produce charts, interactive widgets, visualizations, and custom UI. -All generative UI in this project is registered in `apps/app/src/hooks/use-generative-ui-examples.tsx`. +Hook-based generative UI in this project is registered in `apps/app/src/hooks/use-generative-ui-examples.tsx`. Free-form sandboxed widgets use the runtime-level **Open Generative UI** rail (see below), wired up in `apps/app/src/app/providers.tsx`. ## Hooks Overview -| Hook | Purpose | -|------|---------| -| `useComponent` | Register a named React component the agent can render with parameters | -| `useFrontendTool` | Register a tool the agent can call that runs in the browser | -| `useRenderTool` | Custom renderer for a specific backend tool | -| `useDefaultRenderTool` | Fallback renderer for any tool without a custom renderer | -| `useHumanInTheLoop` | Interactive component that pauses the agent for user input | +| Hook | Purpose | +| ---------------------- | --------------------------------------------------------------------- | +| `useComponent` | Register a named React component the agent can render with parameters | +| `useFrontendTool` | Register a tool the agent can call that runs in the browser | +| `useRenderTool` | Custom renderer for a specific backend tool | +| `useDefaultRenderTool` | Fallback renderer for any tool without a custom renderer | +| `useHumanInTheLoop` | Interactive component that pauses the agent for user input | -All hooks are imported from `@copilotkit/react-core/v2`. +All hooks are imported from `@copilotkit/react-core/v2`. Sandboxed streaming widgets are not hook-registered — they ride the runtime's `openGenerativeUI` option and the provider's `renderActivityMessages` prop. ## useComponent — Agent-Rendered Components @@ -29,10 +29,12 @@ import { useComponent } from "@copilotkit/react-core/v2"; const PieChartProps = z.object({ title: z.string(), description: z.string(), - data: z.array(z.object({ - label: z.string(), - value: z.number(), - })), + data: z.array( + z.object({ + label: z.string(), + value: z.number(), + }), + ), }); useComponent({ @@ -43,31 +45,45 @@ useComponent({ }); ``` -### Widget Renderer (Sandboxed HTML) +## Open Generative UI — Sandboxed Streaming Widgets + +Free-form HTML/SVG widgets use CopilotKit's canonical **Open Generative UI** rail instead of a custom component. The agent streams a whole UI — styles, markup, and behavior — and the frontend renders it live in a sandboxed iframe. See the [Open Generative UI docs](https://docs.copilotkit.ai/generative-ui/open-generative-ui) for the full reference. + +How the pieces connect: -The `widgetRenderer` component renders arbitrary HTML/SVG in a sandboxed iframe. This is the most flexible generative UI — the agent writes HTML and it gets rendered with full interactivity. +1. **Runtime** — the CopilotKit API route enables the rail with `openGenerativeUI: true` (`apps/app/src/lib/copilotkit-runtime-options.ts`). This injects the `generateSandboxedUi` tool for the agent. +2. **Tool** — the agent calls `generateSandboxedUi` with parameters streamed in a fixed order: `initialHeight` → `placeholderMessages` → `css` → `html` → `jsFunctions` → `jsExpressions`. CSS arrives first so the UI never renders unstyled; expressions arrive last so the user watches each behavior take effect. +3. **Middleware** — the runtime's `OpenGenerativeUIMiddleware` turns the streaming tool call into `open-generative-ui` activity events. +4. **Renderer** — the demo registers a custom activity renderer (`apps/app/src/components/generative-ui/open-generative-ui/`) via the provider's `renderActivityMessages` prop. While html streams it morphs each update into a preview iframe with Idiomorph (no flicker); once html completes it boots a [websandbox](https://github.com/jetbrains/websandbox) iframe with the shared design-system CSS and CDN importmap injected, runs `jsFunctions` then each `jsExpression`, and continuously autosizes from a ResizeObserver inside the frame. +5. **Sandbox bridge** — generated UI calls back into the host through Zod-validated sandbox functions (`apps/app/src/lib/sandbox/sandbox-functions.ts`): `await Websandbox.connection.remote.sendPrompt({ text })` and `await Websandbox.connection.remote.openLink({ url })`. ```tsx -useComponent({ - name: "widgetRenderer", - description: - "Renders interactive HTML/SVG visualizations in a sandboxed iframe. " + - "Use for algorithm visualizations, diagrams, interactive widgets, " + - "simulations, math plots, and any visual explanation.", - parameters: WidgetRendererProps, // { title, description, html } - render: WidgetRenderer, -}); +// app/layout.tsx +const renderActivityMessages = [OPEN_GEN_UI_ACTIVITY_RENDERER]; + +const openGenerativeUI = { + sandboxFunctions: [...SANDBOX_FUNCTIONS], // sendPrompt, openLink + designSkill: OPEN_GEN_UI_DESIGN_SKILL, // teaches the agent the design system +}; + + ``` The iframe environment includes: -**ES Module Libraries** (use `")).toBe(true); + expect(IMPORTMAP_SCRIPT_TAG).toContain('"three": "https://esm.sh/three"'); + }); +}); diff --git a/packages/design-system/src/__tests__/single-source.test.ts b/packages/design-system/src/__tests__/single-source.test.ts new file mode 100644 index 0000000..447b5e3 --- /dev/null +++ b/packages/design-system/src/__tests__/single-source.test.ts @@ -0,0 +1,35 @@ +import { describe, it, expect } from "vitest"; +import { readdirSync, readFileSync } from "node:fs"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +// Built via join so this test file itself never matches the needle. +const TOKEN_DEFINITION = ["--color-background-primary", ":"].join(""); + +const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../../../.."); +const SCAN_ROOTS = [join(REPO_ROOT, "apps"), join(REPO_ROOT, "packages")]; +const SKIP_DIRS = new Set(["node_modules", "dist", ".next"]); +const EXTENSIONS = [".ts", ".tsx"]; + +function collectSourceFiles(dir: string, out: string[] = []): string[] { + for (const entry of readdirSync(dir, { withFileTypes: true })) { + const path = join(dir, entry.name); + if (entry.isDirectory()) { + if (!SKIP_DIRS.has(entry.name)) collectSourceFiles(path, out); + } else if (EXTENSIONS.some((ext) => entry.name.endsWith(ext))) { + out.push(path); + } + } + return out; +} + +describe("design-system single source", () => { + it("defines the theme tokens in exactly one source file", () => { + const matches = SCAN_ROOTS.flatMap((root) => collectSourceFiles(root)).filter( + (file) => readFileSync(file, "utf8").includes(TOKEN_DEFINITION) + ); + expect(matches).toEqual([ + join(REPO_ROOT, "packages/design-system/src/index.ts"), + ]); + }); +}); diff --git a/packages/design-system/src/index.ts b/packages/design-system/src/index.ts new file mode 100644 index 0000000..b037c9f --- /dev/null +++ b/packages/design-system/src/index.ts @@ -0,0 +1,474 @@ +// OpenIntelligentUI design system: theme tokens, SVG classes, form styles, +// and the CDN import map shared by the Next.js app and the MCP server. + +// ─── Theme Variables ───────────────────────────────────────────────── +export const THEME_CSS = ` +:root { + --color-background-primary: #ffffff; + --color-background-secondary: #f7f6f3; + --color-background-tertiary: #efeee9; + --color-background-info: #E6F1FB; + --color-background-danger: #FCEBEB; + --color-background-success: #EAF3DE; + --color-background-warning: #FAEEDA; + + --color-text-primary: #1a1a1a; + --color-text-secondary: #73726c; + --color-text-tertiary: #9c9a92; + --color-text-info: #185FA5; + --color-text-danger: #A32D2D; + --color-text-success: #3B6D11; + --color-text-warning: #854F0B; + + --color-border-primary: rgba(0, 0, 0, 0.4); + --color-border-secondary: rgba(0, 0, 0, 0.3); + --color-border-tertiary: rgba(0, 0, 0, 0.15); + --color-border-info: #185FA5; + --color-border-danger: #A32D2D; + --color-border-success: #3B6D11; + --color-border-warning: #854F0B; + + --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + --font-serif: Georgia, "Times New Roman", serif; + --font-mono: "SF Mono", "Fira Code", "Fira Mono", monospace; + + --border-radius-md: 8px; + --border-radius-lg: 12px; + --border-radius-xl: 16px; + + --p: var(--color-text-primary); + --s: var(--color-text-secondary); + --t: var(--color-text-tertiary); + --bg2: var(--color-background-secondary); + --b: var(--color-border-tertiary); +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background-primary: #1a1a18; + --color-background-secondary: #2c2c2a; + --color-background-tertiary: #222220; + --color-background-info: #0C447C; + --color-background-danger: #501313; + --color-background-success: #173404; + --color-background-warning: #412402; + + --color-text-primary: #e8e6de; + --color-text-secondary: #9c9a92; + --color-text-tertiary: #73726c; + --color-text-info: #85B7EB; + --color-text-danger: #F09595; + --color-text-success: #97C459; + --color-text-warning: #EF9F27; + + --color-border-primary: rgba(255, 255, 255, 0.4); + --color-border-secondary: rgba(255, 255, 255, 0.3); + --color-border-tertiary: rgba(255, 255, 255, 0.15); + --color-border-info: #85B7EB; + --color-border-danger: #F09595; + --color-border-success: #97C459; + --color-border-warning: #EF9F27; + } +} +`; + +// ─── SVG Pre-Built Classes ─────────────────────────────────────────── +export const SVG_CLASSES_CSS = ` +svg text.t { font: 400 14px var(--font-sans); fill: var(--p); } +svg text.ts { font: 400 12px var(--font-sans); fill: var(--s); } +svg text.th { font: 500 14px var(--font-sans); fill: var(--p); } + +svg .box > rect, svg .box > circle, svg .box > ellipse { fill: var(--bg2); stroke: var(--b); } +svg .node { cursor: pointer; } +svg .node:hover { opacity: 0.8; } +svg .arr { stroke: var(--s); stroke-width: 1.5; fill: none; } +svg .leader { stroke: var(--t); stroke-width: 0.5; stroke-dasharray: 4 4; fill: none; } + +/* Purple */ +svg .c-purple > rect, svg .c-purple > circle, svg .c-purple > ellipse, +svg rect.c-purple, svg circle.c-purple, svg ellipse.c-purple { fill: #EEEDFE; stroke: #534AB7; } +svg .c-purple text.th, svg .c-purple text.t { fill: #3C3489; } +svg .c-purple text.ts { fill: #534AB7; } + +/* Teal */ +svg .c-teal > rect, svg .c-teal > circle, svg .c-teal > ellipse, +svg rect.c-teal, svg circle.c-teal, svg ellipse.c-teal { fill: #E1F5EE; stroke: #0F6E56; } +svg .c-teal text.th, svg .c-teal text.t { fill: #085041; } +svg .c-teal text.ts { fill: #0F6E56; } + +/* Coral */ +svg .c-coral > rect, svg .c-coral > circle, svg .c-coral > ellipse, +svg rect.c-coral, svg circle.c-coral, svg ellipse.c-coral { fill: #FAECE7; stroke: #993C1D; } +svg .c-coral text.th, svg .c-coral text.t { fill: #712B13; } +svg .c-coral text.ts { fill: #993C1D; } + +/* Pink */ +svg .c-pink > rect, svg .c-pink > circle, svg .c-pink > ellipse, +svg rect.c-pink, svg circle.c-pink, svg ellipse.c-pink { fill: #FBEAF0; stroke: #993556; } +svg .c-pink text.th, svg .c-pink text.t { fill: #72243E; } +svg .c-pink text.ts { fill: #993556; } + +/* Gray */ +svg .c-gray > rect, svg .c-gray > circle, svg .c-gray > ellipse, +svg rect.c-gray, svg circle.c-gray, svg ellipse.c-gray { fill: #F1EFE8; stroke: #5F5E5A; } +svg .c-gray text.th, svg .c-gray text.t { fill: #444441; } +svg .c-gray text.ts { fill: #5F5E5A; } + +/* Blue */ +svg .c-blue > rect, svg .c-blue > circle, svg .c-blue > ellipse, +svg rect.c-blue, svg circle.c-blue, svg ellipse.c-blue { fill: #E6F1FB; stroke: #185FA5; } +svg .c-blue text.th, svg .c-blue text.t { fill: #0C447C; } +svg .c-blue text.ts { fill: #185FA5; } + +/* Green */ +svg .c-green > rect, svg .c-green > circle, svg .c-green > ellipse, +svg rect.c-green, svg circle.c-green, svg ellipse.c-green { fill: #EAF3DE; stroke: #3B6D11; } +svg .c-green text.th, svg .c-green text.t { fill: #27500A; } +svg .c-green text.ts { fill: #3B6D11; } + +/* Amber */ +svg .c-amber > rect, svg .c-amber > circle, svg .c-amber > ellipse, +svg rect.c-amber, svg circle.c-amber, svg ellipse.c-amber { fill: #FAEEDA; stroke: #854F0B; } +svg .c-amber text.th, svg .c-amber text.t { fill: #633806; } +svg .c-amber text.ts { fill: #854F0B; } + +/* Red */ +svg .c-red > rect, svg .c-red > circle, svg .c-red > ellipse, +svg rect.c-red, svg circle.c-red, svg ellipse.c-red { fill: #FCEBEB; stroke: #A32D2D; } +svg .c-red text.th, svg .c-red text.t { fill: #791F1F; } +svg .c-red text.ts { fill: #A32D2D; } + +/* Dark mode overrides */ +@media (prefers-color-scheme: dark) { + svg text.t { fill: #e8e6de; } + svg text.ts { fill: #9c9a92; } + svg text.th { fill: #e8e6de; } + + svg .c-purple > rect, svg .c-purple > circle, svg .c-purple > ellipse, + svg rect.c-purple, svg circle.c-purple, svg ellipse.c-purple { fill: #3C3489; stroke: #AFA9EC; } + svg .c-purple text.th, svg .c-purple text.t { fill: #CECBF6; } + svg .c-purple text.ts { fill: #AFA9EC; } + + svg .c-teal > rect, svg .c-teal > circle, svg .c-teal > ellipse, + svg rect.c-teal, svg circle.c-teal, svg ellipse.c-teal { fill: #085041; stroke: #5DCAA5; } + svg .c-teal text.th, svg .c-teal text.t { fill: #9FE1CB; } + svg .c-teal text.ts { fill: #5DCAA5; } + + svg .c-coral > rect, svg .c-coral > circle, svg .c-coral > ellipse, + svg rect.c-coral, svg circle.c-coral, svg ellipse.c-coral { fill: #712B13; stroke: #F0997B; } + svg .c-coral text.th, svg .c-coral text.t { fill: #F5C4B3; } + svg .c-coral text.ts { fill: #F0997B; } + + svg .c-pink > rect, svg .c-pink > circle, svg .c-pink > ellipse, + svg rect.c-pink, svg circle.c-pink, svg ellipse.c-pink { fill: #72243E; stroke: #ED93B1; } + svg .c-pink text.th, svg .c-pink text.t { fill: #F4C0D1; } + svg .c-pink text.ts { fill: #ED93B1; } + + svg .c-gray > rect, svg .c-gray > circle, svg .c-gray > ellipse, + svg rect.c-gray, svg circle.c-gray, svg ellipse.c-gray { fill: #444441; stroke: #B4B2A9; } + svg .c-gray text.th, svg .c-gray text.t { fill: #D3D1C7; } + svg .c-gray text.ts { fill: #B4B2A9; } + + svg .c-blue > rect, svg .c-blue > circle, svg .c-blue > ellipse, + svg rect.c-blue, svg circle.c-blue, svg ellipse.c-blue { fill: #0C447C; stroke: #85B7EB; } + svg .c-blue text.th, svg .c-blue text.t { fill: #B5D4F4; } + svg .c-blue text.ts { fill: #85B7EB; } + + svg .c-green > rect, svg .c-green > circle, svg .c-green > ellipse, + svg rect.c-green, svg circle.c-green, svg ellipse.c-green { fill: #27500A; stroke: #97C459; } + svg .c-green text.th, svg .c-green text.t { fill: #C0DD97; } + svg .c-green text.ts { fill: #97C459; } + + svg .c-amber > rect, svg .c-amber > circle, svg .c-amber > ellipse, + svg rect.c-amber, svg circle.c-amber, svg ellipse.c-amber { fill: #633806; stroke: #EF9F27; } + svg .c-amber text.th, svg .c-amber text.t { fill: #FAC775; } + svg .c-amber text.ts { fill: #EF9F27; } + + svg .c-red > rect, svg .c-red > circle, svg .c-red > ellipse, + svg rect.c-red, svg circle.c-red, svg ellipse.c-red { fill: #791F1F; stroke: #F09595; } + svg .c-red text.th, svg .c-red text.t { fill: #F7C1C1; } + svg .c-red text.ts { fill: #F09595; } +} +`; + +// ─── Form Element Styles (base, no entrance stagger) ───────────────── +// Used by the MCP server's static documents, which animate via #content > *. +export const FORM_STYLES_CSS = ` +* { box-sizing: border-box; margin: 0; } +html { background: transparent; } +body { + font-family: var(--font-sans); + font-size: 16px; + line-height: 1.7; + color: var(--color-text-primary); + background: transparent; + -webkit-font-smoothing: antialiased; +} +button { + font-family: inherit; + font-size: 14px; + padding: 6px 16px; + border: 0.5px solid var(--color-border-secondary); + border-radius: var(--border-radius-md); + background: transparent; + color: var(--color-text-primary); + cursor: pointer; + transition: background 0.15s, transform 0.1s; +} +button:hover { background: var(--color-background-secondary); } +button:active { transform: scale(0.98); } +input[type="text"], +input[type="number"], +input[type="email"], +input[type="search"], +textarea, +select { + font-family: inherit; + font-size: 14px; + padding: 6px 12px; + height: 36px; + border: 0.5px solid var(--color-border-tertiary); + border-radius: var(--border-radius-md); + background: var(--color-background-primary); + color: var(--color-text-primary); + transition: border-color 0.15s; +} +input:hover, textarea:hover, select:hover { border-color: var(--color-border-secondary); } +input:focus, textarea:focus, select:focus { + outline: none; + border-color: var(--color-border-primary); + box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.06); +} +textarea { height: auto; min-height: 80px; resize: vertical; } +input::placeholder, textarea::placeholder { color: var(--color-text-tertiary); } +input[type="range"] { + -webkit-appearance: none; + appearance: none; + height: 4px; + background: var(--color-border-tertiary); + border-radius: 2px; + border: none; + outline: none; +} +input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + width: 18px; height: 18px; + border-radius: 50%; + background: var(--color-background-primary); + border: 0.5px solid var(--color-border-secondary); + cursor: pointer; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} +input[type="range"]::-moz-range-thumb { + width: 18px; height: 18px; + border-radius: 50%; + background: var(--color-background-primary); + border: 0.5px solid var(--color-border-secondary); + cursor: pointer; +} +input[type="checkbox"], input[type="radio"] { + width: 16px; height: 16px; + accent-color: var(--color-text-info); +} +a { color: var(--color-text-info); text-decoration: none; } +a:hover { text-decoration: underline; } +#content > * { + animation: fadeSlideIn 0.4s ease-out both; +} +#content > *:nth-child(1) { animation-delay: 0s; } +#content > *:nth-child(2) { animation-delay: 0.06s; } +#content > *:nth-child(3) { animation-delay: 0.12s; } +#content > *:nth-child(4) { animation-delay: 0.18s; } +#content > *:nth-child(5) { animation-delay: 0.24s; } +#content > *:nth-child(n+6) { animation-delay: 0.3s; } +@keyframes fadeSlideIn { + from { opacity: 0; transform: translateY(8px); } + to { opacity: 1; transform: translateY(0); } +} +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + } +} +`; + +// ─── Initial-Render Stagger (app-only addition) ────────────────────── +// The streaming widget renderer gates the entrance animation behind the +// .initial-render class and animates morphed-in nodes via .morph-enter. +export const INITIAL_RENDER_STAGGER_CSS = `/* First render: stagger all children */ +#content.initial-render > * { + animation: fadeSlideIn 0.4s ease-out both; +} +#content.initial-render > *:nth-child(1) { animation-delay: 0s; } +#content.initial-render > *:nth-child(2) { animation-delay: 0.06s; } +#content.initial-render > *:nth-child(3) { animation-delay: 0.12s; } +#content.initial-render > *:nth-child(4) { animation-delay: 0.18s; } +#content.initial-render > *:nth-child(5) { animation-delay: 0.24s; } +#content.initial-render > *:nth-child(n+6) { animation-delay: 0.3s; } + +/* Subsequent morphs: only new elements animate in */ +.morph-enter { + animation: fadeSlideIn 0.4s ease-out both; +}`; + +// ─── Form Element Styles + Initial-Render Stagger ──────────────────── +export const FORM_STYLES_WITH_STAGGER_CSS = ` +* { box-sizing: border-box; margin: 0; } + +html { background: transparent; } + +body { + font-family: var(--font-sans); + font-size: 16px; + line-height: 1.7; + color: var(--color-text-primary); + background: transparent; + -webkit-font-smoothing: antialiased; +} + +button { + font-family: inherit; + font-size: 14px; + padding: 6px 16px; + border: 0.5px solid var(--color-border-secondary); + border-radius: var(--border-radius-md); + background: transparent; + color: var(--color-text-primary); + cursor: pointer; + transition: background 0.15s, transform 0.1s; +} +button:hover { background: var(--color-background-secondary); } +button:active { transform: scale(0.98); } + +input[type="text"], +input[type="number"], +input[type="email"], +input[type="search"], +textarea, +select { + font-family: inherit; + font-size: 14px; + padding: 6px 12px; + height: 36px; + border: 0.5px solid var(--color-border-tertiary); + border-radius: var(--border-radius-md); + background: var(--color-background-primary); + color: var(--color-text-primary); + transition: border-color 0.15s; +} +input:hover, textarea:hover, select:hover { border-color: var(--color-border-secondary); } +input:focus, textarea:focus, select:focus { + outline: none; + border-color: var(--color-border-primary); + box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.06); +} +textarea { height: auto; min-height: 80px; resize: vertical; } +input::placeholder, textarea::placeholder { color: var(--color-text-tertiary); } + +input[type="range"] { + -webkit-appearance: none; + appearance: none; + height: 4px; + background: var(--color-border-tertiary); + border-radius: 2px; + border: none; + outline: none; +} +input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + width: 18px; height: 18px; + border-radius: 50%; + background: var(--color-background-primary); + border: 0.5px solid var(--color-border-secondary); + cursor: pointer; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} +input[type="range"]::-moz-range-thumb { + width: 18px; height: 18px; + border-radius: 50%; + background: var(--color-background-primary); + border: 0.5px solid var(--color-border-secondary); + cursor: pointer; +} + +input[type="checkbox"], input[type="radio"] { + width: 16px; height: 16px; + accent-color: var(--color-text-info); +} + +a { color: var(--color-text-info); text-decoration: none; } +a:hover { text-decoration: underline; } + +/* First render: stagger all children */ +#content.initial-render > * { + animation: fadeSlideIn 0.4s ease-out both; +} +#content.initial-render > *:nth-child(1) { animation-delay: 0s; } +#content.initial-render > *:nth-child(2) { animation-delay: 0.06s; } +#content.initial-render > *:nth-child(3) { animation-delay: 0.12s; } +#content.initial-render > *:nth-child(4) { animation-delay: 0.18s; } +#content.initial-render > *:nth-child(5) { animation-delay: 0.24s; } +#content.initial-render > *:nth-child(n+6) { animation-delay: 0.3s; } + +/* Subsequent morphs: only new elements animate in */ +.morph-enter { + animation: fadeSlideIn 0.4s ease-out both; +} + +@keyframes fadeSlideIn { + from { opacity: 0; transform: translateY(8px); } + to { opacity: 1; transform: translateY(0); } +} + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + } +} +`; + +// ─── Open Generative UI Design Skill ───────────────────────────────── +// Injected as agent context for the generateSandboxedUi tool. Replaces the +// canonical default guidance, which contradicts this design system. +export const OPEN_GEN_UI_DESIGN_SKILL = ` +The sandbox already includes the OpenIntelligentUI design system. Build on it instead of restyling from scratch. + +Colors and theming: +- Use the CSS variables for every color: --color-background-primary / --color-background-secondary / --color-background-tertiary, --color-text-primary / --color-text-secondary / --color-text-tertiary, plus the semantic info/danger/success/warning variants (--color-background-info, --color-text-danger, --color-border-success, etc.). +- Dark mode is automatic via these variables — NEVER hardcode hex values for text or backgrounds. +- Fonts: --font-sans, --font-serif, --font-mono. Radii: --border-radius-md, --border-radius-lg, --border-radius-xl. + +Form controls: +- button, input (text/number/email/search/range/checkbox/radio), textarea, and select are pre-styled by the design system. Do not restyle these basics. + +SVG diagrams and charts: +- Pre-built color-ramp classes: .c-purple .c-teal .c-coral .c-pink .c-gray .c-blue .c-green .c-amber .c-red. +- Diagram helpers: .box .node .arr .leader for shapes/connectors, and .t .ts .th for text (body/small/heading). + +Layout: +- Use flex/grid with compact spacing. +- The css parameter should hold widget-specific styles only — the theme, form styles, and SVG classes are already loaded. +`.trim(); + +// ─── CDN Import Map ────────────────────────────────────────────────── +export const IMPORTMAP = { + imports: { + "three": "https://esm.sh/three", + "three/": "https://esm.sh/three/", + "gsap": "https://esm.sh/gsap", + "gsap/": "https://esm.sh/gsap/", + "d3": "https://esm.sh/d3", + "d3/": "https://esm.sh/d3/", + "chart.js": "https://esm.sh/chart.js", + "chart.js/": "https://esm.sh/chart.js/", + }, +} as const satisfies { imports: Record }; + +export const IMPORTMAP_SCRIPT_TAG = ``; diff --git a/packages/design-system/tsconfig.json b/packages/design-system/tsconfig.json new file mode 100644 index 0000000..586c3ce --- /dev/null +++ b/packages/design-system/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "outDir": "dist", + "declaration": true, + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true + }, + "include": ["src/**/*.ts"], + "exclude": ["src/__tests__"] +} diff --git a/packages/design-system/vitest.config.ts b/packages/design-system/vitest.config.ts new file mode 100644 index 0000000..f624398 --- /dev/null +++ b/packages/design-system/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 20c128f..b159b96 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,25 +22,37 @@ importers: dependencies: '@ag-ui/a2ui-middleware': specifier: ^0.0.2 - version: 0.0.2(@ag-ui/client@0.0.47)(rxjs@7.8.1) + version: 0.0.2(@ag-ui/client@0.0.52)(rxjs@7.8.1) '@ag-ui/mcp-apps-middleware': specifier: ^0.0.3 - version: 0.0.3(@ag-ui/client@0.0.47)(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@3.25.76) + version: 0.0.3(@ag-ui/client@0.0.52)(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@3.25.76) + '@copilotkit/a2ui-renderer': + specifier: 1.55.2-next.1 + version: 1.55.2-next.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@copilotkit/react-core': - specifier: next - version: 1.54.0-next.6(@ag-ui/core@0.0.47)(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(graphql@16.12.0)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(signal-polyfill@0.2.2)(zod@3.25.76) + specifier: 1.55.2-next.1 + version: 1.55.2-next.1(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(graphql@16.12.0)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@3.25.76) '@copilotkit/react-ui': - specifier: next - version: 1.54.0-next.6(@ag-ui/core@0.0.47)(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(graphql@16.12.0)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(signal-polyfill@0.2.2)(zod@3.25.76) + specifier: 1.55.2-next.1 + version: 1.55.2-next.1(@ag-ui/core@0.0.52)(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(graphql@16.12.0)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@3.25.76) '@copilotkit/runtime': - specifier: next - version: 1.54.0-next.6(@ag-ui/encoder@0.0.47)(@cfworker/json-schema@4.1.1)(@copilotkitnext/shared@1.54.0-next.6)(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(@langchain/langgraph-sdk@1.5.5(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(ws@8.19.0) + specifier: 1.55.2-next.1 + version: 1.55.2-next.1(@cfworker/json-schema@4.1.1)(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(@langchain/langgraph-sdk@1.9.20(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(langchain@1.4.4(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(ws@8.19.0)(zod-to-json-schema@3.25.1(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod-to-json-schema@3.25.1(zod@3.25.76)) '@copilotkitnext/shared': - specifier: next - version: 1.54.0-next.6 + specifier: 1.54.1-next.6 + version: 1.54.1-next.6 + '@jetbrains/websandbox': + specifier: 1.2.1 + version: 1.2.1 + '@repo/design-system': + specifier: workspace:* + version: link:../../packages/design-system next: specifier: 16.1.6 version: 16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + posthog-js: + specifier: ^1.438.8 + version: 1.438.8(@types/react@19.2.10)(react@19.2.4) qrcode.react: specifier: ^4.2.0 version: 4.2.0(react@19.2.4) @@ -66,6 +78,12 @@ importers: '@tailwindcss/postcss': specifier: ^4 version: 4.1.18 + '@testing-library/jest-dom': + specifier: ^6.9.1 + version: 6.9.1 + '@testing-library/react': + specifier: ^16.3.2 + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@types/node': specifier: ^20 version: 20.19.31 @@ -75,18 +93,27 @@ importers: '@types/react-dom': specifier: ^19 version: 19.2.3(@types/react@19.2.10) + '@vitejs/plugin-react': + specifier: ^6.0.2 + version: 6.0.2(vite@8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)) eslint: specifier: ^9 version: 9.39.2(jiti@2.6.1) eslint-config-next: specifier: 16.1.6 version: 16.1.6(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + jsdom: + specifier: ^29.1.1 + version: 29.1.1 tailwindcss: specifier: ^4 version: 4.1.18 typescript: specifier: ^5 version: 5.9.3 + vitest: + specifier: ^4.1.8 + version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@20.19.31)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)) zod: specifier: ^3.23.8 version: 3.25.76 @@ -99,6 +126,9 @@ importers: '@modelcontextprotocol/sdk': specifier: ^1.25.3 version: 1.25.3(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@3.25.76) + '@repo/design-system': + specifier: workspace:* + version: link:../../packages/design-system hono: specifier: ^4 version: 4.11.7 @@ -115,6 +145,21 @@ importers: typescript: specifier: ^5 version: 5.9.3 + vitest: + specifier: ^4.1.8 + version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@20.19.31)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)) + + packages/design-system: + devDependencies: + '@types/node': + specifier: ^20 + version: 20.19.31 + typescript: + specifier: ^5 + version: 5.9.3 + vitest: + specifier: ^4.1.8 + version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@20.19.31)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)) packages: @@ -126,8 +171,11 @@ packages: graphql: optional: true - '@a2ui/lit@0.8.1': - resolution: {integrity: sha512-QeqobciZz4OGMSgc2WGLFVidyhy+K7Z2GDpiuHN9NN+QlYMXByZqlzMvYPJsXrqf1lpQcMFRHgmUn1mwPpq9ew==} + '@a2ui/web_core@0.9.0': + resolution: {integrity: sha512-TsMWuEeuVDsScGIGPy/fWIZu+EOBRfhx6KwjKh3VwY1AwysRenQM8zDr8VrSk14Wck/aBgVxk2zWVrMCK2/s6A==} + + '@adobe/css-tools@4.5.0': + resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==} '@ag-ui/a2ui-middleware@0.0.2': resolution: {integrity: sha512-dXHWlE9cYxFeQscPpvaLWpbeb7wXjnAlGYMId6kI7nMizSSIgHOrnNTugFRofYm78EY+yVgruNuDjDFWOmYj1A==} @@ -135,34 +183,52 @@ packages: '@ag-ui/client': '>=0.0.40' rxjs: 7.8.1 - '@ag-ui/client@0.0.47': - resolution: {integrity: sha512-zciVwYV6gmYzdMyWwSDR/VBcOj5x1lHPG/ZGDKyxDHbCeIdGp7sKoGORKHAiPAsfUhReGLKXsR/4IknqwY2PgQ==} + '@ag-ui/a2ui-middleware@0.0.4': + resolution: {integrity: sha512-N7goCObceqsCQgFRKBpo/X9D9Q0Jp6ALV+ier2W7WnK3sy0WfY2jAeFhqEaoZRqcNeLTKEt8sDqdtd4TGQE1+w==} + peerDependencies: + '@ag-ui/client': '>=0.0.40' + rxjs: 7.8.1 + + '@ag-ui/client@0.0.48': + resolution: {integrity: sha512-JAYH8gScC4JXxfsH8mfhfMzoQ/V0pUK2EapNCDa9TBpma2nraPNWFfxCneClhrk97Kb0wZCxviBKeJbvS++QGQ==} + + '@ag-ui/client@0.0.52': + resolution: {integrity: sha512-U407VvDDwR5qs8TiyN1qY38x87qMWc2n0epw8iA5aa1qwzCKBBDgg3Fkm4JogQf0X4jwNsz8HUbIZrBB56mrpg==} + + '@ag-ui/core@0.0.48': + resolution: {integrity: sha512-HP4wO+0+j8Rkshn0eiV0XAfrh7zeTbvZsQ2URopmMXVK3f6DC2I3jw3IN1ZGaJwSuzPtch5T3NC4jrj/PazVeA==} + + '@ag-ui/core@0.0.52': + resolution: {integrity: sha512-Xo0bUaNV56EqylzcrAuhUkQX7et7+SZIrqZZtEByGwEq/I1EHny6ZMkWHLkKR7UNi0FJZwJyhKYmKJS3B2SEgA==} - '@ag-ui/core@0.0.47': - resolution: {integrity: sha512-fHat7ZErAH028R90psYclTWaj6PdcvN2GJxzwWPF/j1c5ceqbF2+6xe+t06Psg+gCzZneI9QE3IkOkdJNplZ5A==} + '@ag-ui/encoder@0.0.48': + resolution: {integrity: sha512-tqfyZA6SLVibUi+KcBFRSfwLMUXkJ1qgn/FxqaJ0XK/LvfXW8RPREcKwPl1EWYHKJi3K3g7dvKlIFq4srbvn8A==} - '@ag-ui/encoder@0.0.47': - resolution: {integrity: sha512-AgKTM/DEHtaNrcbMa0z1UQ7lKiKtalbFAjBTTP0vCh+lJ6JWIu9LrpCJQ4EjON1IRoAZtJBORlCj1KY+F14HXQ==} + '@ag-ui/encoder@0.0.52': + resolution: {integrity: sha512-6GVDTb1dv2rjap7VVnmXYypDutZi6nrsTcdfxoP6ryDG5ynlXtmmS+FSDAt62JbIMD5CtEE963xNCb6d1iXw9g==} - '@ag-ui/langgraph@0.0.24': - resolution: {integrity: sha512-ebTYpUw28fvbmhqbpAbmfsDTfEqm1gSeZaBcnxMGHFivJLCzsJ/C9hYw6aV8yRKV3lMFBwh/QFxn1eRcr7yRkQ==} + '@ag-ui/langgraph@0.0.27': + resolution: {integrity: sha512-sfUG985ngG4HAGIZK04POvZVDrsI3QaeWuqJ388QgBPGg9n/oi4+vxueW7O5PIQv6uOPCLsbxf43pZZRN3zZtg==} peerDependencies: '@ag-ui/client': '>=0.0.42' '@ag-ui/core': '>=0.0.42' - '@ag-ui/mcp-apps-middleware@0.0.2': - resolution: {integrity: sha512-EMHm65hs3aNfoCpxZ1RYDLvZejmit0yipvzg39jwKrGTzqvB3CZuZUenDS9o2eWu2PZIvcFuvU15nEwH7SZb8A==} - peerDependencies: - '@ag-ui/client': '>=0.0.40' - rxjs: 7.8.1 - '@ag-ui/mcp-apps-middleware@0.0.3': resolution: {integrity: sha512-Z+NZQXj4J+Y/2PLNsiyhNzRWFtTT2sAoC5dztoAlIsdfzvLvYEa52YGdHesNTN85JJqaIrYxQ8e31IBpKjrnoA==} peerDependencies: '@ag-ui/client': '>=0.0.40' - '@ag-ui/proto@0.0.47': - resolution: {integrity: sha512-+KCrkeVeR6MulWoYUq9Fwm22gFlI9aKG50eKYRtbTM/Yuei/Che5vjbF297XfSnGUunzScrOmdnTeTCprrtb7A==} + '@ag-ui/proto@0.0.48': + resolution: {integrity: sha512-8kfOLdDRLg9B8I+eAlO/hqZ+iPPTqSYXrh9VN05cvLAEyoyeNE37A6XRDE1VBD+PevsCQmeJQDs2MfqY7UlDWQ==} + + '@ag-ui/proto@0.0.52': + resolution: {integrity: sha512-+iCGzNUNL50YIoThVmsolWPjG4MJidl+R9k8QAGVwErEfHRtQ64KFyrdpeOXNVuWtM3SViJqPSgFyv7eGVS63A==} + + '@ai-sdk/anthropic@2.0.81': + resolution: {integrity: sha512-0iqx9hZc9xqdhxOdZkYJAKuCs9o+5a86gStYl0M7IBZzmx6jTDrynXiOigDjH3SQrmLclLCspTjW5E6YFrlyHQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 '@ai-sdk/anthropic@3.0.58': resolution: {integrity: sha512-/53SACgmVukO4bkms4dpxpRlYhW8Ct6QZRe6sj1Pi5H00hYhxIrqfiLbZBGxkdRvjsBQeP/4TVGsXgH5rQeb8Q==} @@ -176,6 +242,18 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/google-vertex@3.0.141': + resolution: {integrity: sha512-+PjbZu63x+7RABQpAnNcJ0+EEZjKt3nQESQszA4Gyv9rLajob+FvxRJWeiLcKDsGIQdEFBknDrI5KLLSm7Doeg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/google@2.0.74': + resolution: {integrity: sha512-Lhw1742RXc+4pRIvqVXa0jdl5+qdpmw8lj0lm6OchUg9rVGHzymlaxe7CDiYX5U2af4jbjKeTY22LDi3bIycgQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/google@3.0.43': resolution: {integrity: sha512-NGCgP5g8HBxrNdxvF8Dhww+UKfqAkZAmyYBvbu9YLoBkzAmGKDBGhVptN/oXPB5Vm0jggMdoLycZ8JReQM8Zqg==} engines: {node: '>=18'} @@ -188,18 +266,34 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/openai-compatible@1.0.39': + resolution: {integrity: sha512-001hdQPPXxYBWrz5d+eAmBVYmwzsB+guIey1DFXi1ZEE5H3j7fRrhPpX55MdM9Fle2DS7WZ8b3qkumCIWE92YQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/openai@3.0.41': resolution: {integrity: sha512-IZ42A+FO+vuEQCVNqlnAPYQnnUpUfdJIwn1BEDOBywiEHa23fw7PahxVtlX9zm3/zMvTW4JKPzWyvAgDu+SQ2A==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/provider-utils@3.0.25': + resolution: {integrity: sha512-CvsRu+32Y8a167s+lrIBtsybvgTHp8j9y+6BeTvLeoW3Q+okw/b4CnNUFOLIXsRaKHQKAH+IHNJPYWywfpw0LA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/provider-utils@4.0.19': resolution: {integrity: sha512-3eG55CrSWCu2SXlqq2QCsFjo3+E7+Gmg7i/oRVoSZzIodTuDSfLb3MRje67xE9RFea73Zao7Lm4mADIfUETKGg==} 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.8': resolution: {integrity: sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==} engines: {node: '>=18'} @@ -211,6 +305,21 @@ packages: '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} + '@asamuzakjp/css-color@5.1.11': + resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/dom-selector@7.1.1': + resolution: {integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/generational-cache@1.0.1': + resolution: {integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@babel/code-frame@7.29.0': resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} @@ -285,6 +394,10 @@ packages: '@braintree/sanitize-url@7.1.2': resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==} + '@bramus/specificity@2.4.2': + resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} + hasBin: true + '@bufbuild/protobuf@2.11.0': resolution: {integrity: sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==} @@ -306,31 +419,38 @@ packages: '@chevrotain/utils@11.0.3': resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} - '@copilotkit/a2ui-renderer@1.54.0-next.6': - resolution: {integrity: sha512-zDdKieiCJXnRstdkcIXpw7rjpJxUXSuGDhwFsCfetcL17pSv+Dbon18rK8Qdku8v6FCCxouUlkunh6iHcSzc9Q==} + '@copilotkit/a2ui-renderer@1.55.2-next.1': + resolution: {integrity: sha512-6R/a07xAUMVuLczUZEapMhHIdurbP7u18+iiKkacn7LBJZwnSDM/CwkFENVKL1TeC/k73aPHN4JYrEdbVxt6vQ==} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc - '@copilotkit/react-core@1.54.0-next.6': - resolution: {integrity: sha512-F/KTUHDhelVS7YxMJ8LT5a6TLfYjh8p8GYOeYKokuL6vL1Eo51oz1GCm4u1ssqQbBb1cw0m0huiQB0nuD3o/mg==} + '@copilotkit/core@1.55.2-next.1': + resolution: {integrity: sha512-z8FfUtZrO8WP2ptPvzLbwPBakooqCVZjv5bHK347CNMHQabfSXR8r+bCsnYSYj8zbc9l9e2cLRdHgADPYh5A3A==} + engines: {node: '>=18'} + + '@copilotkit/license-verifier@0.0.1-a1': + resolution: {integrity: sha512-eTsupi14qPwDhpQBrFC6t4U5rxmHo9nPaHz60gOBPPCu7tTcA8GwEq5QfX/XGfmmKbCX2noL9yto1Pg0A8qQ9g==} + + '@copilotkit/react-core@1.55.2-next.1': + resolution: {integrity: sha512-NfvHwcK3EIdPg3fjfmCuRU2/N0CcRsNkqimg5KfXDd3bvXZesjX740vw65aHqrpthI2TYZMug/G7oZ/HpgTjmA==} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc zod: '>=3.0.0' - '@copilotkit/react-ui@1.54.0-next.6': - resolution: {integrity: sha512-FeQuhd926wK3aMIjWye+NgNLAyMawmFmHonyhMCF0TokPi7g3OPD0uUqNmcLZEk9bEXTwQp/7mZCM3lww0pBAw==} + '@copilotkit/react-ui@1.55.2-next.1': + resolution: {integrity: sha512-+i4HfwEGX90rISVZR1TNIHl15GQuko8qoZLISW4yEEY3HmS3BBtC625J2vhKXLLS0tqdEwVllxUrEVD8riPCjg==} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc - '@copilotkit/runtime-client-gql@1.54.0-next.6': - resolution: {integrity: sha512-S3pD/kcZGbeVbcoL2j5KnPXwyCaOw5G6ayaL6blEfU7BeCJW+J2d1dF0unkpbg6POqtgcgKLl3SrRlCxkG0CIw==} + '@copilotkit/runtime-client-gql@1.55.2-next.1': + resolution: {integrity: sha512-7Rjw2uW09zIcwAw3vyalxjaYbV03OVbtnLAlbXpw2sLjs/FHRpsjIl1Bpv6KCcBt0sTC5rDrVNe+tyzVVCHO0A==} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc - '@copilotkit/runtime@1.54.0-next.6': - resolution: {integrity: sha512-oNhKCJB6ojn50QEIer3NFH53WghuiZ1aYPPQ2F+S6nEgGoCNJwsbwckq3heAEKZ3SPV5Kek75ioeC0vuuESTxA==} + '@copilotkit/runtime@1.55.2-next.1': + resolution: {integrity: sha512-lCZK3wE3eaV7GJnnl+jFtCDOcOE3yAFPUh3cSK+QDfxK+RCsOVAC7fplUxbIolPngKsy//QL2UxKea7pPIKXUg==} peerDependencies: '@anthropic-ai/sdk': ^0.57.0 '@langchain/aws': '>=0.1.9' @@ -359,52 +479,74 @@ packages: langchain: optional: true - '@copilotkit/shared@1.54.0-next.6': - resolution: {integrity: sha512-q+FFUxibkpMtbvcuEeOhzdNsnhcN7YSLOsjy3kis5+NQnnCzfs4maNouELJ9LmkeLREiQ3pA1gw+tUOWPevXHw==} + '@copilotkit/shared@1.55.2-next.1': + resolution: {integrity: sha512-B96UNONgbJLL+pJr3smNkmFtaVMLQJLjjHmHQ7hprMVvwC5kjOxRC1HobhcrM/rwlspd/QPAYH6vKNzhir11jA==} peerDependencies: - '@ag-ui/core': ^0.0.47 + '@ag-ui/core': '>=0.0.48' - '@copilotkitnext/agent@1.54.0-next.6': - resolution: {integrity: sha512-lZVdGe/ESY+N+KXNxMXhazcso4eQh7bJzCMY2uAkROD/0/ihQ134Y/ZpDTlbSY/tgAtYTjJfc1INiuhEVz9FIA==} + '@copilotkit/web-inspector@1.55.2-next.1': + resolution: {integrity: sha512-gWZaSVEORqN3yavjK5987NYMiUuDseIk+W5ahcneKXQFZb7QRptU354AwXBpvPdZ5pVAXIht9xK3aUhivmfzrQ==} engines: {node: '>=18'} - '@copilotkitnext/core@1.54.0-next.6': - resolution: {integrity: sha512-OLL0O4Ql03OMD3E9ZrIxFyT5mFOy9f24nhvHqrUnRdsZRiU9WqytkzsV0cqB1h0yVz4siI5Tj+W2jmpHb/agzQ==} + '@copilotkitnext/shared@1.54.1-next.6': + resolution: {integrity: sha512-jYTkGpdN5CIe7W6xNBOfXPAFdVzpW2UIM18eotF6QF7rFneWYcI3GTl8FaCIhLFN1bjdVjCqRLaVr2EmkCJJig==} engines: {node: '>=18'} + deprecated: This package is deprecated. Use @copilotkit/shared instead. V2 features are being integrated into the main @copilotkit exports and will be available under the /v2 subpath. - '@copilotkitnext/react@1.54.0-next.6': - resolution: {integrity: sha512-pV+NcGyzc5mYY3cqXAZ6LUSAiizi6xY5U4/U3S+XFUIkezuchJ+67Fj7I074l2f21k5yVhyqLgAmAXtCRGI3aA==} - engines: {node: '>=18'} + '@csstools/color-helpers@6.0.2': + resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==} + engines: {node: '>=20.19.0'} + + '@csstools/css-calc@3.2.1': + resolution: {integrity: sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==} + engines: {node: '>=20.19.0'} peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 - '@copilotkitnext/runtime@1.54.0-next.6': - resolution: {integrity: sha512-MMaH+LI0lpMqH8RPG8H35nfTk2iuXf48lf0+DD4nmQQXJKHT2Ht2J3Y6i9t2JA+084IvRk7XDNkLpDqkZMqDHA==} - engines: {node: '>=18'} + '@csstools/css-color-parser@4.1.2': + resolution: {integrity: sha512-n6Zd8mpVhObnaOqq6TC/lBCKgYncAGfFwuvJGQZTDRAwEoxwXIZu9kXBQeXkcqHsE6Sp6LyxDMrvXj5gOxnryw==} + engines: {node: '>=20.19.0'} peerDependencies: - '@ag-ui/client': 0.0.47 - '@ag-ui/core': 0.0.47 - '@ag-ui/encoder': 0.0.47 - '@copilotkitnext/shared': 1.54.0-next.6 + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 - '@copilotkitnext/shared@1.54.0-next.6': - resolution: {integrity: sha512-QzbNBcNgxrzfQ7XtB1dj7FRoQGoKqkAIBWXG5UmiUYANFEfOaS5ESE1tyCtE93ArmpJKHLKJtgKDuNEbBR/Plg==} - engines: {node: '>=18'} + '@csstools/css-parser-algorithms@4.0.0': + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-tokenizer': ^4.0.0 - '@copilotkitnext/web-inspector@1.54.0-next.6': - resolution: {integrity: sha512-KlEaypFWRk1wOZlpDEkfvxanxRpQoLOEFizMzShBSSd7/rzoctbq5DTKBO37ZE3ewsXxpaHqgeurIHo6O4nHGg==} - engines: {node: '>=18'} + '@csstools/css-syntax-patches-for-csstree@1.1.5': + resolution: {integrity: sha512-oNjBvzLq2GPZtJphCjLqXow/cHySHSgtxvKZb7OqSZ/xHgw6NWNhfad+6AB9cLeVm6eA9d/qMll3JdEHjy6M+A==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@4.0.0': + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + engines: {node: '>=20.19.0'} + + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} '@emnapi/core@1.8.1': resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + '@emnapi/runtime@1.8.1': resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@envelop/core@5.5.0': resolution: {integrity: sha512-nsU1EyJQAStaKHR1ZkB/ug9XBm+WPTliYtdedbJ/L1ykrp7dbbn0srqBeDnZ2mbZVp4hH3d0Fy+Og9OgPWZx+g==} engines: {node: '>=18.0.0'} @@ -611,6 +753,15 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@exodus/bytes@1.15.1': + resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true + '@fastify/busboy@3.2.0': resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==} @@ -861,6 +1012,9 @@ packages: cpu: [x64] os: [win32] + '@jetbrains/websandbox@1.2.1': + resolution: {integrity: sha512-FXg2JZ4O4DPf3Tj3MGwnQuJ8jEzddqEZszBEVD4SFPkq44FrbLomS7BLY3Q3eKV312oQRJU9api1YvX3uhNelw==} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -881,6 +1035,12 @@ packages: resolution: {integrity: sha512-vcJDV2vk1AlCwSh3aBm/urQ1ZrlXFFBocv11bz/NBUfLWD5/UDNMzwPdaAd2dKvNmTWa9FM2lirLU3+JCf4cRA==} engines: {node: '>=18'} + '@langchain/langgraph-checkpoint@1.0.4': + resolution: {integrity: sha512-1y5MgZ0gXXrtmoy56e3kaBChI3GwFPIKl27xkrHwN+VE/3iUsyr9gO3Jtp7kdKAe6diZGbcas5bdC/r0yUwTZA==} + engines: {node: '>=18'} + peerDependencies: + '@langchain/core': ^1.1.44 + '@langchain/langgraph-sdk@0.1.10': resolution: {integrity: sha512-9srSCb2bSvcvehMgjA2sMMwX0o1VUgPN6ghwm5Fwc9JGAKsQa6n1S4eCwy1h4abuYxwajH5n3spBw+4I2WYbgw==} peerDependencies: @@ -895,32 +1055,44 @@ packages: react-dom: optional: true - '@langchain/langgraph-sdk@1.5.5': - resolution: {integrity: sha512-SyiAs6TVXPWlt/8cI9pj/43nbIvclY3ytKqUFbL5MplCUnItetEyqvH87EncxyVF5D7iJKRZRfSVYBMmOZbjbQ==} + '@langchain/langgraph-sdk@1.9.20': + resolution: {integrity: sha512-waZQNUN6apVg3jvDApy16wUGwrCvJB8WXHbIPvVrrUZHObqx0w5tk7P/Ite5Qvu4abWrvNtrmqk2zmcqCx7jVw==} peerDependencies: - '@langchain/core': ^1.1.15 + '@langchain/core': ^1.1.48 react: ^18 || ^19 react-dom: ^18 || ^19 + svelte: ^4.0.0 || ^5.0.0 + vue: ^3.0.0 peerDependenciesMeta: - '@langchain/core': - optional: true react: optional: true react-dom: optional: true + svelte: + optional: true + vue: + optional: true + + '@langchain/langgraph@1.3.7': + resolution: {integrity: sha512-6WNskiu3bpy3XFwiD9cm4n2QapnFVX7dqYeJzuEAUGp9R3vbxngRVyb5+Myp5Rz4GCFXGXuhcFSjLVRHPhsNtQ==} + engines: {node: '>=18'} + peerDependencies: + '@langchain/core': ^1.1.48 + zod: ^3.25.32 || ^4.2.0 + zod-to-json-schema: ^3.x + peerDependenciesMeta: + zod-to-json-schema: + optional: true + + '@langchain/protocol@0.0.16': + resolution: {integrity: sha512-ws+J7MaHyhO5dG7f0vdyHQiUn9hoCnki0f3crJPa4MCTGzcRC39jYSCghyrGtBPYQnZbUQiGyRVpW3z3M8IpJg==} '@lit-labs/react@2.1.3': resolution: {integrity: sha512-OD9h2JynerBQUMNzb563jiVpxfvPF0HjQkKY2mx0lpVYvD7F+rtJpOGz6ek+6ufMidV3i+MPT9SX62OKWHFrQg==} - '@lit-labs/signals@0.1.3': - resolution: {integrity: sha512-P0yWgH5blwVyEwBg+WFspLzeu1i0ypJP1QB0l1Omr9qZLIPsUu0p4Fy2jshOg7oQyha5n163K3GJGeUhQQ682Q==} - '@lit-labs/ssr-dom-shim@1.5.1': resolution: {integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==} - '@lit/context@1.1.6': - resolution: {integrity: sha512-M26qDE6UkQbZA2mQ3RjJ3Gzd8TxP+/0obMgE5HfkfLhEEyYE3Bui4A5XHiGPjy0MUGAyxB3QgVuw2ciS0kHn6A==} - '@lit/react@1.0.8': resolution: {integrity: sha512-p2+YcF+JE67SRX3mMlJ1TKCSTsgyOVdAwd/nxp3NuV1+Cb6MWALbN6nT7Ld4tpmYofcE5kcaSY1YBB9erY+6fw==} peerDependencies: @@ -953,6 +1125,12 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + '@napi-rs/wasm-runtime@1.1.5': + resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@next/env@16.1.6': resolution: {integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==} @@ -1027,9 +1205,24 @@ packages: resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} + '@oxc-project/types@0.133.0': + resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@posthog/browser-common@0.9.4': + resolution: {integrity: sha512-QlG0WZFG9iTp9cmXTypB4cgnxBAD3GImrj9AwmA84uh8uy5vIVgVLjoTTdOAW29XL+kh/eLn/5ZtBQt2JQfR+w==} + + '@posthog/core@1.58.0': + resolution: {integrity: sha512-vluXIlVF6WGeHoQbsQK8Y1ywXZlJDU7YHEKiXAArQU38yFBpgxxfD0kInbYHtura4Fr7Z7H8WiDFvtMpCGehGg==} + + '@posthog/types@1.415.2': + resolution: {integrity: sha512-BIIHPyXcPZuNTImrR1qLqLKFw7j9o8co6LG/9OpLtpWJ3RT0y89Lx6VCtd37N9/dkr/qW7y0uPjJxAxjsALHtw==} + + '@preact/signals-core@1.14.2': + resolution: {integrity: sha512-RZHdBj9ZF4n40Rp4jS052EHHjBWf96P9oNdXPfhQTovCuWY9iQn3Gq+gOTJSgBO9A/JBuPfMOWsSX/lIU9Pc/A==} + '@protobuf-ts/protoc@2.11.1': resolution: {integrity: sha512-mUZJaV0daGO6HUX90o/atzQ6A7bbN2RSuHtdwo8SSF2Qoe3zHwa4IHyCN1evftTeHfLmdz+45qo47sL+5P8nyg==} hasBin: true @@ -1383,9 +1576,104 @@ packages: react-redux: optional: true + '@remix-run/node-fetch-server@0.13.3': + resolution: {integrity: sha512-UfjOXed/DQteaM5VyTfqTeGpHwyL2J5aoRGY6cydip4tt1ehNNeSwuXCC7AEGE0RWBs/7bgKxYkL/B/+UDe4AA==} + '@repeaterjs/repeater@3.0.6': resolution: {integrity: sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==} + '@rolldown/binding-android-arm64@1.0.3': + resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.3': + resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.3': + resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.3': + resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.3': + resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.3': + resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@rolldown/binding-linux-s390x-gnu@1.0.3': + resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.3': + resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.3': + resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.0.3': + resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.3': + resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.3': + resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.3': + resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} @@ -1532,9 +1820,41 @@ packages: '@tanstack/virtual-core@3.13.18': resolution: {integrity: sha512-Mx86Hqu1k39icq2Zusq+Ey2J6dDWTjDvEv43PJtRCoEYTLyfaPnxIQ6iy7YAOK0NV/qOEmZQ/uCufrppZxTgcg==} + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/react@16.3.2': + resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/d3-array@3.2.2': resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} @@ -1631,6 +1951,9 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} @@ -1769,6 +2092,7 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + deprecated: Potential CWE-502 - Update to 1.3.1 or higher '@unrs/resolver-binding-android-arm-eabi@1.11.1': resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} @@ -1872,6 +2196,48 @@ packages: resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} engines: {node: '>= 20'} + '@vitejs/plugin-react@6.0.2': + resolution: {integrity: sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + + '@vitest/expect@4.1.8': + resolution: {integrity: sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==} + + '@vitest/mocker@4.1.8': + resolution: {integrity: sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==} + 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.8': + resolution: {integrity: sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==} + + '@vitest/runner@4.1.8': + resolution: {integrity: sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==} + + '@vitest/snapshot@4.1.8': + resolution: {integrity: sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==} + + '@vitest/spy@4.1.8': + resolution: {integrity: sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==} + + '@vitest/utils@4.1.8': + resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} + '@whatwg-node/disposablestack@0.0.6': resolution: {integrity: sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==} engines: {node: '>=18.0.0'} @@ -1918,6 +2284,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + agentkeepalive@4.6.0: resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} engines: {node: '>= 8.0.0'} @@ -1961,6 +2331,9 @@ packages: resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} engines: {node: '>=10'} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} @@ -2000,6 +2373,10 @@ packages: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} @@ -2039,6 +2416,12 @@ packages: resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} hasBin: true + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + body-parser@1.20.4: resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -2062,6 +2445,9 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} @@ -2095,6 +2481,10 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + 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'} @@ -2128,6 +2518,10 @@ packages: chevrotain@11.0.3: resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==} + 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==} @@ -2226,6 +2620,9 @@ packages: copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + core-js@3.50.0: + resolution: {integrity: sha512-BRWgOLKkFeCgRudR6zrs8p9XJZcE14grzKMMssoYrk6krtuEZ7MTKPIY5RzOnqsEKIR9kst7wNzphttraT+Yqw==} + cors@2.8.6: resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} engines: {node: '>= 0.10'} @@ -2244,6 +2641,13 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -2406,6 +2810,14 @@ packages: damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + data-urls@7.0.0: + resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -2418,6 +2830,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + date-fns@4.4.0: + resolution: {integrity: sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w==} + dateformat@4.6.3: resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} @@ -2456,6 +2871,9 @@ packages: decimal.js-light@2.5.1: resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} @@ -2507,9 +2925,18 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + dompurify@3.3.1: resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==} + dompurify@3.4.17: + resolution: {integrity: sha512-B/pSlYVHQ58kqISD/yDjuJ1yfzI34m1gF4lAod2bwSRhiN4K5Cl3H8Af7hqB2PmTL911tdEudnnXn5FnhRoz0w==} + dset@3.1.4: resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} engines: {node: '>=4'} @@ -2518,6 +2945,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -2541,14 +2971,14 @@ packages: resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==} engines: {node: '>=10.13.0'} - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - entities@6.0.1: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} + es-abstract@1.24.1: resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} engines: {node: '>= 0.4'} @@ -2565,6 +2995,9 @@ packages: resolution: {integrity: sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==} engines: {node: '>= 0.4'} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -2719,6 +3152,9 @@ packages: estree-util-is-identifier-name@3.0.0: resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -2749,6 +3185,10 @@ packages: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} engines: {node: '>=18.0.0'} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + express-rate-limit@7.5.1: resolution: {integrity: sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==} engines: {node: '>= 16'} @@ -2806,6 +3246,13 @@ packages: picomatch: optional: true + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + fflate@0.4.9: + resolution: {integrity: sha512-zdxgIEddhfsyCaWpJ2SdXEP8ZMrKJ6+5jl4OupODcywU0IhRk6gdXuVGcPICyfx2H97hVK7xmJtRLPjkxAX8Vw==} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -2852,6 +3299,10 @@ packages: resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} engines: {node: '>= 12.20'} + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -2879,6 +3330,14 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + gaxios@7.1.5: + resolution: {integrity: sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==} + engines: {node: '>=18'} + + gcp-metadata@8.1.2: + resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} + engines: {node: '>=18'} + generator-function@2.0.1: resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} engines: {node: '>= 0.4'} @@ -2934,6 +3393,14 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} + google-auth-library@10.7.0: + resolution: {integrity: sha512-QpTAbNJ36TliZLx3TTtahR8HG0hN9RllL1e3FymOvQSIKK8JmgV58H924ub2wa2DsS3ANjjP1Aw1N+Ramc8hqQ==} + 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'} @@ -3066,6 +3533,10 @@ packages: resolution: {integrity: sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==} engines: {node: '>=16.9.0'} + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + html-url-attributes@3.0.1: resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} @@ -3076,6 +3547,10 @@ packages: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} @@ -3116,6 +3591,10 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -3247,6 +3726,9 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -3320,11 +3802,23 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + jsdom@29.1.1: + resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} hasBin: true + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -3356,6 +3850,12 @@ packages: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + katex@0.16.28: resolution: {integrity: sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg==} hasBin: true @@ -3370,6 +3870,12 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + langchain@1.4.4: + resolution: {integrity: sha512-tepOCwUDaIZOYJ9Eo0O6o5dXEN/0KJheiFDnHHFL8Tx8rfkDLL4cOTSTln4Vpn9LpWzXYkjQ8lkHnnNDQWZPeg==} + engines: {node: '>=20'} + peerDependencies: + '@langchain/core': ^1.1.48 + langium@3.3.1: resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==} engines: {node: '>=16.0.0'} @@ -3391,6 +3897,26 @@ packages: openai: optional: true + langsmith@0.7.6: + resolution: {integrity: sha512-6IRm+sAxHT2n5GAZbqEnUzkhOu3Q8vqQtMiOpYfGiI+pxUe/fYQSzV0Pr7q5x9JD8bnZ8xK2/P9dhPHs4zO/Nw==} + 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 + language-subtag-registry@0.3.23: resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} @@ -3417,20 +3943,44 @@ packages: cpu: [arm64] os: [android] + 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.30.2: resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] + 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.30.2: resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.30.2: - resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} + 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.30.2: + resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] @@ -3441,48 +3991,91 @@ packages: cpu: [arm] os: [linux] + 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.30.2: resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + lightningcss-linux-arm64-musl@1.30.2: resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + lightningcss-linux-x64-gnu@1.30.2: resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + lightningcss-linux-x64-musl@1.30.2: resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + 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] + lightningcss-win32-arm64-msvc@1.30.2: resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] + 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.30.2: resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} engines: {node: '>= 12.0.0'} cpu: [x64] 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.30.2: resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} engines: {node: '>= 12.0.0'} - linkify-it@5.0.0: - resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} lit-element@4.2.2: resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} @@ -3523,6 +4116,10 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.5.1: + resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3539,13 +4136,13 @@ packages: lucide@0.525.0: resolution: {integrity: sha512-sfehWlaE/7NVkcEQ4T9JD3eID8RNMIGJBBUq9wF3UFiJIrcMKRbU3g1KGfDk4svcW7yw8BtDLXaXo02scDtUYQ==} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - markdown-it@14.1.1: - resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} - hasBin: true - markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} @@ -3623,8 +4220,8 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - mdurl@2.0.0: - resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} @@ -3856,6 +4453,10 @@ packages: engines: {node: '>=4'} hasBin: true + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -3888,6 +4489,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + napi-postinstall@0.3.4: resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -3939,6 +4545,10 @@ packages: encoding: optional: true + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} @@ -3974,6 +4584,10 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + obug@2.1.2: + resolution: {integrity: sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==} + engines: {node: '>=12.20.0'} + on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -4063,6 +4677,9 @@ packages: parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -4103,8 +4720,8 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} pino-abstract-transport@2.0.0: @@ -4142,14 +4759,41 @@ packages: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + engines: {node: ^10 || ^12 || >=14} + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} + posthog-js@1.438.8: + resolution: {integrity: sha512-nQpTyiVryD2C3hm3KWrslmqiEGSFqOclTq5bsmiBKHOsDAwvVQ2wgNCbpeCScYOn56h3/dgO/va+Zu1yOv2CCQ==} + peerDependencies: + '@types/react': '>=16.8.0' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + + preact@10.29.8: + resolution: {integrity: sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q==} + peerDependencies: + preact-render-to-string: '>=5' + peerDependenciesMeta: + preact-render-to-string: + optional: true + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + prismjs@1.27.0: resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==} engines: {node: '>=6'} @@ -4184,10 +4828,6 @@ packages: pump@3.0.3: resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} - punycode.js@2.3.1: - resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} - engines: {node: '>=6'} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -4201,6 +4841,9 @@ packages: resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} engines: {node: '>=0.6'} + query-selector-shadow-dom@1.0.1: + resolution: {integrity: sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -4239,6 +4882,9 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -4332,6 +4978,10 @@ packages: react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-is: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + redux-thunk@3.1.0: resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==} peerDependencies: @@ -4457,6 +5107,11 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + rolldown@1.0.3: + resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + roughjs@4.6.6: resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} @@ -4502,6 +5157,10 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -4583,13 +5242,8 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} - signal-polyfill@0.2.2: - resolution: {integrity: sha512-p63Y4Er5/eMQ9RHg0M0Y64NlsQKpiu6MDdhBXpyywRuWiPywhJTpKJ1iB5K2hJEbFZ0BnDS7ZkJ+0AfTuL37Rg==} - - signal-utils@0.21.1: - resolution: {integrity: sha512-i9cdLSvVH4j8ql8mz2lyrA93xL499P8wEbIev3ldSriXeUwqh+wM4Q5VPhIZ19gPtIS4BOopJuKB8l1+wH9LCg==} - peerDependencies: - signal-polyfill: ^0.2.0 + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} simple-wcswidth@1.1.2: resolution: {integrity: sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==} @@ -4614,10 +5268,16 @@ packages: stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} + 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.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -4668,6 +5328,10 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -4709,6 +5373,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tabbable@6.4.0: resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} @@ -4728,6 +5395,9 @@ packages: tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinyexec@1.0.2: resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} engines: {node: '>=18'} @@ -4736,6 +5406,21 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + 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'} + + tldts-core@7.4.2: + resolution: {integrity: sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==} + + tldts@7.4.2: + resolution: {integrity: sha512-kCwffuaH8ntKtygnWe1b4BJKWiCUH30n5KfoTr6IchcXOwR7chAOFJxFrH3vjANafUYrIA4a7SDL+nn7SiR4Sw==} + hasBin: true + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4747,9 +5432,17 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + tough-cookie@6.0.1: + resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} + engines: {node: '>=16'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -4770,10 +5463,6 @@ packages: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} - ts-deepmerge@7.0.3: - resolution: {integrity: sha512-Du/ZW2RfwV/D4cmA5rXafYjBQVuvu4qGiEEla4EmEHVHgRdx68Gftx7i66jn2bzHPwSVZY36Ae6OuDn9el4ZKA==} - engines: {node: '>=14.13.1'} - tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} @@ -4876,9 +5565,6 @@ packages: engines: {node: '>=14.17'} hasBin: true - uc.micro@2.1.0: - resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - ufo@1.6.3: resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} @@ -4892,6 +5578,10 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici@7.27.2: + resolution: {integrity: sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==} + engines: {node: '>=20.18.1'} + unified@10.1.2: resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} @@ -5001,18 +5691,20 @@ packages: 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.0: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true - uuid@13.0.0: - resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} + uuid@14.0.0: + resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} hasBin: true uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uvu@0.5.6: @@ -5046,6 +5738,90 @@ packages: victory-vendor@37.3.6: resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} + vite@8.0.16: + resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.18 + esbuild: ^0.27.3 + 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.8: + resolution: {integrity: sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==} + 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.8 + '@vitest/browser-preview': 4.1.8 + '@vitest/browser-webdriverio': 4.1.8 + '@vitest/coverage-istanbul': 4.1.8 + '@vitest/coverage-v8': 4.1.8 + '@vitest/ui': 4.1.8 + 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 + vscode-jsonrpc@8.2.0: resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} engines: {node: '>=14.0.0'} @@ -5066,16 +5842,42 @@ packages: vscode-uri@3.0.8: resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + web-streams-polyfill@4.0.0-beta.3: resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} engines: {node: '>= 14'} + web-vitals@6.2.1: + resolution: {integrity: sha512-rLcLXA2sx6+9dE88NHFubwTtGxpK4yYBLj6qHPdFoCaLr0cXGb4efOqtKLlm4loGA4OEKHIQKMKzZkKyOh5ctw==} + + web-vitals@6.2.3: + resolution: {integrity: sha512-Dmy+vdO1UPMqXiAtZSNayhl4f794Bxfd94W4HIj2HlYtczEQfEOon969memlcpcHrTuOKLa5baFjX7WbgmOq+A==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + + whatwg-url@16.0.1: + resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -5100,6 +5902,11 @@ packages: engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + wonka@6.3.5: resolution: {integrity: sha512-SSil+ecw6B4/Dm7Pf2sAshKQ5hWFvfyGlfPbEd6A14dOH6VDjrmbY86u6nZvy9omGwwIPFR8V41+of1EezgoUw==} @@ -5126,6 +5933,13 @@ packages: utf-8-validate: optional: true + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -5172,26 +5986,31 @@ snapshots: optionalDependencies: graphql: 16.12.0 - '@a2ui/lit@0.8.1(signal-polyfill@0.2.2)': + '@a2ui/web_core@0.9.0': dependencies: - '@lit-labs/signals': 0.1.3 - '@lit/context': 1.1.6 - lit: 3.3.2 - markdown-it: 14.1.1 - signal-utils: 0.21.1(signal-polyfill@0.2.2) - transitivePeerDependencies: - - signal-polyfill + '@preact/signals-core': 1.14.2 + date-fns: 4.4.0 + zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) + + '@adobe/css-tools@4.5.0': {} - '@ag-ui/a2ui-middleware@0.0.2(@ag-ui/client@0.0.47)(rxjs@7.8.1)': + '@ag-ui/a2ui-middleware@0.0.2(@ag-ui/client@0.0.52)(rxjs@7.8.1)': dependencies: - '@ag-ui/client': 0.0.47 + '@ag-ui/client': 0.0.52 rxjs: 7.8.1 - '@ag-ui/client@0.0.47': + '@ag-ui/a2ui-middleware@0.0.4(@ag-ui/client@0.0.52)(rxjs@7.8.1)': dependencies: - '@ag-ui/core': 0.0.47 - '@ag-ui/encoder': 0.0.47 - '@ag-ui/proto': 0.0.47 + '@ag-ui/client': 0.0.52 + clarinet: 0.12.6 + rxjs: 7.8.1 + + '@ag-ui/client@0.0.48': + dependencies: + '@ag-ui/core': 0.0.48 + '@ag-ui/encoder': 0.0.48 + '@ag-ui/proto': 0.0.48 '@types/uuid': 10.0.0 compare-versions: 6.1.1 fast-json-patch: 3.1.1 @@ -5200,22 +6019,45 @@ snapshots: uuid: 11.1.0 zod: 3.25.76 - '@ag-ui/core@0.0.47': + '@ag-ui/client@0.0.52': dependencies: + '@ag-ui/core': 0.0.52 + '@ag-ui/encoder': 0.0.52 + '@ag-ui/proto': 0.0.52 + '@types/uuid': 10.0.0 + compare-versions: 6.1.1 + fast-json-patch: 3.1.1 rxjs: 7.8.1 + untruncate-json: 0.0.1 + uuid: 11.1.0 + zod: 3.25.76 + + '@ag-ui/core@0.0.48': + dependencies: + rxjs: 7.8.1 + zod: 3.25.76 + + '@ag-ui/core@0.0.52': + dependencies: zod: 3.25.76 - '@ag-ui/encoder@0.0.47': + '@ag-ui/encoder@0.0.48': + dependencies: + '@ag-ui/core': 0.0.48 + '@ag-ui/proto': 0.0.48 + + '@ag-ui/encoder@0.0.52': dependencies: - '@ag-ui/core': 0.0.47 - '@ag-ui/proto': 0.0.47 + '@ag-ui/core': 0.0.52 + '@ag-ui/proto': 0.0.52 - '@ag-ui/langgraph@0.0.24(@ag-ui/client@0.0.47)(@ag-ui/core@0.0.47)(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@ag-ui/langgraph@0.0.27(@ag-ui/client@0.0.52)(@ag-ui/core@0.0.52)(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(ws@8.19.0)(zod-to-json-schema@3.25.1(zod@3.25.76))': dependencies: - '@ag-ui/client': 0.0.47 - '@ag-ui/core': 0.0.47 + '@ag-ui/client': 0.0.52 + '@ag-ui/core': 0.0.52 '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)) '@langchain/langgraph-sdk': 0.1.10(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + langchain: 1.4.4(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(ws@8.19.0)(zod-to-json-schema@3.25.1(zod@3.25.76)) partial-json: 0.1.7 rxjs: 7.8.1 transitivePeerDependencies: @@ -5225,10 +6067,14 @@ snapshots: - openai - react - react-dom + - svelte + - vue + - ws + - zod-to-json-schema - '@ag-ui/mcp-apps-middleware@0.0.2(@ag-ui/client@0.0.47)(@cfworker/json-schema@4.1.1)(hono@4.11.7)(rxjs@7.8.1)(zod@3.25.76)': + '@ag-ui/mcp-apps-middleware@0.0.3(@ag-ui/client@0.0.52)(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@3.25.76)': dependencies: - '@ag-ui/client': 0.0.47 + '@ag-ui/client': 0.0.52 '@modelcontextprotocol/sdk': 1.25.3(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@3.25.76) rxjs: 7.8.1 transitivePeerDependencies: @@ -5237,23 +6083,24 @@ snapshots: - supports-color - zod - '@ag-ui/mcp-apps-middleware@0.0.3(@ag-ui/client@0.0.47)(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@3.25.76)': + '@ag-ui/proto@0.0.48': dependencies: - '@ag-ui/client': 0.0.47 - '@modelcontextprotocol/sdk': 1.25.3(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@3.25.76) - rxjs: 7.8.1 - transitivePeerDependencies: - - '@cfworker/json-schema' - - hono - - supports-color - - zod + '@ag-ui/core': 0.0.48 + '@bufbuild/protobuf': 2.11.0 + '@protobuf-ts/protoc': 2.11.1 - '@ag-ui/proto@0.0.47': + '@ag-ui/proto@0.0.52': dependencies: - '@ag-ui/core': 0.0.47 + '@ag-ui/core': 0.0.52 '@bufbuild/protobuf': 2.11.0 '@protobuf-ts/protoc': 2.11.1 + '@ai-sdk/anthropic@2.0.81(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@3.25.76) + zod: 3.25.76 + '@ai-sdk/anthropic@3.0.58(zod@3.25.76)': dependencies: '@ai-sdk/provider': 3.0.8 @@ -5267,6 +6114,24 @@ snapshots: '@vercel/oidc': 3.1.0 zod: 3.25.76 + '@ai-sdk/google-vertex@3.0.141(zod@3.25.76)': + dependencies: + '@ai-sdk/anthropic': 2.0.81(zod@3.25.76) + '@ai-sdk/google': 2.0.74(zod@3.25.76) + '@ai-sdk/openai-compatible': 1.0.39(zod@3.25.76) + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@3.25.76) + google-auth-library: 10.7.0 + zod: 3.25.76 + transitivePeerDependencies: + - supports-color + + '@ai-sdk/google@2.0.74(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@3.25.76) + zod: 3.25.76 + '@ai-sdk/google@3.0.43(zod@3.25.76)': dependencies: '@ai-sdk/provider': 3.0.8 @@ -5280,12 +6145,25 @@ snapshots: pkce-challenge: 5.0.1 zod: 3.25.76 + '@ai-sdk/openai-compatible@1.0.39(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@3.25.76) + zod: 3.25.76 + '@ai-sdk/openai@3.0.41(zod@3.25.76)': dependencies: '@ai-sdk/provider': 3.0.8 '@ai-sdk/provider-utils': 4.0.19(zod@3.25.76) zod: 3.25.76 + '@ai-sdk/provider-utils@3.0.25(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.0.6 + zod: 3.25.76 + '@ai-sdk/provider-utils@4.0.19(zod@3.25.76)': dependencies: '@ai-sdk/provider': 3.0.8 @@ -5293,6 +6171,10 @@ snapshots: eventsource-parser: 3.0.6 zod: 3.25.76 + '@ai-sdk/provider@2.0.3': + dependencies: + json-schema: 0.4.0 + '@ai-sdk/provider@3.0.8': dependencies: json-schema: 0.4.0 @@ -5304,6 +6186,26 @@ snapshots: package-manager-detector: 1.6.0 tinyexec: 1.0.2 + '@asamuzakjp/css-color@5.1.11': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@asamuzakjp/dom-selector@7.1.1': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + + '@asamuzakjp/generational-cache@1.0.1': {} + + '@asamuzakjp/nwsapi@2.3.9': {} + '@babel/code-frame@7.29.0': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -5408,6 +6310,10 @@ snapshots: '@braintree/sanitize-url@7.1.2': {} + '@bramus/specificity@2.4.2': + dependencies: + css-tree: 3.2.1 + '@bufbuild/protobuf@2.11.0': {} '@cfworker/json-schema@4.1.1': {} @@ -5429,32 +6335,61 @@ snapshots: '@chevrotain/utils@11.0.3': {} - '@copilotkit/a2ui-renderer@1.54.0-next.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(signal-polyfill@0.2.2)': + '@copilotkit/a2ui-renderer@1.55.2-next.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@a2ui/lit': 0.8.1(signal-polyfill@0.2.2) + '@a2ui/web_core': 0.9.0 clsx: 2.1.1 - markdown-it: 14.1.1 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) + + '@copilotkit/core@1.55.2-next.1(@ag-ui/core@0.0.52)(zod@3.25.76)': + dependencies: + '@ag-ui/client': 0.0.52 + '@copilotkit/shared': 1.55.2-next.1(@ag-ui/core@0.0.52) + phoenix: 1.8.5 + rxjs: 7.8.1 + zod-to-json-schema: 3.25.1(zod@3.25.76) transitivePeerDependencies: - - signal-polyfill + - '@ag-ui/core' + - encoding + - zod + + '@copilotkit/license-verifier@0.0.1-a1': {} - '@copilotkit/react-core@1.54.0-next.6(@ag-ui/core@0.0.47)(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(graphql@16.12.0)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(signal-polyfill@0.2.2)(zod@3.25.76)': + '@copilotkit/react-core@1.55.2-next.1(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(graphql@16.12.0)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@3.25.76)': dependencies: - '@ag-ui/client': 0.0.47 - '@copilotkit/runtime-client-gql': 1.54.0-next.6(@ag-ui/core@0.0.47)(graphql@16.12.0)(react@19.2.4) - '@copilotkit/shared': 1.54.0-next.6(@ag-ui/core@0.0.47) - '@copilotkitnext/core': 1.54.0-next.6(zod@3.25.76) - '@copilotkitnext/react': 1.54.0-next.6(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(signal-polyfill@0.2.2) + '@ag-ui/client': 0.0.52 + '@ag-ui/core': 0.0.52 + '@copilotkit/a2ui-renderer': 1.55.2-next.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@copilotkit/core': 1.55.2-next.1(@ag-ui/core@0.0.52)(zod@3.25.76) + '@copilotkit/runtime-client-gql': 1.55.2-next.1(@ag-ui/core@0.0.52)(graphql@16.12.0)(react@19.2.4) + '@copilotkit/shared': 1.55.2-next.1(@ag-ui/core@0.0.52) + '@copilotkit/web-inspector': 1.55.2-next.1(@ag-ui/core@0.0.52)(zod@3.25.76) + '@jetbrains/websandbox': 1.2.1 + '@lit-labs/react': 2.1.3(@types/react@19.2.10) + '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-slot': 1.2.4(@types/react@19.2.10)(react@19.2.4) + '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@scarf/scarf': 1.4.0 + '@tanstack/react-virtual': 3.13.18(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + class-variance-authority: 0.7.1 + clsx: 2.1.1 + katex: 0.16.28 + lucide-react: 0.525.0(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) react-markdown: 8.0.7(@types/react@19.2.10)(react@19.2.4) + rxjs: 7.8.1 + streamdown: 1.6.11(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(react@19.2.4) + tailwind-merge: 3.4.0 + tw-animate-css: 1.4.0 untruncate-json: 0.0.1 + use-stick-to-bottom: 1.1.2(react@19.2.4) zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) transitivePeerDependencies: - - '@ag-ui/core' - '@types/mdast' - '@types/react' - '@types/react-dom' @@ -5462,14 +6397,13 @@ snapshots: - graphql - micromark - micromark-util-types - - signal-polyfill - supports-color - '@copilotkit/react-ui@1.54.0-next.6(@ag-ui/core@0.0.47)(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(graphql@16.12.0)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(signal-polyfill@0.2.2)(zod@3.25.76)': + '@copilotkit/react-ui@1.55.2-next.1(@ag-ui/core@0.0.52)(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(graphql@16.12.0)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@3.25.76)': dependencies: - '@copilotkit/react-core': 1.54.0-next.6(@ag-ui/core@0.0.47)(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(graphql@16.12.0)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(signal-polyfill@0.2.2)(zod@3.25.76) - '@copilotkit/runtime-client-gql': 1.54.0-next.6(@ag-ui/core@0.0.47)(graphql@16.12.0)(react@19.2.4) - '@copilotkit/shared': 1.54.0-next.6(@ag-ui/core@0.0.47) + '@copilotkit/react-core': 1.55.2-next.1(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(graphql@16.12.0)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@3.25.76) + '@copilotkit/runtime-client-gql': 1.55.2-next.1(@ag-ui/core@0.0.52)(graphql@16.12.0)(react@19.2.4) + '@copilotkit/shared': 1.55.2-next.1(@ag-ui/core@0.0.52) '@headlessui/react': 2.2.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-markdown: 10.1.0(@types/react@19.2.10)(react@19.2.4) @@ -5487,13 +6421,12 @@ snapshots: - micromark - micromark-util-types - react-dom - - signal-polyfill - supports-color - zod - '@copilotkit/runtime-client-gql@1.54.0-next.6(@ag-ui/core@0.0.47)(graphql@16.12.0)(react@19.2.4)': + '@copilotkit/runtime-client-gql@1.55.2-next.1(@ag-ui/core@0.0.52)(graphql@16.12.0)(react@19.2.4)': dependencies: - '@copilotkit/shared': 1.54.0-next.6(@ag-ui/core@0.0.47) + '@copilotkit/shared': 1.55.2-next.1(@ag-ui/core@0.0.52) '@urql/core': 5.2.0(graphql@16.12.0) react: 19.2.4 untruncate-json: 0.0.1 @@ -5503,41 +6436,54 @@ snapshots: - encoding - graphql - '@copilotkit/runtime@1.54.0-next.6(@ag-ui/encoder@0.0.47)(@cfworker/json-schema@4.1.1)(@copilotkitnext/shared@1.54.0-next.6)(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(@langchain/langgraph-sdk@1.5.5(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(ws@8.19.0)': + '@copilotkit/runtime@1.55.2-next.1(@cfworker/json-schema@4.1.1)(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(@langchain/langgraph-sdk@1.9.20(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(langchain@1.4.4(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(ws@8.19.0)(zod-to-json-schema@3.25.1(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod-to-json-schema@3.25.1(zod@3.25.76))': dependencies: - '@ag-ui/client': 0.0.47 - '@ag-ui/core': 0.0.47 - '@ag-ui/langgraph': 0.0.24(@ag-ui/client@0.0.47)(@ag-ui/core@0.0.47)(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@ag-ui/a2ui-middleware': 0.0.4(@ag-ui/client@0.0.52)(rxjs@7.8.1) + '@ag-ui/client': 0.0.52 + '@ag-ui/core': 0.0.52 + '@ag-ui/encoder': 0.0.52 + '@ag-ui/langgraph': 0.0.27(@ag-ui/client@0.0.52)(@ag-ui/core@0.0.52)(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(ws@8.19.0)(zod-to-json-schema@3.25.1(zod@3.25.76)) + '@ag-ui/mcp-apps-middleware': 0.0.3(@ag-ui/client@0.0.52)(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@3.25.76) '@ai-sdk/anthropic': 3.0.58(zod@3.25.76) + '@ai-sdk/google': 3.0.43(zod@3.25.76) + '@ai-sdk/google-vertex': 3.0.141(zod@3.25.76) + '@ai-sdk/mcp': 1.0.25(zod@3.25.76) '@ai-sdk/openai': 3.0.41(zod@3.25.76) - '@copilotkit/shared': 1.54.0-next.6(@ag-ui/core@0.0.47) - '@copilotkitnext/agent': 1.54.0-next.6(@cfworker/json-schema@4.1.1)(hono@4.11.7) - '@copilotkitnext/runtime': 1.54.0-next.6(@ag-ui/client@0.0.47)(@ag-ui/core@0.0.47)(@ag-ui/encoder@0.0.47)(@cfworker/json-schema@4.1.1)(@copilotkitnext/shared@1.54.0-next.6)(zod@3.25.76) + '@copilotkit/license-verifier': 0.0.1-a1 + '@copilotkit/shared': 1.55.2-next.1(@ag-ui/core@0.0.52) '@graphql-yoga/plugin-defer-stream': 3.18.0(graphql-yoga@5.18.0(graphql@16.12.0))(graphql@16.12.0) '@hono/node-server': 1.19.9(hono@4.11.7) '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)) + '@modelcontextprotocol/sdk': 1.25.3(@cfworker/json-schema@4.1.1)(hono@4.11.7)(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.116(zod@3.25.76) + clarinet: 0.12.6 class-transformer: 0.5.1 class-validator: 0.14.3 + cors: 2.8.6 + express: 4.22.1 graphql: 16.12.0 graphql-scalars: 1.25.0(graphql@16.12.0) graphql-yoga: 5.18.0(graphql@16.12.0) hono: 4.11.7 openai: 4.104.0(ws@8.19.0)(zod@3.25.76) partial-json: 0.1.7 + phoenix: 1.8.5 pino: 9.14.0 pino-pretty: 11.3.0 reflect-metadata: 0.2.2 rxjs: 7.8.1 type-graphql: 2.0.0-rc.1(class-validator@0.14.3)(graphql-scalars@1.25.0(graphql@16.12.0))(graphql@16.12.0) + uuid: 10.0.0 + ws: 8.19.0 zod: 3.25.76 optionalDependencies: - '@langchain/langgraph-sdk': 1.5.5(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@langchain/langgraph-sdk': 1.9.20(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + langchain: 1.4.4(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(ws@8.19.0)(zod-to-json-schema@3.25.1(zod@3.25.76)) transitivePeerDependencies: - - '@ag-ui/encoder' - '@cfworker/json-schema' - - '@copilotkitnext/shared' - '@opentelemetry/api' - '@opentelemetry/exporter-trace-otlp-proto' - '@opentelemetry/sdk-trace-base' @@ -5546,117 +6492,75 @@ snapshots: - react - react-dom - supports-color + - svelte - utf-8-validate - - ws + - vue + - zod-to-json-schema - '@copilotkit/shared@1.54.0-next.6(@ag-ui/core@0.0.47)': + '@copilotkit/shared@1.55.2-next.1(@ag-ui/core@0.0.52)': dependencies: - '@ag-ui/core': 0.0.47 + '@ag-ui/client': 0.0.52 + '@ag-ui/core': 0.0.52 + '@copilotkit/license-verifier': 0.0.1-a1 '@segment/analytics-node': 2.3.0 + '@standard-schema/spec': 1.1.0 chalk: 4.1.2 graphql: 16.12.0 - uuid: 10.0.0 + partial-json: 0.1.7 + uuid: 11.1.0 zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) transitivePeerDependencies: - encoding - '@copilotkitnext/agent@1.54.0-next.6(@cfworker/json-schema@4.1.1)(hono@4.11.7)': + '@copilotkit/web-inspector@1.55.2-next.1(@ag-ui/core@0.0.52)(zod@3.25.76)': dependencies: - '@ag-ui/client': 0.0.47 - '@ai-sdk/anthropic': 3.0.58(zod@3.25.76) - '@ai-sdk/google': 3.0.43(zod@3.25.76) - '@ai-sdk/mcp': 1.0.25(zod@3.25.76) - '@ai-sdk/openai': 3.0.41(zod@3.25.76) - '@copilotkitnext/shared': 1.54.0-next.6 - '@modelcontextprotocol/sdk': 1.25.3(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@3.25.76) - ai: 6.0.116(zod@3.25.76) - rxjs: 7.8.1 - zod: 3.25.76 + '@ag-ui/client': 0.0.52 + '@copilotkit/core': 1.55.2-next.1(@ag-ui/core@0.0.52)(zod@3.25.76) + lit: 3.3.2 + lucide: 0.525.0 + marked: 12.0.2 transitivePeerDependencies: - - '@cfworker/json-schema' - - hono - - supports-color + - '@ag-ui/core' + - encoding + - zod - '@copilotkitnext/core@1.54.0-next.6(zod@3.25.76)': + '@copilotkitnext/shared@1.54.1-next.6': dependencies: - '@ag-ui/client': 0.0.47 - '@copilotkitnext/shared': 1.54.0-next.6 - phoenix: 1.8.5 - rxjs: 7.8.1 - zod-to-json-schema: 3.25.1(zod@3.25.76) - transitivePeerDependencies: - - zod + '@ag-ui/client': 0.0.48 + '@standard-schema/spec': 1.1.0 + partial-json: 0.1.7 + uuid: 11.1.0 - '@copilotkitnext/react@1.54.0-next.6(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(signal-polyfill@0.2.2)': + '@csstools/color-helpers@6.0.2': {} + + '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - '@ag-ui/client': 0.0.47 - '@ag-ui/core': 0.0.47 - '@copilotkit/a2ui-renderer': 1.54.0-next.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(signal-polyfill@0.2.2) - '@copilotkitnext/core': 1.54.0-next.6(zod@3.25.76) - '@copilotkitnext/shared': 1.54.0-next.6 - '@copilotkitnext/web-inspector': 1.54.0-next.6(zod@3.25.76) - '@lit-labs/react': 2.1.3(@types/react@19.2.10) - '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.4(@types/react@19.2.10)(react@19.2.4) - '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - class-variance-authority: 0.7.1 - clsx: 2.1.1 - katex: 0.16.28 - lucide-react: 0.525.0(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - streamdown: 1.6.11(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(react@19.2.4) - tailwind-merge: 3.4.0 - ts-deepmerge: 7.0.3 - tw-animate-css: 1.4.0 - use-stick-to-bottom: 1.1.2(react@19.2.4) - zod: 3.25.76 - transitivePeerDependencies: - - '@types/mdast' - - '@types/react' - - '@types/react-dom' - - micromark - - micromark-util-types - - signal-polyfill - - supports-color + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 - '@copilotkitnext/runtime@1.54.0-next.6(@ag-ui/client@0.0.47)(@ag-ui/core@0.0.47)(@ag-ui/encoder@0.0.47)(@cfworker/json-schema@4.1.1)(@copilotkitnext/shared@1.54.0-next.6)(zod@3.25.76)': + '@csstools/css-color-parser@4.1.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - '@ag-ui/a2ui-middleware': 0.0.2(@ag-ui/client@0.0.47)(rxjs@7.8.1) - '@ag-ui/client': 0.0.47 - '@ag-ui/core': 0.0.47 - '@ag-ui/encoder': 0.0.47 - '@ag-ui/mcp-apps-middleware': 0.0.2(@ag-ui/client@0.0.47)(@cfworker/json-schema@4.1.1)(hono@4.11.7)(rxjs@7.8.1)(zod@3.25.76) - '@copilotkitnext/shared': 1.54.0-next.6 - cors: 2.8.6 - express: 4.22.1 - hono: 4.11.7 - phoenix: 1.8.5 - rxjs: 7.8.1 - ws: 8.19.0 - transitivePeerDependencies: - - '@cfworker/json-schema' - - bufferutil - - supports-color - - utf-8-validate - - zod + '@csstools/color-helpers': 6.0.2 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 - '@copilotkitnext/shared@1.54.0-next.6': + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': dependencies: - '@ag-ui/client': 0.0.47 - '@standard-schema/spec': 1.1.0 - partial-json: 0.1.7 - uuid: 11.1.0 + '@csstools/css-tokenizer': 4.0.0 - '@copilotkitnext/web-inspector@1.54.0-next.6(zod@3.25.76)': + '@csstools/css-syntax-patches-for-csstree@1.1.5(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.0': {} + + '@emnapi/core@1.10.0': dependencies: - '@ag-ui/client': 0.0.47 - '@copilotkitnext/core': 1.54.0-next.6(zod@3.25.76) - lit: 3.3.2 - lucide: 0.525.0 - marked: 12.0.2 - transitivePeerDependencies: - - zod + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true '@emnapi/core@1.8.1': dependencies: @@ -5664,6 +6568,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.8.1': dependencies: tslib: 2.8.1 @@ -5674,6 +6583,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + '@envelop/core@5.5.0': dependencies: '@envelop/instrumentation': 1.0.0 @@ -5815,6 +6729,8 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@exodus/bytes@1.15.1': {} + '@fastify/busboy@3.2.0': {} '@floating-ui/core@1.7.4': @@ -6037,6 +6953,8 @@ snapshots: '@img/sharp-win32-x64@0.34.5': optional: true + '@jetbrains/websandbox@1.2.1': {} + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -6076,6 +6994,11 @@ snapshots: - '@opentelemetry/sdk-trace-base' - openai + '@langchain/langgraph-checkpoint@1.0.4(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))': + dependencies: + '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)) + uuid: 14.0.0 + '@langchain/langgraph-sdk@0.1.10(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@types/json-schema': 7.0.15 @@ -6087,16 +7010,36 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@langchain/langgraph-sdk@1.5.5(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@langchain/langgraph-sdk@1.9.20(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: + '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)) + '@langchain/protocol': 0.0.16 + '@types/json-schema': 7.0.15 p-queue: 9.1.0 p-retry: 7.1.1 - uuid: 13.0.0 + uuid: 14.0.0 optionalDependencies: - '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - optional: true + + '@langchain/langgraph@1.3.7(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod-to-json-schema@3.25.1(zod@3.25.76))(zod@3.25.76)': + dependencies: + '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)) + '@langchain/langgraph-checkpoint': 1.0.4(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))) + '@langchain/langgraph-sdk': 1.9.20(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@langchain/protocol': 0.0.16 + '@standard-schema/spec': 1.1.0 + uuid: 14.0.0 + zod: 3.25.76 + optionalDependencies: + zod-to-json-schema: 3.25.1(zod@3.25.76) + transitivePeerDependencies: + - react + - react-dom + - svelte + - vue + + '@langchain/protocol@0.0.16': {} '@lit-labs/react@2.1.3(@types/react@19.2.10)': dependencies: @@ -6104,17 +7047,8 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@lit-labs/signals@0.1.3': - dependencies: - lit: 3.3.2 - signal-polyfill: 0.2.2 - '@lit-labs/ssr-dom-shim@1.5.1': {} - '@lit/context@1.1.6': - dependencies: - '@lit/reactive-element': 2.1.2 - '@lit/react@1.0.8(@types/react@19.2.10)': dependencies: '@types/react': 19.2.10 @@ -6164,6 +7098,13 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true + '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.2 + optional: true + '@next/env@16.1.6': {} '@next/eslint-plugin-next@16.1.6': @@ -6210,8 +7151,23 @@ snapshots: '@opentelemetry/api@1.9.0': {} + '@oxc-project/types@0.133.0': {} + '@pinojs/redact@0.4.0': {} + '@posthog/browser-common@0.9.4': + dependencies: + '@posthog/core': 1.58.0 + '@posthog/types': 1.415.2 + + '@posthog/core@1.58.0': + dependencies: + '@posthog/types': 1.415.2 + + '@posthog/types@1.415.2': {} + + '@preact/signals-core@1.14.2': {} + '@protobuf-ts/protoc@2.11.1': {} '@radix-ui/primitive@1.1.3': {} @@ -6551,8 +7507,61 @@ snapshots: react: 19.2.4 react-redux: 9.2.0(@types/react@19.2.10)(react@19.2.4)(redux@5.0.1) + '@remix-run/node-fetch-server@0.13.3': {} + '@repeaterjs/repeater@3.0.6': {} + '@rolldown/binding-android-arm64@1.0.3': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.3': + optional: true + + '@rolldown/binding-darwin-x64@1.0.3': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.3': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.3': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.3': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.3': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.3': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.3': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.3': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + '@rtsao/scc@1.1.0': {} '@scarf/scarf@1.4.0': {} @@ -6694,19 +7703,61 @@ snapshots: postcss: 8.5.6 tailwindcss: 4.1.18 - '@tanstack/react-virtual@3.13.18(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@tanstack/react-virtual@3.13.18(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@tanstack/virtual-core': 3.13.18 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@tanstack/virtual-core@3.13.18': {} + + '@testing-library/dom@10.4.1': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/runtime': 7.28.6 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.9.1': + dependencies: + '@adobe/css-tools': 4.5.0 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@tanstack/virtual-core': 3.13.18 + '@babel/runtime': 7.28.6 + '@testing-library/dom': 10.4.1 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - - '@tanstack/virtual-core@3.13.18': {} + optionalDependencies: + '@types/react': 19.2.10 + '@types/react-dom': 19.2.3(@types/react@19.2.10) '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 optional: true + '@tybys/wasm-util@0.10.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/aria-query@5.0.4': {} + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + '@types/d3-array@3.2.2': {} '@types/d3-axis@3.0.6': @@ -6828,6 +7879,8 @@ snapshots: dependencies: '@types/ms': 2.1.0 + '@types/deep-eql@4.0.2': {} + '@types/estree-jsx@1.0.5': dependencies: '@types/estree': 1.0.8 @@ -6968,7 +8021,7 @@ snapshots: debug: 4.4.3 minimatch: 9.0.5 semver: 7.7.3 - tinyglobby: 0.2.15 + tinyglobby: 0.2.17 ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -7060,6 +8113,52 @@ snapshots: '@vercel/oidc@3.1.0': {} + '@vitejs/plugin-react@6.0.2(vite@8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: 8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0) + + '@vitest/expect@4.1.8': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.8 + '@vitest/utils': 4.1.8 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.8(vite@8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))': + dependencies: + '@vitest/spy': 4.1.8 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0) + + '@vitest/pretty-format@4.1.8': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.1.8': + dependencies: + '@vitest/utils': 4.1.8 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.8': + dependencies: + '@vitest/pretty-format': 4.1.8 + '@vitest/utils': 4.1.8 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.8': {} + + '@vitest/utils@4.1.8': + dependencies: + '@vitest/pretty-format': 4.1.8 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + '@whatwg-node/disposablestack@0.0.6': dependencies: '@whatwg-node/promise-helpers': 1.3.2 @@ -7113,6 +8212,8 @@ snapshots: acorn@8.15.0: {} + agent-base@7.1.4: {} + agentkeepalive@4.6.0: dependencies: humanize-ms: 1.2.1 @@ -7157,6 +8258,10 @@ snapshots: dependencies: tslib: 2.8.1 + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + aria-query@5.3.2: {} array-buffer-byte-length@1.0.2: @@ -7228,6 +8333,8 @@ snapshots: get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 + assertion-error@2.0.1: {} + ast-types-flow@0.0.8: {} async-function@1.0.0: {} @@ -7252,6 +8359,12 @@ snapshots: baseline-browser-mapping@2.9.19: {} + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + + bignumber.js@9.3.1: {} + body-parser@1.20.4: dependencies: bytes: 3.1.2 @@ -7304,6 +8417,8 @@ snapshots: node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.1) + buffer-equal-constant-time@1.0.1: {} + buffer@6.0.3: dependencies: base64-js: 1.5.1 @@ -7336,6 +8451,8 @@ snapshots: ccount@2.0.1: {} + chai@6.2.2: {} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -7369,6 +8486,8 @@ snapshots: '@chevrotain/utils': 11.0.3 lodash-es: 4.17.21 + clarinet@0.12.6: {} + class-transformer@0.5.1: {} class-validator@0.14.3: @@ -7452,6 +8571,8 @@ snapshots: dependencies: toggle-selection: 1.0.6 + core-js@3.50.0: {} + cors@2.8.6: dependencies: object-assign: 4.1.1 @@ -7475,6 +8596,13 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + css.escape@1.5.1: {} + csstype@3.2.3: {} cytoscape-cose-bilkent@4.1.0(cytoscape@3.33.1): @@ -7663,6 +8791,15 @@ snapshots: damerau-levenshtein@1.0.8: {} + data-uri-to-buffer@4.0.1: {} + + data-urls@7.0.0: + dependencies: + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + transitivePeerDependencies: + - '@noble/hashes' + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -7681,6 +8818,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + date-fns@4.4.0: {} + dateformat@4.6.3: {} dayjs@1.11.19: {} @@ -7701,6 +8840,8 @@ snapshots: decimal.js-light@2.5.1: {} + decimal.js@10.6.0: {} + decode-named-character-reference@1.3.0: dependencies: character-entities: 2.0.2 @@ -7745,10 +8886,18 @@ snapshots: dependencies: esutils: 2.0.3 + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + dompurify@3.3.1: optionalDependencies: '@types/trusted-types': 2.0.7 + dompurify@3.4.17: + optionalDependencies: + '@types/trusted-types': 2.0.7 + dset@3.1.4: {} dunder-proto@1.0.1: @@ -7757,6 +8906,10 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + ee-first@1.1.1: {} electron-to-chromium@1.5.286: {} @@ -7776,10 +8929,10 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.0 - entities@4.5.0: {} - entities@6.0.1: {} + entities@8.0.0: {} + es-abstract@1.24.1: dependencies: array-buffer-byte-length: 1.0.2 @@ -7860,6 +9013,8 @@ snapshots: iterator.prototype: 1.1.5 safe-array-concat: 1.1.3 + es-module-lexer@2.1.0: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -8123,6 +9278,10 @@ snapshots: estree-util-is-identifier-name@3.0.0: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + esutils@2.0.3: {} etag@1.8.1: {} @@ -8141,6 +9300,8 @@ snapshots: dependencies: eventsource-parser: 3.0.6 + expect-type@1.3.0: {} + express-rate-limit@7.5.1(express@5.2.1): dependencies: express: 5.2.1 @@ -8246,9 +9407,16 @@ snapshots: dependencies: format: 0.2.2 - fdir@6.5.0(picomatch@4.0.3): + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: - picomatch: 4.0.3 + picomatch: 4.0.4 + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + fflate@0.4.9: {} file-entry-cache@8.0.0: dependencies: @@ -8314,6 +9482,10 @@ snapshots: node-domexception: 1.0.0 web-streams-polyfill: 4.0.0-beta.3 + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + forwarded@0.2.0: {} fresh@0.5.2: {} @@ -8336,6 +9508,22 @@ snapshots: functions-have-names@1.2.3: {} + gaxios@7.1.5: + 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.1.5 + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + generator-function@2.0.1: {} gensync@1.0.0-beta.2: {} @@ -8391,6 +9579,19 @@ snapshots: define-properties: 1.2.1 gopd: 1.2.0 + google-auth-library@10.7.0: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.1.5 + gcp-metadata: 8.1.2 + google-logging-utils: 1.1.3 + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + + google-logging-utils@1.1.3: {} + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -8601,6 +9802,12 @@ snapshots: hono@4.11.7: {} + html-encoding-sniffer@6.0.0: + dependencies: + '@exodus/bytes': 1.15.1 + transitivePeerDependencies: + - '@noble/hashes' + html-url-attributes@3.0.1: {} html-void-elements@3.0.0: {} @@ -8613,6 +9820,13 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + humanize-ms@1.2.1: dependencies: ms: 2.1.3 @@ -8646,6 +9860,8 @@ snapshots: imurmurhash@0.1.4: {} + indent-string@4.0.0: {} + inherits@2.0.4: {} inline-style-parser@0.1.1: {} @@ -8756,8 +9972,7 @@ snapshots: is-negative-zero@2.0.3: {} - is-network-error@1.3.0: - optional: true + is-network-error@1.3.0: {} is-number-object@1.1.1: dependencies: @@ -8768,6 +9983,8 @@ snapshots: is-plain-obj@4.1.0: {} + is-potential-custom-element-name@1.0.1: {} + is-promise@4.0.0: {} is-regex@1.2.1: @@ -8840,8 +10057,38 @@ snapshots: dependencies: argparse: 2.0.1 + jsdom@29.1.1: + dependencies: + '@asamuzakjp/css-color': 5.1.11 + '@asamuzakjp/dom-selector': 7.1.1 + '@bramus/specificity': 2.4.2 + '@csstools/css-syntax-patches-for-csstree': 1.1.5(css-tree@3.2.1) + '@exodus/bytes': 1.15.1 + css-tree: 3.2.1 + data-urls: 7.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.1 + parse5: 8.0.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.1 + undici: 7.27.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' + jsesc@3.1.0: {} + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + json-buffer@3.0.1: {} json-schema-traverse@0.4.1: {} @@ -8867,6 +10114,17 @@ snapshots: object.assign: 4.1.7 object.values: 1.2.1 + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.1: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + katex@0.16.28: dependencies: commander: 8.3.0 @@ -8879,6 +10137,25 @@ snapshots: kleur@4.1.5: {} + langchain@1.4.4(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(ws@8.19.0)(zod-to-json-schema@3.25.1(zod@3.25.76)): + dependencies: + '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)) + '@langchain/langgraph': 1.3.7(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod-to-json-schema@3.25.1(zod@3.25.76))(zod@3.25.76) + '@langchain/langgraph-checkpoint': 1.0.4(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))) + langsmith: 0.7.6(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(ws@8.19.0) + zod: 3.25.76 + transitivePeerDependencies: + - '@opentelemetry/api' + - '@opentelemetry/exporter-trace-otlp-proto' + - '@opentelemetry/sdk-trace-base' + - openai + - react + - react-dom + - svelte + - vue + - ws + - zod-to-json-schema + langium@3.3.1: dependencies: chevrotain: 11.0.3 @@ -8899,6 +10176,14 @@ snapshots: '@opentelemetry/api': 1.9.0 openai: 4.104.0(ws@8.19.0)(zod@3.25.76) + langsmith@0.7.6(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.19.0)(zod@3.25.76))(ws@8.19.0): + dependencies: + p-queue: 6.6.2 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + openai: 4.104.0(ws@8.19.0)(zod@3.25.76) + ws: 8.19.0 + language-subtag-registry@0.3.23: {} language-tags@1.0.9: @@ -8919,36 +10204,69 @@ snapshots: lightningcss-android-arm64@1.30.2: optional: true + lightningcss-android-arm64@1.32.0: + optional: true + lightningcss-darwin-arm64@1.30.2: optional: true + lightningcss-darwin-arm64@1.32.0: + optional: true + lightningcss-darwin-x64@1.30.2: optional: true + lightningcss-darwin-x64@1.32.0: + optional: true + lightningcss-freebsd-x64@1.30.2: optional: true + lightningcss-freebsd-x64@1.32.0: + optional: true + lightningcss-linux-arm-gnueabihf@1.30.2: optional: true + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + lightningcss-linux-arm64-gnu@1.30.2: optional: true + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + lightningcss-linux-arm64-musl@1.30.2: optional: true + lightningcss-linux-arm64-musl@1.32.0: + optional: true + lightningcss-linux-x64-gnu@1.30.2: optional: true + lightningcss-linux-x64-gnu@1.32.0: + optional: true + lightningcss-linux-x64-musl@1.30.2: optional: true + lightningcss-linux-x64-musl@1.32.0: + optional: true + lightningcss-win32-arm64-msvc@1.30.2: optional: true + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + lightningcss-win32-x64-msvc@1.30.2: optional: true + lightningcss-win32-x64-msvc@1.32.0: + optional: true + lightningcss@1.30.2: dependencies: detect-libc: 2.1.2 @@ -8965,9 +10283,21 @@ snapshots: lightningcss-win32-arm64-msvc: 1.30.2 lightningcss-win32-x64-msvc: 1.30.2 - linkify-it@5.0.0: + lightningcss@1.32.0: dependencies: - uc.micro: 2.1.0 + 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 lit-element@4.2.2: dependencies: @@ -9010,6 +10340,8 @@ snapshots: lru-cache@10.4.3: {} + lru-cache@11.5.1: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -9024,19 +10356,12 @@ snapshots: lucide@0.525.0: {} + lz-string@1.5.0: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - markdown-it@14.1.1: - dependencies: - argparse: 2.0.1 - entities: 4.5.0 - linkify-it: 5.0.0 - mdurl: 2.0.0 - punycode.js: 2.3.1 - uc.micro: 2.1.0 - markdown-table@3.0.4: {} marked@12.0.2: {} @@ -9248,7 +10573,7 @@ snapshots: dependencies: '@types/mdast': 4.0.4 - mdurl@2.0.0: {} + mdn-data@2.27.1: {} media-typer@0.3.0: {} @@ -9670,6 +10995,8 @@ snapshots: mime@1.6.0: {} + min-indent@1.0.1: {} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 @@ -9697,6 +11024,8 @@ snapshots: nanoid@3.3.11: {} + nanoid@3.3.12: {} + napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} @@ -9736,6 +11065,12 @@ snapshots: dependencies: whatwg-url: 5.0.0 + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + node-releases@2.0.27: {} object-assign@4.1.1: {} @@ -9780,6 +11115,8 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + obug@2.1.2: {} + on-exit-leak-free@2.1.2: {} on-finished@2.4.1: @@ -9847,7 +11184,6 @@ snapshots: dependencies: eventemitter3: 5.0.4 p-timeout: 7.0.1 - optional: true p-retry@4.6.2: dependencies: @@ -9857,14 +11193,12 @@ snapshots: p-retry@7.1.1: dependencies: is-network-error: 1.3.0 - optional: true p-timeout@3.2.0: dependencies: p-finally: 1.0.0 - p-timeout@7.0.1: - optional: true + p-timeout@7.0.1: {} package-manager-detector@1.6.0: {} @@ -9895,6 +11229,10 @@ snapshots: dependencies: entities: 6.0.1 + parse5@8.0.1: + dependencies: + entities: 8.0.0 + parseurl@1.3.3: {} partial-json@0.1.7: {} @@ -9919,7 +11257,7 @@ snapshots: picomatch@2.3.1: {} - picomatch@4.0.3: {} + picomatch@4.0.4: {} pino-abstract-transport@2.0.0: dependencies: @@ -9981,14 +11319,46 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.15: + dependencies: + nanoid: 3.3.12 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postcss@8.5.6: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 + posthog-js@1.438.8(@types/react@19.2.10)(react@19.2.4): + dependencies: + '@posthog/browser-common': 0.9.4 + '@posthog/core': 1.58.0 + '@posthog/types': 1.415.2 + core-js: 3.50.0 + dompurify: 3.4.17 + fflate: 0.4.9 + preact: 10.29.8 + query-selector-shadow-dom: 1.0.1 + web-vitals: 6.2.3 + web-vitals-soft-navs: web-vitals@6.2.1 + optionalDependencies: + '@types/react': 19.2.10 + react: 19.2.4 + transitivePeerDependencies: + - preact-render-to-string + + preact@10.29.8: {} + prelude-ls@1.2.1: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + prismjs@1.27.0: {} prismjs@1.30.0: {} @@ -10021,8 +11391,6 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 - punycode.js@2.3.1: {} - punycode@2.3.1: {} qrcode.react@4.2.0(react@19.2.4): @@ -10033,6 +11401,8 @@ snapshots: dependencies: side-channel: 1.1.0 + query-selector-shadow-dom@1.0.1: {} + queue-microtask@1.2.3: {} quick-format-unescaped@4.0.4: {} @@ -10072,6 +11442,8 @@ snapshots: react-is@16.13.1: {} + react-is@17.0.2: {} + react-is@18.3.1: {} react-markdown@10.1.0(@types/react@19.2.10)(react@19.2.4): @@ -10205,6 +11577,11 @@ snapshots: - '@types/react' - redux + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + redux-thunk@3.1.0(redux@5.0.1): dependencies: redux: 5.0.1 @@ -10382,6 +11759,27 @@ snapshots: robust-predicates@3.0.2: {} + rolldown@1.0.3: + dependencies: + '@oxc-project/types': 0.133.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.3 + '@rolldown/binding-darwin-arm64': 1.0.3 + '@rolldown/binding-darwin-x64': 1.0.3 + '@rolldown/binding-freebsd-x64': 1.0.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 + '@rolldown/binding-linux-arm64-gnu': 1.0.3 + '@rolldown/binding-linux-arm64-musl': 1.0.3 + '@rolldown/binding-linux-ppc64-gnu': 1.0.3 + '@rolldown/binding-linux-s390x-gnu': 1.0.3 + '@rolldown/binding-linux-x64-gnu': 1.0.3 + '@rolldown/binding-linux-x64-musl': 1.0.3 + '@rolldown/binding-openharmony-arm64': 1.0.3 + '@rolldown/binding-wasm32-wasi': 1.0.3 + '@rolldown/binding-win32-arm64-msvc': 1.0.3 + '@rolldown/binding-win32-x64-msvc': 1.0.3 + roughjs@4.6.6: dependencies: hachure-fill: 0.5.2 @@ -10442,6 +11840,10 @@ snapshots: safer-buffer@2.1.2: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.27.0: {} secure-json-parse@2.7.0: {} @@ -10605,11 +12007,7 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - signal-polyfill@0.2.2: {} - - signal-utils@0.21.1(signal-polyfill@0.2.2): - dependencies: - signal-polyfill: 0.2.2 + siginfo@2.0.0: {} simple-wcswidth@1.1.2: {} @@ -10627,8 +12025,12 @@ snapshots: stable-hash@0.0.5: {} + stackback@0.0.2: {} + statuses@2.0.2: {} + std-env@4.1.0: {} + stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -10737,6 +12139,10 @@ snapshots: strip-bom@3.0.0: {} + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + strip-json-comments@3.1.1: {} style-to-js@1.1.21: @@ -10770,6 +12176,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + symbol-tree@3.2.4: {} + tabbable@6.4.0: {} tailwind-merge@3.4.0: {} @@ -10784,12 +12192,27 @@ snapshots: tiny-invariant@1.3.3: {} + tinybench@2.9.0: {} + tinyexec@1.0.2: {} tinyglobby@0.2.15: dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinyrainbow@3.1.0: {} + + tldts-core@7.4.2: {} + + tldts@7.4.2: + dependencies: + tldts-core: 7.4.2 to-regex-range@5.0.1: dependencies: @@ -10799,8 +12222,16 @@ snapshots: toidentifier@1.0.1: {} + tough-cookie@6.0.1: + dependencies: + tldts: 7.4.2 + tr46@0.0.3: {} + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + tree-kill@1.2.2: {} trim-lines@3.0.1: {} @@ -10813,8 +12244,6 @@ snapshots: ts-dedent@2.2.0: {} - ts-deepmerge@7.0.3: {} - tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 @@ -10936,8 +12365,6 @@ snapshots: typescript@5.9.3: {} - uc.micro@2.1.0: {} - ufo@1.6.3: {} unbox-primitive@1.1.0: @@ -10951,6 +12378,8 @@ snapshots: undici-types@6.21.0: {} + undici@7.27.2: {} + unified@10.1.2: dependencies: '@types/unist': 2.0.11 @@ -11104,8 +12533,7 @@ snapshots: uuid@11.1.0: {} - uuid@13.0.0: - optional: true + uuid@14.0.0: {} uuid@9.0.1: {} @@ -11164,6 +12592,49 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 + vite@8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.15 + rolldown: 1.0.3 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 20.19.31 + esbuild: 0.27.3 + fsevents: 2.3.3 + jiti: 2.6.1 + tsx: 4.21.0 + + vitest@4.1.8(@opentelemetry/api@1.9.0)(@types/node@20.19.31)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)): + dependencies: + '@vitest/expect': 4.1.8 + '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)) + '@vitest/pretty-format': 4.1.8 + '@vitest/runner': 4.1.8 + '@vitest/snapshot': 4.1.8 + '@vitest/spy': 4.1.8 + '@vitest/utils': 4.1.8 + es-module-lexer: 2.1.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.2 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 8.0.16(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + '@types/node': 20.19.31 + jsdom: 29.1.1 + transitivePeerDependencies: + - msw + vscode-jsonrpc@8.2.0: {} vscode-languageserver-protocol@3.17.5: @@ -11181,12 +12652,34 @@ snapshots: vscode-uri@3.0.8: {} + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + web-namespaces@2.0.1: {} + web-streams-polyfill@3.3.3: {} + web-streams-polyfill@4.0.0-beta.3: {} + web-vitals@6.2.1: {} + + web-vitals@6.2.3: {} + webidl-conversions@3.0.1: {} + webidl-conversions@8.0.1: {} + + whatwg-mimetype@5.0.0: {} + + whatwg-url@16.0.1: + dependencies: + '@exodus/bytes': 1.15.1 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -11237,6 +12730,11 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + wonka@6.3.5: {} word-wrap@1.2.5: {} @@ -11251,6 +12749,10 @@ snapshots: ws@8.19.0: {} + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + xtend@4.0.2: {} y18n@5.0.8: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2ea70e5..1d729f4 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,4 @@ packages: - "apps/app" - "apps/mcp" + - "packages/*" diff --git a/render.yaml b/render.yaml index 48a151c..7d1a87f 100644 --- a/render.yaml +++ b/render.yaml @@ -16,12 +16,21 @@ services: envVars: - key: PYTHON_VERSION value: "3.12.6" + - key: ANTHROPIC_API_KEY + sync: false + # OpenAI key for the default ChatGPT Instant model - key: OPENAI_API_KEY sync: false - key: LANGSMITH_API_KEY sync: false + # chat-latest and gpt-* route via OpenAI, Claude names via Anthropic + # (see apps/agent/src/model.py) - key: LLM_MODEL - value: gpt-5.4-2026-03-05 + value: chat-latest + - key: TYPESAFE_API_KEY + sync: false + - key: JEV_MODEL + value: jev-latest buildFilter: paths: - apps/agent/** @@ -36,12 +45,16 @@ services: maxInstances: 3 targetMemoryPercent: 80 targetCPUPercent: 70 - buildCommand: corepack enable && pnpm install --no-frozen-lockfile && pnpm --filter @repo/app build + # turbo's build task dependsOn ^build, so @repo/design-system dist/ is built before the app + buildCommand: corepack enable && pnpm install --no-frozen-lockfile && pnpm exec turbo run build --filter=@repo/app startCommand: pnpm --filter @repo/app start healthCheckPath: /api/health envVars: - key: NODE_VERSION value: "22" + # Public origin used for social-preview metadata; existing hostname retained. + - key: APP_URL + value: https://opengenerativeui.copilotkit.ai - key: SKIP_INSTALL_DEPS value: "true" - key: LANGGRAPH_DEPLOYMENT_URL @@ -57,9 +70,16 @@ services: value: "60000" - key: RATE_LIMIT_MAX value: "40" + # Telemetry (docs/telemetry.md): count the hosted demo separately from self-hosted installs. + - key: OIUI_DISTRIBUTION + value: hosted_demo + # PostHog project key for hosted-demo page analytics; needed at build time. + - key: NEXT_PUBLIC_POSTHOG_KEY + sync: false buildFilter: paths: - apps/app/** + - packages/design-system/** - package.json - pnpm-lock.yaml - turbo.json diff --git a/turbo.json b/turbo.json index 4472312..5a7e0ec 100644 --- a/turbo.json +++ b/turbo.json @@ -9,7 +9,13 @@ "dependsOn": ["^build"], "outputs": [".next/**", "!.next/cache/**", "dist/**"] }, - "lint": {}, + "lint": { + "dependsOn": ["^build"] + }, + "test": { + "dependsOn": ["^build"], + "cache": false + }, "clean": { "cache": false }